You are here

class qformat_coursetestmanager in Quiz 6.5

Same name and namespace in other branches
  1. 6.6 includes/moodle/question/format/coursetestmanager/format.php \qformat_coursetestmanager

Hierarchy

Expanded class hierarchy of qformat_coursetestmanager

File

includes/moodle/question/format/coursetestmanager/format.php, line 16

View source
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;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
qformat_coursetestmanager::connect_win function
qformat_coursetestmanager::deletedatabase function
qformat_coursetestmanager::err function
qformat_coursetestmanager::findfile function
qformat_coursetestmanager::fulldelete function
qformat_coursetestmanager::getcoursedirs function
qformat_coursetestmanager::getquestioncategories function
qformat_coursetestmanager::getquestions function
qformat_coursetestmanager::importpostprocess function Override if any post-processing is required Overrides qformat_default::importpostprocess
qformat_coursetestmanager::importpreprocess function Perform any required pre-processing Overrides qformat_default::importpreprocess
qformat_coursetestmanager::importprocess function Process the file This method should not normally be overidden Overrides qformat_default::importprocess
qformat_coursetestmanager::provide_import function Overrides qformat_default::provide_import
qformat_coursetestmanager::query_linux function
qformat_default::$canaccessbackupdata property
qformat_default::$category property
qformat_default::$catfromfile property
qformat_default::$cattofile property
qformat_default::$contextfromfile property
qformat_default::$contexttofile property
qformat_default::$course property
qformat_default::$displayerrors property
qformat_default::$filename property
qformat_default::$importerrors property
qformat_default::$matchgrades property
qformat_default::$questionids property
qformat_default::$questions property
qformat_default::$realfilename property
qformat_default::$stoponerror property
qformat_default::$translator property
qformat_default::count_questions function Count all non-category questions in the questions array.
qformat_default::create_category_path function find and/or create the category described by a delimited list e.g. $course$/tom/dick/harry or tom/dick/harry
qformat_default::defaultquestion function return an "empty" question Somewhere to specify question parameters that are not handled by import but are required db fields. This should not be overridden.
qformat_default::error function Handle parsing error
qformat_default::exportpostprocess function Do an post-processing that may be required
qformat_default::exportpreprocess function Do any pre-processing that may be required 1
qformat_default::exportprocess function Do the export For most types this should not need to be overrided 1
qformat_default::export_file_extension function Return the files extension appropriate for this type override if you don't want .txt 3
qformat_default::format_question_text function where question specifies a moodle (text) format this performs the conversion.
qformat_default::get_category_path function get the category as a path (e.g., tom/dick/harry)
qformat_default::importimagefile function Import an image file encoded in base64 format
qformat_default::presave_process function Enable any processing to be done on the content just prior to the file being saved default is to do nothing 2
qformat_default::provide_export function 4
qformat_default::question_get_export_dir function get directory into which export is going
qformat_default::readdata function Return complete file within an array, one item per line 1
qformat_default::readquestion function Given the data known to define a question in this format, this function converts it into a question object suitable for processing and insertion into Moodle. 5
qformat_default::readquestions function Parses an array of lines into an array of questions, where each item is a question object as defined by readquestion(). Questions are defined as anything between blank lines. 9
qformat_default::setCategory function set the category
qformat_default::setCatfromfile function set catfromfile
qformat_default::setCattofile function set cattofile
qformat_default::setContextfromfile function set contextfromfile
qformat_default::setContexts function set an array of contexts.
qformat_default::setContexttofile function set contexttofile
qformat_default::setCourse function set the course class variable
qformat_default::setFilename function set the filename
qformat_default::setMatchgrades function set matchgrades
qformat_default::setQuestions function Set the specific questions to export. Should not include questions with parents (sub questions of cloze question type). Only used for question export.
qformat_default::setRealfilename function set the "real" filename (this is what the user typed, regardless of wha happened next)
qformat_default::setStoponerror function set stoponerror
qformat_default::set_can_access_backupdata function
qformat_default::try_exporting_using_qtypes function Provide export functionality for plugin questiontypes Do not override
qformat_default::try_importing_using_qtypes function Import for questiontype plugins Do not override.
qformat_default::writequestion function convert a single question object into text output in the given format. This must be overriden 4