function ma_move_execute($modids, $post) { $section_id = -1; foreach ($post as $key => $val) { if ($key == 'section') { $section = decode_array($val); $section_id = $section['id']; } } if ($section_id == -1) { return; } $section = get_record("course_sections", "id", $section_id); $message = ""; if ($section) { foreach ($modids as $modid) { $cm = get_record("course_modules", "id", $modid); if (!moveto_module($cm, $section)) { $message .= "Could not move module {$modid}, "; } } } else { $message = "No sections were selected"; } return $message; }
// restored copy of the module $newcmid = null; $tasks = $rc->get_plan()->get_tasks(); foreach ($tasks as $task) { if (is_subclass_of($task, 'restore_activity_task')) { if ($task->get_old_contextid() == $cmcontext->id) { $newcmid = $task->get_moduleid(); break; } } } // if we know the cmid of the new course module, let us move it // right below the original one. otherwise it will stay at the // end of the section if ($newcmid) { $newcm = get_coursemodule_from_id('', $newcmid, $course->id, true, MUST_EXIST); moveto_module($newcm, $section, $cm); moveto_module($cm, $section, $newcm); } $rc->destroy(); if (empty($CFG->keeptempdirectoriesonbackup)) { fulldelete($backupbasepath); } echo $output->header(); if ($newcmid) { echo $output->confirm(get_string('duplicatesuccess', 'core', $a), new single_button(new moodle_url('/course/modedit.php', array('update' => $newcmid, 'sr' => $sectionreturn)), get_string('duplicatecontedit'), 'get'), new single_button(course_get_url($course, $cm->sectionnum, array('sr' => $sectionreturn)), get_string('duplicatecontcourse'), 'get')); } else { echo $output->notification(get_string('duplicatesuccess', 'core', $a), 'notifysuccess'); echo $output->continue_button(course_get_url($course, $cm->sectionnum, array('sr' => $sectionreturn))); } echo $output->footer();
/** * Moves the section content to the parent section and deletes it * * Moves all activities and subsections to the parent section (section 0 * can never be deleted) * * @param section_info $section */ protected function mergeup_section($section) { global $DB; if (!$section->section) { // seciton 0 does not have parent return; } // move all modules and activities from this section to parent $modinfo = get_fast_modinfo($this->courseid); $allsections = $modinfo->get_section_info_all(); $subsections = $this->get_subsections($section); $parent = $modinfo->get_section_info($section->parent); if (!empty($modinfo->sections[$section->section])) { foreach ($modinfo->sections[$section->section] as $cmid) { moveto_module($modinfo->get_cm($cmid), $parent); } } foreach ($subsections as $subsection) { $this->update_section_format_options(array('id' => $subsection->id, 'parent' => $parent->section)); } if ($this->get_course()->marker == $section->section) { course_set_marker($this->courseid, 0); } // move the section to be removed to the end (this will re-number other sections) $this->move_section($section->section, 0); // delete it completely $params = array('courseid' => $this->courseid, 'sectionid' => $section->id); $transaction = $DB->start_delegated_transaction(); $DB->delete_records('course_format_options', $params); $DB->delete_records('course_sections', array('id' => $section->id)); $transaction->allow_commit(); rebuild_course_cache($this->courseid, true); }
/** * Make sure that current active activity is in section 0 * * All other activities are moved to section 1 that will be displayed as 'Orphaned'. * It may be needed after the course format was changed or activitytype in * course settings has been changed. * * @return null|cm_info current activity */ public function reorder_activities() { course_create_sections_if_missing($this->courseid, array(0, 1)); foreach ($this->get_sections() as $sectionnum => $section) { if ($sectionnum && $section->visible || !$sectionnum && !$section->visible) { // Make sure that 0 section is visible and all others are hidden. set_section_visible($this->courseid, $sectionnum, $sectionnum == 0); } } $modinfo = get_fast_modinfo($this->courseid); // Find the current activity (first activity with the specified type in all course activities). $activitytype = $this->get_activitytype(); $activity = null; if (!empty($activitytype)) { foreach ($modinfo->sections as $sectionnum => $cmlist) { foreach ($cmlist as $cmid) { if ($modinfo->cms[$cmid]->modname === $activitytype) { $activity = $modinfo->cms[$cmid]; break 2; } } } } // Make sure the current activity is in the 0-section. if ($activity && $activity->sectionnum != 0) { moveto_module($activity, $modinfo->get_section_info(0)); // Cache was reset so get modinfo again. $modinfo = get_fast_modinfo($this->courseid); } // Move all other activities into section 1 (the order must be kept). $hasvisibleactivities = false; $firstorphanedcm = null; foreach ($modinfo->sections as $sectionnum => $cmlist) { if ($sectionnum && !empty($cmlist) && $firstorphanedcm === null) { $firstorphanedcm = reset($cmlist); } foreach ($cmlist as $cmid) { if ($sectionnum > 1) { moveto_module($modinfo->get_cm($cmid), $modinfo->get_section_info(1)); } else { if (!$hasvisibleactivities && $sectionnum == 1 && $modinfo->get_cm($cmid)->visible) { $hasvisibleactivities = true; } } } } if (!empty($modinfo->sections[0])) { foreach ($modinfo->sections[0] as $cmid) { if (!$activity || $cmid != $activity->id) { moveto_module($modinfo->get_cm($cmid), $modinfo->get_section_info(1), $firstorphanedcm); } } } if ($hasvisibleactivities) { set_section_visible($this->courseid, 1, false); } return $activity; }
/** * Duplicate a module on the course. * * @param object $course The course * @param object $cm The course module to duplicate * @throws moodle_exception if the plugin doesn't support duplication * @return Object containing: * - fullcontent: The HTML markup for the created CM * - cmid: The CMID of the newly created CM * - redirect: Whether to trigger a redirect following this change */ function mod_duplicate_activity($course, $cm, $sr = null) { global $CFG, $USER, $PAGE, $DB; require_once $CFG->dirroot . '/backup/util/includes/backup_includes.php'; require_once $CFG->dirroot . '/backup/util/includes/restore_includes.php'; require_once $CFG->libdir . '/filelib.php'; $a = new stdClass(); $a->modtype = get_string('modulename', $cm->modname); $a->modname = format_string($cm->name); if (!plugin_supports('mod', $cm->modname, FEATURE_BACKUP_MOODLE2)) { throw new moodle_exception('duplicatenosupport', 'error'); } // backup the activity $bc = new backup_controller(backup::TYPE_1ACTIVITY, $cm->id, backup::FORMAT_MOODLE, backup::INTERACTIVE_NO, backup::MODE_IMPORT, $USER->id); $backupid = $bc->get_backupid(); $backupbasepath = $bc->get_plan()->get_basepath(); $bc->execute_plan(); $bc->destroy(); // restore the backup immediately $rc = new restore_controller($backupid, $course->id, backup::INTERACTIVE_NO, backup::MODE_IMPORT, $USER->id, backup::TARGET_CURRENT_ADDING); $cmcontext = context_module::instance($cm->id); if (!$rc->execute_precheck()) { $precheckresults = $rc->get_precheck_results(); if (is_array($precheckresults) && !empty($precheckresults['errors'])) { if (empty($CFG->keeptempdirectoriesonbackup)) { fulldelete($backupbasepath); } } } $rc->execute_plan(); // now a bit hacky part follows - we try to get the cmid of the newly // restored copy of the module $newcmid = null; $tasks = $rc->get_plan()->get_tasks(); foreach ($tasks as $task) { error_log("Looking at a task"); if (is_subclass_of($task, 'restore_activity_task')) { error_log("Looking at a restore_activity_task task"); if ($task->get_old_contextid() == $cmcontext->id) { error_log("Contexts match"); $newcmid = $task->get_moduleid(); break; } } } // if we know the cmid of the new course module, let us move it // right below the original one. otherwise it will stay at the // end of the section if ($newcmid) { $info = get_fast_modinfo($course); $newcm = $info->get_cm($newcmid); $section = $DB->get_record('course_sections', array('id' => $cm->section, 'course' => $cm->course)); moveto_module($newcm, $section, $cm); moveto_module($cm, $section, $newcm); // Trigger course module created event. We can trigger the event only if we know the newcmid. $event = \core\event\course_module_created::create_from_cm($newcm); $event->trigger(); } rebuild_course_cache($cm->course); $rc->destroy(); if (empty($CFG->keeptempdirectoriesonbackup)) { fulldelete($backupbasepath); } $resp = new stdClass(); if ($newcm) { $courserenderer = $PAGE->get_renderer('core', 'course'); $completioninfo = new completion_info($course); $modulehtml = $courserenderer->course_section_cm($course, $completioninfo, $newcm, null, array()); $resp->fullcontent = $courserenderer->course_section_cm_list_item($course, $completioninfo, $newcm, $sr); $resp->cmid = $newcm->id; } else { // Trigger a redirect $resp->redirect = true; } return $resp; }
/** * Tests moving a module around in the same section. moveto_module() * is called this way in modduplicate. */ public function test_moveto_module_in_same_section() { global $DB; $this->resetAfterTest(true); $course = $this->getDataGenerator()->create_course(array('numsections' => 3), array('createsections' => true)); $page = $this->getDataGenerator()->create_module('page', array('course' => $course->id)); $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id)); // Simulate inconsistent visible/visibleold values (MDL-38713). $cm = $DB->get_record('course_modules', array('id' => $page->cmid), '*', MUST_EXIST); $cm->visible = 0; $cm->visibleold = 1; $DB->update_record('course_modules', $cm); $modinfo = get_fast_modinfo($course); $forumcm = $modinfo->cms[$forum->cmid]; $pagecm = $modinfo->cms[$page->cmid]; // Verify that page is hidden. $this->assertEquals($pagecm->visible, 0); // Verify section 0 is where all mods added. $section = $modinfo->get_section_info(0); $this->assertEquals($section->id, $forumcm->section); $this->assertEquals($section->id, $pagecm->section); // Move the page inside the hidden section. Make sure it is hidden. $this->assertEquals(0, moveto_module($pagecm, $section, $forumcm)); // Double check that the the page is still hidden. $modinfo = get_fast_modinfo($course); $pagecm = $modinfo->cms[$page->cmid]; $this->assertEquals($pagecm->visible, 0); }
$DB->update_record('course_modules', $cm); rebuild_course_cache($cm->course); } break; case 'move': require_capability('moodle/course:manageactivities', $modcontext); if (!($section = $DB->get_record('course_sections', array('course' => $course->id, 'section' => $sectionid)))) { throw new moodle_exception('AJAX commands.php: Bad section ID ' . $sectionid); } 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' => $isvisible)); break; case 'gettitle': require_capability('moodle/course:manageactivities', $modcontext); $cm = get_coursemodule_from_id('', $id, 0, false, MUST_EXIST); $module = new stdClass(); $module->id = $cm->instance; // Don't pass edit strings through multilang filters - we need the entire string echo json_encode(array('instancename' => $cm->name)); break; case 'updatetitle': require_capability('moodle/course:manageactivities', $modcontext); require_once $CFG->libdir . '/gradelib.php'; $cm = get_coursemodule_from_id('', $id, 0, false, MUST_EXIST); $module = new stdClass();
/** * Tests the filter_users() function. */ public function test_filter_users() { global $CFG, $DB; require_once $CFG->dirroot . '/course/lib.php'; $this->resetAfterTest(); $CFG->enableavailability = true; // Create a course with 2 sections and 2 pages and 3 users. // Availability is set up initially on the 'page/section 2' items. $generator = $this->getDataGenerator(); $course = $generator->create_course(array('numsections' => 2), array('createsections' => true)); $u1 = $generator->create_user(); $u2 = $generator->create_user(); $u3 = $generator->create_user(); $studentroleid = $DB->get_field('role', 'id', array('shortname' => 'student'), MUST_EXIST); $allusers = array($u1->id => $u1, $u2->id => $u2, $u3->id => $u3); $generator->enrol_user($u1->id, $course->id, $studentroleid); $generator->enrol_user($u2->id, $course->id, $studentroleid); $generator->enrol_user($u3->id, $course->id, $studentroleid); // Page 2 allows access to users 2 and 3, while section 2 allows access // to users 1 and 2. $pagegen = $generator->get_plugin_generator('mod_page'); $page = $pagegen->create_instance(array('course' => $course)); $page2 = $pagegen->create_instance(array('course' => $course, 'availability' => '{"op":"|","show":true,"c":[{"type":"mock","filter":[' . $u2->id . ',' . $u3->id . ']}]}')); $modinfo = get_fast_modinfo($course); $section = $modinfo->get_section_info(1); $section2 = $modinfo->get_section_info(2); $DB->set_field('course_sections', 'availability', '{"op":"|","show":true,"c":[{"type":"mock","filter":[' . $u1->id . ',' . $u2->id . ']}]}', array('id' => $section2->id)); moveto_module($modinfo->get_cm($page2->cmid), $section2); // With no restrictions, returns full list. $info = new info_module($modinfo->get_cm($page->cmid)); $this->assertEquals(array($u1->id, $u2->id, $u3->id), array_keys($info->filter_user_list($allusers))); // Set an availability restriction in database for section 1. // For the section we set it so it doesn't support filters; for the // module we have a filter. $DB->set_field('course_sections', 'availability', '{"op":"|","show":true,"c":[{"type":"mock","a":false}]}', array('id' => $section->id)); $DB->set_field('course_modules', 'availability', '{"op":"|","show":true,"c":[{"type":"mock","filter":[' . $u3->id . ']}]}', array('id' => $page->cmid)); rebuild_course_cache($course->id, true); $modinfo = get_fast_modinfo($course); // Now it should work (for the module). $info = new info_module($modinfo->get_cm($page->cmid)); $this->assertEquals(array($u3->id), array_keys($info->filter_user_list($allusers))); $info = new info_section($modinfo->get_section_info(1)); $this->assertEquals(array($u1->id, $u2->id, $u3->id), array_keys($info->filter_user_list($allusers))); // With availability disabled, module returns full list too. $CFG->enableavailability = false; $info = new info_module($modinfo->get_cm($page->cmid)); $this->assertEquals(array($u1->id, $u2->id, $u3->id), array_keys($info->filter_user_list($allusers))); // Check the other section... $CFG->enableavailability = true; $info = new info_section($modinfo->get_section_info(2)); $this->assertEquals(array($u1->id, $u2->id), array_keys($info->filter_user_list($allusers))); // And the module in that section - which has combined the section and // module restrictions. $info = new info_module($modinfo->get_cm($page2->cmid)); $this->assertEquals(array($u2->id), array_keys($info->filter_user_list($allusers))); // If the students have viewhiddenactivities, they get past the module // restriction. role_change_permission($studentroleid, context_module::instance($page2->cmid), 'moodle/course:viewhiddenactivities', CAP_ALLOW); $expected = array($u1->id, $u2->id); $this->assertEquals($expected, array_keys($info->filter_user_list($allusers))); // If they have viewhiddensections, they also get past the section // restriction. role_change_permission($studentroleid, context_course::instance($course->id), 'moodle/course:viewhiddensections', CAP_ALLOW); $expected = array($u1->id, $u2->id, $u3->id); $this->assertEquals($expected, array_keys($info->filter_user_list($allusers))); }
$newsection = $dest->add_section(); $id = $newsection['sectionid']; } else { $id = $info[1]; } // ensure that the destination section does exists if (!($section = $DB->get_record('course_sections', array('id' => (int) $id)))) { print_error('sectionnotcreatedorexisting', 'mod_subpage', "{$CFG->wwwroot}/mod/subpage/view.php?id={$cmid}"); } foreach ($cmids as $id) { if (!($cm = get_coursemodule_from_id('', $id))) { print_error('modulenotfound', 'mod_subpage', "{$CFG->wwwroot}/mod/subpage/view.php?id={$cmid}"); } // no reason to move if in the same section if ($cm->section !== $section->id) { moveto_module($cm, $section); } } rebuild_course_cache($course->id, true); } // return to original subpage view if (!$dest) { redirect("{$CFG->wwwroot}/course/view.php?id=" . $subpage->get_course()->id . "#section-{$section->section}"); } else { redirect("{$CFG->wwwroot}/mod/subpage/view.php?id=" . $dest->get_course_module()->id . "#section-{$section->section}"); } exit; } echo $OUTPUT->header(); // Course wrapper start. echo html_writer::start_tag('div', array('class' => 'course-content'));
} else { $newlocation = ''; } if (empty($newlocation)) { $newlocation = $DB->get_field_sql("SELECT MAX(pageorder) FROM {subpage_sections} WHERE subpageid = ?", array($subpage->get_subpage()->id)); } $subpage->move_section($thissection->id, $newlocation); } } else { if ($action == 'moveactivity') { // Now cleanup and check vars. if (strpos($thisid, 'module-') === 0) { $thisid = str_replace('module-', '', $thisid); $thisid = get_coursemodule_from_id(false, $thisid, $subpage->get_course()->id, false, MUST_EXIST); } else { $thisid = ''; } if (strpos($nextid, 'module-') === 0) { $nextid = str_replace('module-', '', $nextid); $nextid = get_coursemodule_from_id(false, $nextid, $subpage->get_course()->id, false, MUST_EXIST); } else { $nextid = ''; } if (strpos($section, 'section-') === 0) { // Section must be provided - if not then can't move. $section = str_replace('section-', '', $section); $section = $DB->get_record('course_sections', array('course' => $subpage->get_course()->id, 'section' => $section), '*', MUST_EXIST); moveto_module($thisid, $section, $nextid); } } }
/** * Api to duplicate a module. * * @param object $course course object. * @param object $cm course module object to be duplicated. * @since Moodle 2.8 * * @throws Exception * @throws coding_exception * @throws moodle_exception * @throws restore_controller_exception * * @return cm_info|null cminfo object if we sucessfully duplicated the mod and found the new cm. */ function duplicate_module($course, $cm) { global $CFG, $DB, $USER; require_once $CFG->dirroot . '/backup/util/includes/backup_includes.php'; require_once $CFG->dirroot . '/backup/util/includes/restore_includes.php'; require_once $CFG->libdir . '/filelib.php'; $a = new stdClass(); $a->modtype = get_string('modulename', $cm->modname); $a->modname = format_string($cm->name); if (!plugin_supports('mod', $cm->modname, FEATURE_BACKUP_MOODLE2)) { throw new moodle_exception('duplicatenosupport', 'error', '', $a); } // Backup the activity. $bc = new backup_controller(backup::TYPE_1ACTIVITY, $cm->id, backup::FORMAT_MOODLE, backup::INTERACTIVE_NO, backup::MODE_IMPORT, $USER->id); $backupid = $bc->get_backupid(); $backupbasepath = $bc->get_plan()->get_basepath(); $bc->execute_plan(); $bc->destroy(); // Restore the backup immediately. $rc = new restore_controller($backupid, $course->id, backup::INTERACTIVE_NO, backup::MODE_IMPORT, $USER->id, backup::TARGET_CURRENT_ADDING); $cmcontext = context_module::instance($cm->id); if (!$rc->execute_precheck()) { $precheckresults = $rc->get_precheck_results(); if (is_array($precheckresults) && !empty($precheckresults['errors'])) { if (empty($CFG->keeptempdirectoriesonbackup)) { fulldelete($backupbasepath); } } } $rc->execute_plan(); // Now a bit hacky part follows - we try to get the cmid of the newly // restored copy of the module. $newcmid = null; $tasks = $rc->get_plan()->get_tasks(); foreach ($tasks as $task) { if (is_subclass_of($task, 'restore_activity_task')) { if ($task->get_old_contextid() == $cmcontext->id) { $newcmid = $task->get_moduleid(); break; } } } // If we know the cmid of the new course module, let us move it // right below the original one. otherwise it will stay at the // end of the section. if ($newcmid) { $info = get_fast_modinfo($course); $newcm = $info->get_cm($newcmid); $section = $DB->get_record('course_sections', array('id' => $cm->section, 'course' => $cm->course)); moveto_module($newcm, $section, $cm); moveto_module($cm, $section, $newcm); // Update calendar events with the duplicated module. $refresheventsfunction = $newcm->modname . '_refresh_events'; if (function_exists($refresheventsfunction)) { call_user_func($refresheventsfunction, $newcm->course); } // Trigger course module created event. We can trigger the event only if we know the newcmid. $event = \core\event\course_module_created::create_from_cm($newcm); $event->trigger(); } rebuild_course_cache($cm->course); $rc->destroy(); if (empty($CFG->keeptempdirectoriesonbackup)) { fulldelete($backupbasepath); } return isset($newcm) ? $newcm : null; }
$data_progress = new stdClass(); $data_progress->current = 0; $data_progress->size = $progress_bar_elements; $k = 0; $pbar->update_full(40, get_string('progress_counter', 'format_onetopic', $data_progress)); foreach ($section_mods as $modnumber) { $k++; $mod = $modinfo->cms[$modnumber]; $cm = get_coursemodule_from_id('', $mod->id, 0, true, MUST_EXIST); $modcontext = context_module::instance($cm->id); if (has_capability('moodle/course:manageactivities', $modcontext)) { // Duplicate the module. $newcm = duplicate_module($course, $cm); //Move new module to new section if ($newcm && is_object($newcm)) { moveto_module($newcm, $new_sectioninfo); } } $data_progress->current = $k; $percent = 40 + $k / $progress_bar_elements * 60; $pbar->update_full($percent, get_string('progress_counter', 'format_onetopic', $data_progress)); } } } else { $pbar->update_full(100, get_string('progress_full', 'format_onetopic')); } $section_togo = $num_newsection; } else { $section_togo = $section; echo get_string('error_nosectioninfo', 'format_onetopic'); echo $OUTPUT->continue_button(course_get_url($course, $section));
public function test_move_module_in_course() { global $DB; $this->resetAfterTest(true); // Setup fixture $course = $this->getDataGenerator()->create_course(array('numsections' => 5), array('createsections' => true)); $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id)); $cms = get_fast_modinfo($course)->get_cms(); $cm = reset($cms); $newsection = get_fast_modinfo($course)->get_section_info(3); $oldsectionid = $cm->section; // Perform the move moveto_module($cm, $newsection); // reset of get_fast_modinfo is usually called the code calling moveto_module so call it here get_fast_modinfo(0, 0, true); $cms = get_fast_modinfo($course)->get_cms(); $cm = reset($cms); // Check that the cached modinfo contains the correct section info $modinfo = get_fast_modinfo($course); $this->assertTrue(empty($modinfo->sections[0])); $this->assertFalse(empty($modinfo->sections[3])); // Check that the old section's sequence no longer contains this ID $oldsection = $DB->get_record('course_sections', array('id' => $oldsectionid)); $oldsequences = explode(',', $newsection->sequence); $this->assertFalse(in_array($cm->id, $oldsequences)); // Check that the new section's sequence now contains this ID $newsection = $DB->get_record('course_sections', array('id' => $newsection->id)); $newsequences = explode(',', $newsection->sequence); $this->assertTrue(in_array($cm->id, $newsequences)); // Check that the section number has been changed in the cm $this->assertEquals($newsection->id, $cm->section); // Perform a second move as some issues were only seen on the second move $newsection = get_fast_modinfo($course)->get_section_info(2); $oldsectionid = $cm->section; $result = moveto_module($cm, $newsection); $this->assertTrue($result); // reset of get_fast_modinfo is usually called the code calling moveto_module so call it here get_fast_modinfo(0, 0, true); $cms = get_fast_modinfo($course)->get_cms(); $cm = reset($cms); // Check that the cached modinfo contains the correct section info $modinfo = get_fast_modinfo($course); $this->assertTrue(empty($modinfo->sections[0])); $this->assertFalse(empty($modinfo->sections[2])); // Check that the old section's sequence no longer contains this ID $oldsection = $DB->get_record('course_sections', array('id' => $oldsectionid)); $oldsequences = explode(',', $newsection->sequence); $this->assertFalse(in_array($cm->id, $oldsequences)); // Check that the new section's sequence now contains this ID $newsection = $DB->get_record('course_sections', array('id' => $newsection->id)); $newsequences = explode(',', $newsection->sequence); $this->assertTrue(in_array($cm->id, $newsequences)); }
/** * perform the actual deletion of the selected course modules * @param array $modules * @param int $target ID of the section to move to */ function perform_moveto($modules, $target) { global $CFG, $DB; require_once $CFG->dirroot . '/course/lib.php'; foreach ($modules as $cm_record) { if (!($cm = get_coursemodule_from_id('', $cm_record->id, 0, true))) { print_error('invalidcoursemodule'); } // verify target if (!($section = $DB->get_record('course_sections', array('course' => $cm->course, 'section' => $target)))) { print_error('sectionnotexist', 'block_massaction'); } $context = context_course::instance($section->course); require_capability('moodle/course:manageactivities', $context); moveto_module($cm_record, $section); } }
// normal moveto if (!($beforecm = get_record("course_modules", "id", $moveto))) { error("The destination course module doesn't exist"); } if (!($section = get_record("course_sections", "id", $beforecm->section))) { error("This section doesn't exist"); } } require_login($section->course); // needed to setup proper $COURSE $context = get_context_instance(CONTEXT_COURSE, $section->course); require_capability('moodle/course:manageactivities', $context); if (!ismoving($section->course)) { error("You need to copy something first!"); } moveto_module($cm, $section, $beforecm); unset($USER->activitycopy); unset($USER->activitycopycourse); unset($USER->activitycopyname); rebuild_course_cache($section->course); if (SITEID == $section->course) { redirect($CFG->wwwroot); } else { redirect("view.php?id={$section->course}#section-{$sectionreturn}"); } } else { if (!empty($indent) and confirm_sesskey()) { $id = required_param('id', PARAM_INT); if (!($cm = get_record("course_modules", "id", $id))) { error("This course module doesn't exist"); }
/** * If modules are attached to a post they must be moved to timeline section * (normally section number 1). * * @param type $courseid * @param type $cmsequence * @return type */ private function check_and_move_module($courseid, $cmsequence) { $modinfo = get_fast_modinfo($courseid); $section = $modinfo->get_section_info(FORMAT_SOCIALWALL_TIMELINESECTION); $cmids = explode(',', $cmsequence); foreach ($cmids as $cmid) { $mod = $modinfo->get_cm($cmid); moveto_module($mod, $section); } return $cmsequence; }
/** * Tests the filter_user_list() and get_user_list_sql() functions. */ public function test_filter_user_list() { global $CFG, $DB; require_once $CFG->dirroot . '/course/lib.php'; $this->resetAfterTest(); $CFG->enableavailability = true; // Create a course with 2 sections and 2 pages and 3 users. // Availability is set up initially on the 'page/section 2' items. $generator = $this->getDataGenerator(); $course = $generator->create_course(array('numsections' => 2), array('createsections' => true)); $u1 = $generator->create_user(); $u2 = $generator->create_user(); $u3 = $generator->create_user(); $allusers = array($u1->id => $u1, $u2->id => $u2, $u3->id => $u3); $generator->enrol_user($u1->id, $course->id); $generator->enrol_user($u2->id, $course->id); $generator->enrol_user($u3->id, $course->id); $pagegen = $generator->get_plugin_generator('mod_page'); $page = $pagegen->create_instance(array('course' => $course)); $page2 = $pagegen->create_instance(array('course' => $course, 'availability' => '{"op":"|","show":true,"c":[{"type":"mock","filter":[' . $u2->id . ',' . $u3->id . ']}]}')); $modinfo = get_fast_modinfo($course); $section = $modinfo->get_section_info(1); $section2 = $modinfo->get_section_info(2); $DB->set_field('course_sections', 'availability', '{"op":"|","show":true,"c":[{"type":"mock","filter":[' . $u1->id . ',' . $u2->id . ']}]}', array('id' => $section2->id)); moveto_module($modinfo->get_cm($page2->cmid), $section2); // With no restrictions, returns full list. $info = new info_module($modinfo->get_cm($page->cmid)); $this->assertEquals(array($u1->id, $u2->id, $u3->id), array_keys($info->filter_user_list($allusers))); $this->assertEquals(array('', array()), $info->get_user_list_sql(true)); // Set an availability restriction in database for section 1. // For the section we set it so it doesn't support filters; for the // module we have a filter. $DB->set_field('course_sections', 'availability', '{"op":"|","show":true,"c":[{"type":"mock","a":false}]}', array('id' => $section->id)); $DB->set_field('course_modules', 'availability', '{"op":"|","show":true,"c":[{"type":"mock","filter":[' . $u3->id . ']}]}', array('id' => $page->cmid)); rebuild_course_cache($course->id, true); $modinfo = get_fast_modinfo($course); // Now it should work (for the module). $info = new info_module($modinfo->get_cm($page->cmid)); $expected = array($u3->id); $this->assertEquals($expected, array_keys($info->filter_user_list($allusers))); list($sql, $params) = $info->get_user_list_sql(); $result = $DB->get_fieldset_sql($sql, $params); sort($result); $this->assertEquals($expected, $result); $info = new info_section($modinfo->get_section_info(1)); $this->assertEquals(array($u1->id, $u2->id, $u3->id), array_keys($info->filter_user_list($allusers))); $this->assertEquals(array('', array()), $info->get_user_list_sql(true)); // With availability disabled, module returns full list too. $CFG->enableavailability = false; $info = new info_module($modinfo->get_cm($page->cmid)); $this->assertEquals(array($u1->id, $u2->id, $u3->id), array_keys($info->filter_user_list($allusers))); $this->assertEquals(array('', array()), $info->get_user_list_sql(true)); // Check the other section... $CFG->enableavailability = true; $info = new info_section($modinfo->get_section_info(2)); $expected = array($u1->id, $u2->id); $this->assertEquals($expected, array_keys($info->filter_user_list($allusers))); list($sql, $params) = $info->get_user_list_sql(true); $result = $DB->get_fieldset_sql($sql, $params); sort($result); $this->assertEquals($expected, $result); // And the module in that section - which has combined the section and // module restrictions. $info = new info_module($modinfo->get_cm($page2->cmid)); $expected = array($u2->id); $this->assertEquals($expected, array_keys($info->filter_user_list($allusers))); list($sql, $params) = $info->get_user_list_sql(true); $result = $DB->get_fieldset_sql($sql, $params); sort($result); $this->assertEquals($expected, $result); }
update_record('course_modules', $mod); break; case 'move': if (!($section = get_record('course_sections', 'course', $course->id, 'section', $sectionid))) { error_log('AJAX commands.php: Bad section ID ' . $sectionid); die; } if ($beforeid > 0) { $beforemod = get_record('course_modules', 'id', $beforeid); } else { $beforemod = NULL; } if (debugging('', DEBUG_DEVELOPER)) { error_log(serialize($beforemod)); } moveto_module($mod, $section, $beforemod); break; } rebuild_course_cache($course->id); break; case 'course': switch ($field) { case 'marker': $newcourse = new object(); $newcourse->id = $course->id; $newcourse->marker = $value; if (!update_record('course', $newcourse)) { error_log('AJAX commands.php: Failed to update course marker for course ' . $newcourse->id); die; } break;
/** * Tests the get_forum_list() function. This funcion is the meat of the web service but we cannot * check it as a web service so we just call the function. */ public function test_forumlistapi() { global $DB; $this->resetAfterTest(true); // Create course. $record = new stdClass(); $record->shortname = 'testcourse'; $course = self::getDataGenerator()->create_course($record); // Create a teacher user and enrol them onto the course. $record = array(); $record['username'] = '******'; $teacher = self::getDataGenerator()->create_user($record); $roleid = $DB->get_field('role', 'id', array('shortname' => 'teacher')); self::getDataGenerator()->enrol_user($teacher->id, $course->id, $roleid); // Create a student user and enrol them onto the course. $record['username'] = '******'; $student = self::getDataGenerator()->create_user($record); $roleid = $DB->get_field('role', 'id', array('shortname' => 'student')); self::getDataGenerator()->enrol_user($student->id, $course->id, $roleid); // Create forum A. $record = new stdClass(); $record->course = $course->id; $record->name = 'Forum A'; $foruma = self::getDataGenerator()->create_module('forumng', $record); // Needed later when moving forums to specific sections. course_create_sections_if_missing($course->id, array(1)); $modinfo = get_fast_modinfo($course); $mod = $modinfo->get_cm($foruma->cmid); $sectionzero = $modinfo->get_section_info(0, MUST_EXIST); $sectionone = $modinfo->get_section_info(1, MUST_EXIST); // Create forum B. $record = new stdClass(); $record->course = $course->id; $record->name = 'Forum B'; $forumb = self::getDataGenerator()->create_module('forumng', $record); // Create forum C. $record = new stdClass(); $record->course = $course->id; $record->name = 'Forum C'; $forumc = self::getDataGenerator()->create_module('forumng', $record); // Make forum C hidden. set_coursemodule_visible($forumc->cmid, 0); $modinfo = get_fast_modinfo($course); // Move forum A to section 1. $mod = $modinfo->get_cm($foruma->cmid); moveto_module($mod, $sectionone); // Move forum B to section 0. $mod = $modinfo->get_cm($forumb->cmid); moveto_module($mod, $sectionzero); // Move forum C to section 1. $mod = $modinfo->get_cm($forumc->cmid); moveto_module($mod, $sectionone); // Student starts discussion in forum A. $record = new stdClass(); $record->course = $course->id; $record->forum = $foruma->id; $record->userid = $student->id; $this->setUser($student); $discussionid = self::getDataGenerator()->get_plugin_generator('mod_forumng')->create_discussion($record); // Teacher starts discussion in forum B. $record = new stdClass(); $record->course = $course->id; $record->forum = $forumb->id; $record->userid = $teacher->id; $this->setUser($teacher); $discussionid = self::getDataGenerator()->get_plugin_generator('mod_forumng')->create_discussion($record); // Call the web service function to get a list of forums for the teacher. $response = mod_forumng_external::get_forum_list($course->shortname, $teacher->username); // There should be 3 forums in the array. $this->assertEquals(3, count($response)); // Check each forum's data. $this->assertEquals('Forum B', $response[0]->name); $this->assertEquals('n', $response[0]->unread); $this->assertEquals('Forum A', $response[1]->name); $this->assertEquals('y', $response[1]->unread); $this->assertEquals('Forum C', $response[2]->name); $this->assertEquals('n', $response[2]->unread); // Call the web service function to get a list of forums for the student. $response = mod_forumng_external::get_forum_list($course->shortname, $student->username); // There should be 2 forums in the array. $this->assertEquals(2, count($response)); // Check each forum's data. $this->assertEquals('Forum B', $response[0]->name); $this->assertEquals('y', $response[0]->unread); $this->assertEquals('Forum A', $response[1]->name); $this->assertEquals('n', $response[1]->unread); // Call the webservice function with invalid username. $wronguser = '******'; try { // If this does not throw an exception then the test fails. $response = mod_forumng_external::get_forum_list($course->shortname, $wronguser); $this->fail(); } catch (moodle_exception $e) { $this->assertEquals(get_string('cannotfinduser', 'error', $wronguser), $e->errorcode); } // Call the webservice function with invalid course. $wrongcourse = 'doesnotexist'; try { // If this does not throw an exception then the test fails. $response = mod_forumng_external::get_forum_list($wrongcourse, $student->username); $this->fail(); } catch (Exception $e) { $this->assertEquals(get_string('cannotfindcourse', 'error'), $e->errorcode); } }
public function test_move_module_in_course() { $this->resetAfterTest(true); // Setup fixture $course = $this->getDataGenerator()->create_course(array('numsections' => 5)); $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id)); $cms = get_fast_modinfo($course)->get_cms(); $cm = reset($cms); course_create_sections_if_missing($course, 3); $section3 = get_fast_modinfo($course)->get_section_info(3); moveto_module($cm, $section3); $modinfo = get_fast_modinfo($course); $this->assertTrue(empty($modinfo->sections[0])); $this->assertFalse(empty($modinfo->sections[3])); }