Skip to content

Commit

Permalink
Merge pull request #726 from oat-sa/release-5.62.0
Browse files Browse the repository at this point in the history
Release 5.62.0
  • Loading branch information
krampstudio authored Feb 3, 2017
2 parents 4b181e0 + f00c4e5 commit aabf8f1
Show file tree
Hide file tree
Showing 72 changed files with 5,863 additions and 1,421 deletions.
151 changes: 107 additions & 44 deletions actions/class.Runner.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
*/

use oat\taoQtiTest\models\runner\QtiRunnerService;
use oat\taoQtiTest\models\runner\RunnerServiceContext;
use oat\taoQtiTest\models\runner\QtiRunnerServiceContext;
use oat\taoQtiTest\models\runner\QtiRunnerClosedException;
use oat\taoQtiTest\models\runner\QtiRunnerPausedException;
Expand Down Expand Up @@ -372,56 +373,99 @@ public function getItem()

try {
$serviceContext = $this->getServiceContext();
$route = $serviceContext->getTestSession()->getRoute();

$stateId = $this->getStateId();
$itemState = $this->runnerService->getItemState($serviceContext, $stateId);
if (!count($itemState)) {
$itemState = new stdClass();
//verify the parameter
if($route->current()->getAssessmentItemRef()->getHref() != $itemRef){
throw new \common_exception_Unauthorized('Attempt to get another item');
}

// TODO: make a better implementation
// As the rubric blocs are nested at the section level, it could be interesting to send these
// rubric blocs only once per section
if (count($serviceContext->getTestSession()->getRoute()->current()->getRubricBlockRefs())) {
$rubrics = $this->runnerService->getRubrics($serviceContext);
} else {
$rubrics = null;
//load item data
$response = $this->getItemDataResponse($serviceContext, $itemRef, $this->getStateId());

//start the timer
$this->runnerService->startTimer($serviceContext);

} catch (common_Exception $e) {
$response = $this->getErrorResponse($e);
$code = $this->getErrorCode($e);
}

$this->returnJson($response, $code);
}

/**
* Provides the definition data and the state of the
* next item.
*/
public function getNextItemData()
{
$code = 200;

try {

$allowed = $this->runnerService->getTestConfig()->getConfigValue('allowBrowseNextItem');
if(!$allowed){
\common_Logger::w("Attempt to disclose the next item whitout the configuration");
throw new \common_exception_Unauthorized();
}
$serviceContext = $this->getServiceContext();
$session = $serviceContext->getTestSession();
$route = $session->getRoute();

if(!$route->isLast()){

$itemData = $this->runnerService->getItemData($serviceContext, $itemRef);
$baseUrl = $this->runnerService->getItemPublicUrl($serviceContext, $itemRef);
if (is_string($itemData)) {
$response = '{' .
'"success":true,' .
'"token":"' . $this->getCsrf()->getCsrfToken() . '",' .
'"baseUrl":"'.$baseUrl.'",' .
'"itemData":' . $itemData . ',' .
'"itemState":' . json_encode($itemState) . ',' .
'"rubrics":' . json_encode($rubrics) .
'}';
$assessmentItemRef = $route->getNext()->getAssessmentItemRef();
$itemRef = $assessmentItemRef->getHref();
$stateId = $serviceContext->getTestExecutionUri() . $assessmentItemRef->getIdentifier();

$response = $this->getItemDataResponse($serviceContext, $itemRef, $stateId);
if(is_array($response)){
$response['itemDefinition'] = $itemRef;
}
} else {
$response = [
'success' => true,
'itemData' => $itemData,
'itemState' => $itemState,
'baseUrl' => $baseUrl,
'rubrics' => $rubrics
'success' => true
];
}

$this->runnerService->startTimer($serviceContext);

} catch (common_Exception $e) {
\common_Logger::e($e);
$response = $this->getErrorResponse($e);
$code = $this->getErrorCode($e);
}
if (is_string($response)) {
header(HTTPToolkit::statusCodeHeader($code));
Context::getInstance()->getResponse()->setContentHeader('application/json');
echo $response;
} else {
$this->returnJson($response, $code);

$this->returnJson($response, $code);
}

/**
* Create the item definition response for a given item
* @param RunnerServiceContext $context the current test context
* @param string $itemRef the item definition
* @param sttring $stateId
* @return array the item data
*/
protected function getItemDataResponse(RunnerServiceContext $context, $itemRef, $stateId)
{
$itemData = $this->runnerService->getItemData($context, $itemRef);
$baseUrl = $this->runnerService->getItemPublicUrl($context, $itemRef);
$rubrics = $this->runnerService->getRubrics($context);
if(strlen(trim($rubrics))){
$rubrics = null;
}

$itemState = $this->runnerService->getItemState($context, $stateId);
if (!count($itemState)) {
$itemState = new stdClass();
}

return [
'success' => true,
'baseUrl' => $baseUrl,
'itemData' => $itemData,
'itemState' => $itemState,
'rubrics' => $rubrics
];
}

/**
Expand Down Expand Up @@ -449,7 +493,7 @@ public function submitItem()

try {
// get the service context, but do not perform the test state check,
// as we need to store the item state whatever the test state is
// as we need to store the item state whatever the test state is
$serviceContext = $this->getServiceContext(false);

if (!$this->runnerService->isTerminated($serviceContext)) {
Expand Down Expand Up @@ -490,16 +534,16 @@ public function submitItem()
} else {
// we need a complete service context in order to build the test context
$serviceContext->init();

$response = [
'success' => true,
'notAllowed' => true,
'message' => __('A response to this item is required.'),

// send an updated version of the test context
'testContext' => $this->runnerService->getTestContext($serviceContext),
];

// start the timer only after context build to avoid timing error
$this->runnerService->startTimer($serviceContext);
}
Expand All @@ -519,9 +563,10 @@ public function move()
{
$code = 200;

$ref = $this->getRequestParameter('ref');
$ref = $this->getRequestParameter('ref');
$direction = $this->getRequestParameter('direction');
$scope = $this->getRequestParameter('scope');
$scope = $this->getRequestParameter('scope');
$start = $this->hasRequestParameter('start');

try {
$serviceContext = $this->getServiceContext();
Expand All @@ -536,8 +581,17 @@ public function move()
$response['testContext'] = $this->runnerService->getTestContext($serviceContext);
}

\common_Logger::d('Test session state : ' . $serviceContext->getTestSession()->getState());

$this->runnerService->persist($serviceContext);

if($start == true){

// start the timer only when move starts the item session
// and after context build to avoid timing error
$this->runnerService->startTimer($serviceContext);
}

} catch (common_Exception $e) {
$response = $this->getErrorResponse($e);
$code = $this->getErrorCode($e);
Expand All @@ -546,17 +600,19 @@ public function move()
$this->returnJson($response, $code);
}


/**
* Skip the current position to the provided scope: item, section, part
*/
public function skip()
{
$code = 200;

$ref = $this->getRequestParameter('ref');
$scope = $this->getRequestParameter('scope');
$itemDuration = $this->getRequestParameter('itemDuration');
$ref = $this->getRequestParameter('ref');
$scope = $this->getRequestParameter('scope');
$itemDuration = $this->getRequestParameter('itemDuration');
$consumedExtraTime = $this->getRequestParameter('consumedExtraTime');
$start = $this->hasRequestParameter('start');

try {
$serviceContext = $this->getServiceContext();
Expand All @@ -574,6 +630,12 @@ public function skip()

$this->runnerService->persist($serviceContext);

if($start == true){

// start the timer only when move starts the item session
// and after context build to avoid timing error
$this->runnerService->startTimer($serviceContext);
}
} catch (common_Exception $e) {
$response = $this->getErrorResponse($e);
$code = $this->getErrorCode($e);
Expand All @@ -582,6 +644,7 @@ public function skip()
$this->returnJson($response, $code);
}


/**
* Handles a test timeout
*/
Expand Down
22 changes: 21 additions & 1 deletion config/default/testRunner.conf.php
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,26 @@
'dialog' => [
'accept' => 'Enter',
'reject' => 'Esc'
]
],
'magnifier' => array(
'toggle' => 'L',
'in' => 'Shift+I',
'out' => 'Shift+O',
'close' => 'esc'
),
'highlighter' => array(
'toggle' => 'Shift+U'
),
'area-masking' => array(
'toggle' => 'Y'
)
],

/**
* Allows to browse the next item (before it is displayed).
* The is required for caching scenarios
* @type boolean
*/
'allow-browse-next-item' => false

);
6 changes: 3 additions & 3 deletions manifest.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@
'label' => 'QTI test model',
'description' => 'TAO QTI test implementation',
'license' => 'GPL-2.0',
'version' => '5.58.1',
'version' => '5.62.0',
'author' => 'Open Assessment Technologies',
'requires' => array(
'taoTests' => '>=3.7.0',
'taoQtiItem' => '>=6.8.0',
'tao' => '>=7.42.0'
'taoQtiItem' => '>=6.12.0',
'tao' => '>=7.57.0'
),
'models' => array(
'http://www.tao.lu/Ontologies/TAOTest.rdf'
Expand Down
7 changes: 2 additions & 5 deletions models/classes/class.QtiTestService.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
use oat\oatbox\filesystem\FileSystemService;
use oat\oatbox\filesystem\File;
use oat\oatbox\filesystem\Directory;
use oat\taoQtiItem\model\qti\Service;

/**
* the QTI TestModel service.
Expand Down Expand Up @@ -826,16 +827,13 @@ private function setItemsToDoc(XmlDocument $doc, array $items, $sectionIndex = 0
}
$section = $sections[$sectionIndex];

$itemContentProperty = new core_kernel_classes_Property(TAO_ITEM_CONTENT_PROPERTY);
$itemRefs = new SectionPartCollection();
$itemRefIdentifiers = array();
foreach ($items as $itemResource) {
$itemContent = new core_kernel_file_File($itemResource->getUniquePropertyValue($itemContentProperty));

$itemDoc = new XmlDocument();

try {
$itemDoc->load($itemContent->getAbsolutePath());
$itemDoc->loadFromString(Service::singleton()->getXmlByRdfItem($itemResource));
}
catch (StorageException $e) {
// We consider the item not compliant with QTI, let's try the next one.
Expand All @@ -852,7 +850,6 @@ private function setItemsToDoc(XmlDocument $doc, array $items, $sectionIndex = 0
$itemRefIdentifiers[$itemRefIdentifier] = 0;
}
$itemRefs[] = new AssessmentItemRef($itemRefIdentifier, $itemResource->getUri());

}
$section->setSectionParts($itemRefs);

Expand Down
11 changes: 7 additions & 4 deletions models/classes/runner/QtiRunnerService.php
Original file line number Diff line number Diff line change
Expand Up @@ -443,14 +443,15 @@ public function getTestMap(RunnerServiceContext $context)
/**
* Gets the rubrics related to the current session state.
* @param RunnerServiceContext $context
* @param string $itemRef (optional) otherwise use the current
* @return mixed
* @throws \common_Exception
*/
public function getRubrics(RunnerServiceContext $context)
public function getRubrics(RunnerServiceContext $context, $itemRef = null)
{
if ($context instanceof QtiRunnerServiceContext) {
$map = new QtiRunnerRubric();
return $map->getRubrics($context);
$rubricHelper = new QtiRunnerRubric();
return $rubricHelper->getRubrics($context, $itemRef);
} else {
throw new \common_exception_InvalidArgumentType(
'QtiRunnerService',
Expand Down Expand Up @@ -1277,7 +1278,9 @@ public function startTimer(RunnerServiceContext $context)
if ($context instanceof QtiRunnerServiceContext) {
/* @var TestSession $session */
$session = $context->getTestSession();
$session->startItemTimer();
if($session->getState() === AssessmentTestSessionState::INTERACTING) {
$session->startItemTimer();
}
} else {
throw new \common_exception_InvalidArgumentType(
'QtiRunnerService',
Expand Down
3 changes: 2 additions & 1 deletion models/classes/runner/RunnerService.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,11 @@ public function getTestMap(RunnerServiceContext $context);
/**
* Gets the rubrics related to the current session state
* @param RunnerServiceContext $context
* @param string $itemRef (optional) otherwise use the current
* @return mixed
* @throws \common_Exception
*/
public function getRubrics(RunnerServiceContext $context);
public function getRubrics(RunnerServiceContext $context, $itemRef = null);

/**
* Gets definition data of a particular item
Expand Down
1 change: 1 addition & 0 deletions models/classes/runner/config/QtiRunnerConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ protected function buildConfig() {
'enableUnansweredItemsWarning' => isset($rawConfig['test-taker-unanswered-items-message']) ? $rawConfig['test-taker-unanswered-items-message'] : true,
'allowShortcuts' => !empty($rawConfig['allow-shortcuts']),
'shortcuts' => isset($rawConfig['shortcuts']) ? $rawConfig['shortcuts'] : [],
'allowBrowseNextItem' => isset($rawConfig['allow-browse-next-item']) ? $rawConfig['allow-browse-next-item'] : false,
];
}

Expand Down
Loading

0 comments on commit aabf8f1

Please sign in to comment.