public function execute() { global $CFG, $DB; require_once $CFG->dirroot . '/course/lib.php'; $moduleid = intval($this->arguments[0]); if ($moduleid <= 0) { cli_error("Argument 'moduleid' must be bigger than 0."); } if (!$DB->get_record('course_modules', array('id' => $this->arguments[0]))) { cli_error("There is no such activity to delete."); } course_delete_module($moduleid); echo "Deleted activity {$moduleid}\n"; }
/** * Resets (truncates) all dataform tables to remove any records and reset sequences. * This set of steps is essential for any standalone scenario that adds entries with content * since such a scenario has to refer to input elements by the name field_{fieldid}_{entryid} * (or field_{fieldid}_-1 for a new entry) and the ids have to persist between runs. * * @Given /^a fresh site for dataform scenario$/ * @return array */ public function start_afresh_steps() { global $DB; // Dataform module id. $moduleid = $DB->get_field('modules', 'id', array('name' => 'dataform')); // CM ids. if ($cmids = $DB->get_records('course_modules', array('module' => $moduleid), '', 'id,id AS cmid')) { // Delete properly any existing dataform instances. foreach ($cmids as $cmid) { course_delete_module($cmid); } } // Clean up tables. $tables = array('dataform', 'dataform_contents', 'dataform_entries', 'dataform_fields', 'dataform_filters', 'dataform_views'); $prefix = $DB->get_prefix(); foreach ($tables as $table) { $DB->execute("TRUNCATE TABLE {$prefix}{$table}"); } // Clean up instance store cache. \mod_dataform_instance_store::unregister(); $steps = array(); // Add a course. $data = array('| fullname | shortname | category |', '| Course 1 | C1 | 0 |'); $table = new TableNode(implode("\n", $data)); $steps[] = new Given('the following "courses" exist:', $table); // Add users. $data = array('| username | firstname | lastname | email |', '| teacher1 | Teacher | 1 | teacher1@asd.com |', '| assistant1 | Assistant | 1 | assistant1@asd.com |', '| assistant2 | Assistant | 2 | assistant2@asd.com |', '| student1 | Student | 1 | student1@asd.com |', '| student2 | Student | 2 | student2@asd.com |', '| student3 | Student | 3 | student3@asd.com |'); $table = new TableNode(implode("\n", $data)); $steps[] = new Given('the following "users" exist:', $table); // Enrol users in course. $teacherrole = \mod_dataform\helper\testing::get_role_shortname('editingteacher'); $assistantrole = \mod_dataform\helper\testing::get_role_shortname('teacher'); $studentrole = \mod_dataform\helper\testing::get_role_shortname('student'); $data = array('| user | course | role |', "| teacher1 | C1 | {$teacherrole} |", "| assistant1 | C1 | {$assistantrole} |", "| assistant2 | C1 | {$assistantrole} |", "| student1 | C1 | {$studentrole} |", "| student2 | C1 | {$studentrole} |"); $table = new TableNode(implode("\n", $data)); $steps[] = new Given('the following "course enrolments" exist:', $table); // Add groups. $data = array('| name | description | course | idnumber |', '| Group 1 | Anything | C1 | G1 |', '| Group 2 | Anything | C1 | G2 |'); $table = new TableNode(implode("\n", $data)); $steps[] = new Given('the following "groups" exist:', $table); // Add group members. $data = array('| user | group |', '| student1 | G1 |', '| student2 | G2 |'); $table = new TableNode(implode("\n", $data)); $steps[] = new Given('the following "group members" exist:', $table); return $steps; }
/** * Run the deletion task. * * @throws \coding_exception if the module could not be removed. */ public function execute() { global $CFG; require_once $CFG->dirroot . '/course/lib.php'; // Set the proper user. if ($this->get_custom_data()->userid !== $this->get_custom_data()->realuserid) { $realuser = \core_user::get_user($this->get_custom_data()->realuserid, '*', MUST_EXIST); cron_setup_user($realuser); \core\session\manager::loginas($this->get_custom_data()->userid, \context_system::instance(), false); } else { $user = \core_user::get_user($this->get_custom_data()->userid, '*', MUST_EXIST); cron_setup_user($user); } $cms = $this->get_custom_data()->cms; foreach ($cms as $cm) { try { course_delete_module($cm->id); } catch (\Exception $e) { throw new \coding_exception("The course module {$cm->id} could not be deleted. {$e->getTraceAsString()}"); } } }
/** * Tests the event details. */ public function test_event() { global $CFG; require_once "{$CFG->libdir}/gradelib.php"; $this->resetAfterTest(); $course = $this->getDataGenerator()->create_course(); $user = $this->getDataGenerator()->create_user(); $quiz = $this->getDataGenerator()->create_module('quiz', array('course' => $course->id)); // Create a grade item for the quiz. $grade = array(); $grade['userid'] = $user->id; $grade['rawgrade'] = 50; grade_update('mod/quiz', $course->id, 'mod', 'quiz', $quiz->id, 0, $grade); // Get the grade item and override it. $gradeitem = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'quiz', 'iteminstance' => $quiz->id, 'courseid' => $course->id)); $gradeitem->update_final_grade($user->id, 10, 'gradebook'); // Get the grade_grade object. $gradegrade = new grade_grade(array('userid' => $user->id, 'itemid' => $gradeitem->id), true); $gradegrade->grade_item = $gradeitem; // Trigger the event. $sink = $this->redirectEvents(); course_delete_module($quiz->cmid); $events = $sink->get_events(); $event = reset($events); $sink->close(); // Check the event details are correct. $grade = $event->get_grade(); $this->assertInstanceOf('grade_grade', $grade); $this->assertInstanceOf('\\core\\event\\grade_deleted', $event); $this->assertEquals(context_course::instance($course->id), $event->get_context()); $this->assertSame($event->objecttable, 'grade_grades'); $this->assertEquals($event->objectid, $gradegrade->id); $this->assertEquals($event->other['itemid'], $gradeitem->id); $this->assertTrue($event->other['overridden']); $this->assertEquals(10, $event->other['finalgrade']); $this->assertEventContextNotUsed($event); $this->assertEquals($gradegrade->id, $grade->id); }
// Attempt to update the grade item if relevant $grademodule = $DB->get_record($cm->modname, array('id' => $cm->instance)); $grademodule->cmidnumber = $cm->idnumber; $grademodule->modname = $cm->modname; grade_update_mod_grades($grademodule); // We need to return strings after they've been through filters for multilang $stringoptions = new stdClass(); $stringoptions->context = $coursecontext; echo json_encode(array('instancename' => html_entity_decode(format_string($module->name, true, $stringoptions)))); break; } break; case 'course': switch ($field) { case 'marker': require_capability('moodle/course:setcurrentsection', $coursecontext); course_set_marker($course->id, $value); break; } break; } break; case 'DELETE': switch ($class) { case 'resource': require_capability('moodle/course:manageactivities', $modcontext); course_delete_module($cm->id); break; } break; }
/** * Completely removes a section, all subsections and activities they contain * * @param section_info $section */ protected function delete_section_int($section) { global $DB; if (!$section->section) { // section 0 does not have parent return; } $sectionid = $section->id; // move the section to be removed to the end (this will re-number other sections) $this->move_section($section->section, 0); $modinfo = get_fast_modinfo($this->courseid); $allsections = $modinfo->get_section_info_all(); $section = null; $sectionstodelete = array(); $modulestodelete = array(); foreach ($allsections as $sectioninfo) { if ($sectioninfo->id == $sectionid) { // This is the section to be deleted. Since we have already // moved it to the end we know that we need to delete this section // and all the following (which can only be its subsections). $section = $sectioninfo; } if ($section) { $sectionstodelete[] = $sectioninfo->id; if (!empty($modinfo->sections[$sectioninfo->section])) { $modulestodelete = array_merge($modulestodelete, $modinfo->sections[$sectioninfo->section]); } } } foreach ($modulestodelete as $cmid) { course_delete_module($cmid); } list($sectionsql, $params) = $DB->get_in_or_equal($sectionstodelete); $DB->execute('DELETE FROM {course_format_options} WHERE sectionid ' . $sectionsql, $params); $DB->execute('DELETE FROM {course_sections} WHERE id ' . $sectionsql, $params); rebuild_course_cache($this->courseid, true); }
} if ($beforeid > 0) { $beforemod = get_coursemodule_from_id('', $beforeid, $course->id); $beforemod = $DB->get_record('course_modules', array('id' => $beforeid)); } else { $beforemod = NULL; } $isvisible = moveto_module($cm, $section, $beforemod); echo json_encode(array('visible' => (bool) $isvisible)); break; } break; case 'course': switch ($field) { case 'marker': require_capability('moodle/course:setcurrentsection', $coursecontext); course_set_marker($course->id, $value); break; } break; } break; case 'DELETE': switch ($class) { case 'resource': require_capability('moodle/course:manageactivities', $modcontext); course_delete_module($cm->id, true); break; } break; }
public function test_upgrade_offline_assignment() { global $DB; $this->setUser($this->editingteachers[0]); $generator = $this->getDataGenerator()->get_plugin_generator('mod_assignment'); $params = array('course'=>$this->course->id, 'assignmenttype'=>'offline'); $record = $generator->create_instance($params); $assignment = new assignment_base($record->cmid); $this->setAdminUser(); $log = ''; $upgrader = new assign_upgrade_manager(); $this->assertTrue($upgrader->upgrade_assignment($assignment->assignment->id, $log)); $record = $DB->get_record('assign', array('course'=>$this->course->id)); $cm = get_coursemodule_from_instance('assign', $record->id); $context = context_module::instance($cm->id); $assign = new assign($context, $cm, $this->course); $plugin = $assign->get_submission_plugin_by_type('onlinetext'); $this->assertEmpty($plugin->is_enabled()); $plugin = $assign->get_submission_plugin_by_type('comments'); $this->assertEmpty($plugin->is_enabled()); $plugin = $assign->get_submission_plugin_by_type('file'); $this->assertEmpty($plugin->is_enabled()); $plugin = $assign->get_feedback_plugin_by_type('comments'); $this->assertNotEmpty($plugin->is_enabled()); $plugin = $assign->get_feedback_plugin_by_type('file'); $this->assertEmpty($plugin->is_enabled()); $plugin = $assign->get_feedback_plugin_by_type('offline'); $this->assertEmpty($plugin->is_enabled()); course_delete_module($cm->id); }
public static function delete_item($user, $itemid) { global $DB, $USER; $params = self::validate_parameters(self::delete_item_parameters(), array('user' => $user, 'itemid' => $itemid)); $item = $DB->get_record('equella', array('id' => $params['itemid']), '*', MUST_EXIST); self::check_modify_permissions($params['user'], $item->course); $cm = get_coursemodule_from_instance('equella', $item->id, $item->course, false, MUST_EXIST); $success = true; try { course_delete_module($cm->id); } catch (Exception $ex) { $success = false; throw $ex; } return array('success' => $success); }
/** * Called after the mod has set itself up, to finish off any course module settings * (set instance id, add to correct section, set visibility, etc.) and send the response * * @param int $instanceid id returned by the mod when it was created */ protected function finish_setup_course_module($instanceid) { global $DB, $USER; if (!$instanceid) { // Something has gone wrong - undo everything we can. course_delete_module($this->cm->id); throw new moodle_exception('errorcreatingactivity', 'moodle', '', $this->module->name); } // Note the section visibility $visible = get_fast_modinfo($this->course)->get_section_info($this->section)->visible; $DB->set_field('course_modules', 'instance', $instanceid, array('id' => $this->cm->id)); // Rebuild the course cache after update action rebuild_course_cache($this->course->id, true); $sectionid = course_add_cm_to_section($this->course, $this->cm->id, $this->section); set_coursemodule_visible($this->cm->id, $visible); if (!$visible) { $DB->set_field('course_modules', 'visibleold', 1, array('id' => $this->cm->id)); } // retrieve the final info about this module. $info = get_fast_modinfo($this->course); if (!isset($info->cms[$this->cm->id])) { // The course module has not been properly created in the course - undo everything. course_delete_module($this->cm->id); throw new moodle_exception('errorcreatingactivity', 'moodle', '', $this->module->name); } $mod = $info->get_cm($this->cm->id); // Trigger course module created event. $event = \core\event\course_module_created::create(array('courseid' => $this->course->id, 'context' => context_module::instance($mod->id), 'objectid' => $mod->id, 'other' => array('modulename' => $mod->modname, 'name' => $mod->name, 'instanceid' => $instanceid))); $event->trigger(); add_to_log($this->course->id, $mod->modname, "add", "view.php?id={$mod->id}", "{$instanceid}", $mod->id); $this->send_response($mod); }
function forumng_delete_instance($id) { global $DB; require_once dirname(__FILE__) . '/mod_forumng.php'; $cm = get_coursemodule_from_instance('forumng', $id); $forum = mod_forumng::get_from_id($id, mod_forumng::CLONE_DIRECT, true, $cm); $forum->delete_all_data(); if (mod_forumng::search_installed()) { $cm = $forum->get_course_module(); local_ousearch_document::delete_module_instance_data($cm); } if ($forum->is_shared()) { // Find all the clone instances. $clones = $forum->get_clone_details(); $transaction = $DB->start_delegated_transaction(); foreach ($clones as $clone) { try { course_delete_module($clone->context->instanceid); } catch (moodle_exception $e) { notify("Could not delete the Clone\n forumng (coursemoduleid) {$clone->context}->instanceid "); return false; } rebuild_course_cache($clone->courseid, true); } $transaction->allow_commit(); } return $DB->delete_records('forumng', array('id' => $id)); }
/** * function used to delete a module - copied from course/mod.php, it would * be nice for this to be a core function. * @param stdclass $cm full course modules record */ public function delete_module($cm) { global $CFG, $OUTPUT, $USER, $DB; $cm->modname = $DB->get_field("modules", "name", array("id" => $cm->module)); $modlib = "{$CFG->dirroot}/mod/{$cm->modname}/lib.php"; if (file_exists($modlib)) { require_once $modlib; } else { print_error('modulemissingcode', '', '', $modlib); } try { course_delete_module($cm->id); } catch (moodle_exception $e) { echo $OUTPUT->notification("Could not delete the {$cm->modname} (coursemodule)"); } rebuild_course_cache($cm->course); }
} $params = array("module" => "{$cm->module}", "refid" => "{$val}"); $sql = "SELECT * FROM {course_modules} WHERE module = :module AND instance=:refid "; $courses_modules = $DB->get_records_sql($sql, $params); if ($courses_modules) { foreach ($courses_modules as $course_module) { if (!empty($course_module)) { if ($course_record = $DB->get_record("course", array("id" => "{$course_module->course}"))) { require_login($course_module->course); // needed to setup proper $COURSE $context_course = context_course::instance($course_module->course); require_capability('moodle/course:manageactivities', $context_course); if ($that_instance = $DB->get_record("referentiel", array("id" => "{$course_module->instance}"))) { if (function_exists('course_delete_module')) { // Moodle v 2.5 et suivantes if (course_delete_module($course_module->id)) { if (delete_mod_from_section($course_module->id, "{$course_module->section}")) { rebuild_course_cache($course_record->id); $msg .= get_string('instance_deleted', 'referentiel') . ' ' . $that_instance->name; } } } else { // Moodle v 2.x if (delete_course_module($course_module->id)) { if (delete_mod_from_section($course_module->id, "{$course_module->section}")) { rebuild_course_cache($course_record->id); $msg .= get_string('instance_deleted', 'referentiel') . ' ' . $that_instance->name; } } } // Supprimer l'instance
/** * Test the course bin item restored event. */ public function test_course_bin_item_restored() { // Create a course. $course = $this->getDataGenerator()->create_course(); // Create the assignment. $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign'); $instance = $generator->create_instance(array('course' => $course->id)); course_delete_module($instance->cmid); // Get the item from the recycle bin. $rb = new \tool_recyclebin\course_bin($course->id); $items = $rb->get_items(); $item = reset($items); // Trigger and capture the event. $sink = $this->redirectEvents(); $rb->restore_item($item); $events = $sink->get_events(); $event = reset($events); // Check that the event contains the expected values. $this->assertInstanceOf('\\tooL_recyclebin\\event\\course_bin_item_restored', $event); $this->assertEquals(context_course::instance($course->id), $event->get_context()); $this->assertEquals($item->id, $event->objectid); $this->assertEventContextNotUsed($event); }
function pearsondirect_handle_code_change($courseconfig, $newcode, $newparams) { global $DB, $CFG; require_once $CFG->dirroot . '/mod/lti/locallib.php'; require_once $CFG->dirroot . '/course/lib.php'; $types = $DB->get_records('lti_types', array('course' => $courseconfig->course)); if ($types) { foreach ($types as $type) { if (!strncmp($type->tooldomain, 'pearson:', strlen('pearson:'))) { lti_delete_type($type->id); } } } $coursemodules = $DB->get_records('course_modules', array('course' => $courseconfig->course, 'module' => pearsondirect_get_lti_module())); if ($coursemodules) { foreach ($coursemodules as $cm) { if (!strncmp($cm->idnumber, 'pearson:', strlen('pearson:'))) { course_delete_module($cm->id); } } } }
/** * Test observer for course module delete event. */ public function test_course_module_deleted() { global $DB; $this->setAdminUser(); $this->resetAfterTest(true); $user = $this->getDataGenerator()->create_user(); $course1 = $this->getDataGenerator()->create_course(); $course2 = $this->getDataGenerator()->create_course(); $monitorgenerator = $this->getDataGenerator()->get_plugin_generator('tool_monitor'); // Now let us create a rule specific to a module instance. $cm = new stdClass(); $cm->course = $course1->id; $book = $this->getDataGenerator()->create_module('book', $cm); $rule = new stdClass(); $rule->userid = $user->id; $rule->courseid = $course1->id; $rule->plugin = 'test'; $sub = new stdClass(); $sub->courseid = $course1->id; $sub->userid = $user->id; $sub->cmid = $book->cmid; // Add 10 rules for this course with subscriptions for this module. for ($i = 0; $i < 10; $i++) { $createdrule = $monitorgenerator->create_rule($rule); $sub->ruleid = $createdrule->id; $monitorgenerator->create_subscription($sub); } // Add 10 random rules for course 2. $rule->courseid = $course2->id; for ($i = 0; $i < 10; $i++) { $createdrule = $monitorgenerator->create_rule($rule); $sub->courseid = $rule->courseid; $sub->ruleid = $createdrule->id; $sub->cmid = 0; $monitorgenerator->create_subscription($sub); } // Verify data before module delete. $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test'); $this->assertCount(20, $totalrules); $totalsubs = $DB->get_records('tool_monitor_subscriptions'); $this->assertCount(20, $totalsubs); // Let us delete the user now. course_delete_module($book->cmid); // Verify data after course delete. $totalrules = \tool_monitor\rule_manager::get_rules_by_plugin('test'); $this->assertCount(20, $totalrules); $totalsubs = $DB->get_records('tool_monitor_subscriptions'); $this->assertCount(10, $totalsubs); // Make sure only relevant subscriptions are deleted. }
/** * Delete activities, when course format setting "deletemodspermanently" is set * to yes and the activitie is not attached to another post. * * @param int $pid, the id of the post. * @return boolean, true when at least one acitivity is deleted. */ protected static function delete_posts_activities($pid) { global $DB, $CFG; require_once $CFG->dirroot . '/course/format/lib.php'; // Get the course and check, whether the format is "socialwall". $sql = "SELECT c.* FROM {course} c\n JOIN {format_socialwall_posts} p ON p.courseid = c.id\n WHERE p.id = :pid AND c.format = 'socialwall'"; if (!($course = $DB->get_record_sql($sql, array('pid' => $pid)))) { return false; } $course = course_get_format($course)->get_course(); if (empty($course->deletemodspermanently)) { return false; } $sql = "SELECT a.coursemoduleid, count(*) as countmod\n FROM {format_socialwall_attaches} a\n JOIN {format_socialwall_posts} p ON (p.id = a.postid AND p.courseid = :courseid)\n JOIN {format_socialwall_attaches} a2 ON (a2.coursemoduleid = a.coursemoduleid AND a2.postid = :pid)\n GROUP BY coursemoduleid\n HAVING countmod = '1'"; if (!($modcounts = $DB->get_records_sql($sql, array('courseid' => $course->id, 'pid' => $pid)))) { return false; } $cmids = array_keys($modcounts); foreach ($cmids as $cmid) { course_delete_module($cmid); } return true; }
/** * Given a course_module object, this function returns any * "extra" information that may be needed when printing * this activity in a course listing. * See get_array_of_activities() in course/lib.php */ function customlabel_get_coursemodule_info($coursemodule) { global $CFG, $DB, $COURSE; if ($customlabel = $DB->get_record('customlabel', array('id' => $coursemodule->instance), 'id, labelclass, intro, title, name, content, processedcontent')) { // Check label subtype is still installed if (!is_dir($CFG->dirroot . '/mod/customlabel/type/' . $customlabel->labelclass)) { course_delete_module($coursemodule->id); customlabel_delete_instance($customlabel->id); rebuild_course_cache($COURSE); return; } $instance = customlabel_load_class($customlabel, $customlabel->labelclass); $info = new stdClass(); $info->name = $customlabel->name; $info->extra = ''; // $customcontent = json_decode(base64_decode($customlabel->content)); $info->extra = urlencode($customlabel->title); return $info; } else { return null; } }
public function test_hook_course_module_deleted() { $this->resetAfterTest(); $dg = $this->getDataGenerator(); $ccg = $dg->get_plugin_generator('core_competency'); $u1 = $dg->create_user(); $framework = $ccg->create_framework(); $comp1 = $ccg->create_competency(['competencyframeworkid' => $framework->get_id()]); $comp2 = $ccg->create_competency(['competencyframeworkid' => $framework->get_id()]); $c1 = $dg->create_course(); $cc1a = $ccg->create_course_competency(['competencyid' => $comp1->get_id(), 'courseid' => $c1->id]); $cc1b = $ccg->create_course_competency(['competencyid' => $comp2->get_id(), 'courseid' => $c1->id]); $assign1a = $dg->create_module('assign', ['course' => $c1]); $assign1b = $dg->create_module('assign', ['course' => $c1]); $cmc1a = $ccg->create_course_module_competency(['competencyid' => $comp1->get_id(), 'cmid' => $assign1a->cmid]); $cmc1b = $ccg->create_course_module_competency(['competencyid' => $comp1->get_id(), 'cmid' => $assign1b->cmid]); $ucc1a = $ccg->create_user_competency_course(['competencyid' => $comp1->get_id(), 'courseid' => $c1->id, 'userid' => $u1->id]); $ucc1b = $ccg->create_user_competency_course(['competencyid' => $comp2->get_id(), 'courseid' => $c1->id, 'userid' => $u1->id]); $c2 = $dg->create_course(); $cc2a = $ccg->create_course_competency(['competencyid' => $comp1->get_id(), 'courseid' => $c2->id]); $cc2b = $ccg->create_course_competency(['competencyid' => $comp2->get_id(), 'courseid' => $c2->id]); $assign2a = $dg->create_module('assign', ['course' => $c2]); $assign2b = $dg->create_module('assign', ['course' => $c2]); $cmc2a = $ccg->create_course_module_competency(['competencyid' => $comp1->get_id(), 'cmid' => $assign2a->cmid]); $cmc2b = $ccg->create_course_module_competency(['competencyid' => $comp1->get_id(), 'cmid' => $assign2b->cmid]); $ucc2a = $ccg->create_user_competency_course(['competencyid' => $comp1->get_id(), 'courseid' => $c2->id, 'userid' => $u1->id]); $ucc2b = $ccg->create_user_competency_course(['competencyid' => $comp2->get_id(), 'courseid' => $c2->id, 'userid' => $u1->id]); course_delete_module($assign1b->cmid); $this->assertEquals(2, course_competency::count_records(['courseid' => $c1->id])); $this->assertEquals(1, course_module_competency::count_records(['cmid' => $assign1a->cmid])); $this->assertEquals(0, course_module_competency::count_records(['cmid' => $assign1b->cmid])); $this->assertEquals(2, user_competency_course::count_records(['courseid' => $c1->id])); $this->assertEquals(2, course_competency::count_records(['courseid' => $c2->id])); $this->assertEquals(1, course_module_competency::count_records(['cmid' => $assign2a->cmid])); $this->assertEquals(1, course_module_competency::count_records(['cmid' => $assign2b->cmid])); $this->assertEquals(2, user_competency_course::count_records(['courseid' => $c2->id, 'userid' => $u1->id])); }
/** * Test the cleanup task. */ public function test_cleanup_task() { global $DB; set_config('coursebinexpiry', WEEKSECS, 'tool_recyclebin'); // Delete the quiz. course_delete_module($this->quiz->cmid); // Now, run the course module deletion adhoc task. phpunit_util::run_all_adhoc_tasks(); // Set deleted date to the distant past. $recyclebin = new \tool_recyclebin\course_bin($this->course->id); foreach ($recyclebin->get_items() as $item) { $item->timecreated = time() - WEEKSECS; $DB->update_record('tool_recyclebin_course', $item); } // Create another module we are going to delete, but not alter the time it was placed in the recycle bin. $book = $this->getDataGenerator()->get_plugin_generator('mod_book')->create_instance(array('course' => $this->course->id)); course_delete_module($book->cmid); // Now, run the course module deletion adhoc task. phpunit_util::run_all_adhoc_tasks(); // Should have 2 items now. $this->assertEquals(2, count($recyclebin->get_items())); // Execute cleanup task. $this->expectOutputRegex("/\\[tool_recyclebin\\] Deleting item '\\d+' from the course recycle bin/"); $task = new \tool_recyclebin\task\cleanup_course_bin(); $task->execute(); // Should only have the book as it was not due to be deleted. $items = $recyclebin->get_items(); $this->assertEquals(1, count($items)); $deletedbook = reset($items); $this->assertEquals($book->name, $deletedbook->name); }
/** * Tests for event related to course module delete. */ public function test_course_module_deleted_event() { global $USER, $DB; $this->resetAfterTest(); // Create and delete a module. $sink = $this->redirectEvents(); $modinfo = $this->create_specific_module_test('forum'); $cm = $DB->get_record('course_modules', array('id' => $modinfo->coursemodule), '*', MUST_EXIST); course_delete_module($modinfo->coursemodule); $events = $sink->get_events(); $event = array_pop($events); // delete module event.; $sink->close(); // Validate event data. $this->assertInstanceOf('\\core\\event\\course_module_deleted', $event); $this->assertEquals($cm->id, $event->objectid); $this->assertEquals($USER->id, $event->userid); $this->assertEquals('course_modules', $event->objecttable); $this->assertEquals(null, $event->get_url()); $this->assertEquals($cm, $event->get_record_snapshot('course_modules', $cm->id)); // Test legacy data. $this->assertSame('mod_deleted', $event->get_legacy_eventname()); $eventdata = new stdClass(); $eventdata->modulename = 'forum'; $eventdata->cmid = $cm->id; $eventdata->courseid = $cm->course; $eventdata->userid = $USER->id; $this->assertEventLegacyData($eventdata, $event); $arr = array($cm->course, 'course', "delete mod", "view.php?id={$cm->course}", "forum {$cm->instance}", $cm->id); $this->assertEventLegacyLogData($arr, $event); }
function RWSADQuiz() { global $CFG; global $RWSLB; RWSCMAuth(); RWSCRAuth(); RWSCMUSvc(); RWSCMMaint(); $r_pm = RWSGSOpt("quizid", PARAM_ALPHANUM); if ($r_pm === false || strlen($r_pm) == 0) { RWSSErr("2067"); } $r_qzmi = intval($r_pm); $r_rcd = RWSCMUQuiz($r_qzmi); $r_cid = $r_rcd->course; RWSCMUCourse($r_cid, true); if (respondusws_floatcompare($CFG->version, 2013051400, 2) >= 0) { course_delete_module($r_qzmi); } else { if (!quiz_delete_instance($r_rcd->instance)) { RWSSErr("2068"); } if (!delete_course_module($r_qzmi)) { RWSSErr("2069"); } if (!delete_mod_from_section($r_qzmi, $r_rcd->section)) { RWSSErr("2070"); } } if ($RWSLB->mok) { lockdown_delete_options($r_rcd->instance); } else { if ($RWSLB->bok) { lockdown_delete_options($r_rcd->instance); } } rebuild_course_cache($r_cid); RWSSStat("1003"); }
public function test_upgrade_offline_setaskment() { global $DB, $CFG; $commentconfig = false; if (!empty($CFG->usecomments)) { $commentconfig = $CFG->usecomments; } $CFG->usecomments = false; $this->setUser($this->editingteachers[0]); $generator = $this->getDataGenerator()->get_plugin_generator('mod_setaskment'); $params = array('course' => $this->course->id, 'setaskmenttype' => 'offline'); $setaskment = $generator->create_instance($params); $this->setAdminUser(); $log = ''; $upgrader = new setask_upgrade_manager(); $this->assertTrue($upgrader->upgrade_setaskment($setaskment->id, $log)); $record = $DB->get_record('setask', array('course' => $this->course->id)); $cm = get_coursemodule_from_instance('setask', $record->id); $context = context_module::instance($cm->id); $setask = new setask($context, $cm, $this->course); $plugin = $setask->get_submission_plugin_by_type('onlinetext'); $this->assertEmpty($plugin->is_enabled()); $plugin = $setask->get_submission_plugin_by_type('comments'); $this->assertEmpty($plugin->is_enabled()); $plugin = $setask->get_submission_plugin_by_type('file'); $this->assertEmpty($plugin->is_enabled()); $plugin = $setask->get_feedback_plugin_by_type('comments'); $this->assertNotEmpty($plugin->is_enabled()); $plugin = $setask->get_feedback_plugin_by_type('file'); $this->assertEmpty($plugin->is_enabled()); $plugin = $setask->get_feedback_plugin_by_type('offline'); $this->assertEmpty($plugin->is_enabled()); $CFG->usecomments = $commentconfig; course_delete_module($cm->id); }
public function test_rating() { global $USER, $DB; $this->resetAfterTest(); $generator = $this->getDataGenerator()->get_plugin_generator('mod_forumng'); $course = $this->get_new_course(); $course2 = $this->get_new_course(); $suser = $this->get_new_user('student', $course->id); $this->setAdminUser(); $forum = $this->get_new_forumng($course->id, array('name' => 'TEST', 'intro' => 'abc123', 'enableratings' => mod_forumng::FORUMNG_STANDARD_RATING, 'ratingscale' => 10)); $forum2 = $this->get_new_forumng($course->id, array('name' => 'TEST2', 'intro' => 'abc123', 'enableratings' => mod_forumng::FORUMNG_NO_RATING)); $forum3 = $this->get_new_forumng($course2->id, array('name' => 'TEST', 'intro' => 'abc123', 'enableratings' => mod_forumng::FORUMNG_STANDARD_RATING, 'ratingscale' => 10)); $did1 = $generator->create_discussion(array('course' => $course, 'forum' => $forum->get_id(), 'userid' => $suser->id)); $did2 = $generator->create_discussion(array('course' => $course, 'forum' => $forum->get_id(), 'userid' => $suser->id)); $did3 = $generator->create_discussion(array('course' => $course, 'forum' => $forum->get_id(), 'userid' => $suser->id)); $did4 = $generator->create_discussion(array('course' => $course, 'forum' => $forum->get_id(), 'userid' => $suser->id)); // Add rating to all 3 discussions. $rm = new rating_manager(); $params = new stdClass(); $params->context = $forum->get_context(); $params->component = 'mod_forumng'; $params->ratingarea = 'post'; $params->scaleid = $forum->get_rating_scale(); $params->userid = $USER->id; $params->itemid = $did1[1]; $rating = new rating($params); $rating->update_rating(5); $params->itemid = $did2[1]; $rating = new rating($params); $rating->update_rating(5); $params->itemid = $did3[1]; $rating = new rating($params); $rating->update_rating(5); // Check rating object gets added where expected. $post = mod_forumng_post::get_from_id($did1[1], mod_forumng::CLONE_DIRECT, false, false); $ratings = $post->get_ratings(); $this->assertNotNull($ratings); $this->assertEquals($did1[1], $ratings->itemid); $post = mod_forumng_post::get_from_id($did1[1], mod_forumng::CLONE_DIRECT, true, false); $ratings = $post->get_ratings(); $this->assertNotNull($ratings); $this->assertEquals($did1[1], $ratings->itemid); $post = mod_forumng_post::get_from_id($did1[1], mod_forumng::CLONE_DIRECT, true, true); $ratings = $post->get_ratings(); $this->assertNotNull($ratings); $this->assertEquals($did1[1], $ratings->itemid); $ratedposts = $forum->get_all_posts_by_user($suser->id, null, 'fp.id', null, null, true); $this->assertCount(3, $ratedposts); $allposts = $forum->get_all_posts_by_user($suser->id, null); $this->assertCount(4, $allposts); $this->assertNotNull($allposts[$did1[1]]->get_ratings()); // Update grades (does nothing). $forum->update_grades(); // Enable rating grading, forumng_update_instance() should update grades. forumng_update_instance((object) array('instance' => $forum->get_id(), 'grading' => mod_forumng::GRADING_SUM)); $grades = grade_get_grades($course->id, 'mod', 'forumng', $forum->get_id(), $suser->id); // Note sum is set to 10 not 15 as max grade is 10. $this->assertEquals(10, abs($grades->items[0]->grades[$suser->id]->grade)); // Enable rating grading, forumng_update_instance() should update grades. forumng_update_instance((object) array('instance' => $forum->get_id(), 'grading' => mod_forumng::GRADING_COUNT)); $grades = grade_get_grades($course->id, 'mod', 'forumng', $forum->get_id(), $suser->id); $this->assertEquals(3, abs($grades->items[0]->grades[$suser->id]->grade)); // Check get_rated_posts_by_user. $extrapost = $generator->create_post(array('discussionid' => $did1[0], 'parentpostid' => $did1[1], 'userid' => $suser->id, 'created' => 1388589745)); $extraposts = $forum->get_rated_posts_by_user($forum, $suser->id, -1, 'fp.id', null, null); $this->assertCount(0, $extraposts); $extraposts = $forum->get_rated_posts_by_user($forum, $USER->id, -1, 'fp.id', null, null); $this->assertCount(3, $extraposts); $params->itemid = $extrapost->id; $rating = new rating($params); $rating->update_rating(10); $extraposts = $forum->get_rated_posts_by_user($forum, $USER->id, -1, 'fp.id', null, null); $this->assertCount(4, $extraposts); // Now filter out the 'old' extrapost. $extraposts = $forum->get_rated_posts_by_user($forum, $USER->id, -1, 'fp.id', null, null, 1388600000); $this->assertCount(3, $extraposts); // Check discussion delete. $discuss = mod_forumng_discussion::get_from_id($did1[0], mod_forumng::CLONE_DIRECT); $discuss->permanently_delete(); $rating = $DB->get_record('rating', array('itemid' => $did1[1])); $this->assertFalse($rating); $grades = grade_get_grades($course->id, 'mod', 'forumng', $forum->get_id(), $suser->id); $this->assertEquals(2, abs($grades->items[0]->grades[$suser->id]->grade)); // Check discussion move. $discuss = mod_forumng_discussion::get_from_id($did2[0], mod_forumng::CLONE_DIRECT); $discuss->move($forum2, 0); $grades = grade_get_grades($course->id, 'mod', 'forumng', $forum->get_id(), $suser->id); $this->assertEquals(1, abs($grades->items[0]->grades[$suser->id]->grade)); forumng_update_instance((object) array('instance' => $forum2->get_id(), 'grading' => mod_forumng::GRADING_COUNT, 'enableratings' => mod_forumng::FORUMNG_STANDARD_RATING, 'ratingscale' => 10)); $grades = grade_get_grades($course->id, 'mod', 'forumng', $forum2->get_id(), $suser->id); $this->assertEquals(1, abs($grades->items[0]->grades[$suser->id]->grade)); $rating = $DB->get_record('rating', array('itemid' => $did2[1])); $this->assertNotEmpty($rating); $this->assertEquals($forum2->get_context(true)->id, $rating->contextid); // Check discussion copy. $discuss = mod_forumng_discussion::get_from_id($did3[0], mod_forumng::CLONE_DIRECT); $discuss->copy($forum3, 0); $grades = grade_get_grades($course->id, 'mod', 'forumng', $forum->get_id(), $suser->id); $this->assertEquals(1, abs($grades->items[0]->grades[$suser->id]->grade)); // Check rating didn't copy as forum in another course. $ratingtotal = $DB->get_records('rating'); $this->assertCount(2, $ratingtotal); // Check rating does copy to foum in same course. $discuss->copy($forum2, 0); $ratingtotal = $DB->get_records('rating'); $this->assertCount(3, $ratingtotal); // Check forum deleting. course_delete_module($forum->get_course_module_id()); $ratingtotal = $DB->get_records('rating'); $this->assertCount(2, $ratingtotal); $grades = grade_get_grades($course->id, 'mod', 'forumng', $forum->get_id(), $suser->id); $this->assertEmpty($grades->items); }
/** * This function converts all of the base settings for an instance of * the old setaskment to the new format. Then it calls each of the plugins * to see if they can help upgrade this setaskment. * @param int $oldsetaskmentid (don't rely on the old setaskment type even being installed) * @param string $log This string gets appended to during the conversion process * @return bool true or false */ public function upgrade_setaskment($oldsetaskmentid, &$log) { global $DB, $CFG, $USER; // Steps to upgrade an setaskment. core_php_time_limit::raise(ASSIGN_MAX_UPGRADE_TIME_SECS); // Get the module details. $oldmodule = $DB->get_record('modules', array('name' => 'setaskment'), '*', MUST_EXIST); $params = array('module' => $oldmodule->id, 'instance' => $oldsetaskmentid); $oldcoursemodule = $DB->get_record('course_modules', $params, '*', MUST_EXIST); $oldcontext = context_module::instance($oldcoursemodule->id); // We used to check for admin capability, but since Moodle 2.7 this is called // during restore of a mod_setaskment module. // Also note that we do not check for any mod_setaskment capabilities, because they can // be removed so that users don't add new instances of the broken old thing. if (!has_capability('mod/setask:addinstance', $oldcontext)) { $log = get_string('couldnotcreatenewsetaskmentinstance', 'mod_setask'); return false; } // First insert an setask instance to get the id. $oldsetaskment = $DB->get_record('setaskment', array('id' => $oldsetaskmentid), '*', MUST_EXIST); $oldversion = get_config('setaskment_' . $oldsetaskment->setaskmenttype, 'version'); $data = new stdClass(); $data->course = $oldsetaskment->course; $data->name = $oldsetaskment->name; $data->intro = $oldsetaskment->intro; $data->introformat = $oldsetaskment->introformat; $data->alwaysshowdescription = 1; $data->sendnotifications = $oldsetaskment->emailteachers; $data->sendlatenotifications = $oldsetaskment->emailteachers; $data->duedate = $oldsetaskment->timedue; $data->allowsubmissionsfromdate = $oldsetaskment->timeavailable; $data->grade = $oldsetaskment->grade; $data->submissiondrafts = $oldsetaskment->resubmit; $data->requiresubmissionstatement = 0; $data->markingworkflow = 0; $data->markingallocation = 0; $data->cutoffdate = 0; // New way to specify no late submissions. if ($oldsetaskment->preventlate) { $data->cutoffdate = $data->duedate; } $data->teamsubmission = 0; $data->requireallteammemberssubmit = 0; $data->teamsubmissiongroupingid = 0; $data->blindmarking = 0; $data->attemptreopenmethod = 'none'; $data->maxattempts = ASSIGN_UNLIMITED_ATTEMPTS; $newsetaskment = new setask(null, null, null); if (!$newsetaskment->add_instance($data, false)) { $log = get_string('couldnotcreatenewsetaskmentinstance', 'mod_setask'); return false; } // Now create a new coursemodule from the old one. $newmodule = $DB->get_record('modules', array('name' => 'setask'), '*', MUST_EXIST); $newcoursemodule = $this->duplicate_course_module($oldcoursemodule, $newmodule->id, $newsetaskment->get_instance()->id); if (!$newcoursemodule) { $log = get_string('couldnotcreatenewcoursemodule', 'mod_setask'); return false; } // Convert the base database tables (setaskment, submission, grade). // These are used to store information in case a rollback is required. $gradingarea = null; $gradingdefinitions = null; $gradeidmap = array(); $completiondone = false; $gradesdone = false; // From this point we want to rollback on failure. $rollback = false; try { $newsetaskment->set_context(context_module::instance($newcoursemodule->id)); // The course module has now been created - time to update the core tables. // Copy intro files. $newsetaskment->copy_area_files_for_upgrade($oldcontext->id, 'mod_setaskment', 'intro', 0, $newsetaskment->get_context()->id, 'mod_setask', 'intro', 0); // Get the plugins to do their bit. foreach ($newsetaskment->get_submission_plugins() as $plugin) { if ($plugin->can_upgrade($oldsetaskment->setaskmenttype, $oldversion)) { $plugin->enable(); if (!$plugin->upgrade_settings($oldcontext, $oldsetaskment, $log)) { $rollback = true; } } else { $plugin->disable(); } } foreach ($newsetaskment->get_feedback_plugins() as $plugin) { if ($plugin->can_upgrade($oldsetaskment->setaskmenttype, $oldversion)) { $plugin->enable(); if (!$plugin->upgrade_settings($oldcontext, $oldsetaskment, $log)) { $rollback = true; } } else { $plugin->disable(); } } // See if there is advanced grading upgrades required. $gradingarea = $DB->get_record('grading_areas', array('contextid' => $oldcontext->id, 'areaname' => 'submission'), '*', IGNORE_MISSING); if ($gradingarea) { $params = array('id' => $gradingarea->id, 'contextid' => $newsetaskment->get_context()->id, 'component' => 'mod_setask', 'areaname' => 'submissions'); $DB->update_record('grading_areas', $params); $gradingdefinitions = $DB->get_records('grading_definitions', array('areaid' => $gradingarea->id)); } // Upgrade availability data. \core_availability\info::update_dependency_id_across_course($newcoursemodule->course, 'course_modules', $oldcoursemodule->id, $newcoursemodule->id); // Upgrade completion data. $DB->set_field('course_modules_completion', 'coursemoduleid', $newcoursemodule->id, array('coursemoduleid' => $oldcoursemodule->id)); $allcriteria = $DB->get_records('course_completion_criteria', array('moduleinstance' => $oldcoursemodule->id)); foreach ($allcriteria as $criteria) { $criteria->module = 'setask'; $criteria->moduleinstance = $newcoursemodule->id; $DB->update_record('course_completion_criteria', $criteria); } $completiondone = true; // Migrate log entries so we don't lose them. $logparams = array('cmid' => $oldcoursemodule->id, 'course' => $oldcoursemodule->course); $DB->set_field('log', 'module', 'setask', $logparams); $DB->set_field('log', 'cmid', $newcoursemodule->id, $logparams); // Copy all the submission data (and get plugins to do their bit). $oldsubmissions = $DB->get_records('setaskment_submissions', array('setaskment' => $oldsetaskmentid)); foreach ($oldsubmissions as $oldsubmission) { $submission = new stdClass(); $submission->setaskment = $newsetaskment->get_instance()->id; $submission->userid = $oldsubmission->userid; $submission->timecreated = $oldsubmission->timecreated; $submission->timemodified = $oldsubmission->timemodified; $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; // Because in mod_setaskment there could only be one submission per student, it is always the latest. $submission->latest = 1; $submission->id = $DB->insert_record('setask_submission', $submission); if (!$submission->id) { $log .= get_string('couldnotinsertsubmission', 'mod_setask', $submission->userid); $rollback = true; } foreach ($newsetaskment->get_submission_plugins() as $plugin) { if ($plugin->can_upgrade($oldsetaskment->setaskmenttype, $oldversion)) { if (!$plugin->upgrade($oldcontext, $oldsetaskment, $oldsubmission, $submission, $log)) { $rollback = true; } } } if ($oldsubmission->timemarked) { // Submission has been graded - create a grade record. $grade = new stdClass(); $grade->setaskment = $newsetaskment->get_instance()->id; $grade->userid = $oldsubmission->userid; $grade->grader = $oldsubmission->teacher; $grade->timemodified = $oldsubmission->timemarked; $grade->timecreated = $oldsubmission->timecreated; $grade->grade = $oldsubmission->grade; if ($oldsubmission->mailed) { // The mailed flag goes in the flags table. $flags = new stdClass(); $flags->userid = $oldsubmission->userid; $flags->setaskment = $newsetaskment->get_instance()->id; $flags->mailed = 1; $DB->insert_record('setask_user_flags', $flags); } $grade->id = $DB->insert_record('setask_grades', $grade); if (!$grade->id) { $log .= get_string('couldnotinsertgrade', 'mod_setask', $grade->userid); $rollback = true; } // Copy any grading instances. if ($gradingarea) { $gradeidmap[$grade->id] = $oldsubmission->id; foreach ($gradingdefinitions as $definition) { $params = array('definitionid' => $definition->id, 'itemid' => $oldsubmission->id); $DB->set_field('grading_instances', 'itemid', $grade->id, $params); } } foreach ($newsetaskment->get_feedback_plugins() as $plugin) { if ($plugin->can_upgrade($oldsetaskment->setaskmenttype, $oldversion)) { if (!$plugin->upgrade($oldcontext, $oldsetaskment, $oldsubmission, $grade, $log)) { $rollback = true; } } } } } $newsetaskment->update_calendar($newcoursemodule->id); // Reassociate grade_items from the old setaskment instance to the new setask instance. // This includes outcome linked grade_items. $params = array('setask', $newsetaskment->get_instance()->id, 'setaskment', $oldsetaskment->id); $sql = 'UPDATE {grade_items} SET itemmodule = ?, iteminstance = ? WHERE itemmodule = ? AND iteminstance = ?'; $DB->execute($sql, $params); // Create a mapping record to map urls from the old to the new setaskment. $mapping = new stdClass(); $mapping->oldcmid = $oldcoursemodule->id; $mapping->oldinstance = $oldsetaskment->id; $mapping->newcmid = $newcoursemodule->id; $mapping->newinstance = $newsetaskment->get_instance()->id; $mapping->timecreated = time(); $DB->insert_record('setaskment_upgrade', $mapping); $gradesdone = true; } catch (Exception $exception) { $rollback = true; $log .= get_string('conversionexception', 'mod_setask', $exception->getMessage()); } if ($rollback) { // Roll back the grades changes. if ($gradesdone) { // Reassociate grade_items from the new setask instance to the old setaskment instance. $params = array('setaskment', $oldsetaskment->id, 'setask', $newsetaskment->get_instance()->id); $sql = 'UPDATE {grade_items} SET itemmodule = ?, iteminstance = ? WHERE itemmodule = ? AND iteminstance = ?'; $DB->execute($sql, $params); } // Roll back the completion changes. if ($completiondone) { $DB->set_field('course_modules_completion', 'coursemoduleid', $oldcoursemodule->id, array('coursemoduleid' => $newcoursemodule->id)); $allcriteria = $DB->get_records('course_completion_criteria', array('moduleinstance' => $newcoursemodule->id)); foreach ($allcriteria as $criteria) { $criteria->module = 'setaskment'; $criteria->moduleinstance = $oldcoursemodule->id; $DB->update_record('course_completion_criteria', $criteria); } } // Roll back the log changes. $logparams = array('cmid' => $newcoursemodule->id, 'course' => $newcoursemodule->course); $DB->set_field('log', 'module', 'setaskment', $logparams); $DB->set_field('log', 'cmid', $oldcoursemodule->id, $logparams); // Roll back the advanced grading update. if ($gradingarea) { foreach ($gradeidmap as $newgradeid => $oldsubmissionid) { foreach ($gradingdefinitions as $definition) { $DB->set_field('grading_instances', 'itemid', $oldsubmissionid, array('definitionid' => $definition->id, 'itemid' => $newgradeid)); } } $params = array('id' => $gradingarea->id, 'contextid' => $oldcontext->id, 'component' => 'mod_setaskment', 'areaname' => 'submission'); $DB->update_record('grading_areas', $params); } $newsetaskment->delete_instance(); return false; } // Delete the old setaskment (use object delete). $cm = get_coursemodule_from_id('', $oldcoursemodule->id, $oldcoursemodule->course); if ($cm) { course_delete_module($cm->id); } rebuild_course_cache($oldcoursemodule->course); return true; }
/** * This function converts all of the base settings for an instance of * the old assignment to the new format. Then it calls each of the plugins * to see if they can help upgrade this assignment. * @param int $oldassignmentid (don't rely on the old assignment type even being installed) * @param string $log This string gets appended to during the conversion process * @return bool true or false */ public function upgrade_assignment($oldassignmentid, & $log) { global $DB, $CFG, $USER; // Steps to upgrade an assignment. // Is the user the admin? admin check goes here. if (!is_siteadmin($USER->id)) { return false; } @set_time_limit(ASSIGN_MAX_UPGRADE_TIME_SECS); // Get the module details. $oldmodule = $DB->get_record('modules', array('name'=>'assignment'), '*', MUST_EXIST); $params = array('module'=>$oldmodule->id, 'instance'=>$oldassignmentid); $oldcoursemodule = $DB->get_record('course_modules', $params, '*', MUST_EXIST); $oldcontext = context_module::instance($oldcoursemodule->id); // First insert an assign instance to get the id. $oldassignment = $DB->get_record('assignment', array('id'=>$oldassignmentid), '*', MUST_EXIST); $oldversion = get_config('assignment_' . $oldassignment->assignmenttype, 'version'); $data = new stdClass(); $data->course = $oldassignment->course; $data->name = $oldassignment->name; $data->intro = $oldassignment->intro; $data->introformat = $oldassignment->introformat; $data->alwaysshowdescription = 1; $data->sendnotifications = $oldassignment->emailteachers; $data->sendlatenotifications = $oldassignment->emailteachers; $data->duedate = $oldassignment->timedue; $data->allowsubmissionsfromdate = $oldassignment->timeavailable; $data->grade = $oldassignment->grade; $data->submissiondrafts = $oldassignment->resubmit; $data->requiresubmissionstatement = 0; $data->cutoffdate = 0; // New way to specify no late submissions. if ($oldassignment->preventlate) { $data->cutoffdate = $data->duedate; } $data->teamsubmission = 0; $data->requireallteammemberssubmit = 0; $data->teamsubmissiongroupingid = 0; $data->blindmarking = 0; $newassignment = new assign(null, null, null); if (!$newassignment->add_instance($data, false)) { $log = get_string('couldnotcreatenewassignmentinstance', 'mod_assign'); return false; } // Now create a new coursemodule from the old one. $newmodule = $DB->get_record('modules', array('name'=>'assign'), '*', MUST_EXIST); $newcoursemodule = $this->duplicate_course_module($oldcoursemodule, $newmodule->id, $newassignment->get_instance()->id); if (!$newcoursemodule) { $log = get_string('couldnotcreatenewcoursemodule', 'mod_assign'); return false; } // Convert the base database tables (assignment, submission, grade). // These are used to store information in case a rollback is required. $gradingarea = null; $gradingdefinitions = null; $gradeidmap = array(); $completiondone = false; $gradesdone = false; // From this point we want to rollback on failure. $rollback = false; try { $newassignment->set_context(context_module::instance($newcoursemodule->id)); // The course module has now been created - time to update the core tables. // Copy intro files. $newassignment->copy_area_files_for_upgrade($oldcontext->id, 'mod_assignment', 'intro', 0, $newassignment->get_context()->id, 'mod_assign', 'intro', 0); // Get the plugins to do their bit. foreach ($newassignment->get_submission_plugins() as $plugin) { if ($plugin->can_upgrade($oldassignment->assignmenttype, $oldversion)) { $plugin->enable(); if (!$plugin->upgrade_settings($oldcontext, $oldassignment, $log)) { $rollback = true; } } else { $plugin->disable(); } } foreach ($newassignment->get_feedback_plugins() as $plugin) { if ($plugin->can_upgrade($oldassignment->assignmenttype, $oldversion)) { $plugin->enable(); if (!$plugin->upgrade_settings($oldcontext, $oldassignment, $log)) { $rollback = true; } } else { $plugin->disable(); } } // See if there is advanced grading upgrades required. $gradingarea = $DB->get_record('grading_areas', array('contextid'=>$oldcontext->id, 'areaname'=>'submission'), '*', IGNORE_MISSING); if ($gradingarea) { $params = array('id'=>$gradingarea->id, 'contextid'=>$newassignment->get_context()->id, 'component'=>'mod_assign', 'areaname'=>'submissions'); $DB->update_record('grading_areas', $params); $gradingdefinitions = $DB->get_records('grading_definitions', array('areaid'=>$gradingarea->id)); } // Upgrade availability data. $DB->set_field('course_modules_avail_fields', 'coursemoduleid', $newcoursemodule->id, array('coursemoduleid'=>$oldcoursemodule->id)); $DB->set_field('course_modules_availability', 'coursemoduleid', $newcoursemodule->id, array('coursemoduleid'=>$oldcoursemodule->id)); $DB->set_field('course_modules_availability', 'sourcecmid', $newcoursemodule->id, array('sourcecmid'=>$oldcoursemodule->id)); $DB->set_field('course_sections_availability', 'sourcecmid', $newcoursemodule->id, array('sourcecmid'=>$oldcoursemodule->id)); // Upgrade completion data. $DB->set_field('course_modules_completion', 'coursemoduleid', $newcoursemodule->id, array('coursemoduleid'=>$oldcoursemodule->id)); $allcriteria = $DB->get_records('course_completion_criteria', array('moduleinstance'=>$oldcoursemodule->id)); foreach ($allcriteria as $criteria) { $criteria->module = 'assign'; $criteria->moduleinstance = $newcoursemodule->id; $DB->update_record('course_completion_criteria', $criteria); } $completiondone = true; // Migrate log entries so we don't lose them. $logparams = array('cmid' => $oldcoursemodule->id, 'course' => $oldcoursemodule->course); $DB->set_field('log', 'module', 'assign', $logparams); $DB->set_field('log', 'cmid', $newcoursemodule->id, $logparams); // Copy all the submission data (and get plugins to do their bit). $oldsubmissions = $DB->get_records('assignment_submissions', array('assignment'=>$oldassignmentid)); foreach ($oldsubmissions as $oldsubmission) { $submission = new stdClass(); $submission->assignment = $newassignment->get_instance()->id; $submission->userid = $oldsubmission->userid; $submission->timecreated = $oldsubmission->timecreated; $submission->timemodified = $oldsubmission->timemodified; $submission->status = ASSIGN_SUBMISSION_STATUS_SUBMITTED; $submission->id = $DB->insert_record('assign_submission', $submission); if (!$submission->id) { $log .= get_string('couldnotinsertsubmission', 'mod_assign', $submission->userid); $rollback = true; } foreach ($newassignment->get_submission_plugins() as $plugin) { if ($plugin->can_upgrade($oldassignment->assignmenttype, $oldversion)) { if (!$plugin->upgrade($oldcontext, $oldassignment, $oldsubmission, $submission, $log)) { $rollback = true; } } } if ($oldsubmission->timemarked) { // Submission has been graded - create a grade record. $grade = new stdClass(); $grade->assignment = $newassignment->get_instance()->id; $grade->userid = $oldsubmission->userid; $grade->grader = $oldsubmission->teacher; $grade->timemodified = $oldsubmission->timemarked; $grade->timecreated = $oldsubmission->timecreated; $grade->grade = $oldsubmission->grade; $grade->mailed = $oldsubmission->mailed; $grade->id = $DB->insert_record('assign_grades', $grade); if (!$grade->id) { $log .= get_string('couldnotinsertgrade', 'mod_assign', $grade->userid); $rollback = true; } // Copy any grading instances. if ($gradingarea) { $gradeidmap[$grade->id] = $oldsubmission->id; foreach ($gradingdefinitions as $definition) { $params = array('definitionid'=>$definition->id, 'itemid'=>$oldsubmission->id); $DB->set_field('grading_instances', 'itemid', $grade->id, $params); } } foreach ($newassignment->get_feedback_plugins() as $plugin) { if ($plugin->can_upgrade($oldassignment->assignmenttype, $oldversion)) { if (!$plugin->upgrade($oldcontext, $oldassignment, $oldsubmission, $grade, $log)) { $rollback = true; } } } } } $newassignment->update_calendar($newcoursemodule->id); // Reassociate grade_items from the old assignment instance to the new assign instance. // This includes outcome linked grade_items. $params = array('assign', $newassignment->get_instance()->id, 'assignment', $oldassignment->id); $sql = 'UPDATE {grade_items} SET itemmodule = ?, iteminstance = ? WHERE itemmodule = ? AND iteminstance = ?'; $DB->execute($sql, $params); $gradesdone = true; } catch (Exception $exception) { $rollback = true; $log .= get_string('conversionexception', 'mod_assign', $exception->error); } if ($rollback) { // Roll back the grades changes. if ($gradesdone) { // Reassociate grade_items from the new assign instance to the old assignment instance. $params = array('assignment', $oldassignment->id, 'assign', $newassignment->get_instance()->id); $sql = 'UPDATE {grade_items} SET itemmodule = ?, iteminstance = ? WHERE itemmodule = ? AND iteminstance = ?'; $DB->execute($sql, $params); } // Roll back the completion changes. if ($completiondone) { $DB->set_field('course_modules_completion', 'coursemoduleid', $oldcoursemodule->id, array('coursemoduleid'=>$newcoursemodule->id)); $allcriteria = $DB->get_records('course_completion_criteria', array('moduleinstance'=>$newcoursemodule->id)); foreach ($allcriteria as $criteria) { $criteria->module = 'assignment'; $criteria->moduleinstance = $oldcoursemodule->id; $DB->update_record('course_completion_criteria', $criteria); } } // Roll back the log changes. $logparams = array('cmid' => $newcoursemodule->id, 'course' => $newcoursemodule->course); $DB->set_field('log', 'module', 'assignment', $logparams); $DB->set_field('log', 'cmid', $oldcoursemodule->id, $logparams); // Roll back the advanced grading update. if ($gradingarea) { foreach ($gradeidmap as $newgradeid => $oldsubmissionid) { foreach ($gradingdefinitions as $definition) { $DB->set_field('grading_instances', 'itemid', $oldsubmissionid, array('definitionid'=>$definition->id, 'itemid'=>$newgradeid)); } } $params = array('id'=>$gradingarea->id, 'contextid'=>$oldcontext->id, 'component'=>'mod_assignment', 'areaname'=>'submission'); $DB->update_record('grading_areas', $params); } $newassignment->delete_instance(); return false; } // Delete the old assignment (use object delete). $cm = get_coursemodule_from_id('', $oldcoursemodule->id, $oldcoursemodule->course); if ($cm) { course_delete_module($cm->id); } rebuild_course_cache($oldcoursemodule->course); return true; }
/** * Deletes a list of provided module instances. * * @param array $cmids the course module ids * @since Moodle 2.5 */ public static function delete_modules($cmids) { global $CFG, $DB; // Require course file containing the course delete module function. require_once($CFG->dirroot . "/course/lib.php"); // Clean the parameters. $params = self::validate_parameters(self::delete_modules_parameters(), array('cmids' => $cmids)); // Keep track of the course ids we have performed a capability check on to avoid repeating. $arrcourseschecked = array(); foreach ($params['cmids'] as $cmid) { // Get the course module. $cm = $DB->get_record('course_modules', array('id' => $cmid), '*', MUST_EXIST); // Check if we have not yet confirmed they have permission in this course. if (!in_array($cm->course, $arrcourseschecked)) { // Ensure the current user has required permission in this course. $context = context_course::instance($cm->course); self::validate_context($context); // Add to the array. $arrcourseschecked[] = $cm->course; } // Ensure they can delete this module. $modcontext = context_module::instance($cm->id); require_capability('moodle/course:manageactivities', $modcontext); // Delete the module. course_delete_module($cm->id); } }
public function test_async_section_deletion_hook_implemented() { // Async section deletion (provided section contains modules), depends on the 'true' being returned by at least one plugin // implementing the 'course_module_adhoc_deletion_recommended' hook. In core, is implemented by the course recyclebin, // which will only return true if the plugin is enabled. To make sure async deletion occurs, this test enables recyclebin. global $DB, $USER; $this->resetAfterTest(true); $this->setAdminUser(); // Ensure recyclebin is enabled. set_config('coursebinenable', true, 'tool_recyclebin'); // Create course, module and context. $generator = $this->getDataGenerator(); $course = $generator->create_course(['numsections' => 4, 'format' => 'topics'], ['createsections' => true]); $assign0 = $generator->create_module('assign', ['course' => $course, 'section' => 2]); $assign1 = $generator->create_module('assign', ['course' => $course, 'section' => 2]); $assign2 = $generator->create_module('assign', ['course' => $course, 'section' => 2]); $assign3 = $generator->create_module('assign', ['course' => $course, 'section' => 0]); // Delete empty section. No difference from normal, synchronous behaviour. $this->assertTrue(course_delete_section($course, 4, false, true)); $this->assertEquals(3, course_get_format($course)->get_course()->numsections); // Delete a module in section 2 (using async). Need to verify this doesn't generate two tasks when we delete // the section in the next step. course_delete_module($assign2->cmid, true); // Confirm that the module is pending deletion in its current section. $section = $DB->get_record('course_sections', ['course' => $course->id, 'section' => '2']); // For event comparison. $this->assertEquals(true, $DB->record_exists('course_modules', ['id' => $assign2->cmid, 'deletioninprogress' => 1, 'section' => $section->id])); // Now, delete section 2. $this->assertFalse(course_delete_section($course, 2, false, true)); // Non-empty section, no forcedelete, so no change. $sink = $this->redirectEvents(); // To capture the event. $this->assertTrue(course_delete_section($course, 2, true, true)); // Now, confirm that: // a) the section's modules have been flagged for deletion and moved to section 0 and; // b) the section has been deleted and; // c) course_section_deleted event has been fired. The course_module_deleted events will only fire once they have been // removed from section 0 via the adhoc task. // Modules should have been flagged for deletion and moved to section 0. $sectionid = $DB->get_field('course_sections', 'id', ['course' => $course->id, 'section' => 0]); $this->assertEquals(3, $DB->count_records('course_modules', ['section' => $sectionid, 'deletioninprogress' => 1])); // Confirm the section has been deleted. $this->assertEquals(2, course_get_format($course)->get_course()->numsections); // Check event fired. $events = $sink->get_events(); $event = array_pop($events); $sink->close(); $this->assertInstanceOf('\\core\\event\\course_section_deleted', $event); $this->assertEquals($section->id, $event->objectid); $this->assertEquals($USER->id, $event->userid); $this->assertEquals('course_sections', $event->objecttable); $this->assertEquals(null, $event->get_url()); $this->assertEquals($section, $event->get_record_snapshot('course_sections', $section->id)); // Now, run the adhoc task to delete the modules from section 0. $sink = $this->redirectEvents(); // To capture the events. phpunit_util::run_all_adhoc_tasks(); // Confirm the modules have been deleted. list($insql, $assignids) = $DB->get_in_or_equal([$assign0->cmid, $assign1->cmid, $assign2->cmid]); $cmcount = $DB->count_records_select('course_modules', 'id ' . $insql, $assignids); $this->assertEmpty($cmcount); // Confirm other modules in section 0 still remain. $this->assertEquals(1, $DB->count_records('course_modules', ['id' => $assign3->cmid])); // Confirm that events were generated for all 3 of the modules. $events = $sink->get_events(); $sink->close(); $count = 0; while (!empty($events)) { $event = array_pop($events); if ($event instanceof \core\event\course_module_deleted && in_array($event->objectid, [$assign0->cmid, $assign1->cmid, $assign2->cmid])) { $count++; } } $this->assertEquals(3, $count); }
/** * Deletes a section * * Do not call this function directly, instead call {@link course_delete_section()} * * @param int|stdClass|section_info $section * @param bool $forcedeleteifnotempty if set to false section will not be deleted if it has modules in it. * @return bool whether section was deleted */ public function delete_section($section, $forcedeleteifnotempty = false) { global $DB; if (!$this->uses_sections()) { // Not possible to delete section if sections are not used. return false; } if (!is_object($section)) { $section = $DB->get_record('course_sections', array('course' => $this->get_courseid(), 'section' => $section), 'id,section,sequence,summary'); } if (!$section || !$section->section) { // Not possible to delete 0-section. return false; } if (!$forcedeleteifnotempty && (!empty($section->sequence) || !empty($section->summary))) { return false; } $course = $this->get_course(); // Remove the marker if it points to this section. if ($section->section == $course->marker) { course_set_marker($course->id, 0); } $lastsection = $DB->get_field_sql('SELECT max(section) from {course_sections} WHERE course = ?', array($course->id)); // Find out if we need to descrease the 'numsections' property later. $courseformathasnumsections = array_key_exists('numsections', $this->get_format_options()); $decreasenumsections = $courseformathasnumsections && $section->section <= $course->numsections; // Move the section to the end. move_section_to($course, $section->section, $lastsection, true); // Delete all modules from the section. foreach (preg_split('/,/', $section->sequence, -1, PREG_SPLIT_NO_EMPTY) as $cmid) { course_delete_module($cmid); } // Delete section and it's format options. $DB->delete_records('course_format_options', array('sectionid' => $section->id)); $DB->delete_records('course_sections', array('id' => $section->id)); rebuild_course_cache($course->id, true); // Descrease 'numsections' if needed. if ($decreasenumsections) { $this->update_course_format_options(array('numsections' => $course->numsections - 1)); } return true; }
/** * Called after the mod has set itself up, to finish off any course module settings * (set instance id, add to correct section, set visibility, etc.) and send the response * * @param int $instanceid id returned by the mod when it was created */ protected function finish_setup_course_module($instanceid) { global $DB, $USER; if (!$instanceid) { // Something has gone wrong - undo everything we can. course_delete_module($this->cm->id); throw new moodle_exception('errorcreatingactivity', 'moodle', '', $this->module->name); } // Note the section visibility $visible = get_fast_modinfo($this->course)->get_section_info($this->section)->visible; $DB->set_field('course_modules', 'instance', $instanceid, array('id' => $this->cm->id)); // Rebuild the course cache after update action rebuild_course_cache($this->course->id, true); $this->course->modinfo = null; // Otherwise we will just get the old version back again. $sectionid = course_add_cm_to_section($this->course, $this->cm->id, $this->section); set_coursemodule_visible($this->cm->id, $visible); if (!$visible) { $DB->set_field('course_modules', 'visibleold', 1, array('id' => $this->cm->id)); } // retrieve the final info about this module. $info = get_fast_modinfo($this->course); if (!isset($info->cms[$this->cm->id])) { // The course module has not been properly created in the course - undo everything. course_delete_module($this->cm->id); throw new moodle_exception('errorcreatingactivity', 'moodle', '', $this->module->name); } $mod = $info->get_cm($this->cm->id); $mod->groupmodelink = $this->cm->groupmodelink; $mod->groupmode = $this->cm->groupmode; // Trigger mod_created event with information about this module. $eventdata = new stdClass(); $eventdata->modulename = $mod->modname; $eventdata->name = $mod->name; $eventdata->cmid = $mod->id; $eventdata->courseid = $this->course->id; $eventdata->userid = $USER->id; events_trigger('mod_created', $eventdata); add_to_log($this->course->id, "course", "add mod", "../mod/{$mod->modname}/view.php?id={$mod->id}", "{$mod->modname} {$instanceid}"); add_to_log($this->course->id, $mod->modname, "add", "view.php?id={$mod->id}", "{$instanceid}", $mod->id); $this->send_response($mod); }