/** * Edit program - course associations. * @param array $elements An array of course information to edit. * @param bool $bulkaction Whether this is a bulk-action or not. * @return array An array to format as JSON and return to the Javascript. */ protected function _respond_to_js(array $elements, $bulkaction) { global $DB; $programid = required_param('id', PARAM_INT); $assocdata = required_param('assocdata', PARAM_CLEAN); $assocdata = $this->process_incoming_assoc_data($assocdata, $bulkaction); if (!is_array($assocdata)) { throw new Exception('Did not receive valid enrolment data.'); } if (!empty($assocdata)) { foreach ($elements as $courseid => $label) { if ($this->can_manage_assoc($programid, $courseid) === true) { $assoc = $DB->get_record(curriculumcourse::TABLE, array('curriculumid' => $programid, 'courseid' => $courseid)); if (!empty($assoc)) { $curriculumcourse = new curriculumcourse($assoc); $fields = array('required', 'frequency', 'timeperiod', 'position'); foreach ($fields as $field) { if (isset($assocdata[$field])) { $curriculumcourse->{$field} = $assocdata[$field]; } } $curriculumcourse->save(); } } } } $formatteddata = $this->format_assocdata_for_display($assocdata); return array('result' => 'success', 'msg' => 'Success', 'displaydata' => $formatteddata, 'saveddata' => $assocdata); }
/** * Validate that track-class associations can be created during a class instance * update action * * @param mixed $autoenrol The appropriate autoenrol value specified * @param int $dbautoenrol The value expected to be set in the db for autoenrol * @dataProvider autoenrol_provider */ public function test_associate_track_during_class_update($autoenrol, $dbautoenrol) { 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/curriculum.class.php'); require_once elispm::lib('data/curriculumcourse.class.php'); require_once elispm::lib('data/pmclass.class.php'); require_once elispm::lib('data/track.class.php'); // Create the course description. $course = new course(array('name' => 'testcoursename', 'idnumber' => 'testcourseidnumber', 'syllabus' => '')); $course->save(); // Create the class instance. $pmclass = new pmclass(array('courseid' => $course->id, 'idnumber' => 'testclassidnumber')); $pmclass->save(); // Create the curriculum / program. $curriculum = new curriculum(array('idnumber' => 'testcurriculumidnumber')); $curriculum->save(); // Associate the course description to the program. $curriculumcourse = new curriculumcourse(array('curriculumid' => $curriculum->id, 'courseid' => $course->id)); $curriculumcourse->save(); // Create the track. $track = new track(array('curid' => $curriculum->id, 'idnumber' => 'testtrackidnumber')); $track->save(); // Run the class instance update action. $record = new stdClass(); $record->assignment = 'testcourseidnumber'; $record->idnumber = 'testclassidnumber'; $record->track = 'testtrackidnumber'; if ($autoenrol !== null) { $record->autoenrol = $autoenrol; } $importplugin = rlip_dataplugin_factory::factory('dhimport_version1elis'); $importplugin->fslogger = new silent_fslogger(null); $importplugin->class_update($record, 'bogus'); // Validation. $classid = $DB->get_field(pmclass::TABLE, 'id', array('idnumber' => 'testclassidnumber')); $this->assertTrue($DB->record_exists(trackassignment::TABLE, array('trackid' => $track->id, 'classid' => $classid, 'autoenrol' => $dbautoenrol))); }
/** * Test available table only shows classes that the assigner has the local/elisprogram::associate permission on. * @dataProvider dataprovider_available_permissions_associate * @param array $contextstoassign An array of information specifying the contexts to assign the associate permission on. * This is formatted like array('system' => true, 'class' => array(1, 2, 3)) * @param int $tabletrackid The ID of the track we're going to manage. * @param array $expectedresults The expected page of results. * @param int $expectedtotal The expected number of total results. */ public function test_available_permissions_associate($contextstoassign, $tabletrackid, $expectedresults, $expectedtotal) { global $USER, $DB, $CFG; $userbackup = $USER; // Set up permissions. $USER = $this->setup_permissions_test(); // We're not interested in the class > course > program > track requirement for this test, so assign all courses to all // programs. foreach (array(5, 6, 7) as $programid) { foreach (array(100, 101, 102) as $courseid) { $association = new curriculumcourse(array('curriculumid' => $programid, 'courseid' => $courseid)); $association->save(); } } // Set up capabilities. foreach ($contextstoassign as $contexttype => $ids) { if ($contexttype === 'system') { $this->give_permission_for_context($USER->id, 'local/elisprogram:associate', context_system::instance()); } else { foreach ($ids as $contextinstanceid) { switch ($contexttype) { case 'class': $context = \local_elisprogram\context\pmclass::instance($contextinstanceid); break; } $this->give_permission_for_context($USER->id, 'local/elisprogram:associate', $context); } } } accesslib_clear_all_caches(true); // Construct test table. $table = new deepsight_datatable_trackclass_available_mock($DB, 'test', 'http://localhost', 'testuniqid'); $table->set_trackid($tabletrackid); // Perform test. $actualresults = $table->get_search_results(array(), array(), 0, 20); // Verify result. $this->assert_search_results($expectedresults, $expectedtotal, $actualresults); // Restore user. $USER = $userbackup; }
/** * Test available table doesn't show assigned courses. * @dataProvider dataprovider_available_doesnt_show_assigned_courses * @param array $associations An array of arrays of parameters to construct curriculumcourse associations. * @param int $tableprogramid The ID of the program we're going to manage. * @param array $expectedresults The expected page of results. * @param int $expectedtotal The expected number of total results. */ public function test_available_doesnt_show_assigned_courses($associations, $tableprogramid, $expectedresults, $expectedtotal) { global $USER, $DB, $CFG; $userbackup = $USER; // Set up permissions. $USER = $this->setup_permissions_test(); $this->give_permission_for_context($USER->id, 'local/elisprogram:associate', context_system::instance()); foreach ($associations as $association) { $curriculumcourse = new curriculumcourse($association); $curriculumcourse->save(); } // Construct test table. $table = new deepsight_datatable_programcourse_available_mock($DB, 'test', 'http://localhost', 'testuniqid'); $table->set_programid($tableprogramid); // Perform test. $actualresults = $table->get_search_results(array(), array(), 0, 20); // Verify result. $this->assert_search_results($expectedresults, $expectedtotal, $actualresults); // Restore user. $USER = $userbackup; }
/** * Test validation of duplicates * @expectedException data_object_validation_exception */ public function test_curriculumcourse_validationpreventsduplicates() { $this->load_csv_data(); $curriculumcourse = new curriculumcourse(array('curriculumid' => 1, 'courseid' => 1)); $curriculumcourse->save(); }
/** * Validate that mappings are applied during the track create action */ public function test_mapping_applied_during_track_create() { global $CFG, $DB; require_once $CFG->dirroot . '/local/eliscore/lib/data/customfield.class.php'; require_once $CFG->dirroot . '/local/elisprogram/accesslib.php'; require_once $CFG->dirroot . '/local/elisprogram/lib/data/course.class.php'; require_once $CFG->dirroot . '/local/elisprogram/lib/data/curriculum.class.php'; require_once $CFG->dirroot . '/local/elisprogram/lib/data/curriculumcourse.class.php'; require_once $CFG->dirroot . '/local/elisprogram/lib/data/pmclass.class.php'; require_once $CFG->dirroot . '/local/elisprogram/lib/data/track.class.php'; $this->init_mapping(); $customfieldid = $this->create_custom_field(CONTEXT_ELIS_TRACK); $course = new course(array('name' => 'testcoursename', 'idnumber' => 'testcourseidnumber', 'syllabus' => '')); $course->save(); $program = new curriculum(array('idnumber' => 'testprogramidnumber')); $program->save(); $curriculumcourse = new curriculumcourse(array('curriculumid' => $program->id, 'courseid' => $course->id)); $curriculumcourse->save(); // Run the track create action. $record = new stdClass(); $record->customaction = 'create'; $record->customcontext = 'track'; $record->customidnumber = 'testtrackidnumber'; $record->customname = 'testtrackname'; $record->customdescription = 'testtrackdescription'; $record->customstartdate = 'Jan/01/2012'; $record->customenddate = 'Jan/01/2012'; $record->customautocreate = 1; $record->customassignment = 'testprogramidnumber'; $record->customtestfieldshortname = '1'; $this->run_pmentity_import((array) $record); // Validation. $data = array('idnumber' => 'testtrackidnumber', 'name' => 'testtrackname', 'startdate' => rlip_timestamp(0, 0, 0, 1, 1, 2012), 'enddate' => rlip_timestamp(0, 0, 0, 1, 1, 2012)); $this->assertTrue($DB->record_exists(track::TABLE, $data)); $record = $DB->get_record(track::TABLE, array('idnumber' => 'testtrackidnumber')); $this->assertEquals('testtrackdescription', $record->description); $this->assertEquals(1, $DB->count_records(pmclass::TABLE)); $instance = \local_elisprogram\context\track::instance(1); $this->assertTrue($DB->record_exists(field_data_int::TABLE, array('fieldid' => $customfieldid, 'contextid' => $instance->id, 'data' => 1))); }
/** * Add a new corequisite for a course. * * @param int $cid The course ID to add as a corequisite. * @param bool True on success, False otherwise. */ function add_corequisite($cid, $add_to_curriculum = false) { if (empty($this->id)) { return false; } if ($this->is_prerequisite($cid) || $this->is_corequisite($cid)) { return false; } $cp = new stdClass(); $cp->curriculumcourseid = $this->id; $cp->courseid = $cid; $cp->id = $this->_db->insert_record(coursecorequisite::TABLE, $cp); $result = !empty($cp->id); if ($result && $add_to_curriculum) { $data = new object(); $data->curriculumid = $this->curriculumid; $data->courseid = $cid; $data->timeperiod = 'year'; $currprereq = new curriculumcourse($data); if (!$currprereq->is_recorded()) { $currprereq->save(); } } return $result; }
/** * Add a course to a curricula * * @param array $curriculums array value is the curriculum id * @return nothing * TODO: need to add some error checking */ function add_course_to_curricula($curriculums = array()) { $curcourse = new curriculumcourse(); // Add course to curricula (one or more) $curcrsrecord = array(); $curcrsrecord['id'] = 0; $curcrsrecord['courseid'] = $this->id; $curcrsrecord['required'] = 0; $curcrsrecord['frequency'] = 0; $curcrsrecord['timeperiod'] = key($curcourse->timeperiod_values); $curcrsrecord['position'] = 0; if (is_array($curriculums)) { foreach ($curriculums as $curr) { $curcrsrecord['curriculumid'] = $curr; $newcurcrs = new curriculumcourse($curcrsrecord); $status = $newcurcrs->save(); if ($status !== true) { if (!empty($status->message)) { //$output .= cm_error('Record not created. Reason: '.$status->message); } else { //echo cm_error('Record not created.'); } } else { //echo 'New record created.'; } } } }
/** * Update a course * @todo: consider factoring this some more once other actions exist * * @param object $record One record of import data * @param string $filename The import file name, used for logging * @return boolean true on success, otherwise false */ function course_update($record, $filename) { global $CFG, $DB; require_once $CFG->dirroot . '/local/elisprogram/lib/data/course.class.php'; $message = ""; //field length checking $lengthcheck = $this->check_course_field_lengths($record, $filename); if (!$lengthcheck) { return false; } if (isset($record->idnumber)) { if (!($crsid = $DB->get_field(course::TABLE, 'id', array('idnumber' => $record->idnumber)))) { $identifier = $this->get_field_mapping('idnumber'); $this->fslogger->log_failure("{$identifier} value of \"{$record->idnumber}\" does not refer to a valid course description.", 0, $filename, $this->linenumber, $record, "course"); return false; } } $currid = 0; if (isset($record->assignment)) { if (!($currid = $DB->get_field(curriculum::TABLE, 'id', array('idnumber' => $record->assignment)))) { $identifier = $this->get_field_mapping('assignment'); $this->fslogger->log_failure("{$identifier} value of \"{$record->assignment}\" does not refer to a valid program.", 0, $filename, $this->linenumber, $record, "course"); return false; } else { if ($DB->record_exists(curriculumcourse::TABLE, array('curriculumid' => $currid, 'courseid' => $crsid))) { $identifier = $this->get_field_mapping('idnumber'); $message = "Course description with {$identifier} \"{$record->idnumber}\" already assigned to program with idnumber \"{$record->assignment}\"."; } } } if (!$this->validate_course_data('update', $record, $filename)) { return false; } $record = $this->add_custom_field_prefixes($record); //custom field validation if (!$this->validate_custom_field_data('update', $record, $filename, 'course')) { return false; } $record = $this->initialize_course_fields($record); $record->id = $crsid; $course = new course(); $course->set_from_data($record); $course->save(); if ($currid != 0) { $currcrs = new curriculumcourse(); $assoc = new stdClass(); $assoc->curriculumid = $currid; $assoc->courseid = $course->id; $currcrs->set_from_data($assoc); $currcrs->save(); } //associate this course description to a Moodle course, if necessary $this->associate_course_to_moodle_course($record, $course->id); //log success $success_message = "Course description with idnumber \"{$record->idnumber}\" successfully updated."; $this->fslogger->log_success($success_message, 0, $filename, $this->linenumber); return true; }
/** * Validate that enrolling a user into a user set via IP auto-enrolls them in * an associated track, and any associated programs or class instances */ public function test_userset_enrolment_creates_track_enrolment() { global $CFG, $DB; require_once $CFG->dirroot . '/local/elisprogram/lib/setup.php'; require_once elispm::lib('data/clustertrack.class.php'); require_once elispm::lib('data/course.class.php'); require_once elispm::lib('data/curriculum.class.php'); require_once elispm::lib('data/curriculumcourse.class.php'); require_once elispm::lib('data/curriculumstudent.class.php'); require_once elispm::lib('data/pmclass.class.php'); require_once elispm::lib('data/student.class.php'); require_once elispm::lib('data/track.class.php'); require_once elispm::lib('data/user.class.php'); require_once elispm::lib('data/userset.class.php'); require_once elispm::lib('data/usertrack.class.php'); // Make sure no emails are sent. set_config('noemailever', true); // Set up data. // Test user. $user = new user(array('idnumber' => 'testuseridnumber', 'username' => 'testuserusername', 'firstname' => 'testuserfirstname', 'firstname' => 'testuserfirstname', 'lastname' => 'testuserlastname', 'email' => '*****@*****.**', 'country' => 'CA')); $user->save(); // Test user set. $userset = new userset(array('name' => 'testusersetname')); $userset->save(); // Test program and track. $program = new curriculum(array('idnumber' => 'testprogramidnumber')); $program->save(); $track = new track(array('curid' => $program->id, 'idnumber' => 'testtrackidnumber')); $track->save(); // Associate the userset to the track. $clustertrack = new clustertrack(array('clusterid' => $userset->id, 'trackid' => $track->id, 'autoenrol' => 1)); $clustertrack->save(); // Test course and class. $course = new course(array('name' => 'testcoursename', 'idnumber' => 'testcourseidnumber', 'syllabus' => '')); $course->save(); $class = new pmclass(array('courseid' => $course->id, 'idnumber' => 'testclass1idnumber')); $class->save(); // Associate course to the program. $curriculumcourse = new curriculumcourse(array('curriculumid' => $program->id, 'courseid' => $course->id)); $curriculumcourse->save(); // Associate track to the test class. $trackassignment = new trackassignment(array('trackid' => $track->id, 'classid' => $class->id, 'autoenrol' => 1)); $trackassignment->save(); // Run the assignment create action. $record = new stdClass(); $record->context = 'userset_testusersetname'; $record->user_username = '******'; $importplugin = rlip_dataplugin_factory::factory('dhimport_version1elis'); $importplugin->fslogger = new silent_fslogger(null); $importplugin->cluster_enrolment_create($record, 'bogus', 'testusersetname'); // Validation. // Userset assignment should trigger track assignment. $this->assertTrue($DB->record_exists(usertrack::TABLE, array('userid' => $user->id, 'trackid' => $track->id))); // Track assignment should trigger program assignment. $this->assertTrue($DB->record_exists(curriculumstudent::TABLE, array('userid' => $user->id, 'curriculumid' => $program->id))); // Track assignment should create a class enrolment. $this->assertTrue($DB->record_exists(student::TABLE, array('userid' => $user->id, 'classid' => $class->id))); }
/** * Clone a curriculum. * @param array $options options for cloning. Valid options are: * - 'tracks': whether or not to clone tracks (default: false) * - 'courses': whether or not to clone courses (default: false) * - 'classes': whether or not to clone classes (default: false) * - '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 * - 'targetcluster': the cluster id or cluster object (if any) to * associate the clones with (default: none) * @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(array $options = array()) { require_once elispm::lib('data/track.class.php'); $objs = array('errors' => array()); if (isset($options['targetcluster'])) { $userset = $options['targetcluster']; if (!is_object($userset) || !is_a($userset, 'userset')) { $options['targetcluster'] = $userset = new userset($userset); } } // Due to lazy loading, we need to pre-load this object $this->load(); // clone main curriculum object $clone = new curriculum($this); unset($clone->id); $idnumber = $clone->idnumber; $name = $clone->name; if (isset($userset)) { $to_append = ' - ' . $userset->name; // if cluster specified, append cluster's name to curriculum $idnumber = append_once($idnumber, $to_append, array('maxlength' => 95)); $name = append_once($name, $to_append, array('maxlength' => 59)); } //get a unique idnumber $clone->idnumber = generate_unique_identifier(curriculum::TABLE, 'idnumber', $idnumber, array('idnumber' => $idnumber)); if ($clone->idnumber != $idnumber) { //get the suffix appended and add it to the name $parts = explode('.', $clone->idnumber); $suffix = end($parts); $clone->name = $name . '.' . $suffix; } else { $clone->name = $name; } $clone = new curriculum($clone); $clone->save(); $objs['curricula'] = array($this->id => $clone->id); $options['targetcurriculum'] = $clone->id; // associate with target cluster (if any) if (isset($userset)) { clustercurriculum::associate($userset->id, $clone->id); } if (!empty($options['courses'])) { // copy courses $currcrs = curriculumcourse_get_list_by_curr($this->id); if ($currcrs->valid()) { $objs['courses'] = array(); $objs['classes'] = array(); foreach ($currcrs as $currcrsdata) { $course = new course($currcrsdata->courseid); $rv = $course->duplicate($options); if (isset($rv['errors']) && !empty($rv['errors'])) { $objs['errors'] = array_merge($objs['errors'], $rv['errors']); } if (isset($rv['courses'])) { $objs['courses'] = $objs['courses'] + $rv['courses']; } if (isset($rv['classes'])) { $objs['classes'] = $objs['classes'] + $rv['classes']; } // associate with curriculum if (isset($rv['courses'][$course->id])) { $curcrs = new curriculumcourse($currcrsdata); unset($curcrs->id); $curcrs->courseid = $rv['courses'][$course->id]; $curcrs->curriculumid = $clone->id; $curcrs->save(); } } } unset($currcrs); } if (!empty($objs['errors'])) { return $objs; } if (!empty($options['tracks'])) { // copy tracks $tracks = track_get_listing('name', 'ASC', 0, 0, '', '', $this->id); if (isset($objs['courses'])) { $options['coursemap'] = $objs['courses']; } if (!empty($tracks)) { $objs['tracks'] = array(); if (isset($objs['courses'])) { $options['coursemap'] = $objs['courses']; } if (!isset($objs['classes'])) { $objs['classes'] = array(); } foreach ($tracks as $track) { $track = new track($track); $options['classmap'] = $objs['classes']; $rv = $track->duplicate($options); if (isset($rv['errors']) && !empty($rv['errors'])) { $objs['errors'] = array_merge($objs['errors'], $rv['errors']); } if (isset($rv['tracks'])) { $objs['tracks'] = $objs['tracks'] + $rv['tracks']; } if (isset($rv['classes'])) { $objs['classes'] = $objs['classes'] + $rv['classes']; } } } } return $objs; }