• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

assessment/classes/class.assClozeTest.php

Go to the documentation of this file.
00001 <?php
00002  /*
00003    +----------------------------------------------------------------------------+
00004    | ILIAS open source                                                          |
00005    +----------------------------------------------------------------------------+
00006    | Copyright (c) 1998-2001 ILIAS open source, University of Cologne           |
00007    |                                                                            |
00008    | This program is free software; you can redistribute it and/or              |
00009    | modify it under the terms of the GNU General Public License                |
00010    | as published by the Free Software Foundation; either version 2             |
00011    | of the License, or (at your option) any later version.                     |
00012    |                                                                            |
00013    | This program is distributed in the hope that it will be useful,            |
00014    | but WITHOUT ANY WARRANTY; without even the implied warranty of             |
00015    | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              |
00016    | GNU General Public License for more details.                               |
00017    |                                                                            |
00018    | You should have received a copy of the GNU General Public License          |
00019    | along with this program; if not, write to the Free Software                |
00020    | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
00021    +----------------------------------------------------------------------------+
00022 */
00023 
00024 require_once "./assessment/classes/class.assQuestion.php";
00025 require_once "./assessment/classes/class.assAnswerCloze.php";
00026 require_once "./assessment/classes/class.ilQTIUtils.php";
00027 
00028 define("CLOZE_TEXT", "0");
00029 define("CLOZE_SELECT", "1");
00030 define("CLOZE_TEST_IDENTIFIER", "CLOZE QUESTION");
00031 
00042 class ASS_ClozeTest extends ASS_Question
00043 {
00052         var $cloze_text;
00053 
00061         var $gaps;
00062 
00070         var $start_tag;
00071 
00079         var $end_tag;
00092         function ASS_ClozeTest(
00093                 $title = "",
00094                 $comment = "",
00095                 $author = "",
00096                 $owner = -1,
00097                 $cloze_text = ""
00098         )
00099         {
00100                 $this->start_tag = "<gap>";
00101                 $this->end_tag = "</gap>";
00102                 $this->ASS_Question($title, $comment, $author, $owner);
00103                 $this->gaps = array();
00104                 $this->set_cloze_text($cloze_text);
00105         }
00106 
00115         function isComplete()
00116         {
00117                 if (($this->title) and ($this->author) and ($this->cloze_text) and (count($this->gaps)))
00118                 {
00119                         return true;
00120                 }
00121                 else
00122                 {
00123                         return false;
00124                 }
00125         }
00126 
00135         function &createCloseTextArray()
00136         {
00137                 $result = array();
00138                 $search_pattern = "|<gap([^>]*?)>(.*?)</gap>|i";
00139                 preg_match_all($search_pattern, $this->cloze_text, $gaps);
00140                 if (count($gaps[0]))
00141                 {
00142                         // found at least one gap
00143                         $delimiters = preg_split($search_pattern, $this->cloze_text, -1, PREG_SPLIT_OFFSET_CAPTURE);
00144                         $result["gaps"] = array();
00145                         foreach ($gaps[0] as $index => $gap)
00146                         {
00147                                 $result["gaps"][$index] = array();
00148                                 $result["gaps"][$index]["gap"] = $gap;
00149                                 $result["gaps"][$index]["params"] = array();
00150                                 $result["gaps"][$index]["params"]["text"] = $gaps[1][$index];
00151                                 // separate gap params
00152                                 if (preg_match("/name\=\"([^\"]*?)\"/", $gaps[1][$index], $params))
00153                                 {
00154                                         $result["gaps"][$index]["params"]["name"] = $params[1];
00155                                 }
00156                                 else
00157                                 {
00158                                         $result["gaps"][$index]["params"]["name"] = $this->lng->txt("gap") . " " . ($index+1);
00159                                 }
00160                                 if (preg_match("/type\=\"([^\"]*?)\"/", $gaps[1][$index], $params))
00161                                 {
00162                                         $result["gaps"][$index]["params"]["type"] = $params[1];
00163                                 }
00164                                 else
00165                                 {
00166                                         $result["gaps"][$index]["params"]["type"] = "text";
00167                                 }
00168                                 if (preg_match("/shuffle\=\"([^\"]*?)\"/", $gaps[1][$index], $params))
00169                                 {
00170                                         $result["gaps"][$index]["params"]["shuffle"] = $params[1];
00171                                 }
00172                                 else
00173                                 {
00174                                         if (strcmp(strtolower($result["gaps"][$index]["params"]["type"]), "select") == 0)
00175                                         {
00176                                                 $result["gaps"][$index]["params"]["shuffle"] = "yes";
00177                                         }
00178                                 }
00179                                 $result["gaps"][$index]["text"] = array();
00180                                 $result["gaps"][$index]["text"]["text"] = $gaps[2][$index];
00181                                 $textparams = preg_split("/(?<!\\\\),/", $gaps[2][$index]);
00182                                 foreach ($textparams as $key => $value)
00183                                 {
00184                                         $result["gaps"][$index]["text"][$key] = $value;
00185                                 }
00186                         }
00187                         $result["delimiters"] = $delimiters;
00188                 }
00189                 //echo str_replace("\n", "<br />", str_replace(" ", "&nbsp;", ilUtil::prepareFormOutput(print_r($result, true))));
00190                 return $result;         
00191         }
00192 
00201         function createCloseTextFromArray($assoc_array)
00202         {
00203                 $this->cloze_text = "";
00204                 if (count($assoc_array))
00205                 {
00206                         $gap = 0;
00207                         foreach ($assoc_array["delimiters"] as $key => $value)
00208                         {
00209                                 if (($key > 0) && ($key < count($assoc_array["delimiters"])))
00210                                 {
00211                                         if (strcmp($assoc_array["gaps"][$gap]["params"]["shuffle"], "") == 0)
00212                                         {
00213                                                 $shuffle = "";
00214                                         }
00215                                         else
00216                                         {
00217                                                 $shuffle = " shuffle=\"" . $assoc_array["gaps"][$gap]["params"]["shuffle"] . "\"";
00218                                         }
00219                                         $textarray = array();
00220                                         foreach ($assoc_array["gaps"][$gap]["text"] as $textindex => $textvalue)
00221                                         {
00222                                                 if (preg_match("/\d+/", $textindex))
00223                                                 {
00224                                                         array_push($textarray, $textvalue);
00225                                                 }
00226                                         }
00227                                         $this->cloze_text .= sprintf("<gap name=\"%s\" type=\"%s\"%s>%s</gap>",
00228                                                 $assoc_array["gaps"][$gap]["params"]["name"],
00229                                                 $assoc_array["gaps"][$gap]["params"]["type"],
00230                                                 $shuffle,
00231                                                 join(",", $textarray)
00232                                         );
00233                                         $gap++;
00234                                 }
00235                                 $this->cloze_text .= $value[0];
00236                         }
00237                 }
00238         }
00239         
00248         function saveToDb($original_id = "")
00249         {
00250                 global $ilias;
00251 
00252                 $db =& $ilias->db;
00253                 $complete = 0;
00254                 if ($this->isComplete())
00255                 {
00256                         $complete = 1;
00257                 }
00258 
00259                 $estw_time = $this->getEstimatedWorkingTime();
00260                 $estw_time = sprintf("%02d:%02d:%02d", $estw_time['h'], $estw_time['m'], $estw_time['s']);
00261                 $shuffle = 1;
00262 
00263                 if (!$this->shuffle)
00264                 {
00265                         $shuffle = 0;
00266                 }
00267 
00268                 if ($original_id)
00269                 {
00270                         $original_id = $db->quote($original_id);
00271                 }
00272                 else
00273                 {
00274                         $original_id = "NULL";
00275                 }
00276 
00277                 if ($this->id == -1)
00278                 {
00279                         // Neuen Datensatz schreiben
00280                         $now = getdate();
00281                         $created = sprintf("%04d%02d%02d%02d%02d%02d", $now['year'], $now['mon'], $now['mday'], $now['hours'], $now['minutes'], $now['seconds']);
00282                         $query = sprintf("INSERT INTO qpl_questions (question_id, question_type_fi, obj_fi, title, comment, author, owner, question_text, working_time, shuffle, complete, created, original_id, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
00283                                 $db->quote($this->getQuestionType()),
00284                                 $db->quote($this->obj_id),
00285                                 $db->quote($this->title),
00286                                 $db->quote($this->comment),
00287                                 $db->quote($this->author),
00288                                 $db->quote($this->owner),
00289                                 $db->quote($this->cloze_text),
00290                                 $db->quote($estw_time),
00291                                 $db->quote("$this->shuffle"),
00292                                 $db->quote("$complete"),
00293                                 $db->quote($created),
00294                                 $original_id
00295                         );
00296                         $result = $db->query($query);
00297                         if ($result == DB_OK)
00298                         {
00299                                 $this->id = $this->ilias->db->getLastInsertId();
00300 
00301                                 // create page object of question
00302                                 $this->createPageObject();
00303 
00304                                 // Falls die Frage in einen Test eingef�gt werden soll, auch diese Verbindung erstellen
00305                                 if ($this->getTestId() > 0)
00306                                 {
00307                                         $this->insertIntoTest($this->getTestId());
00308                                 }
00309                         }
00310                 }
00311                 else
00312                 {
00313                         // Vorhandenen Datensatz aktualisieren
00314                         $query = sprintf("UPDATE qpl_questions SET obj_fi = %s, title = %s, comment = %s, author = %s, question_text = %s, working_time = %s, shuffle = %s, complete = %s WHERE question_id = %s",
00315                                 $db->quote($this->obj_id. ""),
00316                                 $db->quote($this->title),
00317                                 $db->quote($this->comment),
00318                                 $db->quote($this->author),
00319                                 $db->quote($this->cloze_text),
00320                                 $db->quote($estw_time),
00321                                 $db->quote("$this->shuffle"),
00322                                 $db->quote("$complete"),
00323                                 $db->quote($this->id)
00324                                 );
00325                         $result = $db->query($query);
00326                 }
00327 
00328                 if ($result == DB_OK)
00329                 {
00330                         // Antworten schreiben
00331 
00332                         // delete old answers
00333                         $query = sprintf("DELETE FROM qpl_answers WHERE question_fi = %s",
00334                                 $db->quote($this->id)
00335                         );
00336                         $result = $db->query($query);
00337                         // Anworten wegschreiben
00338                         foreach ($this->gaps as $key => $value)
00339                         {
00340                                 foreach ($value as $answer_id => $answer_obj)
00341                                 {
00342                                         $query = sprintf("INSERT INTO qpl_answers (answer_id, question_fi, gap_id, answertext, points, aorder, cloze_type, name, shuffle, correctness, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
00343                                                 $db->quote($this->id),
00344                                                 $db->quote($key),
00345                                                 $db->quote($answer_obj->get_answertext() . ""),
00346                                                 $db->quote($answer_obj->get_points() . ""),
00347                                                 $db->quote($answer_obj->get_order() . ""),
00348                                                 $db->quote($answer_obj->get_cloze_type() . ""),
00349                                                 $db->quote($answer_obj->get_name() . ""),
00350                                                 $db->quote($answer_obj->get_shuffle() . ""),
00351                                                 $db->quote($answer_obj->getState() . "")
00352                                                 );
00353                                         $answer_result = $db->query($query);
00354                                 }
00355                         }
00356                 }
00357                 parent::saveToDb($original_id);
00358         }
00359 
00369   function loadFromDb($question_id)
00370   {
00371     global $ilias;
00372     $db =& $ilias->db;
00373 
00374     $query = sprintf("SELECT * FROM qpl_questions WHERE question_id = %s",
00375       $db->quote($question_id)
00376     );
00377     $result = $db->query($query);
00378     if (strcmp(strtolower(get_class($result)), db_result) == 0) {
00379       if ($result->numRows() == 1) {
00380         $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
00381         $this->id = $question_id;
00382         $this->obj_id = $data->obj_fi;
00383         $this->title = $data->title;
00384         $this->comment = $data->comment;
00385                                 $this->solution_hint = $data->solution_hint;
00386                                 $this->original_id = $data->original_id;
00387         $this->author = $data->author;
00388         $this->owner = $data->owner;
00389         $this->cloze_text = $data->question_text;
00390                                 $this->shuffle = $data->shuffle;
00391         $this->setEstimatedWorkingTime(substr($data->working_time, 0, 2), substr($data->working_time, 3, 2), substr($data->working_time, 6, 2));
00392       }
00393 
00394       $query = sprintf("SELECT * FROM qpl_answers WHERE question_fi = %s ORDER BY gap_id, aorder ASC",
00395         $db->quote($question_id)
00396       );
00397       $result = $db->query($query);
00398       if (strcmp(strtolower(get_class($result)), db_result) == 0) {
00399         $counter = -1;
00400         while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
00401           if ($data->gap_id != $counter) {
00402             $answer_array = array();
00403             array_push($this->gaps, $answer_array);
00404             $counter = $data->gap_id;
00405           }
00406                                         if ($data->cloze_type == CLOZE_SELECT)
00407                                         {
00408                                                 if ($data->correctness == 0)
00409                                                 {
00410                                                         // fix for older single response answers where points could be given for unchecked answers
00411                                                         $data->correctness = 1;
00412                                                         $data->points = 0;
00413                                                 }
00414                                         }
00415           array_push($this->gaps[$counter], new ASS_AnswerCloze($data->answertext, $data->points, $data->aorder, $data->correctness, $data->cloze_type, $data->name, $data->shuffle, $data->answer_id));
00416         }
00417       }
00418     }
00419                 parent::loadFromDb($question_id);
00420   }
00421 
00429         function duplicate($for_test = true, $title = "", $author = "", $owner = "")
00430         {
00431                 if ($this->id <= 0)
00432                 {
00433                         // The question has not been saved. It cannot be duplicated
00434                         return;
00435                 }
00436                 // duplicate the question in database
00437                 $clone = $this;
00438                 include_once ("./assessment/classes/class.assQuestion.php");
00439                 $original_id = ASS_Question::_getOriginalId($this->id);
00440                 $clone->id = -1;
00441                 if ($title)
00442                 {
00443                         $clone->setTitle($title);
00444                 }
00445                 if ($author)
00446                 {
00447                         $clone->setAuthor($author);
00448                 }
00449                 if ($owner)
00450                 {
00451                         $clone->setOwner($owner);
00452                 }
00453                 if ($for_test)
00454                 {
00455                         $clone->saveToDb($original_id);
00456                 }
00457                 else
00458                 {
00459                         $clone->saveToDb();
00460                 }
00461 
00462                 // copy question page content
00463                 $clone->copyPageOfQuestion($original_id);
00464 
00465                 return $clone->id;
00466         }
00467         
00477         function from_xml($xml_text)
00478         {
00479                 $result = false;
00480                 if (!empty($this->domxml))
00481                 {
00482                         $this->domxml->free();
00483                 }
00484                 $xml_text = preg_replace("/>\s*?</", "><", $xml_text);
00485                 $this->domxml = domxml_open_mem($xml_text);
00486                 if (!empty($this->domxml))
00487                 {
00488                         $root = $this->domxml->document_element();
00489                         $item = $root->first_child();
00490                         $this->setTitle($item->get_attribute("title"));
00491                         $this->gaps = array();
00492                         $itemnodes = $item->child_nodes();
00493                         $materials = array();
00494                         $gapcounter = 0;
00495                         foreach ($itemnodes as $index => $node)
00496                         {
00497                                 switch ($node->node_name())
00498                                 {
00499                                         case "qticomment":
00500                                                 $comment = $node->get_content();
00501                                                 if (strpos($comment, "ILIAS Version=") !== false)
00502                                                 {
00503                                                 }
00504                                                 elseif (strpos($comment, "Questiontype=") !== false)
00505                                                 {
00506                                                 }
00507                                                 elseif (strpos($comment, "Author=") !== false)
00508                                                 {
00509                                                         $comment = str_replace("Author=", "", $comment);
00510                                                         $this->setAuthor($comment);
00511                                                 }
00512                                                 else
00513                                                 {
00514                                                         $this->setComment($comment);
00515                                                 }
00516                                                 break;
00517                                         case "itemmetadata":
00518                                                 $md_array = array();
00519                                                 $metanodes = $node->child_nodes();
00520                                                 foreach ($metanodes as $metanode)
00521                                                 {
00522                                                         switch ($metanode->node_name())
00523                                                         {
00524                                                                 case "qtimetadata":
00525                                                                         $metafields = $metanode->child_nodes();
00526                                                                         foreach ($metafields as $metafield)
00527                                                                         {
00528                                                                                 switch ($metafield->node_name())
00529                                                                                 {
00530                                                                                         case "qtimetadatafield":
00531                                                                                                 $metafieldlist = $metafield->child_nodes();
00532                                                                                                 $md = array("label" => "", "entry" => "");
00533                                                                                                 foreach ($metafieldlist as $attr)
00534                                                                                                 {
00535                                                                                                         switch ($attr->node_name())
00536                                                                                                         {
00537                                                                                                                 case "fieldlabel":
00538                                                                                                                         $md["label"] = $attr->get_content();
00539                                                                                                                         break;
00540                                                                                                                 case "fieldentry":
00541                                                                                                                         $md["entry"] = $attr->get_content();
00542                                                                                                                         break;
00543                                                                                                         }
00544                                                                                                 }
00545                                                                                                 array_push($md_array, $md);
00546                                                                                                 break;
00547                                                                                 }
00548                                                                         }
00549                                                                         break;
00550                                                         }
00551                                                 }
00552                                                 foreach ($md_array as $md)
00553                                                 {
00554                                                         switch ($md["label"])
00555                                                         {
00556                                                                 case "ILIAS_VERSION":
00557                                                                         break;
00558                                                                 case "QUESTIONTYPE":
00559                                                                         break;
00560                                                                 case "AUTHOR":
00561                                                                         $this->setAuthor($md["entry"]);
00562                                                                         break;
00563                                                         }
00564                                                 }
00565                                                 break;
00566                                         case "duration":
00567                                                 $iso8601period = $node->get_content();
00568                                                 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
00569                                                 {
00570                                                         $this->setEstimatedWorkingTime($matches[4], $matches[5], $matches[6]);
00571                                                 }
00572                                                 break;
00573                                         case "presentation":
00574                                                 $flow = $node->first_child();
00575                                                 $flownodes = $flow->child_nodes();
00576                                                 foreach ($flownodes as $idx => $flownode)
00577                                                 {
00578                                                         if (strcmp($flownode->node_name(), "material") == 0)
00579                                                         {
00580                                                                 $mattext = $flownode->first_child();
00581                                                                 array_push($materials, $mattext->get_content());
00582                                                         }
00583                                                         elseif (strcmp($flownode->node_name(), "response_str") == 0)
00584                                                         {
00585                                                                 $ident = $flownode->get_attribute("ident");
00586                                                                 $this->gaps["$ident"] = array();
00587                                                                 $shuffle = "";
00588                                                                 $subnodes = $flownode->child_nodes();
00589                                                                 foreach ($subnodes as $node_type)
00590                                                                 {
00591                                                                         switch ($node_type->node_name())
00592                                                                         {
00593                                                                                 case "render_choice":
00594                                                                                         $render_type = $node_type;
00595                                                                                         if (strcmp($render_type->node_name(), "render_choice") == 0)
00596                                                                                         {
00597                                                                                                 // select gap
00598                                                                                                 $shuffle = $render_type->get_attribute("shuffle");
00599                                                                                                 $labels = $render_type->child_nodes();
00600                                                                                                 foreach ($labels as $lidx => $response_label)
00601                                                                                                 {
00602                                                                                                         $material = $response_label->first_child();
00603                                                                                                         $mattext = $material->first_child();
00604                                                                                                         $shuf = 0;
00605                                                                                                         if (strcmp(strtolower($shuffle), "yes") == 0)
00606                                                                                                         {
00607                                                                                                                 $shuf = 1;
00608                                                                                                         }
00609                                                                                                         array_push($this->gaps["$ident"], new ASS_AnswerCloze($mattext->get_content(), 0, count($this->gaps["$ident"]), 0, CLOZE_SELECT, $ident, $shuf));
00610                                                                                                 }
00611                                                                                         }
00612                                                                                         break;
00613                                                                                 case "render_fib":
00614                                                                                         break;
00615                                                                                 case "material":
00616                                                                                         $matlabel = $node_type->get_attribute("label");
00617                                                                                         if (strcmp($matlabel, "suggested_solution") == 0)
00618                                                                                         {
00619                                                                                                 $mattype = $node_type->first_child();
00620                                                                                                 if (strcmp($mattype->node_name(), "mattext") == 0)
00621                                                                                                 {
00622                                                                                                         $suggested_solution = $mattype->get_content();
00623                                                                                                         if ($suggested_solution)
00624                                                                                                         {
00625                                                                                                                 if ($this->getId() < 1)
00626                                                                                                                 {
00627                                                                                                                         $this->saveToDb();
00628                                                                                                                 }
00629                                                                                                                 if (preg_match("/gap_(\d+)/", $ident, $matches))
00630                                                                                                                 {
00631                                                                                                                         $this->setSuggestedSolution($suggested_solution, $matches[1], true);
00632                                                                                                                 }
00633                                                                                                         }
00634                                                                                                 }
00635                                                                                         }
00636                                                                                         break;
00637                                                                         }
00638                                                                 }
00639                                                         }
00640                                                 }
00641                                                 break;
00642                                         case "resprocessing":
00643                                                 $resproc_nodes = $node->child_nodes();
00644                                                 foreach ($resproc_nodes as $index => $respcondition)
00645                                                 {
00646                                                         if (strcmp($respcondition->node_name(), "respcondition") == 0)
00647                                                         {
00648                                                                 $respcondition_array =& ilQTIUtils::_getRespcondition($respcondition);
00649                                                                 $found_answer = 0;
00650                                                                 foreach ($this->gaps[$respcondition_array["conditionvar"]["respident"]] as $key => $value)
00651                                                                 {
00652                                                                         if (strcmp($value->get_answertext(), $respcondition_array["conditionvar"]["value"]) == 0)
00653                                                                         {
00654                                                                                 $found_answer = 1;
00655                                                                                 $this->gaps[$respcondition_array["conditionvar"]["respident"]][$key]->set_points($respcondition_array["setvar"]["points"]);
00656                                                                                 if ($respcondition_array["conditionvar"]["selected"])
00657                                                                                 {
00658                                                                                         $this->gaps[$respcondition_array["conditionvar"]["respident"]][$key]->setChecked();
00659                                                                                 }
00660                                                                         }
00661                                                                 }
00662                                                                 if (!$found_answer)
00663                                                                 {
00664                                                                         // text gap
00665                                                                         array_push($this->gaps[$respcondition_array["conditionvar"]["respident"]], new ASS_AnswerCloze($respcondition_array["conditionvar"]["value"], $respcondition_array["setvar"]["points"], count($this->gaps[$respcondition_array["conditionvar"]["respident"]]), 1, CLOZE_TEXT, $respcondition_array["conditionvar"]["respident"], 0));
00666                                                                 }
00667                                                         }
00668                                                 }
00669                                                 break;
00670                                 }
00671                         }
00672                         $this->gaps = array_values($this->gaps);
00673                         $i = 0;
00674                         foreach ($materials as $key => $value)
00675                         {
00676                                 $this->cloze_text .= $value;
00677                                 $gaptext = $this->get_gap_text_list($i);
00678                                 if ($gaptext)
00679                                 {
00680                                         $type = " type=\"select\"";
00681                                         if ($this->gaps[$i][0]->get_cloze_type() == CLOZE_TEXT)
00682                                         {
00683                                                 $type = " type=\"text\"";
00684                                         }
00685                                         $shuffle = " shuffle=\"yes\"";
00686                                         if (!$this->gaps[$i][0]->get_shuffle())
00687                                         {
00688                                                 $shuffle = " shuffle=\"no\"";
00689                                         }
00690                                         $this->cloze_text .= "<gap$type$shuffle>$gaptext</gap>";
00691                                 }
00692                                 $i++;
00693                         }
00694                         $result = true;
00695                 }
00696                 return $result;
00697         }
00698 
00708         function to_xml($a_include_header = true, $a_include_binary = true, $a_shuffle = false, $test_output = false)
00709         {
00710                 if (!empty($this->domxml))
00711                 {
00712                         $this->domxml->free();
00713                 }
00714                 $xml_header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<questestinterop></questestinterop>\n";
00715                 $this->domxml = domxml_open_mem($xml_header);
00716                 $root = $this->domxml->document_element();
00717                 // qti ident
00718                 $qtiIdent = $this->domxml->create_element("item");
00719                 $qtiIdent->set_attribute("ident", "il_".IL_INST_ID."_qst_".$this->getId());
00720                 $qtiIdent->set_attribute("title", $this->getTitle());
00721                 $root->append_child($qtiIdent);
00722         // add question description
00723                 $qtiComment = $this->domxml->create_element("qticomment");
00724                 $qtiCommentText = $this->domxml->create_text_node($this->getComment());
00725                 $qtiComment->append_child($qtiCommentText);
00726                 $qtiIdent->append_child($qtiComment);
00727                 // add estimated working time
00728                 $qtiDuration = $this->domxml->create_element("duration");
00729                 $workingtime = $this->getEstimatedWorkingTime();
00730                 $qtiDurationText = $this->domxml->create_text_node(sprintf("P0Y0M0DT%dH%dM%dS", $workingtime["h"], $workingtime["m"], $workingtime["s"]));
00731                 $qtiDuration->append_child($qtiDurationText);
00732                 $qtiIdent->append_child($qtiDuration);
00733 
00734                 // add ILIAS specific metadata
00735                 $qtiItemmetadata = $this->domxml->create_element("itemmetadata");
00736                 $qtiMetadata = $this->domxml->create_element("qtimetadata");
00737                 
00738                 $qtiMetadatafield = $this->domxml->create_element("qtimetadatafield");
00739                 $qtiFieldlabel = $this->domxml->create_element("fieldlabel");
00740                 $qtiFieldlabelText = $this->domxml->create_text_node("ILIAS_VERSION");
00741                 $qtiFieldlabel->append_child($qtiFieldlabelText);
00742                 $qtiFieldentry = $this->domxml->create_element("fieldentry");
00743                 $qtiFieldentryText = $this->domxml->create_text_node($this->ilias->getSetting("ilias_version"));
00744                 $qtiFieldentry->append_child($qtiFieldentryText);
00745                 $qtiMetadatafield->append_child($qtiFieldlabel);
00746                 $qtiMetadatafield->append_child($qtiFieldentry);
00747                 $qtiMetadata->append_child($qtiMetadatafield);
00748 
00749                 $qtiMetadatafield = $this->domxml->create_element("qtimetadatafield");
00750                 $qtiFieldlabel = $this->domxml->create_element("fieldlabel");
00751                 $qtiFieldlabelText = $this->domxml->create_text_node("QUESTIONTYPE");
00752                 $qtiFieldlabel->append_child($qtiFieldlabelText);
00753                 $qtiFieldentry = $this->domxml->create_element("fieldentry");
00754                 $qtiFieldentryText = $this->domxml->create_text_node(CLOZE_TEST_IDENTIFIER);
00755                 $qtiFieldentry->append_child($qtiFieldentryText);
00756                 $qtiMetadatafield->append_child($qtiFieldlabel);
00757                 $qtiMetadatafield->append_child($qtiFieldentry);
00758                 $qtiMetadata->append_child($qtiMetadatafield);
00759                 
00760                 $qtiMetadatafield = $this->domxml->create_element("qtimetadatafield");
00761                 $qtiFieldlabel = $this->domxml->create_element("fieldlabel");
00762                 $qtiFieldlabelText = $this->domxml->create_text_node("AUTHOR");
00763                 $qtiFieldlabel->append_child($qtiFieldlabelText);
00764                 $qtiFieldentry = $this->domxml->create_element("fieldentry");
00765                 $qtiFieldentryText = $this->domxml->create_text_node($this->getAuthor());
00766                 $qtiFieldentry->append_child($qtiFieldentryText);
00767                 $qtiMetadatafield->append_child($qtiFieldlabel);
00768                 $qtiMetadatafield->append_child($qtiFieldentry);
00769                 $qtiMetadata->append_child($qtiMetadatafield);
00770                 
00771                 $qtiItemmetadata->append_child($qtiMetadata);
00772                 $qtiIdent->append_child($qtiItemmetadata);
00773                 
00774                 // PART I: qti presentation
00775                 $qtiPresentation = $this->domxml->create_element("presentation");
00776                 $qtiPresentation->set_attribute("label", $this->getTitle());
00777                 // add flow to presentation
00778                 $qtiFlow = $this->domxml->create_element("flow");
00779 
00780                 $text_parts = preg_split("/<gap.*?<\/gap>/", $this->get_cloze_text());
00781                 // add material with question text to presentation
00782                 for ($i = 0; $i <= $this->get_gap_count(); $i++)
00783                 {
00784                         // n-th text part
00785                         $qtiMaterial = $this->domxml->create_element("material");
00786                         $qtiMatText = $this->domxml->create_element("mattext");
00787                         $qtiMatTextText = $this->domxml->create_text_node($text_parts[$i]);
00788                         $qtiMatText->append_child($qtiMatTextText);
00789                         $qtiMaterial->append_child($qtiMatText);
00790                         $qtiFlow->append_child($qtiMaterial);
00791 
00792                         if ($i < $this->get_gap_count())
00793                         {
00794                                 // add gap
00795                                 $gap = $this->get_gap($i);
00796                                 if ($gap[0]->get_cloze_type() == CLOZE_SELECT)
00797                                 {
00798                                         // comboboxes
00799                                         $qtiResponseStr = $this->domxml->create_element("response_str");
00800                                         $qtiResponseStr->set_attribute("ident", "gap_$i");
00801                                         $qtiResponseStr->set_attribute("rcardinality", "Single");
00802                                         $solution = $this->getSuggestedSolution($i);
00803                                         if (count($solution))
00804                                         {
00805                                                 if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $solution["internal_link"], $matches))
00806                                                 {
00807                                                         $qtiMaterial = $this->domxml->create_element("material");
00808                                                         $qtiMaterial->set_attribute("label", "suggested_solution");
00809                                                         $qtiMatText = $this->domxml->create_element("mattext");
00810                                                         $intlink = "il_" . IL_INST_ID . "_" . $matches[2] . "_" . $matches[3];
00811                                                         if (strcmp($matches[1], "") != 0)
00812                                                         {
00813                                                                 $intlink = $solution["internal_link"];
00814                                                         }
00815                                                         $qtiMatTextText = $this->domxml->create_text_node($intlink);
00816                                                         $qtiMatText->append_child($qtiMatTextText);
00817                                                         $qtiMaterial->append_child($qtiMatText);
00818                                                         $qtiResponseStr->append_child($qtiMaterial);
00819                                                 }
00820                                         }
00821                                         
00822                                         $qtiRenderChoice = $this->domxml->create_element("render_choice");
00823                                         // shuffle output
00824                                         if ($gap[0]->get_shuffle())
00825                                         {
00826                                                 $qtiRenderChoice->set_attribute("shuffle", "Yes");
00827                                         }
00828                                         else
00829                                         {
00830                                                 $qtiRenderChoice->set_attribute("shuffle", "No");
00831                                         }
00832 
00833                                         $gkeys = array_keys($gap);
00834                                         if ($this->getshuffle() && $a_shuffle)
00835                                         {
00836                                                 $gkeys = $this->pcArrayShuffle($gkeys);
00837                                         }
00838 
00839                                         // add answers
00840                                         foreach ($gkeys as $key)
00841                                         {
00842                                                 $value = $gap[$key];
00843                                                 $qtiResponseLabel = $this->domxml->create_element("response_label");
00844                                                 $qtiResponseLabel->set_attribute("ident", $key);
00845                                                 $qtiMaterial = $this->domxml->create_element("material");
00846                                                 $qtiMatText = $this->domxml->create_element("mattext");
00847                                                 $tmpvalue = $value->get_answertext();
00848                                                 $qtiMatTextText = $this->domxml->create_text_node($tmpvalue);
00849                                                 $qtiMatText->append_child($qtiMatTextText);
00850                                                 $qtiMaterial->append_child($qtiMatText);
00851                                                 $qtiResponseLabel->append_child($qtiMaterial);
00852                                                 $qtiRenderChoice->append_child($qtiResponseLabel);
00853                                         }
00854                                         $qtiResponseStr->append_child($qtiRenderChoice);
00855                                         $qtiFlow->append_child($qtiResponseStr);
00856                                 }
00857                                 else
00858                                 {
00859                                         // text fields
00860                                         $qtiResponseStr = $this->domxml->create_element("response_str");
00861                                         $qtiResponseStr->set_attribute("ident", "gap_$i");
00862                                         $qtiResponseStr->set_attribute("rcardinality", "Single");
00863                                         $solution = $this->getSuggestedSolution($i);
00864                                         if (count($solution))
00865                                         {
00866                                                 if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $solution["internal_link"], $matches))
00867                                                 {
00868                                                         $qtiMaterial = $this->domxml->create_element("material");
00869                                                         $qtiMaterial->set_attribute("label", "suggested_solution");
00870                                                         $qtiMatText = $this->domxml->create_element("mattext");
00871                                                         $intlink = "il_" . IL_INST_ID . "_" . $matches[2] . "_" . $matches[3];
00872                                                         if (strcmp($matches[1], "") != 0)
00873                                                         {
00874                                                                 $intlink = $solution["internal_link"];
00875                                                         }
00876                                                         $qtiMatTextText = $this->domxml->create_text_node($intlink);
00877                                                         $qtiMatText->append_child($qtiMatTextText);
00878                                                         $qtiMaterial->append_child($qtiMatText);
00879                                                         $qtiResponseStr->append_child($qtiMaterial);
00880                                                 }
00881                                         }
00882                                         $qtiRenderFib = $this->domxml->create_element("render_fib");
00883                                         $qtiRenderFib->set_attribute("fibtype", "String");
00884                                         $qtiRenderFib->set_attribute("prompt", "Box");
00885                                         $qtiResponseLabel = $this->domxml->create_element("response_label");
00886                                         $qtiResponseLabel->set_attribute("ident", $i);
00887                                         $qtiRenderFib->append_child($qtiResponseLabel);
00888                                         $qtiResponseStr->append_child($qtiRenderFib);
00889                                         $qtiFlow->append_child($qtiResponseStr);
00890                                 }
00891                         }
00892                 }
00893                 $qtiPresentation->append_child($qtiFlow);
00894                 $qtiIdent->append_child($qtiPresentation);
00895 
00896                 // PART II: qti resprocessing
00897                 $qtiResprocessing = $this->domxml->create_element("resprocessing");
00898                 $qtiOutcomes = $this->domxml->create_element("outcomes");
00899                 $qtiDecvar = $this->domxml->create_element("decvar");
00900                 $qtiOutcomes->append_child($qtiDecvar);
00901                 $qtiResprocessing->append_child($qtiOutcomes);
00902                 // add response conditions
00903                 for ($i = 0; $i < $this->get_gap_count(); $i++)
00904                 {
00905                         $gap = $this->get_gap($i);
00906                         if ($gap[0]->get_cloze_type() == CLOZE_SELECT)
00907                         {
00908                                 foreach ($gap as $index => $answer)
00909                                 {
00910                                         $qtiRespcondition = $this->domxml->create_element("respcondition");
00911                                         $qtiRespcondition->set_attribute("continue", "Yes");
00912                                         // qti conditionvar
00913                                         $qtiConditionvar = $this->domxml->create_element("conditionvar");
00914 
00915                                         if (!$answer->isStateSet())
00916                                         {
00917                                                 $qtinot = $this->domxml->create_element("not");
00918                                         }
00919                                         
00920                                         $qtiVarequal = $this->domxml->create_element("varequal");
00921                                         $qtiVarequal->set_attribute("respident", "gap_$i");
00922                                         $qtiVarequalText = $this->domxml->create_text_node($answer->get_answertext());
00923                                         $qtiVarequal->append_child($qtiVarequalText);
00924                                         if (!$answer->isStateSet())
00925                                         {
00926                                                 $qtiConditionvar->append_child($qtinot);
00927                                                 $qtinot->append_child($qtiVarequal);
00928                                         }
00929                                         else
00930                                         {
00931                                                 $qtiConditionvar->append_child($qtiVarequal);
00932                                         }
00933                                         // qti setvar
00934                                         $qtiSetvar = $this->domxml->create_element("setvar");
00935                                         $qtiSetvar->set_attribute("action", "Add");
00936                                         $qtiSetvarText = $this->domxml->create_text_node($answer->get_points());
00937                                         $qtiSetvar->append_child($qtiSetvarText);
00938                                         // qti displayfeedback
00939                                         $qtiDisplayfeedback = $this->domxml->create_element("displayfeedback");
00940                                         $qtiDisplayfeedback->set_attribute("feedbacktype", "Response");
00941                                         $linkrefid = "";
00942                                         if ($answer->isStateSet())
00943                                         {
00944                                                 $linkrefid = "$i" . "_True";
00945                                         }
00946                                                 else
00947                                         {
00948                                                 $linkrefid = "$i" . "_False_$index";
00949                                         }
00950                                         $qtiDisplayfeedback->set_attribute("linkrefid", $linkrefid);
00951                                         $qtiRespcondition->append_child($qtiConditionvar);
00952                                         $qtiRespcondition->append_child($qtiSetvar);
00953                                         $qtiRespcondition->append_child($qtiDisplayfeedback);
00954                                         $qtiResprocessing->append_child($qtiRespcondition);
00955                                 }
00956                         }
00957                         else
00958                         {
00959                                 foreach ($gap as $index => $answer)
00960                                 {
00961                                         $qtiRespcondition = $this->domxml->create_element("respcondition");
00962                                         $qtiRespcondition->set_attribute("continue", "Yes");
00963                                         // qti conditionvar
00964                                         $qtiConditionvar = $this->domxml->create_element("conditionvar");
00965                                         $qtiVarequal = $this->domxml->create_element("varequal");
00966                                         $qtiVarequal->set_attribute("respident", "gap_$i");
00967                                         $qtiVarequalText = $this->domxml->create_text_node($answer->get_answertext());
00968                                         $qtiVarequal->append_child($qtiVarequalText);
00969                                         $qtiConditionvar->append_child($qtiVarequal);
00970                                         // qti setvar
00971                                         $qtiSetvar = $this->domxml->create_element("setvar");
00972                                         $qtiSetvar->set_attribute("action", "Add");
00973                                         $qtiSetvarText = $this->domxml->create_text_node($answer->get_points());
00974                                         $qtiSetvar->append_child($qtiSetvarText);
00975                                         // qti displayfeedback
00976                                         $qtiDisplayfeedback = $this->domxml->create_element("displayfeedback");
00977                                         $qtiDisplayfeedback->set_attribute("feedbacktype", "Response");
00978                                         $qtiDisplayfeedback->set_attribute("linkrefid", "$i" . "_True_$index");
00979                                         $qtiRespcondition->append_child($qtiConditionvar);
00980                                         $qtiRespcondition->append_child($qtiSetvar);
00981                                         $qtiRespcondition->append_child($qtiDisplayfeedback);
00982                                         $qtiResprocessing->append_child($qtiRespcondition);
00983                                 }
00984                         }
00985                 }
00986                 $qtiIdent->append_child($qtiResprocessing);
00987 
00988                 // PART III: qti itemfeedback
00989                 for ($i = 0; $i < $this->get_gap_count(); $i++)
00990                 {
00991                         $gap = $this->get_gap($i);
00992                         if ($gap[0]->get_cloze_type() == CLOZE_SELECT)
00993                         {
00994                                 foreach ($gap as $index => $answer)
00995                                 {
00996                                         $qtiItemfeedback = $this->domxml->create_element("itemfeedback");
00997                                         $linkrefid = "";
00998                                         if ($answer->isStateSet())
00999                                         {
01000                                                 $linkrefid = "$i" . "_True";
01001                                         }
01002                                                 else
01003                                         {
01004                                                 $linkrefid = "$i" . "_False_$index";
01005                                         }
01006                                         $qtiItemfeedback->set_attribute("ident", $linkrefid);
01007                                         $qtiItemfeedback->set_attribute("view", "All");
01008                                         // qti flow_mat
01009                                         $qtiFlowmat = $this->domxml->create_element("flow_mat");
01010                                         $qtiMaterial = $this->domxml->create_element("material");
01011                                         $qtiMattext = $this->domxml->create_element("mattext");
01012                                         // Insert response text for right/wrong answers here!!!
01013                                         $qtiMattextText = $this->domxml->create_text_node("");
01014                                         $qtiMattext->append_child($qtiMattextText);
01015                                         $qtiMaterial->append_child($qtiMattext);
01016                                         $qtiFlowmat->append_child($qtiMaterial);
01017                                         $qtiItemfeedback->append_child($qtiFlowmat);
01018                                         $qtiIdent->append_child($qtiItemfeedback);
01019                                 }
01020                         }
01021                         else
01022                         {
01023                                 foreach ($gap as $index => $answer)
01024                                 {
01025                                         $qtiItemfeedback = $this->domxml->create_element("itemfeedback");
01026                                         $linkrefid = "";
01027                                         if ($answer->isStateSet())
01028                                         {
01029                                                 $linkrefid = "$i" . "_True_$index";
01030                                         }
01031                                                 else
01032                                         {
01033                                                 $linkrefid = "$i" . "_False_$index";
01034                                         }
01035                                         $qtiItemfeedback->set_attribute("ident", $linkrefid);
01036                                         $qtiItemfeedback->set_attribute("view", "All");
01037                                         // qti flow_mat
01038                                         $qtiFlowmat = $this->domxml->create_element("flow_mat");
01039                                         $qtiMaterial = $this->domxml->create_element("material");
01040                                         $qtiMattext = $this->domxml->create_element("mattext");
01041                                         // Insert response text for right/wrong answers here!!!
01042                                         $qtiMattextText = $this->domxml->create_text_node("");
01043                                         $qtiMattext->append_child($qtiMattextText);
01044                                         $qtiMaterial->append_child($qtiMattext);
01045                                         $qtiFlowmat->append_child($qtiMaterial);
01046                                         $qtiItemfeedback->append_child($qtiFlowmat);
01047                                         $qtiIdent->append_child($qtiItemfeedback);
01048                                 }
01049                         }
01050                 }
01051 
01052                 $xml = $this->domxml->dump_mem(true);
01053                 if (!$a_include_header)
01054                 {
01055                         $pos = strpos($xml, "?>");
01056                         $xml = substr($xml, $pos + 2);
01057                 }
01058 //echo htmlentities($xml);
01059                 return $xml;
01060 
01061         }
01062 
01074         function set_cloze_text($cloze_text = "")
01075         {
01076                 $this->gaps = array();
01077                 $this->cloze_text =& $cloze_text;
01078                 $close = $this->createCloseTextArray();
01079                 if (count($close))
01080                 {
01081                         foreach ($close["gaps"] as $key => $value)
01082                         {
01083                                 if (strcmp(strtolower($value["params"]["type"]), "select") == 0)
01084                                 {
01085                                         $type = CLOZE_SELECT;
01086                                 }
01087                                         else
01088                                 {
01089                                         $type = CLOZE_TEXT;
01090                                 }
01091                                 if ($type == CLOZE_TEXT)
01092                                 {
01093                                         $default_state = 1;
01094                                 }
01095                                 else
01096                                 {
01097                                         $default_state = 0;
01098                                 }
01099                                 $name = $value["params"]["name"];
01100                                 if (strcmp(strtolower($value["params"]["shuffle"]), "no") == 0)
01101                                 {
01102                                         $shuffle = 0;
01103                                 }
01104                                         else
01105                                 {
01106                                         $shuffle = 1;
01107                                 }
01108                                 $answer_array = array();
01109                                 foreach ($value["text"] as $index => $textvalue)
01110                                 {
01111                                         if (preg_match("/\d+/", $index))
01112                                         {
01113                                                 $textvalue = str_replace("\,", ",", $textvalue);
01114                                                 array_push($answer_array, new ASS_AnswerCloze($textvalue, 0, $index, $default_state, $type, $name, $shuffle));
01115                                         }
01116                                 }
01117                                 array_push($this->gaps, $answer_array);
01118                         }
01119                 }
01120         }
01121 
01131   function get_cloze_text() {
01132     return $this->cloze_text;
01133   }
01134 
01144   function get_start_tag() {
01145     return $this->start_tag;
01146   }
01147 
01157   function get_end_tag() {
01158     return $this->end_tag;
01159   }
01160 
01170   function set_start_tag($start_tag = "<gap>") {
01171     $this->start_tag = $start_tag;
01172   }
01173 
01174 
01184   function set_end_tag($end_tag = "</gap>") {
01185     $this->end_tag = $end_tag;
01186   }
01187 
01196   function rebuild_cloze_text() 
01197         {
01198                 $close =& $this->createCloseTextArray();
01199                 if (count($close))
01200                 {
01201                         for ($i = 0; $i < count($this->gaps); $i++)
01202                         {
01203                                 $gaptext = $this->get_gap_text_list($i);
01204                                 $textparams = preg_split("/(?<!\\\\),/", $gaptext);
01205                                 $close["gaps"][$i]["text"] = array();
01206                                 $close["gaps"][$i]["text"]["text"] = $gaptext;
01207                                 foreach ($textparams as $key => $value)
01208                                 {
01209                                         $close["gaps"][$i]["text"][$key] = $value;
01210                                 }
01211                         }
01212                 }
01213                 $this->createCloseTextFromArray($close);
01214   }
01215 
01227   function get_gap($index = 0) {
01228     if ($index < 0) return array();
01229     if (count($this->gaps) < 1) return array();
01230     if ($index >= count($this->gaps)) return array();
01231     return $this->gaps[$index];
01232   }
01233 
01243   function get_gap_count() {
01244     return count($this->gaps);
01245   }
01246 
01259   function get_gap_text_list($index = 0, $separator = ",") {
01260     if ($index < 0) return "";
01261     if (count($this->gaps) < 1) return "";
01262     if ($index >= count($this->gaps)) return "";
01263     $result = array();
01264     foreach ($this->gaps[$index] as $key => $value) {
01265                         array_push($result, str_replace(",", "\,", $value->get_answertext()));
01266     }
01267     return join($separator, $result);
01268   }
01278   function get_gap_text_count($index = 0) {
01279     if ($index < 0) return 0;
01280     if (count($this->gaps) < 1) return 0;
01281     if ($index >= count($this->gaps)) return 0;
01282     return count($this->gaps[$index]);
01283   }
01294   function delete_gap($index = 0) {
01295     if ($index < 0) return;
01296     if (count($this->gaps) < 1) return;
01297     if ($index >= count($this->gaps)) return;
01298                 $close = $this->createCloseTextArray();
01299                 unset($close["gaps"][$index]);
01300                 $this->createCloseTextFromArray($close);
01301     unset($this->gaps[$index]);
01302     $this->gaps = array_values($this->gaps);
01303   }
01304 
01313   function flush_gaps() {
01314     $this->gaps = array();
01315   }
01316 
01328   function delete_answertext_by_index($gap_index = 0, $answertext_index = 0) {
01329     if ($gap_index < 0) return;
01330     if (count($this->gaps) < 1) return;
01331     if ($gap_index >= count($this->gaps)) return;
01332     $old_text = $this->get_gap_text_list($gap_index);
01333                 if (count($this->gaps[$gap_index]) == 1) {
01334                         $this->delete_gap($gap_index);
01335                 } else {
01336                         $close = $this->createCloseTextArray();
01337                         unset($this->gaps[$gap_index][$answertext_index]);
01338       $this->gaps[$gap_index] = array_values($this->gaps[$gap_index]);
01339                         unset($close["gaps"][$gap_index]["text"][$answertext_index]);
01340                         $this->createCloseTextFromArray($close);
01341                 }
01342   }
01343 
01356   function set_answertext($index = 0, $answertext_index = 0, $answertext = "", $add_gaptext=0) {
01357                 $answertext = str_replace("\,", ",", $answertext);
01358         if ($add_gaptext == 1)    {
01359         $arr = $this->gaps[$index][0];
01360         if (strlen($this->gaps[$index][count($this->gaps[$index])-1]->get_answertext()) != 0) {
01361                                 $default_state = 0;
01362                                 if ($arr->get_cloze_type() == CLOZE_TEXT)
01363                                 {
01364                                         $default_state = 1;
01365                                 }
01366                 array_push($this->gaps[$index], new ASS_AnswerCloze($answertext, 0, count($this->gaps[$index]),
01367                         $default_state, $arr->get_cloze_type(),
01368                         $arr->get_name(), $arr->get_shuffle()));
01369                 $this->rebuild_cloze_text();
01370         }
01371         return;
01372     }
01373     if ($index < 0) return;
01374     if (count($this->gaps) < 1) return;
01375     if ($index >= count($this->gaps)) return;
01376     if ($answertext_index < 0) return;
01377     if (count($this->gaps[$index]) < 1) return;
01378     if ($answertext_index >= count($this->gaps[$index])) return;
01379 
01380 
01381     if (strlen($answertext) == 0) {
01382       // delete the answertext
01383       $this->delete_answertext($index, $this->gaps[$index][$answertext_index]->get_answertext());
01384     } else {
01385       $this->gaps[$index][$answertext_index]->set_answertext($answertext);
01386       $this->rebuild_cloze_text();
01387     }
01388   }
01389 
01398         function update_all_gap_params() {
01399                 global $lng;
01400                 $close = $this->createCloseTextArray();
01401                 for ($i = 0; $i < $this->get_gap_count(); $i++)
01402                 {
01403                         $gaptext = $this->get_gap_text_list($i);
01404                         if ($this->gaps[$i][0]->get_cloze_type() == CLOZE_TEXT)
01405                         {
01406                                 $close["gaps"][$i]["params"]["type"] = "text";
01407                                 if (array_key_exists("shuffle", $close["gaps"][$i]["params"]))
01408                                 {
01409                                         unset($close["gaps"][$i]["params"]["shuffle"]);
01410                                 }
01411                         }
01412                                 else
01413                         {
01414                                 $close["gaps"][$i]["params"]["type"] = "select";
01415                                 if ($this->gaps[$i][0]->get_shuffle() == 0)
01416                                 {
01417                                         $close["gaps"][$i]["params"]["shuffle"] = "no";
01418                                 }
01419                                         else
01420                                 {
01421                                         $close["gaps"][$i]["params"]["shuffle"] = "yes";
01422                                 }
01423                         }
01424                         $name = $this->gaps[$i][0]->get_name();
01425                         if (!$name)
01426                         {
01427                                 $name = $this->lng->txt("gap") . " " . ($i+1);
01428                         }
01429                         $close["gaps"][$i]["params"]["name"] = $name;
01430                 }
01431                 $this->createCloseTextFromArray($close);
01432         }
01433 
01444         function set_cloze_type($index, $cloze_type = CLOZE_TEXT) {
01445     if ($index < 0) return;
01446     if (count($this->gaps) < 1) return;
01447     if ($index >= count($this->gaps)) return;
01448                 $close = $this->createCloseTextArray();
01449                 foreach ($this->gaps[$index] as $key => $value) {
01450                         $this->gaps[$index][$key]->set_cloze_type($cloze_type);
01451                         $this->gaps[$index][$key]->setState(1);
01452                 }
01453                 if ($cloze_type == CLOZE_TEXT)
01454                 {
01455                         $type = "text";
01456                 }
01457                 else
01458                 {
01459                         $type = "select";
01460                 }
01461                 $close["gaps"][$index]["type"] = $type;
01462                 $this->createCloseTextFromArray($close);
01463         }
01464 
01476   function set_gap_points($index = 0, $points = 0.0) {
01477     if ($index < 0) return;
01478     if (count($this->gaps) < 1) return;
01479     if ($index >= count($this->gaps)) return;
01480     foreach ($this->gaps[$index] as $key => $value) {
01481       $this->gaps[$index][$key]->set_points($points);
01482     }
01483   }
01484 
01496   function set_gap_shuffle($index = 0, $shuffle = 1) {
01497     if ($index < 0) return;
01498     if (count($this->gaps) < 1) return;
01499     if ($index >= count($this->gaps)) return;
01500     foreach ($this->gaps[$index] as $key => $value) {
01501       $this->gaps[$index][$key]->set_shuffle($shuffle);
01502     }
01503   }
01504 
01505 
01518   function set_single_answer_points($index_gaps = 0, $index_answerobject = 0, $points = 0.0) {
01519     if ($index_gaps < 0) return;
01520     if (count($this->gaps) < 1) return;
01521     if ($index_gaps >= count($this->gaps)) return;
01522     if ($index_answerobject < 0) return;
01523     if (count($this->gaps[$index_gaps]) < 1) return;
01524     if ($index_answerobject >= count($this->gaps[$index_gaps])) return;
01525     $this->gaps[$index_gaps][$index_answerobject]->set_points($points);
01526   }
01527 
01540   function set_single_answer_state($index_gaps = 0, $index_answerobject = 0, $state = 0) {
01541     if ($index_gaps < 0) return;
01542     if (count($this->gaps) < 1) return;
01543     if ($index_gaps >= count($this->gaps)) return;
01544     if ($index_answerobject < 0) return;
01545     if (count($this->gaps[$index_gaps]) < 1) return;
01546     if ($index_answerobject >= count($this->gaps[$index_gaps])) return;
01547     $this->gaps[$index_gaps][$index_answerobject]->setState($state);
01548   }
01549         
01559   function getReachedPoints($user_id, $test_id) {
01560     $found_value1 = array();
01561     $found_value2 = array();
01562     $query = sprintf("SELECT * FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
01563       $this->ilias->db->quote($user_id),
01564       $this->ilias->db->quote($test_id),
01565       $this->ilias->db->quote($this->getId())
01566     );
01567     $result = $this->ilias->db->query($query);
01568                 $user_result = array();
01569     while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
01570                         if (strcmp($data->value2, "") != 0)
01571                         {
01572                                 $user_result[$data->value1] = array(
01573                                         "gap_id" => $data->value1,
01574                                         "value" => $data->value2
01575                                 );
01576                         }
01577     }
01578     $points = 0;
01579     $counter = 0;
01580                 foreach ($user_result as $gap_id => $value) {
01581                         if ($this->gaps[$gap_id][0]->get_cloze_type() == CLOZE_TEXT) 
01582                         {
01583                                 $foundsolution = 0;
01584                                 foreach ($this->gaps[$gap_id] as $k => $v) {
01585                                         if ((strcmp(strtolower($v->get_answertext()), strtolower($value["value"])) == 0) && (!$foundsolution)) {
01586                                                 $points += $v->get_points();
01587                                                 $foundsolution = 1;
01588                                         }
01589                                 }
01590                         } 
01591                         else 
01592                         {
01593                                 if ($value["value"] >= 0)
01594                                 {
01595                                         foreach ($this->gaps[$gap_id] as $answerkey => $answer)
01596                                         {
01597                                                 if ($value["value"] == $answerkey)
01598                                                 {
01599                                                         $points += $answer->get_points();
01600                                                 }
01601                                         }
01602                                 }
01603                         }
01604     }
01605     return $points;
01606   }
01607 
01617   function getReachedInformation($user_id, $test_id) {
01618     $found_value1 = array();
01619     $found_value2 = array();
01620     $query = sprintf("SELECT * FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
01621       $this->ilias->db->quote($user_id),
01622       $this->ilias->db->quote($test_id),
01623       $this->ilias->db->quote($this->getId())
01624     );
01625     $result = $this->ilias->db->query($query);
01626     while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT)) {
01627       array_push($found_value1, $data->value1);
01628       array_push($found_value2, $data->value2);
01629     }
01630     $counter = 1;
01631                 $user_result = array();
01632     foreach ($found_value1 as $key => $value) {
01633       if ($this->gaps[$value][0]->get_cloze_type() == CLOZE_TEXT) 
01634                         {
01635                                 $solution = array(
01636                                         "gap" => "$counter",
01637                                         "points" => 0,
01638                                         "true" => 0,
01639                                         "value" => $found_value2[$key]
01640                                 );
01641         foreach ($this->gaps[$value] as $k => $v) {
01642           if (strcmp(strtolower($v->get_answertext()), strtolower($found_value2[$key])) == 0) {
01643                                                 $solution = array(
01644                                                         "gap" => "$counter",
01645                                                         "points" => $v->get_points(),
01646                                                         "true" => 1,
01647                                                         "value" => $found_value2[$key]
01648                                                 );
01649           }
01650         }
01651       } 
01652                         else 
01653                         {
01654                                 $solution = array(
01655                                         "gap" => "$counter",
01656                                         "points" => 0,
01657                                         "true" => 0,
01658                                         "value" => $found_value2[$key]
01659                                 );
01660         if ($this->gaps[$value][$found_value1[$key]]->isStateSet()) {
01661                                         $solution["points"] = $this->gaps[$value][$found_value1[$key]]->get_points();
01662                                         $solution["true"] = 1;
01663         }
01664       }
01665                         $counter++;
01666                         $user_result[$value] = $solution;
01667     }
01668     return $user_result;
01669   }
01670 
01679   function getMaximumPoints() {
01680     $points = 0;
01681     foreach ($this->gaps as $key => $value) {
01682       if ($value[0]->get_cloze_type() == CLOZE_TEXT) {
01683         $points += $value[0]->get_points();
01684       } else {
01685                                 $points_arr = array("set" => 0, "unset" => 0);
01686         foreach ($value as $key2 => $value2) {
01687                                         if ($value2->get_points() > $points_arr["set"])
01688                                         {
01689                                                 $points_arr["set"] = $value2->get_points();
01690                                         }
01691                                 }
01692                                 $points += $points_arr["set"];
01693       }
01694     }
01695     return $points;
01696   }
01697 
01708   function saveWorkingData($test_id, $limit_to = LIMIT_NO_LIMIT) {
01709     global $ilDB;
01710                 global $ilUser;
01711     $db =& $ilDB->db;
01712 
01713     $query = sprintf("DELETE FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
01714       $db->quote($ilUser->id),
01715       $db->quote($test_id),
01716       $db->quote($this->getId())
01717     );
01718     $result = $db->query($query);
01719 
01720     foreach ($_POST as $key => $value) {
01721       if (preg_match("/^gap_(\d+)/", $key, $matches)) {
01722         $query = sprintf("INSERT INTO tst_solutions (solution_id, user_fi, test_fi, question_fi, value1, value2, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, NULL)",
01723                                         $db->quote($ilUser->id),
01724                                         $db->quote($test_id),
01725           $db->quote($this->getId()),
01726           $db->quote($matches[1]),
01727           $db->quote(ilUtil::stripSlashes($value))
01728         );
01729         $result = $db->query($query);
01730       }
01731     }
01732     //parent::saveWorkingData($limit_to);
01733                 return true;
01734   }
01735 
01736         function syncWithOriginal()
01737         {
01738                 global $ilias;
01739                 if ($this->original_id)
01740                 {
01741                         $complete = 0;
01742                         if ($this->isComplete())
01743                         {
01744                                 $complete = 1;
01745                         }
01746                         $db = & $ilias->db;
01747         
01748                         $estw_time = $this->getEstimatedWorkingTime();
01749                         $estw_time = sprintf("%02d:%02d:%02d", $estw_time['h'], $estw_time['m'], $estw_time['s']);
01750         
01751                         $query = sprintf("UPDATE qpl_questions SET obj_fi = %s, title = %s, comment = %s, author = %s, question_text = %s, working_time = %s, shuffle = %s, complete = %s WHERE question_id = %s",
01752                                 $db->quote($this->obj_id. ""),
01753                                 $db->quote($this->title . ""),
01754                                 $db->quote($this->comment . ""),
01755                                 $db->quote($this->author . ""),
01756                                 $db->quote($this->cloze_text . ""),
01757                                 $db->quote($estw_time . ""),
01758                                 $db->quote($this->shuffle . ""),
01759                                 $db->quote($complete . ""),
01760                                 $db->quote($this->original_id . "")
01761                                 );
01762                         $result = $db->query($query);
01763 
01764                         if ($result == DB_OK)
01765                         {
01766                                 // write answers
01767                                 // delete old answers
01768                                 $query = sprintf("DELETE FROM qpl_answers WHERE question_fi = %s",
01769                                         $db->quote($this->original_id)
01770                                 );
01771                                 $result = $db->query($query);
01772         
01773                                 foreach ($this->gaps as $key => $value)
01774                                 {
01775                                         foreach ($value as $answer_id => $answer_obj)
01776                                         {
01777                                                 $query = sprintf("INSERT INTO qpl_answers (answer_id, question_fi, gap_id, answertext, points, aorder, cloze_type, name, shuffle, correctness, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
01778                                                         $db->quote($this->original_id . ""),
01779                                                         $db->quote($key . ""),
01780                                                         $db->quote($answer_obj->get_answertext() . ""),
01781                                                         $db->quote($answer_obj->get_points() . ""),
01782                                                         $db->quote($answer_obj->get_order() . ""),
01783                                                         $db->quote($answer_obj->get_cloze_type() . ""),
01784                                                         $db->quote($answer_obj->get_name() . ""),
01785                                                         $db->quote($answer_obj->get_shuffle() . ""),
01786                                                         $db->quote($answer_obj->getState() . "")
01787                                                         );
01788                                                 $answer_result = $db->query($query);
01789                                         }
01790                                 }
01791                         }
01792                         parent::syncWithOriginal();
01793                 }
01794         }
01795 
01804         function getQuestionType()
01805         {
01806                 return 3;
01807         }
01808 }
01809 
01810 ?>

Generated on Fri Dec 13 2013 09:06:32 for ILIAS Release_3_4_x_branch .rev 46804 by  doxygen 1.7.1