public function testMarshallMaximal() { $assessmentSection1 = new ExtendedAssessmentSection('section1', 'My Section 1', true); $assessmentSection2 = new ExtendedAssessmentSection('section2', 'My Section 2', true); $preCondition = new PreCondition(new BaseValue(BaseType::BOOLEAN, true)); $branching = new BranchRule(new BaseValue(BaseType::BOOLEAN, true), 'EXIT_TESTPART'); $itemSessionControl = new ItemSessionControl(); $itemSessionControl->setShowSolution(true); $timeLimits = new TimeLimits(null, new QtiDuration('PT1M40S')); $p = new P(); $p->setContent(new InlineCollection(array(new TextRun('Prima!')))); $testFeedback = new TestFeedback('feedback1', 'show', new FlowStaticCollection(array($p))); $testFeedback->setTitle('hello!'); $testFeedback->setAccess(TestFeedbackAccess::AT_END); $testFeedback->setShowHide(ShowHide::SHOW); $testFeedbackRef = new TestFeedbackRef('feedback1', 'show', TestFeedbackAccess::AT_END, ShowHide::SHOW, './TF01.xml'); $assessmentSections = new AssessmentSectionCollection(array($assessmentSection1, $assessmentSection2)); $preConditions = new PreConditionCollection(array($preCondition)); $branchings = new BranchRuleCollection(array($branching)); $testFeedbacks = new TestFeedbackCollection(array($testFeedback)); $testFeedbackRefs = new TestFeedbackRefCollection(array($testFeedbackRef)); $extendedTestPart = new ExtendedTestPart('part1', $assessmentSections); $extendedTestPart->setPreConditions($preConditions); $extendedTestPart->setBranchRules($branchings); $extendedTestPart->setItemSessionControl($itemSessionControl); $extendedTestPart->setTimeLimits($timeLimits); $extendedTestPart->setTestFeedbacks($testFeedbacks); $extendedTestPart->setTestFeedbackRefs($testFeedbackRefs); $factory = new CompactMarshallerFactory(); $element = $factory->createMarshaller($extendedTestPart)->marshall($extendedTestPart); $dom = new DOMDocument('1.0', 'UTF-8'); $element = $dom->importNode($element, true); $this->assertEquals('<testPart identifier="part1" navigationMode="linear" submissionMode="individual"><preCondition><baseValue baseType="boolean">true</baseValue></preCondition><branchRule target="EXIT_TESTPART"><baseValue baseType="boolean">true</baseValue></branchRule><itemSessionControl maxAttempts="1" showFeedback="false" allowReview="true" showSolution="true" allowComment="false" allowSkipping="true" validateResponses="false"/><timeLimits maxTime="100" allowLateSubmission="false"/><assessmentSection identifier="section1" required="false" fixed="false" title="My Section 1" visible="true" keepTogether="true"/><assessmentSection identifier="section2" required="false" fixed="false" title="My Section 2" visible="true" keepTogether="true"/><testFeedback access="atEnd" outcomeIdentifier="show" showHide="show" identifier="feedback1" title="hello!"><p>Prima!</p></testFeedback><testFeedbackRef identifier="feedback1" outcomeIdentifier="show" access="atEnd" showHide="show" href="./TF01.xml"/></testPart>', $dom->saveXML($element)); }
/** * @see \qtism\data\storage\xml\marshalling\Marshaller::unmarshall() */ protected function unmarshall(DOMElement $element) { $baseComponent = parent::unmarshall($element); $component = ExtendedTestPart::createFromTestPart($baseComponent); // TestFeedbackRefs. $testFeedbackRefElts = self::getChildElementsByTagName($element, 'testFeedbackRef'); $testFeedbackRefs = new TestFeedbackRefCollection(); foreach ($testFeedbackRefElts as $testFeedbackRefElt) { $marshaller = $this->getMarshallerFactory()->createMarshaller($testFeedbackRefElt); $testFeedbackRefs[] = $marshaller->unmarshall($testFeedbackRefElt); } $component->setTestFeedbackRefs($testFeedbackRefs); return $component; }
/** * Create a new instance of XmlCompactDocument from an XmlAssessmentTestDocument. * * @param \qtism\data\storage\xml\XmlDocument $xmlAssessmentTestDocument An XmlAssessmentTestDocument object you want to store as a compact XML file. * @return \qtism\data\storage\xml\XmlCompactDocument An XmlCompactAssessmentTestDocument object. * @throws \qtism\data\storage\xml\XmlStorageException If an error occurs while transforming the XmlAssessmentTestDocument object into an XmlCompactAssessmentTestDocument object. */ public static function createFromXmlAssessmentTestDocument(XmlDocument $xmlAssessmentTestDocument, FileResolver $itemResolver = null) { $compactAssessmentTest = new XmlCompactDocument(); $identifier = $xmlAssessmentTestDocument->getDocumentComponent()->getIdentifier(); $title = $xmlAssessmentTestDocument->getDocumentComponent()->getTitle(); $assessmentTest = new AssessmentTest($identifier, $title); $assessmentTest->setOutcomeDeclarations($xmlAssessmentTestDocument->getDocumentComponent()->getOutcomeDeclarations()); $assessmentTest->setOutcomeProcessing($xmlAssessmentTestDocument->getDocumentComponent()->getOutcomeProcessing()); $assessmentTest->setTestFeedbacks($xmlAssessmentTestDocument->getDocumentComponent()->getTestFeedbacks()); $assessmentTest->setTestParts($xmlAssessmentTestDocument->getDocumentComponent()->getTestParts()); $assessmentTest->setTimeLimits($xmlAssessmentTestDocument->getDocumentComponent()->getTimeLimits()); $assessmentTest->setToolName($xmlAssessmentTestDocument->getDocumentComponent()->getToolName()); $assessmentTest->setToolVersion($xmlAssessmentTestDocument->getDocumentComponent()->getToolVersion()); // File resolution. $sectionResolver = new LocalFileResolver($xmlAssessmentTestDocument->getUrl()); if (is_null($itemResolver) === true) { $itemResolver = new LocalFileResolver($xmlAssessmentTestDocument->getUrl()); } else { $itemResolver->setBasePath($xmlAssessmentTestDocument->getUrl()); } // It simply consists of replacing assessmentItemRef and assessmentSectionRef elements. $trail = array(); // trailEntry[0] = a component, trailEntry[1] = from where we are coming (parent). $mark = array(); $root = $xmlAssessmentTestDocument->getDocumentComponent(); array_push($trail, array($root, $root)); while (count($trail > 0)) { $trailer = array_pop($trail); $component = $trailer[0]; $previous = $trailer[1]; if (!in_array($component, $mark) && count($component->getComponents()) > 0) { // First pass on a hierarchical node... go deeper in the n-ary tree. array_push($mark, $component); // We want to go back on this component. array_push($trail, $trailer); // Prepare further exploration. foreach ($component->getComponents()->getArrayCopy() as $comp) { array_push($trail, array($comp, $component)); } } elseif (in_array($component, $mark) || count($component->getComponents()) === 0) { // Second pass on a hierarchical node (we are bubbling up accross the n-ary tree) // OR // Leaf node if ($component instanceof AssessmentItemRef) { // Transform the ref in an compact extended ref. $compactRef = ExtendedAssessmentItemRef::createFromAssessmentItemRef($component); // find the old one and replace it. $previousParts = $previous->getSectionParts(); foreach ($previousParts as $k => $previousPart) { if ($previousParts[$k] === $component) { // If the previous processed component is an XmlAssessmentSectionDocument, // it means that the given baseUri must be adapted. $baseUri = $xmlAssessmentTestDocument->getUrl(); if ($component instanceof XmlDocument && $component->getDocumentComponent() instanceof AssessmentSection) { $baseUri = $component->getUrl(); } $itemResolver->setBasePath($baseUri); self::resolveAssessmentItemRef($compactRef, $itemResolver); $previousParts->replace($component, $compactRef); break; } } } elseif ($component instanceof AssessmentSectionRef) { // We follow the unreferenced AssessmentSection as if it was // the 1st pass. $assessmentSection = self::resolveAssessmentSectionRef($component, $sectionResolver); $previousParts = $previous->getSectionParts(); foreach ($previousParts as $k => $previousPart) { if ($previousParts[$k] === $component) { $previousParts->replace($component, $assessmentSection); break; } } array_push($trail, array($assessmentSection, $previous)); } elseif ($component instanceof AssessmentSection) { $assessmentSection = ExtendedAssessmentSection::createFromAssessmentSection($component); $previousParts = $previous instanceof TestPart ? $previous->getAssessmentSections() : $previous->getSectionParts(); foreach ($previousParts as $k => $previousPart) { if ($previousParts[$k] === $component) { $previousParts->replace($component, $assessmentSection); break; } } } elseif ($component instanceof TestPart) { $testPart = ExtendedTestPart::createFromTestPart($component); $root->getTestParts()->replace($component, $testPart); } elseif ($component === $root) { // 2nd pass on the root, we have to stop. $compactAssessmentTest->setDocumentComponent(ExtendedAssessmentTest::createFromAssessmentTest($assessmentTest)); return $compactAssessmentTest; } } } }