/** * Save a set of enrolments and LO grades to the database * @param array $enrolments Enrolment data to save * @param array $grades LO grade data to save */ protected function save_enrolments($enrolments, $grades = array()) { // Enrolments. foreach ($enrolments as $enrolment) { $student = new student($enrolment); $sink = $this->redirectMessages(); $student->save(); } // LO grades. foreach ($grades as $grade) { $studentgrade = new student_grade($grade); $studentgrade->save(); } }
function action_update() { global $CURMAN; $stuid = $this->required_param('association_id', PARAM_INT); $clsid = $this->required_param('id', PARAM_INT); $users = $this->required_param('users'); $uid = key($users); $user = current($users); $sturecord = array(); $sturecord['id'] = $stuid; $sturecord['classid'] = $clsid; $sturecord['userid'] = $uid; $startyear = $user['startyear']; $startmonth = $user['startmonth']; $startday = $user['startday']; $sturecord['enrolmenttime'] = mktime(0, 0, 0, $startmonth, $startday, $startyear); $endyear = $user['endyear']; $endmonth = $user['endmonth']; $endday = $user['endday']; $sturecord['completetime'] = mktime(0, 0, 0, $endmonth, $endday, $endyear); $sturecord['completestatusid'] = $user['completestatusid']; $sturecord['grade'] = $user['grade']; $sturecord['credits'] = $user['credits']; $sturecord['locked'] = !empty($user['locked']) ? 1 : 0; $stu = new student($sturecord); if ($stu->completestatusid == STUSTATUS_PASSED && $CURMAN->db->get_field(STUTABLE, 'completestatusid', 'id', $stuid) != STUSTATUS_PASSED) { $stu->complete(); } else { if (($status = $stu->update()) !== true) { echo cm_error('Record not updated. Reason: ' . $status->message); } } /// Check for grade records... $element = cm_get_param('element', array()); $newelement = cm_get_param('newelement', array()); $timegraded = cm_get_param('timegraded', array()); $newtimegraded = cm_get_param('newtimegraded', array()); $completionid = cm_get_param('completionid', array()); $newcompletionid = cm_get_param('newcompletionid', array()); $grade = cm_get_param('grade', array()); $newgrade = cm_get_param('newgrade', array()); $locked = cm_get_param('locked', array()); $newlocked = cm_get_param('newlocked', array()); foreach ($element as $gradeid => $element) { $graderec = array(); $graderec['id'] = $gradeid; $graderec['userid'] = $uid; $graderec['classid'] = $clsid; $graderec['completionid'] = $element; $graderec['timegraded'] = mktime(0, 0, 0, $timegraded[$gradeid]['startmonth'], $timegraded[$gradeid]['startday'], $timegraded[$gradeid]['startyear']); $graderec['grade'] = $grade[$gradeid]; $graderec['locked'] = isset($locked[$gradeid]) ? $locked[$gradeid] : '0'; $sgrade = new student_grade($graderec); $sgrade->update(); } foreach ($newelement as $elementid => $element) { $graderec = array(); $graderec['userid'] = $uid; $graderec['classid'] = $clsid; $graderec['completionid'] = $element; $graderec['timegraded'] = mktime(0, 0, 0, $newtimegraded[$elementid]['startmonth'], $newtimegraded[$elementid]['startday'], $newtimegraded[$elementid]['startyear']); $graderec['grade'] = $newgrade[$elementid]; $graderec['locked'] = isset($newlocked[$elementid]) ? $newlocked[$elementid] : '0'; $sgrade = new student_grade($graderec); $sgrade->add(); } $this->action_default(); }
/** * Test sync_completionelements method. * * @dataProvider dataprovider_sync_completionelements * @param array $gradeitem Array of parameters to create grade_item. * @param array $gradegrade Array of parameters to create grade_grade. * @param array $coursecompletion Array of parameters to create coursecompletion. * @param array $studentgrade Array of parameters to create student_grade. * @param int $timenow Current timestamp to enable testing with time. * @param array $expectedstudentgrade Array of parameters we expect to be set in the student_grade. */ public function test_sync_completionelements($gradeitem, $gradegrade, $coursecompletion, $studentgrade, $timenow, $expectedstudentgrade) { global $DB; $sync = new \local_elisprogram\moodle\synchronize(); // Test data setup. $crs = new \course(array('idnumber' => 'CRS1', 'name' => 'Course 1', 'syllabus' => '')); $crs->save(); $cls = new \pmclass(array('courseid' => $crs->id, 'idnumber' => 'CLS1')); $cls->save(); $usr = new \user(array('username' => 'test1', 'idnumber' => 'test2', 'firstname' => 'test', 'lastname' => 'user', 'email' => '*****@*****.**', 'country' => 'CA')); $usr->save(); $musr = $this->getDataGenerator()->create_user(); $gradeitem = new \grade_item($gradeitem, false); $gradeitem->insert(); $gradegrade['itemid'] = $gradeitem->id; $gradegrade['userid'] = $musr->id; $gradegrade = new \grade_grade($gradegrade, false); $gradegrade->insert(); $coursecompletion['courseid'] = $crs->id; $coursecompletion = new \coursecompletion($coursecompletion); $coursecompletion->save(); if ($studentgrade !== false) { $studentgrade['classid'] = $cls->id; $studentgrade['userid'] = $usr->id; $studentgrade['completionid'] = $coursecompletion->id; $studentgrade = new \student_grade($studentgrade); $studentgrade->save(); $studentgrade = new \student_grade($studentgrade->id); $studentgrade->load(); } // Method parameter setup. $causer = (object) array('cmid' => $usr->id, 'pmclassid' => $cls->id); $gis = array($gradeitem->id => (object) array('id' => $gradeitem->id, 'grademax' => $gradeitem->grademax)); $compelements = array($gradeitem->id => (object) array('id' => $coursecompletion->id, 'completion_grade' => $coursecompletion->completion_grade)); $moodlegrades = array($gradeitem->id => $gradegrade); if ($studentgrade !== false) { $cmgrades = array($coursecompletion->id => $studentgrade->to_object()); } else { $cmgrades = array(); } $sync->sync_completionelements($causer, $gis, $compelements, $moodlegrades, $cmgrades, $timenow); $actualstudentgrade = false; if ($studentgrade !== false) { $actualstudentgrade = $DB->get_record(\student_grade::TABLE, array('id' => $studentgrade->id)); } else { $actualstudentgrades = $DB->get_records(\student_grade::TABLE, array(), 'id DESC'); if (!empty($actualstudentgrades)) { $actualstudentgrade = array_shift($actualstudentgrades); } } if ($actualstudentgrade !== false) { if ($expectedstudentgrade !== false) { $expectedstudentgrade['id'] = $actualstudentgrade->id; $expectedstudentgrade['classid'] = $cls->id; $expectedstudentgrade['userid'] = $usr->id; $expectedstudentgrade['completionid'] = $coursecompletion->id; // This is here for tests where we can't reliably predetermine timemodified (i.e. no-sync cases). if (!isset($expectedstudentgrade['timemodified'])) { $expectedstudentgrade['timemodified'] = $actualstudentgrade->timemodified; } $expectedstudentgrade = (object) $expectedstudentgrade; $this->assertEquals($expectedstudentgrade, $actualstudentgrade); } else { $this->assertTrue(false, 'A student_grade was created when one was not expected.'); } } else { // If $expectedstudentgrade is false we were expected no grade to be created. If not, we have a problem. if ($expectedstudentgrade !== false) { $this->assertTrue(false, 'No student_grade created when one was expected'); } else { $this->assertTrue(true); } } }
/** * Perform all necessary tasks to remove a student enrolment from the system. */ function delete() { /// Remove any grade records for this enrolment. $result = student_grade::delete_for_user_and_class($this->userid, $this->classid); /// Unenrol them from the Moodle class. if ($moodlecourseid = moodle_get_course($this->classid)) { if (($mcourse = $this->_db->get_record('course', array('id' => $moodlecourseid))) && ($muser = $this->users->get_moodleuser())) { $sql = 'SELECT enrol.* FROM {user_enrolments} enrolments JOIN {enrol} enrol ON enrol.id = enrolments.enrolid WHERE enrol.courseid = ? AND enrolments.userid = ?'; $enrolments = $this->_db->get_recordset_sql($sql, array($moodlecourseid, $muser->id)); foreach ($enrolments as $enrolment) { $plugin = enrol_get_plugin($enrolment->enrol); $plugin->unenrol_user($enrolment, $muser->id); } unset($enrolments); } } parent::delete(); if ($this->completestatusid == STUSTATUS_NOTCOMPLETE) { $pmclass = $this->pmclass; if (empty($pmclass->maxstudents) || $pmclass->maxstudents > static::count_enroled($pmclass->id)) { $wlst = waitlist::get_next($this->classid); if (!empty($wlst)) { $wlst->enrol(); } } } return $result; }
public function delete() { global $CFG; $result = false; $muser = cm_get_moodleuserid($this->id); if (empty($muser) || !is_primary_admin($muser)) { $level = context_level_base::get_custom_context_level('user', 'block_curr_admin'); $result = attendance::delete_for_user($this->id); $result = $result && curriculumstudent::delete_for_user($this->id); $result = $result && instructor::delete_for_user($this->id); $result = $result && student::delete_for_user($this->id); $result = $result && student_grade::delete_for_user($this->id); $result = $result && usertrack::delete_for_user($this->id); $result = $result && usercluster::delete_for_user($this->id); $result = $result && clusterassignment::delete_for_user($this->id); $result = $result && waitlist::delete_for_user($this->id); $result = $result && delete_context($level, $this->id); // Delete Moodle user. if ($muser = get_record('user', 'idnumber', $this->idnumber, 'mnethostid', $CFG->mnet_localhost_id, 'deleted', 0)) { $result = $result && delete_user($muser); } $result = $result && parent::delete(); } return $result; }
public function delete() { global $CFG; $muser = $this->get_moodleuser(); if (empty($muser) || !is_primary_admin($muser->id)) { // delete associated data require_once elis::lib('data/data_filter.class.php'); $filter = new field_filter('userid', $this->id); curriculumstudent::delete_records($filter, $this->_db); student::delete_records($filter, $this->_db); student_grade::delete_records($filter, $this->_db); waitlist::delete_records($filter, $this->_db); instructor::delete_records($filter, $this->_db); usertrack::delete_records($filter, $this->_db); clusterassignment::delete_records($filter, $this->_db); //delete association to Moodle user, if applicable require_once elispm::lib('data/usermoodle.class.php'); $filter = new field_filter('cuserid', $this->id); usermoodle::delete_records($filter, $this->_db); // Delete Moodle user. if (!empty($muser)) { delete_user($muser); } parent::delete(); $context = \local_elisprogram\context\user::instance($this->id); $context->delete(); } }
/** * Perform all necessary tasks to remove a student enrolment from the system. */ function delete() { /// Remove any grade records for this enrolment. $result = student_grade::delete_for_user_and_class($this->userid, $this->classid); /// Unenrol them from the Moodle class. if (!empty($this->classid) && !empty($this->userid) && ($moodlecourseid = get_field('crlm_class_moodle', 'moodlecourseid', 'classid', $this->classid)) && ($muserid = cm_get_moodleuserid($this->userid))) { $context = get_context_instance(CONTEXT_COURSE, $moodlecourseid); if ($context && $context->id) { role_unassign(0, $muserid, 0, $context->id); } } $result = $result && $this->data_delete_record(); if ($this->completestatusid == STUSTATUS_NOTCOMPLETE) { $cmclass = new cmclass($this->classid); if (empty($cmclass->maxstudents) || $cmclass->maxstudents > student::count_enroled($cmclass->id)) { $wlst = waitlist::get_next($this->classid); if (!empty($wlst)) { $wlst->enrol(); } } } return $result; }
/** * Validate that LO grades are locked when they are updated and grade * is sufficient when run for a specific user */ public function test_methodlockslearningobjectivegradesduringupdateforspecificuserid() { global $DB; $this->load_csv_data(); // Create enrolment. $this->make_course_enrollable(); enrol_try_internal_enrol(2, 100, 1); enrol_try_internal_enrol(2, 101, 1); // Create LO and Moodle grade. $itemid = $this->create_grade_item(); $this->create_grade_grade($itemid, 100, 75, 100, 1); $this->create_grade_grade($itemid, 101, 75, 100, 1); $this->create_course_completion('manualitem', 50); // Enrol in PM class. $studentgrade = new \student_grade(array('userid' => 103, 'classid' => 100, 'completionid' => 1, 'grade' => 75, 'locked' => 0, 'timegraded' => 1)); $studentgrade->save(); $studentgrade = new \student_grade(array('userid' => 104, 'classid' => 100, 'completionid' => 1, 'grade' => 75, 'locked' => 0, 'timegraded' => 1)); $studentgrade->save(); // Validate setup. $this->assert_num_student_grades(2); $count = $DB->count_records(\student_grade::TABLE, array('locked' => 1)); $this->assertEquals(0, $count); $this->assert_student_grade_exists(100, 103, 1, null, 0); // Update Moodle info. $DB->execute("UPDATE {grade_grades} SET finalgrade = 80, timemodified = 2"); // Run and validate. $sync = new \local_elisprogram\moodle\synchronize(); $sync->synchronize_moodle_class_grades(100); $this->assert_num_student_grades(2); $count = $DB->count_records(\student_grade::TABLE, array('locked' => 1)); $this->assertEquals(1, $count); $this->assert_student_grade_exists(100, 103, 1, null, 1); }
/** * Test that a record can be modified. */ public function teststudentgradecanupdaterecord() { $this->load_csv_data(); // Read a record. $src = new student_grade(1, null, array(), false, array()); $src->grade = 70; $src->save(); // Read it back. $retr = new student_grade(3, null, array(), false, array()); foreach ($src as $key => $value) { if (strpos($key, elis_data_object::FIELD_PREFIX) !== false) { $key = substr($key, strlen(elis_data_object::FIELD_PREFIX)); $this->assertEquals($src->{$key}, $retr->{$key}); } } }
function delete() { $status = true; if (!empty($this->id)) { instructor::delete_for_class($this->id); student::delete_for_class($this->id); trackassignmentclass::delete_for_class($this->id); classmoodlecourse::delete_for_class($this->id); student_grade::delete_for_class($this->id); attendance::delete_for_class($this->id); taginstance::delete_for_class($this->id); waitlist::delete_for_class($this->id); classmoodlecourse::delete_for_class($this->id); $level = context_level_base::get_custom_context_level('class', 'block_curr_admin'); $result = delete_context($level, $this->id); $status = $this->data_delete_record(); } return $status; }
/** * Test enrolment functions using an invalid class ID. */ public function test_enrolment_with_invalid_classid() { global $CFG, $DB; require_once $CFG->dirroot . '/local/elisprogram/lib/setup.php'; require_once elispm::lib('lib.php'); $this->load_csv_data(); $enrolment = new stdClass(); $enrolment->classid = 1000; // Invalid class ID. $enrolment->userid = 103; $enrolment->enrolmenttime = time(); $enrolment->completetime = 0; $enrolment->endtime = 0; $enrolment->completestatusid = 0; $enrolment->grade = 0; $enrolment->credits = 0.0; $enrolment->locked = 0; // Directly insert the record to bypass 'student' class validation on the classid. $this->assertGreaterThan(0, $DB->insert_record(student::TABLE, $enrolment)); // Attempt to update status before the required learning objective is satisfied. // ELIS-4955 -- This should ignore the bad data and proceed without error. pm_update_enrolment_status(); // Validate that the enrolment is still in progress. $sturecord = new student(100); $this->assertEquals(STUSTATUS_NOTCOMPLETE, $sturecord->completestatusid); $this->assertEquals(0, $sturecord->locked); // Satisfy the required learning objective. $graderecord = new student_grade(1); $graderecord->grade = 80; $graderecord->save(); // Attempt to update status now that the required learning objective is satisfied. pm_update_enrolment_status(); // Validate that the enrolment is passed. $sturecord = new student(100); $this->assertEquals(STUSTATUS_PASSED, $sturecord->completestatusid); $this->assertEquals(1, $sturecord->locked); }
/** * Perform an update for a single user/class pair. * * @param int $userid The user ID we're updating. * @param int $classid The class ID we're updating information for. * @param array $enroldata The updated enrolment data. * @param array $learningobjectives The updated learning objective data. */ protected function do_update($userid, $classid, array $enroldata, array $learningobjectives) { global $DB; if (student::can_manage_assoc($userid, $classid) !== true) { throw new Exception('Unauthorized'); } if (!isset($enroldata['id'])) { $associationid = $DB->get_field(student::TABLE, 'id', array('classid' => $classid, 'userid' => $userid)); if (empty($associationid)) { return false; } else { $enroldata['id'] = $associationid; } } $enroldata['userid'] = $userid; $stu = new student($enroldata); if ($stu->completestatusid == STUSTATUS_PASSED && $DB->get_field(student::TABLE, 'completestatusid', array('id' => $stu->id)) != STUSTATUS_PASSED) { $stu->complete(); } else { $status = $stu->save(); } foreach ($learningobjectives as $id => $data) { $graderec = array('userid' => $userid, 'classid' => $classid, 'completionid' => $id); $existingrec = $DB->get_record(student_grade::TABLE, $graderec); if (!empty($existingrec)) { $graderec = (array) $existingrec; } $graderec['timegraded'] = $data['timegraded']; $graderec['grade'] = $data['grade']; $graderec['locked'] = $data['locked']; $sgrade = new student_grade($graderec); $sgrade->save(); } }
/** * Validate that the pm_update_enrolment_status method respects its userid parameter, i.e. it can run only for a specific user. * NOTE: this unit test does not test all cases because that should be specifically tested for $pmclass->update_enrolment_status * * @param array $enrolments A list of class enrolment records we are processing * @param array $classgraded A list of learning objective grades we are processing * @dataProvider dataprovider_updatedelegation */ public function test_pmupdateenrolmentstatusrespectsuseridparameter($enrolments, $classgraded) { global $DB; // Necessary data. $this->load_csv_data(); foreach ($enrolments as $key => $enrolment) { // Create student enrolment. $record = new student($enrolment); $record->save(); } foreach ($classgraded as $lograde) { // Create learning objective grade. $record = new student_grade($lograde); $record->save(); } // Pass the appropriate student. pm_update_enrolment_status(2); // We should have one passed student in the PM class instance, and that student should be the second user. $enrolments = $DB->get_records(student::TABLE, array('completestatusid' => STUSTATUS_PASSED)); $this->assertEquals(1, count($enrolments)); $enrolment = reset($enrolments); $this->assertEquals(100, $enrolment->classid); $this->assertEquals(2, $enrolment->userid); $this->assertEquals(100, $enrolment->grade); }
function delete() { if (!empty($this->id)) { //clean make the delete cascade into association records $filter = new field_filter('classid', $this->id); instructor::delete_records($filter, $this->_db); student::delete_records($filter, $this->_db); trackassignment::delete_records($filter, $this->_db); classmoodlecourse::delete_records($filter, $this->_db); student_grade::delete_records($filter, $this->_db); waitlist::delete_records($filter, $this->_db); parent::delete(); $context = \local_elisprogram\context\pmclass::instance($this->id); $context->delete(); } }