From 0a3d81c26139ada51c0b9e0bc4be5b55d6e907a7 Mon Sep 17 00:00:00 2001 From: Ankit Agarwal Date: Fri, 13 Jun 2014 13:40:50 +0800 Subject: [PATCH] MDL-45958 courselib: Refactor module duplication code to remove duplication --- course/lib.php | 72 ++++++++++++++++++----------- course/modduplicate.php | 82 +++------------------------------ course/tests/courselib_test.php | 22 +++++++++ 3 files changed, 75 insertions(+), 101 deletions(-) diff --git a/course/lib.php b/course/lib.php index 6c13a7d68b5..c0f714e576a 100644 --- a/course/lib.php +++ b/course/lib.php @@ -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; } /** diff --git a/course/modduplicate.php b/course/modduplicate.php index 72476713468..94e9e00892a 100644 --- a/course/modduplicate.php +++ b/course/modduplicate.php @@ -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( diff --git a/course/tests/courselib_test.php b/course/tests/courselib_test.php index 8f851021a30..216db322cb4 100644 --- a/course/tests/courselib_test.php +++ b/course/tests/courselib_test.php @@ -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); + } + } }