. */ use Gibbon\Domain\System\SettingGateway; use Gibbon\Services\Format; use Gibbon\Contracts\Comms\Mailer; use Gibbon\Comms\EmailTemplate; use Gibbon\Comms\NotificationEvent; use Gibbon\Comms\NotificationSender; use Gibbon\Domain\Behaviour\BehaviourLetterGateway; use Gibbon\Domain\System\NotificationGateway; use Gibbon\Domain\System\EmailTemplateGateway; use Gibbon\Domain\User\UserGateway; require getcwd().'/../gibbon.php'; //Check for CLI, so this cannot be run through browser $settingGateway = $container->get(SettingGateway::class); $remoteCLIKey = $settingGateway->getSettingByScope('System Admin', 'remoteCLIKey'); $remoteCLIKeyInput = $_GET['remoteCLIKey'] ?? null; if (!(isCommandLineInterface() OR ($remoteCLIKey != '' AND $remoteCLIKey == $remoteCLIKeyInput))) { echo __('This script cannot be run from a browser, only via CLI.'); } else { $emailSendCount = 0; $emailFailCount = 0; $emailFailList = []; // Prep for email sending later $mail = $container->get(Mailer::class); $mail->SMTPKeepAlive = true; // Initialize the notification sender & gateway objects $notificationGateway = new NotificationGateway($pdo); $notificationSender = new NotificationSender($notificationGateway, $session); //Get settings $enableDescriptors = $settingGateway->getSettingByScope('Behaviour', 'enableDescriptors'); $enableLevels = $settingGateway->getSettingByScope('Behaviour', 'enableLevels'); $enableNegativeBehaviourLetters = $settingGateway->getSettingByScope('Behaviour', 'enableNegativeBehaviourLetters'); if ($enableNegativeBehaviourLetters == 'Y') { $behaviourLettersNegativeLetter1Count = $settingGateway->getSettingByScope('Behaviour', 'behaviourLettersNegativeLetter1Count'); $behaviourLettersNegativeLetter2Count = $settingGateway->getSettingByScope('Behaviour', 'behaviourLettersNegativeLetter2Count'); $behaviourLettersNegativeLetter3Count = $settingGateway->getSettingByScope('Behaviour', 'behaviourLettersNegativeLetter3Count'); $behaviourLetterGateway = $container->get(BehaviourLetterGateway::class); $emailTemplateGateway = $container->get(EmailTemplateGateway::class); $userGateway = $container->get(UserGateway::class); $template = $container->get(EmailTemplate::class); if ($behaviourLettersNegativeLetter1Count != '' and $behaviourLettersNegativeLetter2Count != '' and $behaviourLettersNegativeLetter3Count != '' and is_numeric($behaviourLettersNegativeLetter1Count) and is_numeric($behaviourLettersNegativeLetter2Count) and is_numeric($behaviourLettersNegativeLetter3Count)) { //SCAN THROUGH ALL STUDENTS $data = array('gibbonSchoolYearID' => $session->get('gibbonSchoolYearID')); $sql = "SELECT gibbonPerson.gibbonPersonID, preferredName, surname, gibbonFormGroup.gibbonFormGroupID, gibbonFormGroup.name AS formGroup, 'Student' AS role, gibbonPersonIDTutor, gibbonPersonIDTutor2, gibbonPersonIDTutor3 FROM gibbonPerson, gibbonStudentEnrolment, gibbonFormGroup WHERE gibbonPerson.gibbonPersonID=gibbonStudentEnrolment.gibbonPersonID AND gibbonStudentEnrolment.gibbonFormGroupID=gibbonFormGroup.gibbonFormGroupID AND status='Full' AND (dateStart IS NULL OR dateStart<='".date('Y-m-d')."') AND (dateEnd IS NULL OR dateEnd>='".date('Y-m-d')."') AND gibbonFormGroup.gibbonSchoolYearID=:gibbonSchoolYearID ORDER BY surname, preferredName"; $result = $pdo->select($sql, $data); if ($result->rowCount() > 0) { while ($student = $result->fetch()) { //For every student $studentName = Format::name('', $student['preferredName'], $student['surname'], 'Student', false); $formGroup = $student['formGroup']; //Check count of negative behaviour records in the current year= $dataBehaviour = array('gibbonPersonID' => $student['gibbonPersonID'], 'gibbonSchoolYearID' => $session->get('gibbonSchoolYearID')); $sqlBehaviour = "SELECT * FROM gibbonBehaviour WHERE gibbonPersonID=:gibbonPersonID AND gibbonSchoolYearID=:gibbonSchoolYearID AND type='Negative'"; $resultBehaviour = $pdo->select($sqlBehaviour, $dataBehaviour); $behaviourCount = $resultBehaviour->rowCount(); if ($behaviourCount > 0) { //Only worry about students with more than zero negative records in the current year //Get most recent letter entry $dataLetters = array('gibbonPersonID' => $student['gibbonPersonID'], 'gibbonSchoolYearID' => $session->get('gibbonSchoolYearID')); $sqlLetters = "SELECT * FROM gibbonBehaviourLetter WHERE gibbonPersonID=:gibbonPersonID AND gibbonSchoolYearID=:gibbonSchoolYearID AND type='Negative' ORDER BY timestamp DESC LIMIT 0, 1"; $resultLetters = $pdo->select($sqlLetters, $dataLetters); $newLetterRequired = false; $newLetterRequiredLevel = null; $newLetterRequiredStatus = null; $issueExistingLetter = false; $issueExistingLetterLevel = null; $issueExistingLetterID = null; //DECIDE WHAT LETTERS TO SEND if ($resultLetters->rowCount() != 1) { //NO LETTER EXISTS $lastLetterLevel = null; $lastLetterStatus = null; if ($behaviourCount >= $behaviourLettersNegativeLetter3Count) { //Student is over or equal to level 3 $newLetterRequired = true; $newLetterRequiredLevel = 3; $newLetterRequiredStatus = 'Issued'; } elseif ($behaviourCount >= $behaviourLettersNegativeLetter2Count and $behaviourCount < $behaviourLettersNegativeLetter3Count) { //Student is equal to or greater than level 2 but less than level 3 $newLetterRequired = true; $newLetterRequiredLevel = 2; $newLetterRequiredStatus = 'Issued'; } elseif ($behaviourCount >= $behaviourLettersNegativeLetter1Count and $behaviourCount < $behaviourLettersNegativeLetter2Count) { //Student is equal to or greater than level 1 but less than level 2 $newLetterRequired = true; $newLetterRequiredLevel = 1; $newLetterRequiredStatus = 'Issued'; } elseif ($behaviourCount == ($behaviourLettersNegativeLetter1Count - 1)) { //Student is one less than level 1 $newLetterRequired = true; $newLetterRequiredLevel = 1; $newLetterRequiredStatus = 'Warning'; } } else { //YES LETTER EXISTS $rowLetters = $resultLetters->fetch(); $lastLetterLevel = $rowLetters['letterLevel']; $lastLetterStatus = $rowLetters['status']; if ($behaviourCount > $rowLetters['recordCountAtCreation']) { //Only consider action if count has increased since creation (stops second day issue of warning when count has not changed) if ($lastLetterStatus == 'Warning') { //Last letter is warning if ($behaviourCount >= ${'behaviourLettersNegativeLetter'.$lastLetterLevel.'Count'} and $behaviourCount < ${'behaviourLettersNegativeLetter'.($lastLetterLevel + 1).'Count'}) { //Count escalted to above warning, and less than next full level $issueExistingLetter = true; $issueExistingLetterID = $rowLetters['gibbonBehaviourLetterID']; $issueExistingLetterLevel = $rowLetters['letterLevel']; } elseif ($behaviourCount >= ${'behaviourLettersNegativeLetter'.($lastLetterLevel + 1).'Count'}) { //Count escalated to equal to or above next level $newLetterRequired = true; if ($behaviourCount >= $behaviourLettersNegativeLetter3Count) { $newLetterRequiredLevel = 3; } elseif ($behaviourCount >= $behaviourLettersNegativeLetter2Count and $behaviourCount < $behaviourLettersNegativeLetter3Count) { $newLetterRequiredLevel = 2; } $newLetterRequiredStatus = 'Issued'; } } else { //Last letter is issued if ($behaviourCount == (${'behaviourLettersNegativeLetter'.($lastLetterLevel + 1).'Count'} - 1)) { //Count escalated to next warning $newLetterRequired = true; if ($behaviourCount == ($behaviourLettersNegativeLetter3Count - 1)) { $newLetterRequiredLevel = 3; } elseif ($behaviourCount == ($behaviourLettersNegativeLetter2Count - 1)) { $newLetterRequiredLevel = 2; } $newLetterRequiredStatus = 'Warning'; } elseif ($behaviourCount > (${'behaviourLettersNegativeLetter'.($lastLetterLevel + 1).'Count'} - 1)) { //Count escalated above next warning $newLetterRequired = true; if ($behaviourCount >= $behaviourLettersNegativeLetter3Count) { $newLetterRequiredLevel = 3; } elseif ($behaviourCount >= $behaviourLettersNegativeLetter2Count) { $newLetterRequiredLevel = 2; } $newLetterRequiredStatus = 'Issued'; } } } } //SEND LETTERS ACCORDING TO DECISIONS ABOVE $email = false; $letterUpdateFail = false; $gibbonBehaviourLetterID = null; //PREPARE BEHAVIOUR RECORD if ($issueExistingLetter or ($newLetterRequired and $newLetterRequiredStatus == 'Issued')) { //Prepare behaviour record for replacement $behaviourRecord = ''; } if ($issueExistingLetter) { //Issue existing letter //Update record $gibbonBehaviourLetterID = $issueExistingLetterID; $updated = $behaviourLetterGateway->update($gibbonBehaviourLetterID, ['status' => 'Issued']); if ($updated) { //Flag parents to receive email $email = true; //Notify tutor(s) $notificationText = sprintf(__('A student (%1$s) in your form group has received a behaviour letter.'), $studentName); if ($student['gibbonPersonIDTutor'] != '') { $notificationSender->addNotification($student['gibbonPersonIDTutor'], $notificationText, 'Behaviour', '/index.php?q=/modules/Behaviour/behaviour_letters.php&gibbonPersonID='.$student['gibbonPersonID']); } if ($student['gibbonPersonIDTutor2'] != '') { $notificationSender->addNotification($student['gibbonPersonIDTutor2'], $notificationText, 'Behaviour', '/index.php?q=/modules/Behaviour/behaviour_letters.php&gibbonPersonID='.$student['gibbonPersonID']); } if ($student['gibbonPersonIDTutor3'] != '') { $notificationSender->addNotification($student['gibbonPersonIDTutor3'], $notificationText, 'Behaviour', '/index.php?q=/modules/Behaviour/behaviour_letters.php&gibbonPersonID='.$student['gibbonPersonID']); } } } elseif ($newLetterRequired) { //Issue new letter if ($newLetterRequiredStatus == 'Warning') { //It's a warning //Create new record $gibbonBehaviourLetterID = $behaviourLetterGateway->insert([ 'type' => 'Negative', 'status' => 'Warning', 'gibbonSchoolYearID' => $session->get('gibbonSchoolYearID'), 'gibbonPersonID' => $student['gibbonPersonID'], 'letterLevel' => $newLetterRequiredLevel, 'recordCountAtCreation' => $behaviourCount, ]); if (!empty($gibbonBehaviourLetterID)) { //Notify tutor(s) $notificationText = sprintf(__('A warning has been issued for a student (%1$s) in your form group, pending a behaviour letter.'), $studentName); if ($student['gibbonPersonIDTutor'] != '') { $notificationSender->addNotification($student['gibbonPersonIDTutor'], $notificationText, 'Behaviour', '/index.php?q=/modules/Behaviour/behaviour_letters.php&gibbonPersonID='.$student['gibbonPersonID']); } if ($student['gibbonPersonIDTutor2'] != '') { $notificationSender->addNotification($student['gibbonPersonIDTutor2'], $notificationText, 'Behaviour', '/index.php?q=/modules/Behaviour/behaviour_letters.php&gibbonPersonID='.$student['gibbonPersonID']); } if ($student['gibbonPersonIDTutor3'] != '') { $notificationSender->addNotification($student['gibbonPersonIDTutor3'], $notificationText, 'Behaviour', '/index.php?q=/modules/Behaviour/behaviour_letters.php&gibbonPersonID='.$student['gibbonPersonID']); } //Notify teachers $notificationText = sprintf(__('A warning has been issued for a student (%1$s) in one of your classes, pending a behaviour letter.'), $studentName); $dataTeachers = array('gibbonPersonID' => $student['gibbonPersonID']); $sqlTeachers = "SELECT DISTINCT teacher.gibbonPersonID FROM gibbonPerson AS teacher JOIN gibbonCourseClassPerson AS teacherClass ON (teacherClass.gibbonPersonID=teacher.gibbonPersonID) JOIN gibbonCourseClassPerson AS studentClass ON (studentClass.gibbonCourseClassID=teacherClass.gibbonCourseClassID) JOIN gibbonPerson AS student ON (studentClass.gibbonPersonID=student.gibbonPersonID) JOIN gibbonCourseClass ON (studentClass.gibbonCourseClassID=gibbonCourseClass.gibbonCourseClassID) JOIN gibbonCourse ON (gibbonCourseClass.gibbonCourseID=gibbonCourse.gibbonCourseID) WHERE teacher.status='Full' AND teacherClass.role='Teacher' AND studentClass.role='Student' AND student.gibbonPersonID=:gibbonPersonID AND gibbonCourse.gibbonSchoolYearID=(SELECT gibbonSchoolYearID FROM gibbonSchoolYear WHERE status='Current') ORDER BY teacher.preferredName, teacher.surname, teacher.email ;"; $resultTeachers = $pdo->select($sqlTeachers, $dataTeachers); while ($rowTeachers = $resultTeachers->fetch()) { $notificationSender->addNotification($rowTeachers['gibbonPersonID'], $notificationText, 'Behaviour', '/index.php?q=/modules/Behaviour/behaviour_letters.php&gibbonPersonID='.$student['gibbonPersonID']); } } } else { //It's being issued //Create new record $gibbonBehaviourLetterID = $behaviourLetterGateway->insert([ 'type' => 'Negative', 'status' => 'Issued', 'gibbonSchoolYearID' => $session->get('gibbonSchoolYearID'), 'gibbonPersonID' => $student['gibbonPersonID'], 'letterLevel' => $newLetterRequiredLevel, 'recordCountAtCreation' => $behaviourCount, ]); if (!empty($gibbonBehaviourLetterID)) { //Flag parents to receive email $email = true; //Notify tutor(s) $notificationText = sprintf(__('A student (%1$s) in your form group has received a behaviour letter.'), $studentName); if ($student['gibbonPersonIDTutor'] != '') { $notificationSender->addNotification($student['gibbonPersonIDTutor'], $notificationText, 'Behaviour', '/index.php?q=/modules/Behaviour/behaviour_letters.php&gibbonPersonID='.$student['gibbonPersonID']); } if ($student['gibbonPersonIDTutor2'] != '') { $notificationSender->addNotification($student['gibbonPersonIDTutor2'], $notificationText, 'Behaviour', '/index.php?q=/modules/Behaviour/behaviour_letters.php&gibbonPersonID='.$student['gibbonPersonID']); } if ($student['gibbonPersonIDTutor3'] != '') { $notificationSender->addNotification($student['gibbonPersonIDTutor3'], $notificationText, 'Behaviour', '/index.php?q=/modules/Behaviour/behaviour_letters.php&gibbonPersonID='.$student['gibbonPersonID']); } } } } //DEAL WIITH EMAILS if ($email) { $recipientList = ''; // Setup template to send $templateCount = $issueExistingLetter ? $issueExistingLetterLevel : $newLetterRequiredLevel; $templateType = "Negative Behaviour Letter $templateCount"; $templateDetails = $emailTemplateGateway->selectBy(['templateType' => $templateType], ['templateName'])->fetch(); $template->setTemplate($templateDetails['templateName'] ?? 'Negative Behaviour Letter 1'); // Get form tutor details $formTutor = $userGateway->getByID($student['gibbonPersonIDTutor'], ['title', 'surname', 'preferredName', 'email']); //Send emails $dataMember = array('gibbonPersonID' => $student['gibbonPersonID']); $sqlMember = "SELECT DISTINCT email, preferredName, surname, title FROM gibbonFamilyChild JOIN gibbonFamily ON (gibbonFamilyChild.gibbonFamilyID=gibbonFamily.gibbonFamilyID) JOIN gibbonFamilyAdult ON (gibbonFamilyAdult.gibbonFamilyID=gibbonFamily.gibbonFamilyID) JOIN gibbonPerson ON (gibbonFamilyAdult.gibbonPersonID=gibbonPerson.gibbonPersonID) WHERE gibbonFamilyChild.gibbonPersonID=:gibbonPersonID AND gibbonPerson.status='Full' AND contactEmail='Y' ORDER BY contactPriority, surname, preferredName"; $resultMember = $pdo->select($sqlMember, $dataMember); while ($parent = $resultMember->fetch()) { ++$emailSendCount; if ($parent['email'] == '') { ++$emailFailCount; $emailFailList[] = $parent['surname'].', '.$parent['preferredName'].' (no email)'; } else { $recipientList .= $parent['email'].', '; // Setup template data $templateData = [ 'behaviourCount' => $behaviourCount, 'behaviourRecord' => $behaviourRecord, 'studentPreferredName' => $student['preferredName'], 'studentSurname' => $student['surname'], 'studentFormGroup' => $student['formGroup'], 'parentPreferredName' => $parent['preferredName'], 'parentSurname' => $parent['surname'], 'parentTitle' => $parent['title'], 'formTutorPreferredName' => $formTutor['preferredName'], 'formTutorSurname' => $formTutor['surname'], 'formTutorTitle' => $formTutor['title'], 'formTutorEmail' => $formTutor['email'], 'date' => Format::date(date('Y-m-d')), ]; // Render the templates for this email $subject = $template->renderSubject($templateData); $body = $template->renderBody($templateData); // Send message $mail->AddAddress($parent['email'], $parent['surname'].', '.$parent['preferredName']); if ($session->has('organisationEmail')) { $mail->SetFrom($session->get('organisationEmail'), $session->get('organisationName')); } else { $mail->SetFrom($session->get('organisationAdministratorEmail'), $session->get('organisationAdministratorName')); } $mail->Subject = $subject; $mail->renderBody('mail/message.twig.html', [ 'title' => $subject, 'body' => $body, ]); if ($mail->Send()) { $behaviourLetterGateway->update($gibbonBehaviourLetterID, ['body' => $body]); } else { ++$emailFailCount; $emailFailList[] = $parent['surname'].', '.$parent['preferredName'].' ('.$parent['email'].')'; } // Clear addresses $mail->ClearAllRecipients(); } } if ($recipientList != '') { $recipientList = substr($recipientList, 0, -2); //Record email recipients in letter record $dataUpdate = array('recipientList' => $recipientList, 'gibbonBehaviourLetterID' => $gibbonBehaviourLetterID); $sqlUpdate = 'UPDATE gibbonBehaviourLetter set recipientList=:recipientList WHERE gibbonBehaviourLetterID=:gibbonBehaviourLetterID'; $resultUpdate = $pdo->select($sqlUpdate, $dataUpdate); } } } } } } } // Close SMTP connection $mail->smtpClose(); // Raise a new notification event $event = new NotificationEvent('Behaviour', 'Behaviour Letters'); //Notify admin if (empty($email)) { $event->setNotificationText(__('The Behaviour Letter CLI script has run: no emails were sent.')); } else { $event->setNotificationText(sprintf(__('The Behaviour Letter CLI script has run: %1$s emails were sent, of which %2$s failed.'), $emailSendCount, $emailFailCount).'

'.Format::list($emailFailList)); } $event->setActionLink('/index.php?q=/modules/Behaviour/behaviour_letters.php'); // Add admin, then push the event to the notification sender $event->addRecipient($session->get('organisationAdministrator')); $event->pushNotifications($notificationGateway, $notificationSender); // Send all notifications $sendReport = $notificationSender->sendNotifications(); // Output the result to terminal echo sprintf('Sent %1$s notifications: %2$s inserts, %3$s updates, %4$s emails sent, %5$s emails failed.', $sendReport['count'], $sendReport['inserts'], $sendReport['updates'], $emailSendCount, $emailFailCount)."\n"; }