CourseRestorer.class.php 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302
  1. <?php // $Id: CourseRestorer.class.php 22200 2009-07-17 19:47:58Z iflorespaz $
  2. /*
  3. ==============================================================================
  4. Dokeos - elearning and course management software
  5. Copyright (c) 2008 Dokeos SPRL
  6. Copyright (c) 2003 Ghent University (UGent)
  7. Copyright (c) 2001 Universite catholique de Louvain (UCL)
  8. Copyright (c) Bart Mollet (bart.mollet@hogent.be)
  9. For a full list of contributors, see "credits.txt".
  10. The full license can be read in "license.txt".
  11. This program is free software; you can redistribute it and/or
  12. modify it under the terms of the GNU General Public License
  13. as published by the Free Software Foundation; either version 2
  14. of the License, or (at your option) any later version.
  15. See the GNU General Public License for more details.
  16. Contact address: Dokeos, 44 rue des palais, B-1030 Brussels, Belgium
  17. Mail: info@dokeos.com
  18. ==============================================================================
  19. */
  20. require_once 'Course.class.php';
  21. require_once 'Event.class.php';
  22. require_once 'Link.class.php';
  23. require_once 'ToolIntro.class.php';
  24. require_once 'LinkCategory.class.php';
  25. require_once 'ForumCategory.class.php';
  26. require_once 'Forum.class.php';
  27. require_once 'ForumTopic.class.php';
  28. require_once 'ForumPost.class.php';
  29. require_once 'CourseDescription.class.php';
  30. require_once 'Learnpath.class.php';
  31. require_once 'Survey.class.php';
  32. require_once 'SurveyQuestion.class.php';
  33. require_once 'Glossary.class.php';
  34. require_once api_get_path(LIBRARY_PATH).'fileUpload.lib.php';
  35. define('FILE_SKIP', 1);
  36. define('FILE_RENAME', 2);
  37. define('FILE_OVERWRITE', 3);
  38. /**
  39. * Class to restore items from a course object to a Dokeos-course
  40. * @author Bart Mollet <bart.mollet@hogent.be>
  41. * @package dokeos.backup
  42. */
  43. class CourseRestorer
  44. {
  45. /**
  46. * The course-object
  47. */
  48. var $course;
  49. /**
  50. * What to do with files with same name (FILE_SKIP, FILE_RENAME or
  51. * FILE_OVERWRITE)
  52. */
  53. var $file_option;
  54. /**
  55. * Create a new CourseRestorer
  56. */
  57. function CourseRestorer($course)
  58. {
  59. $this->course = $course;
  60. $this->file_option = FILE_RENAME;
  61. }
  62. /**
  63. * Set the file-option
  64. * @param constant $options What to do with files with same name (FILE_SKIP,
  65. * FILE_RENAME or FILE_OVERWRITE)
  66. */
  67. function set_file_option($option)
  68. {
  69. $this->file_option = $option;
  70. }
  71. /**
  72. * Restore a course.
  73. * @param string $destination_course_code The code of the Dokeos-course in
  74. * which the resources should be stored. Default: Current Dokeos-course.
  75. */
  76. function restore($destination_course_code = '')
  77. {
  78. if ($destination_course_code == '') {
  79. $course_info = api_get_course_info();
  80. $this->course->destination_db = $course_info['dbName'];
  81. $this->course->destination_path = $course_info['path'];
  82. } else {
  83. $course_info = Database :: get_course_info($destination_course_code);
  84. $this->course->destination_db = $course_info['database'];
  85. $this->course->destination_path = $course_info['directory'];
  86. }
  87. // platform encoding
  88. $course_charset = $this->course->encoding;
  89. $this->restore_links();
  90. $this->restore_tool_intro();
  91. $this->restore_events();
  92. $this->restore_announcements();
  93. $this->restore_documents();
  94. $this->restore_scorm_documents();
  95. $this->restore_course_descriptions();
  96. $this->restore_forums();
  97. $this->restore_quizzes(); // after restore_documents! (for correct import of sound/video)
  98. $this->restore_learnpaths();
  99. $this->restore_surveys();
  100. $this->restore_student_publication();
  101. $this->restore_glossary();
  102. // Restore the item properties
  103. $table = Database :: get_course_table(TABLE_ITEM_PROPERTY, $this->course->destination_db);
  104. foreach ($this->course->resources as $type => $resources) {
  105. if (is_array($resources)) {
  106. foreach ($resources as $id => $resource) {
  107. foreach ($resource->item_properties as $property)
  108. {
  109. // First check if there isn't allready a record for this resource
  110. $sql = "SELECT * FROM $table WHERE tool = '".$property['tool']."' AND ref = '".$resource->destination_id."'";
  111. $res = api_sql_query($sql,__FILE__,__LINE__);
  112. if( Database::num_rows($res) == 0) {
  113. // The to_group_id and to_user_id are set to default values as users/groups possibly not exist in the target course
  114. $sql = "INSERT INTO $table SET
  115. tool = '".Database::escape_string($property['tool'])."',
  116. insert_user_id = '".Database::escape_string($property['insert_user_id'])."',
  117. insert_date = '".Database::escape_string($property['insert_date'])."',
  118. lastedit_date = '".Database::escape_string($property['lastedit_date'])."',
  119. ref = '".Database::escape_string($resource->destination_id)."',
  120. lastedit_type = '".Database::escape_string($property['lastedit_type'])."',
  121. lastedit_user_id = '".Database::escape_string($property['lastedit_user_id'])."',
  122. visibility = '".Database::escape_string($property['visibility'])."',
  123. start_visible = '".Database::escape_string($property['start_visible'])."',
  124. end_visible = '".Database::escape_string($property['end_visible'])."',
  125. to_user_id = '".Database::escape_string($property['to_user_id'])."',
  126. to_group_id = '0'";
  127. ;
  128. api_sql_query($sql, __FILE__, __LINE__);
  129. }
  130. }
  131. }
  132. }
  133. }
  134. // Restore the linked-resources
  135. $table = Database :: get_course_table(TABLE_LINKED_RESOURCES, $this->course->destination_db);
  136. foreach ($this->course->resources as $type => $resources)
  137. {
  138. if (is_array($resources))
  139. foreach ($resources as $id => $resource)
  140. {
  141. $linked_resources = $resource->get_linked_resources();
  142. foreach ($linked_resources as $to_type => $to_ids)
  143. {
  144. foreach ($to_ids as $index => $to_id)
  145. {
  146. $to_resource = $this->course->resources[$to_type][$to_id];
  147. $sql = "INSERT INTO ".$table." SET source_type = '".$type."', source_id = '".$resource->destination_id."', resource_type='".$to_type."', resource_id='".$to_resource->destination_id."' ";
  148. api_sql_query($sql, __FILE__, __LINE__);
  149. }
  150. }
  151. }
  152. }
  153. }
  154. /**
  155. * Restore documents
  156. */
  157. function restore_documents()
  158. {
  159. if ($this->course->has_resources(RESOURCE_DOCUMENT)) {
  160. $table = Database :: get_course_table(TABLE_DOCUMENT, $this->course->destination_db);
  161. $resources = $this->course->resources;
  162. $destination_course['dbName']= $this->course->destination_db;
  163. /* echo '<pre>'; echo $this->course->backup_path; echo '<br>'; */
  164. foreach ($resources[RESOURCE_DOCUMENT] as $id => $document) {
  165. $path = api_get_path(SYS_COURSE_PATH).$this->course->destination_path.'/';
  166. $perm = api_get_setting('permissions_for_new_directories');
  167. $perm = octdec(!empty($perm)?$perm:0770);
  168. $dirs = explode('/', dirname($document->path));
  169. if (count($dirs)==1) {
  170. if ($this->file_type==FOLDER) {
  171. $new = substr($document->path, 8);
  172. $created_dir = create_unexisting_directory($destination_course,api_get_user_id(),0, 0 ,$path.'document',$new,basename($new));
  173. }
  174. } else {
  175. $my_temp = '';
  176. for ($i=1; $i<=count($dirs); $i++) {
  177. $my_temp .= $dirs[$i];
  178. if (!is_dir($path.'document/'.$my_temp)) {
  179. $sql = "SELECT id FROM ".$table." WHERE path='/".Database::escape_string($my_temp)."'";
  180. //echo '<br>';
  181. $res = api_sql_query($sql, __FILE__, __LINE__);
  182. $num_result = Database::num_rows($res);
  183. if ($num_result==0) {
  184. $created_dir = create_unexisting_directory($destination_course,api_get_user_id(),0, 0 ,$path.'document','/'.$my_temp,basename($my_temp));
  185. }
  186. }
  187. $my_temp .= '/';
  188. }
  189. }
  190. /*
  191. echo '<br>';
  192. echo '------------------------';
  193. echo '<br>';
  194. echo '$doculent:';echo '<br>';
  195. echo print_r($document); echo '<br>';
  196. echo 'documlent->path'.$path.$document->path;echo '<br>';
  197. echo 'file option:'.$this->file_option; echo '<br>';
  198. echo 'filetype:'.$document->file_type ;
  199. echo '<br>';
  200. */
  201. if ($document->file_type == DOCUMENT) {
  202. if (file_exists($path.$document->path)) {
  203. switch ($this->file_option) {
  204. case FILE_OVERWRITE :
  205. $this->course->backup_path.'/'.$document->path;
  206. copy($this->course->backup_path.'/'.$document->path, $path.$document->path);
  207. $sql = "SELECT id FROM ".$table." WHERE path='/".substr($document->path, 9)."'";
  208. $res = api_sql_query($sql, __FILE__, __LINE__);
  209. $obj = Database::fetch_object($res);
  210. $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $obj->id;
  211. $sql = "UPDATE ".$table." SET comment = '".Database::escape_string($document->comment)."', title='".Database::escape_string($document->title)."', size='".$document->size."' WHERE id = '".$obj->id."'";
  212. api_sql_query($sql, __FILE__, __LINE__);
  213. break;
  214. case FILE_SKIP :
  215. $sql = "SELECT id FROM ".$table." WHERE path='/".Database::escape_string(substr($document->path, 9))."'";
  216. $res = api_sql_query($sql, __FILE__, __LINE__);
  217. $obj = Database::fetch_object($res);
  218. $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $obj->id;
  219. break;
  220. case FILE_RENAME :
  221. $i = 1;
  222. $ext = explode('.', basename($document->path));
  223. if (count($ext) > 1) {
  224. $ext = array_pop($ext);
  225. $file_name_no_ext = substr($document->path, 0, - (strlen($ext) + 1));
  226. $ext = '.'.$ext;
  227. } else {
  228. $ext = '';
  229. $file_name_no_ext = $document->path;
  230. }
  231. $new_file_name = $file_name_no_ext.'_'.$i.$ext;
  232. $file_exists = file_exists($path.$new_file_name);
  233. while ($file_exists) {
  234. $i ++;
  235. $new_file_name = $file_name_no_ext.'_'.$i.$ext;
  236. $file_exists = file_exists($path.$new_file_name);
  237. }
  238. copy($this->course->backup_path.'/'.$document->path, $path.$new_file_name);
  239. $sql = "INSERT INTO ".$table." SET path = '/".Database::escape_string(substr($new_file_name, 9))."', comment = '".Database::escape_string($document->comment)."', title = '".Database::escape_string($document->title)."' ,filetype='".$document->file_type."', size= '".$document->size."'";
  240. api_sql_query($sql, __FILE__, __LINE__);
  241. $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = Database::get_last_insert_id();
  242. //also insert into item_property
  243. /*
  244. api_item_property_update(
  245. array('dbName'=>$this->course->destination_db,
  246. TOOL_DOCUMENT,
  247. $this->course->resource[RESOURCE_DOCUMENT][$id]->destination_id,
  248. 'DocumentAdded',
  249. );
  250. */
  251. break;
  252. } // end switch
  253. } // end if file exists
  254. else
  255. {
  256. //make sure the source file actually exists
  257. //echo $this->course->backup_path.'/'.$document->path;
  258. if(is_file($this->course->backup_path.'/'.$document->path) && is_readable($this->course->backup_path.'/'.$document->path) && is_dir(dirname($path.$document->path)) && is_writeable(dirname($path.$document->path)))
  259. {
  260. copy($this->course->backup_path.'/'.$document->path, $path.$document->path);
  261. $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."'";
  262. api_sql_query($sql, __FILE__, __LINE__);
  263. $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = Database::get_last_insert_id();
  264. }
  265. else
  266. {
  267. if(is_file($this->course->backup_path.'/'.$document->path) && is_readable($this->course->backup_path.'/'.$document->path))
  268. {
  269. error_log('Course copy generated an ignoreable error while trying to copy '.$this->course->backup_path.'/'.$document->path.': file not found');
  270. }
  271. if(!is_dir(dirname($path.$document->path)))
  272. {
  273. error_log('Course copy generated an ignoreable error while trying to copy to '.dirname($path.$document->path).': directory not found');
  274. }
  275. if(!is_writeable(dirname($path.$document->path)))
  276. {
  277. error_log('Course copy generated an ignoreable error while trying to copy to '.dirname($path.$document->path).': directory not writeable');
  278. }
  279. }
  280. } // end file doesn't exist
  281. }
  282. else
  283. {
  284. /*$sql = "SELECT id FROM ".$table." WHERE path = '/".Database::escape_string(substr($document->path, 9))."'";
  285. $res = api_sql_query($sql,__FILE__,__LINE__);
  286. if( Database::num_rows($res)> 0)
  287. {
  288. $obj = Database::fetch_object($res);
  289. $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = $obj->id;
  290. }
  291. else
  292. {
  293. $sql = "INSERT INTO ".$table." SET path = '/".Database::escape_string(substr($document->path, 9))."', comment = '".Database::escape_string($document->comment)."', title = '".Database::escape_string($document->title)."' ,filetype='".$document->file_type."', size= '".$document->size."'";
  294. api_sql_query($sql, __FILE__, __LINE__);
  295. $this->course->resources[RESOURCE_DOCUMENT][$id]->destination_id = Database::get_last_insert_id();
  296. }*/
  297. } // end folder
  298. } // end for each
  299. }
  300. }
  301. /**
  302. * Restore scorm documents
  303. * TODO @TODO check that the restore function with renaming doesn't break the scorm structure!
  304. */
  305. function restore_scorm_documents()
  306. {
  307. if ($this->course->has_resources(RESOURCE_SCORM))
  308. {
  309. $resources = $this->course->resources;
  310. foreach ($resources[RESOURCE_SCORM] as $id => $document)
  311. {
  312. $path = api_get_path(SYS_COURSE_PATH).$this->course->destination_path.'/';
  313. $perm = api_get_setting('permissions_for_new_directories');
  314. $perm = octdec(!empty($perm)?$perm:'0770');
  315. @mkdir(dirname($path.$document->path), $perm, true);
  316. if (file_exists($path.$document->path))
  317. {
  318. switch ($this->file_option)
  319. {
  320. case FILE_OVERWRITE :
  321. rmdirr($path.$document->path);
  322. copyDirTo($this->course->backup_path.'/'.$document->path, $path.dirname($document->path), false);
  323. break;
  324. case FILE_SKIP :
  325. break;
  326. case FILE_RENAME :
  327. $i = 1;
  328. $ext = explode('.', basename($document->path));
  329. if (count($ext) > 1)
  330. {
  331. $ext = array_pop($ext);
  332. $file_name_no_ext = substr($document->path, 0, - (strlen($ext) + 1));
  333. $ext = '.'.$ext;
  334. }
  335. else
  336. {
  337. $ext = '';
  338. $file_name_no_ext = $document->path;
  339. }
  340. $new_file_name = $file_name_no_ext.'_'.$i.$ext;
  341. $file_exists = file_exists($path.$new_file_name);
  342. while ($file_exists)
  343. {
  344. $i ++;
  345. $new_file_name = $file_name_no_ext.'_'.$i.$ext;
  346. $file_exists = file_exists($path.$new_file_name);
  347. }
  348. rename($this->course->backup_path.'/'.$document->path,$this->course->backup_path.'/'.$new_file_name);
  349. copyDirTo($this->course->backup_path.'/'.$new_file_name, $path.dirname($new_file_name), false);
  350. rename($this->course->backup_path.'/'.$new_file_name,$this->course->backup_path.'/'.$document->path);
  351. break;
  352. } // end switch
  353. } // end if file exists
  354. else
  355. {
  356. copyDirTo($this->course->backup_path.'/'.$document->path, $path.dirname($document->path), false);
  357. }
  358. } // end for each
  359. }
  360. }
  361. /**
  362. * Restore forums
  363. */
  364. function restore_forums()
  365. {
  366. if ($this->course->has_resources(RESOURCE_FORUM))
  367. {
  368. $table_forum = Database :: get_course_table(TABLE_FORUM, $this->course->destination_db);
  369. $table_topic = Database :: get_course_table(TABLE_FORUM_THREAD, $this->course->destination_db);
  370. $table_post = Database :: get_course_table(TABLE_FORUM_POST, $this->course->destination_db);
  371. $resources = $this->course->resources;
  372. foreach ($resources[RESOURCE_FORUM] as $id => $forum)
  373. {
  374. $cat_id = $this->restore_forum_category($forum->category_id);
  375. $sql = "INSERT INTO ".$table_forum.
  376. " SET forum_title = '".Database::escape_string($forum->title).
  377. "', forum_comment = '".Database::escape_string($forum->description).
  378. "', forum_category = ".(int)Database::escape_string($cat_id).
  379. ", forum_last_post = ".(int)Database::escape_string($forum->last_post).
  380. ", forum_threads = ".(int)Database::escape_string($forum->topics).
  381. ", forum_posts = ".(int)Database::escape_string($forum->posts).
  382. ", allow_anonymous = ".(int)Database::escape_string($forum->allow_anonymous).
  383. ", allow_edit = ".(int)Database::escape_string($forum->allow_edit).
  384. ", approval_direct_post = '".Database::escape_string($forum->approval_direct_post).
  385. "', allow_attachments = ".(int)Database::escape_string($forum->allow_attachments).
  386. ", allow_new_threads = ".(int)Database::escape_string($forum->allow_new_topics).
  387. ", default_view = '".Database::escape_string($forum->default_view).
  388. "', forum_of_group = '".Database::escape_string($forum->of_group).
  389. "', forum_group_public_private = '".Database::escape_string($forum->group_public_private).
  390. "', forum_order = ".(int)Database::escape_string($forum->order).
  391. ", locked = ".(int)Database::escape_string($forum->locked).
  392. ", session_id = ".(int)Database::escape_string($forum->session_id).
  393. ", forum_image = '".Database::escape_string($forum->image)."'";
  394. api_sql_query($sql, __FILE__, __LINE__);
  395. $new_id = Database::get_last_insert_id();
  396. $this->course->resources[RESOURCE_FORUM][$id]->destination_id = $new_id;
  397. $forum_topics = 0;
  398. if (is_array($this->course->resources[RESOURCE_FORUMTOPIC]))
  399. {
  400. foreach ($this->course->resources[RESOURCE_FORUMTOPIC] as $topic_id => $topic)
  401. {
  402. if ($topic->forum_id == $id)
  403. {
  404. $this->restore_topic($topic_id, $new_id);
  405. $forum_topics ++;
  406. }
  407. }
  408. }
  409. if ($forum_topics > 0)
  410. {
  411. $last_post = $this->course->resources[RESOURCE_FORUMPOST][$forum->last_post];
  412. $sql = "UPDATE ".$table_forum." SET forum_threads = ".$forum_topics.", forum_last_post = ".(int)$last_post->destination_id." WHERE forum_id = ".(int)$new_id;
  413. api_sql_query($sql, __FILE__, __LINE__);
  414. }
  415. }
  416. }
  417. }
  418. /**
  419. * Restore forum-categories
  420. */
  421. function restore_forum_category($id)
  422. {
  423. $forum_cat_table = Database :: get_course_table(TABLE_FORUM_CATEGORY, $this->course->destination_db);
  424. $resources = $this->course->resources;
  425. $forum_cat = $resources[RESOURCE_FORUMCATEGORY][$id];
  426. if (!$forum_cat->is_restored())
  427. {
  428. $title = $forum_cat->title;
  429. if (!preg_match('/.*\((.+)\)$/', $title, $matches)) // This is for avoiding repetitive adding of training code after several backup/restore cycles.
  430. {
  431. if ($matches[1] != $this->course->code)
  432. {
  433. $title = $title.' ('.$this->course->code.')';
  434. }
  435. }
  436. $sql = "INSERT INTO ".$forum_cat_table.
  437. " SET cat_title = '".Database::escape_string($title).
  438. "', cat_comment = '".Database::escape_string($forum_cat->description).
  439. "', cat_order = ".(int)Database::escape_string($forum_cat->order).
  440. ", locked = ".(int)Database::escape_string($forum_cat->locked).
  441. ", session_id = ".(int)Database::escape_string($forum_cat->session_id);
  442. api_sql_query($sql, __FILE__, __LINE__);
  443. $new_id = Database::get_last_insert_id();
  444. $this->course->resources[RESOURCE_FORUMCATEGORY][$id]->destination_id = $new_id;
  445. return $new_id;
  446. }
  447. return $this->course->resources[RESOURCE_FORUMCATEGORY][$id]->destination_id;
  448. }
  449. /**
  450. * Restore a forum-topic
  451. */
  452. function restore_topic($id, $forum_id)
  453. {
  454. $table = Database :: get_course_table(TABLE_FORUM_THREAD, $this->course->destination_db);
  455. $resources = $this->course->resources;
  456. $topic = $resources[RESOURCE_FORUMTOPIC][$id];
  457. $sql = "INSERT INTO ".$table.
  458. " SET thread_title = '".Database::escape_string($topic->title).
  459. "', forum_id = ".(int)Database::escape_string($forum_id).
  460. ", thread_date = '".Database::escape_string($topic->time).
  461. "', thread_poster_id = ".(int)Database::escape_string($topic->topic_poster_id).
  462. ", thread_poster_name = '".Database::escape_string($topic->topic_poster_name).
  463. "', thread_views = ".(int)Database::escape_string($topic->views).
  464. ", thread_sticky = ".(int)Database::escape_string($topic->sticky).
  465. ", locked = ".(int)Database::escape_string($topic->locked).
  466. ", thread_close_date = '".Database::escape_string($topic->time_closed).
  467. "', thread_weight = ".(float)Database::escape_string($topic->weight).
  468. ", thread_title_qualify = '".Database::escape_string($topic->title_qualify).
  469. "', thread_qualify_max = ".(float)Database::escape_string($topic->qualify_max);
  470. api_sql_query($sql, __FILE__, __LINE__);
  471. $new_id = Database::get_last_insert_id();
  472. $this->course->resources[RESOURCE_FORUMTOPIC][$id]->destination_id = $new_id;
  473. $topic_replies = -1;
  474. foreach ($this->course->resources[RESOURCE_FORUMPOST] as $post_id => $post)
  475. {
  476. if ($post->topic_id == $id)
  477. {
  478. $topic_replies ++;
  479. $this->restore_post($post_id, $new_id, $forum_id);
  480. }
  481. }
  482. $last_post = $this->course->resources[RESOURCE_FORUMPOST][$topic->last_post];
  483. if (is_object($last_post))
  484. {
  485. $sql = "UPDATE ".$table." SET thread_last_post = ".(int)$last_post->destination_id;
  486. api_sql_query($sql, __FILE__, __LINE__);
  487. }
  488. if ($topic_replies >= 0)
  489. {
  490. $sql = "UPDATE ".$table." SET thread_replies = ".$topic_replies;
  491. api_sql_query($sql, __FILE__, __LINE__);
  492. }
  493. return $new_id;
  494. }
  495. /**
  496. * Restore a forum-post
  497. * @TODO Restore tree-structure of posts. For example: attachments to posts.
  498. */
  499. function restore_post($id, $topic_id, $forum_id)
  500. {
  501. $table_post = Database :: get_course_table(TABLE_FORUM_POST, $this->course->destination_db);
  502. $resources = $this->course->resources;
  503. $post = $resources[RESOURCE_FORUMPOST][$id];
  504. $sql = "INSERT INTO ".$table_post.
  505. " SET post_title = '".Database::escape_string($post->title).
  506. "', post_text = '".Database::escape_string($post->text).
  507. "', thread_id = ".(int)Database::escape_string($topic_id).
  508. ", post_date = '".Database::escape_string($post->post_time).
  509. "', forum_id = ".(int)Database::escape_string($forum_id).
  510. ", poster_id = ".(int)Database::escape_string($post->poster_id).
  511. ", poster_name = '".Database::escape_string($post->poster_name).
  512. "', post_notification = ".(int)Database::escape_string($post->topic_notify).
  513. ", post_parent_id = ".(int)Database::escape_string($post->parent_post_id).
  514. ", visible = ".(int)Database::escape_string($post->visible);
  515. api_sql_query($sql, __FILE__, __LINE__);
  516. $new_id = Database::get_last_insert_id();
  517. $this->course->resources[RESOURCE_FORUMPOST][$id]->destination_id = $new_id;
  518. return $new_id;
  519. }
  520. /**
  521. * Restore links
  522. */
  523. function restore_links()
  524. {
  525. if ($this->course->has_resources(RESOURCE_LINK))
  526. {
  527. $link_table = Database :: get_course_table(TABLE_LINK, $this->course->destination_db);
  528. $resources = $this->course->resources;
  529. foreach ($resources[RESOURCE_LINK] as $id => $link)
  530. {
  531. $cat_id = $this->restore_link_category($link->category_id);
  532. $sql = "SELECT MAX(display_order) FROM $link_table WHERE category_id='" . Database::escape_string($cat_id). "'";
  533. $result = api_sql_query($sql, __FILE__, __LINE__);
  534. list($max_order) = Database::fetch_array($result);
  535. $sql = "INSERT INTO ".$link_table." SET url = '".Database::escape_string($link->url)."', title = '".Database::escape_string($link->title)."', description = '".Database::escape_string($link->description)."', category_id='".$cat_id."', on_homepage = '".$link->on_homepage."', display_order='".($max_order+1)."'";
  536. api_sql_query($sql, __FILE__, __LINE__);
  537. $this->course->resources[RESOURCE_LINK][$id]->destination_id = Database::get_last_insert_id();
  538. }
  539. }
  540. }
  541. /**
  542. * Restore tool intro
  543. */
  544. function restore_tool_intro()
  545. {
  546. if ($this->course->has_resources(RESOURCE_TOOL_INTRO))
  547. {
  548. $tool_intro_table = Database :: get_course_table(TABLE_TOOL_INTRO, $this->course->destination_db);
  549. $resources = $this->course->resources;
  550. foreach ($resources[RESOURCE_TOOL_INTRO] as $id => $tool_intro)
  551. {
  552. $sql = "DELETE FROM ".$tool_intro_table." WHERE id='".Database::escape_string($tool_intro->id)."'";
  553. api_sql_query($sql, __FILE__, __LINE__);
  554. $sql = "INSERT INTO ".$tool_intro_table." SET id='".Database::escape_string($tool_intro->id)."', intro_text = '".Database::escape_string($tool_intro->intro_text)."'";
  555. api_sql_query($sql, __FILE__, __LINE__);
  556. $this->course->resources[RESOURCE_TOOL_INTRO][$id]->destination_id = Database::get_last_insert_id();
  557. }
  558. }
  559. }
  560. /**
  561. * Restore a link-category
  562. */
  563. function restore_link_category($id)
  564. {
  565. if ($id == 0)
  566. return 0;
  567. $link_cat_table = Database :: get_course_table(TABLE_LINK_CATEGORY, $this->course->destination_db);
  568. $resources = $this->course->resources;
  569. $link_cat = $resources[RESOURCE_LINKCATEGORY][$id];
  570. if (is_object($link_cat) && !$link_cat->is_restored())
  571. {
  572. $sql = "SELECT MAX(display_order) FROM $link_cat_table";
  573. $result=api_sql_query($sql,__FILE__,__LINE__);
  574. list($orderMax)=Database::fetch_array($result,'NUM');
  575. $display_order=$orderMax+1;
  576. $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."' ";
  577. api_sql_query($sql, __FILE__, __LINE__);
  578. $new_id = Database::get_last_insert_id();
  579. $this->course->resources[RESOURCE_LINKCATEGORY][$id]->destination_id = $new_id;
  580. return $new_id;
  581. }
  582. return $this->course->resources[RESOURCE_LINKCATEGORY][$id]->destination_id;
  583. }
  584. /**
  585. * Restore events
  586. */
  587. function restore_events()
  588. {
  589. if ($this->course->has_resources(RESOURCE_EVENT))
  590. {
  591. $table = Database :: get_course_table(TABLE_AGENDA, $this->course->destination_db);
  592. $resources = $this->course->resources;
  593. foreach ($resources[RESOURCE_EVENT] as $id => $event)
  594. {
  595. $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."'";
  596. api_sql_query($sql, __FILE__, __LINE__);
  597. $this->course->resources[RESOURCE_EVENT][$id]->destination_id = Database::get_last_insert_id();
  598. }
  599. }
  600. }
  601. /**
  602. * Restore course-description
  603. */
  604. function restore_course_descriptions()
  605. {
  606. if ($this->course->has_resources(RESOURCE_COURSEDESCRIPTION))
  607. {
  608. $table = Database :: get_course_table(TABLE_COURSE_DESCRIPTION, $this->course->destination_db);
  609. $resources = $this->course->resources;
  610. foreach ($resources[RESOURCE_COURSEDESCRIPTION] as $id => $cd)
  611. {
  612. if (isset($_POST['destination_course'])) {
  613. $course_destination=Security::remove_XSS($_POST['destination_course']);
  614. $course_destination=api_get_course_info($course_destination);
  615. $course_destination=$course_destination['path'];
  616. } else {
  617. $course_destination=$this->course->destination_path;
  618. }
  619. $course_info=api_get_course_info(api_get_course_id());
  620. $search='../courses/'.$course_info['path'].'/document';
  621. $replace_search_by='../courses/'.$course_destination.'/document';
  622. $description_content=str_replace($search,$replace_search_by,$cd->content);
  623. $sql = "INSERT INTO ".$table." SET title = '".Database::escape_string($cd->title)."', content = '".Database::escape_string($description_content)."'";
  624. api_sql_query($sql, __FILE__, __LINE__);
  625. $this->course->resources[RESOURCE_COURSEDESCRIPTION][$id]->destination_id = Database::get_last_insert_id();
  626. }
  627. }
  628. }
  629. /**
  630. * Restore announcements
  631. */
  632. function restore_announcements()
  633. {
  634. if ($this->course->has_resources(RESOURCE_ANNOUNCEMENT))
  635. {
  636. $table = Database :: get_course_table(TABLE_ANNOUNCEMENT, $this->course->destination_db);
  637. $resources = $this->course->resources;
  638. foreach ($resources[RESOURCE_ANNOUNCEMENT] as $id => $announcement)
  639. {
  640. $sql = "INSERT INTO ".$table." " .
  641. "SET title = '".Database::escape_string($announcement->title)."'," .
  642. "content = '".Database::escape_string($announcement->content)."', " .
  643. "end_date = '".$announcement->date."', " .
  644. "display_order = '".$announcement->display_order."', " .
  645. "email_sent = '".$announcement->email_sent."'";
  646. api_sql_query($sql, __FILE__, __LINE__);
  647. $this->course->resources[RESOURCE_ANNOUNCEMENT][$id]->destination_id = Database::get_last_insert_id();
  648. }
  649. }
  650. }
  651. /**
  652. * Restore Quiz
  653. */
  654. function restore_quizzes()
  655. {
  656. if ($this->course->has_resources(RESOURCE_QUIZ))
  657. {
  658. $table_qui = Database :: get_course_table(TABLE_QUIZ_TEST, $this->course->destination_db);
  659. $table_rel = Database :: get_course_table(TABLE_QUIZ_TEST_QUESTION, $this->course->destination_db);
  660. $table_doc = Database :: get_course_table(TABLE_DOCUMENT, $this->course->destination_db);
  661. $resources = $this->course->resources;
  662. foreach ($resources[RESOURCE_QUIZ] as $id => $quiz)
  663. {
  664. $doc = '';
  665. if (strlen($quiz->media) > 0)
  666. {
  667. if ($this->course->resources[RESOURCE_DOCUMENT][$quiz->media]->is_restored())
  668. {
  669. $sql = "SELECT path FROM ".$table_doc." WHERE id = ".$resources[RESOURCE_DOCUMENT][$quiz->media]->destination_id;
  670. $doc = api_sql_query($sql, __FILE__, __LINE__);
  671. $doc = Database::fetch_object($doc);
  672. $doc = str_replace('/audio/', '', $doc->path);
  673. }
  674. }
  675. if ($id != -1)
  676. {
  677. // Normal tests are stored in the database.
  678. $sql = "INSERT INTO ".$table_qui.
  679. " SET title = '".Database::escape_string($quiz->title).
  680. "', description = '".Database::escape_string($quiz->description).
  681. "', type = '".$quiz->quiz_type.
  682. "', random = '".$quiz->random.
  683. "', active = '".$quiz->active.
  684. "', sound = '".Database::escape_string($doc).
  685. "', max_attempt = ".(int)$quiz->attempts.
  686. ", results_disabled = ".(int)$quiz->results_disabled.
  687. ", access_condition = '".$quiz->access_condition.
  688. "', start_time = '".$quiz->start_time.
  689. "', end_time = '".$quiz->end_time.
  690. "', feedback_type = ".(int)$quiz->feedback_type;
  691. api_sql_query($sql, __FILE__, __LINE__);
  692. $new_id = Database::get_last_insert_id();
  693. }
  694. else
  695. {
  696. // $id = -1 identifies the fictionary test for collecting orphan questions. We do not store it in the database.
  697. $new_id = -1;
  698. }
  699. $this->course->resources[RESOURCE_QUIZ][$id]->destination_id = $new_id;
  700. foreach ($quiz->question_ids as $index => $question_id)
  701. {
  702. $qid = $this->restore_quiz_question($question_id);
  703. $sql = "INSERT IGNORE INTO ".$table_rel." SET question_id = ".$qid.", exercice_id = ".$new_id."";
  704. api_sql_query($sql, __FILE__, __LINE__);
  705. }
  706. }
  707. }
  708. }
  709. /**
  710. * Restore quiz-questions
  711. */
  712. function restore_quiz_question($id)
  713. {
  714. $resources = $this->course->resources;
  715. $question = $resources[RESOURCE_QUIZQUESTION][$id];
  716. $new_id=0;
  717. if(is_object($question))
  718. {
  719. if ($question->is_restored())
  720. {
  721. return $question->destination_id;
  722. }
  723. $table_que = Database :: get_course_table(TABLE_QUIZ_QUESTION, $this->course->destination_db);
  724. $table_ans = Database :: get_course_table(TABLE_QUIZ_ANSWER, $this->course->destination_db);
  725. $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)."', level='".addslashes($question->level)."'";
  726. api_sql_query($sql, __FILE__, __LINE__);
  727. $new_id = Database::get_last_insert_id();
  728. foreach ($question->answers as $index => $answer)
  729. {
  730. $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']."'";
  731. api_sql_query($sql, __FILE__, __LINE__);
  732. }
  733. $this->course->resources[RESOURCE_QUIZQUESTION][$id]->destination_id = $new_id;
  734. }
  735. return $new_id;
  736. }
  737. /**
  738. * Restore surveys
  739. */
  740. function restore_surveys()
  741. {
  742. if ($this->course->has_resources(RESOURCE_SURVEY))
  743. {
  744. $table_sur = Database :: get_course_table(TABLE_SURVEY, $this->course->destination_db);
  745. $table_que = Database :: get_course_table(TABLE_SURVEY_QUESTION, $this->course->destination_db);
  746. $table_ans = Database :: get_course_table(TABLE_SURVEY_QUESTION_OPTION, $this->course->destination_db);
  747. $resources = $this->course->resources;
  748. foreach ($resources[RESOURCE_SURVEY] as $id => $survey)
  749. {
  750. $sql_check = 'SELECT survey_id FROM '.$table_sur.'
  751. WHERE code = "'.Database::escape_string($survey->code).'"
  752. AND lang="'.Database::escape_string($survey->lang).'"
  753. ';
  754. $result_check = api_sql_query($sql_check, __FILE__, __LINE__);
  755. $doc = '';
  756. $sql = "INSERT INTO ".$table_sur." " .
  757. "SET code = '".Database::escape_string($survey->code)."', " .
  758. "title = '".Database::escape_string($survey->title)."', " .
  759. "subtitle = '".Database::escape_string($survey->subtitle)."', " .
  760. "author = '".Database::escape_string($survey->author)."', " .
  761. "lang = '".Database::escape_string($survey->lang)."', " .
  762. "avail_from = '".Database::escape_string($survey->avail_from)."', " .
  763. "avail_till = '".Database::escape_string($survey->avail_till)."', " .
  764. "is_shared = '".Database::escape_string($survey->is_shared)."', " .
  765. "template = '".Database::escape_string($survey->template)."', " .
  766. "intro = '".Database::escape_string($survey->intro)."', " .
  767. "surveythanks = '".Database::escape_string($survey->surveythanks)."', " .
  768. "creation_date = '".Database::escape_string($survey->creation_date)."', " .
  769. "invited = '0', " .
  770. "answered = '0', " .
  771. "invite_mail = '".Database::escape_string($survey->invite_mail)."', " .
  772. "reminder_mail = '".Database::escape_string($survey->reminder_mail)."'";
  773. //An existing survey exists with the same code and the same language
  774. if(Database::num_rows($result_check) == 1)
  775. {
  776. switch ($this->file_option) {
  777. case FILE_SKIP:
  778. //Do nothing
  779. break;
  780. case FILE_RENAME:
  781. $survey_code = $survey->code.'_';
  782. $i=1;
  783. $temp_survey_code = $survey_code.$i;
  784. while (!$this->is_survey_code_available($temp_survey_code))
  785. {
  786. $temp_survey_code = $survey_code.++$i;
  787. }
  788. $survey_code = $temp_survey_code;
  789. $sql = "INSERT INTO ".$table_sur." " .
  790. "SET code = '".Database::escape_string($survey_code)."', " .
  791. "title = '".Database::escape_string($survey->title)."', " .
  792. "subtitle = '".Database::escape_string($survey->subtitle)."', " .
  793. "author = '".Database::escape_string($survey->author)."', " .
  794. "lang = '".Database::escape_string($survey->lang)."', " .
  795. "avail_from = '".Database::escape_string($survey->avail_from)."', " .
  796. "avail_till = '".Database::escape_string($survey->avail_till)."', " .
  797. "is_shared = '".Database::escape_string($survey->is_shared)."', " .
  798. "template = '".Database::escape_string($survey->template)."', " .
  799. "intro = '".Database::escape_string($survey->intro)."', " .
  800. "surveythanks = '".Database::escape_string($survey->surveythanks)."', " .
  801. "creation_date = '".Database::escape_string($survey->creation_date)."', " .
  802. "invited = '0', " .
  803. "answered = '0', " .
  804. "invite_mail = '".Database::escape_string($survey->invite_mail)."', " .
  805. "reminder_mail = '".Database::escape_string($survey->reminder_mail)."'";
  806. //Insert the new source survey
  807. api_sql_query($sql, __FILE__, __LINE__);
  808. $new_id = Database::get_last_insert_id();
  809. $this->course->resources[RESOURCE_SURVEY][$id]->destination_id = $new_id;
  810. foreach ($survey->question_ids as $index => $question_id)
  811. {
  812. $qid = $this->restore_survey_question($question_id);
  813. $sql = "UPDATE ".$table_que." " .
  814. "SET survey_id = ".$new_id." WHERE " .
  815. "question_id = ".$qid."";
  816. api_sql_query($sql, __FILE__, __LINE__);
  817. $sql = "UPDATE ".$table_ans." ".
  818. "SET survey_id = ".$new_id." WHERE " .
  819. "question_id = ".$qid."";
  820. api_sql_query($sql, __FILE__, __LINE__);
  821. }
  822. break;
  823. case FILE_OVERWRITE:
  824. // Delete the existing survey with the same code and language and import the one of the source course
  825. // getting the information of the survey (used for when the survey is shared)
  826. require_once(api_get_path(SYS_CODE_PATH).'survey/survey.lib.php');
  827. $sql_select_existing_survey = "SELECT * FROM $table_sur WHERE survey_id='".Database::escape_string(Database::result($result_check,0,0))."'";
  828. $result = api_sql_query($sql_select_existing_survey, __FILE__, __LINE__);
  829. $survey_data = Database::fetch_array($result,'ASSOC');
  830. // if the survey is shared => also delete the shared content
  831. if (is_numeric($survey_data['survey_share']))
  832. {
  833. survey_manager::delete_survey($survey_data['survey_share'], true,$this->course->destination_db);
  834. }
  835. $return = survey_manager :: delete_survey($survey_data['survey_id'],false,$this->course->destination_db);
  836. //Insert the new source survey
  837. api_sql_query($sql, __FILE__, __LINE__);
  838. $new_id = Database::get_last_insert_id();
  839. $this->course->resources[RESOURCE_SURVEY][$id]->destination_id = $new_id;
  840. foreach ($survey->question_ids as $index => $question_id)
  841. {
  842. $qid = $this->restore_survey_question($question_id);
  843. $sql = "UPDATE ".$table_que." " .
  844. "SET survey_id = ".$new_id." WHERE " .
  845. "question_id = ".$qid."";
  846. api_sql_query($sql, __FILE__, __LINE__);
  847. $sql = "UPDATE ".$table_ans." ".
  848. "SET survey_id = ".$new_id." WHERE " .
  849. "question_id = ".$qid."";
  850. api_sql_query($sql, __FILE__, __LINE__);
  851. }
  852. break;
  853. default:
  854. break;
  855. }
  856. }
  857. //No existing survey with the same language and the same code, we just copy the survey
  858. else
  859. {
  860. api_sql_query($sql, __FILE__, __LINE__);
  861. $new_id = Database::get_last_insert_id();
  862. $this->course->resources[RESOURCE_SURVEY][$id]->destination_id = $new_id;
  863. foreach ($survey->question_ids as $index => $question_id)
  864. {
  865. $qid = $this->restore_survey_question($question_id);
  866. $sql = "UPDATE ".$table_que." " .
  867. "SET survey_id = ".$new_id." WHERE " .
  868. "question_id = ".$qid."";
  869. api_sql_query($sql, __FILE__, __LINE__);
  870. $sql = "UPDATE ".$table_ans." ".
  871. "SET survey_id = ".$new_id." WHERE " .
  872. "question_id = ".$qid."";
  873. api_sql_query($sql, __FILE__, __LINE__);
  874. }
  875. }
  876. }
  877. }
  878. }
  879. /**
  880. * Check availability of a survey code
  881. */
  882. function is_survey_code_available($survey_code)
  883. {
  884. $table_sur = Database :: get_course_table(TABLE_SURVEY, $this->course->destination_db);
  885. $sql = "SELECT * FROM $table_sur WHERE code='".Database::escape_string($survey_code)."'";
  886. $result = api_sql_query($sql, __FILE__, __LINE__);
  887. if(Database::num_rows($result) > 0) return false; else return true;
  888. }
  889. /**
  890. * Restore survey-questions
  891. */
  892. function restore_survey_question($id)
  893. {
  894. $resources = $this->course->resources;
  895. $question = $resources[RESOURCE_SURVEYQUESTION][$id];
  896. $new_id=0;
  897. if(is_object($question))
  898. {
  899. if ($question->is_restored())
  900. {
  901. return $question->destination_id;
  902. }
  903. $table_que = Database :: get_course_table(TABLE_SURVEY_QUESTION, $this->course->destination_db);
  904. $table_ans = Database :: get_course_table(TABLE_SURVEY_QUESTION_OPTION, $this->course->destination_db);
  905. $sql = "INSERT INTO ".$table_que." " .
  906. "SET survey_id = '".Database::escape_string($question->survey_id)."', " .
  907. "survey_question = '".Database::escape_string($question->survey_question)."', " .
  908. "survey_question_comment = '".Database::escape_string($question->survey_question_comment)."', " .
  909. "type = '".Database::escape_string($question->survey_question_type)."', " .
  910. "display = '".Database::escape_string($question->display)."', " .
  911. "sort = '".Database::escape_string($question->sort)."', " .
  912. "shared_question_id = '".Database::escape_string($question->shared_question_id)."', " .
  913. "max_value = '".Database::escape_string($question->max_value)."' ";
  914. api_sql_query($sql, __FILE__, __LINE__);
  915. $new_id = Database::get_last_insert_id();
  916. foreach ($question->answers as $index => $answer) {
  917. $sql = "INSERT INTO ".$table_ans." " .
  918. "SET " .
  919. "question_id = '".Database::escape_string($new_id)."', " .
  920. "option_text = '".Database::escape_string($answer['option_text'])."', " .
  921. "sort = '".Database::escape_string($answer['sort'])."', " .
  922. "survey_id = '".Database::escape_string($question->survey_id)."'";
  923. api_sql_query($sql, __FILE__, __LINE__);
  924. }
  925. $this->course->resources[RESOURCE_SURVEYQUESTION][$id]->destination_id = $new_id;
  926. }
  927. return $new_id;
  928. }
  929. /**
  930. * Restore learnpaths
  931. */
  932. function restore_learnpaths()
  933. {
  934. if ($this->course->has_resources(RESOURCE_LEARNPATH)) {
  935. $table_main = Database :: get_course_table(TABLE_LP_MAIN, $this->course->destination_db);
  936. $table_item = Database :: get_course_table(TABLE_LP_ITEM, $this->course->destination_db);
  937. $table_tool = Database::get_course_table(TABLE_TOOL_LIST, $this->course->destination_db);
  938. $resources = $this->course->resources;
  939. foreach ($resources[RESOURCE_LEARNPATH] as $id => $lp) {
  940. $sql = "INSERT INTO ".$table_main." " .
  941. "SET lp_type = '".$lp->lp_type."', " .
  942. "name = '".Database::escape_string($lp->name)."', " .
  943. "path = '".Database::escape_string($lp->path)."', " .
  944. "ref = '".$lp->ref."', " .
  945. "description = '".Database::escape_string($lp->description)."', " .
  946. "content_local = '".Database::escape_string($lp->content_local)."', " .
  947. "default_encoding = '".Database::escape_string($lp->default_encoding)."', " .
  948. "default_view_mod = '".Database::escape_string($lp->default_view_mod)."', " .
  949. "prevent_reinit = '".Database::escape_string($lp->prevent_reinit)."', " .
  950. "force_commit = '".Database::escape_string($lp->force_commit)."', " .
  951. "content_maker = '".Database::escape_string($lp->content_maker)."', " .
  952. "display_order = '".Database::escape_string($lp->display_order)."', " .
  953. "js_lib= '".Database::escape_string($lp->js_lib)."', " .
  954. "content_license= '".Database::escape_string($lp->content_license)."', " .
  955. "debug= '".Database::escape_string($lp->debug)."' ";
  956. api_sql_query($sql, __FILE__, __LINE__);
  957. $new_lp_id = Database::get_last_insert_id();
  958. if($lp->visibility) {
  959. $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'";
  960. api_sql_query($sql, __FILE__, __LINE__);
  961. }
  962. $new_item_ids = array();
  963. $parent_item_ids = array();
  964. $previous_item_ids = array();
  965. $next_item_ids = array();
  966. $old_prerequisite = array();
  967. $old_refs = array();
  968. $prerequisite_ids = array();
  969. foreach ($lp->get_items() as $index => $item) {
  970. /*
  971. if ($item['id'] != 0)
  972. {
  973. // Links in learnpath have types 'Link _self' or 'Link _blank'. We only need 'Link' here.
  974. $type_parts = explode(' ',$item['type']);
  975. $item['id'] = $this->course->resources[$type_parts[0]][$item['id']]->destination_id;
  976. }
  977. */
  978. /*
  979. //Get the new ref ID for all items that are not sco (dokeos quizzes, documents, etc)
  980. $ref = '';
  981. if(!empty($item['ref']) && $lp->lp_type!='2'){
  982. $ref = $this->get_new_id($item['item_type'],$item['ref']);
  983. } else {
  984. $ref = $item['ref'];
  985. }*/
  986. // we set the ref code here and then we update in a for loop
  987. $ref = $item['ref'];
  988. //Dealing with path the same way as ref as some data has been put into path when it's a
  989. //local resource
  990. $path = Database::escape_string($item['path']);
  991. if(strval(intval($path)) === $path) {
  992. $path = $this->get_new_id($item['item_type'],$path);
  993. }
  994. $sql = "INSERT INTO ".$table_item." SET " .
  995. "lp_id = '".Database::escape_string($new_lp_id)."', " .
  996. "item_type='".Database::escape_string($item['item_type'])."', " .
  997. "ref = '".Database::escape_string($ref)."', " .
  998. "title = '".Database::escape_string($item['title'])."', " .
  999. "description ='".Database::escape_string($item['description'])."', " .
  1000. "path = '".Database::escape_string($path)."', " .
  1001. "min_score = '".Database::escape_string($item['min_score'])."', " .
  1002. "max_score = '".Database::escape_string($item['max_score'])."', " .
  1003. "mastery_score = '".Database::escape_string($item['mastery_score'])."', " .
  1004. "parent_item_id = '".Database::escape_string($item['parent_item_id'])."', " .
  1005. "previous_item_id = '".Database::escape_string($item['previous_item_id'])."', " .
  1006. "next_item_id = '".Database::escape_string($item['next_item_id'])."', " .
  1007. "display_order = '".Database::escape_string($item['display_order'])."', " .
  1008. "prerequisite = '".Database::escape_string($item['prerequisite'])."', " .
  1009. "parameters='".Database::escape_string($item['parameters'])."', " .
  1010. "launch_data = '".Database::escape_string($item['launch_dataprereq_type'])."'";
  1011. api_sql_query($sql, __FILE__, __LINE__);
  1012. $new_item_id = Database::get_last_insert_id();
  1013. //save a link between old and new item IDs
  1014. $new_item_ids[$item['id']] = $new_item_id;
  1015. //save a reference of items that need a parent_item_id refresh
  1016. $parent_item_ids[$new_item_id] = $item['parent_item_id'];
  1017. //save a reference of items that need a previous_item_id refresh
  1018. $previous_item_ids[$new_item_id] = $item['previous_item_id'];
  1019. //save a reference of items that need a next_item_id refresh
  1020. $next_item_ids[$new_item_id] = $item['next_item_id'];
  1021. if (!empty($item['prerequisite'])) {
  1022. if ($lp->lp_type =='2') {
  1023. // if is an sco
  1024. $old_prerequisite[$new_item_id]= $item['prerequisite'];
  1025. } else {
  1026. $old_prerequisite[$new_item_id]= $new_item_ids[$item['prerequisite']];
  1027. }
  1028. }
  1029. if (!empty($ref)) {
  1030. if ($lp->lp_type =='2') {
  1031. // if is an sco
  1032. $old_refs[$new_item_id]= $ref;
  1033. } else {
  1034. $old_refs[$new_item_id]= $new_item_ids[$ref];
  1035. }
  1036. }
  1037. $prerequisite_ids[$new_item_id] = $item['prerequisite'];
  1038. }
  1039. // updating prerequisites
  1040. foreach ($old_prerequisite as $key=>$my_old_prerequisite) {
  1041. if($my_old_prerequisite != ''){
  1042. $sql = "UPDATE ".$table_item." SET prerequisite = '".$my_old_prerequisite."' WHERE id = '".$key."' ";
  1043. api_sql_query($sql, __FILE__, __LINE__);
  1044. }
  1045. }
  1046. //updating refs
  1047. foreach ($old_refs as $key=>$my_old_ref) {
  1048. if ($my_old_ref != '') {
  1049. $sql = "UPDATE ".$table_item." SET ref = '".$my_old_ref."' WHERE id = '".$key."' ";
  1050. api_sql_query($sql, __FILE__, __LINE__);
  1051. }
  1052. }
  1053. foreach ($parent_item_ids as $new_item_id => $parent_item_old_id) {
  1054. $parent_new_id = 0;
  1055. if($parent_item_old_id != 0){
  1056. $parent_new_id = $new_item_ids[$parent_item_old_id];
  1057. }
  1058. $sql = "UPDATE ".$table_item." SET parent_item_id = '".$parent_new_id."' WHERE id = '".$new_item_id."'";
  1059. api_sql_query($sql, __FILE__, __LINE__);
  1060. }
  1061. foreach ($previous_item_ids as $new_item_id => $previous_item_old_id) {
  1062. $previous_new_id = 0;
  1063. if($previous_item_old_id != 0){
  1064. $previous_new_id = $new_item_ids[$previous_item_old_id];
  1065. }
  1066. $sql = "UPDATE ".$table_item." SET previous_item_id = '".$previous_new_id."' WHERE id = '".$new_item_id."'";
  1067. api_sql_query($sql, __FILE__, __LINE__);
  1068. }
  1069. foreach ($next_item_ids as $new_item_id => $next_item_old_id) {
  1070. $next_new_id = 0;
  1071. if($next_item_old_id != 0){
  1072. $next_new_id = $new_item_ids[$next_item_old_id];
  1073. }
  1074. $sql = "UPDATE ".$table_item." SET next_item_id = '".$next_new_id."' WHERE id = '".$new_item_id."'";
  1075. api_sql_query($sql, __FILE__, __LINE__);
  1076. }
  1077. foreach ($prerequisite_ids as $new_item_id => $prerequisite_old_id)
  1078. {
  1079. $prerequisite_new_id = 0;
  1080. if($prerequisite_old_id != 0){
  1081. $prerequisite_new_id = $new_item_ids[$prerequisite_old_id];
  1082. }
  1083. $sql = "UPDATE ".$table_item." SET prerequisite = '".$prerequisite_new_id."' WHERE id = '".$new_item_id."'";
  1084. api_sql_query($sql, __FILE__, __LINE__);
  1085. }
  1086. $this->course->resources[RESOURCE_LEARNPATH][$id]->destination_id = $new_lp_id;
  1087. }
  1088. }
  1089. }
  1090. /**
  1091. * restore works
  1092. */
  1093. function restore_student_publication ()
  1094. {
  1095. $my_course_id=api_get_course_id();
  1096. $my_course_info=api_get_course_info($my_course_id);//student_publication_assignment
  1097. $my_tbl_db_spa_origin=Database :: get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT,$my_course_info['dbName']);
  1098. $my_tbl_db_spa_destination = Database :: get_course_table(TABLE_STUDENT_PUBLICATION_ASSIGNMENT, $this->course->destination_db);
  1099. $my_tbl_db_origin=Database :: get_course_table(TABLE_STUDENT_PUBLICATION,$my_course_info['dbName']);
  1100. $my_tbl_db_destination = Database :: get_course_table(TABLE_STUDENT_PUBLICATION, $this->course->destination_db);
  1101. $my_tbl_db_item_property_origin=Database :: get_course_table(TABLE_ITEM_PROPERTY, $my_course_info['dbName']);
  1102. $my_tbl_db_item_property_destination=Database :: get_course_table(TABLE_ITEM_PROPERTY, $this->course->destination_db);
  1103. //query in student publication
  1104. $query_sql_fin_sp='INSERT IGNORE INTO '.$my_tbl_db_destination.'' .
  1105. '(id,url,title,description,author,active,accepted,post_group_id,sent_date,' .
  1106. 'filetype,has_properties,view_properties,qualification,date_of_qualification,' .
  1107. 'parent_id,qualificator_id,session_id) ';
  1108. $query_sql_ini_sp='SELECT id,url,title,description,author,active,accepted,post_group_id,' .
  1109. 'sent_date,filetype,has_properties,view_properties,qualification,date_of_qualification,' .
  1110. 'parent_id,qualificator_id,session_id FROM '.$my_tbl_db_origin.' WHERE filetype="folder" ';
  1111. //var_dump($query_sql_ini_sp);
  1112. $destination='../../courses/'.$this->course->destination_path.'/work/';
  1113. $course_info=api_get_course_info(api_get_course_id());
  1114. $origin='../../courses/'.$course_info['path'].'/work/';
  1115. self::allow_create_all_directory($origin,$destination,false);
  1116. //query in item property
  1117. $query_sql_fin_ip='INSERT IGNORE INTO '.$my_tbl_db_item_property_destination.'' .
  1118. '(tool,insert_user_id,insert_date,lastedit_date,ref,lastedit_type,lastedit_user_id,to_group_id,' .
  1119. 'to_user_id,visibility,start_visible,end_visible) ';
  1120. $query_sql_ini_ip='SELECT tool,insert_user_id,insert_date,lastedit_date,ref,lastedit_type,' .
  1121. 'lastedit_user_id,to_group_id,to_user_id,visibility,start_visible,
  1122. end_visible FROM '.$my_tbl_db_item_property_origin.' ip INNER JOIN '.$my_tbl_db_origin.' sp' .
  1123. ' ON ip.ref=sp.id WHERE tool="work" ';
  1124. $query_sql_fin_sa='INSERT IGNORE INTO '.$my_tbl_db_spa_destination.'' .
  1125. '(id,expires_on,ends_on,add_to_calendar,enable_qualification,publication_id) ';
  1126. $query_sql_ini_sa='SELECT sa.id,sa.expires_on,sa.ends_on,sa.add_to_calendar,sa.enable_qualification,sa.publication_id FROM '.$my_tbl_db_spa_origin.' sa INNER JOIN '.$my_tbl_db_origin.' sp
  1127. ON sa.publication_id=sp.id WHERE filetype="folder" ';
  1128. $query_sql_sp = $query_sql_fin_sp.$query_sql_ini_sp;
  1129. $query_sql_ip = $query_sql_fin_ip.$query_sql_ini_ip;
  1130. $query_sql_sa = $query_sql_fin_sa.$query_sql_ini_sa;
  1131. api_sql_query($query_sql_sp,__FILE__,__LINE__);
  1132. api_sql_query($query_sql_ip,__FILE__,__LINE__);
  1133. api_sql_query($query_sql_sa,__FILE__,__LINE__);
  1134. }
  1135. /**
  1136. * copy all directory and sub directory
  1137. * @param string The path origin
  1138. * @param string The path destination
  1139. * @param boolean Option Overwrite
  1140. * @return void()
  1141. */
  1142. function allow_create_all_directory($source, $dest, $overwrite = false){
  1143. if(!is_dir($dest)) {
  1144. mkdir($dest);
  1145. }
  1146. if ($handle = opendir($source)) { // if the folder exploration is sucsessful, continue
  1147. while (false !== ($file = readdir($handle))) { // as long as storing the next file to $file is successful, continue
  1148. if ($file != '.' && $file != '..') {
  1149. $path = $source . '/' . $file;
  1150. if (is_file($path)) {
  1151. /* if (!is_file($dest . '/' . $file) || $overwrite)
  1152. if (!@copy($path, $dest . '/' . $file)) {
  1153. echo '<font color="red">File ('.$path.') '.get_lang('NotHavePermission').'</font>';
  1154. }*/
  1155. } elseif(is_dir($path)) {
  1156. if (!is_dir($dest . '/' . $file))
  1157. mkdir($dest . '/' . $file);
  1158. self:: allow_create_all_directory($path, $dest . '/' . $file, $overwrite);
  1159. }
  1160. }
  1161. }
  1162. closedir($handle);
  1163. }
  1164. }
  1165. /**
  1166. * Gets the new ID of one specific tool item from the tool name and the old ID
  1167. * @param string Tool name
  1168. * @param integer Old ID
  1169. * @return integer New ID
  1170. */
  1171. function get_new_id($tool,$ref)
  1172. {
  1173. //transform $tool into one backup/restore constant
  1174. if($tool == 'hotpotatoes'){$tool = 'document';}
  1175. if(!empty($this->course->resources[$tool][$ref]->destination_id)){
  1176. return $this->course->resources[$tool][$ref]->destination_id;
  1177. }
  1178. return '';
  1179. }
  1180. /**
  1181. * Restore glossary
  1182. */
  1183. function restore_glossary()
  1184. {
  1185. if ($this->course->has_resources(RESOURCE_GLOSSARY))
  1186. {
  1187. $table_glossary = Database :: get_course_table(TABLE_GLOSSARY, $this->course->destination_db);
  1188. $t_item_propery = Database :: get_course_table(TABLE_ITEM_PROPERTY, $this->course->destination_db);
  1189. $resources = $this->course->resources;
  1190. foreach ($resources[RESOURCE_GLOSSARY] as $id => $glossary) {
  1191. $this->course->resources[RESOURCE_GLOSSARY][$id]->destination_id = $glossary->glossary_id;
  1192. $sql = "INSERT INTO ".$table_glossary." SET glossary_id = '".Database::escape_string($glossary->glossary_id)."', name = '".Database::escape_string($glossary->name)."', description = '".Database::escape_string($glossary->description)."', display_order='".Database::escape_string($glossary->display_order)."'";
  1193. Database::query($sql, __FILE__, __LINE__);
  1194. }
  1195. }
  1196. }
  1197. }
  1198. ?>