/** * Get all of the data from Moodle and update the curriculum system. * This should do the following: * - Get all Moodle courses connected with classes. * - Get all users in each Moodle course. * - Get grade records from the class's course and completion elements. * - For each user: * - Check if they have an enrolment record in CM, and add if not. * - Update grade information in the enrollment and grade tables in CM. * * @param int $muserid optional user to update, default(0) updates all users */ function pm_update_student_progress($muserid = 0) { global $CFG; require_once $CFG->dirroot . '/grade/lib.php'; require_once $CFG->dirroot . '/grade/querylib.php'; /// Get all grades in all relevant courses for all relevant users. require_once elispm::lib('data/classmoodlecourse.class.php'); require_once elispm::lib('data/student.class.php'); require_once elispm::lib('data/pmclass.class.php'); require_once elispm::lib('data/course.class.php'); /// Start with the Moodle classes... if ($muserid == 0) { if (in_cron()) { mtrace("Synchronizing Moodle class grades<br />\n"); } } $sync = new \local_elisprogram\moodle\synchronize(); $sync->synchronize_moodle_class_grades($muserid); flush(); // sleep(1); /// Now we need to check all of the student and grade records again, since data may have come from sources /// other than Moodle. if ($muserid == 0) { //running for all users if (in_cron()) { mtrace("Updating all class grade completions.<br />\n"); } pm_update_enrolment_status(); } else { //attempting to run for a particular user $pmuserid = pm_get_crlmuserid($muserid); if ($pmuserid != false) { //user has a matching PM user pm_update_enrolment_status($pmuserid); } } return true; }
/** * Function to handle class not completed events. * * @param student $student The class enrolment / student object who is "not completed" * @uses $CFG * @uses $DB * @return boolean TRUE is successful, otherwise FALSE */ public static function class_notcompleted_handler($student) { global $CFG, $DB; require_once elispm::lib('notifications.php'); /// Does the user receive a notification? $sendtouser = elis::$config->local_elisprogram->notify_classnotcompleted_user; $sendtorole = elis::$config->local_elisprogram->notify_classnotcompleted_role; $sendtosupervisor = elis::$config->local_elisprogram->notify_classnotcompleted_supervisor; /// If nobody receives a notification, we're done. if (!$sendtouser && !$sendtorole && !$sendtosupervisor) { return true; } if (!empty($student->moodlecourseid)) { if (!($context = context_course::instance($student->moodlecourseid))) { if (in_cron()) { mtrace(get_string('invalidcontext')); } else { debugging(get_string('invalidcontext')); } return true; } } else { $context = context_system::instance(); } $message = new notification(); /// Set up the text of the message $text = empty(elis::$config->local_elisprogram->notify_classnotcompleted_message) ? get_string('notifyclassnotcompletedmessagedef', self::LANG_FILE) : elis::$config->local_elisprogram->notify_classnotcompleted_message; $search = array('%%userenrolname%%', '%%classname%%', '%%coursename%%'); $user = new user($student->userid); if (!$user) { if (in_cron()) { mtrace(get_string('nouser', 'local_elisprogram')); } else { debugging(get_string('nouser', 'local_elisprogram')); } return true; } $user->load(); // Get course info $pmcourse = $DB->get_record(course::TABLE, array('id' => $student->courseid)); $pmclass = $DB->get_record(pmclass::TABLE, array('id' => $student->classid)); $replace = array($user->moodle_fullname(), $pmclass->idnumber, $pmcourse->name); $text = str_replace($search, $replace, $text); $eventlog = new Object(); $eventlog->event = 'class_notcompleted'; $eventlog->instance = $student->classid; $eventlog->fromuserid = $user->id; if ($sendtouser) { $message->send_notification($text, $user, null, $eventlog); } $users = array(); if ($sendtorole) { /// Get all users with the notify_classnotcomplete capability. if ($roleusers = get_users_by_capability($context, 'local/elisprogram:notify_classnotcomplete')) { $users = $users + $roleusers; } } if ($sendtosupervisor) { /// Get parent-context users. if ($supervisors = pm_get_users_by_capability('user', $user->id, 'local/elisprogram:notify_classnotcomplete')) { $users = $users + $supervisors; } } // Send notifications to any users who need to receive them. foreach ($users as $touser) { $message->send_notification($text, $touser, $user, $eventlog); } return true; }
/** * Updates resulting enrolments that are auto-created after users are * assigned to user sets (specifically user-track assignments, user-program * assignments, and class enrolments in a track's default class) * * Note: This is essentially equivalent to cluster_assigned_handler but * runs a fixed number of queries for scalability reasons * * @param int $userid A specific PM user id to filter on for * consideration, or all users if zero * @param int $clusterid A specific cluster / user set id to filter * on for consideration, or all users if zero */ static function update_enrolments($userid = 0, $clusterid = 0) { global $DB; require_once elispm::lib('data/usermoodle.class.php'); // error_log("/local/elisprogram/lib/data/clusterassignment.class.php::update_enrolments({$userid}, {$clusterid})"); // ELIS-7582 @set_time_limit(0); // convert provided parameters to SQL conditions $extraconditions = array(); $extraparams = array(); if (!empty($userid)) { $users = array($userid); $extraconditions[] = 'u.id = ?'; $extraparams[] = $userid; } else { $users = clusterassignment::find(new field_filter('clusterid', $clusterid)); } if (!empty($clusterid)) { $extraconditions[] = 'clu.clusterid = ?'; $extraparams[] = $clusterid; } $extrawhere = ''; if (!empty($extraconditions)) { $extrawhere = ' AND ' . implode(' AND ', $extraconditions); } //use the current time as the time created and modified for curriculum //assignments $timenow = time(); //assign to curricula based on user-cluster and cluster-curriculum //associations $sql = "INSERT INTO {" . curriculumstudent::TABLE . "}\n (userid, curriculumid, timecreated, timemodified)\n SELECT DISTINCT u.id, clucur.curriculumid, {$timenow}, {$timenow}\n FROM {" . clusterassignment::TABLE . "} clu\n JOIN {" . user::TABLE . "} u ON u.id = clu.userid\n JOIN {" . clustercurriculum::TABLE . "} clucur\n ON clucur.clusterid = clu.clusterid\n LEFT JOIN {" . curriculumstudent::TABLE . "} ca\n ON ca.userid = u.id\n AND ca.curriculumid = clucur.curriculumid\n WHERE ca.curriculumid IS NULL\n AND clucur.autoenrol = 1\n {$extrawhere}"; $DB->execute($sql, $extraparams); //assign to curricula based on user-cluster and cluster-track //associations (assigning a user to a track auto-assigns them to //the track's curriculum, track assignment happens below) $sql = "INSERT INTO {" . curriculumstudent::TABLE . "}\n (userid, curriculumid, timecreated, timemodified)\n SELECT DISTINCT u.id, trk.curid, {$timenow}, {$timenow}\n FROM {" . clusterassignment::TABLE . "} clu\n JOIN {" . user::TABLE . "} u\n ON u.id = clu.userid\n JOIN {" . clustertrack::TABLE . "} clutrk\n ON clutrk.clusterid = clu.clusterid\n JOIN {" . track::TABLE . "} trk\n ON clutrk.trackid = trk.id\n LEFT JOIN {" . curriculumstudent::TABLE . "} ca\n ON ca.userid = u.id\n AND ca.curriculumid = trk.curid\n WHERE ca.curriculumid IS NULL\n AND clutrk.autoenrol = 1\n {$extrawhere}"; $DB->execute($sql, $extraparams); //this represents the tracks that users will be assigned to //based on user-cluster and cluster-track associations //(actual assignment happens below) $exists = "EXISTS (SELECT DISTINCT u.id, clutrk.trackid\n FROM {" . clusterassignment::TABLE . "} clu\n JOIN {" . user::TABLE . "} u\n ON u.id = clu.userid\n JOIN {" . clustertrack::TABLE . "} clutrk\n ON clutrk.clusterid = clu.clusterid\n LEFT JOIN {" . usertrack::TABLE . "} ta\n ON ta.userid = u.id\n AND ta.trackid = clutrk.trackid\n WHERE ta.trackid IS NULL\n AND clutrk.autoenrol = 1\n AND outerta.trackid = clutrk.trackid\n\t {$extrawhere})"; /** * Get autoenrollable classes in the track. Classes are autoenrollable * if: * - the autoenrol flag is set * - it is the only class in that course slot for the track */ // group the classes from the same course together // only select the ones that are the only class for that course in // the given track, and if the autoenrol flag is set $sql = "SELECT outerta.classid, outerta.courseid, trk.curid\n FROM {" . trackassignment::TABLE . "} outerta\n JOIN {" . track::TABLE . "} trk ON trk.id = outerta.trackid\n WHERE {$exists}\n GROUP BY courseid\n HAVING COUNT(*) = 1 AND MAX(autoenrol) = 1"; //go through and assign user(s) to the autoenollable classes $classes = $DB->get_records_sql($sql, $extraparams); if (!empty($classes)) { foreach ($users as $user) { $userid = is_object($user) ? $user->userid : $user; foreach ($classes as $class) { // check pre-requisites $curcrs = new curriculumcourse(array('courseid' => $class->courseid, 'curriculumid' => $class->curid)); if (!$curcrs->prerequisites_satisfied($userid)) { continue; } $now = time(); // enrol user in each autoenrolable class $stu_record = new object(); $stu_record->userid = $userid; $stu_record->classid = $class->classid; $stu_record->enrolmenttime = $now; $enrolment = new student($stu_record); // catch enrolment limits try { $enrolment->save(); } catch (pmclass_enrolment_limit_validation_exception $e) { // autoenrol into waitlist $wait_record = new object(); $wait_record->userid = $userid; $wait_record->classid = $class->classid; $wait_record->enrolmenttime = $now; $wait_record->timecreated = $now; $wait_record->position = 0; $wait_list = new waitlist($wait_record); $wait_list->save(); } catch (Exception $e) { $param = array('message' => $e->getMessage()); if (in_cron()) { mtrace(get_string('record_not_created_reason', 'local_elisprogram', $param)); } else { echo cm_error(get_string('record_not_created_reason', 'local_elisprogram', $param)); } } } } } //assign to tracks based on user-cluster and cluster-track //associations $sql = "INSERT INTO {" . usertrack::TABLE . "}\n (userid, trackid)\n SELECT DISTINCT u.id, clutrk.trackid\n FROM {" . clusterassignment::TABLE . "} clu\n JOIN {" . user::TABLE . "} u\n ON u.id = clu.userid\n JOIN {" . clustertrack::TABLE . "} clutrk\n ON clutrk.clusterid = clu.clusterid\n LEFT JOIN {" . usertrack::TABLE . "} ta\n ON ta.userid = u.id\n AND ta.trackid = clutrk.trackid\n WHERE ta.trackid IS NULL\n AND clutrk.autoenrol = 1\n {$extrawhere}"; $DB->execute($sql, $extraparams); //update site-level "cluster groups" //TODO: make sure all "cluster groups" scenarios are handled here, and look at //performance in more detal if (!empty($userid) && file_exists(elispm::file('plugins/usetgroups/lib.php'))) { require_once elispm::file('plugins/usetgroups/lib.php'); //need the Moodle user id $mdluserid = $DB->get_field(usermoodle::TABLE, 'muserid', array('cuserid' => $userid)); if ($mdluserid) { //find all assignments for this user $assignments = $DB->get_recordset(clusterassignment::TABLE, array('userid' => $userid)); foreach ($assignments as $assignment) { //update site-level group assignments userset_groups_update_site_course($assignment->clusterid, true, $mdluserid); } } //update course-level group assignment userset_groups_update_groups(array('mdlusr.cuserid' => $userid)); } }
public function send_notification($message = '', $userto = null, $userfrom = null, $logevent = false) { global $DB, $USER; /// Handle parameters: if (!empty($userto)) { $this->userto = $userto; } else { if (empty($this->userto)) { if (in_cron()) { mtrace(get_string('message_nodestinationuser', 'local_elisprogram')); } else { print_error('message_nodestinationuser', 'local_elisprogram'); } return false; } } if (!empty($userfrom)) { $this->userfrom = $userfrom; } else { if (empty($this->userfrom)) { $this->userfrom = $USER; } } if ($message != '') { $this->fullmessage = $message; } /// Check for the user object type. If a PM User was sent in, need to get the Moodle object. //todo: convert this code to use "is_a" $topmuserid = false; if (get_class($this->userto) == 'user') { $topmuserid = $this->userto->id; if (!($this->userto = $this->userto->get_moodleuser())) { // TODO log here. return false; } } if (empty($this->userto)) { // TODO log here. return false; } if (get_class($this->userfrom) == 'user') { // if (!($this->userfrom = cm_get_moodleuser($this->userfrom->id))) { if (!($this->userfrom = $this->userfrom->get_moodleuser())) { if (in_cron()) { mtrace(get_string('nomoodleuser', 'local_elisprogram')); } else { debugging(get_string('nomoodleuser', 'local_elisprogram')); } } } if (empty($this->userfrom)) { // ELIS-3632: prevent DB errors downstream $this->userfrom = $USER; // TBD } /// Handle unset variables: $this->name = $this->name == '' ? $this->defname : $this->name; $this->subject = $this->subject == '' ? $this->defsubject : $this->subject; //this call performs the core work involved in notifying users pm_notify_send_handler(clone $this); /// Insert a notification log if we have data for it. if ($logevent !== false) { if (!empty($logevent->event)) { $newlog = new Object(); $newlog->event = $logevent->event; if (isset($logevent->userid)) { $newlog->userid = $logevent->userid; } else { if ($topmuserid === false) { $newlog->userid = pm_get_crlmuserid($this->userto->id); } else { $newlog->userid = $topmuserid; } } //if the log entry specifies which user triggered the event, //store that info //NOTE: Do not use $userfrom because that is the message sender //but not necessarily the user whose criteria triggered the event if (isset($logevent->fromuserid)) { $newlog->fromuserid = $logevent->fromuserid; } if (isset($logevent->instance)) { $newlog->instance = $logevent->instance; } if (isset($logevent->data)) { $newlog->data = $logevent->data; } if (isset($logevent->timecreated)) { $newlog->timecreated = $logevent->timecreated; } else { $newlog->timecreated = time(); } $DB->insert_record('local_elisprogram_notifylog', $newlog); } } }
/** * Function to handle course recurrence events. * * @param user $user CM user object representing the user in the course * * @return boolean TRUE is successful, otherwise FALSE */ public static function course_recurrence_handler($user) { global $DB; require_once elispm::lib('notifications.php'); /// Does the user receive a notification? $sendtouser = elis::$config->local_elisprogram->notify_courserecurrence_user; $sendtorole = elis::$config->local_elisprogram->notify_courserecurrence_role; $sendtosupervisor = elis::$config->local_elisprogram->notify_courserecurrence_supervisor; /// If nobody receives a notification, we're done. if (!$sendtouser && !$sendtorole && !$sendtosupervisor) { return true; } $context = context_system::instance(); /// Make sure this is a valid user. $enroluser = new user($user->userid); if (!$enroluser) { if (in_cron()) { mtrace(get_string('nouser', 'local_elisprogram')); } else { print_error('nouser', 'local_elisprogram'); } return true; } // Due to lazy loading, we need to pre-load this object $enroluser->load(); if (empty($enroluser->id)) { if (in_cron()) { mtrace(get_string('nouser', 'local_elisprogram')); } else { print_error('nouser', 'local_elisprogram'); } return true; } /// Set up the text of the message $message = new notification(); $text = empty(elis::$config->local_elisprogram->notify_courserecurrence_message) ? get_string('notifycourserecurrencemessagedef', 'local_elisprogram') : elis::$config->local_elisprogram->notify_courserecurrence_message; $search = array('%%userenrolname%%', '%%coursename%%'); $replace = array($enroluser->moodle_fullname(), $user->coursename); $text = str_replace($search, $replace, $text); $eventlog = new Object(); $eventlog->event = 'course_recurrence'; $eventlog->instance = $user->enrolmentid; $eventlog->fromuserid = $enroluser->id; if ($sendtouser) { $message->send_notification($text, $enroluser, null, $eventlog); } $users = array(); if ($sendtorole) { /// Get all users with the notify_courserecurrence capability. if ($roleusers = get_users_by_capability($context, 'local/elisprogram:notify_courserecurrence')) { $users = $users + $roleusers; } } if ($sendtosupervisor) { /// Get parent-context users. if ($supervisors = pm_get_users_by_capability('user', $enroluser->id, 'local/elisprogram:notify_courserecurrence')) { $users = $users + $supervisors; } } foreach ($users as $u) { $message->send_notification($text, $u, $enroluser, $eventlog); } return true; }