protected function unmarshallChildrenKnown(DOMElement $element, QtiComponentCollection $children)
 {
     if (($identifier = self::getDOMElementAttributeAs($element, 'identifier')) !== null) {
         $fqClass = $this->lookupClass($element);
         try {
             $component = new $fqClass($identifier);
         } catch (InvalidArgumentException $e) {
             $msg = "'{$identifier}' is not a valid identifier for an 'inlineChoice' element.";
             throw new UnmarshallingException($msg, $element, $e);
         }
         try {
             $component->setContent(new TextOrVariableCollection($children->getArrayCopy()));
         } catch (InvalidArgumentException $e) {
             $msg = "'inlineChoice' elements must only contain text or 'printedVariable' elements.";
             throw new UnmarshallingException($msg, $element, $e);
         }
         if (($fixed = self::getDOMElementAttributeAs($element, 'fixed', 'boolean')) !== null) {
             $component->setFixed($fixed);
         }
         if (($templateIdentifier = self::getDOMElementAttributeAs($element, 'templateIdentifier')) !== null) {
             $component->setTemplateIdentifier($templateIdentifier);
         }
         if (($showHide = self::getDOMElementAttributeAs($element, 'showHide')) !== null) {
             $component->setShowHide(ShowHide::getConstantByName($showHide));
         }
         self::fillBodyElement($component, $element);
         return $component;
     } else {
         $msg = "The mandatory 'identifier' attribute is missing from the 'simpleChoice' element.";
         throw new UnmarshallingException($msg, $element);
     }
 }
 protected function buildComponentCollectionWithNonMergeableInteractionTypes()
 {
     $collection = new QtiComponentCollection();
     $choiceInteraction = ChoiceInteractionBuilder::buildSimple('testChoiceInteractionIdentifier', ['ChoiceOne' => 'A', 'ChoiceTwo' => 'B']);
     $collection->attach($choiceInteraction);
     return $collection;
 }
Exemple #3
0
 /**
  * @see \qtism\data\storage\xml\marshalling\RecursiveMarshaller::unmarshallChildrenKnown()
  */
 protected function unmarshallChildrenKnown(DOMElement $element, QtiComponentCollection $children)
 {
     // At item authoring time, we could admit that an empty data attribute
     // may occur.
     if (($data = self::getDOMElementAttributeAs($element, 'data')) === null) {
         $data = '';
     }
     if (($type = self::getDOMElementAttributeAs($element, 'type')) !== null) {
         $fqClass = $this->lookupClass($element);
         $component = new $fqClass($data, $type);
         $component->setContent(new ObjectFlowCollection($children->getArrayCopy()));
         if (($width = self::getDOMElementAttributeAs($element, 'width', 'integer')) !== null) {
             $component->setWidth($width);
         }
         if (($height = self::getDOMElementAttributeAs($element, 'height', 'integer')) !== null) {
             $component->setHeight($height);
         }
         if (($xmlBase = self::getXmlBase($element)) !== false) {
             $component->setXmlBase($xmlBase);
         }
         $this->fillBodyElement($component, $element);
         return $component;
     } else {
         $msg = "The mandatory attribute 'type' is missign from the 'object' element.";
         throw new UnmarshallingException($msg, $element);
     }
 }
 /**
  * @see \qtism\data\storage\xml\marshalling\RecursiveMarshaller::unmarshallChildrenKnown()
  */
 protected function unmarshallChildrenKnown(DOMElement $element, QtiComponentCollection $children)
 {
     if (($identifier = self::getDOMElementAttributeAs($element, 'identifier')) !== null) {
         $fqClass = $this->lookupClass($element);
         $component = new $fqClass($identifier);
         if (($fixed = self::getDOMElementAttributeAs($element, 'fixed', 'boolean')) !== null) {
             $component->setFixed($fixed);
         }
         if (($templateIdentifier = self::getDOMElementAttributeAs($element, 'templateIdentifier')) !== null) {
             $component->setTemplateIdentifier($templateIdentifier);
         }
         if (($showHide = self::getDOMElementAttributeAs($element, 'showHide')) !== null) {
             $component->setShowHide(ShowHide::getConstantByName($showHide));
         }
         if (($xmlBase = self::getXmlBase($element)) !== false) {
             $component->setXmlBase($xmlBase);
         }
         $component->setContent(new InlineStaticCollection($children->getArrayCopy()));
         $this->fillBodyElement($component, $element);
         return $component;
     } else {
         $msg = "The mandatory 'identifier' attribute is missing from the 'hottext' element.";
         throw new UnmarshallingException($msg, $element);
     }
 }
 protected function unmarshallChildrenKnown(DOMElement $element, QtiComponentCollection $children)
 {
     if (($responseIdentifier = self::getDOMElementAttributeAs($element, 'responseIdentifier')) !== null) {
         $fqClass = $this->lookupClass($element);
         $component = new $fqClass($responseIdentifier, new SimpleAssociableChoiceCollection($children->getArrayCopy()));
         if (($shuffle = self::getDOMElementAttributeAs($element, 'shuffle', 'boolean')) !== null) {
             $component->setShuffle($shuffle);
         }
         if (($maxAssociations = self::getDOMElementAttributeAs($element, 'maxAssociations', 'integer')) !== null) {
             $component->setMaxAssociations($maxAssociations);
         }
         if (($minAssociations = self::getDOMElementAttributeAs($element, 'minAssociations', 'integer')) !== null) {
             $component->setMinAssociations($minAssociations);
         }
         if (($xmlBase = self::getXmlBase($element)) !== false) {
             $component->setXmlBase($xmlBase);
         }
         $promptElts = self::getChildElementsByTagName($element, 'prompt');
         if (count($promptElts) > 0) {
             $promptElt = $promptElts[0];
             $prompt = $this->getMarshallerFactory()->createMarshaller($promptElt)->unmarshall($promptElt);
             $component->setPrompt($prompt);
         }
         self::fillBodyElement($component, $element);
         return $component;
     } else {
         $msg = "The mandatory 'responseIdentifier' attribute is missing from the 'associateInteraction' element.";
         throw new UnmarshallingException($msg, $element);
     }
 }
 protected function buildResponseDeclaration()
 {
     $responseDeclartation = ResponseDeclarationBuilder::buildWithCorrectResponse('testChoiceInteractionIdentifier', ['1', '2']);
     $collection = new QtiComponentCollection();
     $collection->attach($responseDeclartation);
     return $collection;
 }
 /**
  * @see \qtism\data\storage\xml\marshalling\RecursiveMarshaller::unmarshallChildrenKnown()
  */
 protected function unmarshallChildrenKnown(DOMElement $element, QtiComponentCollection $children)
 {
     if (($responseIdentifier = self::getDOMElementAttributeAs($element, 'responseIdentifier')) !== null) {
         $version = $this->getVersion();
         $fqClass = $this->lookupClass($element);
         $choices = new InlineChoiceCollection($children->getArrayCopy());
         if (count($choices) === 0) {
             $msg = "An 'inlineChoiceInteraction' element must contain at least 1 'inlineChoice' elements, none given.";
             throw new UnmarshallingException($message, $element);
         }
         try {
             $component = new $fqClass($responseIdentifier, $choices);
         } catch (InvalidArgumentException $e) {
             $msg = "The value of the attribute 'responseIdentifier' for element 'inlineChoiceInteraction' is not a valid identifier.";
             throw new UnmarshallingException($msg, $element, $e);
         }
         if (($shuffle = self::getDOMElementAttributeAs($element, 'shuffle', 'boolean')) !== null) {
             $component->setShuffle($shuffle);
         } elseif (Version::compare($version, '2.1.0', '<') === true) {
             $msg = "The mandatory 'shuffle' attribute is missing from the 'inlineChoiceInteraction' element.";
             throw new UnmarshallingException($msg, $element);
         }
         if (Version::compare($version, '2.1.0', '>=') === true && ($required = self::getDOMElementAttributeAs($element, 'required', 'boolean')) !== null) {
             $component->setRequired($required);
         }
         if (($xmlBase = self::getXmlBase($element)) !== false) {
             $component->setXmlBase($xmlBase);
         }
         $this->fillBodyElement($component, $element);
         return $component;
     } else {
         $msg = "The mandatory 'responseIdentifier' attribute is missing from the 'inlineChoiceInteraction' element.";
         throw new UnmarshallingException($msg, $element);
     }
 }
 /**
  * @see \qtism\data\storage\xml\marshalling\RecursiveMarshaller::unmarshallChildrenKnown()
  */
 protected function unmarshallChildrenKnown(DOMElement $element, QtiComponentCollection $children)
 {
     $fqClass = $this->lookupClass($element);
     if ($element->localName === 'a') {
         if (($href = self::getDOMElementAttributeAs($element, 'href')) !== null) {
             $component = new $fqClass($href);
             if (($xmlBase = self::getXmlBase($element)) !== false) {
                 $component->setXmlBase($xmlBase);
             }
             if (($type = self::getDOMElementAttributeAs($element, 'type')) !== null) {
                 $component->setType($type);
             }
         } else {
             $msg = "The mandatory 'href' attribute of the 'a' element is missing.";
             throw new UnmarshallingException($msg, $element);
         }
     } else {
         $component = new $fqClass();
     }
     $component->setContent(new InlineCollection($children->getArrayCopy()));
     $this->fillBodyElement($component, $element);
     // The q class has a specific cite (URI) attribute.
     if ($component instanceof Q && ($cite = self::getDOMElementAttributeAs($element, 'cite')) !== null) {
         try {
             $component->setCite($cite);
         } catch (InvalidArgumentException $e) {
             $msg = "The 'cite' attribute of a 'q' element must be a valid URI, '" . $cite . "' given.";
             throw new UnmarshallingException($msg, $element, $e);
         }
     }
     return $component;
 }
 protected function unmarshallChildrenKnown(DOMElement $element, QtiComponentCollection $children)
 {
     if (($identifier = self::getDOMElementAttributeAs($element, 'identifier')) !== null) {
         if (($matchMax = self::getDOMElementAttributeAs($element, 'matchMax', 'integer')) !== null) {
             $fqClass = $this->lookupClass($element);
             $component = new $fqClass($identifier, $matchMax);
             if (($fixed = self::getDOMElementAttributeAs($element, 'fixed', 'boolean')) !== null) {
                 $component->setFixed($fixed);
             }
             if (($templateIdentifier = self::getDOMElementAttributeAs($element, 'templateIdentifier')) !== null) {
                 $component->setTemplateIdentifier($templateIdentifier);
             }
             if (($showHide = self::getDOMElementAttributeAs($element, 'showHide')) !== null) {
                 $component->setShowHide(ShowHide::getConstantByName($showHide));
             }
             if (($matchMin = self::getDOMElementAttributeAs($element, 'matchMin', 'integer')) !== null) {
                 $component->setMatchMin($matchMin);
             }
             $component->setContent(new FlowStaticCollection($children->getArrayCopy()));
             self::fillBodyElement($component, $element);
             return $component;
         } else {
             $msg = "The mandatory 'matchMax' attribute is missing from the 'simpleAssociableChoice' element.";
             throw new UnmarshallingException($msg, $element);
         }
     } else {
         $msg = "The mandatory 'identifier' attribute is missing from the 'simpleAssociableChoice' element.";
         throw new UnmarshallingException($msg, $element);
     }
 }
 public static function unmarshallElement($string)
 {
     try {
         libxml_use_internal_errors(true);
         $dom = new DOMDocument('1.0', 'UTF-8');
         $dom->formatOutput = true;
         // TODO: Try to clean as much as I can blah
         $string = html_entity_decode($string, ENT_XHTML);
         // TODO: Can only unmarshall nice stuff, doesnt work with dodgy or invalid HTML
         if (!$dom->loadXML("<body>{$string}</body>", LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD)) {
             $errors = libxml_get_errors();
             throw new \Exception('Something wrong with XML format');
         }
         $marshallerFactory = new LearnosityMarshallerFactory();
         $components = new QtiComponentCollection();
         foreach ($dom->documentElement->childNodes as $element) {
             if ($element instanceof \DOMText) {
                 $component = new TextRun($element->nodeValue);
             } else {
                 $marshaller = $marshallerFactory->createMarshaller($element);
                 $component = $marshaller->unmarshall($element);
             }
             $components->attach($component);
         }
         return $components;
     } catch (\Exception $e) {
         throw new MappingException('[Unable to transform to QTI] ' . $e->getMessage());
     }
 }
 protected function unmarshallChildrenKnown(DOMElement $element, QtiComponentCollection $children)
 {
     if (($responseIdentifier = self::getDOMElementAttributeAs($element, 'responseIdentifier')) !== null) {
         $gapChoiceElts = self::getChildElementsByTagName($element, array('gapText', 'gapImg'));
         if (count($gapChoiceElts) > 0) {
             $gapChoices = new GapChoiceCollection();
             foreach ($gapChoiceElts as $g) {
                 $gapChoices[] = $this->getMarshallerFactory()->createMarshaller($g)->unmarshall($g);
             }
             $fqClass = $this->lookupClass($element);
             $component = new $fqClass($responseIdentifier, $gapChoices, new BlockStaticCollection($children->getArrayCopy()));
             $promptElts = self::getChildElementsByTagName($element, 'prompt');
             if (count($promptElts) === 1) {
                 $component->setPrompt($this->getMarshallerFactory()->createMarshaller($promptElts[0])->unmarshall($promptElts[0]));
             }
             if (($shuffle = self::getDOMElementAttributeAs($element, 'shuffle', 'boolean')) !== null) {
                 $component->setShuffle($shuffle);
             }
             if (($xmlBase = self::getXmlBase($element)) !== false) {
                 $component->setXmlBase($xmlBase);
             }
             self::fillBodyElement($component, $element);
             return $component;
         } else {
             $msg = "A 'gapMatchInteraction' element must contain at least 1 'gapChoice' element, none given.";
             throw new UnmarshallingException($msg, $element);
         }
     } else {
         $msg = "The mandatory 'responseIdentifier' attribute is missing from the 'gapMatchInteraction' element.";
         throw new UnmarshallingException($msg, $element);
     }
 }
Exemple #12
0
 /**
  * @see \qtism\data\storage\xml\marshalling\RecursiveMarshaller::unmarshallChildrenKnown()
  */
 protected function unmarshallChildrenKnown(DOMElement $element, QtiComponentCollection $children)
 {
     $fqClass = $this->lookupClass($element);
     $component = new $fqClass();
     $component->setContent(new FlowCollection($children->getArrayCopy()));
     $this->fillBodyElement($component, $element);
     return $component;
 }
 private function getUniqueInteractionTypes(QtiComponentCollection $interactionComponents)
 {
     // Decide whether we shall merge interaction
     $interactionTypes = array_unique(array_map(function ($component) {
         /* @var $component Interaction */
         return $component->getQtiClassName();
     }, $interactionComponents->getArrayCopy()));
     return $interactionTypes;
 }
 protected function unmarshallChildrenKnown(DOMElement $element, QtiComponentCollection $children)
 {
     $fqClass = $this->lookupClass($element);
     $component = new $fqClass();
     $childrenArray = $children->getArrayCopy();
     $component->setContent($component instanceof Dt ? new InlineCollection($childrenArray) : new FlowCollection($childrenArray));
     self::fillBodyElement($component, $element);
     return $component;
 }
 /**
  * @see \qtism\data\storage\xml\marshalling\RecursiveMarshaller::unmarshallChildrenKnown()
  */
 protected function unmarshallChildrenKnown(DOMElement $element, QtiComponentCollection $children)
 {
     $version = $this->getVersion();
     if (($responseIdentifier = self::getDOMElementAttributeAs($element, 'responseIdentifier')) !== null) {
         $objectElts = self::getChildElementsByTagName($element, 'object');
         if (count($objectElts) > 0) {
             $object = $this->getMarshallerFactory()->createMarshaller($objectElts[0])->unmarshall($objectElts[0]);
             try {
                 $choices = new HotspotChoiceCollection($children->getArrayCopy());
             } catch (InvalidArgumentException $e) {
                 $msg = "A 'graphicOrderInteraction' element can only contain 'hotspotChoice' choices.";
                 throw new UnmarshallingException($msg, $element, $e);
             }
             if (count($choices) > 0) {
                 $fqClass = $this->lookupClass($element);
                 $component = new $fqClass($responseIdentifier, $object, $choices);
                 if (Version::compare($version, '2.1.0', '>=') === true) {
                     if (($minChoices = self::getDOMElementAttributeAs($element, 'minChoices', 'integer')) !== null) {
                         // graphicOrderInteraction->minChoices = 0 is an endless debate:
                         // The Information models says: If specfied, minChoices must be 1 or greater but ...
                         // The XSD 2.1 says: xs:integer, [-inf, +inf], optional
                         // The XSD 2.1.1 says: xs:nonNegativeInteger, [0, +inf]
                         //
                         // --> Let's say that if <= 0, we consider it not specfied!
                         if ($minChoices > 0) {
                             $component->setMinChoices($minChoices);
                         }
                     }
                     if (($maxChoices = self::getDOMElementAttributeAs($element, 'maxChoices', 'integer')) !== null) {
                         $component->setMaxChoices($maxChoices);
                     }
                 }
                 if (($xmlBase = self::getXmlBase($element)) !== false) {
                     $component->setXmlBase($xmlBase);
                 }
                 $promptElts = self::getChildElementsByTagName($element, 'prompt');
                 if (count($promptElts) > 0) {
                     $promptElt = $promptElts[0];
                     $prompt = $this->getMarshallerFactory()->createMarshaller($promptElt)->unmarshall($promptElt);
                     $component->setPrompt($prompt);
                 }
                 $this->fillBodyElement($component, $element);
                 return $component;
             } else {
                 $msg = "A 'graphicOrderInteraction' must contain at least one 'hotspotChoice' element, none given.";
                 throw new UnmarshallingException($msg, $element);
             }
         } else {
             $msg = "A 'graphicOrderInteraction' element must contain exactly one 'object' element, none given.";
             throw new UnmarshallingException($msg, $element);
         }
     } else {
         $msg = "The mandatory 'responseIdentifier' attribute is missing from the 'graphicOrderInteraction' element.";
         throw new UnmarshallingException($msg, $element);
     }
 }
 protected function unmarshallChildrenKnown(DOMElement $element, QtiComponentCollection $children)
 {
     if (($responseIdentifier = self::getDOMElementAttributeAs($element, 'responseIdentifier')) !== null) {
         $fqClass = $this->lookupClass($element);
         $component = new $fqClass($responseIdentifier, new SimpleChoiceCollection($children->getArrayCopy()));
         if (($shuffle = self::getDOMElementAttributeAs($element, 'shuffle', 'boolean')) !== null) {
             $component->setShuffle($shuffle);
         }
         if (($maxChoices = self::getDOMElementAttributeAs($element, 'maxChoices', 'integer')) !== null) {
             if ($element->localName === 'orderInteraction') {
                 if ($maxChoices !== 0) {
                     $component->setMaxChoices($maxChoices);
                 }
             } else {
                 $component->setMaxChoices($maxChoices);
             }
         }
         if (($minChoices = self::getDOMElementAttributeAs($element, 'minChoices', 'integer')) !== null) {
             if ($element->localName === 'orderInteraction') {
                 /*
                  * Lots of QTI implementations output minChoices = 0 while
                  * dealing with orderInteraction unmarshalling. However, regarding
                  * the IMS QTI Specification, it is invalid.
                  * 
                  * "If specified, minChoices must be 1 or greater but must not exceed the 
                  * number of choices available."
                  * 
                  * See http://www.imsglobal.org/question/qtiv2p1/imsqti_infov2p1.html#element10283
                  */
                 if ($minChoices !== 0) {
                     $component->setMinChoices($minChoices);
                 }
             } else {
                 $component->setMinChoices($minChoices);
             }
         }
         if (($orientation = self::getDOMElementAttributeAs($element, 'orientation')) !== null) {
             $component->setOrientation(Orientation::getConstantByName($orientation));
         }
         if (($xmlBase = self::getXmlBase($element)) !== false) {
             $component->setXmlBase($xmlBase);
         }
         $promptElts = self::getChildElementsByTagName($element, 'prompt');
         if (count($promptElts) > 0) {
             $promptElt = $promptElts[0];
             $prompt = $this->getMarshallerFactory()->createMarshaller($promptElt)->unmarshall($promptElt);
             $component->setPrompt($prompt);
         }
         self::fillBodyElement($component, $element);
         return $component;
     } else {
         $msg = "The mandatory 'responseIdentifier' attribute is missing from the " . $element->localName . " element.";
         throw new UnmarshallingException($msg, $element);
     }
 }
Exemple #17
0
 /**
  * @see \qtism\data\storage\xml\marshalling\RecursiveMarshaller::unmarshallChildrenKnown()
  */
 protected function unmarshallChildrenKnown(DOMElement $element, QtiComponentCollection $children)
 {
     try {
         $component = new Tr(new TableCellCollection($children->getArrayCopy()));
         $this->fillBodyElement($component, $element);
         return $component;
     } catch (InvalidArgumentException $e) {
         $msg = "A 'tr' element must contain at least one 'td' or 'th' element.";
         throw new UnmarshallingException($msg, $element);
     }
 }
 protected function unmarshallChildrenKnown(DOMElement $element, QtiComponentCollection $children)
 {
     $fqClass = $this->lookupClass($element);
     $component = new $fqClass();
     $component->setContent(new FlowCollection($children->getArrayCopy()));
     if (($xmlBase = self::getXmlBase($element)) !== false) {
         $component->setXmlBase($xmlBase);
     }
     self::fillBodyElement($component, $element);
     return $component;
 }
 public function buildContentCollection(QtiComponentCollection $contentCollection)
 {
     // Check whether the content is already an InlineCollection
     $areInlineComponents = array_reduce($contentCollection->getArrayCopy(), function ($initial, $component) {
         return $initial && $component instanceof Inline;
     }, true);
     if ($areInlineComponents) {
         return $contentCollection;
     }
     // Otherwise, make it inline - impossible to make things inline if contents are block elements
     // TODO: Give up for now
     throw new \Exception('Fail to build inline content');
 }
 protected function getMergedInteractionType(QtiComponentCollection $interactionComponents)
 {
     // Decide whether we shall merge interaction
     $interactionTypes = array_unique(array_map(function ($component) {
         /* @var $component Interaction */
         return $component->getQtiClassName();
     }, $interactionComponents->getArrayCopy()));
     if (count($interactionTypes) === 1 && in_array($interactionTypes[0], Constants::$needMergeInteractionTypes)) {
         return $interactionTypes[0];
     } else {
         return false;
     }
 }
 /**
  * @see \qtism\data\storage\xml\marshalling\RecursiveMarshaller::unmarshallChildrenKnown()
  */
 protected function unmarshallChildrenKnown(DOMElement $element, QtiComponentCollection $children)
 {
     $fqClass = $this->lookupClass($element);
     $component = new $fqClass();
     $component->setContent(new FlowStaticCollection($children->getArrayCopy()));
     if (($xmlBase = self::getXmlBase($element)) !== false) {
         $component->setXmlBase($xmlBase);
     }
     $this->fillBodyElement($component, $element);
     if (($title = static::getDOMElementAttributeAs($element, 'title')) !== null) {
         $component->setTitle($title);
     }
     return $component;
 }
 /**
  * @see \qtism\data\storage\xml\marshalling\RecursiveMarshaller::unmarshallChildrenKnown()
  */
 protected function unmarshallChildrenKnown(DOMElement $element, QtiComponentCollection $children)
 {
     $version = $this->getVersion();
     if (($responseIdentifier = self::getDOMElementAttributeAs($element, 'responseIdentifier')) !== null) {
         $objectElts = self::getChildElementsByTagName($element, 'object');
         if (count($objectElts) > 0) {
             $object = $this->getMarshallerFactory()->createMarshaller($objectElts[0])->unmarshall($objectElts[0]);
             if (($maxChoices = self::getDOMElementAttributeAs($element, 'maxChoices', 'integer')) !== null) {
                 try {
                     $choices = new HotspotChoiceCollection($children->getArrayCopy());
                 } catch (InvalidArgumentException $e) {
                     $msg = "An 'hotspotInteraction' element can only contain 'hotspotChoice' choices.";
                     throw new UnmarshallingException($msg, $element, $e);
                 }
                 if (count($choices) > 0) {
                     $fqClass = $this->lookupClass($element);
                     $component = new $fqClass($responseIdentifier, $object, $maxChoices, $choices);
                     if (Version::compare($version, '2.1.0', '>=') === true && ($minChoices = self::getDOMElementAttributeAs($element, 'minChoices', 'integer')) !== null) {
                         $component->setMinChoices($minChoices);
                     }
                     if (($xmlBase = self::getXmlBase($element)) !== false) {
                         $component->setXmlBase($xmlBase);
                     }
                     $promptElts = self::getChildElementsByTagName($element, 'prompt');
                     if (count($promptElts) > 0) {
                         $promptElt = $promptElts[0];
                         $prompt = $this->getMarshallerFactory()->createMarshaller($promptElt)->unmarshall($promptElt);
                         $component->setPrompt($prompt);
                     }
                     $this->fillBodyElement($component, $element);
                     return $component;
                 } else {
                     $msg = "An 'hotspotInteraction' element must contain at least one 'hotspotChoice' element, none given";
                     throw new UnmarshallingException($msg, $element);
                 }
             } else {
                 $msg = "The mandatory 'maxChoices' attribute is missing from the 'hotspotInteraction' element.";
                 throw new UnmarshallingException($msg, $element);
             }
         } else {
             $msg = "A 'hotspotInteraction' element must contain exactly one 'object' element, none given.";
             throw new UnmarshallingException($msg, $element);
         }
     } else {
         $msg = "The mandatory 'responseIdentifier' attribute is missing from the '" . $element->localName . "' element.";
         throw new UnmarshallingException($msg, $element);
     }
 }
 /**
  * @see \qtism\data\storage\xml\marshalling\RecursiveMarshaller::unmarshallChildrenKnown()
  */
 protected function unmarshallChildrenKnown(DOMElement $element, QtiComponentCollection $children)
 {
     $version = $this->getVersion();
     // responseIdentifier.
     if (($responseIdentifier = self::getDOMElementAttributeAs($element, 'responseIdentifier')) !== null) {
         $fqClass = $this->lookupClass($element);
         try {
             $component = new $fqClass($responseIdentifier, new SimpleMatchSetCollection($children->getArrayCopy()));
         } catch (InvalidArgumentException $e) {
             $msg = "A matchInteraction element must contain exactly 2 simpleMatchSet elements, " . count($children) . "' given.";
             throw new UnmarshallingException($msg, $element, $e);
         }
         // shuffle.
         if (($shuffle = self::getDOMElementAttributeAs($element, 'shuffle', 'boolean')) !== null) {
             $component->setShuffle($shuffle);
         } elseif (Version::compare($version, '2.1.0', '<') === true) {
             $msg = "The mandatory attribute 'shuffle' is missing from the 'matchInteraction' element.";
             throw new UnmarshallingException($msg, $element);
         }
         // maxAssociations.
         if (($maxAssociations = self::getDOMElementAttributeAs($element, 'maxAssociations', 'integer')) !== null) {
             $component->setMaxAssociations($maxAssociations);
         } elseif (Version::compare($version, '2.1.0', '<') === true) {
             $msg = "The mandatory attribute 'maxAssociations' is missing from the 'matchInteraction' element.";
             throw new UnmarshallingException($msg, $element);
         }
         // minAssociations.
         if (Version::compare($version, '2.1.0', '>=') === true && ($minAssociations = self::getDOMElementAttributeAs($element, 'minAssociations', 'integer')) !== null) {
             $component->setMinAssociations($minAssociations);
         }
         // xml:base
         if (($xmlBase = self::getXmlBase($element)) !== false) {
             $component->setXmlBase($xmlBase);
         }
         // prompt.
         $promptElts = self::getChildElementsByTagName($element, 'prompt');
         if (count($promptElts) > 0) {
             $promptElt = $promptElts[0];
             $prompt = $this->getMarshallerFactory()->createMarshaller($promptElt)->unmarshall($promptElt);
             $component->setPrompt($prompt);
         }
         $this->fillBodyElement($component, $element);
         return $component;
     } else {
         $msg = "The mandatory 'responseIdentifier' attribute is missing from the 'matchInteraction' element.";
         throw new UnmarshallingException($msg, $element);
     }
 }
 protected function unmarshallChildrenKnown(DOMElement $element, QtiComponentCollection $children)
 {
     if (($responseIdentifier = self::getDOMElementAttributeAs($element, 'responseIdentifier')) !== null) {
         $objectElts = self::getChildElementsByTagName($element, 'object');
         if (count($objectElts) > 0) {
             $object = $this->getMarshallerFactory()->createMarshaller($objectElts[0])->unmarshall($objectElts[0]);
             try {
                 $choices = new AssociableHotspotCollection($children->getArrayCopy());
             } catch (InvalidArgumentException $e) {
                 $msg = "An 'graphicAssociateInteraction' element can only contain 'associableHotspot' choices.";
                 throw new UnmarshallingException($msg, $element, $e);
             }
             if (count($choices) > 0) {
                 $fqClass = $this->lookupClass($element);
                 $component = new $fqClass($responseIdentifier, $object, $choices);
                 if (($minAssociations = self::getDOMElementAttributeAs($element, 'minAssociations', 'integer')) !== null) {
                     $component->setMinAssociations($minAssociations);
                 }
                 if (($maxAssociations = self::getDOMElementAttributeAs($element, 'maxAssociations', 'integer')) !== null) {
                     $component->setMaxAssociations($maxAssociations);
                 }
                 if (($xmlBase = self::getXmlBase($element)) !== false) {
                     $component->setXmlBase($xmlBase);
                 }
                 $promptElts = self::getChildElementsByTagName($element, 'prompt');
                 if (count($promptElts) > 0) {
                     $promptElt = $promptElts[0];
                     $prompt = $this->getMarshallerFactory()->createMarshaller($promptElt)->unmarshall($promptElt);
                     $component->setPrompt($prompt);
                 }
                 self::fillBodyElement($component, $element);
                 return $component;
             } else {
                 $msg = "A 'graphicAssociateInteraction' element must contain at lease one 'associableHotspot' element, none given.";
             }
         } else {
             $msg = "A 'graphicAssociateInteraction' element must contain exactly one 'object' element, none given.";
             throw new UnmarshallingException($msg, $element);
         }
     } else {
         $msg = "The mandatory 'responseIdentifier' attribute is missing from the 'graphicAssociateInteraction' element.";
         throw new UnmarshallingException($msg, $element);
     }
 }
 private function buildTemplate(QtiGapMatchInteraction $interaction)
 {
     $templateCollection = new QtiComponentCollection();
     foreach ($interaction->getComponents() as $component) {
         // Ignore `prompt` and the `gapChoice` since they are going to be mapped somewhere else :)
         if (!$component instanceof Prompt && !$component instanceof GapChoice) {
             $templateCollection->attach($component);
         }
     }
     $gapIdentifiers = [];
     $content = QtiMarshallerUtil::marshallCollection($templateCollection);
     foreach ($interaction->getComponentsByClassName('gap', true) as $gap) {
         /** @var Gap $gap */
         $gapIdentifiers[] = $gap->getIdentifier();
         $gapString = QtiMarshallerUtil::marshall($gap);
         $content = str_replace($gapString, '{{response}}', $content);
     }
     return [$content, $gapIdentifiers];
 }
 /**
  * @see \qtism\data\storage\xml\marshalling\RecursiveMarshaller::unmarshallChildrenKnown()
  */
 protected function unmarshallChildrenKnown(DOMElement $element, QtiComponentCollection $children)
 {
     $fqClass = $this->lookupClass($element);
     $component = new $fqClass();
     if (($headers = self::getDOMElementAttributeAs($element, 'headers')) !== null) {
         try {
             $headersCollection = new IdentifierCollection();
             foreach (explode(" ", $headers) as $h) {
                 $headersCollection[] = $h;
             }
             $component->setHeaders($headersCollection);
         } catch (InvalidArgumentException $e) {
             $msg = "The 'headers' attribute does not contain valid QTI identifiers.";
             throw new UnmarshallingException($msg, $element);
         }
     }
     if (($scope = self::getDOMElementAttributeAs($element, 'scope')) !== null) {
         $component->setScope(TableCellScope::getConstantByName($scope));
     }
     if (($abbr = self::getDOMElementAttributeAs($element, 'abbr')) !== null) {
         $component->setAbbr($abbr);
     }
     if (($axis = self::getDOMElementAttributeAs($element, 'axis')) !== null) {
         $component->setAxis($axis);
     }
     if (($rowspan = self::getDOMElementAttributeAs($element, 'rowspan', 'integer')) !== null) {
         $component->setRowspan($rowspan);
     }
     if (($colspan = self::getDOMElementAttributeAs($element, 'colspan', 'integer')) !== null) {
         $component->setColspan($colspan);
     }
     try {
         $component->setContent(new FlowCollection($children->getArrayCopy()));
         $this->fillBodyElement($component, $element);
         return $component;
     } catch (InvalidArgumentException $e) {
         $msg = "A '" . $element->localName . "' element can only contain QTI flow elements.";
         throw new UnmarshallingException($msg, $element);
     }
 }
 /**
  * @see \qtism\data\storage\xml\marshalling\RecursiveMarshaller::unmarshallChildrenKnown()
  */
 protected function unmarshallChildrenKnown(DOMElement $element, QtiComponentCollection $children)
 {
     $version = $this->getVersion();
     if (($responseIdentifier = self::getDOMElementAttributeAs($element, 'responseIdentifier')) !== null) {
         $fqClass = $this->lookupClass($element);
         try {
             $content = new BlockStaticCollection($children->getArrayCopy());
         } catch (InvalidArgumentException $e) {
             $msg = "The content of the 'hottextInteraction' element is invalid.";
             throw new UnmarshallingException($msg, $element, $e);
         }
         try {
             $component = new $fqClass($responseIdentifier, $content);
         } catch (InvalidArgumentException $e) {
             $msg = "The value '{$responseIdentifier}' for the attribute 'responseIdentifier' for element 'hottextInteraction' is not a valid QTI identifier.";
             throw new UnmarshallingException($msg, $element, $e);
         }
         if (($maxChoices = self::getDOMElementAttributeAs($element, 'maxChoices', 'integer')) !== null) {
             $component->setMaxChoices($maxChoices);
         }
         if (Version::compare($version, '2.1.0', '>=') === true && ($minChoices = self::getDOMElementAttributeAs($element, 'minChoices', 'integer')) !== null) {
             $component->setMinChoices($minChoices);
         }
         if (($xmlBase = self::getXmlBase($element)) !== false) {
             $component->setXmlBase($xmlBase);
         }
         $promptElts = self::getChildElementsByTagName($element, 'prompt');
         if (count($promptElts) > 0) {
             $promptElt = $promptElts[0];
             $prompt = $this->getMarshallerFactory()->createMarshaller($promptElt)->unmarshall($promptElt);
             $component->setPrompt($prompt);
         }
         $this->fillBodyElement($component, $element);
         return $component;
     } else {
         $msg = "The mandatory 'responseIdentifier' attribute is missing from the " . $element->localName . " element.";
         throw new UnmarshallingException($msg, $element);
     }
 }
 /**
  * @see \qtism\data\storage\xml\marshalling\RecursiveMarshaller::unmarshallChildrenKnown()
  */
 protected function unmarshallChildrenKnown(DOMElement $element, QtiComponentCollection $children)
 {
     $version = $this->getVersion();
     if (($identifier = self::getDOMElementAttributeAs($element, 'identifier')) !== null) {
         $fqClass = $this->lookupClass($element);
         $component = new $fqClass($identifier);
         if (($fixed = self::getDOMElementAttributeAs($element, 'fixed', 'boolean')) !== null) {
             $component->setFixed($fixed);
         }
         if (Version::compare($version, '2.1.0', '>=') === true && ($templateIdentifier = self::getDOMElementAttributeAs($element, 'templateIdentifier')) !== null) {
             $component->setTemplateIdentifier($templateIdentifier);
         }
         if (Version::compare($version, '2.1.0', '>=') === true && ($showHide = self::getDOMElementAttributeAs($element, 'showHide')) !== null) {
             $component->setShowHide(ShowHide::getConstantByName($showHide));
         }
         $component->setContent(new FlowStaticCollection($children->getArrayCopy()));
         $this->fillBodyElement($component, $element);
         return $component;
     } else {
         $msg = "The mandatory 'identifier' attribute is missing from the 'simpleChoice' element.";
         throw new UnmarshallingException($msg, $element);
     }
 }
 private function buildTemplate(HottextInteraction $interaction)
 {
     $templateCollection = new QtiComponentCollection();
     foreach ($interaction->getComponents() as $component) {
         // Ignore `prompt` since its going to be mapped to `stimulus`
         if (!$component instanceof Prompt) {
             $templateCollection->attach($component);
         }
     }
     $content = QtiMarshallerUtil::marshallCollection($templateCollection);
     foreach ($interaction->getComponentsByClassName('hottext') as $hottext) {
         /** @var Hottext $hottext */
         $hottextString = QtiMarshallerUtil::marshall($hottext);
         $tokenSpan = new span();
         $tokenSpan->setClass('lrn_token');
         $inlineCollection = new InlineCollection();
         foreach ($hottext->getComponents() as $c) {
             $inlineCollection->attach($c);
         }
         $tokenSpan->setContent($inlineCollection);
         $content = str_replace($hottextString, QtiMarshallerUtil::marshall($tokenSpan), $content);
     }
     return $content;
 }
 protected function unmarshallChildrenKnown(DOMElement $element, QtiComponentCollection $children)
 {
     $fqClass = $this->lookupClass($element);
     if (($outcomeIdentifier = self::getDOMElementAttributeAs($element, 'outcomeIdentifier')) !== null) {
         if (($identifier = self::getDOMElementAttributeAs($element, 'identifier')) !== null) {
             $component = new $fqClass($outcomeIdentifier, $identifier);
             if (($showHide = self::getDOMElementAttributeAs($element, 'showHide')) !== null) {
                 try {
                     $component->setShowHide(ShowHide::getConstantByName($showHide));
                 } catch (InvalidArgumentException $e) {
                     $msg = "'{$showHide}' is not a valid value for the 'showHide' attribute of element 'modalFeedback'.";
                     throw new UnmarshallingException($msg, $element, $e);
                 }
                 try {
                     $content = new FlowStaticCollection($children->getArrayCopy());
                     $component->setContent($content);
                 } catch (InvalidArgumentException $e) {
                     $msg = "The content of the 'modalFeedback' is invalid. It must only contain 'flowStatic' elements.";
                     throw new UnmarshallingException($msg, $element, $e);
                 }
                 if (($title = self::getDOMElementAttributeAs($element, 'title')) !== null) {
                     $component->setTitle($title);
                 }
                 return $component;
             } else {
                 $msg = "The mandatory 'showHide' attribute is missing from element 'modalFeedback'.";
             }
         } else {
             $msg = "The mandatory 'identifier' attribute is missing from element 'modalFeedback'.";
             throw new UnmarshallingException($msg, $element);
         }
     } else {
         $msg = "The mandatory 'outcomeIdentifier' attribute is missing from element 'modalFeedback'.";
         throw new UnmarshallingException($msg, $element);
     }
 }