made a copy
[atutor.git] / tools / tests / import_test.php
1 <?php
2 /************************************************************************/
3 /* ATutor                                                                                                                               */
4 /************************************************************************/
5 /* Copyright (c) 2002-2008 by Greg Gay, Harris Wong                                             */
6 /* Adaptive Technology Resource Centre / University of Toronto                  */
7 /* http://atutor.ca                                                                                                             */
8 /*                                                                                                                                              */
9 /* This program is free software. You can redistribute it and/or                */
10 /* modify it under the terms of the GNU General Public License                  */
11 /* as published by the Free Software Foundation.                                                */
12 /************************************************************************/
13 // $Id$
14 define('AT_INCLUDE_PATH', '../../include/');
15 require(AT_INCLUDE_PATH.'vitals.inc.php');
16 require(AT_INCLUDE_PATH.'lib/filemanager.inc.php'); /* for clr_dir() and preImportCallBack and dirsize() */
17 require(AT_INCLUDE_PATH.'lib/qti.inc.php'); 
18 require(AT_INCLUDE_PATH.'classes/pclzip.lib.php');
19 //require(AT_INCLUDE_PATH.'classes/QTI/QTIParser.class.php');   
20 require(AT_INCLUDE_PATH.'classes/QTI/QTIImport.class.php');
21
22 /* to avoid timing out on large files */
23 @set_time_limit(0);
24 $_SESSION['done'] = 1;
25
26 $element_path = array();
27 $character_data = '';
28 $test_title = '';
29 $resource_num = 0;
30 $qids = array();        //store all the question ids that's being inserted into the db by this import
31 $overwrite = false;     //files will not be overwrite and prompt
32
33 /* handle get */
34 if (isset($_POST['submit_yes'])){
35         $overwrite = true;
36 } elseif (isset($_POST['submit_no'])){
37         $msg->addFeedback('IMPORT_CANCELLED');
38         header('Location: index.php');
39         exit;
40 }
41
42 /* functions */
43 /* called at the start of en element */
44 /* builds the $path array which is the path from the root to the current element */
45 function startElement($parser, $name, $attrs) {
46         global $attributes, $element_path, $resource_num;
47         //save attributes.
48         switch($name) {
49                 case 'resource':
50                         $attributes[$name.$resource_num]['identifier'] = $attrs['identifier'];
51                         $attributes[$name.$resource_num]['href'] = $attrs['href'];
52                         $attributes[$name.$resource_num]['type'] = $attrs['type'];
53                         $resource_num++;
54                         break;
55                 case 'file':
56                         if(in_array('resource', $element_path)){
57                                 $attributes['resource'.($resource_num-1)]['file'][] = $attrs['href'];
58                         }
59                         break;
60                 case 'dependency':
61                         if(in_array('resource', $element_path)){
62                                 $attributes['resource'.($resource_num-1)]['dependency'][] = $attrs['identifierref'];
63                         }
64                         break;
65
66         }
67         array_push($element_path, $name);               
68 }
69
70 /* called when an element ends */
71 /* removed the current element from the $path */
72 function endElement($parser, $name) {
73         global $element_path, $test_title, $character_data;
74         switch($name) {
75                 case 'title':
76                         if (in_array('organization', $element_path)){
77                                 $test_title = $character_data;
78                         }
79         }
80         $character_data = '';
81         array_pop($element_path);
82 }
83
84 /* called when there is character data within elements */
85 /* constructs the $items array using the last entry in $path as the parent element */
86 function characterData($parser, $data){
87         global $character_data;
88         if (trim($data)!=''){
89                 $character_data .= preg_replace('/[\t\0\x0B]*/', '', $data);
90         }
91 }
92
93 //If overwrite hasn't been set to true, then the file has not been exported and still in the cache.
94 //otherwise, the zip file is extracted but has not been deleted (due to the confirmation).
95 if (!$overwrite){
96         if (!isset($_POST['submit_import'])) {
97                 /* just a catch all */
98                 
99                 $errors = array('FILE_MAX_SIZE', ini_get('post_max_size'));
100                 $msg->addError($errors);
101
102                 header('Location: ./index.php');
103                 exit;
104         } 
105
106
107         //Handles import
108         /*
109         if (isset($_POST['url']) && ($_POST['url'] != 'http://') ) {
110                 if ($content = @file_get_contents($_POST['url'])) {
111
112                         // save file to /content/
113                         $filename = substr(time(), -6). '.zip';
114                         $full_filename = AT_CONTENT_DIR . $filename;
115
116                         if (!$fp = fopen($full_filename, 'w+b')) {
117                                 echo "Cannot open file ($filename)";
118                                 exit;
119                         }
120
121                         if (fwrite($fp, $content, strlen($content) ) === FALSE) {
122                                 echo "Cannot write to file ($filename)";
123                                 exit;
124                         }
125                         fclose($fp);
126                 }       
127                 $_FILES['file']['name']     = $filename;
128                 $_FILES['file']['tmp_name'] = $full_filename;
129                 $_FILES['file']['size']     = strlen($content);
130                 unset($content);
131                 $url_parts = pathinfo($_POST['url']);
132                 $package_base_name_url = $url_parts['basename'];
133         }
134         */
135         $ext = pathinfo($_FILES['file']['name']);
136         $ext = $ext['extension'];
137
138         if ($ext != 'zip') {
139                 $msg->addError('IMPORTDIR_IMS_NOTVALID');
140         } else if ($_FILES['file']['error'] == 1) {
141                 $errors = array('FILE_MAX_SIZE', ini_get('upload_max_filesize'));
142                 $msg->addError($errors);
143         } else if ( !$_FILES['file']['name'] || (!is_uploaded_file($_FILES['file']['tmp_name']) && !$_POST['url'])) {
144                 $msg->addError('FILE_NOT_SELECTED');
145         } else if ($_FILES['file']['size'] == 0) {
146                 $msg->addError('IMPORTFILE_EMPTY');
147         } 
148 }
149
150 if ($msg->containsErrors()) {
151         if (isset($_GET['tile'])) {
152                 header('Location: '.$_base_path.'tools/tile/index.php');
153         } else {
154                 header('Location: index.php');
155         }
156         exit;
157 }
158
159 /* check if ../content/import/ exists */
160 $import_path = AT_CONTENT_DIR . 'import/';
161 $content_path = AT_CONTENT_DIR;
162
163 if (!is_dir($import_path)) {
164         if (!@mkdir($import_path, 0700)) {
165                 $msg->addError('IMPORTDIR_FAILED');
166         }
167 }
168
169 $import_path .= $_SESSION['course_id'].'/';
170 if (!$overwrite){
171         if (is_dir($import_path)) {
172                 clr_dir($import_path);
173         }
174
175         if (!@mkdir($import_path, 0700)) {
176                 $msg->addError('IMPORTDIR_FAILED');
177         }
178
179         /* extract the entire archive into AT_COURSE_CONTENT . import/$course using the call back function to filter out php files */
180         error_reporting(0);
181         $archive = new PclZip($_FILES['file']['tmp_name']);
182         if ($archive->extract(  PCLZIP_OPT_PATH,        $import_path,
183                                                         PCLZIP_CB_PRE_EXTRACT,  'preImportCallBack') == 0) {
184                 $msg->addError('IMPORT_FAILED');
185                 echo 'Error : '.$archive->errorInfo(true);
186                 clr_dir($import_path);
187                 header('Location: questin_db.php');
188                 exit;
189         }
190         error_reporting(AT_ERROR_REPORTING);
191 }
192 /* get the course's max_quota */
193 $sql    = "SELECT max_quota FROM ".TABLE_PREFIX."courses WHERE course_id=$_SESSION[course_id]";
194 $result = mysql_query($sql, $db);
195 $q_row  = mysql_fetch_assoc($result);
196
197 if ($q_row['max_quota'] != AT_COURSESIZE_UNLIMITED) {
198
199         if ($q_row['max_quota'] == AT_COURSESIZE_DEFAULT) {
200                 $q_row['max_quota'] = $MaxCourseSize;
201         }
202         $totalBytes   = dirsize($import_path);
203         $course_total = dirsize(AT_CONTENT_DIR . $_SESSION['course_id'].'/');
204         $total_after  = $q_row['max_quota'] - $course_total - $totalBytes + $MaxCourseFloat;
205
206         if ($total_after < 0) {
207                 /* remove the content dir, since there's no space for it */
208                 $errors = array('NO_CONTENT_SPACE', number_format(-1*($total_after/AT_KBYTE_SIZE), 2 ) );
209                 $msg->addError($errors);
210                 
211                 clr_dir($import_path);
212
213                 if (isset($_GET['tile'])) {
214                         header('Location: '.$_base_path.'tools/tile/index.php');
215                 } else {
216                         header('Location: index.php');
217                 }
218                 exit;
219         }
220 }
221
222 $ims_manifest_xml = @file_get_contents($import_path.'imsmanifest.xml');
223
224 if ($ims_manifest_xml === false) {
225         $msg->addError('NO_IMSMANIFEST');
226
227         if (file_exists($import_path . 'atutor_backup_version')) {
228                 $msg->addError('NO_IMS_BACKUP');
229         }
230
231         clr_dir($import_path);
232
233         if (isset($_GET['tile'])) {
234                 header('Location: '.$_base_path.'tools/tile/index.php');
235         } else {
236                 header('Location: index.php');
237         }
238         exit;
239 }
240
241 $xml_parser = xml_parser_create();
242
243 xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false); /* conform to W3C specs */
244 xml_set_element_handler($xml_parser, 'startElement', 'endElement');
245 xml_set_character_data_handler($xml_parser, 'characterData');
246
247 if (!xml_parse($xml_parser, $ims_manifest_xml, true)) {
248         die(sprintf("XML error: %s at line %d",
249                                 xml_error_string(xml_get_error_code($xml_parser)),
250                                 xml_get_current_line_number($xml_parser)));
251 }
252
253 xml_parser_free($xml_parser);
254
255 //assign folder names
256 //if (!$package_base_name){
257 //      $package_base_name = substr($_FILES['file']['name'], 0, -4);
258 //}
259
260 //$package_base_name = strtolower($package_base_name);
261 //$package_base_name = str_replace(array('\'', '"', ' ', '|', '\\', '/', '<', '>', ':'), '_' , $package_base_name);
262 //$package_base_name = preg_replace("/[^A-Za-z0-9._\-]/", '', $package_base_name);
263
264 //if (is_dir(AT_CONTENT_DIR . $_SESSION['course_id'].'/'.$package_base_name)) {
265 //      echo 'Already exist: Quitting.  (Need better msg here)';
266 //      exit;
267 //      $package_base_name .= '_'.date('ymdHis');
268 //}
269
270 if ($package_base_path) {
271         $package_base_path = implode('/', $package_base_path);
272 }
273
274 //debug($attributes);
275 //Dependency handling
276 //$media_items = array();
277 $xml_items = array();
278 //foreach($attributes as $resource=>$attrs){
279 //      if ($attrs['type'] != 'webcontent'){
280 //              $media_items[$attrs['identifier']] = $attrs['file'];
281 //      }
282 //}
283
284 //Check if the files exist, if so, warn the user.
285 $existing_files = isQTIFileExist($attributes);
286 //debug($existing_files);
287 if (!$overwrite && !empty($existing_files)){
288         $existing_files = implode('<br/>', $existing_files);
289         require(AT_INCLUDE_PATH.'header.inc.php');
290 //      $msg->addConfirm(array('MEDIA_FILE_EXISTED', $existing_files));
291 //      $msg->printConfirm();
292         echo '<form action="" method="POST">';
293         echo '<div class="input-form">';
294         echo '<div class="row">';
295         $msg->printInfos(array('MEDIA_FILE_EXISTED', $existing_files));
296         echo '</div>';
297         echo '<div class="row buttons">';
298         echo '<input type="submit" class="" name="submit_yes" value="'._AT('yes').'"/>';
299         echo '<input type="submit" class="" name="submit_no" value="'._AT('no').'"/>';
300         echo '<input type="hidden" name="submit_import" value="submit_import" />';
301         ECHO '<input type="hidden" name="url" value="'.$_POST['url'].'" />';
302         echo '</div></div>';
303         echo '</form>';
304         require (AT_INCLUDE_PATH.'footer.inc.php');
305
306         exit;
307 }
308
309 //Get the XML file out and start importing them into our database.
310 //TODO: See question_import.php 287-289.
311 $qti_import =& new QTIImport($import_path);
312 $qids = $qti_import->importQuestions($attributes);
313
314 //import test
315 $tid = $qti_import->importTest();
316
317 //associate question and tests
318 foreach ($qids as $order=>$qid){
319         if (isset($qti_import->weights[$order])){
320                 $weight = round($qti_import->weights[$order]);
321         } else {
322                 $weight = 0;
323         }
324         $new_order = $order + 1;
325         $sql = "INSERT INTO " . TABLE_PREFIX . "tests_questions_assoc" . 
326                         "(test_id, question_id, weight, ordering, required) " .
327                         "VALUES ($tid, $qid, $weight, $new_order, 0)";
328         $result = mysql_query($sql, $db);
329 }
330 //debug('imported test');
331 if (!$msg->containsErrors()) {
332         $msg->addFeedback('IMPORT_SUCCEEDED');
333 }
334
335 //clear directory
336 clr_dir(AT_CONTENT_DIR . 'import/'.$_SESSION['course_id']);
337
338 header('Location: index.php');
339 exit;
340 ?>