Merge branch 'MDL-22146_backup_course_format_wip' of git://github.com/stronk7/moodle

This commit is contained in:
Petr Skoda 2011-02-14 21:08:19 +01:00
commit 251e5a8b62
13 changed files with 261 additions and 32 deletions

View File

@ -0,0 +1,50 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @package moodlecore
* @subpackage backup-moodle2
* @copyright 2011 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Class extending standard backup_plugin in order to implement some
* helper methods related with the course formats (format plugin)
*
* TODO: Finish phpdocs
*/
abstract class backup_format_plugin extends backup_plugin {
protected $courseformat; // To store the format (course->format) of the instance
public function __construct($plugintype, $pluginname, $optigroup, $step) {
parent::__construct($plugintype, $pluginname, $optigroup, $step);
$this->courseformat = backup_plan_dbops::get_courseformat_from_courseid($this->task->get_courseid());
}
/**
* Return the condition encapsulated into sqlparam format
* to get evaluated by value, not by path nor processor setting
*/
protected function get_format_condition() {
return array('sqlparam' => $this->courseformat);
}
}

View File

@ -34,6 +34,7 @@ require_once($CFG->dirroot . '/backup/moodle2/backup_default_block_task.class.ph
require_once($CFG->dirroot . '/backup/moodle2/backup_xml_transformer.class.php');
require_once($CFG->dirroot . '/backup/moodle2/backup_plugin.class.php');
require_once($CFG->dirroot . '/backup/moodle2/backup_qtype_plugin.class.php');
require_once($CFG->dirroot . '/backup/moodle2/backup_format_plugin.class.php');
require_once($CFG->dirroot . '/backup/moodle2/backup_subplugin.class.php');
require_once($CFG->dirroot . '/backup/moodle2/backup_settingslib.php');
require_once($CFG->dirroot . '/backup/moodle2/backup_stepslib.php');

View File

@ -33,12 +33,16 @@ abstract class backup_plugin {
protected $pluginname;
protected $connectionpoint;
protected $optigroup; // Optigroup, parent of all optigroup elements
protected $step;
protected $task;
public function __construct($plugintype, $pluginname, $optigroup) {
public function __construct($plugintype, $pluginname, $optigroup, $step) {
$this->plugintype = $plugintype;
$this->pluginname = $pluginname;
$this->optigroup = $optigroup;
$this->optigroup = $optigroup;
$this->connectionpoint = '';
$this->step = $step;
$this->task = $step->get_task();
}
public function define_plugin_structure($connectionpoint) {
@ -52,6 +56,22 @@ abstract class backup_plugin {
}
}
// Protected API starts here
// backup_step/structure_step/task wrappers
/**
* Returns the value of one (task/plan) setting
*/
protected function get_setting_value($name) {
if (is_null($this->task)) {
throw new backup_step_exception('not_specified_backup_task');
}
return $this->task->get_setting_value($name);
}
// end of backup_step/structure_step/task wrappers
/**
* Factory method that will return one backup_plugin_element (backup_optigroup_element)
* with its name automatically calculated, based one the plugin being handled (type, name)

View File

@ -125,13 +125,21 @@ abstract class backup_activity_structure_step extends backup_structure_step {
$backupfile = $subpluginsdir . '/backup/moodle2/' . $classname . '.class.php';
if (file_exists($backupfile)) {
require_once($backupfile);
$backupsubplugin = new $classname($subplugintype, $name, $optigroup);
$backupsubplugin = new $classname($subplugintype, $name, $optigroup, $this);
// Add subplugin returned structure to optigroup
$backupsubplugin->define_subplugin_structure($element->get_name());
}
}
}
/**
* As far as activity backup steps are implementing backup_subplugin stuff, they need to
* have the parent task available for wrapping purposes (get course/context....)
*/
public function get_task() {
return $this->task;
}
/**
* Wraps any activity backup structure within the common 'activity' element
* that will include common to all activities information like id, context...
@ -310,6 +318,9 @@ class backup_module_structure_step extends backup_structure_step {
$availability = new backup_nested_element('availability', array('id'), array(
'sourcecmid', 'requiredcompletion', 'gradeitemid', 'grademin', 'grademax'));
// attach format plugin structure to $module element, only one allowed
$this->add_plugin_structure('format', $module, false);
// Define the tree
$module->add_child($availinfo);
$availinfo->add_child($availability);
@ -346,6 +357,9 @@ class backup_section_structure_step extends backup_structure_step {
$section = new backup_nested_element('section', array('id'), array(
'number', 'name', 'summary', 'summaryformat', 'sequence', 'visible'));
// attach format plugin structure to $section element, only one allowed
$this->add_plugin_structure('format', $section, false);
// Define sources
$section->set_source_table('course_sections', array('id' => backup::VAR_SECTIONID));
@ -395,6 +409,9 @@ class backup_course_structure_step extends backup_structure_step {
$module = new backup_nested_element('module', array(), array('modulename'));
// attach format plugin structure to $course element, only one allowed
$this->add_plugin_structure('format', $course, false);
// Build the tree
$course->add_child($category);

View File

@ -34,12 +34,16 @@ abstract class backup_subplugin {
protected $subpluginname;
protected $connectionpoint;
protected $optigroup; // Optigroup, parent of all optigroup elements
protected $step;
protected $task;
public function __construct($subplugintype, $subpluginname, $optigroup) {
public function __construct($subplugintype, $subpluginname, $optigroup, $step) {
$this->subplugintype = $subplugintype;
$this->subpluginname = $subpluginname;
$this->optigroup = $optigroup;
$this->connectionpoint = '';
$this->step = $step;
$this->task = $step->get_task();
}
public function define_subplugin_structure($connectionpoint) {
@ -53,6 +57,22 @@ abstract class backup_subplugin {
}
}
// Protected API starts here
// backup_step/structure_step/task wrappers
/**
* Returns the value of one (task/plan) setting
*/
protected function get_setting_value($name) {
if (is_null($this->task)) {
throw new backup_step_exception('not_specified_backup_task');
}
return $this->task->get_setting_value($name);
}
// end of backup_step/structure_step/task wrappers
/**
* Factory method that will return one backup_subplugin_element (backup_optigroup_element)
* with its name automatically calculated, based one the subplugin being handled (type, name)

View File

@ -0,0 +1,33 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* @package moodlecore
* @subpackage backup-moodle2
* @copyright 2011 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Class extending standard restore_plugin in order to implement some
* helper methods related with the course formats (format plugin)
*
* TODO: Finish phpdocs
*/
abstract class restore_format_plugin extends restore_plugin {
// Love these classes. :-) Nothing special to customize here for now
}

View File

@ -33,8 +33,10 @@ require_once($CFG->dirroot . '/backup/moodle2/restore_block_task.class.php');
require_once($CFG->dirroot . '/backup/moodle2/restore_default_block_task.class.php');
require_once($CFG->dirroot . '/backup/moodle2/restore_plugin.class.php');
require_once($CFG->dirroot . '/backup/moodle2/restore_qtype_plugin.class.php');
require_once($CFG->dirroot . '/backup/moodle2/restore_format_plugin.class.php');
require_once($CFG->dirroot . '/backup/moodle2/backup_plugin.class.php');
require_once($CFG->dirroot . '/backup/moodle2/backup_qtype_plugin.class.php');
require_once($CFG->dirroot . '/backup/moodle2/backup_format_plugin.class.php');
require_once($CFG->dirroot . '/backup/moodle2/restore_subplugin.class.php');
require_once($CFG->dirroot . '/backup/moodle2/restore_settingslib.php');
require_once($CFG->dirroot . '/backup/moodle2/restore_stepslib.php');

View File

@ -202,6 +202,18 @@ abstract class restore_plugin {
return $this->step->apply_date_offset($value);
}
/**
* Returns the value of one (task/plan) setting
*/
protected function get_setting_value($name) {
if (is_null($this->task)) {
throw new restore_step_exception('not_specified_restore_task');
}
return $this->task->get_setting_value($name);
}
// end of restore_step/structure_step/task wrappers
/**
* Simple helper function that returns the name for the restore_path_element
* It's not mandatory to use it but recommended ;-)

View File

@ -32,12 +32,14 @@ class restore_section_task extends restore_task {
protected $info; // info related to section gathered from backup file
protected $contextid; // course context id
protected $sectionid; // new (target) id of the course section
/**
* Constructor - instantiates one object of this class
*/
public function __construct($name, $info, $plan = null) {
$this->info = $info;
$this->sectionid = 0;
parent::__construct($name, $plan);
}
@ -49,10 +51,18 @@ class restore_section_task extends restore_task {
return $this->get_basepath() . '/sections/section_' . $this->info->sectionid;
}
public function set_sectionid($sectionid) {
$this->sectionid = $sectionid;
}
public function get_contextid() {
return $this->contextid;
}
public function get_sectionid() {
return $this->sectionid;
}
/**
* Create all the steps that will be part of this task
*/

View File

@ -920,7 +920,12 @@ class restore_process_categories_and_questions extends restore_execution_step {
class restore_section_structure_step extends restore_structure_step {
protected function define_structure() {
return array(new restore_path_element('section', '/section'));
$section = new restore_path_element('section', '/section');
// Apply for 'format' plugins optional paths at section level
$this->add_plugin_structure('format', $section);
return array($section);
}
public function process_section($data) {
@ -962,6 +967,10 @@ class restore_section_structure_step extends restore_structure_step {
// Annotate the section mapping, with restorefiles option if needed
$this->set_mapping('course_section', $oldid, $newitemid, $restorefiles);
// set the new course_section id in the task
$this->task->set_sectionid($newitemid);
// Commented out. We never modify course->numsections as far as that is used
// by a lot of people to "hide" sections on purpose (so this remains as used to be in Moodle 1.x)
// Note: We keep the code here, to know about and because of the possibility of making this
@ -991,12 +1000,15 @@ class restore_course_structure_step extends restore_structure_step {
protected function define_structure() {
$course = new restore_path_element('course', '/course', true); // Grouped
$course = new restore_path_element('course', '/course');
$category = new restore_path_element('category', '/course/category');
$tag = new restore_path_element('tag', '/course/tags/tag');
$allowed = new restore_path_element('allowed', '/course/allowed_modules/module');
$allowed_module = new restore_path_element('allowed_module', '/course/allowed_modules/module');
return array($course, $category, $tag, $allowed);
// Apply for 'format' plugins optional paths at course level
$this->add_plugin_structure('format', $course);
return array($course, $category, $tag, $allowed_module);
}
/**
@ -1026,9 +1038,6 @@ class restore_course_structure_step extends restore_structure_step {
$data->shortname= $shortname;
$data->idnumber = '';
// Category is set by UI when choosing the destination
unset($data->category);
$data->startdate= $this->apply_date_offset($data->startdate);
if ($data->defaultgroupingid) {
$data->defaultgroupingid = $this->get_mappingid('grouping', $data->defaultgroupingid);
@ -1050,34 +1059,56 @@ class restore_course_structure_step extends restore_structure_step {
// Course record ready, update it
$DB->update_record('course', $data);
// Course tags
if (!empty($CFG->usetags) && isset($coursetags)) { // if enabled in server and present in backup
// Role name aliases
restore_dbops::set_course_role_names($this->get_restoreid(), $this->get_courseid());
}
public function process_category($data) {
// Nothing to do with the category. UI sets it before restore starts
}
public function process_tag($data) {
global $CFG, $DB;
$data = (object)$data;
if (!empty($CFG->usetags)) { // if enabled in server
// TODO: This is highly inneficient. Each time we add one tag
// we fetch all the existing because tag_set() deletes them
// so everything must be reinserted on each call
$tags = array();
foreach ($coursetags as $coursetag) {
$coursetag = (object)$coursetag;
$tags[] = $coursetag->rawname;
$existingtags = tag_get_tags('course', $this->get_courseid());
// Re-add all the existitng tags
foreach ($existingtags as $existingtag) {
$tags[] = $existingtag->rawname;
}
// Add the one being restored
$tags[] = $data->rawname;
// Send all the tags back to the course
tag_set('course', $this->get_courseid(), $tags);
}
// Course allowed modules
if (!empty($data->restrictmodules) && !empty($coursemodules)) {
}
public function process_allowed_module($data) {
global $CFG, $DB;
$data = (object)$data;
// only if enabled by admin setting
if (!empty($CFG->restrictmodulesfor) && $CFG->restrictmodulesfor == 'all') {
$available = get_plugin_list('mod');
foreach ($coursemodules as $coursemodule) {
$mname = $coursemodule['modulename'];
if (array_key_exists($mname, $available)) {
if ($module = $DB->get_record('modules', array('name' => $mname, 'visible' => 1))) {
$rec = new stdclass();
$rec->course = $this->get_courseid();
$rec->module = $module->id;
if (!$DB->record_exists('course_allowed_modules', (array)$rec)) {
$DB->insert_record('course_allowed_modules', $rec);
}
$mname = $data->modulename;
if (array_key_exists($mname, $available)) {
if ($module = $DB->get_record('modules', array('name' => $mname, 'visible' => 1))) {
$rec = new stdclass();
$rec->course = $this->get_courseid();
$rec->module = $module->id;
if (!$DB->record_exists('course_allowed_modules', (array)$rec)) {
$DB->insert_record('course_allowed_modules', $rec);
}
}
}
}
// Role name aliases
restore_dbops::set_course_role_names($this->get_restoreid(), $this->get_courseid());
}
protected function after_execute() {
@ -1963,11 +1994,15 @@ class restore_module_structure_step extends restore_structure_step {
$paths = array();
$paths[] = new restore_path_element('module', '/module');
$module = new restore_path_element('module', '/module');
$paths[] = $module;
if ($CFG->enableavailability) {
$paths[] = new restore_path_element('availability', '/module/availability_info/availability');
}
// Apply for 'format' plugins optional paths at module level
$this->add_plugin_structure('format', $module);
return $paths;
}

View File

@ -151,6 +151,18 @@ abstract class restore_subplugin {
return $this->step->apply_date_offset($value);
}
/**
* Returns the value of one (task/plan) setting
*/
protected function get_setting_value($name) {
if (is_null($this->task)) {
throw new restore_step_exception('not_specified_restore_task');
}
return $this->task->get_setting_value($name);
}
// end of restore_step/structure_step/task wrappers
/**
* Simple helper function that returns the name for the restore_path_element
* It's not mandatory to use it but recommended ;-)

View File

@ -119,6 +119,15 @@ abstract class backup_plan_dbops extends backup_dbops {
return $sectionsarr;
}
/**
* Given one course id, return its format in DB
*/
public static function get_courseformat_from_courseid($courseid) {
global $DB;
return $DB->get_field('course', 'format', array('id' => $courseid));
}
/**
* Return the wwwroot of the $CFG->mnet_localhost_id host
* caching it along the request

View File

@ -101,6 +101,14 @@ abstract class backup_structure_step extends backup_step {
$structure->destroy();
}
/**
* As far as backup structure steps are implementing backup_plugin stuff, they need to
* have the parent task available for wrapping purposes (get course/context....)
*/
public function get_task() {
return $this->task;
}
// Protected API starts here
/**
@ -133,7 +141,7 @@ abstract class backup_structure_step extends backup_step {
$backupfile = $plugindir . '/backup/moodle2/' . $classname . '.class.php';
if (file_exists($backupfile)) {
require_once($backupfile);
$backupplugin = new $classname($plugintype, $name, $optigroup);
$backupplugin = new $classname($plugintype, $name, $optigroup, $this);
// Add plugin returned structure to optigroup
$backupplugin->define_plugin_structure($element->get_name());
}