/** * Clone a class * @param array $options options for cloning. Valid options are: * - 'moodlecourses': whether or not to clone Moodle courses (if they were * autocreated). Values can be (default: "copyalways"): * - "copyalways": always copy course * - "copyautocreated": only copy autocreated courses * - "autocreatenew": autocreate new courses from course template * - "link": link to existing course * - 'targetcourse': the course id to associate the clones with (default: * same as original class) * @return array array of array of object IDs created. Key in outer array * is type of object (plural). Key in inner array is original object ID, * value is new object ID. Outer array also has an entry called 'errors', * which is an array of any errors encountered when duplicating the * object. */ function duplicate($options = array()) { global $CURMAN; $objs = array('errors' => array()); if (isset($options['targetcluster'])) { $cluster = $options['targetcluster']; if (!is_object($cluster) || !is_a($cluster, 'cluster')) { $options['targetcluster'] = $cluster = new cluster($cluster); } } // clone main class object $clone = new cmclass($this); unset($clone->id); if (isset($options['targetcourse'])) { $clone->courseid = $options['targetcourse']; } if (isset($cluster)) { // if cluster specified, append cluster's name to class $clone->idnumber = $clone->idnumber . ' - ' . $cluster->name; } $clone = new cmclass(addslashes_recursive($clone)); $clone->autocreate = false; // avoid warnings if (!$clone->add()) { $objs['errors'][] = get_string('failclustcpycls', 'block_curr_admin', $this); return $objs; } $objs['classes'] = array($this->id => $clone->id); $cmc = $CURMAN->db->get_record(CLSMDLTABLE, 'classid', $this->id); if ($cmc) { if ($cmc->autocreated == -1) { $cmc->autocreated = $CURMAN->config->autocreated_unknown_is_yes; } if (empty($options['moodlecourses']) || $options['moodlecourses'] == 'copyalways' || $options['moodlecourses'] == 'copyautocreated' && $cmc->autocreated) { // create a new Moodle course based on the current class's Moodle course $moodlecourseid = content_rollover($cmc->moodlecourseid, $clone->startdate); // Rename the fullname, shortname and idnumber of the restored course $restore->id = $moodlecourseid; $restore->fullname = addslashes($clone->course->name . '_' . $clone->idnumber); $restore->shortname = addslashes($clone->idnumber); $CURMAN->db->update_record('course', $restore); moodle_attach_class($clone->id, $moodlecourseid); } elseif ($options['moodlecourses'] == 'link' || $options['moodlecourses'] == 'copyautocreated' && !$cmc->autocreated) { // link to the current class's Moodle course moodle_attach_class($clone->id, $cmc->moodlecourseid); } else { // $options['moodlecourses'] == 'autocreatenew' // create a new course based on the course template moodle_attach_class($clone->id, 0, '', false, false, true); } } // FIXME: copy tags return $objs; }
/** * Creates and associates a class with a track for every course that * belongs to the track curriculum * * TODO: return some data */ function track_auto_create() { // Had to load $this due to lazy-loading $this->load(); if (empty($this->curid) or empty($this->id)) { cm_error('trackid and curid have not been properly initialized'); return false; } $autoenrol = false; $usetemplate = false; // Pull up the curricula assignment record(s) // $curcourse = curriculumcourse_get_list_by_curr($this->curid); $sql = 'SELECT ccc.*, cc.idnumber, cc.name ' . 'FROM {' . curriculumcourse::TABLE . '} ccc ' . 'INNER JOIN {' . course::TABLE . '} cc ON cc.id = ccc.courseid ' . 'WHERE ccc.curriculumid = ? '; $params = array($this->curid); $curcourse = $this->_db->get_recordset_sql($sql, $params); $classparams = array(); // ELIS-6854: TBD - should new classes use track's start/end dates? if (!empty($this->startdate)) { $classparams['startdate'] = $this->startdate; } if (!empty($this->enddate)) { $classparams['enddate'] = $this->enddate; } // For every course of the curricula determine which ones need - // to have their auto enrol flag set foreach ($curcourse as $recid => $curcourec) { //get a unique idnumber $idnumber = $this->idnumber; if (!empty($curcourec->idnumber)) { $idnumber = append_once($idnumber, $curcourec->idnumber . '-', array('prepend' => true, 'maxlength' => 95, 'strict' => true)); } generate_unique_identifier(pmclass::TABLE, 'idnumber', $idnumber, array('idnumber' => $idnumber), 'pmclass', $classojb, array('courseid' => $curcourec->courseid, 'idnumber' => $idnumber)); // Course is required if ($curcourec->required) { $autoenrol = true; } //attempte to obtain the course template $cortemplate = coursetemplate::find(new field_filter('courseid', $curcourec->courseid)); if ($cortemplate->valid()) { $cortemplate = $cortemplate->current(); } // Course is using a Moodle template if (!empty($cortemplate->location)) { // Parse the course id from the template location $classname = $cortemplate->templateclass; $templateobj = new $classname(); $templatecorid = $cortemplate->location; $usetemplate = true; } // Create class $classparams['courseid'] = $curcourec->courseid; if (!($classid = $classojb->auto_create_class($classparams))) { cm_error(get_string('error_creating_class', 'local_elisprogram', $curcourec->name)); continue; } // attach course to moodle template if ($usetemplate) { moodle_attach_class($classid, 0, '', false, false, true); } $trackclassobj = new trackassignment(array('courseid' => $curcourec->courseid, 'trackid' => $this->id, 'classid' => $classojb->id)); // Set auto-enrol flag if ($autoenrol) { $trackclassobj->autoenrol = 1; } // Assign class to track $trackclassobj->save(); // Create and assign class to default system track // TODO: for now, use elis::$config->local_elisprogram in place of $CURMAN->config if (!empty(elis::$config->local_elisprogram->userdefinedtrack)) { $trkid = $this->create_default_track(); $trackclassobj = new trackassignment(array('courseid' => $curcourec->courseid, 'trackid' => $trkid, 'classid' => $classojb->id)); // Set auto-enrol flag if ($autoenrol) { $trackclassobj->autoenrol = 1; } // Assign class to default system track $trackclassobj->save(); } $usetemplate = false; $autoenrol = false; } unset($curcourse); }
/** * Test validation that moodle_attach_class will attach a Moodle course if autocreate is true */ public function test_autocreatemoodlecourse_attachesmoodlecourse() { global $DB; $clsid = 1; $mdlid = 2; $autocreate = true; $result = moodle_attach_class($clsid, $mdlid, '', false, false, $autocreate); // Make sure that moodle_attach_class returns true. $this->assertTrue($result); $recordexists = $DB->record_exists('local_elisprogram_cls_mdl', array('classid' => $clsid)); // We want to validate that a link to the new moodle course was created. $this->assertTrue($recordexists); // Get the new course id. $record = $DB->get_record('local_elisprogram_cls_mdl', array('classid' => $clsid)); $courseexists = $DB->record_exists('course', array('id' => $record->moodlecourseid)); // We want to validate that new moodle course was created. $this->assertTrue($recordexists); ini_set('max_execution_time', '0'); }
/** * Creates and assoicates a class with a track for every course that * belongs to the track curriculum * * TODO: return some data */ function track_auto_create() { global $CURMAN; if (empty($this->curid) or empty($this->id)) { cm_error('trackid and curid have not been properly initialized'); return false; } $autoenrol = false; $usetemplate = false; // Pull up the curricula assignment record(s) // $curcourse = curriculumcourse_get_list_by_curr($this->curid); $sql = "SELECT ccc.*, cc.idnumber " . "FROM " . $CURMAN->db->prefix_table(CURCRSTABLE) . " ccc " . "INNER JOIN " . $CURMAN->db->prefix_table(CRSTABLE) . " cc ON cc.id = ccc.courseid " . "WHERE ccc.curriculumid = {$this->curid}"; $curcourse = $CURMAN->db->get_records_sql($sql); if (empty($curcourse)) { $curcourse = array(); } // For every course of the curricula determine which ones need - // to have their auto enrol flag set foreach ($curcourse as $recid => $curcourec) { $idnumfmt = (!empty($curcourec->idnumber) ? $curcourec->idnumber . '-' : '') . $this->idnumber; $idnumber = $idnumfmt; $suffix = 1; while ($CURMAN->db->record_exists(CLSTABLE, 'idnumber', $idnumber)) { $idnumber = $idnumfmt . '.' . $suffix++; } $classojb = new cmclass(array('courseid' => $curcourec->courseid, 'idnumber' => $idnumber)); // Course is required if ($curcourec->required) { $autoenrol = true; } $cortemplate = new coursetemplate($curcourec->courseid); // Course is using a Moodle template if (!empty($cortemplate->location)) { // Parse the course id from the template location $classname = $cortemplate->templateclass; $templateobj = new $classname(); $templatecorid = $cortemplate->location; $usetemplate = true; } // Create class if (!($classid = $classojb->auto_create_class(array('courseid' => $curcourec->courseid)))) { cm_error('Could not create class'); return false; } // attach course to moodle template if ($usetemplate) { moodle_attach_class($classid, 0, '', false, false, true); } $trackclassobj = new trackassignmentclass(array('courseid' => $curcourec->courseid, 'trackid' => $this->id, 'classid' => $classojb->id)); // Set auto-enrol flag if ($autoenrol) { $trackclassobj->autoenrol = 1; } // Assign class to track $trackclassobj->data_insert_record(); // Create and assign class to default system track if (!empty($CURMAN->config->userdefinedtrack)) { $trkid = $this->create_default_track(); $trackclassobj = new trackassignmentclass(array('courseid' => $curcourec->courseid, 'trackid' => $trkid, 'classid' => $classojb->id)); // Set auto-enrol flag if ($autoenrol) { $trackclassobj->autoenrol = 1; } // Assign class to default system track $trackclassobj->data_insert_record(); } $usetemplate = false; $autoenrol = false; } }
/** * Validate that a Moodle user with duplicate username does not produce an error when enrolling an ELIS user to a class. */ public function test_elisuserstudentenrolmenthandlesduplicatemoodleuser() { global $CFG, $DB; require_once $CFG->dirroot . '/local/elisprogram/lib/setup.php'; require_once elispm::lib('data/course.class.php'); require_once elispm::lib('data/pmclass.class.php'); require_once elispm::lib('data/user.class.php'); // Create an ELIS course. $course = new course(array('name' => 'testcoursename', 'idnumber' => 'testcourseidnumber', 'syllabus' => '')); $course->save(); // Create an ELIS class. $class = new pmclass(array('courseid' => $course->id, 'idnumber' => 'testclassidnumber')); $class->save(); // Create a Moodle course. $mdlcoursedata = new stdClass(); $mdlcoursedata->shortname = "testcourse"; $mdlcoursedata->fullname = "Test Course"; $mdlcoursedata->category = 1; $mdlcourse = create_course($mdlcoursedata); // Associate ELIS class to Moodle course. $result = moodle_attach_class($class->id, $mdlcourse->id); $this->assertTrue($result); // Create an ELIS user. $user = new user(array('idnumber' => 'testidnumber', 'username' => 'testusername', 'firstname' => 'testfirstname', 'lastname' => 'testlasname', 'email' => '*****@*****.**', 'country' => 'CA')); $user->save(); // Change the idnumber of the associated Moodle user record. $DB->execute("UPDATE {user} SET idnumber = 'bogus' WHERE idnumber = 'testidnumber'"); // Remove the ELIS user to Moodle user association record. $DB->execute("DELETE FROM {" . usermoodle::TABLE . "} WHERE cuserid = " . $user->id); // Run the class enrolment create action. $record = new stdClass(); $record->action = 'enrol'; $record->context = 'class_testclassidnumber'; $record->user_username = $user->username; $record->user_email = $user->email; $record->user_idnumber = $user->idnumber; $importplugin = rlip_dataplugin_factory::factory('dhimport_version1elis'); $importplugin->fslogger = new silent_fslogger(null); $importplugin->process_record('enrolment', (object) $record, 'bogus'); // Validation. $this->assertTrue($DB->record_exists(student::TABLE, array('userid' => $user->id, 'classid' => $class->id))); }
/** * Associate a class instance to a Moodle course, if necessary, either by * auto-creating that Moodle course or by using a new one * * @param object $record The import record containing information about the track * @param int $classid The id of the class instance */ function associate_class_to_moodle_course($record, $classid) { global $CFG, $DB; require_once $CFG->dirroot . '/local/elisprogram/lib/setup.php'; require_once elispm::lib('data/classmoodlecourse.class.php'); if (isset($record->link)) { if ($record->link == 'auto') { moodle_attach_class($classid, 0, '', true, true, true); } else { $moodlecourseid = $DB->get_field('course', 'id', array('shortname' => $record->link)); moodle_attach_class($classid, $moodlecourseid, '', true, true, false); } } //TODO: return a status, add error handling }
/** * Performs class-specific actions as a part of the back-end approval process * * @param object $request the request record * @param object $formdata the submitted form data * @param int $courseid the id of the course that the applicable class * will belong to, if created * @uses $CFG * @uses $DB */ function approve_request_class_actions(&$request, $formdata, $courseid) { global $CFG, $DB; $config = get_config('block_courserequest'); // Create the new class if we are using an existing course, or if // create_class_with_course is on. if (!empty($request->courseid) || !empty($config->create_class_with_course)) { require_once $CFG->dirroot . '/local/elisprogram/lib/data/pmclass.class.php'; $clsdata = array('courseid' => $courseid, 'idnumber' => $formdata->clsidnumber, 'starttimehour' => 25, 'starttimeminute' => 61, 'endtimehour' => 25, 'endtimeminute' => 61); $newclass = new pmclass($clsdata); $newclass->autocreate = false; if (!empty($config->use_class_fields)) { // class fields are enabled, so add the relevant data $this->add_custom_fields($formdata, 'class', $newclass); } $newclass->save(); // ->add() // needed to update the request record with the created class $request->classidnumber = $newclass->idnumber; $request->classid = $newclass->id; // assign role to requester in the newly created class if (!empty($config->class_role)) { $context = \local_elisprogram\context\pmclass::instance($newclass->id); role_assign($config->class_role, $request->userid, $context->id, ECR_CI_ROLE_COMPONENT); } // create a new Moodle course from the CM course template if set on the approve form if (!empty($formdata->usecoursetemplate)) { moodle_attach_class($newclass->id, 0, '', true, true, true); // copy role over into Moodle course if (!empty($config->class_role)) { require_once $CFG->dirroot . '/local/elisprogram/lib/data/classmoodlecourse.class.php'; if ($class_moodle_record = $DB->get_record(classmoodlecourse::TABLE, array('classid' => $newclass->id))) { $context = context_course::instance($class_moodle_record->moodlecourseid); role_assign($config->class_role, $request->userid, $context->id, ECR_MC_ROLE_COMPONENT); } } } } }
public function save() { $isnew = empty($this->id); parent::save(); if (isset($this->track) && is_array($this->track)) { $param['classid'] = $this->id; $param['courseid'] = $this->courseid; foreach ($this->track as $t) { if (trackassignment::exists(array(new field_filter('classid', $this->id), new field_filter('trackid', $t)))) { continue; } $param['trackid'] = $t; $trackassignobj = new trackassignment($param); $trackassignobj->save(); } } if (isset($this->unlink_attached_course) && isset($this->moodlecourseid)) { // process unlink moodle course id request $return = moodle_detach_class($this->id, $this->moodlecourseid); $this->moodlecourseid = 0; } if ($this->moodlecourseid || $this->autocreate) { moodle_attach_class($this->id, $this->moodlecourseid, '', true, true, $this->autocreate); } if (!$isnew) { if (!empty($this->oldmax) && (!$this->maxstudents || $this->oldmax < $this->maxstudents) && ($waiting = waitlist::count_records($this->id)) > 0) { $start = student_count_records($this->id); $max = $this->maxstudents ? $this->maxstudents : $start + $waiting + 1; //error_log("pmclass.class.php::save() oldmax = {$this->oldmax}, start = {$start}, newmax = {$this->maxstudents}, waiting = {$waiting} ... max = {$max}"); for ($i = $start; $i < $max; $i++) { $next_student = waitlist::get_next($this->id); if (empty($next_student)) { break; } $next_student->enrol(); } } } field_data::set_for_context_from_datarecord(CONTEXT_ELIS_CLASS, $this); }
function display_create() { // action_create() global $CFG, $DB; $target = $this->get_new_page(array('action' => 'create'), true); $form = new create_form($target->url); $data = $form->get_data(); if ($form->is_cancelled()) { redirect($this->url); // TBV return; } else { if ($data) { global $USER; require_once $CFG->dirroot . '/local/elisprogram/lib/data/course.class.php'; $request = new stdClass(); $request->userid = $USER->id; $request->firstname = $data->first; $request->lastname = $data->last; $request->email = $data->email; if (empty($data->title)) { $course_record = $DB->get_record(course::TABLE, array('id' => $data->courseid)); $data->title = $course_record->name; } $request->title = $data->title; $request->courseid = $data->courseid; $request->usecoursetemplate = empty($data->usecoursetemplate) ? 0 : 1; $request->requeststatus = 'pending'; $request->timemodified = $request->timecreated = time(); $id = $DB->insert_record('block_courserequest', $request); $fields = $DB->get_records('block_courserequest_fields'); $fields = $fields ? $fields : array(); foreach ($fields as $reqfield) { $field = new field($reqfield->fieldid); if (!$field->id || !isset($field->owners['manual'])) { // skip nonexistent fields, or fields without manual editing continue; } $fielddata = new stdClass(); $fielddata->requestid = $id; $fielddata->fieldid = $reqfield->fieldid; // key that represents the appropriate attribute on the object $field_key = "field_{$field->shortname}"; // make sure the field was enabled, especially for preventing the // storage of course fields when using an existing course if (isset($data->{$field_key})) { // check for multiple fields if (is_array($data->{$field_key})) { $fielddata->data = serialize($data->{$field_key}); $fielddata->multiple = '1'; } else { $fielddata->data = $data->{$field_key}; } // remember the context level that the field corresponds to $fielddata->contextlevel = $reqfield->contextlevel; $DB->insert_record('block_courserequest_data', $fielddata); } } require_once $CFG->dirroot . '/local/elisprogram/lib/notifications.php'; $syscontext = context_system::instance(); $config = get_config('block_courserequest'); if (has_capability('block/courserequest:approve', $syscontext)) { // Since we want to automatically approve requests for people approval permission, let's go ahead and create the course/class $requestid = $id; if (!($request = $DB->get_record('block_courserequest', array('id' => $requestid)))) { $target = str_replace($CFG->wwwroot, '', $this->url); print_error('errorinvalidrequestid', 'block_courserequest', $target, $requestid); } $target = $this->get_new_page(array('action' => 'approveconfirm')); $approveform = new pending_request_approve_form($target->url, $request); $request->request = $request->id; $approveform->set_data($request); // We're not actually approving the request, redirect back to the approval table. if ($approveform->is_cancelled()) { redirect($this->url, '', 0); } // Do we have to create a brand new course? if (empty($request->courseid)) { $crsdata = array('name' => $request->title, 'idnumber' => $data->crsidnumber, 'syllabus' => ''); $newcourse = new course($crsdata); if (!empty($config->use_course_fields)) { // course fields are enabled, so add the relevant data $this->add_custom_fields($request->id, 'course', $newcourse); } $newcourse->save(); // ->add() // do the course role assignment, if applicable if (!empty($config->course_role)) { if ($context = \local_elisprogram\context\course::instance($newcourse->id)) { // TBD: role_assign() now throws exceptions! $result = role_assign($config->course_role, $request->userid, $context->id, ECR_CD_ROLE_COMPONENT); } } $courseid = $newcourse->id; } else { $courseid = $request->courseid; // TBV: addslashes() } // Create the new class if we are using an existing course, or if // create_class_with_course is on. if (!empty($request->courseid) || !empty($config->create_class_with_course)) { require_once $CFG->dirroot . '/local/elisprogram/lib/data/pmclass.class.php'; $clsdata = array('name' => $request->title, 'courseid' => $courseid, 'idnumber' => $data->clsidnumber, 'starttimehour' => 25, 'starttimeminute' => 61, 'endtimehour' => 25, 'endtimeminute' => 61); $newclass = new pmclass($clsdata); $newclass->autocreate = false; if (!empty($config->use_class_fields)) { // class fields are enabled, so add the relevant data $this->add_custom_fields($request->id, 'class', $newclass); } $newclass->save(); // ->add() } // Update the request record to mark it as being approved. $request->requeststatus = 'approved'; $request->statusnote = ''; $DB->update_record('block_courserequest', $request); // TBV: addslashes_object() // assign role to requester in the newly created class if (!empty($newclass->id)) { if (!empty($config->class_role)) { $context = \local_elisprogram\context\pmclass::instance($newclass->id); // TBD: role_assign() now throws exceptions! role_assign($config->class_role, $request->userid, $context->id, ECR_CI_ROLE_COMPONENT); } } // create a new Moodle course from the course template if applicable if (!empty($data->usecoursetemplate) && !empty($newclass->id)) { moodle_attach_class($newclass->id, 0, '', true, true, true); // copy role over into Moodle course if (!empty($config->class_role)) { require_once $CFG->dirroot . '/local/elisprogram/lib/data/classmoodlecourse.class.php'; if ($class_moodle_record = $DB->get_record(classmoodlecourse::TABLE, array('classid' => $newclass->id))) { $context = context_course::instance($class_moodle_record->moodlecourseid); // TBD: role_assign() now throws exceptions! role_assign($config->class_role, $request->userid, $context->id, ECR_MC_ROLE_COMPONENT); } } } // Send a notification to the requesting user that their course / class is ready. // set additional course / class information for use in the message if (isset($newclass->idnumber) && isset($newclass->id)) { $request->classidnumber = $newclass->idnumber; $request->classid = $newclass->id; } $request->newcourseid = $courseid; // calculate the actual message $notice = block_courserequest_get_approval_message($request); // send it to the requester notification::notify($notice, $DB->get_record('user', array('id' => $request->userid))); print_string('request_submitted_and_auto_approved', 'block_courserequest'); } else { // find users with approve capabilities in the system context $admin = get_users_by_capability($syscontext, 'block/courserequest:approve'); foreach ($admin as $userto) { notification::notify(get_string('new_request_notification', 'block_courserequest', $data), $userto); } print_string('request_submitted', 'block_courserequest'); } redirect($this->url); return; } } $form->display(); }