/** * Persist an AssessmentTestSession into binary data. * * @param \qtism\runtime\tests\AssessmentTestSession $assessmentTestSession * @throws \qtism\runtime\storage\common\StorageException */ public function persist(AssessmentTestSession $assessmentTestSession) { try { $stream = new MemoryStream(); $stream->open(); $access = $this->createBinaryStreamAccess($stream); // -- Deal with intrinsic values of the Test Session. $access->writeTinyInt($assessmentTestSession->getState()); // Write the current position in the route. $route = $assessmentTestSession->getRoute(); $access->writeTinyInt($route->getPosition()); // persist time reference. $timeReference = $assessmentTestSession->getTimeReference(); if (is_null($timeReference) === true) { $access->writeBoolean(false); } else { $access->writeBoolean(true); $access->writeDateTime($timeReference); } // -- Persist the Route of the AssessmentTestSession and the related item sessions. $access->writeTinyInt($route->count()); $itemSessionStore = $assessmentTestSession->getAssessmentItemSessionStore(); $pendingResponseStore = $assessmentTestSession->getPendingResponseStore(); $oldRoutePosition = $route->getPosition(); foreach ($route as $routeItem) { $item = $routeItem->getAssessmentItemRef(); $occurence = $routeItem->getOccurence(); // Deal with RouteItem $access->writeRouteItem($this->getSeeker(), $routeItem); // Deal with ItemSession related to the previously written RouteItem. try { $itemSession = $itemSessionStore->getAssessmentItemSession($item, $occurence); $access->writeBoolean(true); $access->writeAssessmentItemSession($this->getSeeker(), $itemSession); // Deal with last occurence update. $access->writeBoolean($assessmentTestSession->isLastOccurenceUpdate($item, $occurence)); // Deal with PendingResponses if (($pendingResponses = $pendingResponseStore->getPendingResponses($item, $occurence)) !== false) { $access->writeBoolean(true); $access->writePendingResponses($this->getSeeker(), $pendingResponses); } else { $access->writeBoolean(false); } } catch (OutOfBoundsException $e) { $access->writeBoolean(false); // No assessmentItemSession for this route item. continue; } } $route->setPosition($oldRoutePosition); // Deal with test session configuration. // !!! AutoForward (not in use anymore, fake it). $access->writeBoolean(false); // Persist the test-level global scope. foreach ($assessmentTestSession->getKeys() as $outcomeIdentifier) { $outcomeVariable = $assessmentTestSession->getVariable($outcomeIdentifier); $access->writeVariableValue($outcomeVariable); } $durationStore = $assessmentTestSession->getDurationStore(); $access->writeShort(count($durationStore)); foreach ($durationStore->getKeys() as $k) { $access->writeString($k); $access->writeVariableValue($durationStore->getVariable($k)); } $this->persistStream($assessmentTestSession, $stream); $stream->close(); } catch (Exception $e) { $sessionId = $assessmentTestSession->getSessionId(); $msg = "An error occured while persisting AssessmentTestSession with ID '{$sessionId}': " . $e->getMessage(); throw new StorageException($msg, StorageException::PERSITANCE, $e); } }