diff --git a/course/externallib.php b/course/externallib.php index b18c0a454f9..edee81b93f2 100644 --- a/course/externallib.php +++ b/course/externallib.php @@ -883,6 +883,189 @@ class core_course_external extends external_api { ); } + /** + * Returns description of method parameters for import_course + * + * @return external_function_parameters + * @since Moodle 2.4 + */ + public static function import_course_parameters() { + return new external_function_parameters( + array( + 'importfrom' => new external_value(PARAM_INT, 'the id of the course we are importing from'), + 'importto' => new external_value(PARAM_INT, 'the id of the course we are importing to'), + 'deletecontent' => new external_value(PARAM_INT, 'whether to delete the course content where we are importing to (default to 0 = No)', VALUE_DEFAULT, 0), + 'options' => new external_multiple_structure( + new external_single_structure( + array( + 'name' => new external_value(PARAM_ALPHA, 'The backup option name: + "activities" (int) Include course activites (default to 1 that is equal to yes), + "blocks" (int) Include course blocks (default to 1 that is equal to yes), + "filters" (int) Include course filters (default to 1 that is equal to yes)' + ), + 'value' => new external_value(PARAM_RAW, 'the value for the option 1 (yes) or 0 (no)' + ) + ) + ), VALUE_DEFAULT, array() + ), + ) + ); + } + + /** + * Imports a course + * + * @param int $importfrom The id of the course we are importing from + * @param int $importto The id of the course we are importing to + * @param bool $deletecontent Whether to delete the course we are importing to content + * @param array $options List of backup options + * @return null + * @since Moodle 2.4 + */ + public static function import_course($importfrom, $importto, $deletecontent = 0, $options = array()) { + global $CFG, $USER, $DB; + require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php'); + require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php'); + + // Parameter validation. + $params = self::validate_parameters( + self::import_course_parameters(), + array( + 'importfrom' => $importfrom, + 'importto' => $importto, + 'deletecontent' => $deletecontent, + 'options' => $options + ) + ); + + if ($params['deletecontent'] !== 0 and $params['deletecontent'] !== 1) { + throw new moodle_exception('invalidextparam', 'webservice', '', $option['deletecontent']); + } + + // Context validation. + + if (! ($importfrom = $DB->get_record('course', array('id'=>$params['importfrom'])))) { + throw new moodle_exception('invalidcourseid', 'error', '', $params['importfrom']); + } + + if (! ($importto = $DB->get_record('course', array('id'=>$params['importto'])))) { + throw new moodle_exception('invalidcourseid', 'error', '', $params['importto']); + } + + $importfromcontext = context_course::instance($importfrom->id); + self::validate_context($importfromcontext); + + $importtocontext = context_course::instance($importto->id); + self::validate_context($importtocontext); + + $backupdefaults = array( + 'activities' => 1, + 'blocks' => 1, + 'filters' => 1 + ); + + $backupsettings = array(); + + // Check for backup and restore options. + if (!empty($params['options'])) { + foreach ($params['options'] as $option) { + + // Strict check for a correct value (allways 1 or 0, true or false). + $value = clean_param($option['value'], PARAM_INT); + + if ($value !== 0 and $value !== 1) { + throw new moodle_exception('invalidextparam', 'webservice', '', $option['name']); + } + + if (!isset($backupdefaults[$option['name']])) { + throw new moodle_exception('invalidextparam', 'webservice', '', $option['name']); + } + + $backupsettings[$option['name']] = $value; + } + } + + // Capability checking. + + require_capability('moodle/backup:backuptargetimport', $importfromcontext); + require_capability('moodle/restore:restoretargetimport', $importtocontext); + + $bc = new backup_controller(backup::TYPE_1COURSE, $importfrom->id, backup::FORMAT_MOODLE, + backup::INTERACTIVE_NO, backup::MODE_IMPORT, $USER->id); + + foreach ($backupsettings as $name => $value) { + $bc->get_plan()->get_setting($name)->set_value($value); + } + + $backupid = $bc->get_backupid(); + $backupbasepath = $bc->get_plan()->get_basepath(); + + $bc->execute_plan(); + $bc->destroy(); + + // Restore the backup immediately. + + // Check if we must delete the contents of the destination course. + if ($params['deletecontent']) { + $restoretarget = backup::TARGET_EXISTING_DELETING; + } else { + $restoretarget = backup::TARGET_EXISTING_ADDING; + } + + $rc = new restore_controller($backupid, $importto->id, + backup::INTERACTIVE_NO, backup::MODE_IMPORT, $USER->id, $restoretarget); + + foreach ($backupsettings as $name => $value) { + $rc->get_plan()->get_setting($name)->set_value($value); + } + + if (!$rc->execute_precheck()) { + $precheckresults = $rc->get_precheck_results(); + if (is_array($precheckresults) && !empty($precheckresults['errors'])) { + if (empty($CFG->keeptempdirectoriesonbackup)) { + fulldelete($backupbasepath); + } + + $errorinfo = ''; + + foreach ($precheckresults['errors'] as $error) { + $errorinfo .= $error; + } + + if (array_key_exists('warnings', $precheckresults)) { + foreach ($precheckresults['warnings'] as $warning) { + $errorinfo .= $warning; + } + } + + throw new moodle_exception('backupprecheckerrors', 'webservice', '', $errorinfo); + } + } else { + if ($restoretarget == backup::TARGET_EXISTING_DELETING) { + restore_dbops::delete_course_content($importto->id); + } + } + + $rc->execute_plan(); + $rc->destroy(); + + if (empty($CFG->keeptempdirectoriesonbackup)) { + fulldelete($backupbasepath); + } + + return null; + } + + /** + * Returns description of method result value + * + * @return external_description + * @since Moodle 2.4 + */ + public static function import_course_returns() { + return null; + } + /** * Returns description of method parameters * diff --git a/lib/db/services.php b/lib/db/services.php index 4df607ad609..cf9acb04fe6 100644 --- a/lib/db/services.php +++ b/lib/db/services.php @@ -534,6 +534,15 @@ $functions = array( 'capabilities'=> 'moodle/category:manage', ), + 'core_course_import_course' => array( + 'classname' => 'core_course_external', + 'methodname' => 'import_course', + 'classpath' => 'course/externallib.php', + 'description' => 'Import course data from a course into another course. Does not include any user data.', + 'type' => 'write', + 'capabilities'=> 'moodle/backup:backuptargetimport, moodle/restore:restoretargetimport', + ), + // === message related functions === 'moodle_message_send_instantmessages' => array( diff --git a/version.php b/version.php index f1afca3dcce..bf7c438fbdc 100644 --- a/version.php +++ b/version.php @@ -30,7 +30,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2012071200.00; // YYYYMMDD = weekly release date of this DEV branch +$version = 2012071700.00; // YYYYMMDD = weekly release date of this DEV branch // RR = release increments - 00 in DEV branches // .XX = incremental changes