/** * temporary helper until proper servicemanager integration * @return ExtendedStateService */ public static function getExtendedStateService() { if (!isset(self::$extendedStateService)) { self::$extendedStateService = new ExtendedStateService(); } return self::$extendedStateService; }
/** * Returns the options related to the current test context * @param RunnerServiceContext $context The test context * @return mixed */ public function getOptions(RunnerServiceContext $context) { $session = $context->getTestSession(); // Comment allowed? Skipping allowed? Logout or Exit allowed ? $options = ['allowComment' => \taoQtiTest_helpers_TestRunnerUtils::doesAllowComment($session), 'allowSkipping' => \taoQtiTest_helpers_TestRunnerUtils::doesAllowSkipping($session), 'exitButton' => \taoQtiTest_helpers_TestRunnerUtils::doesAllowExit($session), 'logoutButton' => \taoQtiTest_helpers_TestRunnerUtils::doesAllowLogout($session)]; // get the options from the categories owned by the current item $categories = \taoQtiTest_helpers_TestRunnerUtils::getCategories($session); $prefixCategory = 'x-tao-option-'; $prefixCategoryLen = strlen($prefixCategory); foreach ($categories as $category) { if (!strncmp($category, $prefixCategory, $prefixCategoryLen)) { // extract the option name from the category, transform to camelCase if needed $optionName = lcfirst(str_replace(' ', '', ucwords(strtr(substr($category, $prefixCategoryLen), ['-' => ' ', '_' => ' '])))); // the options added by the categories are just flags $options[$optionName] = true; } } return $options; }
/** * Save session metadata. * * @param array $metaData Meta data array to be saved. * Example: * array( * 'TEST' => array('TEST_EXIT_CODE' => 'IC'), * 'SECTION' => array('SECTION_EXIT_CODE' => 701), * ) */ public function save(array $metaData) { $testUri = $this->session->getTest()->getUri(); $resultServer = \taoResultServer_models_classes_ResultServerStateFull::singleton(); foreach ($metaData as $type => $data) { foreach ($data as $key => $value) { $metaVariable = $this->getVariable($key, $value); if (strcasecmp($type, 'ITEM') === 0) { $itemUri = \taoQtiTest_helpers_TestRunnerUtils::getCurrentItemUri($this); $occurence = $this->session->getCurrentAssessmentItemRefOccurence(); $transmissionId = "{$sessionId}.{$item}.{$occurence}"; $resultServer->storeItemVariable($testUri, $itemUri, $metaVariable, $transmissionId); } elseif (strcasecmp($type, 'TEST') === 0) { $resultServer->storeTestVariable($testUri, $metaVariable, $this->session->getSessionId()); } elseif (strcasecmp($type, 'SECTION') === 0) { //suffix section variables with _{SECTION_IDENTIFIER} $assessmentSectionId = $this->session->getCurrentAssessmentSection()->getIdentifier(); $metaVariable->setIdentifier($key . '_' . $assessmentSectionId); $resultServer->storeTestVariable($testUri, $metaVariable, $this->session->getSessionId()); } } } }
/** * Retrieve the current test session as an AssessmentTestSession object from * persistent storage. * */ protected function retrieveTestSession() { $qtiStorage = $this->getStorage(); $sessionId = $this->getServiceCallId(); if ($qtiStorage->exists($sessionId) === false) { common_Logger::i("Instantiating QTI Assessment Test Session"); $this->setTestSession($qtiStorage->instantiate($this->getTestDefinition(), $sessionId)); $testTaker = \common_session_SessionManager::getSession()->getUser(); taoQtiTest_helpers_TestRunnerUtils::setInitialOutcomes($this->getTestSession(), $testTaker); } else { common_Logger::i("Retrieving QTI Assessment Test Session '{$sessionId}'..."); $this->setTestSession($qtiStorage->retrieve($this->getTestDefinition(), $sessionId)); } taoQtiTest_helpers_TestRunnerUtils::preserveOutcomes($this->getTestSession()); }
/** * Builds the map of an assessment test * @param RunnerServiceContext $context The test context * @param RunnerConfig $config The runner config * @return mixed */ public function getMap(RunnerServiceContext $context, RunnerConfig $config) { $map = ['parts' => [], 'jumps' => []]; // get config for the sequence number option $reviewConfig = $config->getConfigValue('review'); $checkInformational = $config->getConfigValue('checkInformational'); $forceTitles = !empty($reviewConfig['forceTitle']); $uniqueTitle = isset($reviewConfig['itemTitle']) ? $reviewConfig['itemTitle'] : '%d'; /* @var AssessmentTestSession $session */ $session = $context->getTestSession(); if ($session->isRunning() !== false) { $route = $session->getRoute(); $store = $session->getAssessmentItemSessionStore(); $routeItems = $route->getAllRouteItems(); $offset = $route->getRouteItemPosition($routeItems[0]); $offsetPart = 0; $offsetSection = 0; $lastPart = null; $lastSection = null; /** @var \qtism\runtime\tests\RouteItem $routeItem */ foreach ($routeItems as $routeItem) { // access the item reference $itemRef = $routeItem->getAssessmentItemRef(); $occurrence = $routeItem->getOccurence(); // get the jump definition $itemSession = $store->getAssessmentItemSession($itemRef, $occurrence); // load item infos $testPart = $routeItem->getTestPart(); $partId = $testPart->getIdentifier(); $section = $routeItem->getAssessmentSection(); $sectionId = $section->getIdentifier(); $itemId = $itemRef->getIdentifier(); $itemUri = strstr($itemRef->getHref(), '|', true); $item = new \core_kernel_classes_Resource($itemUri); if ($lastPart != $partId) { $offsetPart = 0; $lastPart = $partId; } if ($lastSection != $sectionId) { $offsetSection = 0; $lastSection = $sectionId; } if ($forceTitles) { $label = sprintf($uniqueTitle, $offsetSection + 1); } else { $label = $item->getLabel(); } $itemInfos = ['id' => $itemId, 'uri' => $itemUri, 'label' => $label, 'position' => $offset, 'positionInPart' => $offsetPart, 'positionInSection' => $offsetSection, 'index' => $offsetSection + 1, 'occurrence' => $occurrence, 'remainingAttempts' => $itemSession->getRemainingAttempts(), 'answered' => TestRunnerUtils::isItemCompleted($routeItem, $itemSession), 'flagged' => TestRunnerUtils::getItemFlag($session, $routeItem), 'viewed' => $itemSession->isPresented()]; if ($checkInformational) { $itemInfos['informational'] = TestRunnerUtils::isItemInformational($routeItem, $itemSession); } // update the map $map['jumps'][] = ['identifier' => $itemId, 'section' => $sectionId, 'part' => $partId, 'position' => $offset, 'uri' => $itemUri]; if (!isset($map['parts'][$partId])) { $map['parts'][$partId]['id'] = $partId; $map['parts'][$partId]['label'] = $partId; $map['parts'][$partId]['position'] = $offset; $map['parts'][$partId]['isLinear'] = $testPart->getNavigationMode() == NavigationMode::LINEAR; } if (!isset($map['parts'][$partId]['sections'][$sectionId])) { $map['parts'][$partId]['sections'][$sectionId]['id'] = $sectionId; $map['parts'][$partId]['sections'][$sectionId]['label'] = $section->getTitle(); $map['parts'][$partId]['sections'][$sectionId]['position'] = $offset; } $map['parts'][$partId]['sections'][$sectionId]['items'][$itemId] = $itemInfos; // update the stats $this->updateStats($map, $itemInfos); $this->updateStats($map['parts'][$partId], $itemInfos); $this->updateStats($map['parts'][$partId]['sections'][$sectionId], $itemInfos); $offset++; $offsetPart++; $offsetSection++; } } return $map; }
/** * Action to call to comment an item. * */ public function comment() { $this->beforeAction(); $testSession = $this->getTestSession(); $resultServer = taoResultServer_models_classes_ResultServerStateFull::singleton(); $transmitter = new taoQtiCommon_helpers_ResultTransmitter($resultServer); // prepare transmission Id for result server. $item = $testSession->getCurrentAssessmentItemRef()->getIdentifier(); $occurence = $testSession->getCurrentAssessmentItemRefOccurence(); $sessionId = $testSession->getSessionId(); $transmissionId = "{$sessionId}.{$item}.{$occurence}"; // retrieve comment's intrinsic value. $comment = $this->getRequestParameter('comment'); // build variable and send it. $itemUri = taoQtiTest_helpers_TestRunnerUtils::getCurrentItemUri($testSession); $testUri = $testSession->getTest()->getUri(); $variable = new ResponseVariable('comment', Cardinality::SINGLE, BaseType::STRING, new String($comment)); $transmitter->transmitItemVariable($variable, $transmissionId, $itemUri, $testUri); }
/** * Flag an item */ public function flagItem() { $code = 200; try { $serviceContext = $this->getServiceContext(); $testSession = $serviceContext->getTestSession(); if ($this->hasRequestParameter('position')) { $itemPosition = intval($this->getRequestParameter('position')); } else { $itemPosition = $testSession->getRoute()->getPosition(); } if ($this->hasRequestParameter('flag')) { $flag = $this->getRequestParameter('flag'); if (is_numeric($flag)) { $flag = !!intval($flag); } else { $flag = 'false' != strtolower($flag); } } else { $flag = true; } TestRunnerUtils::setItemFlag($testSession, $itemPosition, $flag); $response = ['success' => true]; } catch (common_Exception $e) { $response = $this->getErrorResponse($e); $code = $this->getErrorCode($e); } $this->returnJson($response, $code); }