Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
bheyser committed Aug 21, 2015
1 parent f501c1d commit 7d3f424
Show file tree
Hide file tree
Showing 6 changed files with 316 additions and 11 deletions.
30 changes: 26 additions & 4 deletions Modules/Test/classes/class.ilTestOutputGUI.php
Original file line number Diff line number Diff line change
Expand Up @@ -324,10 +324,12 @@ protected function redirectQuestionCmd()

$objectivesAdapter->notifyTestStart($this->testSession, $this->object->getId());
$objectivesAdapter->prepareTestPass($this->testSession, $this->testSequence);

$objectivesAdapter->buildQuestionRelatedObjectiveList(
$this->questionRelatedObjectivesList
);
$objectivesAdapter->buildQuestionRelatedObjectiveList($this->questionRelatedObjectivesList);

if( $this->testSequence->hasOptionalQuestions() )
{
$this->adoptUserSolutionsFromPreviousPass();
}
}

$active_time_id = $this->object->startWorkingTime($this->testSession->getActiveId(), $this->testSession->getPass());
Expand Down Expand Up @@ -974,4 +976,24 @@ protected function performCustomRedirect()

ilUtil::redirect($redirectTarget);
}

protected function adoptUserSolutionsFromPreviousPass()
{
global $ilDB, $ilUser;

$assSettings = new ilSetting('assessment');

include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
$isAssessmentLogEnabled = ilObjAssessmentFolder::_enabledAssessmentLogging();

require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionUserSolutionAdopter.php';
$userSolutionAdopter = new ilAssQuestionUserSolutionAdopter($ilDB, $assSettings, $isAssessmentLogEnabled);

$userSolutionAdopter->setUserId($ilUser->getId());
$userSolutionAdopter->setActiveId($this->testSession->getActiveId());
$userSolutionAdopter->setTargetPass($this->testSequence->getPass());
$userSolutionAdopter->setQuestionIds($this->testSequence->getOptionalQuestions());

$userSolutionAdopter->perform();
}
}
7 changes: 6 additions & 1 deletion Modules/Test/classes/class.ilTestSequence.php
Original file line number Diff line number Diff line change
Expand Up @@ -707,7 +707,12 @@ public function hasOptionalQuestions()
{
return (bool)count($this->optionalQuestions);
}


public function getOptionalQuestions()
{
return $this->optionalQuestions;
}

public function clearOptionalQuestions()
{
$this->optionalQuestions = array();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,14 @@ public function releaseUserTestResultUpdateLock()
{
// overwrite method in concrete locker if something to do
}

public function requestUserSolutionAdoptLock()
{
// overwrite method in concrete locker if something to do
}

public function releaseUserSolutionAdoptLock()
{
// overwrite method in concrete locker if something to do
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,18 @@ private function getTablesUsedDuringAssessmentLog()
array('name' => 'ass_log', 'type' => ilDB::LOCK_WRITE, 'sequence' => true)
);
}

public function requestUserSolutionUpdateLock()
private function getTablesUsedDuringSolutionUpdate()
{
$tables = array(
return array(
array('name' => 'tst_solutions', 'type' => ilDB::LOCK_WRITE),
array('name' => 'tst_solutions', 'type' => ilDB::LOCK_WRITE, 'sequence' => true)
);
}

public function requestUserSolutionUpdateLock()
{
$tables = $this->getTablesUsedDuringSolutionUpdate();

if( $this->isAssessmentLogEnabled() )
{
Expand All @@ -67,6 +72,18 @@ public function releaseUserSolutionUpdateLock()
$this->db->unlockTables();
}

public function requestUserSolutionAdoptLock()
{
$this->db->lockTables(
$this->getTablesUsedDuringSolutionUpdate()
);
}

public function releaseUserSolutionAdoptLock()
{
$this->db->unlockTables();
}

public function requestUserQuestionResultUpdateLock()
{
$this->db->lockTables(array(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*/
class ilAssQuestionProcessLockerFile extends ilAssQuestionProcessLocker
{
const PROCESS_NAME_PERSIST_WORKING_STATE = 'persistWorkingState';
const PROCESS_NAME_QUESTION_WORKING_STATE_UPDATE = 'questionWorkingStateUpdate';

/**
* @var ilAssQuestionProcessLockFileStorage
Expand All @@ -34,12 +34,22 @@ public function __construct(ilAssQuestionProcessLockFileStorage $lockFileStorage

public function requestPersistWorkingStateLock()
{
$this->requestLock(self::PROCESS_NAME_PERSIST_WORKING_STATE);
$this->requestLock(self::PROCESS_NAME_QUESTION_WORKING_STATE_UPDATE);
}

public function releasePersistWorkingStateLock()
{
$this->releaseLock(self::PROCESS_NAME_PERSIST_WORKING_STATE);
$this->releaseLock(self::PROCESS_NAME_QUESTION_WORKING_STATE_UPDATE);
}

public function requestUserSolutionAdoptLock()
{
$this->requestLock(self::PROCESS_NAME_QUESTION_WORKING_STATE_UPDATE);
}

public function releaseUserSolutionAdoptLock()
{
$this->releaseLock(self::PROCESS_NAME_QUESTION_WORKING_STATE_UPDATE);
}

private function requestLock($processName)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
<?php
/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */


/**
* @author Björn Heyser <[email protected]>
* @version $Id$
*
* @package Modules/TestQuestionPool
*/
class ilAssQuestionUserSolutionAdopter
{
/**
* @var ressource
*/
protected static $preparedDeleteSolutionRecordsStatement = null;

/**
* @var ressource
*/
protected static $preparedSelectSolutionRecordsStatement = null;

/**
* @var ressource
*/
protected static $preparedInsertSolutionRecordStatement = null;

/**
* @var ilDB
*/
protected $db;

/**
* @var ilAssQuestionProcessLockerFactory
*/
protected $processLockerFactory;

/**
* @var integer
*/
protected $userId;

/**
* @var integer
*/
protected $activeId;

/**
* @var integer
*/
protected $targetPass;

/**
* @var array
*/
protected $questionIds;

/**
* @param ilDB $db
* @param ilSetting $assSettings
* @param bool $isAssessmentLogEnabled
*/
public function __construct(ilDB $db, ilSetting $assSettings, $isAssessmentLogEnabled)
{
$this->db = $db;

$this->userId = null;
$this->activeId = null;
$this->targetPass = null;
$this->questionIds = array();

require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionProcessLockerFactory.php';
$this->processLockerFactory = new ilAssQuestionProcessLockerFactory($assSettings, $db);
$this->processLockerFactory->setAssessmentLogEnabled($isAssessmentLogEnabled);
}

/**
* @return int
*/
public function getUserId()
{
return $this->userId;
}

/**
* @param int $userId
*/
public function setUserId($userId)
{
$this->userId = $userId;
}

/**
* @return int
*/
public function getActiveId()
{
return $this->activeId;
}

/**
* @param int $activeId
*/
public function setActiveId($activeId)
{
$this->activeId = $activeId;
}

/**
* @return int
*/
public function getTargetPass()
{
return $this->targetPass;
}

/**
* @param int $targetPass
*/
public function setTargetPass($targetPass)
{
$this->targetPass = $targetPass;
}

/**
* @return array
*/
public function getQuestionIds()
{
return $this->questionIds;
}

/**
* @param array $questionIds
*/
public function setQuestionIds($questionIds)
{
$this->questionIds = $questionIds;
}

public function perform()
{
$this->processLockerFactory->setUserId($this->getUserId());

foreach($this->getQuestionIds() as $questionId)
{
$this->processLockerFactory->setQuestionId($questionId);
$processLocker = $this->processLockerFactory->getLocker();

$processLocker->requestUserSolutionAdoptLock();

$this->resetTargetSolution($questionId);
$this->adoptSourceSolution($questionId);

$processLocker->releaseUserSolutionAdoptLock();
}
}

protected function resetTargetSolution($questionId)
{
$this->db->execute(
$this->getPreparedDeleteSolutionRecordsStatement(),
array($this->getActiveId(), $questionId, $this->getTargetPass())
);
}

protected function adoptSourceSolution($questionId)
{
$res = $this->db->execute(
$this->getPreparedSelectSolutionRecordsStatement(),
array($this->getActiveId(), $questionId, $this->getTargetPass())
);

$currentPass = null;

while($row = $this->db->fetchAssoc($res))
{
if($currentPass === null)
{
$currentPass = $row['pass'];
}
elseif($row['pass'] < $currentPass)
{
break;
}

$solutionId = $this->db->nextId('tst_solutions');

$this->db->execute($this->getPreparedInsertSolutionRecordStatement(), array(
$solutionId, $this->getActiveId(), $questionId, $this->getTargetPass(), time(),
$row['points'], $row['value1'], $row['value2']
));
}
}

protected function getPreparedDeleteSolutionRecordsStatement()
{
if( self::$preparedDeleteSolutionRecordsStatement === null )
{
self::$preparedDeleteSolutionRecordsStatement = $this->db->prepareManip(
"DELETE FROM tst_solutions WHERE active_fi = ? AND question_fi = ? AND pass = ?",
array('integer', 'integer', 'integer')
);
}

return self::$preparedDeleteSolutionRecordsStatement;
}

protected function getPreparedSelectSolutionRecordsStatement()
{
if( self::$preparedSelectSolutionRecordsStatement === null )
{
self::$preparedSelectSolutionRecordsStatement = $this->db->prepare(
"SELECT FROM tst_solutions WHERE active_fi = ? AND question_fi = ? AND pass < ? ORDER BY pass DESC",
array('integer', 'integer', 'integer')
);
}

return self::$preparedSelectSolutionRecordsStatement;
}

protected function getPreparedInsertSolutionRecordStatement()
{
if( self::$preparedInsertSolutionRecordStatement === null )
{
$query = "
INSERT INTO tst_solutions (
solution_id, active_fi, question_fi, pass, tstamp, points, value1, value2
) VALUES (
?, ?, ?, ?, ?, ?, ?, ?
)
";

self::$preparedInsertSolutionRecordStatement = $this->db->prepareManip(
$query, array('integer', 'integer', 'integer', 'integer', 'integer', 'integer', 'text', 'text')
);
}

return self::$preparedInsertSolutionRecordStatement;
}
}

0 comments on commit 7d3f424

Please sign in to comment.