Commit 5c0ff68d authored by Petr Skoda's avatar Petr Skoda
Browse files

backup/restore support

parent e6bf43cd
<?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/>.
/**
* Description of book backup task
*
* @package mod
* @subpackage book
* @copyright 2010 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die;
require_once($CFG->dirroot.'/mod/book/backup/moodle2/backup_book_stepslib.php'); // Because it exists (must)
require_once($CFG->dirroot.'/mod/book/backup/moodle2/backup_book_settingslib.php'); // Because it exists (optional)
/**
* book backup task that provides all the settings and steps to perform one
* complete backup of the activity
*/
class backup_book_activity_task extends backup_activity_task {
/**
* Define (add) particular settings this activity can have
*
* @return void
*/
protected function define_my_settings() {
// No particular settings for this activity
}
/**
* Define (add) particular steps this activity can have
*
* @return void
*/
protected function define_my_steps() {
// book only has one structure step
$this->add_step(new backup_book_activity_structure_step('book structure', 'book.xml'));
}
/**
* Code the transformations to perform in the activity in
* order to get transportable (encoded) links
*
* @param string $content
* @return $string encoded content
*/
static public function encode_content_links($content) {
global $CFG;
$base = preg_quote($CFG->wwwroot,"/");
// Link to the list of books
$search = "/(".$base."\/mod\/book\/index.php\?id\=)([0-9]+)/";
$content = preg_replace($search, '$@bookINDEX*$2@$', $content);
// Link to book view by moduleid
$search = "/(".$base."\/mod\/book\/view.php\?id\=)([0-9]+)/";
$content = preg_replace($search, '$@bookVIEWBYID*$2@$', $content);
$search = "/(".$base."\/mod\/book\/view.php\?id\=)([0-9]+)&chapterid=([0-9]+)/";
$content = preg_replace($search, '$@bookVIEWBYIDCH*$2*$3@$', $content);
// Link to book view by bookid
$search = "/(".$base."\/mod\/book\/view.php\?b\=)([0-9]+)/";
$content = preg_replace($search, '$@bookVIEWBYB*$2@$', $content);
$search = "/(".$base."\/mod\/book\/view.php\?b\=)([0-9]+)&chapterid=([0-9]+)/";
$content = preg_replace($search, '$@bookVIEWBYBCH*$2*$3@$', $content);
return $content;
}
}
<?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/>.
/**
* Description of book backup settings
*
* @package mod
* @subpackage book
* @copyright 2010 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die;
// This activity has not particular settings but the inherited from the generic
// backup_activity_task so here there isn't any class definition, like the ones
// existing in /backup/moodle2/backup_settingslib.php (activities section)
<?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/>.
/**
* Define all the backup steps that will be used by the backup_book_activity_task
*
* @package mod
* @subpackage book
* @copyright 2010 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die;
/**
* Define the complete book structure for backup, with file and id annotations
*/
class backup_book_activity_structure_step extends backup_activity_structure_step {
protected function define_structure() {
// Define each element separated
$book = new backup_nested_element('book', array('id'), array('name', 'intro', 'introformat', 'numbering', 'disableprinting', 'customtitles', 'timecreated', 'timemodified'));
$chapters = new backup_nested_element('chapters');
$chapter = new backup_nested_element('chapter', array('id'), array('pagenum', 'subchapter', 'title', 'content', 'contentormat', 'hidden', 'timemcreated', 'timemodified', 'importsrc',));
$book->add_child($chapters);
$chapters->add_child($chapter);
// Define sources
$book->set_source_table('book', array('id' => backup::VAR_ACTIVITYID));
// Define file annotations
$book->annotate_files('mod_book', 'intro', null); // This file area hasn't itemid
$chapter->annotate_files('mod_book', 'chapter', 'id');
// Return the root element (book), wrapped into standard activity structure
return $this->prepare_activity_structure($book);
}
}
<?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/>.
/**
* Define all the restore tasks
*
* @package mod
* @subpackage book
* @copyright 2010 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/mod/book/backup/moodle2/restore_book_stepslib.php'); // Because it exists (must)
/**
* book restore task that provides all the settings and steps to perform one
* complete restore of the activity
*/
class restore_book_activity_task extends restore_activity_task {
/**
* Define (add) particular settings this activity can have
*
* @return void
*/
protected function define_my_settings() {
// No particular settings for this activity
}
/**
* Define (add) particular steps this activity can have
*
* @return void
*/
protected function define_my_steps() {
// Choice only has one structure step
$this->add_step(new restore_book_activity_structure_step('book_structure', 'book.xml'));
}
/**
* Define the contents in the activity that must be
* processed by the link decoder
*
* @return array
*/
static public function define_decode_contents() {
$contents = array();
$contents[] = new restore_decode_content('book', array('intro'), 'book');
$contents[] = new restore_decode_content('book_chapters', array('content'), 'book_chapter');
return $contents;
}
/**
* Define the decoding rules for links belonging
* to the activity to be executed by the link decoder
*
* @return array
*/
static public function define_decode_rules() {
$rules = array();
// List of books in course
$rules[] = new restore_decode_rule('bookINDEX', '/mod/book/index.php?id=$1', 'course');
// book by cm->id
$rules[] = new restore_decode_rule('bookVIEWBYID', '/mod/book/view.php?id=$1', 'course_module');
$rules[] = new restore_decode_rule('bookVIEWBYIDCH', '/mod/book/view.php?id=$1&chapterid=$2', array('course_module', 'book_chapter'));
// book by book->id
$rules[] = new restore_decode_rule('bookVIEWBYB', '/mod/book/view.php?b=$1', 'book');
$rules[] = new restore_decode_rule('bookVIEWBYBCH', '/mod/book/view.php?b=$1&chapterid=$2', array('book', 'book_chapter'));
return $rules;
}
/**
* Define the restore log rules that will be applied
* by the {@link restore_logs_processor} when restoring
* book logs. It must return one array
* of {@link restore_log_rule} objects
*
* @return array
*/
static public function define_restore_log_rules() {
$rules = array();
$rules[] = new restore_log_rule('book', 'update', 'view.php?id={course_module}', '{book}');
$rules[] = new restore_log_rule('book', 'view', 'view.php?id={course_module}', '{book}');
$rules[] = new restore_log_rule('book', 'view all', 'view.php?id={course_module}', '{book}');
$rules[] = new restore_log_rule('book', 'print', 'view.php?id={course_module}', '{book}');
return $rules;
}
/**
* Define the restore log rules that will be applied
* by the {@link restore_logs_processor} when restoring
* course logs. It must return one array
* of {@link restore_log_rule} objects
*
* Note this rules are applied when restoring course logs
* by the restore final task, but are defined here at
* activity level. All them are rules not linked to any module instance (cmid = 0)
*
* @return array
*/
static public function define_restore_log_rules_for_course() {
$rules = array();
return $rules;
}
}
<?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/>.
/**
* Define all the restore steps that will be used by the restore_book_activity_task
*
* @package mod
* @subpackage book
* @copyright 2010 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Structure step to restore one book activity
*/
class restore_book_activity_structure_step extends restore_activity_structure_step {
protected function define_structure() {
$paths = array();
$paths[] = new restore_path_element('book', '/activity/book');
$paths[] = new restore_path_element('book_chapter', '/activity/book/chapters/chapter');
// Return the paths wrapped into standard activity structure
return $this->prepare_activity_structure($paths);
}
protected function process_book($data) {
global $DB;
$data = (object)$data;
$oldid = $data->id;
$data->course = $this->get_courseid();
$newitemid = $DB->insert_record('book', $data);
$this->apply_activity_instance($newitemid);
}
protected function process_book_chapter($data) {
global $DB;
$data = (object)$data;
$oldid = $data->id;
$data->course = $this->get_courseid();
$data->bookid = $this->get_new_parentid('book');
$newitemid = $DB->insert_record('book_chapters', $data);
$this->set_mapping('book_chapter', $oldid, $newitemid);
}
protected function after_execute() {
global $DB;
// Add book related files
$this->add_related_files('mod_book', 'intro', null);
$this->add_related_files('mod_book', 'chapter', 'book_chapter');
}
}
<?php
//This php script contains all the stuff to backup/restore
//book mods
//This is the 'graphical' structure of the book mod:
//
// book
// (CL,pk->id)
// |
// |
// |
// book_chapters
// (CL,pk->id, fk->bookid)
//
// Meaning: pk->primary key field of the table
// fk->foreign key to link with parent
// nt->nested field (recursive data)
// CL->course level info
// UL->user level info
// files->table may have files)
//
//-----------------------------------------------------------
//This function executes all the backup procedure about this mod
function book_backup_mods($bf,$preferences) {
global $CFG;
$status = true;
////Iterate over book table
if ($books = get_records ('book', 'course', $preferences->backup_course, 'id')) {
foreach ($books as $book) {
if (backup_mod_selected($preferences,'book',$book->id)) {
$status = book_backup_one_mod($bf,$preferences,$book);
}
}
}
return $status;
}
function book_backup_one_mod($bf,$preferences,$book) {
global $CFG;
if (is_numeric($book)) {
$book = get_record('book','id',$book);
}
$status = true;
//Start mod
fwrite ($bf,start_tag('MOD',3,true));
//Print book data
fwrite ($bf,full_tag('ID',4,false,$book->id));
fwrite ($bf,full_tag('MODTYPE',4,false,'book'));
fwrite ($bf,full_tag('NAME',4,false,$book->name));
fwrite ($bf,full_tag('SUMMARY',4,false,$book->summary));
fwrite ($bf,full_tag('NUMBERING',4,false,$book->numbering));
fwrite ($bf,full_tag('DISABLEPRINTING',4,false,$book->disableprinting));
fwrite ($bf,full_tag('CUSTOMTITLES',4,false,$book->customtitles));
fwrite ($bf,full_tag('TIMECREATED',4,false,$book->timecreated));
fwrite ($bf,full_tag('TIMEMODIFIED',4,false,$book->timemodified));
//back up the chapters
$status = backup_book_chapters($bf,$preferences,$book);
//End mod
$status = fwrite($bf,end_tag('MOD',3,true));
return $status;
}
//Backup book_chapters contents (executed from book_backup_mods)
function backup_book_chapters($bf,$preferences,$book) {
global $CFG;
$status = true;
//Print book's chapters
if ($chapters = get_records('book_chapters', 'bookid', $book->id, 'id')) {
//Write start tag
$status =fwrite ($bf,start_tag('CHAPTERS',4,true));
foreach ($chapters as $ch) {
//Start chapter
fwrite ($bf,start_tag('CHAPTER',5,true));
//Print chapter data
fwrite ($bf,full_tag('ID',6,false,$ch->id));
fwrite ($bf,full_tag('PAGENUM',6,false,$ch->pagenum));
fwrite ($bf,full_tag('SUBCHAPTER',6,false,$ch->subchapter));
fwrite ($bf,full_tag('TITLE',6,false,$ch->title));
fwrite ($bf,full_tag('CONTENT',6,false,$ch->content));
fwrite ($bf,full_tag('HIDDEN',6,false,$ch->hidden));
fwrite ($bf,full_tag('TIMECREATED',6,false,$ch->timecreated));
fwrite ($bf,full_tag('TIMEMODIFIED',6,false,$ch->timemodified));
fwrite ($bf,full_tag('IMPORTSRC',6,false,$ch->importsrc));
//End chapter
$status = fwrite ($bf,end_tag('CHAPTER',5,true));
}
//Write end tag
$status = fwrite ($bf,end_tag('CHAPTERS',4,true));
}
return $status;
}
//Return a content encoded to support interactivities linking. Every module
//should have its own. They are called automatically from the backup procedure.
function book_encode_content_links ($content,$preferences) {
global $CFG;
$base = preg_quote($CFG->wwwroot,"/");
$result = $content;
//Link to the list of books
$buscar="/(".$base."\/mod\/book\/index.php\?id\=)([0-9]+)/";
$result= preg_replace($buscar,'$@BOOKINDEX*$2@$',$result);
//Link to book's specific chapter
$buscar="/(".$base."\/mod\/book\/view.php\?id\=)([0-9]+)\&chapterid\=([0-9]+)/";
$result= preg_replace($buscar,'$@BOOKCHAPTER*$2*$3@$',$result);
//Link to book's first chapter
$buscar="/(".$base."\/mod\/book\/view.php\?id\=)([0-9]+)/";
$result= preg_replace($buscar,'$@BOOKSTART*$2@$',$result);
return $result;
}
////Return an array of info (name,value)
function book_check_backup_mods($course,$user_data=false,$backup_unique_code,$instances=null) {
if (!empty($instances) && is_array($instances) && count($instances)) {
$info = array();
foreach ($instances as $id => $instance) {
$info += book_check_backup_mods_instances($instance,$backup_unique_code);
}
return $info;
}
//First the course data
$info[0][0] = get_string('modulenameplural','book');
$info[0][1] = count_records('book', 'course', $course);
//No user data for books ;-)
return $info;
}
////Return an array of info (name,value)
function book_check_backup_mods_instances($instance,$backup_unique_code) {
$info[$instance->id.'0'][0] = '<b>'.$instance->name.'</b>';
$info[$instance->id.'0'][1] = '';
return $info;
}
......@@ -196,7 +196,7 @@ function book_supports($feature) {
case FEATURE_GROUPMEMBERSONLY: return true;
case FEATURE_MOD_INTRO: return true;
case FEATURE_COMPLETION_TRACKS_VIEWS: return false; //TODO
case FEATURE_BACKUP_MOODLE2: return false; //TODO
case FEATURE_BACKUP_MOODLE2: return true;
default: return null;
}
......
<?php
//This php script contains all the stuff to backup/restore
//book mods
//This is the "graphical" structure of the book mod:
//
// book
// (CL,pk->id)
// |
// |
// |
// book_chapters
// (CL,pk->id, fk->bookid)
//
// Meaning: pk->primary key field of the table
// fk->foreign key to link with parent
// nt->nested field (recursive data)
// CL->course level info
// UL->user level info
// files->table may have files)
//
//-----------------------------------------------------------
//This function executes all the restore procedure about this mod
function book_restore_mods($mod,$restore) {
global $CFG;
$status = true;
//Get record from backup_ids
$data = backup_getid($restore->backup_unique_code,$mod->modtype,$mod->id);
if ($data) {
//Now get completed xmlized object
$info = $data->info;
//traverse_xmlize($info); //Debug
//print_object ($GLOBALS['traverse_array']); //Debug
//$GLOBALS['traverse_array']=""; //Debug
//Now, build the BOOK record structure
$book = new object();
$book->course = $restore->course_id;
$book->name = backup_todb($info['MOD']['#']['NAME']['0']['#']);
$book->summary = backup_todb($info['MOD']['#']['SUMMARY']['0']['#']);
$book->numbering = backup_todb($info['MOD']['#']['NUMBERING']['0']['#']);
$book->disableprinting = backup_todb($info['MOD']['#']['DISABLEPRINTING']['0']['#']);
$book->customtitles = backup_todb($info['MOD']['#']['CUSTOMTITLES']['0']['#']);
$book->timecreated = $info['MOD']['#']['TIMECREATED']['0']['#'];
$book->timemodified = $info['MOD']['#']['TIMEMODIFIED']['0']['#'];
//The structure is equal to the db, so insert the book
$newid = insert_record ('book',$book);
//Do some output
if (!defined('RESTORE_SILENTLY')) {
echo '<ul><li>'.get_string('modulename','book').' "'.$book->name.'"<br>';
}
backup_flush(300);
if ($newid) {
//We have the newid, update backup_ids
backup_putid($restore->backup_unique_code,$mod->modtype,
$mod->id, $newid);
//now restore chapters
$status = book_chapters_restore($mod->id,$newid,$info,$restore);
} else {
$status = false;