public function setUp()
 {
     parent::setUp();
     $stream = new MemoryStream();
     $stream->open();
     $this->setStreamAccess(new PhpStreamAccess($stream));
 }
 public function setUp()
 {
     parent::setUp();
     $stream = new MemoryStream();
     $stream->open();
     $this->setStream($stream);
 }
 /**
  * Persist the binary stream $stream which contains the binary equivalent of $assessmentTestSession in
  * the temporary directory of the file system.
  *
  * @param \qtism\runtime\tests\AssessmentTestSession $assessmentTestSession The AssessmentTestSession to be persisted.
  * @param \qtism\common\storage\MemoryStream $stream The MemoryStream to be stored in the temporary directory of the host file system.
  * @throws \RuntimeException If the binary stream cannot be persisted.
  */
 protected function persistStream(AssessmentTestSession $assessmentTestSession, MemoryStream $stream)
 {
     $sessionId = $assessmentTestSession->getSessionId();
     $path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . md5($sessionId) . '.bin';
     $written = @file_put_contents($path, $stream->getBinary());
     if ($written === false || $written === 0) {
         $msg = "An error occured while persisting the binary stream at '{$path}'.";
         throw new RuntimeException($msg);
     }
 }
 public function testReadFloat()
 {
     $stream = new MemoryStream(pack('d', 0.0) . pack('d', -M_PI) . pack('d', M_2_PI));
     $stream->open();
     $reader = new BinaryStreamAccess($stream);
     $float = $reader->readFloat();
     $this->assertInternalType('float', $float);
     $this->assertEquals(round(0.0, 3), round($float, 3));
     $float = $reader->readFloat();
     $this->assertInternalType('float', $float);
     $this->assertEquals(round(-M_PI, 3), round($float, 3));
     $float = $reader->readFloat();
     $this->assertInternalType('float', $float);
     $this->assertEquals(round(M_2_PI, 3), round($float, 3));
     try {
         $float = $reader->readFloat();
     } catch (BinaryStreamAccessException $e) {
         $this->assertEquals(BinaryStreamAccessException::FLOAT, $e->getCode());
     }
 }
 /**
  * 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);
     }
 }
 public function testWriteShufflingState()
 {
     $shufflingGroup = new ShufflingGroup(new IdentifierCollection(array('id1', 'id2', 'id3')));
     $shufflingGroup->setFixedIdentifiers(new IdentifierCollection(array('id2')));
     $shufflingGroups = new ShufflingGroupCollection(array($shufflingGroup));
     $shuffling = new Shuffling('RESPONSE', $shufflingGroups);
     $stream = new MemoryStream();
     $stream->open();
     $access = new QtiBinaryStreamAccess($stream, new FileSystemFileManager());
     $access->writeShufflingState($shuffling);
     $stream->rewind();
     $shufflingState = $access->readShufflingState();
     $this->assertEquals('RESPONSE', $shufflingState->getResponseIdentifier());
     $shufflingGroups = $shufflingState->getShufflingGroups();
     $this->assertEquals(array('id1', 'id2', 'id3'), $shufflingGroups[0]->getIdentifiers()->getArrayCopy());
     $this->assertEquals(array('id2'), $shufflingGroups[0]->getFixedIdentifiers()->getArrayCopy());
 }
 protected function persistStream(AssessmentTestSession $assessmentTestSession, MemoryStream $stream)
 {
     $storageService = tao_models_classes_service_StateStorage::singleton();
     $userUri = common_session_SessionManager::getSession()->getUserUri();
     if (is_null($userUri) === true) {
         $msg = "Could not retrieve current user URI.";
         throw new StorageException($msg, StorageException::RETRIEVAL);
     }
     $data = $this->getLastError() . $stream->getBinary();
     $storageService->set($userUri, $assessmentTestSession->getSessionId(), $data);
 }
Exemple #8
0
 /**
  * Initialize the object to be ready for a new rescoping.
  *
  * @param string $id The identifier to be used for scoping.
  * @param string $file The path to the CSS file to be scoped.
  */
 protected function init($id, $file)
 {
     $this->setState(self::RUNNING);
     $this->setId($id);
     $this->setBuffer(array());
     $this->setOutput('');
     $this->setPreviousChar(false);
     $this->setPreviousSignificantChar(false);
     if (($data = @file_get_contents($file)) !== false) {
         $stream = new MemoryStream($data);
         $stream->open();
         $this->setStream($stream);
     } else {
         throw new RenderingException("The CSS file '{$file}' could not be open.", RenderingException::RUNTIME);
     }
 }
 public function testWritePendingResponses()
 {
     $doc = new XmlCompactDocument();
     $doc->load(self::samplesDir() . 'custom/runtime/itemsubset_simultaneous.xml');
     $seeker = new AssessmentTestSeeker($doc->getDocumentComponent(), array('assessmentItemRef', 'assessmentSection', 'testPart', 'outcomeDeclaration', 'responseDeclaration', 'branchRule', 'preCondition'));
     $stream = new MemoryStream();
     $stream->open();
     $access = new QtiBinaryStreamAccessFsFile($stream);
     $factory = new SessionManager();
     $session = $factory->createAssessmentTestSession($doc->getDocumentComponent());
     $session->beginTestSession();
     $session->beginAttempt();
     $session->endAttempt(new State(array(new ResponseVariable('RESPONSE', Cardinality::SINGLE, BaseType::IDENTIFIER, new Identifier('ChoiceB')))));
     $store = $session->getPendingResponseStore();
     $pendingResponses = $store->getPendingResponses($doc->getDocumentComponent()->getComponentByIdentifier('Q01'));
     $access->writePendingResponses($seeker, $pendingResponses);
     $stream->rewind();
     $pendingResponses = $access->readPendingResponses($seeker);
     $state = $pendingResponses->getState();
     $this->assertEquals('ChoiceB', $state['RESPONSE']->getValue());
     $this->assertEquals('Q01', $pendingResponses->getAssessmentItemRef()->getIdentifier());
     $this->assertEquals(0, $pendingResponses->getOccurence());
     $this->assertInternalType('integer', $pendingResponses->getOccurence());
 }
 /**
  * Save the PhpDocument to a specific location.
  * 
  * @param string $url A URL (Uniform Resource Locator) describing where to save the document.
  * @throws PhpStorageException If an error occurs while saving.
  */
 public function save($url)
 {
     $stack = new SplStack();
     $stack->push($this->getDocumentComponent());
     // 1st/2nd pass marker.
     $marker = array();
     try {
         // marshalling context.
         $stream = new MemoryStream();
         $stream->open();
         $streamAccess = new PhpStreamAccess($stream);
         $streamAccess->writeOpeningTag();
         $ctx = new PhpMarshallingContext($streamAccess);
         $ctx->setFormatOutput(true);
         while (count($stack) > 0) {
             $component = $stack->pop();
             $isMarked = in_array($component, $marker, true);
             if ($isMarked === false && $component instanceof QtiComponent) {
                 // -- QtiComponent node, 1st pass.
                 // Mark as explored.
                 array_push($marker, $component);
                 // Ask for a 2nd pass.
                 $stack->push($component);
                 // Let's look at the Bean properties and ask for a future exploration.
                 $bean = new Bean($component, false, self::getBaseImplementation($component));
                 $ctorGetters = $bean->getConstructorGetters();
                 $bodyGetters = $bean->getGetters(true);
                 $getters = array_reverse(array_merge($bodyGetters->getArrayCopy(), $ctorGetters->getArrayCopy()));
                 foreach ($getters as $getter) {
                     $stack->push(call_user_func(array($component, $getter->getName())));
                 }
             } else {
                 if ($isMarked === false && ($component instanceof AbstractCollection && !$component instanceof Coords)) {
                     // AbstractCollection node, 1st pass.
                     // Mark as explored.
                     array_push($marker, $component);
                     // Ask for a 2nd pass.
                     $stack->push($component);
                     // Explore all values of the collection please!
                     $values = array_reverse($component->getArrayCopy());
                     foreach ($values as $val) {
                         $stack->push($val);
                     }
                 } else {
                     if ($isMarked === true && $component instanceof QtiComponent) {
                         // QtiComponent, 2nd pass.
                         $marshaller = new PhpQtiComponentMarshaller($ctx, $component);
                         $marshaller->setAsInstanceOf(self::getBaseImplementation($component));
                         if ($component === $this->getDocumentComponent()) {
                             $marshaller->setVariableName('rootcomponent');
                         }
                         $marshaller->marshall();
                     } else {
                         if ($component instanceof QtiDatatype) {
                             // Leaf node QtiDataType.
                             $marshaller = new PhpQtiDatatypeMarshaller($ctx, $component);
                             $marshaller->marshall();
                         } else {
                             if ($isMarked === true && $component instanceof AbstractCollection) {
                                 // AbstractCollection, 2nd pass.
                                 $marshaller = new PhpCollectionMarshaller($ctx, $component);
                                 $marshaller->marshall();
                             } else {
                                 if (PhpUtils::isScalar($component) === true) {
                                     // Leaf node (QtiDatatype or PHP scalar (including the null value)).
                                     $marshaller = new PhpScalarMarshaller($ctx, $component);
                                     $marshaller->marshall();
                                 } else {
                                     if (is_array($component) === true) {
                                         // Leaf node array.
                                         $marshaller = new PhpArrayMarshaller($ctx, $component);
                                         $marshaller->marshall();
                                     } else {
                                         $msg = "Datatype '" . gettype($component) . "' cannot be handled by the PhpDocument::save() method.";
                                         throw new PhpStorageException($msg);
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
         file_put_contents($url, $stream->getBinary());
     } catch (StreamAccessException $e) {
         $msg = "An error occured while writing the PHP source code stream.";
         throw new PhpStorageException($msg, 0, $e);
     }
 }
 /**
  * Persist an AssessmentTestSession into binary data.
  * 
  * The QTI Binary Storage Version that will be used to persist the AssessmentTestSession
  * will be systematically the one defined in QtiBinaryConstants::QTI_BINARY_STORAGE_VERSION. 
  * 
  * @param AssessmentTestSession $assessmentTestSession
  * @throws StorageException
  */
 public function persist(AssessmentTestSession $assessmentTestSession)
 {
     try {
         $stream = new MemoryStream();
         $stream->open();
         $access = $this->createBinaryStreamAccess($stream);
         // write the QTI Binary Storage version in use to persist the test session.
         $access->writeTinyInt(QtiBinaryConstants::QTI_BINARY_STORAGE_VERSION);
         $access->writeTinyInt($assessmentTestSession->getState());
         $route = $assessmentTestSession->getRoute();
         $access->writeTinyInt($route->getPosition());
         // Persist the Route of the AssessmentTestSession and the related item sessions.
         $access->writeTinyInt($route->count());
         $itemSessionStore = $assessmentTestSession->getAssessmentItemSessionStore();
         $pendingResponseStore = $assessmentTestSession->getPendingResponseStore();
         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.
             $itemSession = $itemSessionStore->getAssessmentItemSession($item, $occurence);
             $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);
             }
         }
         // 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}'.";
         throw new StorageException($msg, StorageException::PERSITANCE, $e);
     }
 }