Ejemplo n.º 1
0
 function enrol_all_track_users_in_class()
 {
     // find all users who are not enrolled in the class
     // TODO: validate this...
     $sql = "NOT EXISTS (SELECT 'x'\n                                FROM {" . student::TABLE . "} s\n                                WHERE s.classid = ? AND s.userid = {" . usertrack::TABLE . "}.userid)\n                  AND trackid = ?";
     $params = array($this->classid, $this->trackid);
     $users = $this->_db->get_recordset_select(usertrack::TABLE, $sql, $params, 'userid');
     if ($users->valid() === true) {
         // ELIS-7582
         @set_time_limit(0);
         $timenow = time();
         $count = 0;
         $waitlisted = 0;
         $prereq = 0;
         foreach ($users as $user) {
             // enrol user in track
             $enrol = new student();
             $enrol->classid = $this->classid;
             $enrol->userid = $user->userid;
             $enrol->enrolmenttime = $timenow;
             try {
                 $enrol->save();
                 $count++;
             } catch (unsatisfied_prerequisites_exception $ex) {
                 $prereq++;
             } catch (pmclass_enrolment_limit_validation_exception $ex) {
                 // autoenrol into waitlist
                 $wait_record = new stdClass();
                 $wait_record->userid = $user->userid;
                 $wait_record->classid = $this->classid;
                 //$wait_record->enrolmenttime = $timenow;
                 $wait_record->timecreated = $timenow;
                 $wait_record->position = 0;
                 $wait_list = new waitlist($wait_record);
                 $wait_list->save();
                 $waitlisted++;
             }
         }
         print_string('n_users_enrolled', 'local_elisprogram', $count);
         if ($waitlisted) {
             print_string('n_users_waitlisted', 'local_elisprogram', $waitlisted);
         }
         if ($prereq) {
             print_string('n_users_unsatisfied_prereq', 'local_elisprogram', $prereq);
         }
     } else {
         print_string('all_users_already_enrolled', 'local_elisprogram');
     }
     unset($users);
 }
Ejemplo n.º 2
0
 /**
  * Enrols a user in a track.
  *
  * @param int $userid The user id
  * @param int $trackid The track id
  */
 public static function enrol($userid, $trackid)
 {
     global $DB;
     // make sure we don't double-enrol
     if ($DB->record_exists(self::TABLE, array('userid' => $userid, 'trackid' => $trackid))) {
         return false;
     }
     $record = new usertrack();
     $record->userid = $userid;
     $record->trackid = $trackid;
     $record->save();
     $user = new user($userid);
     $track = new track($trackid);
     if (!$DB->record_exists(curriculumstudent::TABLE, array('userid' => $userid, 'curriculumid' => $track->curid))) {
         $curstu = new curriculumstudent();
         $curstu->userid = $userid;
         $curstu->curriculumid = $track->curid;
         $curstu->completed = 0;
         $curstu->credits = 0;
         $curstu->locked = 0;
         $curstu->save();
     }
     events_trigger('track_assigned', $record);
     /**
      * 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
      */
     $sql = 'SELECT classid, courseid ' . 'FROM {' . trackassignment::TABLE . '} ' . 'WHERE trackid = ? ' . 'GROUP BY courseid ' . 'HAVING COUNT(*) = 1 AND MAX(autoenrol) = 1';
     $params = array($trackid);
     $classes = $DB->get_recordset_sql($sql, $params);
     foreach ($classes as $class) {
         // ELIS-3460: check pre-requisites ...
         $curcrs = new curriculumcourse(array('courseid' => $class->courseid, 'curriculumid' => $track->curid));
         if (!$curcrs->prerequisites_satisfied($userid)) {
             //error_log("/local/elisprogram/lib/data/usertrack.class.php::enrol({$userid}); pre-requisites NOT satisfied for course: {$class->courseid}, curriculum: {$track->curid}");
             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 {
             $status = $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();
             $status = true;
         } catch (Exception $e) {
             $param = array('message' => $e->getMessage());
             echo cm_error(get_string('record_not_created_reason', 'local_elisprogram', $param));
         }
     }
     unset($classes);
     return true;
 }
Ejemplo n.º 3
0
 /**
  * Test validation of duplicates
  *
  * Note: no exception thrown from waitlist.class.php for dup.
  */
 public function test_waitlistvalidationpreventsduplicates()
 {
     global $DB;
     $this->load_csv_data();
     $waitlist = new waitlist(array('classid' => 100, 'userid' => 1, 'position' => 1));
     $waitlist->save();
     $waitlistentries = $DB->get_records(waitlist::TABLE, array('classid' => 100, 'userid' => 1));
     $this->assertEquals(count($waitlistentries), 1);
 }
Ejemplo n.º 4
0
 function do_savewaitlist()
 {
     // action_savewaitlist
     global $USER, $DB;
     $classid = cm_get_param('id', 0, PARAM_INT);
     $form = $this->create_waitlistform($classid);
     $now = time();
     if ($form->is_cancelled()) {
         $this->display('available');
     } else {
         if ($data = $form->get_data()) {
             $class = new pmclass($classid);
             $userid = cm_get_crlmuserid($USER->id);
             $position = $DB->get_field(waitlist::TABLE, 'MAX(position)', array('classid' => $classid)) + 1;
             $wait_record = new object();
             $wait_record->userid = $userid;
             $wait_record->classid = $classid;
             $wait_record->enrolmenttime = $class->startdate;
             $wait_record->timecreated = $now;
             $wait_record->timemodified = $now;
             $wait_record->position = $position;
             $wait_list = new waitlist($wait_record);
             $wait_list->save();
             // TBD: was ->add()
             $this->display('waitlist');
         }
     }
 }
Ejemplo n.º 5
0
 /**
  * Handle a request to resolve the enrolment limit for a class.
  *
  * Over-enrols, adds to waitlist, or skips enrolment based on user selection.
  *
  * @param array $elements An array of elements to perform the action on.
  * @param int $classid The ID of the class we're enrolling into.
  * @param string $rawuseractions The JSON string containing the actions we want to perform. This will be an array, indexed by
  *                               element ID, with values being "waitlist" for add to waitlist, "overenrol" for overenrol, or
  *                               anything else being skip enrolment. If we are performing a bulk enrolment, a "bulk_enrol" key
  *                               will be present, which will take precendence.
  * @param string $enroldata A JSON string containing enrolment data for the users we want to overenrol.
  * @return array An array consisting of 'result' and 'num_affected', indicating success, and the number of users either enroled,
  *               or added to waitlist, respectively.
  */
 protected function waitlistconfirm($elements, $classid, $rawuseractions, $enroldata)
 {
     set_time_limit(0);
     // Unpack and process incoming desired user actions.
     // $rawuseractions comes from jQuery's serializeArray function, which gives us an array of arrays, each containing a "name"
     // and "value" member. after processing here, we will get an array indexed by user ID, with the value being the desired
     // waitlist action (waitlist, overenrol, skip).
     if (is_string($rawuseractions)) {
         $rawuseractions = @json_decode($rawuseractions, true);
     }
     if (empty($rawuseractions) || !is_array($rawuseractions)) {
         $rawuseractions = array();
     }
     $useractions = array();
     foreach ($rawuseractions as $param) {
         if (is_numeric($param['name']) || $param['name'] == 'bulk_action') {
             $useractions[$param['name']] = $param['value'];
         }
     }
     if (empty($useractions)) {
         throw new Exception('Did not receive any valid user ids.');
     }
     // Original enrolment data.
     $enroldata = $this->process_enrolment_data($classid, @json_decode($enroldata));
     if (empty($enroldata)) {
         throw new Exception('Did not receive valid enrolment data.');
     }
     $now = time();
     $numaffected = 0;
     foreach ($elements as $userid) {
         // Skip invalid userids or users which we dont have permission to modify.
         if (!is_numeric($userid) || !student::can_manage_assoc($userid, $classid)) {
             continue;
         }
         // Get action.
         if (isset($useractions['bulk_action'])) {
             $action = $useractions['bulk_action'];
         } else {
             if (isset($useractions[$userid])) {
                 $action = $useractions[$userid];
             } else {
                 continue;
             }
         }
         // Perform actions.
         try {
             if ($action === 'waitlist') {
                 $waitrecord = new object();
                 $waitrecord->userid = $userid;
                 $waitrecord->classid = $classid;
                 $waitrecord->timecreated = $now;
                 $waitrecord->timemodified = $now;
                 $waitrecord->position = 0;
                 $waitlist = new waitlist($waitrecord);
                 $status = $waitlist->save();
                 $numaffected++;
             } else {
                 if ($action === 'overenrol') {
                     $sturecord = $enroldata;
                     $sturecord['userid'] = $userid;
                     $newstu = new student($sturecord);
                     $newstu->validation_overrides[] = 'prerequisites';
                     $newstu->validation_overrides[] = 'enrolment_limit';
                     $status = $newstu->save();
                     $numaffected++;
                 }
             }
         } catch (Exception $e) {
             $param = array('message' => $e->getMessage());
             throw new Exception(get_string('record_not_created_reason', 'local_elisprogram', $param));
         }
     }
     return array('result' => 'success', 'num_affected' => $numaffected);
 }
Ejemplo n.º 6
0
 /**
  * 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));
     }
 }