Automatic installer.php lang files by installer_builder (20070726)
[moodle-linuxchix.git] / question / format / coursetestmanager / format.php
blobb80cf24d4f90dba02d92b0fb63d884dc906e9018
1 <?php // $Id$
2 ////////////////////////////////////////////////////////////////////
3 /// Class for importing course test manager questions. //
4 /// //
5 /// //
6 ////////////////////////////////////////////////////////////////////
8 // Based on format.php, included by ../../import.php
9 /**
10 * @package questionbank
11 * @subpackage importexport
14 require_once($CFG->dirroot.'/lib/uploadlib.php');
16 class qformat_coursetestmanager extends qformat_default {
18 function provide_import() {
19 return true;
22 function importpreprocess($category) {
23 $this->category = $category; // Important
24 return true;
27 function importprocess($filename) {
28 global $CFG,$strimportquestions,$form,$question_category,$category,$course,
29 $hostname, $mdapath, $mdbpath;
30 if ((PHP_OS == "Linux") and isset($hostname)) {
31 $hostname = trim($hostname);
32 // test the ODBC socket server connection
33 // if failure, unset hostname and set hostname_access_error
34 $question_categories = $this->getquestioncategories($mdbpath, $mdapath, $hostname);
35 if (!$question_categories) {
36 $hostname_access_error = $hostname . " ";
37 unset($hostname);
38 } else {
39 $hostname_access_error = 0;
43 if ((PHP_OS == "Linux") and !isset($hostname)) {
44 // copy the file to a semi-permanent location
45 if (! $basedir = make_upload_directory("$course->id")) {
46 error("The site administrator needs to fix the file permissions for the data directory");
48 if (!isset($hostname_access_error)) {
49 $bname=basename($filename);
50 $cleanfilename = clean_filename($bname);
51 if ($cleanfilename) {
52 $newfile = "$basedir/$cleanfilename";
53 if (move_uploaded_file($filename, $newfile)) {
54 chmod($newfile, 0666);
55 clam_log_upload($newfile,$course);
56 } else {
57 notify(get_string("uploadproblem", "", $filename));
60 $filename = $newfile;
62 print_heading_with_help($strimportquestions, "import", "quiz");
63 print_simple_box_start("center");
64 if ($hostname_access_error) { notify("couldn't connect to ODBC Socket Server on " . $hostname_access_error); }
65 echo "<form method=\"post\" action=\"import.php\">";
66 echo '<fieldset class="invisiblefieldset">';
67 echo "<table cellpadding=\"5\">";
69 echo "<tr><td align=\"right\">";
70 echo "What is the hostname or IP address of the ODBC Socket Server:</td><td>";
71 echo " <input name=\"hostname\" type=\"text\" size=\"50\" value=\"".stripslashes($hostname_access_error)."\" />";
72 echo " <input name=\"filename\" type=\"hidden\" value=\"".$filename."\" />";
73 echo " <input name=\"category\" type=\"hidden\" value=\"".$category->id."\" />";
74 echo " <input name=\"format\" type=\"hidden\" value=\"".$form->format."\" />";
75 echo "</td><td>&nbsp;</td></tr>";
76 echo "<tr><td align=\"right\">";
77 echo "What is the location of the database (.mdb file) on the Socket Server:</td><td>";
78 echo " <input name=\"mdbpath\" type=\"text\" size=\"50\" value=\"".stripslashes($mdbpath)."\" />";
79 echo "</td><td>&nbsp;</td></tr>";
80 echo "<tr><td align=\"right\">";
81 echo "What is the location of the system database (System.mda file) on the Socket Server:</td><td>";
82 echo " <input name=\"mdapath\" type=\"text\" size=\"50\" value=\"".stripslashes($mdapath)."\" />";
83 echo "</td><td>&nbsp;</td></tr>";
84 echo "<tr><td>&nbsp;</td><td>";
85 echo " <input type=\"submit\" name=\"save\" value=\"Connect to Server\" />";
86 echo "</td></tr>";
87 echo "</table>";
88 echo '</fieldset>';
89 echo "</form>";
90 print_simple_box_end();
91 print_footer($course);
92 exit;
95 // we get here if running windows or after connect to ODBC socket server on linux
97 // this generates the page to choose categories of questions to import
99 if (!isset($question_category)) {
101 if (PHP_OS == "WINNT") {
102 // copy the file to a semi-permanent location
103 if (! $basedir = make_upload_directory("$course->id")) {
104 error("The site administrator needs to fix the file permissions for the data directory");
106 $bname=basename($filename);
107 $cleanfilename = clean_filename($bname);
108 if ($cleanfilename) {
109 $newfile = "$basedir/$cleanfilename";
110 if (move_uploaded_file($filename, $newfile)) {
111 chmod($newfile, 0666);
112 clam_log_upload($newfile,$course);
113 } else {
114 notify(get_string("uploadproblem", "", $filename));
117 $filename = $newfile;
119 // end of file copy
121 // don't have to do this on linux, since it's alreay been done in the test above
122 if (PHP_OS == "WINNT") {
123 $question_categories = $this->getquestioncategories($filename);
125 // print the intermediary form
126 if (!$categories = question_category_options($course->id, true)) {
127 error("No categories!");
129 print_heading_with_help($strimportquestions, "import", "quiz");
130 print_simple_box_start("center");
131 echo "<form method=\"post\" action=\"import.php\">";
132 echo '<fieldset class="invisiblefieldset">';
133 echo "<table cellpadding=\"5\">";
134 echo "<tr><td align=\"right\">";
135 echo "Choose a category of questions to import:</td><td>";
136 asort($question_categories);
137 choose_from_menu($question_categories, "question_category","All Categories","All Categories", "", "allcategories");
138 echo " <input name=\"filename\" type=\"hidden\" value=\"".$filename."\" />";
139 echo " <input name=\"category\" type=\"hidden\" value=\"".$category->id."\" />";
140 echo " <input name=\"format\" type=\"hidden\" value=\"".$form->format."\" />";
141 if (PHP_OS == "Linux") {
142 echo " <input name=\"hostname\" type=\"hidden\" value=\"".stripslashes(trim($hostname))."\" />";
143 echo " <input name=\"mdbpath\" type=\"hidden\" value=\"".stripslashes($mdbpath)."\" />";
144 echo " <input name=\"mdapath\" type=\"hidden\" value=\"".stripslashes($mdapath)."\" />";
146 echo "</td><td>&nbsp;</td>";
147 echo "</tr><tr><td>&nbsp;</td><td>";
148 echo " <input type=\"submit\" name=\"save\" value=\"Import Questions\" />";
149 echo "</td></tr>";
150 echo "</table>";
151 echo '</fieldset>';
152 echo "</form>";
153 print_simple_box_end();
154 print_footer($course);
155 exit;
158 // this is the main import section
160 notify("Importing questions");
161 if (PHP_OS == "Linux") {
162 $hostname = trim($hostname);
163 $records = $this->getquestions($mdbpath,$question_category,$mdapath, $hostname);
164 } else {
165 $records = $this->getquestions($filename,$question_category);
167 foreach ($records as $qrec) {
168 $question = $this->defaultquestion();
169 if ($qrec[9] != "") {
170 $question->image = $qrec[9];
172 // 0 Selected
173 // 1 PracticeTestOK?
174 // 2 QuestionText
175 // 3 QuestionType
176 // 4 Option1Text
177 // 5 Option2Text
178 // 6 Option3Text
179 // 7 Option4Text
180 // 8 CorrectAnswer
181 // 9 Graphic
182 // 10 Module
183 // 11 ChapterNumber
184 // 12 PageNumber
185 $ref = "Answer can be found in chapter ". $qrec[11] . ", page " . $qrec[12] . ".";
186 switch ($qrec[3]) {
187 case 1:
188 $question->qtype = MULTICHOICE; // MULTICHOICE, SHORTANSWER, TRUEFALSE
189 // echo "<pre>";echo htmlspecialchars($qrec[2]); echo "</pre>";
190 $question->questiontext = addslashes(trim($qrec[2]));
191 // echo "<pre>";echo $question->questiontext; echo "</pre>";
192 $question->name = preg_replace("/<br />/", "", $question->questiontext);
193 $question->single = 1; // Only one answer is allowed -- used for multiple choicers
194 $fractionset = 0;
195 for ($i=4;$i<=7;$i++) {
196 if ($qrec[$i] != "") {
197 $question->answer[$i-3]=addslashes($qrec[$i]);
198 if ($qrec[8] == $i-3) { // if this is the index of CorrectAnswer
199 $question->fraction[$i-3] = 1;
200 $fractionset = 1;
201 } else {
202 $question->fraction[$i-3] = 0;
204 $question->feedback[$i-3] = (($qrec[8] == $i-3)?"Correct. ":"Incorrect. ") . $ref;
207 if ($fractionset == 0) {
208 $question->fraction[1] = 1;
210 break;
211 case 2: // TRUE FALSE
212 $question->qtype = TRUEFALSE;
213 $question->questiontext = addslashes(trim($qrec[2]));
214 $question->name = preg_replace("/<br />/", "", $question->questiontext);
215 // for TF, $question->answer should be 1 for true, 0 for false
216 if ($qrec[8] == "T") {
217 $question->answer =1;
218 } else {
219 $question->answer = 0;
221 // for TF, use $question->feedbacktrue and feedbackfalse
222 $question->feedbacktrue = (($qrec[8] =="T")?"Correct. ":"Incorrect. ") . $ref;
223 $question->feedbackfalse = (($qrec[8] =="F")?"Correct. ":"Incorrect. ") . $ref;
224 break;
225 case 3:
226 $question->qtype = SHORTANSWER;
227 $question->questiontext = addslashes(trim($qrec[2]));
228 // echo "<pre>";echo $question->questiontext; echo "</pre>";
229 $question->name = preg_replace("/<br />/", "", $question->questiontext);
230 $question->usecase=0; // Ignore case -- for SHORT ANSWER questions
231 $answers = explode("~", $qrec[8]);
232 $question->answer[0]=" ";
233 $question->fraction[0]=1;
234 for ($i=0;$i<count($answers);$i++) {
235 $question->answer[$i] = addslashes(trim($answers[$i]));
236 $question->feedback[$i] = $ref;
237 $question->fraction[$i] = 1; // 1 for 100%, 0 for none or somewhere in between
239 break;
240 case 4:
241 $question = 0;
242 notify("Cannot use essay questions - skipping question ". $qrec[2] . " " . $ref);
243 break;
244 default:
245 $question = 0;
246 notify("Misformatted Record. Question Skipped.");
247 break;
249 if ($question) {
250 $questions[] = $question;
253 $count = 0;
254 // process all the questions
255 if (PHP_OS == "WINNT") {
256 $filename = str_replace("\\\\","\\",$filename);
257 $filename = str_replace("/","\\",$filename);
259 foreach ($questions as $question) { // Process and store each question
260 $count++;
261 echo "<hr /><p><b>$count</b>. ".stripslashes($question->questiontext)."</p>";
262 $question->category = $this->category->id;
263 $question->stamp = make_unique_id_code(); // Set the unique code (not to be changed)
264 if (!$question->id = insert_record("question", $question)) {
265 error("Could not insert new question!");
267 $this->questionids[] = $question->id;
268 // Now to save all the answers and type-specific options
269 $result = save_question_options($question);
270 if (!empty($result->error)) {
271 notify($result->error);
272 $this->deletedatabase($filename);
273 return false;
275 if (!empty($result->notice)) {
276 notify($result->notice);
277 $this->deletedatabase($filename);
278 return true;
280 // Give the question a unique version stamp determined by question_hash()
281 set_field('question', 'version', question_hash($question), 'id', $question->id);
283 $this->deletedatabase($filename);
284 return true;
287 function importpostprocess() {
288 return true;
291 function deletedatabase($filename) {
292 if (! $this->fulldelete($filename)) {
293 echo "<br />Error: Could not delete: $filename";
294 return false;
296 return true;
299 function getquestions($filename, $category, $mdapath="", $hostname="") {
300 if (($category == "allcategories") or ($category == "")) {
301 $sql = "SELECT * FROM TBQuestions";
302 } else {
303 $sql = "SELECT * FROM TBQuestions where module = '".$category."'";
305 if (PHP_OS == "WINNT") {
306 $ldb =& $this->connect_win($filename);
307 $qset = $ldb->Execute("$sql");
308 if ( $qset->RecordCount() > 0 ) {
309 $records = $qset->GetAssoc(true);
310 } else {
311 $this->err("There were no records in the database.",$dsn);
312 $ldb->Close();
313 return false;
315 $ldb->Close();
316 } else { // if PHP_OS == WINNT
317 // we have a linux installation
318 $result = $this->query_linux($sql,$filename, $mdapath,$hostname);
319 if ( count($result) > 0 ) {
320 // get rid of the ID field in the first column.
321 for($i=0;$i<count($result);$i++) {
322 foreach (array_keys($result[$i]) as $j) {
323 $records[$i][$j-1] = $result[$i][$j];
326 } else {
327 $this->err("There were no records in the database.",$dsn);
328 $ldb->Close();
329 return false;
331 // xml test and connect
332 } // PHP_OS TEST
333 return $records;
336 function getquestioncategories($filename, $mdapath="", $hostname="") {
337 global $CFG, $result;
338 $sql = "SELECT Distinct module FROM TBQuestions";
339 if (PHP_OS == "WINNT") {
340 $ldb =& $this->connect_win($filename);
341 $qset = $ldb->Execute("$sql");
342 if ( $qset->RecordCount() > 0 ) {
343 $records = $qset->GetArray(true);
344 foreach ($records as $record) {
345 $categories[$record[0]] = $record[0];
347 } else { // if recordcount
348 $this->err("There were no records in the database.",$dsn);
349 $ldb->Close();
350 return false;
352 $ldb->Close();
353 } else { // if PHP_OS == WINNT
354 // we have a linux installation
355 $result = $this->query_linux($sql, $filename, $mdapath, $hostname);
356 for($i=0;$i<count($result);$i++) {
357 $categories[$result[$i][0]] = $result[$i][0];
359 } // PHP_OS TEST
360 return $categories;
363 function query_linux($sql, $mdbpath, $mdapath, $hostname) {
364 global $result;
365 include_once("odbcsocketserver.class.php");
366 // set up socket server object to connect to remote host
367 $oTest = new ODBCSocketServer;
368 //Set the Hostname, port, and connection string
369 $oTest->sHostName = $hostname;
370 $oTest->nPort = 9628;
371 // $oTest->sConnectionString="DRIVER=Microsoft Access Driver (*.mdb);SystemDB=C:\CTM\System.mda;DBQ=C:\CTM\of2K3\ctm.mdb;UID=Assess;PWD=VBMango;";
372 $oTest->sConnectionString="DRIVER=Microsoft Access Driver (*.mdb);SystemDB=".
373 $mdapath.";DBQ=".$mdbpath.";UID=Assess;PWD=VBMango;";
374 // send and receive XML communication
375 $qResult = $oTest->ExecSQL($sql);
376 // set up XML parser to read the results
377 $xml_parser = xml_parser_create("US-ASCII");
378 xml_set_element_handler($xml_parser, "quiz_xmlstart", "quiz_xmlend");
379 xml_set_character_data_handler($xml_parser, "quiz_xmldata");
380 // parse the XML and get back the result set array
381 if (!xml_parse($xml_parser, $qResult)) {
382 $this->err("XML error: ".xml_error_string(xml_get_error_code($xml_parser))
383 ." at line ".xml_get_current_line_number($xml_parser),$oTest->sConnectionString);
384 return false;
385 } else {
386 // echo("Successful XML parse. ");
387 // prepare the array for use in the pull-down
388 /* echo "<br />count of rows is ". count ($result);
389 echo "<pre>\n";
390 $qResult = HtmlSpecialChars($qResult);
391 echo $qResult;
392 echo "\n</pre>";
394 xml_parser_free($xml_parser);
395 // $sResult = HtmlSpecialChars($qResult);
396 //echo("<pre>");
397 // echo($sResult);
398 // echo("</pre>");
400 return $result;
404 function connect_win($filename) {
405 global $CFG, $systemdb;
406 // first, verify the location of System.mda
407 if (!isset($systemdb)) {
408 $systemdb=$this->findfile("System.mda");
410 if (! $systemdb) {
411 $this->err("The system database System.mda cannot be found. Check that you've uploaded it to the course.",$dsn);
412 die;
415 $ldb = &ADONewConnection('access');
416 $dsn="DRIVER=Microsoft Access Driver (*.mdb);SystemDB=".$systemdb.";DBQ=".$filename.";UID=Assess;PWD=VBMango;";
417 $dbconnected = $ldb->Connect($dsn);
418 if (! $dbconnected) {
419 $this->err("Moodle could not connect to the database.",$dsn);
420 die;
422 return $ldb;
425 function err($message, $dsn) {
426 echo "<font color=\"#990000\">";
427 echo "<p>Error: $message</p>";
428 echo "<p>ODBC File DSN: $dsn<br />";
429 echo "</font>";
432 function fulldelete($location) {
433 if (is_dir($location)) {
434 $currdir = opendir($location);
435 while ($file = readdir($currdir)) {
436 if ($file <> ".." && $file <> ".") {
437 $fullfile = $location."/".$file;
438 if (is_dir($fullfile)) {
439 if (!fulldelete($fullfile)) {
440 return false;
442 } else {
443 if (!unlink($fullfile)) {
444 return false;
449 closedir($currdir);
450 if (! rmdir($location)) {
451 return false;
454 } else {
455 if (!unlink($location)) {
456 return false;
459 return true;
463 function findfile($filename) {
464 global $CFG;
465 $dirs = $this->getcoursedirs();
466 $dirs[] = $CFG->dirroot."\mod\quiz\format";
467 foreach ($dirs as $dir) {
468 $file = $dir . "\System.mda";
469 // look for System.mda
470 if (is_file($file)) return $file;
472 return false;
475 function getcoursedirs() {
476 global $CFG;
477 // for every course in the system, find the root of the data directory
478 $courses = get_records_sql("select distinct id,fullname from ".$CFG->prefix."course");
479 $dirs = array();
480 if ($courses) {
481 foreach ($courses as $course) {
482 $dir = $CFG->dataroot . "/" . $course->id;
483 if (is_dir($dir)) {
484 $dirs[] = $dir;
488 return $dirs;
490 } // END OF CLASS
492 //Handler for starting elements
493 function quiz_xmlstart($parser, $name, $attribs) {
494 global $result,$row, $col, $incolumn;
495 $name = strtolower($name);
496 switch ($name) {
497 case "row":
498 $col=0;break;
499 case "column":
500 $incolumn = 1;break;
501 case "error":
502 break;
503 case "result":
504 $row = 0; break;
505 } // switch
508 //handler for the end of elements
509 function quiz_xmlend($parser, $name) {
510 global $result, $row, $col, $incolumn;
511 $name = strtolower($name);
512 switch ($name) {
513 case "row":
514 $row++;break;
515 case "column":
516 $incolumn = 0;
517 $col++;
518 break;
519 case "error":
520 break;
521 case "result":
522 break;
523 } // switch
524 } // function
526 //handler for character data
527 function quiz_xmldata($parser, $data) {
528 global $result, $row, $col, $incolumn;
529 if ($incolumn) {
530 $result[$row][$col] = $result[$row][$col] . $data;