MDL-45958 courselib: Refactor module duplication code to remove duplication

This commit is contained in:
Ankit Agarwal 2014-06-13 13:40:50 +08:00
parent e7ea6b9a24
commit 0a3d81c261
3 changed files with 75 additions and 101 deletions

View File

@ -3418,10 +3418,12 @@ function update_module($moduleinfo) {
}
/**
* Duplicate a module on the course.
* Duplicate a module on the course for ajax.
*
* @see mod_duplicate_module()
* @param object $course The course
* @param object $cm The course module to duplicate
* @param int $sr The section to link back to (used for creating the links)
* @throws moodle_exception if the plugin doesn't support duplication
* @return Object containing:
* - fullcontent: The HTML markup for the created CM
@ -3429,8 +3431,42 @@ function update_module($moduleinfo) {
* - redirect: Whether to trigger a redirect following this change
*/
function mod_duplicate_activity($course, $cm, $sr = null) {
global $CFG, $USER, $PAGE, $DB;
global $PAGE;
$newcm = duplicate_module($course, $cm);
$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;
}
/**
* 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');
@ -3440,10 +3476,10 @@ function mod_duplicate_activity($course, $cm, $sr = null) {
$a->modname = format_string($cm->name);
if (!plugin_supports('mod', $cm->modname, FEATURE_BACKUP_MOODLE2)) {
throw new moodle_exception('duplicatenosupport', 'error');
throw new moodle_exception('duplicatenosupport', 'error', '', $a);
}
// backup the activity
// Backup the activity.
$bc = new backup_controller(backup::TYPE_1ACTIVITY, $cm->id, backup::FORMAT_MOODLE,
backup::INTERACTIVE_NO, backup::MODE_IMPORT, $USER->id);
@ -3455,7 +3491,7 @@ function mod_duplicate_activity($course, $cm, $sr = null) {
$bc->destroy();
// restore the backup immediately
// Restore the backup immediately.
$rc = new restore_controller($backupid, $course->id,
backup::INTERACTIVE_NO, backup::MODE_IMPORT, $USER->id, backup::TARGET_CURRENT_ADDING);
@ -3472,25 +3508,22 @@ function mod_duplicate_activity($course, $cm, $sr = null) {
$rc->execute_plan();
// now a bit hacky part follows - we try to get the cmid of the newly
// restored copy of the module
// 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
// 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
// end of the section.
if ($newcmid) {
$info = get_fast_modinfo($course);
$newcm = $info->get_cm($newcmid);
@ -3506,20 +3539,7 @@ function mod_duplicate_activity($course, $cm, $sr = null) {
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;
return isset($newcm) ? $newcm : null;
}
/**

View File

@ -28,9 +28,6 @@
*/
require_once(dirname(dirname(__FILE__)) . '/config.php');
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');
$cmid = required_param('cmid', PARAM_INT);
$courseid = required_param('course', PARAM_INT);
@ -56,85 +53,20 @@ $PAGE->set_pagelayout('incourse');
$output = $PAGE->get_renderer('core', 'backup');
// Duplicate the module.
$newcm = duplicate_module($course, $cm);
echo $output->header();
$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)) {
$url = course_get_url($course, $cm->sectionnum, array('sr' => $sectionreturn));
print_error('duplicatenosupport', 'error', $url, $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, $courseid,
backup::INTERACTIVE_NO, backup::MODE_IMPORT, $USER->id, backup::TARGET_CURRENT_ADDING);
if (!$rc->execute_precheck()) {
$precheckresults = $rc->get_precheck_results();
if (is_array($precheckresults) && !empty($precheckresults['errors'])) {
if (empty($CFG->keeptempdirectoriesonbackup)) {
fulldelete($backupbasepath);
}
echo $output->header();
echo $output->precheck_notices($precheckresults);
$url = course_get_url($course, $cm->sectionnum, array('sr' => $sectionreturn));
echo $output->continue_button($url);
echo $output->footer();
die();
}
}
$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) {
$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) {
if (!empty($newcm)) {
echo $output->confirm(
get_string('duplicatesuccess', 'core', $a),
new single_button(
new moodle_url('/course/modedit.php', array('update' => $newcmid, 'sr' => $sectionreturn)),
new moodle_url('/course/modedit.php', array('update' => $newcm->id, 'sr' => $sectionreturn)),
get_string('duplicatecontedit'),
'get'),
new single_button(

View File

@ -2477,4 +2477,26 @@ class core_course_courselib_testcase extends advanced_testcase {
$this->assertEventLegacyLogData($expectedlegacydata, $event);
$this->assertEventContextNotUsed($event);
}
/**
* Test duplicate_module()
*/
public function test_duplicate_module() {
$this->setAdminUser();
$this->resetAfterTest();
$course = self::getDataGenerator()->create_course();
$res = self::getDataGenerator()->create_module('resource', array('course' => $course));
$cm = get_coursemodule_from_id('resource', $res->cmid, 0, false, MUST_EXIST);
$newcm = duplicate_module($course, $cm);
// Make sure they are the same, except obvious id changes.
foreach ($cm as $prop => $value) {
if ($prop == 'id' || $prop == 'url' || $prop == 'instance' || $prop == 'added') {
// Ignore obviously different properties.
continue;
}
$this->assertEquals($value, $newcm->$prop);
}
}
}