Source for file CourseRestorer.class.php
Documentation is available at CourseRestorer.class.php
<?php // $Id: CourseRestorer.class.php 15301 2008-05-16 03:21:42Z yannoo $
==============================================================================
Dokeos - elearning and course management software
Copyright (c) 2008 Dokeos SPRL
Copyright (c) 2003 Ghent University (UGent)
Copyright (c) 2001 Universite catholique de Louvain (UCL)
Copyright (c) Bart Mollet (bart.mollet@hogent.be)
For a full list of contributors, see "credits.txt".
The full license can be read in "license.txt".
This program 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 2
of the License, or (at your option) any later version.
See the GNU General Public License for more details.
Contact address: Dokeos, 44 rue des palais, B-1030 Brussels, Belgium
==============================================================================
require_once ('Course.class.php');
require_once ('Event.class.php');
require_once ('Link.class.php');
require_once ('ToolIntro.class.php');
require_once ('LinkCategory.class.php');
require_once ('ForumCategory.class.php');
require_once ('Forum.class.php');
require_once ('ForumTopic.class.php');
require_once ('ForumPost.class.php');
require_once ('CourseDescription.class.php');
require_once ('Learnpath.class.php');
require_once ('Survey.class.php');
require_once ('SurveyQuestion.class.php');
require_once ('mkdirr.php');
require_once ('rmdirr.php');
* Class to restore items from a course object to a Dokeos-course
* @author Bart Mollet <bart.mollet@hogent.be>
* What to do with files with same name (FILE_SKIP, FILE_RENAME or
* Create a new CourseRestorer
* @param constant $options What to do with files with same name (FILE_SKIP,
* FILE_RENAME or FILE_OVERWRITE)
* @param string $destination_course_code The code of the Dokeos-course in
* which the resources should be stored. Default: Current Dokeos-course.
function restore($destination_course_code = '')
if ($destination_course_code == '')
$this->course->destination_db = $course_info['dbName'];
$this->course->destination_path = $course_info['path'];
$this->course->destination_db = $course_info['database'];
$this->course->destination_path = $course_info['directory'];
//$this->restore_forums();
$this->restore_quizzes(); // after restore_documents! (for correct import of sound/video)
// Restore the item properties
foreach ($this->course->resources as $type => $resources)
foreach ($resources as $id => $resource)
foreach ($resource->item_properties as $property)
// First check if there isn't allready a record for this resource
$sql = "SELECT * FROM $table WHERE tool = '". $property['tool']. "' AND ref = '". $resource->destination_id. "'";
// The to_group_id and to_user_id are set to default values as users/groups possibly not exist in the target course
$sql = "INSERT INTO $table SET
tool = '". $property['tool']. "',
insert_user_id = '". $property['insert_user_id']. "',
insert_date = '". $property['insert_date']. "',
lastedit_date = '". $property['lastedit_date']. "',
ref = '". $resource->destination_id. "',
lastedit_type = '". $property['lastedit_type']. "',
lastedit_user_id = '". $property['lastedit_user_id']. "',
visibility = '". $property['visibility']. "',
start_visible = '". $property['start_visible']. "',
end_visible = '". $property['end_visible']. "',
to_user_id = '". $property['to_user_id']. "',
// Restore the linked-resources
foreach ($this->course->resources as $type => $resources)
foreach ($resources as $id => $resource)
$linked_resources = $resource->get_linked_resources();
foreach ($linked_resources as $to_type => $to_ids)
foreach ($to_ids as $index => $to_id)
$to_resource = $this->course->resources[$to_type][$to_id];
$sql = "INSERT INTO ". $table. " SET source_type = '". $type. "', source_id = '". $resource->destination_id. "', resource_type='". $to_type. "', resource_id='". $to_resource->destination_id. "' ";
$resources = $this->course->resources;
$perm = octdec(!empty($perm)? $perm: '0770');
copy($this->course->backup_path. '/'. $document->path, $path. $document->path);
$sql = "SELECT id FROM ". $table. " WHERE path='/". substr($document->path, 9). "'";
$file_name_no_ext = substr($document->path, 0, - (strlen($ext) + 1));
$file_name_no_ext = $document->path;
$new_file_name = $file_name_no_ext. '_'. $i. $ext;
$new_file_name = $file_name_no_ext. '_'. $i. $ext;
copy($this->course->backup_path. '/'. $document->path, $path. $new_file_name);
//also insert into item_property
api_item_property_update(
array('dbName'=>$this->course->destination_db,
$this->course->resource[RESOURCE_DOCUMENT][$id]->destination_id,
//make sure the source file actually exists
copy($this->course->backup_path. '/'. $document->path, $path. $document->path);
$sql = "INSERT INTO ". $table. " SET path = '/". substr($document->path, 9). "', comment = '". Database::escape_string($document->comment). "', title = '". Database::escape_string($document->title). "' ,filetype='". $document->file_type. "', size= '". $document->size. "'";
error_log('Course copy generated an ignoreable error while trying to copy '. $this->course->backup_path. '/'. $document->path. ': file not found');
error_log('Course copy generated an ignoreable error while trying to copy to '. dirname($path. $document->path). ': directory not found');
error_log('Course copy generated an ignoreable error while trying to copy to '. dirname($path. $document->path). ': directory not writeable');
} // end file doesn't exist
* Restore scorm documents
* TODO @TODO check that the restore function with renaming doesn't break the scorm structure!
$resources = $this->course->resources;
$perm = octdec(!empty($perm)? $perm: '0770');
rmdirr($path. $document->path);
$file_name_no_ext = substr($document->path, 0, - (strlen($ext) + 1));
$file_name_no_ext = $document->path;
$new_file_name = $file_name_no_ext. '_'. $i. $ext;
$new_file_name = $file_name_no_ext. '_'. $i. $ext;
rename($this->course->backup_path. '/'. $document->path,$this->course->backup_path. '/'. $new_file_name);
rename($this->course->backup_path. '/'. $new_file_name,$this->course->backup_path. '/'. $document->path);
$resources = $this->course->resources;
if ($topic->forum_id == $id)
$sql = "UPDATE ". $table_forum. " SET forum_topics = ". $forum_topics. ", forum_last_post_id = ". $last_post->destination_id. " WHERE forum_id = '". $new_id. "' ";
* Restore forum-categories
$resources = $this->course->resources;
if (!$forum_cat->is_restored())
$sql = "INSERT INTO ". $forum_cat_table. " SET cat_title = '". Database::escape_string($forum_cat->title. ' ('. $this->course->code. ')'). "'";
$resources = $this->course->resources;
if ($post->topic_id == $id)
$sql = "UPDATE ". $table. " SET topic_replies = '". $topic_replies. "', topic_last_post_id = ". $last_post->destination_id;
* @todo restore tree-structure of posts.
$resources = $this->course->resources;
$sql = "INSERT INTO ". $table_post. " SET topic_id = '". $topic_id. "', post_time = '". $post->post_time. "', forum_id = '". $forum_id. "', nom = '". Database::escape_string($post->lastname). "', prenom = '". Database::escape_string($post->firstname). "', topic_notify = '". $post->topic_notify. "', poster_ip = '". $post->poster_ip. "'";
$resources = $this->course->resources;
$sql = "SELECT MAX(display_order) FROM $link_table WHERE category_id='" . Database::escape_string($cat_id). "'";
$resources = $this->course->resources;
* Restore a link-category
$resources = $this->course->resources;
if (is_object($link_cat) && !$link_cat->is_restored())
$sql = "SELECT MAX(display_order) FROM $link_cat_table";
$display_order= $orderMax+ 1;
$sql = "INSERT INTO ". $link_cat_table. " SET category_title = '". Database::escape_string($link_cat->title). "', description='". Database::escape_string($link_cat->description). "', display_order='". $display_order. "' ";
$resources = $this->course->resources;
$sql = "INSERT INTO ". $table. " SET title = '". Database::escape_string($event->title). "', content = '". Database::escape_string($event->content). "', start_date = '". $event->start_date. "', end_date = '". $event->end_date. "'";
* Restore course-description
$resources = $this->course->resources;
$resources = $this->course->resources;
$sql = "INSERT INTO ". $table. " " .
"end_date = '". $announcement->date. "', " .
"display_order = '". $announcement->display_order. "', " .
"email_sent = '". $announcement->email_sent. "'";
$resources = $this->course->resources;
$sql = "SELECT path FROM ". $table_doc. " WHERE id = ". $resources[RESOURCE_DOCUMENT][$quiz->media]->destination_id;
foreach ($quiz->question_ids as $index => $question_id)
$sql = "INSERT IGNORE INTO ". $table_rel. " SET question_id = ". $qid. ", exercice_id = ". $new_id. "";
$resources = $this->course->resources;
if ($question->is_restored())
return $question->destination_id;
$sql = "INSERT INTO ". $table_que. " SET question = '". addslashes($question->question). "', description = '". addslashes($question->description). "', ponderation = '". addslashes($question->ponderation). "', position = '". addslashes($question->position). "', type='". addslashes($question->quiz_type). "', picture='". addslashes($question->picture). "'";
foreach ($question->answers as $index => $answer)
$sql = "INSERT INTO ". $table_ans. " SET id= '". ($index + 1). "',question_id = '". $new_id. "', answer = '". Database::escape_string($answer['answer']). "', correct = '". $answer['correct']. "', comment = '". Database::escape_string($answer['comment']). "', ponderation='". $answer['ponderation']. "', position = '". $answer['position']. "', hotspot_coordinates = '". $answer['hotspot_coordinates']. "', hotspot_type = '". $answer['hotspot_type']. "'";
$resources = $this->course->resources;
$sql = "INSERT INTO ". $table_sur. " " .
foreach ($survey->question_ids as $index => $question_id)
$sql = "UPDATE ". $table_que. " " .
"SET survey_id = ". $new_id. " WHERE " .
"question_id = ". $qid. "";
$sql = "UPDATE ". $table_ans. " ".
"SET survey_id = ". $new_id. " WHERE " .
"question_id = ". $qid. "";
* Restore survey-questions
$resources = $this->course->resources;
if ($question->is_restored())
return $question->destination_id;
$sql = "INSERT INTO ". $table_que. " " .
"SET survey_id = '". addslashes($question->survey_id). "', " .
"survey_question = '". addslashes($question->survey_question). "', " .
"survey_question_comment = '". addslashes($question->survey_question_comment). "', " .
"type = '". addslashes($question->survey_question_type). "', " .
"display = '". addslashes($question->display). "', " .
"shared_question_id = '". addslashes($question->shared_question_id). "', " .
"max_value = '". addslashes($question->max_value). "' ";
foreach ($question->answers as $index => $answer)
$sql = "INSERT INTO ". $table_ans. " " .
"option_text = '". addslashes($answer['option_text']). "', " .
"survey_id = '". addslashes($question->survey_id). "'";
$resources = $this->course->resources;
$sql = "INSERT INTO ". $table_main. " " .
"SET lp_type = '". $lp->lp_type. "', " .
"ref = '". $lp->ref. "', " .
$sql = "INSERT INTO $table_tool SET name='". Database::escape_string($lp->name). "', link='newscorm/lp_controller.php?action=view&lp_id=$new_lp_id', image='scormbuilder.gif', visibility='1', admin='0', address='squaregrey.gif'";
$parent_item_ids = array();
$previous_item_ids = array();
$next_item_ids = array();
foreach ($lp->get_items() as $index => $item)
// Links in learnpath have types 'Link _self' or 'Link _blank'. We only need 'Link' here.
$type_parts = explode(' ',$item['type']);
$item['id'] = $this->course->resources[$type_parts[0]][$item['id']]->destination_id;
//Get the new ref ID for all items that are not sco (dokeos quizzes, documents, etc)
if(!empty($item['ref']) && $lp->lp_type!= '2'){
$ref = $this->get_new_id($item['item_type'],$item['ref']);
//Dealing with path the same way as ref as some data has been put into path when it's a
$path = $this->get_new_id($item['item_type'],$path);
$sql = "INSERT INTO ". $table_item. " SET " .
"lp_id = '". $new_lp_id. "', " .
"item_type='". $item['item_type']. "', " .
"min_score = '". $item['min_score']. "', " .
"max_score = '". $item['max_score']. "', " .
"mastery_score = '". $item['mastery_score']. "', " .
"parent_item_id = '". $item['parent_item_id']. "', " .
"previous_item_id = '". $item['previous_item_id']. "', " .
"next_item_id = '". $item['next_item_id']. "', " .
"display_order = '". $item['display_order']. "', " .
//save a link between old and new item IDs
$new_item_ids[$item['id']] = $new_item_id;
//save a reference of items that need a parent_item_id refresh
$parent_item_ids[$new_item_id] = $item['parent_item_id'];
//save a reference of items that need a previous_item_id refresh
$previous_item_ids[$new_item_id] = $item['previous_item_id'];
//save a reference of items that need a next_item_id refresh
$next_item_ids[$new_item_id] = $item['next_item_id'];
foreach ($parent_item_ids as $new_item_id => $parent_item_old_id)
if($parent_item_old_id != 0){
$parent_new_id = $new_item_ids[$parent_item_old_id];
$sql = "UPDATE ". $table_item. " SET parent_item_id = '". $parent_new_id. "' WHERE id = '". $new_item_id. "'";
foreach ($previous_item_ids as $new_item_id => $previous_item_old_id)
if($previous_item_old_id != 0){
$previous_new_id = $new_item_ids[$previous_item_old_id];
$sql = "UPDATE ". $table_item. " SET previous_item_id = '". $previous_new_id. "' WHERE id = '". $new_item_id. "'";
foreach ($next_item_ids as $new_item_id => $next_item_old_id)
if($next_item_old_id != 0){
$next_new_id = $new_item_ids[$next_item_old_id];
$sql = "UPDATE ". $table_item. " SET next_item_id = '". $next_new_id. "' WHERE id = '". $new_item_id. "'";
* Gets the new ID of one specific tool item from the tool name and the old ID
* @param string Tool name
//transform $tool into one backup/restore constant
if($tool == 'hotpotatoes'){$tool = 'document';}
if(!empty($this->course->resources[$tool][$ref]->destination_id)){
return $this->course->resources[$tool][$ref]->destination_id;
|