tao-test/app/taoQtiTest/models/classes/runner/QtiRunnerServiceContext.php

1035 lines
32 KiB
PHP

<?php
/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2017 (original work) Open Assessment Technologies SA ;
*/
/**
* @author Jean-Sébastien Conan <jean-sebastien.conan@vesperiagroup.com>
*/
namespace oat\taoQtiTest\models\runner;
use oat\libCat\CatSession;
use oat\libCat\Exception\CatEngineException;
use oat\libCat\result\AbstractResult;
use oat\libCat\result\ItemResult;
use oat\taoDelivery\model\execution\DeliveryServerService;
use oat\taoQtiTest\helpers\TestSessionMemento;
use oat\taoQtiTest\models\CompilationDataService;
use oat\taoQtiTest\models\event\QtiTestChangeEvent;
use oat\taoQtiTest\models\QtiTestCompilerIndex;
use oat\taoQtiTest\models\runner\session\TestSession;
use oat\taoQtiTest\models\SessionStateService;
use oat\taoQtiTest\models\cat\CatService;
use oat\taoQtiTest\models\ExtendedStateService;
use oat\taoQtiTest\models\SectionPauseService;
use oat\tao\helpers\UserHelper;
use qtism\data\AssessmentTest;
use qtism\data\AssessmentItemRef;
use qtism\data\NavigationMode;
use qtism\runtime\storage\binary\AbstractQtiBinaryStorage;
use qtism\runtime\storage\binary\BinaryAssessmentTestSeeker;
use qtism\runtime\tests\AssessmentTestSession;
use qtism\runtime\tests\RouteItem;
use oat\oatbox\event\EventManager;
use oat\taoQtiTest\models\event\SelectAdaptiveNextItemEvent;
use oat\libCat\result\ResultVariable;
use taoQtiTest_models_classes_QtiTestService;
/**
* Class QtiRunnerServiceContext
*
* Defines a container to store and to share runner service context of the QTI implementation
*
* @package oat\taoQtiTest\models
*/
class QtiRunnerServiceContext extends RunnerServiceContext
{
/**
* The session storage
* @var AbstractQtiBinaryStorage
*/
protected $storage;
/**
* @var \taoQtiTest_helpers_SessionManager
*/
protected $sessionManager;
/**
* The assessment test definition
* @var AssessmentTest
*/
protected $testDefinition;
/**
* The path of the compilation directory.
*
* @var \tao_models_classes_service_StorageDirectory[]
*/
protected $compilationDirectory;
/**
* The meta data about the test definition being executed.
*
* @var array
*/
private $testMeta;
/**
* The index of compiled items.
*
* @var QtiTestCompilerIndex
*/
private $itemIndex;
/**
* The URI of the assessment test
* @var string
*/
protected $testDefinitionUri;
/**
* The URI of the compiled delivery
* @var string
*/
protected $testCompilationUri;
/**
* The URI of the delivery execution
* @var string
*/
protected $testExecutionUri;
/**
* Whether we are in synchronization mode
* @var boolean
*/
private $syncingMode = false;
/**
* @var string
*/
private $userUri;
/**
* QtiRunnerServiceContext constructor.
*
* @param string $testDefinitionUri
* @param string $testCompilationUri
* @param string $testExecutionUri
*/
public function __construct($testDefinitionUri, $testCompilationUri, $testExecutionUri)
{
$this->testDefinitionUri = $testDefinitionUri;
$this->testCompilationUri = $testCompilationUri;
$this->testExecutionUri = $testExecutionUri;
}
/**
* Starts the context
*/
public function init()
{
$this->retrieveItemIndex();
}
/**
* Extracts the path of the compilation directory
*/
protected function initCompilationDirectory()
{
$fileStorage = \tao_models_classes_service_FileStorage::singleton();
$directoryIds = explode('|', $this->getTestCompilationUri());
$directories = [
'private' => $fileStorage->getDirectoryById($directoryIds[0]),
'public' => $fileStorage->getDirectoryById($directoryIds[1])
];
$this->compilationDirectory = $directories;
}
/**
* Loads the test definition
*/
protected function initTestDefinition()
{
$this->testDefinition = \taoQtiTest_helpers_Utils::getTestDefinition($this->getTestCompilationUri());
}
/**
* Loads the storage
* @throws \common_exception_Error
* @throws \common_ext_ExtensionException
*/
protected function initStorage()
{
/** @var DeliveryServerService $deliveryServerService */
$deliveryServerService = $this->getServiceManager()->get(DeliveryServerService::SERVICE_ID);
$resultStore = $deliveryServerService->getResultStoreWrapper($this->getTestExecutionUri());
$testResource = new \core_kernel_classes_Resource($this->getTestDefinitionUri());
$sessionManager = new \taoQtiTest_helpers_SessionManager($resultStore, $testResource);
$seeker = new BinaryAssessmentTestSeeker($this->getTestDefinition());
$userUri = $this->getUserUri();
$config = \common_ext_ExtensionsManager::singleton()->getExtensionById('taoQtiTest')->getConfig('testRunner');
$storageClassName = $config['test-session-storage'];
$this->storage = new $storageClassName($sessionManager, $seeker, $userUri);
$this->sessionManager = $sessionManager;
}
/**
* Loads the test session
* @throws \common_exception_Error
*/
protected function initTestSession()
{
$storage = $this->getStorage();
$sessionId = $this->getTestExecutionUri();
if ($storage->exists($sessionId) === false) {
\common_Logger::d("Instantiating QTI Assessment Test Session");
$this->setTestSession($storage->instantiate($this->getTestDefinition(), $sessionId));
$testTaker = $this->getTestTakerFromSessionOrRds();
\taoQtiTest_helpers_TestRunnerUtils::setInitialOutcomes($this->getTestSession(), $testTaker);
} else {
\common_Logger::d("Retrieving QTI Assessment Test Session '${sessionId}'...");
$this->setTestSession($storage->retrieve($this->getTestDefinition(), $sessionId));
}
\taoQtiTest_helpers_TestRunnerUtils::preserveOutcomes($this->getTestSession());
}
/**
* @deprecated
*/
protected function retrieveTestMeta()
{
}
/**
* Retrieves the index of compiled items.
*/
protected function retrieveItemIndex()
{
$this->itemIndex = new QtiTestCompilerIndex();
try {
$directories = $this->getCompilationDirectory();
$data = $directories['private']->read(taoQtiTest_models_classes_QtiTestService::TEST_COMPILED_INDEX);
if ($data) {
$this->itemIndex->unserialize($data);
}
} catch (\Exception $e) {
\common_Logger::d('Ignoring file not found exception for Items Index');
}
}
/**
* Sets the test session
* @param mixed $testSession
* @throws \common_exception_InvalidArgumentType
*/
public function setTestSession($testSession)
{
if ($testSession instanceof TestSession) {
parent::setTestSession($testSession);
} else {
throw new \common_exception_InvalidArgumentType(
'QtiRunnerServiceContext',
'setTestSession',
0,
'oat\taoQtiTest\models\runner\session\TestSession',
$testSession
);
}
}
/**
* Gets the session storage
* @return AbstractQtiBinaryStorage
* @throws \common_exception_Error
* @throws \common_ext_ExtensionException
*/
public function getStorage()
{
if (!$this->storage) {
$this->initStorage();
}
return $this->storage;
}
/**
* @return EventManager
* @throws \Zend\ServiceManager\Exception\ServiceNotFoundException
*/
protected function getEventManager()
{
return $this->getServiceLocator()->get(EventManager::SERVICE_ID);
}
/**
* @return \taoQtiTest_helpers_SessionManager
* @throws \common_exception_Error
* @throws \common_ext_ExtensionException
*/
public function getSessionManager()
{
if (null === $this->sessionManager) {
$this->initStorage();
}
return $this->sessionManager;
}
/**
* Gets the assessment test definition
* @return AssessmentTest
*/
public function getTestDefinition()
{
if (null === $this->testDefinition) {
$this->initTestDefinition();
}
return $this->testDefinition;
}
/**
* Gets the path of the compilation directory
* @return \tao_models_classes_service_StorageDirectory[]
*/
public function getCompilationDirectory()
{
if (null === $this->compilationDirectory) {
$this->initCompilationDirectory();
}
return $this->compilationDirectory;
}
/**
* Gets the meta data about the test definition being executed.
* @return array
*/
public function getTestMeta()
{
if (!isset($this->testMeta)) {
$directories = $this->getCompilationDirectory();
/** @var CompilationDataService $compilationDataService */
$compilationDataService = $this->getServiceLocator()->get(CompilationDataService::SERVICE_ID);
$this->testMeta = $compilationDataService->readCompilationMetadata($directories['private']);
}
return $this->testMeta;
}
/**
* Gets the URI of the assessment test
* @return string
*/
public function getTestDefinitionUri()
{
return $this->testDefinitionUri;
}
/**
* Gets the URI of the compiled delivery
* @return string
*/
public function getTestCompilationUri()
{
return $this->testCompilationUri;
}
/**
* Gets the URI of the delivery execution
* @return string
*/
public function getTestExecutionUri()
{
return $this->testExecutionUri;
}
/**
* Gets info from item index
* @param string $id
* @return mixed
* @throws \common_exception_Error
*/
public function getItemIndex($id)
{
return $this->itemIndex->getItem($id, \common_session_SessionManager::getSession()->getInterfaceLanguage());
}
/**
* @return string
* @throws \common_exception_Error
*/
public function getUserUri()
{
if ($this->userUri === null) {
$this->userUri = \common_session_SessionManager::getSession()->getUserUri();
}
return $this->userUri;
}
/**
* @param string $userUri
*/
public function setUserUri($userUri)
{
$this->userUri = $userUri;
}
/**
* Gets a particular value from item index
* @param string $id
* @param string $name
* @return mixed
* @throws \common_exception_Error
*/
public function getItemIndexValue($id, $name)
{
return $this->itemIndex->getItemValue($id, \common_session_SessionManager::getSession()->getInterfaceLanguage(), $name);
}
/**
* Get Cat Engine Implementation
*
* Get the currently configured Cat Engine implementation.
*
* @return \oat\libCat\CatEngine
*/
public function getCatEngine(RouteItem $routeItem = null)
{
$compiledDirectory = $this->getCompilationDirectory()['private'];
$adaptiveSectionMap = $this->getServiceManager()->get(CatService::SERVICE_ID)->getAdaptiveSectionMap($compiledDirectory);
$routeItem = $routeItem ? $routeItem : $this->getTestSession()->getRoute()->current();
$sectionId = $routeItem->getAssessmentSection()->getIdentifier();
$catEngine = false;
if (isset($adaptiveSectionMap[$sectionId])) {
$catEngine = $this->getServiceManager()->get(CatService::SERVICE_ID)->getEngine($adaptiveSectionMap[$sectionId]['endpoint']);
}
return $catEngine;
}
/**
* @return AssessmentTestSession
* @throws \common_exception_Error
*/
public function getTestSession()
{
if (!$this->testSession) {
$this->initTestSession();
}
return parent::getTestSession(); // TODO: Change the autogenerated stub
}
/**
* Get the current CAT Session Object.
*
* @param RouteItem|null $routeItem
* @return \oat\libCat\CatSession|false
*/
public function getCatSession(RouteItem $routeItem = null)
{
return $this->getServiceManager()->get(CatService::SERVICE_ID)->getCatSession(
$this->getTestSession(),
$this->getCompilationDirectory()['private'],
$routeItem
);
}
/**
* Persist the CAT Session Data.
*
* Persist the current CAT Session Data in storage.
*
* @param string $catSession JSON encoded CAT Session data.
* @param RouteItem|null $routeItem
* @return mixed
*/
public function persistCatSession($catSession, RouteItem $routeItem = null)
{
return $this->getServiceManager()->get(CatService::SERVICE_ID)->persistCatSession(
$catSession,
$this->getTestSession(),
$this->getCompilationDirectory()['private'],
$routeItem
);
}
/**
* Persist seen CAT Item identifiers.
*
* @param string $seenCatItemId
*/
public function persistSeenCatItemIds($seenCatItemId)
{
$sessionId = $this->getTestSession()->getSessionId();
$items = $this->getServiceManager()->get(ExtendedStateService::SERVICE_ID)->getCatValue(
$sessionId,
$this->getCatSection()->getSectionId(),
'cat-seen-item-ids'
);
if (!$items) {
$items = [];
} else {
$items = json_decode($items);
}
if (!in_array($seenCatItemId, $items)) {
$items[] = $seenCatItemId;
}
$this->getServiceManager()->get(ExtendedStateService::SERVICE_ID)->setCatValue(
$sessionId,
$this->getCatSection()->getSectionId(),
'cat-seen-item-ids',
json_encode($items)
);
}
/**
* Get Last CAT Item Output.
*
* Get the last CAT Item Result from memory.
*/
public function getLastCatItemOutput()
{
$sessionId = $this->getTestSession()->getSessionId();
$itemOutput = $this->getServiceManager()->get(ExtendedStateService::SERVICE_ID)->getCatValue(
$sessionId,
$this->getCatSection()->getSectionId(),
'cat-item-output'
);
$output = [];
if (!is_null($itemOutput)) {
$rawData = json_decode($itemOutput, true);
foreach ($rawData as $result) {
/** @var ItemResult $itemResult */
$itemResult = ItemResult::restore($result);
$output[$itemResult->getItemRefId()] = $itemResult;
}
}
return $output;
}
/**
* Persist CAT Item Output.
*
* Persist the last CAT Item Result in memory.
*/
public function persistLastCatItemOutput(array $lastCatItemOutput)
{
$sessionId = $this->getTestSession()->getSessionId();
$this->getServiceManager()->get(ExtendedStateService::SERVICE_ID)->setCatValue(
$sessionId,
$this->getCatSection()->getSectionId(),
'cat-item-output',
json_encode($lastCatItemOutput)
);
}
/**
* Get Current CAT Section.
*
* Returns the current CatSection object. In case of the current Assessment Section is not adaptive, the method
* returns the boolean false value.
*
* @return \oat\libCat\CatSection|boolean
*/
public function getCatSection(RouteItem $routeItem = null)
{
return $this->getServiceManager()->get(CatService::SERVICE_ID)->getCatSection(
$this->getTestSession(),
$this->getCompilationDirectory()['private'],
$routeItem
);
}
/**
* Is the Assessment Test Session Context Adaptive.
*
* Determines whether or not the current Assessment Test Session is in an adaptive context.
*
* @param AssessmentItemRef $currentAssessmentItemRef (optional) An AssessmentItemRef object to be considered as the current assessmentItemRef.
* @return boolean
*/
public function isAdaptive(AssessmentItemRef $currentAssessmentItemRef = null)
{
return $this->getServiceManager()->get(CatService::SERVICE_ID)->isAdaptive($this->getTestSession(), $currentAssessmentItemRef);
}
/**
* Contains Adaptive Content.
*
* Whether or not the current Assessment Test Session has some adaptive contents.
*
* @return boolean
*/
public function containsAdaptive()
{
$adaptiveSectionMap = $this->getServiceManager()->get(CatService::SERVICE_ID)->getAdaptiveSectionMap($this->getCompilationDirectory()['private']);
return !empty($adaptiveSectionMap);
}
/**
* Select the next Adaptive Item and store the retrieved results from CAT engine
*
* Ask the CAT Engine for the Next Item to be presented to the candidate, depending on the last
* CAT Item ID and last CAT Item Output currently stored.
*
* This method returns a CAT Item ID in case of the CAT Engine returned one. Otherwise, it returns
* null meaning that there is no CAT Item to be presented.
*
* @return mixed|null
* @throws \common_Exception
*/
public function selectAdaptiveNextItem()
{
$lastItemId = $this->getCurrentCatItemId();
$lastOutput = $this->getLastCatItemOutput();
$catSession = $this->getCatSession();
$preSelection = $catSession->getTestMap();
try {
if (!$this->syncingMode) {
$selection = $catSession->getTestMap(array_values($lastOutput));
if (!$this->saveAdaptiveResults($catSession)) {
\common_Logger::w('Unable to save CatService results.');
}
$isShadowItem = false;
} else {
$selection = $catSession->getTestMap();
$isShadowItem = true;
}
} catch (CatEngineException $e) {
\common_Logger::e('Error during CatEngine processing. ' . $e->getMessage());
$selection = $catSession->getTestMap();
$isShadowItem = true;
}
$event = new SelectAdaptiveNextItemEvent($this->getTestSession(), $lastItemId, $preSelection, $selection, $isShadowItem);
$this->getServiceManager()->get(EventManager::SERVICE_ID)->trigger($event);
$this->persistCatSession($catSession);
if (is_array($selection) && count($selection) > 0) {
\common_Logger::d("New CAT item selection is '" . implode(', ', $selection) . "'.");
return $selection[0];
} else {
\common_Logger::d('No new CAT item selection.');
return null;
}
}
/**
* Get Current AssessmentItemRef object.
*
* This method returns the current AssessmentItemRef object depending on the test $context.
*
* @return \qtism\data\ExtendedAssessmentItemRef|false
*/
public function getCurrentAssessmentItemRef()
{
if ($this->isAdaptive()) {
return $this->getServiceManager()->get(CatService::SERVICE_ID)->getAssessmentItemRefByIdentifier(
$this->getCompilationDirectory()['private'],
$this->getCurrentCatItemId()
);
} else {
return $this->getTestSession()->getCurrentAssessmentItemRef();
}
}
public function getPreviouslySeenCatItemIds(RouteItem $routeItem = null)
{
return $this->getServiceManager()->get(CatService::SERVICE_ID)->getPreviouslySeenCatItemIds(
$this->getTestSession(),
$this->getCompilationDirectory()['private'],
$routeItem
);
}
public function getShadowTest(RouteItem $routeItem = null)
{
return $this->getServiceManager()->get(CatService::SERVICE_ID)->getShadowTest(
$this->getTestSession(),
$this->getCompilationDirectory()['private'],
$routeItem
);
}
public function getCurrentCatItemId(RouteItem $routeItem = null)
{
return $this->getServiceManager()->get(CatService::SERVICE_ID)->getCurrentCatItemId(
$this->getTestSession(),
$this->getCompilationDirectory()['private'],
$routeItem
);
}
public function persistCurrentCatItemId($catItemId)
{
$session = $this->getTestSession();
$sessionId = $session->getSessionId();
$this->getServiceManager()->get(ExtendedStateService::SERVICE_ID)->setCatValue(
$sessionId,
$this->getCatSection()->getSectionId(),
'current-cat-item-id',
$catItemId
);
$event = new QtiTestChangeEvent($session, new TestSessionMemento($session));
$this->getServiceManager()->propagate($event);
$this->getEventManager()->trigger($event);
}
public function getItemPositionInRoute($refId, &$catItemId = '')
{
$route = $this->getTestSession()->getRoute();
$routeCount = $route->count();
$i = 0;
$j = 0;
while ($i < $routeCount) {
$routeItem = $route->getRouteItemAt($i);
if ($this->isAdaptive($routeItem->getAssessmentItemRef())) {
$shadow = $this->getShadowTest($routeItem);
for ($k = 0; $k < count($shadow); $k++) {
if ($j == $refId) {
$catItemId = $shadow[$k];
break 2;
}
$j++;
}
} else {
if ($j == $refId) {
break;
}
$j++;
}
$i++;
}
return $i;
}
/**
* Get Real Current Position.
*
* This method returns the real position of the test taker within
* the item flow, by considering CAT sections.
*
* @return integer A zero-based index.
*/
public function getCurrentPosition()
{
$route = $this->getTestSession()->getRoute();
$routeCount = $route->count();
$routeItemPosition = $route->getPosition();
$currentRouteItem = $route->getRouteItemAt($routeItemPosition);
$finalPosition = 0;
for ($i = 0; $i < $routeCount; $i++) {
$routeItem = $route->getRouteItemAt($i);
if ($routeItem !== $currentRouteItem) {
if (!$this->isAdaptive($routeItem->getAssessmentItemRef())) {
$finalPosition++;
} else {
$finalPosition += count($this->getShadowTest($routeItem));
}
} else {
if ($this->isAdaptive($routeItem->getAssessmentItemRef())) {
$finalPosition += array_search(
$this->getCurrentCatItemId($routeItem),
$this->getShadowTest($routeItem)
);
}
break;
}
}
return $finalPosition;
}
public function getCatAttempts($identifier, RouteItem $routeItem = null)
{
return $this->getServiceManager()->get(CatService::SERVICE_ID)->getCatAttempts(
$this->getTestSession(),
$this->getCompilationDirectory()['private'],
$identifier,
$routeItem
);
}
public function persistCatAttempts($identifier, $attempts)
{
$sessionId = $this->getTestSession()->getSessionId();
$sectionId = $this->getCatSection()->getSectionId();
$catAttempts = $this->getServiceManager()->get(ExtendedStateService::SERVICE_ID)->getCatValue(
$sessionId,
$sectionId,
'cat-attempts'
);
$catAttempts = ($catAttempts) ? $catAttempts : [];
$catAttempts[$identifier] = $attempts;
$this->getServiceManager()->get(ExtendedStateService::SERVICE_ID)->setCatValue(
$sessionId,
$sectionId,
'cat-attempts',
$catAttempts
);
}
/**
* Can Move Backward
*
* Whether or not the Test Taker is able to navigate backward.
* This implementation takes the CAT sections into consideration.
*
* @return boolean
*/
public function canMoveBackward()
{
$moveBack = false;
$session = $this->getTestSession();
if ($this->isAdaptive()) {
$positionInCatSession = array_search(
$this->getCurrentCatItemId(),
$this->getShadowTest()
);
if ($positionInCatSession === 0) {
// First item in cat section.
if ($session->getRoute()->getPosition() !== 0) {
$moveBack = $session->getPreviousRouteItem()->getTestPart()->getNavigationMode() === NavigationMode::NONLINEAR;
}
} else {
$moveBack = $session->getRoute()->current()->getTestPart()->getNavigationMode() === NavigationMode::NONLINEAR;
}
} else {
$moveBack = $session->canMoveBackward();
//check also if the sectionPause prevents you from moving backward
if ($moveBack) {
$moveBack = $this->getServiceManager()->get(SectionPauseService::SERVICE_ID)->canMoveBackward($session);
}
}
return $moveBack;
}
/**
* Save the Cat service result for tests and items
*
* @param CatSession $catSession
* @return bool
*/
protected function saveAdaptiveResults(CatSession $catSession)
{
$testResult = $catSession->getTestResult();
$testResult = empty($testResult) ? [] : [$testResult];
return $this->storeResult(array_merge($testResult, $catSession->getItemResults()));
}
/**
* Store a Cat Result variable
*
* The result has to be an ItemResult and TestResult to embed CAT variables
* After converted them to taoResultServer variables
* Use the runner service to store the variables
*
* @param AbstractResult[] $results
* @return bool
*/
protected function storeResult(array $results)
{
/** @var QtiRunnerService $runnerService */
$runnerService = $this->getServiceLocator()->get(QtiRunnerService::SERVICE_ID);
$success = true;
try {
foreach ($results as $result) {
if (!$result instanceof AbstractResult) {
throw new \common_Exception(__FUNCTION__ . ' requires a CAT result to store it.');
}
$variables = $this->convertCatVariables($result->getVariables());
if (empty($variables)) {
\common_Logger::t('No Cat result variables to store.');
continue;
}
if ($result instanceof ItemResult) {
$itemId = $result->getItemRefId();
$itemUri = $this->getItemUriFromRefId($itemId);
} else {
$itemUri = $itemId = null;
$sectionId = $this
->getTestSession()
->getRoute()
->current()
->getAssessmentSection()
->getIdentifier();
/** @var \taoResultServer_models_classes_Variable $variable */
foreach ($variables as $variable) {
$variable->setIdentifier($sectionId . '-' . $variable->getIdentifier());
}
}
if (!$runnerService->storeVariables($this, $itemUri, $variables, $itemId)) {
$success = false;
}
}
} catch (\Exception $e) {
\common_Logger::w('An error has occurred during CAT result storing: ' . $e->getMessage());
$success = false;
}
return $success;
}
/**
* Convert CAT variables to taoResultServer variables
*
* Following the variable type, use the Runner service to get the appropriate variable
* The method manage the trace, response and outcome variable
*
* @param array $variables
* @return array
* @throws \common_exception_NotImplemented If variable type is not managed
*/
protected function convertCatVariables(array $variables)
{
/** @var QtiRunnerService $runnerService */
$runnerService = $this->getServiceLocator()->get(QtiRunnerService::SERVICE_ID);
$convertedVariables = [];
foreach ($variables as $variable) {
switch ($variable->getVariableType()) {
case ResultVariable::TRACE_VARIABLE:
$getVariableMethod = 'getTraceVariable';
break;
case ResultVariable::RESPONSE_VARIABLE:
$getVariableMethod = 'getResponseVariable';
break;
case ResultVariable::OUTCOME_VARIABLE:
$getVariableMethod = 'getOutcomeVariable';
break;
case ResultVariable::TEMPLATE_VARIABLE:
default:
$getVariableMethod = null;
break;
}
if (is_null($getVariableMethod)) {
\common_Logger::w('Variable of type ' . $variable->getVariableType() . ' is not implemented in ' . __METHOD__);
throw new \common_exception_NotImplemented();
}
$convertedVariables[] = call_user_func_array(
[$runnerService, $getVariableMethod],
[$variable->getId(), $variable->getValue()]
);
}
return $convertedVariables;
}
/**
* Get item uri associated to the given $itemId.
*
* @return string The uri
*/
protected function getItemUriFromRefId($itemId)
{
$ref = $this->getServiceManager()->get(CatService::SERVICE_ID)->getAssessmentItemRefByIdentifier(
$this->getCompilationDirectory()['private'],
$itemId
);
return explode('|', $ref->getHref())[0];
}
/**
* Are we in a synchronization mode
* @return bool
*/
public function isSyncingMode()
{
return $this->syncingMode;
}
/**
* Set/Unset the synchronization mode
* @param bool $syncing
*/
public function setSyncingMode($syncing)
{
$this->syncingMode = (bool) $syncing;
}
/**
* @return \oat\oatbox\user\User
* @throws \common_exception_Error
*/
private function getTestTakerFromSessionOrRds()
{
try {
$session = \common_session_SessionManager::getSession();
} catch (\common_exception_Error $exception) {
$session = null;
\common_Logger::w($exception->getMessage());
}
if ($session == null || $session->getUser() == null) {
$testTaker = UserHelper::getUser($this->getUserUri());
} else {
$testTaker = $session->getUser();
}
return $testTaker;
}
}