CourseArchiver.class.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. require_once 'Course.class.php';
  4. require_once api_get_path(LIBRARY_PATH).'pclzip/pclzip.lib.php';
  5. /**
  6. * Some functions to write a course-object to a zip-file and to read a course-
  7. * object from such a zip-file.
  8. * @author Bart Mollet <bart.mollet@hogent.be>
  9. * @package chamilo.backup
  10. *
  11. * @todo Use archive-folder of Chamilo?
  12. */
  13. class CourseArchiver
  14. {
  15. /**
  16. * Delete old temp-dirs
  17. */
  18. function clean_backup_dir()
  19. {
  20. $dir = api_get_path(SYS_ARCHIVE_PATH);
  21. if ($handle = @ opendir($dir))
  22. {
  23. while (($file = readdir($handle)) !== false)
  24. {
  25. if ($file != "." && $file != ".." && strpos($file,'CourseArchiver_') === 0 && is_dir($dir.'/'.$file))
  26. {
  27. rmdirr($dir.'/'.$file);
  28. }
  29. }
  30. closedir($handle);
  31. }
  32. }
  33. /**
  34. * Write a course and all its resources to a zip-file.
  35. * @return string A pointer to the zip-file
  36. */
  37. function write_course($course) {
  38. $perm_dirs = api_get_permissions_for_new_directories();
  39. CourseArchiver::clean_backup_dir();
  40. // Create a temp directory
  41. $tmp_dir_name = 'CourseArchiver_'.api_get_unique_id();
  42. $backup_dir = api_get_path(SYS_ARCHIVE_PATH).$tmp_dir_name.'/';
  43. // All course-information will be stored in course_info.dat
  44. $course_info_file = $backup_dir.'course_info.dat';
  45. $zip_dir = api_get_path(SYS_ARCHIVE_PATH);
  46. $user = api_get_user_info();
  47. $zip_file = $user['user_id'].'_'.$course->code.'_'.date("Ymd-His").'.zip';
  48. $php_errormsg = '';
  49. $res = @mkdir($backup_dir, $perm_dirs);
  50. if ($res === false)
  51. {
  52. //TODO set and handle an error message telling the user to review the permissions on the archive directory
  53. error_log(__FILE__.' line '.__LINE__.': '.(ini_get('track_errors')!=false?$php_errormsg:'error not recorded because track_errors is off in your php.ini').' - This error, occuring because your archive directory will not let this script write data into it, will prevent courses backups to be created',0);
  54. }
  55. // Write the course-object to the file
  56. $fp = @fopen($course_info_file, 'w');
  57. if ($fp === false)
  58. {
  59. error_log(__FILE__.' line '.__LINE__.': '.(ini_get('track_errors')!=false?$php_errormsg:'error not recorded because track_errors is off in your php.ini'),0);
  60. }
  61. $res = @fwrite($fp, base64_encode(serialize($course)));
  62. if ($res === false)
  63. {
  64. error_log(__FILE__.' line '.__LINE__.': '.(ini_get('track_errors')!=false?$php_errormsg:'error not recorded because track_errors is off in your php.ini'),0);
  65. }
  66. $res = @fclose($fp);
  67. if ($res === false)
  68. {
  69. error_log(__FILE__.' line '.__LINE__.': '.(ini_get('track_errors')!=false?$php_errormsg:'error not recorded because track_errors is off in your php.ini'),0);
  70. }
  71. // Copy all documents to the temp-dir
  72. if (is_array($course->resources[RESOURCE_DOCUMENT])) {
  73. foreach ($course->resources[RESOURCE_DOCUMENT] as $id => $document) {
  74. if ($document->file_type == DOCUMENT) {
  75. $doc_dir = $backup_dir.$document->path;
  76. @mkdir(dirname($doc_dir), $perm_dirs, true);
  77. if (file_exists($course->path.$document->path)) {
  78. copy($course->path.$document->path, $doc_dir);
  79. }
  80. } else {
  81. @mkdir($backup_dir.$document->path, $perm_dirs, true);
  82. }
  83. }
  84. }
  85. // Copy all scorm documents to the temp-dir
  86. if (is_array($course->resources[RESOURCE_SCORM])) {
  87. foreach ($course->resources[RESOURCE_SCORM] as $id => $document) {
  88. $doc_dir = dirname($backup_dir.$document->path);
  89. @mkdir($doc_dir, $perm_dirs, true);
  90. copyDirTo($course->path.$document->path, $doc_dir, false);
  91. }
  92. }
  93. //Copy calendar attachments
  94. if (is_array($course->resources[RESOURCE_EVENT])) {
  95. $doc_dir = dirname($backup_dir.'/upload/calendar/');
  96. @mkdir($doc_dir, $perm_dirs, true);
  97. copyDirTo($course->path.'upload/calendar/', $doc_dir, false);
  98. }
  99. //Copy learningpath author image
  100. if (is_array($course->resources[RESOURCE_LEARNPATH])) {
  101. $doc_dir = dirname($backup_dir.'/upload/learning_path/');
  102. @mkdir($doc_dir, $perm_dirs, true);
  103. copyDirTo($course->path.'upload/learning_path/', $doc_dir, false);
  104. }
  105. //Copy announcements attachments
  106. if (is_array($course->resources[RESOURCE_ANNOUNCEMENT])) {
  107. $doc_dir = dirname($backup_dir.'/upload/announcements/');
  108. @mkdir($doc_dir, $perm_dirs, true);
  109. copyDirTo($course->path.'upload/announcements/', $doc_dir, false);
  110. }
  111. // Zip the course-contents
  112. $zip = new PclZip($zip_dir.$zip_file);
  113. $zip->create($zip_dir.$tmp_dir_name, PCLZIP_OPT_REMOVE_PATH, $zip_dir.$tmp_dir_name.'/');
  114. //$zip->deleteByIndex(0);
  115. // Remove the temp-dir.
  116. rmdirr($backup_dir);
  117. return ''.$zip_file;
  118. }
  119. /**
  120. *
  121. */
  122. function get_available_backups($user_id = null)
  123. {
  124. global $dateTimeFormatLong;
  125. $backup_files = array();
  126. $dirname = api_get_path(SYS_ARCHIVE_PATH).'';
  127. if ($dir = opendir($dirname)) {
  128. while (($file = readdir($dir)) !== false) {
  129. $file_parts = explode('_',$file);
  130. if(count($file_parts) == 3)
  131. {
  132. $owner_id = $file_parts[0];
  133. $course_code = $file_parts[1];
  134. $file_parts = explode('.',$file_parts[2]);
  135. $date = $file_parts[0];
  136. $ext = $file_parts[1];
  137. if($ext == 'zip' && ($user_id != null && $owner_id == $user_id || $user_id == null) )
  138. {
  139. $date = substr($date,0,4).'-'.substr($date,4,2).'-'.substr($date,6,2).' '.substr($date,8,2).':'.substr($date,10,2).':'.substr($date,12,2);
  140. $backup_files[] = array('file' => $file, 'date' => $date, 'course_code' => $course_code);
  141. }
  142. }
  143. }
  144. closedir($dir);
  145. }
  146. return $backup_files;
  147. }
  148. /**
  149. *
  150. */
  151. function import_uploaded_file($file)
  152. {
  153. $new_filename = uniqid('').'.zip';
  154. $new_dir = api_get_path(SYS_ARCHIVE_PATH);
  155. if(is_dir($new_dir) && is_writable($new_dir))
  156. {
  157. move_uploaded_file($file,api_get_path(SYS_ARCHIVE_PATH).''.$new_filename);
  158. return $new_filename;
  159. }
  160. return false;
  161. }
  162. /**
  163. * Read a course-object from a zip-file
  164. * @return course The course
  165. * @param boolean $delete Delete the file after reading the course?
  166. * @todo Check if the archive is a correct Chamilo-export
  167. */
  168. function read_course($filename,$delete = false)
  169. {
  170. CourseArchiver::clean_backup_dir();
  171. // Create a temp directory
  172. $tmp_dir_name = 'CourseArchiver_'.uniqid('');
  173. $unzip_dir = api_get_path(SYS_ARCHIVE_PATH).''.$tmp_dir_name;
  174. @mkdir($unzip_dir, api_get_permissions_for_new_directories(), true);
  175. @copy(api_get_path(SYS_ARCHIVE_PATH).''.$filename,$unzip_dir.'/backup.zip');
  176. // unzip the archive
  177. $zip = new PclZip($unzip_dir.'/backup.zip');
  178. @chdir($unzip_dir);
  179. $zip->extract();
  180. // remove the archive-file
  181. if($delete)
  182. {
  183. @unlink(api_get_path(SYS_ARCHIVE_PATH).''.$filename);
  184. }
  185. // read the course
  186. if(!is_file('course_info.dat'))
  187. {
  188. return new Course();
  189. }
  190. $fp = @fopen('course_info.dat', "r");
  191. $contents = @fread($fp, filesize('course_info.dat'));
  192. @fclose($fp);
  193. // CourseCopyLearnpath class appeared in Chamilo 1.8.7, it is the former Learnpath class in the "Copy course" tool.
  194. // For backward comaptibility with archives created on Chamilo 1.8.6.2 or older systems, we have to do the following:
  195. // Before unserialization, if class name "Learnpath" was found, it should be renamed as "CourseCopyLearnpath".
  196. $course = unserialize(str_replace('O:9:"Learnpath":', 'O:19:"CourseCopyLearnpath":', base64_decode($contents)));
  197. if( get_class($course) != 'Course')
  198. {
  199. return new Course();
  200. }
  201. $course->backup_path = $unzip_dir;
  202. return $course;
  203. }
  204. }