public function fromXML(SimpleXMLElement $xml)
 {
     $data = array("itemtype" => $this->itemType(), "title" => (string) $xml["title"], "stimulus" => qti_get_stimulus($xml->itemBody));
     // check for a div with the item class name
     $itembodycontainer = null;
     foreach ($xml->itemBody->div as $div) {
         if (!isset($div["class"]) || (string) $div["class"] != "eqiat-mcr") {
             continue;
         }
         // get elements from here
         $itembodycontainer = $div;
         break;
     }
     // if there was none, get elements from itemBody
     if (is_null($itembodycontainer)) {
         $itembodycontainer = $xml->itemBody;
     }
     // there is one choiceInteraction
     if (count($itembodycontainer->choiceInteraction) != 1) {
         return 0;
     }
     // there is one responseDeclaration
     if (count($xml->responseDeclaration) != 1) {
         return 0;
     }
     // check cardinality is as expected
     if ($this->itemType() == "multipleResponse" && (string) $xml->responseDeclaration["cardinality"] != "multiple") {
         return 0;
     }
     if ($this->itemType() == "multipleChoice" && (string) $xml->responseDeclaration["cardinality"] != "single") {
         return 0;
     }
     // multiple choice must have maxchoices 1 and one correct response value
     if ($this->itemType() == "multipleChoice") {
         if (!isset($itembodycontainer->choiceInteraction["maxChoices"]) || (string) $itembodycontainer->choiceInteraction["maxChoices"] != "1") {
             return 0;
         }
         if (!isset($xml->responseDeclaration->correctResponse)) {
             return 0;
         }
         if (count($xml->responseDeclaration->correctResponse->value) != 1) {
             return 0;
         }
     }
     // get shuffle value
     $shuffle = isset($itembodycontainer->choiceInteraction["shuffle"]) && (string) $itembodycontainer->choiceInteraction["shuffle"] == "true";
     if ($shuffle) {
         $data["shuffle"] = "on";
     }
     // there is at least one option
     if (count($itembodycontainer->choiceInteraction->simpleChoice) == 0) {
         return 0;
     }
     // collect options and their identifiers
     $o = 0;
     $options = array();
     foreach ($itembodycontainer->choiceInteraction->simpleChoice as $sc) {
         $options[] = (string) $sc["identifier"];
         $data["option_{$o}_optiontext"] = (string) $sc;
         if ($shuffle && isset($sc["fixed"]) && (string) $sc["fixed"] == "true") {
             $data["option_{$o}_fixed"] = "on";
         }
         $o++;
     }
     // check correct response makes sense; collect correct responses
     $correct = array();
     if (count($xml->responseDeclaration->correctResponse) > 0) {
         foreach ($xml->responseDeclaration->correctResponse->value as $value) {
             $pos = array_search((string) $value, $options);
             if ($pos === false) {
                 return 0;
             }
             $correct[] = $pos;
         }
     }
     if ($this->itemType() == "multipleChoice") {
         $data["correct"] = "option_" . $correct[0];
     } else {
         foreach ($correct as $o) {
             $data["option_{$o}_correct"] = "on";
         }
     }
     // get max and min choices
     if ($this->itemType() == "multipleResponse") {
         $data["maxchoices"] = isset($itembodycontainer->choiceInteraction["maxChoices"]) ? (string) $itembodycontainer->choiceInteraction["maxChoices"] : "0";
         $data["minchoices"] = isset($itembodycontainer->choiceInteraction["minChoices"]) ? (string) $itembodycontainer->choiceInteraction["minChoices"] : "0";
     }
     // get prompt
     $data["prompt"] = (string) $itembodycontainer->choiceInteraction->prompt;
     // not checking this properly at all but if modalFeedback elements exist
     // which look about right, use them for feedback
     foreach ($xml->modalFeedback as $mf) {
         $id = explode("_", (string) $mf["identifier"]);
         if (count($id) == 3 && $id[2] < count($options) && (string) $mf["outcomeIdentifier"] == "FEEDBACK") {
             $data["feedback"] = true;
             if ((string) $mf["showHide"] == "show") {
                 $data["option_{$id[2]}_feedback_chosen"] = xml_remove_wrapper_element($mf->asXML());
             } else {
                 $data["option_{$id[2]}_feedback_unchosen"] = xml_remove_wrapper_element($mf->asXML());
             }
         }
     }
     // get min score
     foreach ($xml->responseProcessing->responseCondition as $rc) {
         if (count($rc->responseIf) != 1) {
             continue;
         }
         if (count($rc->responseIf->lt) != 1) {
             continue;
         }
         $ltchildren = $rc->responseIf->lt->children();
         if ($ltchildren[0]->getName() != "variable" || (string) $ltchildren[0]["identifier"] != "SCORE") {
             continue;
         }
         if ($ltchildren[1]->getName() != "baseValue") {
             continue;
         }
         $val = (string) $ltchildren[1];
         if (count($rc->responseIf->setOutcomeValue) != 1) {
             continue;
         }
         if ((string) $rc->responseIf->setOutcomeValue["identifier"] != "SCORE") {
             continue;
         }
         if (count($rc->responseIf->setOutcomeValue->baseValue) != 1) {
             continue;
         }
         if ((string) $rc->responseIf->setOutcomeValue->baseValue != $val) {
             continue;
         }
         $data["minscore"] = $val;
     }
     // get max score
     foreach ($xml->responseProcessing->responseCondition as $rc) {
         if (count($rc->responseIf) != 1) {
             continue;
         }
         if (count($rc->responseIf->gt) != 1) {
             continue;
         }
         $gtchildren = $rc->responseIf->gt->children();
         if ($gtchildren[0]->getName() != "variable" || (string) $gtchildren[0]["identifier"] != "SCORE") {
             continue;
         }
         if ($gtchildren[1]->getName() != "baseValue") {
             continue;
         }
         $val = (string) $gtchildren[1];
         if (count($rc->responseIf->setOutcomeValue) != 1) {
             continue;
         }
         if ((string) $rc->responseIf->setOutcomeValue["identifier"] != "SCORE") {
             continue;
         }
         if (count($rc->responseIf->setOutcomeValue->baseValue) != 1) {
             continue;
         }
         if ((string) $rc->responseIf->setOutcomeValue->baseValue != $val) {
             continue;
         }
         $data["maxscore"] = $val;
     }
     // check response conditions for incrementing score if a particular
     // response is given
     $data["scoring"] = "exact";
     foreach ($xml->responseProcessing->responseCondition as $rc) {
         if (count($rc->responseIf) != 1) {
             continue;
         }
         if (count($rc->responseIf->member) != 1) {
             continue;
         }
         $mchildren = $rc->responseIf->member->children();
         if ($mchildren[0]->getName() != "baseValue" || (string) $mchildren[0]["baseType"] != "identifier") {
             continue;
         }
         $oid = (string) $mchildren[0];
         if ($mchildren[1]->getName() != "variable" || (string) $mchildren[1]["identifier"] != "RESPONSE") {
             continue;
         }
         if (count($rc->responseIf->setOutcomeValue) != 1) {
             continue;
         }
         if ((string) $rc->responseIf->setOutcomeValue["identifier"] != "SCORE") {
             continue;
         }
         if (count($rc->responseIf->setOutcomeValue->sum) != 1) {
             continue;
         }
         if (count($rc->responseIf->setOutcomeValue->sum->children()) != 2) {
             continue;
         }
         if (count($rc->responseIf->setOutcomeValue->sum->variable) != 1 || (string) $rc->responseIf->setOutcomeValue->sum->variable["identifier"] != "SCORE") {
             continue;
         }
         if (count($rc->responseIf->setOutcomeValue->sum->baseValue) != 1) {
             continue;
         }
         $val = (string) $rc->responseIf->setOutcomeValue->sum->baseValue;
         $pos = array_search((string) $oid, $options);
         if ($pos === false) {
             continue;
         }
         $data["option_{$pos}_score"] = $val;
         $data["scoring"] = "cumulative";
     }
     // see if it is in fact cumulative
     if ($data["scoring"] == "cumulative" && (!isset($data["minscore"]) || $data["minscore"] != 0 || isset($data["maxscore"]))) {
         $data["scoring"] = "custom";
     }
     if ($data["scoring"] == "cumulative") {
         foreach ($options as $o => $option) {
             if (!isset($data["option_{$o}_score"]) || $data["option_{$o}_score"] != 1 && $data["option_{$o}_score"] != -1) {
                 $data["scoring"] = "custom";
                 break;
             }
         }
     }
     // happy with that -- set data property and identifier
     $this->data = $data;
     $this->setQTIID((string) $xml["identifier"]);
     // multiple response with one correct answer is less than ideal
     if ($this->itemType() == "multipleresponse" && count($options) == 1) {
         return 192;
     }
     return 255;
 }
Example #2
0
function qti_get_stimulus(SimpleXMLElement $ib)
{
    $stimulus = simplexml_load_string('<stimulus xmlns="http://www.imsglobal.org/xsd/imsqti_v2p1"/>', null);
    foreach ($ib->children() as $child) {
        if (containsQTIInteraction($child)) {
            continue;
        }
        // doesn't contain a QTI interaction so it counts as stimulus
        simplexml_append($stimulus, $child);
    }
    return xml_remove_wrapper_element($stimulus->asXML());
}