You are here

format.php in Quiz 6.5

File

includes/moodle/question/format/coursetestmanager/format.php
View source
<?php

// $Id$

////////////////////////////////////////////////////////////////////

/// Class for importing course test manager questions.            //

///                                                               //

///                                                               //

////////////////////////////////////////////////////////////////////

// Based on format.php, included by ../../import.php

/**
 * @package questionbank
 * @subpackage importexport
 */
require_once $CFG->dirroot . '/lib/uploadlib.php';
class qformat_coursetestmanager extends qformat_default {
  function provide_import() {
    return true;
  }
  function importpreprocess($category) {
    $this->category = $category;

    // Important
    return true;
  }
  function importprocess($filename) {
    global $CFG, $USER, $strimportquestions, $form, $question_category, $category, $COURSE, $hostname, $mdapath, $mdbpath;
    if (PHP_OS == "Linux" and isset($hostname)) {
      $hostname = trim($hostname);

      // test the ODBC socket server connection
      // if failure, unset hostname and set hostname_access_error
      $question_categories = $this
        ->getquestioncategories($mdbpath, $mdapath, $hostname);
      if (!$question_categories) {
        $hostname_access_error = $hostname . " ";
        unset($hostname);
      }
      else {
        $hostname_access_error = 0;
      }
    }
    if (PHP_OS == "Linux" and !isset($hostname)) {

      // copy the file to a semi-permanent location
      if (!($basedir = make_upload_directory("{$COURSE->id}"))) {
        error("The site administrator needs to fix the file permissions for the data directory");
      }
      if (!isset($hostname_access_error)) {
        $bname = basename($filename);
        $cleanfilename = clean_filename($bname);
        if ($cleanfilename) {
          $newfile = "{$basedir}/{$cleanfilename}";
          if (move_uploaded_file($filename, $newfile)) {
            chmod($newfile, 0666);
            clam_log_upload($newfile, $COURSE);
          }
          else {
            notify(get_string("uploadproblem", "", $filename));
          }
        }
        $filename = $newfile;
      }
      print_heading_with_help($strimportquestions, "import", "quiz");
      print_simple_box_start("center");
      if ($hostname_access_error) {
        notify("couldn't connect to ODBC Socket Server on " . $hostname_access_error);
      }
      echo "<form method=\"post\" action=\"import.php\">";
      echo '<fieldset class="invisiblefieldset">';
      echo "<table cellpadding=\"5\">";
      echo "<tr><td align=\"right\">";
      echo "What is the hostname or IP address of the ODBC Socket Server:</td><td>";
      echo " <input name=\"hostname\" type=\"text\" size=\"50\" value=\"" . stripslashes($hostname_access_error) . "\" />";
      echo " <input name=\"filename\" type=\"hidden\" value=\"" . $filename . "\" />";
      echo " <input name=\"category\" type=\"hidden\" value=\"" . $category->id . "\" />";
      echo " <input name=\"format\" type=\"hidden\" value=\"" . $form->format . "\" />";
      echo "</td><td>&nbsp;</td></tr>";
      echo "<tr><td align=\"right\">";
      echo "What is the location of the database (.mdb file) on the Socket Server:</td><td>";
      echo " <input name=\"mdbpath\" type=\"text\" size=\"50\" value=\"" . stripslashes($mdbpath) . "\" />";
      echo "</td><td>&nbsp;</td></tr>";
      echo "<tr><td align=\"right\">";
      echo "What is the location of the system database (System.mda file) on the Socket Server:</td><td>";
      echo " <input name=\"mdapath\" type=\"text\" size=\"50\" value=\"" . stripslashes($mdapath) . "\" />";
      echo "</td><td>&nbsp;</td></tr>";
      echo "<tr><td>&nbsp;</td><td>";
      echo " <input type=\"submit\" name=\"save\" value=\"Connect to Server\" />";
      echo "</td></tr>";
      echo "</table>";
      echo '</fieldset>';
      echo "</form>";
      print_simple_box_end();
      print_footer($COURSE);
      exit;
    }

    // we get here if running windows or after connect to ODBC socket server on linux
    //
    // this generates the page to choose categories of questions to import
    //
    if (!isset($question_category)) {
      if (PHP_OS == "WINNT") {

        // copy the file to a semi-permanent location
        if (!($basedir = make_upload_directory("{$COURSE->id}"))) {
          error("The site administrator needs to fix the file permissions for the data directory");
        }
        $bname = basename($filename);
        $cleanfilename = clean_filename($bname);
        if ($cleanfilename) {
          $newfile = "{$basedir}/{$cleanfilename}";
          if (move_uploaded_file($filename, $newfile)) {
            chmod($newfile, 0666);
            clam_log_upload($newfile, $COURSE);
          }
          else {
            notify(get_string("uploadproblem", "", $filename));
          }
        }
        $filename = $newfile;
      }

      // end of file copy
      // don't have to do this on linux, since it's alreay been done in the test above
      if (PHP_OS == "WINNT") {
        $question_categories = $this
          ->getquestioncategories($filename);
      }

      // print the intermediary form
      if (!($categories = question_category_options($COURSE->id, true))) {
        error("No categories!");
      }
      print_heading_with_help($strimportquestions, "import", "quiz");
      print_simple_box_start("center");
      echo "<form method=\"post\" action=\"import.php\">";
      echo '<fieldset class="invisiblefieldset">';
      echo "<table cellpadding=\"5\">";
      echo "<tr><td align=\"right\">";
      echo "Choose a category of questions to import:</td><td>";
      asort($question_categories);
      choose_from_menu($question_categories, "question_category", "All Categories", "All Categories", "", "allcategories");
      echo " <input name=\"filename\" type=\"hidden\" value=\"" . $filename . "\" />";
      echo " <input name=\"category\" type=\"hidden\" value=\"" . $category->id . "\" />";
      echo " <input name=\"format\" type=\"hidden\" value=\"" . $form->format . "\" />";
      if (PHP_OS == "Linux") {
        echo " <input name=\"hostname\" type=\"hidden\" value=\"" . stripslashes(trim($hostname)) . "\" />";
        echo " <input name=\"mdbpath\" type=\"hidden\" value=\"" . stripslashes($mdbpath) . "\" />";
        echo " <input name=\"mdapath\" type=\"hidden\" value=\"" . stripslashes($mdapath) . "\" />";
      }
      echo "</td><td>&nbsp;</td>";
      echo "</tr><tr><td>&nbsp;</td><td>";
      echo " <input type=\"submit\" name=\"save\" value=\"Import Questions\" />";
      echo "</td></tr>";
      echo "</table>";
      echo '</fieldset>';
      echo "</form>";
      print_simple_box_end();
      print_footer($COURSE);
      exit;
    }

    //
    // this is the main import section
    //
    notify("Importing questions");
    if (PHP_OS == "Linux") {
      $hostname = trim($hostname);
      $records = $this
        ->getquestions($mdbpath, $question_category, $mdapath, $hostname);
    }
    else {
      $records = $this
        ->getquestions($filename, $question_category);
    }
    foreach ($records as $qrec) {
      $question = $this
        ->defaultquestion();
      if ($qrec[9] != "") {
        $question->image = $qrec[9];
      }

      //  0   Selected
      //  1   PracticeTestOK?
      //  2   QuestionText
      //  3   QuestionType
      //  4   Option1Text
      //  5   Option2Text
      //  6   Option3Text
      //  7   Option4Text
      //  8   CorrectAnswer
      //  9   Graphic
      //  10  Module
      //  11  ChapterNumber
      //  12  PageNumber
      $ref = "Answer can be found in chapter " . $qrec[11] . ", page " . $qrec[12] . ".";
      switch ($qrec[3]) {
        case 1:
          $question->qtype = MULTICHOICE;

          // MULTICHOICE, SHORTANSWER, TRUEFALSE
          //          echo "<pre>";echo htmlspecialchars($qrec[2]); echo "</pre>";
          $question->questiontext = addslashes(trim($qrec[2]));

          //          echo "<pre>";echo $question->questiontext; echo "</pre>";
          $question->name = preg_replace("/<br />/", "", $question->questiontext);
          $question->single = 1;

          // Only one answer is allowed -- used for multiple choicers
          $fractionset = 0;
          for ($i = 4; $i <= 7; $i++) {
            if ($qrec[$i] != "") {
              $question->answer[$i - 3] = addslashes($qrec[$i]);
              if ($qrec[8] == $i - 3) {

                // if this is the index of CorrectAnswer
                $question->fraction[$i - 3] = 1;
                $fractionset = 1;
              }
              else {
                $question->fraction[$i - 3] = 0;
              }
              $question->feedback[$i - 3] = ($qrec[8] == $i - 3 ? "Correct. " : "Incorrect. ") . $ref;
            }
          }
          if ($fractionset == 0) {
            $question->fraction[1] = 1;
          }
          break;
        case 2:

          // TRUE FALSE
          $question->qtype = TRUEFALSE;
          $question->questiontext = addslashes(trim($qrec[2]));
          $question->name = preg_replace("/<br />/", "", $question->questiontext);

          // for TF, $question->answer should be 1 for true, 0 for false
          if ($qrec[8] == "T") {
            $question->answer = 1;
          }
          else {
            $question->answer = 0;
          }

          // for TF, use $question->feedbacktrue and feedbackfalse
          $question->feedbacktrue = ($qrec[8] == "T" ? "Correct. " : "Incorrect. ") . $ref;
          $question->feedbackfalse = ($qrec[8] == "F" ? "Correct. " : "Incorrect. ") . $ref;
          break;
        case 3:
          $question->qtype = SHORTANSWER;
          $question->questiontext = addslashes(trim($qrec[2]));

          //          echo "<pre>";echo $question->questiontext; echo "</pre>";
          $question->name = preg_replace("/<br />/", "", $question->questiontext);
          $question->usecase = 0;

          // Ignore case -- for SHORT ANSWER questions
          $answers = explode("~", $qrec[8]);
          $question->answer[0] = " ";
          $question->fraction[0] = 1;
          for ($i = 0; $i < count($answers); $i++) {
            $question->answer[$i] = addslashes(trim($answers[$i]));
            $question->feedback[$i] = $ref;
            $question->fraction[$i] = 1;

            // 1 for 100%, 0 for none or somewhere in between
          }
          break;
        case 4:
          $question = 0;
          notify("Cannot use essay questions - skipping question " . $qrec[2] . " " . $ref);
          break;
        default:
          $question = 0;
          notify("Misformatted Record.  Question Skipped.");
          break;
      }
      if ($question) {
        $questions[] = $question;
      }
    }
    $count = 0;

    // process all the questions
    if (PHP_OS == "WINNT") {
      $filename = str_replace("\\\\", "\\", $filename);
      $filename = str_replace("/", "\\", $filename);
    }
    foreach ($questions as $question) {

      // Process and store each question
      $count++;
      echo "<hr /><p><b>{$count}</b>. " . stripslashes($question->questiontext) . "</p>";
      $question->category = $this->category->id;
      $question->stamp = make_unique_id_code();

      // Set the unique code (not to be changed)
      $question->createdby = $USER->id;
      $question->timecreated = time();
      if (!($question->id = insert_record("question", $question))) {
        error("Could not insert new question!");
      }
      $this->questionids[] = $question->id;

      // Now to save all the answers and type-specific options
      $result = save_question_options($question);
      if (!empty($result->error)) {
        notify($result->error);
        $this
          ->deletedatabase($filename);
        return false;
      }
      if (!empty($result->notice)) {
        notify($result->notice);
        $this
          ->deletedatabase($filename);
        return true;
      }

      // Give the question a unique version stamp determined by question_hash()
      set_field('question', 'version', question_hash($question), 'id', $question->id);
    }
    $this
      ->deletedatabase($filename);
    return true;
  }
  function importpostprocess() {
    return true;
  }
  function deletedatabase($filename) {
    if (!$this
      ->fulldelete($filename)) {
      echo "<br />Error: Could not delete: {$filename}";
      return false;
    }
    return true;
  }
  function getquestions($filename, $category, $mdapath = "", $hostname = "") {
    if ($category == "allcategories" or $category == "") {
      $sql = "SELECT * FROM TBQuestions";
    }
    else {
      $sql = "SELECT * FROM TBQuestions where module = '" . $category . "'";
    }
    if (PHP_OS == "WINNT") {
      $ldb =& $this
        ->connect_win($filename);
      $qset = $ldb
        ->Execute("{$sql}");
      if (!$qset->EOF) {
        $records = $qset
          ->GetAssoc(true);
      }
      else {
        $this
          ->err("There were no records in the database.", $dsn);
        $ldb
          ->Close();
        return false;
      }
      $ldb
        ->Close();
    }
    else {

      // if PHP_OS == WINNT
      // we have a linux installation
      $result = $this
        ->query_linux($sql, $filename, $mdapath, $hostname);
      if (count($result) > 0) {

        // get rid of the ID field in the first column.
        for ($i = 0; $i < count($result); $i++) {
          foreach (array_keys($result[$i]) as $j) {
            $records[$i][$j - 1] = $result[$i][$j];
          }
        }
      }
      else {
        $this
          ->err("There were no records in the database.", $dsn);
        $ldb
          ->Close();
        return false;
      }

      // xml test and connect
    }

    // PHP_OS TEST
    return $records;
  }
  function getquestioncategories($filename, $mdapath = "", $hostname = "") {
    global $CFG, $result;
    $sql = "SELECT Distinct module FROM TBQuestions";
    if (PHP_OS == "WINNT") {
      $ldb =& $this
        ->connect_win($filename);
      $qset = $ldb
        ->Execute("{$sql}");
      if (!$qset->EOF) {
        $records = $qset
          ->GetArray(true);
        foreach ($records as $record) {
          $categories[$record[0]] = $record[0];
        }
      }
      else {

        // if recordcount
        $this
          ->err("There were no records in the database.", $dsn);
        $ldb
          ->Close();
        return false;
      }
      $ldb
        ->Close();
    }
    else {

      // if PHP_OS == WINNT
      // we have a linux installation
      $result = $this
        ->query_linux($sql, $filename, $mdapath, $hostname);
      for ($i = 0; $i < count($result); $i++) {
        $categories[$result[$i][0]] = $result[$i][0];
      }
    }

    // PHP_OS TEST
    return $categories;
  }
  function query_linux($sql, $mdbpath, $mdapath, $hostname) {
    global $result;
    include_once "odbcsocketserver.class.php";

    // set up socket server object to connect to remote host
    $oTest = new ODBCSocketServer();

    //Set the Hostname, port, and connection string
    $oTest->sHostName = $hostname;
    $oTest->nPort = 9628;

    //      $oTest->sConnectionString="DRIVER=Microsoft Access Driver (*.mdb);SystemDB=C:\CTM\System.mda;DBQ=C:\CTM\of2K3\ctm.mdb;UID=Assess;PWD=VBMango;";
    $oTest->sConnectionString = "DRIVER=Microsoft Access Driver (*.mdb);SystemDB=" . $mdapath . ";DBQ=" . $mdbpath . ";UID=Assess;PWD=VBMango;";

    // send and receive XML communication
    $qResult = $oTest
      ->ExecSQL($sql);

    // set up XML parser to read the results
    $xml_parser = xml_parser_create("US-ASCII");
    xml_set_element_handler($xml_parser, "quiz_xmlstart", "quiz_xmlend");
    xml_set_character_data_handler($xml_parser, "quiz_xmldata");

    // parse the XML and get back the result set array
    if (!xml_parse($xml_parser, $qResult)) {
      $this
        ->err("XML error: " . xml_error_string(xml_get_error_code($xml_parser)) . " at line " . xml_get_current_line_number($xml_parser), $oTest->sConnectionString);
      return false;
    }
    else {

      //          echo("Successful XML parse.  ");
      // prepare the array for use in the pull-down

      /*          echo "<br />count of rows is ". count ($result);
                          echo "<pre>\n";
                          $qResult = HtmlSpecialChars($qResult);
                          echo $qResult;
                          echo "\n</pre>";
      */
      xml_parser_free($xml_parser);

      //  $sResult = HtmlSpecialChars($qResult);

      //echo("<pre>");

      //  echo($sResult);
      //  echo("</pre>");
      return $result;
    }
  }
  function connect_win($filename) {
    global $CFG, $systemdb;

    // first, verify the location of System.mda
    if (!isset($systemdb)) {
      $systemdb = $this
        ->findfile("System.mda");
    }
    if (!$systemdb) {
      $this
        ->err("The system database System.mda cannot be found.  Check that you've uploaded it to the course.", $dsn);
      die;
    }
    $ldb =& ADONewConnection('access');
    $dsn = "DRIVER=Microsoft Access Driver (*.mdb);SystemDB=" . $systemdb . ";DBQ=" . $filename . ";UID=Assess;PWD=VBMango;";
    $dbconnected = $ldb
      ->Connect($dsn);
    if (!$dbconnected) {
      $this
        ->err("Moodle could not connect to the database.", $dsn);
      die;
    }
    return $ldb;
  }
  function err($message, $dsn) {
    echo "<font color=\"#990000\">";
    echo "<p>Error: {$message}</p>";
    echo "<p>ODBC File DSN: {$dsn}<br />";
    echo "</font>";
  }
  function fulldelete($location) {
    if (is_dir($location)) {
      $currdir = opendir($location);
      while (false !== ($file = readdir($currdir))) {
        if ($file != ".." && $file != ".") {
          $fullfile = $location . "/" . $file;
          if (is_dir($fullfile)) {
            if (!fulldelete($fullfile)) {
              return false;
            }
          }
          else {
            if (!unlink($fullfile)) {
              return false;
            }
          }
        }
      }
      closedir($currdir);
      if (!rmdir($location)) {
        return false;
      }
    }
    else {
      if (!unlink($location)) {
        return false;
      }
    }
    return true;
  }
  function findfile($filename) {
    global $CFG;
    $dirs = $this
      ->getcoursedirs();
    $dirs[] = $CFG->dirroot . "\\mod\\quiz\format";
    foreach ($dirs as $dir) {
      $file = $dir . "\\System.mda";

      // look for System.mda
      if (is_file($file)) {
        return $file;
      }
    }
    return false;
  }
  function getcoursedirs() {
    global $CFG;

    // for every course in the system, find the root of the data directory
    $courses = get_records_sql("select distinct id,fullname from " . $CFG->prefix . "course");
    $dirs = array();
    if ($courses) {
      foreach ($courses as $course) {
        $dir = $CFG->dataroot . "/" . $course->id;
        if (is_dir($dir)) {
          $dirs[] = $dir;
        }
      }
    }
    return $dirs;
  }

}

// END OF CLASS

//Handler for starting elements
function quiz_xmlstart($parser, $name, $attribs) {
  global $result, $row, $col, $incolumn;
  $name = strtolower($name);
  switch ($name) {
    case "row":
      $col = 0;
      break;
    case "column":
      $incolumn = 1;
      break;
    case "error":
      break;
    case "result":
      $row = 0;
      break;
  }

  // switch
}

//handler for the end of elements
function quiz_xmlend($parser, $name) {
  global $result, $row, $col, $incolumn;
  $name = strtolower($name);
  switch ($name) {
    case "row":
      $row++;
      break;
    case "column":
      $incolumn = 0;
      $col++;
      break;
    case "error":
      break;
    case "result":
      break;
  }

  // switch
}

// function

//handler for character data
function quiz_xmldata($parser, $data) {
  global $result, $row, $col, $incolumn;
  if ($incolumn) {
    $result[$row][$col] = $result[$row][$col] . $data;
  }
}

Functions

Classes