/** * @dataProvider sequencedIdentifiersProvider * * @param string $identifier * @param string $expectedPrefix * @param string $expectedSequence * @param string $expectedVariableName */ public function testSequencedIdentifiers($identifier, $expectedPrefix, $expectedSequence, $expectedVariableName) { $v = new VariableIdentifier($identifier); $this->assertEquals($identifier, $v->getIdentifier()); $this->assertTrue($v->hasPrefix()); $this->assertTrue($v->hasSequenceNumber()); $this->assertEquals($expectedPrefix, $v->getPrefix()); $this->assertEquals($expectedVariableName, $v->getVariableName()); $this->assertEquals($expectedSequence, $v->getSequenceNumber()); }
/** * Set the value of a variable with identifier $offset. * * @throws OutOfRangeException If $offset is not a string or an invalid variable identifier. * @throws OutOfBoundsException If the variable with identifier $offset cannot be found. */ public function offsetSet($offset, $value) { if (gettype($offset) !== 'string') { $msg = "An AssessmentTestSession object must be addressed by string."; throw new OutOfRangeException($msg); } try { $v = new VariableIdentifier($offset); if ($v->hasPrefix() === false) { // global scope request. $data =& $this->getDataPlaceHolder(); $varName = $v->getVariableName(); if (isset($data[$varName]) === false) { $msg = "The variable '{$varName}' to be set does not exist in the current context."; throw new OutOfBoundsException($msg); } $data[$offset]->setValue($value); return; } else { // prefix given. // - prefix targets an item ? $store = $this->getAssessmentItemSessionStore(); $items = $this->getAssessmentItemRefs(); $sequence = $v->hasSequenceNumber() === true ? $v->getSequenceNumber() - 1 : 0; $prefix = $v->getPrefix(); try { if (isset($items[$prefix]) && ($session = $this->getItemSession($items[$prefix], $sequence)) !== false) { $session[$v->getVariableName()] = $value; return; } } catch (OutOfBoundsException $e) { // The session could be retrieved, but no such variable into it. } $msg = "The variable '" . $v->__toString() . "' does not exist in the current context."; throw new OutOfBoundsException($msg); } } catch (InvalidArgumentException $e) { // Invalid variable identifier. $msg = "AssessmentTestSession object addressed with an invalid identifier '{$offset}'."; throw new OutOfRangeException($msg, 0, $e); } }
/** * Perform a branching on a TestPart, AssessmentSection or AssessmentItemRef with * the given $identifier. * * The target will be considered invalid if the following constraints are not fullfilled: * * From IMS QTI: * In the case of an item or section, the target must refer to an item or section in the same * testPart that has not yet been presented. For testParts, the target must refer to another testPart. * * @param string $identifier A QTI Identifier to be the target of the branching. * @throws \OutOfBoundsException If an error occurs while branching e.g. the $identifier is not referenced in the route or the target is invalid. * @throws \OutOfRangeException If $identifier is not a valid branching identifier. */ public function branch($identifier) { try { $identifier = new VariableIdentifier($identifier); $id = $identifier->hasPrefix() === false ? $identifier->getVariableName() : $identifier->getPrefix(); $occurence = $identifier->hasPrefix() === false ? 0 : intval($identifier->getVariableName() - 1); } catch (InvalidArgumentException $e) { $msg = "The given identifier '{$identifier}' is an invalid branching target."; throw new OutOfRangeException($msg); } // Check for an assessmentItemRef. $assessmentItemRefs = $this->getAssessmentItemRefs(); if (isset($assessmentItemRefs[$id]) === true) { $assessmentItemRefMap = $this->getAssessmentItemRefMap(); $targetRouteItems = $assessmentItemRefMap[$assessmentItemRefs[$id]]; if ($targetRouteItems[$occurence]->getTestPart() !== $this->current()->getTestPart()) { // From IMS QTI: // In case of an item or section, the target must refer to an item or section // in the same testPart [...] $msg = "Branchings to items outside of the current testPart is forbidden by the QTI 2.1 specification."; throw new OutOfBoundsException($msg); } $this->setPosition($this->getRouteItemPosition($targetRouteItems[$occurence])); return; } // Check for an assessmentSection. $assessmentSectionIdentifierMap = $this->getAssessmentSectionIdentifierMap(); if (isset($assessmentSectionIdentifierMap[$id]) === true) { if ($assessmentSectionIdentifierMap[$id][0]->getTestPart() !== $this->current()->getTestPart()) { // From IMS QTI: // In case of an item or section, the target must refer to an item or section // in the same testPart [...] $msg = "Branchings to assessmentSections outside of the current testPart is forbidden by the QTI 2.1 specification."; throw new OutOfBoundsException($msg); } // We branch to the first RouteItem belonging to the section. $this->setPosition($this->getRouteItemPosition($assessmentSectionIdentifierMap[$id][0])); return; } // Check for a testPart. $testPartIdentifierMap = $this->getTestPartIdentifierMap(); if (isset($testPartIdentifierMap[$id]) === true) { // We branch to the first RouteItem belonging to the testPart. if ($testPartIdentifierMap[$id][0]->getTestPart() === $this->current()->getTestPart()) { // From IMS QTI: // For testParts, the target must refer to another testPart. $msg = "Cannot branch to the same testPart."; throw new OutOfBoundsException($msg); } // We branch to the first RouteItem belonging to the testPart. $this->setPosition($this->getRouteItemPosition($testPartIdentifierMap[$id][0])); return; } // No such identifier referenced in the route, cannot branch. $msg = "No such identifier '{$id}' found in the route for branching."; throw new OutOfBoundsException($msg); }