00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 require_once "./assessment/classes/class.assQuestion.php";
00025 require_once "./assessment/classes/class.assAnswerOrdering.php";
00026
00027 define ("OQ_PICTURES", 0);
00028 define ("OQ_TERMS", 1);
00029
00030 define ("ORDERING_QUESTION_IDENTIFIER", "ORDERING QUESTION");
00031
00042 class ASS_OrderingQuestion extends ASS_Question
00043 {
00051 var $question;
00052
00060 var $answers;
00061
00070 var $ordering_type;
00071
00084 function ASS_OrderingQuestion (
00085 $title = "",
00086 $comment = "",
00087 $author = "",
00088 $owner = -1,
00089 $question = "",
00090 $ordering_type = OQ_TERMS
00091 )
00092 {
00093 $this->ASS_Question($title, $comment, $author, $owner);
00094 $this->answers = array();
00095 $this->question = $question;
00096 $this->ordering_type = $ordering_type;
00097 }
00098
00107 function isComplete()
00108 {
00109 if (($this->title) and ($this->author) and ($this->question) and (count($this->answers)))
00110 {
00111 return true;
00112 }
00113 else
00114 {
00115 return false;
00116 }
00117 }
00118
00128 function from_xml($xml_text)
00129 {
00130 $result = false;
00131 if (!empty($this->domxml))
00132 {
00133 $this->domxml->free();
00134 }
00135 $xml_text = preg_replace("/>\s*?</", "><", $xml_text);
00136 $this->domxml = domxml_open_mem($xml_text);
00137 if (!empty($this->domxml))
00138 {
00139 $root = $this->domxml->document_element();
00140 $item = $root->first_child();
00141 $this->setTitle($item->get_attribute("title"));
00142 $this->gaps = array();
00143 $itemnodes = $item->child_nodes();
00144 $materials = array();
00145 $images = array();
00146 $shuffle = "";
00147 foreach ($itemnodes as $index => $node)
00148 {
00149 switch ($node->node_name())
00150 {
00151 case "qticomment":
00152 $comment = $node->get_content();
00153 if (strpos($comment, "ILIAS Version=") !== false)
00154 {
00155 }
00156 elseif (strpos($comment, "Questiontype=") !== false)
00157 {
00158 }
00159 elseif (strpos($comment, "Author=") !== false)
00160 {
00161 $comment = str_replace("Author=", "", $comment);
00162 $this->setAuthor($comment);
00163 }
00164 else
00165 {
00166 $this->setComment($comment);
00167 }
00168 break;
00169 case "itemmetadata":
00170 $md_array = array();
00171 $metanodes = $node->child_nodes();
00172 foreach ($metanodes as $metanode)
00173 {
00174 switch ($metanode->node_name())
00175 {
00176 case "qtimetadata":
00177 $metafields = $metanode->child_nodes();
00178 foreach ($metafields as $metafield)
00179 {
00180 switch ($metafield->node_name())
00181 {
00182 case "qtimetadatafield":
00183 $metafieldlist = $metafield->child_nodes();
00184 $md = array("label" => "", "entry" => "");
00185 foreach ($metafieldlist as $attr)
00186 {
00187 switch ($attr->node_name())
00188 {
00189 case "fieldlabel":
00190 $md["label"] = $attr->get_content();
00191 break;
00192 case "fieldentry":
00193 $md["entry"] = $attr->get_content();
00194 break;
00195 }
00196 }
00197 array_push($md_array, $md);
00198 break;
00199 }
00200 }
00201 break;
00202 }
00203 }
00204 foreach ($md_array as $md)
00205 {
00206 switch ($md["label"])
00207 {
00208 case "ILIAS_VERSION":
00209 break;
00210 case "QUESTIONTYPE":
00211 break;
00212 case "AUTHOR":
00213 $this->setAuthor($md["entry"]);
00214 break;
00215 }
00216 }
00217 break;
00218 case "duration":
00219 $iso8601period = $node->get_content();
00220 if (preg_match("/P(\d+)Y(\d+)M(\d+)DT(\d+)H(\d+)M(\d+)S/", $iso8601period, $matches))
00221 {
00222 $this->setEstimatedWorkingTime($matches[4], $matches[5], $matches[6]);
00223 }
00224 break;
00225 case "presentation":
00226 $flow = $node->first_child();
00227 $flownodes = $flow->child_nodes();
00228 foreach ($flownodes as $idx => $flownode)
00229 {
00230 if (strcmp($flownode->node_name(), "material") == 0)
00231 {
00232 $mattext = $flownode->first_child();
00233 $this->set_question($mattext->get_content());
00234 }
00235 elseif (strcmp($flownode->node_name(), "response_lid") == 0)
00236 {
00237 $ident = $flownode->get_attribute("ident");
00238 if (strcmp($ident, "OQT") == 0)
00239 {
00240 $this->set_ordering_type(OQ_TERMS);
00241 }
00242 elseif (strcmp($ident, "OQP") == 0)
00243 {
00244 $this->set_ordering_type(OQ_PICTURES);
00245 }
00246 $subnodes = $flownode->child_nodes();
00247 foreach ($subnodes as $node_type)
00248 {
00249 switch ($node_type->node_name())
00250 {
00251 case "material":
00252 $matlabel = $node_type->get_attribute("label");
00253 if (strcmp($matlabel, "suggested_solution") == 0)
00254 {
00255 $mattype = $node_type->first_child();
00256 if (strcmp($mattype->node_name(), "mattext") == 0)
00257 {
00258 $suggested_solution = $mattype->get_content();
00259 if ($suggested_solution)
00260 {
00261 if ($this->getId() < 1)
00262 {
00263 $this->saveToDb();
00264 }
00265 $this->setSuggestedSolution($suggested_solution, 0, true);
00266 }
00267 }
00268 }
00269 break;
00270 case "render_choice":
00271 $render_choice = $node_type;
00272 $shuffle = $render_choice->get_attribute("shuffle");
00273 $shuf = 0;
00274 if (strcmp(strtolower($shuffle), "yes") == 0)
00275 {
00276 $shuf = 1;
00277 }
00278 $this->setShuffle($shuf);
00279 $labels = $render_choice->child_nodes();
00280 foreach ($labels as $lidx => $response_label)
00281 {
00282 $material = $response_label->first_child();
00283 if ($this->get_ordering_type() == OQ_PICTURES)
00284 {
00285 $matimage = $material->first_child();
00286 $filename = $matimage->get_attribute("label");
00287 $image = base64_decode($matimage->get_content());
00288 $images["$filename"] = $image;
00289 $materials[$response_label->get_attribute("ident")] = $filename;
00290 }
00291 else
00292 {
00293 $mattext = $material->first_child();
00294 $materials[$response_label->get_attribute("ident")] = $mattext->get_content();
00295 }
00296 }
00297 }
00298 }
00299 }
00300 }
00301 break;
00302 case "resprocessing":
00303 $resproc_nodes = $node->child_nodes();
00304 foreach ($resproc_nodes as $index => $respcondition)
00305 {
00306 if (strcmp($respcondition->node_name(), "respcondition") == 0)
00307 {
00308 $respcondition_array =& ilQTIUtils::_getRespcondition($respcondition);
00309 $this->add_answer($materials[$respcondition_array["conditionvar"]["value"]], $respcondition_array["setvar"]["points"], count($this->answers), $respcondition_array["conditionvar"]["index"]);
00310 }
00311 }
00312 break;
00313 }
00314 }
00315 if (count($images))
00316 {
00317 $this->saveToDb();
00318 foreach ($images as $filename => $image)
00319 {
00320 if ($filename)
00321 {
00322 $imagepath = $this->getImagePath();
00323 if (!file_exists($imagepath))
00324 {
00325 ilUtil::makeDirParents($imagepath);
00326 }
00327 $imagepath .= $filename;
00328 $fh = fopen($imagepath, "wb");
00329 if ($fh == false)
00330 {
00331 global $ilErr;
00332 $ilErr->raiseError($this->lng->txt("error_save_image_file") . ": $php_errormsg", $ilErr->MESSAGE);
00333 return;
00334 }
00335 $imagefile = fwrite($fh, $image);
00336 fclose($fh);
00337
00338 $thumbpath = $imagepath . "." . "thumb.jpg";
00339 ilUtil::convertImage($imagepath, $thumbpath, "JPEG", 100);
00340 }
00341 }
00342 }
00343 $result = true;
00344 }
00345 return $result;
00346 }
00347
00357 function to_xml($a_include_header = true, $a_include_binary = true, $a_shuffle = false, $test_output = false)
00358 {
00359 if (!empty($this->domxml))
00360 {
00361 $this->domxml->free();
00362 }
00363 $xml_header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<questestinterop></questestinterop>\n";
00364 $this->domxml = domxml_open_mem($xml_header);
00365 $root = $this->domxml->document_element();
00366
00367 $qtiIdent = $this->domxml->create_element("item");
00368 $qtiIdent->set_attribute("ident", "il_".IL_INST_ID."_qst_".$this->getId());
00369 $qtiIdent->set_attribute("title", $this->getTitle());
00370 $root->append_child($qtiIdent);
00371
00372 $qtiComment = $this->domxml->create_element("qticomment");
00373 $qtiCommentText = $this->domxml->create_text_node($this->getComment());
00374 $qtiComment->append_child($qtiCommentText);
00375 $qtiIdent->append_child($qtiComment);
00376
00377 $qtiDuration = $this->domxml->create_element("duration");
00378 $workingtime = $this->getEstimatedWorkingTime();
00379 $qtiDurationText = $this->domxml->create_text_node(sprintf("P0Y0M0DT%dH%dM%dS", $workingtime["h"], $workingtime["m"], $workingtime["s"]));
00380 $qtiDuration->append_child($qtiDurationText);
00381 $qtiIdent->append_child($qtiDuration);
00382
00383 $qtiItemmetadata = $this->domxml->create_element("itemmetadata");
00384 $qtiMetadata = $this->domxml->create_element("qtimetadata");
00385
00386 $qtiMetadatafield = $this->domxml->create_element("qtimetadatafield");
00387 $qtiFieldlabel = $this->domxml->create_element("fieldlabel");
00388 $qtiFieldlabelText = $this->domxml->create_text_node("ILIAS_VERSION");
00389 $qtiFieldlabel->append_child($qtiFieldlabelText);
00390 $qtiFieldentry = $this->domxml->create_element("fieldentry");
00391 $qtiFieldentryText = $this->domxml->create_text_node($this->ilias->getSetting("ilias_version"));
00392 $qtiFieldentry->append_child($qtiFieldentryText);
00393 $qtiMetadatafield->append_child($qtiFieldlabel);
00394 $qtiMetadatafield->append_child($qtiFieldentry);
00395 $qtiMetadata->append_child($qtiMetadatafield);
00396
00397 $qtiMetadatafield = $this->domxml->create_element("qtimetadatafield");
00398 $qtiFieldlabel = $this->domxml->create_element("fieldlabel");
00399 $qtiFieldlabelText = $this->domxml->create_text_node("QUESTIONTYPE");
00400 $qtiFieldlabel->append_child($qtiFieldlabelText);
00401 $qtiFieldentry = $this->domxml->create_element("fieldentry");
00402 $qtiFieldentryText = $this->domxml->create_text_node(ORDERING_QUESTION_IDENTIFIER);
00403 $qtiFieldentry->append_child($qtiFieldentryText);
00404 $qtiMetadatafield->append_child($qtiFieldlabel);
00405 $qtiMetadatafield->append_child($qtiFieldentry);
00406 $qtiMetadata->append_child($qtiMetadatafield);
00407
00408 $qtiMetadatafield = $this->domxml->create_element("qtimetadatafield");
00409 $qtiFieldlabel = $this->domxml->create_element("fieldlabel");
00410 $qtiFieldlabelText = $this->domxml->create_text_node("AUTHOR");
00411 $qtiFieldlabel->append_child($qtiFieldlabelText);
00412 $qtiFieldentry = $this->domxml->create_element("fieldentry");
00413 $qtiFieldentryText = $this->domxml->create_text_node($this->getAuthor());
00414 $qtiFieldentry->append_child($qtiFieldentryText);
00415 $qtiMetadatafield->append_child($qtiFieldlabel);
00416 $qtiMetadatafield->append_child($qtiFieldentry);
00417 $qtiMetadata->append_child($qtiMetadatafield);
00418
00419 $qtiItemmetadata->append_child($qtiMetadata);
00420 $qtiIdent->append_child($qtiItemmetadata);
00421
00422
00423 $qtiPresentation = $this->domxml->create_element("presentation");
00424 $qtiPresentation->set_attribute("label", $this->getTitle());
00425
00426 $qtiFlow = $this->domxml->create_element("flow");
00427
00428 $qtiMaterial = $this->domxml->create_element("material");
00429 $qtiMatText = $this->domxml->create_element("mattext");
00430 $qtiMatTextText = $this->domxml->create_text_node($this->get_question());
00431 $qtiMatText->append_child($qtiMatTextText);
00432 $qtiMaterial->append_child($qtiMatText);
00433 $qtiFlow->append_child($qtiMaterial);
00434
00435 $qtiResponseLid = $this->domxml->create_element("response_lid");
00436 if ($this->get_ordering_type() == OQ_PICTURES)
00437 {
00438 $qtiResponseLid->set_attribute("ident", "OQP");
00439 $qtiResponseLid->set_attribute("rcardinality", "Ordered");
00440 if ($this->getOutputType() == OUTPUT_JAVASCRIPT)
00441 {
00442 $qtiResponseLid->set_attribute("output", "javascript");
00443 }
00444 }
00445 else
00446 {
00447 $qtiResponseLid->set_attribute("ident", "OQT");
00448 $qtiResponseLid->set_attribute("rcardinality", "Ordered");
00449 if ($this->getOutputType() == OUTPUT_JAVASCRIPT)
00450 {
00451 $qtiResponseLid->set_attribute("output", "javascript");
00452 }
00453 }
00454 $solution = $this->getSuggestedSolution(0);
00455 if (count($solution))
00456 {
00457 if (preg_match("/il_(\d*?)_(\w+)_(\d+)/", $solution["internal_link"], $matches))
00458 {
00459 $qtiMaterial = $this->domxml->create_element("material");
00460 $qtiMaterial->set_attribute("label", "suggested_solution");
00461 $qtiMatText = $this->domxml->create_element("mattext");
00462 $intlink = "il_" . IL_INST_ID . "_" . $matches[2] . "_" . $matches[3];
00463 if (strcmp($matches[1], "") != 0)
00464 {
00465 $intlink = $solution["internal_link"];
00466 }
00467 $qtiMatTextText = $this->domxml->create_text_node($intlink);
00468 $qtiMatText->append_child($qtiMatTextText);
00469 $qtiMaterial->append_child($qtiMatText);
00470 $qtiResponseLid->append_child($qtiMaterial);
00471 }
00472 }
00473 $qtiRenderChoice = $this->domxml->create_element("render_choice");
00474
00475 if ($this->getShuffle())
00476 {
00477 $qtiRenderChoice->set_attribute("shuffle", "Yes");
00478 }
00479 else
00480 {
00481 $qtiRenderChoice->set_attribute("shuffle", "No");
00482 }
00483
00484
00485 $akeys = array_keys($this->answers);
00486 if ($this->getshuffle() && $a_shuffle)
00487 {
00488 $akeys = $this->pcArrayShuffle($akeys);
00489 }
00490
00491
00492 foreach ($akeys as $index)
00493 {
00494 $answer = $this->answers[$index];
00495
00496 $qtiResponseLabel = $this->domxml->create_element("response_label");
00497 $qtiResponseLabel->set_attribute("ident", $index);
00498 $qtiMaterial = $this->domxml->create_element("material");
00499 if ($this->get_ordering_type() == OQ_PICTURES)
00500 {
00501 $qtiMatImage = $this->domxml->create_element("matimage");
00502 $imagetype = "image/jpeg";
00503 if (preg_match("/.*\.(png|gif)$/", $answer->get_answertext(), $matches))
00504 {
00505 $imagetype = "image/".$matches[1];
00506 }
00507 $qtiMatImage->set_attribute("imagtype", $imagetype);
00508 $qtiMatImage->set_attribute("label", $answer->get_answertext());
00509 if ($test_output)
00510 {
00511 $qtiMatImage->set_attribute("uri", $this->getImagePathWeb() . $answer->get_answertext());
00512 }
00513 else
00514 {
00515 $qtiMatImage->set_attribute("embedded", "base64");
00516 $imagepath = $this->getImagePath() . $answer->get_answertext();
00517 $fh = fopen($imagepath, "rb");
00518 if ($fh == false)
00519 {
00520
00521
00522
00523 }
00524 else
00525 {
00526 $imagefile = fread($fh, filesize($imagepath));
00527 fclose($fh);
00528 $base64 = base64_encode($imagefile);
00529 $qtiBase64Data = $this->domxml->create_text_node($base64);
00530 $qtiMatImage->append_child($qtiBase64Data);
00531 }
00532 }
00533 $qtiMaterial->append_child($qtiMatImage);
00534 }
00535 else
00536 {
00537 $qtiMatText = $this->domxml->create_element("mattext");
00538 $qtiMatTextText = $this->domxml->create_text_node($answer->get_answertext());
00539 $qtiMatText->append_child($qtiMatTextText);
00540 $qtiMaterial->append_child($qtiMatText);
00541 }
00542 $qtiResponseLabel->append_child($qtiMaterial);
00543 $qtiRenderChoice->append_child($qtiResponseLabel);
00544 }
00545 $qtiResponseLid->append_child($qtiRenderChoice);
00546 $qtiFlow->append_child($qtiResponseLid);
00547 $qtiPresentation->append_child($qtiFlow);
00548 $qtiIdent->append_child($qtiPresentation);
00549
00550
00551 $qtiResprocessing = $this->domxml->create_element("resprocessing");
00552 $qtiOutcomes = $this->domxml->create_element("outcomes");
00553 $qtiDecvar = $this->domxml->create_element("decvar");
00554 $qtiOutcomes->append_child($qtiDecvar);
00555 $qtiResprocessing->append_child($qtiOutcomes);
00556
00557 foreach ($this->answers as $index => $answer)
00558 {
00559 $qtiRespcondition = $this->domxml->create_element("respcondition");
00560 $qtiRespcondition->set_attribute("continue", "Yes");
00561
00562 $qtiConditionvar = $this->domxml->create_element("conditionvar");
00563 $qtiVarequal = $this->domxml->create_element("varequal");
00564 if ($this->get_ordering_type() == OQ_PICTURES)
00565 {
00566 $qtiVarequal->set_attribute("respident", "OQP");
00567 }
00568 else
00569 {
00570 $qtiVarequal->set_attribute("respident", "OQT");
00571 }
00572 $qtiVarequal->set_attribute("index", $answer->get_solution_order());
00573 $qtiVarequalText = $this->domxml->create_text_node($index);
00574 $qtiVarequal->append_child($qtiVarequalText);
00575 $qtiConditionvar->append_child($qtiVarequal);
00576
00577 $qtiSetvar = $this->domxml->create_element("setvar");
00578 $qtiSetvar->set_attribute("action", "Add");
00579 $qtiSetvarText = $this->domxml->create_text_node($answer->get_points());
00580 $qtiSetvar->append_child($qtiSetvarText);
00581
00582 $qtiDisplayfeedback = $this->domxml->create_element("displayfeedback");
00583 $qtiDisplayfeedback->set_attribute("feedbacktype", "Response");
00584 $qtiDisplayfeedback->set_attribute("linkrefid", "link_$index");
00585 $qtiRespcondition->append_child($qtiConditionvar);
00586 $qtiRespcondition->append_child($qtiSetvar);
00587 $qtiRespcondition->append_child($qtiDisplayfeedback);
00588 $qtiResprocessing->append_child($qtiRespcondition);
00589 }
00590 $qtiIdent->append_child($qtiResprocessing);
00591
00592
00593 foreach ($this->answers as $index => $answer)
00594 {
00595 $qtiItemfeedback = $this->domxml->create_element("itemfeedback");
00596 $qtiItemfeedback->set_attribute("ident", "link_$index");
00597 $qtiItemfeedback->set_attribute("view", "All");
00598
00599 $qtiFlowmat = $this->domxml->create_element("flow_mat");
00600 $qtiMaterial = $this->domxml->create_element("material");
00601 $qtiMattext = $this->domxml->create_element("mattext");
00602
00603 $qtiMattextText = $this->domxml->create_text_node("");
00604 $qtiMattext->append_child($qtiMattextText);
00605 $qtiMaterial->append_child($qtiMattext);
00606 $qtiFlowmat->append_child($qtiMaterial);
00607 $qtiItemfeedback->append_child($qtiFlowmat);
00608 $qtiIdent->append_child($qtiItemfeedback);
00609 }
00610
00611 $xml = $this->domxml->dump_mem(true);
00612 if (!$a_include_header)
00613 {
00614 $pos = strpos($xml, "?>");
00615 $xml = substr($xml, $pos + 2);
00616 }
00617
00618 return $xml;
00619
00620 }
00621
00622
00631 function saveToDb($original_id = "")
00632 {
00633 global $ilias;
00634
00635 $db =& $ilias->db;
00636 $complete = 0;
00637 if ($this->isComplete())
00638 {
00639 $complete = 1;
00640 }
00641
00642 $estw_time = $this->getEstimatedWorkingTime();
00643 $estw_time = sprintf("%02d:%02d:%02d", $estw_time['h'], $estw_time['m'], $estw_time['s']);
00644
00645 if ($original_id)
00646 {
00647 $original_id = $db->quote($original_id);
00648 }
00649 else
00650 {
00651 $original_id = "NULL";
00652 }
00653
00654 if ($this->id == -1)
00655 {
00656
00657 $now = getdate();
00658 $question_type = $this->getQuestionType();
00659 $created = sprintf("%04d%02d%02d%02d%02d%02d", $now['year'], $now['mon'], $now['mday'], $now['hours'], $now['minutes'], $now['seconds']);
00660 $query = sprintf("INSERT INTO qpl_questions (question_id, question_type_fi, obj_fi, title, comment, author, owner, question_text, working_time, ordering_type, points, complete, created, original_id, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NULL)",
00661 $db->quote($question_type . ""),
00662 $db->quote($this->obj_id . ""),
00663 $db->quote($this->title . ""),
00664 $db->quote($this->comment . ""),
00665 $db->quote($this->author . ""),
00666 $db->quote($this->owner . ""),
00667 $db->quote($this->question . ""),
00668 $db->quote($estw_time . ""),
00669 $db->quote($this->ordering_type . ""),
00670 $db->quote($this->getMaximumPoints() . ""),
00671 $db->quote($complete . ""),
00672 $db->quote($created . ""),
00673 $original_id
00674 );
00675 $result = $db->query($query);
00676 if ($result == DB_OK)
00677 {
00678 $this->id = $this->ilias->db->getLastInsertId();
00679
00680
00681 $this->createPageObject();
00682
00683
00684 if ($this->getTestId() > 0)
00685 {
00686 $this->insertIntoTest($this->getTestId());
00687 }
00688 }
00689 }
00690 else
00691 {
00692
00693 $query = sprintf("UPDATE qpl_questions SET obj_fi = %s, title = %s, comment = %s, author = %s, question_text = %s, working_time = %s, ordering_type = %s, points = %s, complete = %s WHERE question_id = %s",
00694 $db->quote($this->obj_id. ""),
00695 $db->quote($this->title . ""),
00696 $db->quote($this->comment . ""),
00697 $db->quote($this->author . ""),
00698 $db->quote($this->question . ""),
00699 $db->quote($estw_time . ""),
00700 $db->quote($this->ordering_type . ""),
00701 $db->quote($this->getMaximumPoints() . ""),
00702 $db->quote($complete . ""),
00703 $db->quote($this->id . "")
00704 );
00705 $result = $db->query($query);
00706 }
00707 if ($result == DB_OK)
00708 {
00709
00710
00711 $query = sprintf("DELETE FROM qpl_answers WHERE question_fi = %s",
00712 $db->quote($this->id)
00713 );
00714 $result = $db->query($query);
00715
00716
00717 foreach ($this->answers as $key => $value)
00718 {
00719 $answer_obj = $this->answers[$key];
00720 $query = sprintf("INSERT INTO qpl_answers (answer_id, question_fi, answertext, points, aorder, solution_order, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, NULL)",
00721 $db->quote($this->id),
00722 $db->quote($answer_obj->get_answertext() . ""),
00723 $db->quote($answer_obj->get_points() . ""),
00724 $db->quote($answer_obj->get_order() . ""),
00725 $db->quote($answer_obj->get_solution_order() . "")
00726 );
00727 $answer_result = $db->query($query);
00728 }
00729 }
00730 parent::saveToDb($original_id);
00731 }
00732
00742 function loadFromDb($question_id)
00743 {
00744 global $ilias;
00745 $db =& $ilias->db;
00746
00747 $query = sprintf("SELECT * FROM qpl_questions WHERE question_id = %s",
00748 $db->quote($question_id)
00749 );
00750 $result = $db->query($query);
00751 if (strcmp(strtolower(get_class($result)), db_result) == 0)
00752 {
00753 if ($result->numRows() == 1)
00754 {
00755 $data = $result->fetchRow(DB_FETCHMODE_OBJECT);
00756 $this->id = $question_id;
00757 $this->title = $data->title;
00758 $this->obj_id = $data->obj_fi;
00759 $this->comment = $data->comment;
00760 $this->original_id = $data->original_id;
00761 $this->author = $data->author;
00762 $this->owner = $data->owner;
00763 $this->question = $data->question_text;
00764 $this->solution_hint = $data->solution_hint;
00765 $this->ordering_type = $data->ordering_type;
00766 $this->points = $data->points;
00767 $this->setEstimatedWorkingTime(substr($data->working_time, 0, 2), substr($data->working_time, 3, 2), substr($data->working_time, 6, 2));
00768 }
00769
00770 $query = sprintf("SELECT * FROM qpl_answers WHERE question_fi = %s ORDER BY aorder ASC",
00771 $db->quote($question_id)
00772 );
00773 $result = $db->query($query);
00774 if (strcmp(strtolower(get_class($result)), db_result) == 0)
00775 {
00776 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT))
00777 {
00778 array_push($this->answers, new ASS_AnswerOrdering($data->answertext, $data->points, $data->aorder, $data->solution_order));
00779 }
00780 }
00781 }
00782 parent::loadFromDb($question_id);
00783 }
00784
00792 function addAnswer($answertext, $points, $answerorder, $solutionorder)
00793 {
00794 array_push($this->answers, new ASS_AnswerOrdering($answertext, $points, $answerorder, $solutionorder));
00795 }
00796
00804 function duplicate($for_test = true, $title = "", $author = "", $owner = "")
00805 {
00806 if ($this->id <= 0)
00807 {
00808
00809 return;
00810 }
00811
00812 $clone = $this;
00813 include_once ("./assessment/classes/class.assQuestion.php");
00814 $original_id = ASS_Question::_getOriginalId($this->id);
00815 $clone->id = -1;
00816 if ($title)
00817 {
00818 $clone->setTitle($title);
00819 }
00820 if ($author)
00821 {
00822 $clone->setAuthor($author);
00823 }
00824 if ($owner)
00825 {
00826 $clone->setOwner($owner);
00827 }
00828 if ($for_test)
00829 {
00830 $clone->saveToDb($original_id);
00831 }
00832 else
00833 {
00834 $clone->saveToDb();
00835 }
00836
00837
00838 $clone->copyPageOfQuestion($original_id);
00839
00840
00841 $clone->duplicateImages($original_id);
00842 return $clone->id;
00843 }
00844
00845 function duplicateImages($question_id)
00846 {
00847 if ($this->get_ordering_type() == OQ_PICTURES)
00848 {
00849 $imagepath = $this->getImagePath();
00850 $imagepath_original = str_replace("/$this->id/images", "/$question_id/images", $imagepath);
00851 if (!file_exists($imagepath)) {
00852 ilUtil::makeDirParents($imagepath);
00853 }
00854 foreach ($this->answers as $answer)
00855 {
00856 $filename = $answer->get_answertext();
00857 if (!copy($imagepath_original . $filename, $imagepath . $filename)) {
00858 print "image could not be duplicated!!!! ";
00859 }
00860 if (!copy($imagepath_original . $filename . ".thumb.jpg", $imagepath . $filename . ".thumb.jpg")) {
00861 print "image thumbnail could not be duplicated!!!! ";
00862 }
00863 }
00864 }
00865 }
00866
00876 function set_question($question = "")
00877 {
00878 $this->question = $question;
00879 }
00880
00890 function set_ordering_type($ordering_type = OQ_TERMS)
00891 {
00892 $this->ordering_type = $ordering_type;
00893 }
00894
00904 function get_question()
00905 {
00906 return $this->question;
00907 }
00908
00918 function get_ordering_type()
00919 {
00920 return $this->ordering_type;
00921 }
00922
00938 function add_answer(
00939 $answertext = "",
00940 $points = 0.0,
00941 $order = 0,
00942 $solution_order = 0
00943 )
00944 {
00945 $found = -1;
00946 foreach ($this->answers as $key => $value)
00947 {
00948 if ($value->get_order() == $order)
00949 {
00950 $found = $order;
00951 }
00952 }
00953 if ($found >= 0)
00954 {
00955
00956 $answer = new ASS_AnswerOrdering($answertext, $points, $found, $solution_order);
00957 array_push($this->answers, $answer);
00958 for ($i = $found + 1; $i < count($this->answers); $i++)
00959 {
00960 $this->answers[$i] = $this->answers[$i-1];
00961 }
00962 $this->answers[$found] = $answer;
00963 }
00964 else
00965 {
00966
00967 $answer = new ASS_AnswerOrdering($answertext, $points,
00968 count($this->answers), $solution_order);
00969 array_push($this->answers, $answer);
00970 }
00971 }
00972
00984 function get_answer($index = 0)
00985 {
00986 if ($index < 0) return NULL;
00987 if (count($this->answers) < 1) return NULL;
00988 if ($index >= count($this->answers)) return NULL;
00989 return $this->answers[$index];
00990 }
00991
01002 function delete_answer($index = 0)
01003 {
01004 if ($index < 0)
01005 {
01006 return;
01007 }
01008 if (count($this->answers) < 1)
01009 {
01010 return;
01011 }
01012 if ($index >= count($this->answers))
01013 {
01014 return;
01015 }
01016 unset($this->answers[$index]);
01017 $this->answers = array_values($this->answers);
01018 for ($i = 0; $i < count($this->answers); $i++)
01019 {
01020 if ($this->answers[$i]->get_order() > $index)
01021 {
01022 $this->answers[$i]->set_order($i);
01023 }
01024 }
01025 }
01026
01035 function flush_answers()
01036 {
01037 $this->answers = array();
01038 }
01039
01049 function get_answer_count()
01050 {
01051 return count($this->answers);
01052 }
01053
01062 function get_max_solution_order()
01063 {
01064 if (count($this->answers) == 0)
01065 {
01066 $max = 0;
01067 }
01068 else
01069 {
01070 $max = $this->answers[0]->get_solution_order();
01071 }
01072 foreach ($this->answers as $key => $value)
01073 {
01074 if ($value->get_solution_order() > $max)
01075 {
01076 $max = $value->get_solution_order();
01077 }
01078 }
01079 return $max;
01080 }
01081
01093 function calculateReachedPoints($user_id, $test_id)
01094 {
01095 global $ilDB;
01096
01097 $found_value1 = array();
01098 $found_value2 = array();
01099 $query = sprintf("SELECT * FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
01100 $ilDB->quote($user_id),
01101 $ilDB->quote($test_id),
01102 $ilDB->quote($this->getId())
01103 );
01104 $result = $ilDB->query($query);
01105 $user_order = array();
01106 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT))
01107 {
01108 if ((strcmp($data->value1, "") != 0) && (strcmp($data->value2, "") != 0))
01109 {
01110 $user_order[$data->value2] = $data->value1;
01111 }
01112 }
01113 ksort($user_order);
01114 $user_order = array_values($user_order);
01115 $answer_order = array();
01116 foreach ($this->answers as $key => $answer)
01117 {
01118 $answer_order[$answer->get_solution_order()] = $key;
01119 }
01120 ksort($answer_order);
01121 $answer_order = array_values($answer_order);
01122 $points = 0;
01123 foreach ($answer_order as $index => $answer_id)
01124 {
01125 if (strcmp($user_order[$index], "") != 0)
01126 {
01127 if ($answer_id == $user_order[$index])
01128 {
01129 $points += $this->answers[$answer_id]->get_points();
01130 }
01131 }
01132 }
01133
01134
01135 $query = sprintf("SELECT * FROM tst_tests WHERE test_id = %s",
01136 $ilDB->quote($test_id)
01137 );
01138 $result = $ilDB->query($query);
01139 if ($result->numRows() == 1)
01140 {
01141 $row = $result->fetchRow(DB_FETCHMODE_ASSOC);
01142 if ($row["count_system"] == 1)
01143 {
01144 if ($points != $this->getMaximumPoints())
01145 {
01146 $points = 0;
01147 }
01148 }
01149 }
01150 else
01151 {
01152 $points = 0;
01153 }
01154 return $points;
01155 }
01156
01166 function getReachedInformation($user_id, $test_id)
01167 {
01168 $found_value1 = array();
01169 $found_value2 = array();
01170 $query = sprintf("SELECT * FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
01171 $this->ilias->db->quote($user_id),
01172 $this->ilias->db->quote($test_id),
01173 $this->ilias->db->quote($this->getId())
01174 );
01175 $result = $this->ilias->db->query($query);
01176 $user_result = array();
01177 while ($data = $result->fetchRow(DB_FETCHMODE_OBJECT))
01178 {
01179 $solution = array(
01180 "answer_id" => $data->value1,
01181 "order" => $data->value2
01182 );
01183 $user_result[$data->value1] = $solution;
01184 }
01185 return $user_result;
01186 }
01187
01196 function getMaximumPoints()
01197 {
01198 $points = 0;
01199 foreach ($this->answers as $key => $value)
01200 {
01201 $points += $value->get_points();
01202 }
01203 return $points;
01204 }
01205
01216 function set_image_file($image_filename, $image_tempfilename = "")
01217 {
01218 $result = 0;
01219 if (!empty($image_tempfilename))
01220 {
01221 $image_filename = str_replace(" ", "_", $image_filename);
01222 $imagepath = $this->getImagePath();
01223 if (!file_exists($imagepath))
01224 {
01225 ilUtil::makeDirParents($imagepath);
01226 }
01227 if (!ilUtil::moveUploadedFile($image_tempfilename,$image_filename, $imagepath.$image_filename))
01228 {
01229 $result = 2;
01230 }
01231 else
01232 {
01233 require_once "./content/classes/Media/class.ilObjMediaObject.php";
01234 $mimetype = ilObjMediaObject::getMimeType($imagepath . $image_filename);
01235 if (!preg_match("/^image/", $mimetype))
01236 {
01237 unlink($imagepath . $image_filename);
01238 $result = 1;
01239 }
01240 else
01241 {
01242
01243 $thumbpath = $imagepath . $image_filename . "." . "thumb.jpg";
01244 ilUtil::convertImage($imagepath.$image_filename, $thumbpath, strtoupper($extension), 100);
01245 }
01246 }
01247 }
01248 return $result;
01249 }
01250
01260 function checkSaveData()
01261 {
01262 $result = true;
01263 $order_values = array();
01264 foreach ($_POST as $key => $value)
01265 {
01266 if (preg_match("/^order_(\d+)/", $key, $matches))
01267 {
01268 if (strcmp($value, "") != 0)
01269 {
01270 array_push($order_values, $value);
01271 }
01272 }
01273 }
01274 $check_order = array_flip($order_values);
01275 if (count($check_order) != count($order_values))
01276 {
01277
01278 $result = false;
01279 sendInfo($this->lng->txt("duplicate_order_values_entered"));
01280 }
01281 return $result;
01282 }
01283
01294 function saveWorkingData($test_id, $limit_to = LIMIT_NO_LIMIT)
01295 {
01296 global $ilDB;
01297 global $ilUser;
01298
01299 $saveWorkingDataResult = $this->checkSaveData();
01300 if ($saveWorkingDataResult)
01301 {
01302 $db =& $ilDB->db;
01303
01304 $query = sprintf("DELETE FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
01305 $db->quote($ilUser->id),
01306 $db->quote($test_id),
01307 $db->quote($this->getId())
01308 );
01309 $result = $db->query($query);
01310
01311 foreach ($_POST as $key => $value)
01312 {
01313 if (preg_match("/^order_(\d+)/", $key, $matches))
01314 {
01315 if (!(preg_match("/initial_value_\d+/", $value)))
01316 {
01317 $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)",
01318 $db->quote($ilUser->id),
01319 $db->quote($test_id),
01320 $db->quote($this->getId()),
01321 $db->quote($matches[1]),
01322 $db->quote($value)
01323 );
01324 $result = $db->query($query);
01325 }
01326 }
01327 }
01328 }
01329 parent::saveWorkingData($test_id);
01330 return $saveWorkingDataResult;
01331 }
01332
01333 function syncWithOriginal()
01334 {
01335 global $ilias;
01336 if ($this->original_id)
01337 {
01338 $complete = 0;
01339 if ($this->isComplete())
01340 {
01341 $complete = 1;
01342 }
01343 $db = & $ilias->db;
01344
01345 $estw_time = $this->getEstimatedWorkingTime();
01346 $estw_time = sprintf("%02d:%02d:%02d", $estw_time['h'], $estw_time['m'], $estw_time['s']);
01347
01348 $query = sprintf("UPDATE qpl_questions SET obj_fi = %s, title = %s, comment = %s, author = %s, question_text = %s, working_time = %s, ordering_type = %s, points = %s, complete = %s WHERE question_id = %s",
01349 $db->quote($this->obj_id. ""),
01350 $db->quote($this->title . ""),
01351 $db->quote($this->comment . ""),
01352 $db->quote($this->author . ""),
01353 $db->quote($this->question . ""),
01354 $db->quote($estw_time . ""),
01355 $db->quote($this->ordering_type . ""),
01356 $db->quote($this->getMaximumPoints() . ""),
01357 $db->quote($complete . ""),
01358 $db->quote($this->original_id . "")
01359 );
01360 $result = $db->query($query);
01361
01362 if ($result == DB_OK)
01363 {
01364
01365
01366 $query = sprintf("DELETE FROM qpl_answers WHERE question_fi = %s",
01367 $db->quote($this->original_id)
01368 );
01369 $result = $db->query($query);
01370
01371 foreach ($this->answers as $key => $value)
01372 {
01373 $answer_obj = $this->answers[$key];
01374 $query = sprintf("INSERT INTO qpl_answers (answer_id, question_fi, answertext, points, aorder, solution_order, TIMESTAMP) VALUES (NULL, %s, %s, %s, %s, %s, NULL)",
01375 $db->quote($this->original_id . ""),
01376 $db->quote($answer_obj->get_answertext() . ""),
01377 $db->quote($answer_obj->get_points() . ""),
01378 $db->quote($answer_obj->get_order() . ""),
01379 $db->quote($answer_obj->get_solution_order() . "")
01380 );
01381 $answer_result = $db->query($query);
01382 }
01383 }
01384 parent::syncWithOriginal();
01385 }
01386 }
01387
01388 function pc_array_shuffle($array) {
01389 mt_srand((double)microtime()*1000000);
01390 $i = count($array);
01391 while(--$i)
01392 {
01393 $j = mt_rand(0, $i);
01394 if ($i != $j)
01395 {
01396
01397 $tmp = $array[$j];
01398 $array[$j] = $array[$i];
01399 $array[$i] = $tmp;
01400 }
01401 }
01402 return $array;
01403 }
01404
01405 function createRandomSolution($test_id, $user_id)
01406 {
01407 global $ilDB;
01408 global $ilUser;
01409
01410 $db =& $ilDB->db;
01411
01412 $query = sprintf("DELETE FROM tst_solutions WHERE user_fi = %s AND test_fi = %s AND question_fi = %s",
01413 $db->quote($user_id),
01414 $db->quote($test_id),
01415 $db->quote($this->getId())
01416 );
01417 $result = $db->query($query);
01418
01419 $orders = range(1, count($this->answers));
01420 $orders = $this->pc_array_shuffle($orders);
01421 foreach ($this->answers as $key => $value)
01422 {
01423 $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)",
01424 $db->quote($user_id),
01425 $db->quote($test_id),
01426 $db->quote($this->getId()),
01427 $db->quote($key),
01428 $db->quote(array_pop($orders))
01429 );
01430 $result = $db->query($query);
01431 }
01432 }
01433
01442 function getQuestionType()
01443 {
01444 return 5;
01445 }
01446 }
01447
01448 ?>