MigrationMoodle: Add task for quiz attempts - refs BT#15992

pull/3127/head
Angel Fernando Quiroz Campos 6 years ago
parent cae0864668
commit c1e2d41588
  1. 3
      plugin/migrationmoodle/admin.php
  2. 1
      plugin/migrationmoodle/lang/english.php
  3. 78
      plugin/migrationmoodle/src/Loader/UserQuizAttemptLoader.php
  4. 94
      plugin/migrationmoodle/src/Task/UsersQuizzesAttemptsTask.php
  5. 70
      plugin/migrationmoodle/src/Transformer/Property/QuizDataTracking.php

@ -104,6 +104,9 @@ $menu = [
'users_scorms_view' => [
'users_scorms_progress',
],
'users_learn_paths_quizzes' => [
'users_quizzes_attempts',
],
];
$htmlHeadXtra[] = '<style>.fa-ul {list-style-type: decimal; list-style-position: outside;}</style>';

@ -64,3 +64,4 @@ $strings['QuestionGapselectTask'] = 'Answers for gapselect questions';
$strings['UsersLearnPathsLessonBranchTask'] = 'Lesson branch to total time in learn paths documents';
$strings['UsersLearnPathsLessonAttemptsTask'] = 'Lesson attemprs to total time in learn paths quizzes';
$strings['UsersLearnPathsQuizzesTask'] = 'Question attempts of learn paths quiz';
$strings['UsersQuizzesAttemptsTask'] = 'Quiz attempts of users';

@ -0,0 +1,78 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Loader;
use Chamilo\CoreBundle\Entity\TrackEExercises;
use Chamilo\CourseBundle\Entity\CLpItemView;
use Chamilo\PluginBundle\MigrationMoodle\Interfaces\LoaderInterface;
/**
* Class UserQuizAttemptLoader.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Loader
*/
class UserQuizAttemptLoader implements LoaderInterface
{
/**
* @inheritDoc
*/
public function load(array $incomingData)
{
$view = $this->findViewByQuiz(
$incomingData['exo_id'],
$incomingData['user_id'],
$incomingData['session_id']
);
return \Database::insert(
\Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES),
[
'exe_exo_id' => $incomingData['exo_id'],
'exe_user_id' => $incomingData['user_id'],
'c_id' => $view['c_id'],
'status' => $incomingData['status'] === 'finished' ? '' : 'incomplete',
'session_id' => $incomingData['session_id'],
'data_tracking' => $incomingData['data_tracking'],
'start_date' => $incomingData['date']->format('Y-m-d H:i:s'),
'orig_lp_id' => $view['lp_id'],
'orig_lp_item_id' => $view['lp_item_id'],
'orig_lp_item_view_id' => $view['iid'],
'exe_weighting' => $incomingData['weighting'],
'user_ip' => '',
'exe_date' => $incomingData['date']->format('Y-m-d H:i:s'),
'exe_result' => (float) $incomingData['result'],
'steps_counter' => 0,
'exe_duration' => $incomingData['duration'],
'questions_to_check' => '',
]
);
}
/**
* @param int $quizId
* @param int $userId
* @param int $sessionId
*
* @throws \Exception
*
* @return array
*/
private function findViewByQuiz($quizId, $userId, $sessionId)
{
$query = \Database::query("SELECT lpiv.lp_item_id, lpv.c_id, lpiv.iid, lpv.lp_id
FROM c_lp_item_view lpiv
INNER JOIN c_lp_item lpi ON (lpiv.lp_item_id = lpi.iid AND lpiv.c_id = lpi.c_id)
INNER JOIN c_lp_view lpv ON (lpv.iid = lpiv.lp_view_id AND lpv.c_id = lpiv.c_id)
WHERE lpi.path = $quizId AND lpv.user_id = $userId AND lpv.session_id = $sessionId
LIMIT 1"
);
$result = \Database::fetch_assoc($query);
if (!$result) {
throw new \Exception("Item view not found for quiz ($quizId) and user ($userId) in session ($sessionId).");
}
return $result;
}
}

@ -0,0 +1,94 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Task;
use Chamilo\PluginBundle\MigrationMoodle\Extractor\LoadedUsersFilterExtractor;
use Chamilo\PluginBundle\MigrationMoodle\Loader\UserQuizAttemptLoader;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\BaseTransformer;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\DateTimeObject;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedQuizLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedUserLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\LoadedUserSessionLookup;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\QuizDataTracking;
use Chamilo\PluginBundle\MigrationMoodle\Transformer\Property\Subtract;
/**
* Class UsersQuizzesAttemptsTask.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Task
*/
class UsersQuizzesAttemptsTask extends BaseTask
{
/**
* @inheritDoc
*/
public function getExtractConfiguration()
{
return [
'class' => LoadedUsersFilterExtractor::class,
'query' => 'SELECT
qa.id,
qa.quiz,
qa.userid,
qa.layout,
qa.state,
qa.timestart,
qa.timefinish,
qa.sumgrades real_result,
q.sumgrades weighting
FROM mdl_quiz_attempts qa
INNER JOIN mdl_quiz q ON qa.quiz = q.id
ORDER BY qa.userid, q.id, qa.attempt',
];
}
/**
* @inheritDoc
*/
public function getTransformConfiguration()
{
return [
'class' => BaseTransformer::class,
'map' => [
'user_id' => [
'class' => LoadedUserLookup::class,
'properties' => ['userid'],
],
'date' => [
'class' => DateTimeObject::class,
'properties' => ['timestart'],
],
'exo_id' => [
'class' => LoadedQuizLookup::class,
'properties' => ['quiz']
],
'result' => 'real_result',
'weighting' => 'weighting',
'data_tracking' => [
'class' => QuizDataTracking::class,
'properties' => ['quiz', 'layout'],
],
'session_id' => [
'class' => LoadedUserSessionLookup::class,
'properties' => ['userid'],
],
'duration' => [
'class' => Subtract::class,
'properties' => ['timefinish', 'timestart'],
],
'status' => 'state',
],
];
}
/**
* @inheritDoc
*/
public function getLoadConfiguration()
{
return [
'class' => UserQuizAttemptLoader::class,
];
}
}

@ -0,0 +1,70 @@
<?php
/* For licensing terms, see /license.txt */
namespace Chamilo\PluginBundle\MigrationMoodle\Transformer\Property;
use Doctrine\DBAL\DBALException;
/**
* Class QuizDataTracking.
*
* Transform mdl_quiz_attempt.layout to track_e_exercises.data_tracking.
*
* @package Chamilo\PluginBundle\MigrationMoodle\Transformer\Property
*/
class QuizDataTracking extends LoadedQuestionLookup
{
/**
* @param array $data
*
* @throws \Exception
*
* @return mixed
*/
public function transform(array $data)
{
list($mQuizId, $mAttemptLayout) = array_values($data);
$mAttemptLayout = explode(',', $mAttemptLayout);
$mAttemptLayout = array_filter($mAttemptLayout);
$tracking = [];
foreach ($mAttemptLayout as $mQuestionSlot) {
$mQuestionId = $this->findQuestionBySlotInQuiz($mQuizId, $mQuestionSlot);
$tracking[] = parent::transform([$mQuestionId]);
}
return implode(',', $tracking);
}
/**
* @param int $quizId
* @param int $slot
*
* @throws \Exception
*
* @return mixed
*/
private function findQuestionBySlotInQuiz($quizId = 0, $slot = 0)
{
try {
$connection = \MigrationMoodlePlugin::create()->getConnection();
} catch (DBALException $exception) {
throw new \Exception('Unable to start connection.', 0, $exception);
}
try {
$sql = "SELECT questionid FROM mdl_quiz_slots WHERE slot = ? AND quizid = ?";
$result = $connection->fetchAssoc($sql, [$slot, $quizId]);
} catch (DBALException $exception) {
throw new \Exception("Unable to execute query '{$this->query}'.", 0, $exception);
}
$connection->close();
return $result['questionid'];
}
}
Loading…
Cancel
Save