/** * A method that generates emails and letters from letter details that usually come from the UI via POST requests. * * @param \Ventus\Specialist\EmailLetterGenerator $model. The EmailLetterGenerator model. * @param array $letter_details. An array containing letters details. * @param array $course_details. An array containing course details (optional parameter). * @return array containing email and letters details. */ public function generateEmailLetter(\Ventus\Specialist\EmailLetterGenerator $model, array $letter_details, array $course_details = array()) { // Variable declarations & initiations $email_letter_serial = array(); // If document is not an CAM_LETTER_ID_FRENCH, and CAM_LETTER_ID_ENGLISH if ((empty($letter_details['acc_mode']) || $letter_details['acc_mode'] === 'template') && ((int) $letter_details['template_id'] !== CAM_LETTER_ID_FRENCH && (int) $letter_details['template_id'] !== CAM_LETTER_ID_ENGLISH)) { $email_letter_serial[$letter_details['template_id']] = $model->insertSentTemplate($letter_details, $course_details); } else { //Has student opted out? We assume no by default $opted_out = false; $all_active_accommodations = null; if ($letter_details['acc_mode'] !== 'template') { if (empty($course_details)) { $course_components = explode('-', $letter_details['acc_mode']); $course_details['code'] = $course_components[0]; $course_details['section'] = $course_components[1] === 'null' ? null : $course_components[1]; $course_details['session'] = $course_components[2]; } $course_code = $course_details['code']; $course_section = $course_details['section']; $course_session = $course_details['session']; $opted_out = \Ventus\Utilities\Functions::checkIfStudentHasOptedOut($letter_details['student_num'], $course_code, $course_section, $course_session); //This string is passed to the email letter generator code $acc_mode = $course_code . '-' . (empty($course_section) ? 'null' : $course_section) . '-' . $course_session; //Accommodations are course specific so we need to fetch all the accommodations for a specific course $all_active_accommodations = $this->student_profile->fetchStudentActiveTemplateAndCsaAccommodations($letter_details['student_num'], $course_code, $course_section, $course_session); } //Check if student has opted out- if so, don't send email. Double checking here, even though the opt-out courses are disabled on the UI if (!$opted_out) { if (empty($all_active_accommodations) && $letter_details['acc_mode'] === 'template' || !empty($all_active_accommodations) && $letter_details['acc_mode'] !== 'template') { // Ensure the CAM LETTER ID are set correctly. if (is_int(CAM_LETTER_ID_FRENCH) && is_int(CAM_LETTER_ID_ENGLISH)) { $cam_ids = array("fr" => CAM_LETTER_ID_FRENCH, "en" => CAM_LETTER_ID_ENGLISH); } foreach ($cam_ids as $key => $cam_id) { //Generate letter and put in to students letters- first in French, then english $letter_details['template_id'] = $cam_id; $letter_details['content'] = file_get_contents("https://" . URL_SPECIALIST . "/email-letter-generator.php?page=fetch-template&templateid={$letter_details['template_id']}&student_num={$letter_details['student_num']}&acc_mode={$acc_mode}"); $email_letter_serial[$key] = $model->insertSentTemplate($letter_details, $course_details); if ($letter_details['mode'] === 'letter') { $model->markPastCamsAsInactive($letter_details['student_num'], $letter_details['template_id'], $course_details); } } } } } // populate the email_letter object $email_letter = array('email_letter_serial' => $email_letter_serial, 'cam_ids' => $cam_ids, 'model' => $model, 'course_details' => $course_details, 'letter_details' => $letter_details); return $email_letter; }
/** * Given a student, fetch all the courses they are registered to in a given semester * @param int $student_num The student number * @param string $semester The semester * @return array */ public function fetchAllStudentCoursesForSemester($student_num, $semester) { if (!ctype_digit($student_num) && !is_int($student_num)) { throw new \InvalidArgumentException('Invalid student number'); } if (!ctype_digit($semester)) { throw new \InvalidArgumentException("Semester provided is not a numeric value…"); } $sql = "SELECT c.name, c.code, c.section, c.session,\n cc.professor_first_name, cc.professor_last_name,\n GROUP_CONCAT(DISTINCT cc.professor_email SEPARATOR ',') AS professor_email\n FROM org_courses c\n JOIN org_course_classes cc\n ON c.course_id = cc.course_id\n JOIN org_student_course_classes x\n ON cc.class_id = x.class_id\n WHERE x.student_id = :student_num\n AND c.session = :semester\n GROUP BY c.code, c.section\n ORDER BY c.session DESC;"; $current_courses = $this->db->query($sql, array('student_num' => $student_num, 'semester' => $semester))->fetchAll(); //Add the opt out status foreach ($current_courses as $key => $cc) { $current_courses[$key]['opted_out'] = \Ventus\Utilities\Functions::checkIfStudentHasOptedOut($student_num, $cc['code'], $cc['section'], $cc['session']); $current_courses[$key]['csa_active'] = \Ventus\Utilities\Functions::checkIfStudentHasCSA($student_num, $cc['code'], $cc['section'], $cc['session']); $current_courses[$key]['template_active'] = \Ventus\Utilities\Functions::checkIfStudentHasTemplateAccs($student_num); $current_courses[$key]['expired'] = \Ventus\Utilities\Functions::checkIfStudentHasExpiredAccs($student_num, $cc['code'], $cc['section'], $cc['session']); } return $current_courses; }
require_once FS_PHP . '/header-external.php'; require_once 'views/exam-requests.php'; require_once FS_PHP . '/footer-external.php'; } elseif ($_GET['page'] === "confirm-participation") { if (!isset($_POST['eid'])) { $loggers['audit']->error('Attempted to confirm exam participation at Access Service without NOE ID.'); header('Location: exam-requests.php'); die; } $count_pending_follow_ups = $dashboard->fetchCountPendingFollowUps($SESSION->student_num); $exam_still_awaiting_response = $model->verifyExamAwaitingResponse($SESSION->student_num, $_POST['eid']); if (!empty($exam_still_awaiting_response)) { $extra_time_allowed = null; $all_active_exam_accommodations = array(); //We must also check to see if the student has opted out $opted_out = \Ventus\Utilities\Functions::checkIfStudentHasOptedOut($SESSION->student_num, $exam_still_awaiting_response['course_code'], $exam_still_awaiting_response['course_section'], $exam_still_awaiting_response['session']); if (!$opted_out) { $all_active_exam_accommodations = $profile->fetchAllStudentActiveExamAndTranscriptionAccommodations($SESSION->student_num, $exam_still_awaiting_response['exam_date'], $exam_still_awaiting_response['course_code'], $exam_still_awaiting_response['course_section'], $exam_still_awaiting_response['session']); //Check all the possible allowed accommodations to see if the student has extra time foreach ($all_active_exam_accommodations as $a) { if ($a['type'] === "Extra time") { $extra_time_allowed = explode(" ", $a['name_en']); //Get the last bit of the name of the acc. resulting in the percentage value } } } $l10n->addResource(__DIR__ . '/l10n/header.json'); $l10n->addResource(__DIR__ . '/l10n/exam-confirm-participation.json'); $l10n->localizeArray($all_active_exam_accommodations, 'name'); require_once FS_PHP . '/header-external.php'; require_once 'views/exam-confirm-participation.php';
$sentLetters = $model->getStudentLetters($_GET['student_num']); $l10n->addResource(__DIR__ . '/l10n/email-letter-generator.json'); $viewFile = 'views/email-letter-generator.php'; } } elseif ($_GET['page'] === "fetch-template") { $semester = \Ventus\Utilities\Functions::fetchSemester(); //Has student opted out? We assume no by default $opted_out = false; //Deal with whether we have course specific accs that need to be fetched $course_details = array(); if (!empty($_GET['acc_mode']) && $_GET['acc_mode'] !== 'template') { $course_components = explode('-', $_GET['acc_mode']); $course_details['course_code'] = $course_components[0]; $course_details['course_section'] = $course_components[1] === 'null' ? null : $course_components[1]; $course_details['session'] = $course_components[2]; $opted_out = \Ventus\Utilities\Functions::checkIfStudentHasOptedOut($_GET['student_num'], $course_details['course_code'], $course_details['course_section'], $course_details['session']); } //Get the actual base template that we are starting with $content = $template->getTemplate($_GET['templateid']); $content = html_entity_decode($content[0]['content']); //Fetch all the possible fields that need to be changed from tags to actual data $replacementItems = $model->getTemplateReplaceItems($_GET['student_num']); //Given a comma seperated list this functions puts that into the proper HTML so it will display in the rich editor as a bullet list function generateBulletList($accs, $lang) { $result = ""; foreach ($accs as $a) { if ($lang === 'en') { $name = $a['name']; } else { $name = $a['nom'];
} elseif ($_GET['page'] === "startnow") { $model->changeStart($_POST['reqID']); $loggers['audit']->info("Exam {$_POST['reqID']} started"); } elseif ($_GET['page'] === "startnowextend") { $model->changeStartAndEnd($_POST['reqID']); $loggers['audit']->info("Exam {$_POST['reqID']} started, time extended"); } elseif ($_GET['page'] === "exam") { $render = true; $result = $model->dataRequest($_GET['reqID']); $consheet = $model->proctorInfo($result['parent_request_id']); $allowed_accommodations = array(); //Even though it is fair to assume that the student will only have the accommodations //that they are allowed to have in ventus_exam_confirmed_accommodations, there is //no harm is making sure that we don't let anything slip through the cracks //For the course, check if the student has opted out if (!\Ventus\Utilities\Functions::checkIfStudentHasOptedOut($result['student_num'], $result['course_code'], $result['course_section'], $result['session'])) { //The student hasn't opted out. Get the confirmed accommodations $allowed_accommodations = $model->fetchConfirmedAccommodationsForExam($result['request_id']); } $result['official_evaluation_starttime'] = \DateTime::createFromFormat(DATETIME_MYSQL, $result['official_evaluation_starttime']); $result['official_evaluation_endtime'] = \DateTime::createFromFormat(DATETIME_MYSQL, $result['official_evaluation_endtime']); $result['actual_evaluation_starttime'] = \DateTime::createFromFormat(DATETIME_MYSQL, $result['actual_evaluation_starttime']); $result['actual_evaluation_endtime'] = \DateTime::createFromFormat(DATETIME_MYSQL, $result['actual_evaluation_endtime']); $result['meta'] = Proctor::determineStatus($result); $l10n->addResource(__DIR__ . '/l10n/event.json'); $viewFile = 'views/event.php'; } elseif ($_GET['page'] === "end") { $model->logInsertComment($_POST['remarks'], $_POST['reqID']); sleep(1); $model->changeEndTime($_POST['reqID']); $loggers['audit']->info("Exam {$_POST['reqID']} ended");
$active_accommodations = array_merge($active_accommodations, $active_accommodations_non_template); //Then remove the course specific exclusions $items_to_exclude = array(); foreach ($active_accommodations_non_template as $aa) { if ($aa['exception_type'] === "exclusion") { $items_to_exclude[] = $aa['accommodation_id']; } } foreach ($active_accommodations as $key => $a) { if (in_array($active_accommodations[$key]['accommodation_id'], $items_to_exclude)) { unset($active_accommodations[$key]); } } //But we also need to check if there is an opt out for this course-student combination //If so, let's empty out the active accs if (\Ventus\Utilities\Functions::checkIfStudentHasOptedOut($_GET['student_num'], $course_details[0], $course_details[1], $course_details[2])) { $read_only = -1; $active_accommodations = array(); } } //We want the id's of active accommodations in a 1D array rather than associative $active_acc_ids = array(); foreach ($active_accommodations as $a) { $active_acc_ids[$a['accommodation_id']] = $a['student_accommodation_id']; } //Given all the accommodations in the system, we will assemble active/inactive properties $global_accommodations = $model->getGlobalAccommodations(); $all_acc_properties = array(); foreach ($global_accommodations as $a) { if (array_key_exists($a['accommodation_id'], $active_acc_ids)) { $all_acc_properties[$a['accommodation_id']]['status'] = "active";
/** * Return number of eligible accommodations * @param int $student_num The student number * @param array $course_details The course details * @return boolean */ public function verifyStudentEligibilityForCourseExams($student_num, array $course_details) { //First check if the student has opted out for this course if (\Ventus\Utilities\Functions::checkIfStudentHasOptedOut($student_num, $course_details['course_code'], $course_details['course_section'], $course_details['session'])) { return false; } // If the student hasn't opted out, fetch their template accommodations $tSql = "SELECT a.accommodation_id\n FROM ventus_student_accommodations a\n JOIN ventus_accommodations v\n ON a.accommodation_id = v.accommodation_id\n JOIN ventus_accommodation_types t\n ON v.type_id = t.type_id\n WHERE a.student_num = :student_num\n AND NOW() BETWEEN a.effective_on AND a.expires_on\n AND t.category IN ('Exam', 'Transcription');"; $eligible_accommodations = $this->db->query($tSql, array('student_num' => $student_num))->fetchAll(\PDO::FETCH_COLUMN); //Then fetch the non template accommodations for this course $cParams = array('student_num' => $student_num, 'course_code' => $course_details['course_code'], 'session' => $course_details['session']); $cSql = "SELECT a.accommodation_id AS acc, exception_type\n FROM ventus_student_accommodations_exceptions a\n JOIN ventus_accommodations v\n ON a.accommodation_id = v.accommodation_id\n JOIN ventus_accommodation_types t\n ON v.type_id = t.type_id\n WHERE a.student_num = :student_num\n AND NOW() BETWEEN a.effective_on AND a.expires_on\n AND t.category IN ('Exam', 'Transcription')\n AND a.course_code = :course_code\n AND a.session = :session"; if (!empty($course_details['course_section'])) { $cParams['course_section'] = $course_details['course_section']; $cSql .= " AND a.course_section = :course_section;"; } $result = $this->db->query($cSql, $cParams)->fetchAll(); // If we have CSA, we take them into account // Add the additional ones to eligible accs foreach ($result as $r) { if ($r['exception_type'] === 'additional' && !in_array($r['acc'], $eligible_accommodations, true)) { $eligible_accommodations[] = $r['acc']; } } //Remove the exclusions foreach ($result as $r) { if ($r['exception_type'] === "exclusion" && in_array($r['acc'], $eligible_accommodations, true)) { $key = array_search($r['acc'], $eligible_accommodations); unset($eligible_accommodations[$key]); } } return !empty($eligible_accommodations); }
$denied->confirmStudentParticipationInClass($_GET); $loggers['audit']->info("In-class participation confirmed for student {$_GET['student_num']} for {$_GET['professor_exam_request_id']}"); if (ctype_digit($_GET['professor_exam_request_id']) && ctype_digit($_GET['student_num']) && \Ventus\Utilities\Functions::checkIfStringIsDate($_GET['exam_date'])) { header('Location: denied-requests.php?focus=' . $_GET['professor_exam_request_id'] . $_GET['student_num'] . '&start=' . $_GET['exam_date'] . '&end=' . $_GET['exam_date']); } else { header('Location: denied-requests.php'); } die; } elseif ($_GET['page'] === "export") { $l10n->addResource(FS_L10N . '/filenames.json'); $l10n->addResource(__DIR__ . '/l10n/unconfirmed-requests.json'); $requests = $model->getExamsAwaitingResponseForExport($_GET['start'], $_GET['end']); //Remove the elements where a student does not yet have active accommodations for the exam foreach ($requests as $key => $r) { //We must also check to see if the student has opted out $opted_out = \Ventus\Utilities\Functions::checkIfStudentHasOptedOut($r['column0'], $r['column4'], $r['column5'], $r['column3']); $active_exam_accommodations = $model->getAllStudentActiveExamAndTranscriptionAccommodations($r['column0'], $r['column7'], $r['column4'], $r['column5'], $r['column3']); if (empty($active_exam_accommodations)) { unset($requests[$key]); } } foreach ($requests as &$r) { $r["column6"] = $l10n->__($r["column6"]); //The exam type is stored in English in the database $r["column9"] = $l10n->__($r["column9"]); //The alternate status is stored in English in the database for ($i = 0; $i < sizeof($r); $i++) { $r[$l10n->__("csvColumn" . $i)] = $r["column" . $i]; unset($r["column" . $i]); } }