Add ajax call to save exercise duration when page unload see BT#14149

pull/3063/head
jmontoyaa 8 years ago
parent 413f0bffd8
commit 2e091a9b2f
  1. 2
      main/exercise/exercise.php
  2. 4
      main/exercise/exercise_result.php
  3. 27
      main/exercise/exercise_submit.php
  4. 2
      main/exercise/overview.php
  5. 91
      main/inc/ajax/exercise.ajax.php
  6. 23
      main/inc/lib/internationalization.lib.php
  7. 9
      main/lp/learnpathItem.class.php
  8. 2
      main/lp/lp_ajax_save_item.php
  9. 2
      main/lp/lp_view.php
  10. 2
      main/session/index.php

@ -72,6 +72,8 @@ Session::erase('objAnswer');
Session::erase('questionList');
Session::erase('exerciseResult');
Session::erase('firstTime');
Session::erase('duration_time_previous');
Session::erase('duration_time');
//General POST/GET/SESSION/COOKIES parameters recovery
$origin = api_get_origin();

@ -203,6 +203,8 @@ if ($origin != 'learnpath') {
if (api_is_allowed_to_session_edit()) {
Session::erase('objExercise');
Session::erase('exe_id');
Session::erase('duration_time_previous');
Session::erase('duration_time');
}
Display::display_footer();
} else {
@ -213,6 +215,8 @@ if ($origin != 'learnpath') {
if (api_is_allowed_to_session_edit()) {
Session::erase('objExercise');
Session::erase('exe_id');
Session::erase('duration_time_previous');
Session::erase('duration_time');
}
Session::write('attempt_remaining', $remainingMessage);

@ -95,7 +95,6 @@ $endExercise = isset($_REQUEST['end_exercise']) && $_REQUEST['end_exercise'] ==
// Error message
$error = '';
$exercise_attempt_table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
/* Teacher takes an exam and want to see a preview,
@ -186,7 +185,15 @@ $current_expired_time_key = ExerciseLib::get_time_control_key(
$learnpath_item_id
);
$_SESSION['duration_time'][$current_expired_time_key] = $current_timestamp;
Session::write('duration_time_previous', [$current_expired_time_key => $current_timestamp]);
$durationTime = Session::read('duration_time');
if (!empty($durationTime) && isset($durationTime[$current_expired_time_key])) {
Session::write(
'duration_time_previous',
[$current_expired_time_key => $durationTime[$current_expired_time_key]]
);
}
Session::write('duration_time', [$current_expired_time_key => $current_timestamp]);
if ($time_control) {
// Get the expired time of the current exercise in track_e_exercises
@ -412,6 +419,7 @@ if (empty($exercise_stat_info)) {
}
}
$saveDurationUrl = api_get_path(WEB_AJAX_PATH).'exercise.ajax.php?a=update_duration&exe_id='.$exe_id.'&'.api_get_cidreq();
$questionListInSession = Session::read('questionList');
if (!isset($questionListInSession)) {
@ -1069,9 +1077,7 @@ if (!empty($error)) {
});*/
$(\'form#exercise_form\').prepend($(\'#exercise-description\'));
});
$(document).on(\'ready\', function () {
$(\'button[name="previous_question_and_save"]\').on(\'click\', function (e) {
e.preventDefault();
e.stopPropagation();
@ -1113,6 +1119,19 @@ if (!empty($error)) {
validate_all();
});
var saveDurationUrl = "'.$saveDurationUrl.'";
// Save attempt duration
$(window).on(\'beforeunload\', function () {
// Logout of course just in case
$.ajax({
url: saveDurationUrl,
success: function (data) {
return 1;
}
});
});
});
function previous_question(question_num) {

@ -16,6 +16,8 @@ $current_course_tool = TOOL_QUIZ;
// Clear the exercise session just in case
Session::erase('objExercise');
Session::erase('duration_time_previous');
Session::erase('duration_time');
$this_section = SECTION_COURSES;

@ -21,6 +21,89 @@ $session_id = isset($_REQUEST['session_id']) ? intval($_REQUEST['session_id']) :
$course_code = isset($_REQUEST['cidReq']) ? $_REQUEST['cidReq'] : api_get_course_id();
switch ($action) {
case 'update_duration':
$debug = true;
$exeId = isset($_REQUEST['exe_id']) ? $_REQUEST['exe_id'] : 0;
/** @var Exercise $exerciseInSession */
$exerciseInSession = Session::read('objExercise');
if (!empty($exeId) && !empty($exerciseInSession)) {
$em = Database::getManager();
/** @var \Chamilo\CoreBundle\Entity\TrackEExercises $attempt */
$attempt = $em->getRepository('ChamiloCoreBundle:TrackEExercises')->find($exeId);
$onlyUpdateValue = 10;
$nowObject = api_get_utc_datetime(null, false, true);
$now = $nowObject->getTimestamp();
$exerciseId = $attempt->getExeExoId();
$userId = $attempt->getExeUserId();
$currentUserId = api_get_user_id();
if ($exerciseInSession->id != $exerciseId) {
if ($debug) {
error_log("Cannot update exercise are different.");
}
exit;
}
if ($attempt->getStatus() != 'incomplete') {
if ($debug) {
error_log("Cannot update exercise is already completed.");
}
exit;
}
// Check if we are dealing with the same exercise.
if ($attempt && $userId == $currentUserId) {
$timeWithOutUpdate = $now - $attempt->getExeDate()->getTimestamp();
if ($timeWithOutUpdate > $onlyUpdateValue) {
$key = ExerciseLib::get_time_control_key(
$exerciseId,
$attempt->getOrigLpId(),
$attempt->getOrigLpItemId()
);
$durationFromObject = $attempt->getExeDuration();
$previousTime = Session::read('duration_time_previous');
if (isset($previousTime[$key]) &&
!empty($previousTime[$key])
) {
$sessionTime = $previousTime[$key];
$duration = $now - $sessionTime;
if ($debug) {
//error_log("Now in UTC: ".$nowObject->format('Y-m-d H:i:s'));
//error_log("Session time in UTC: ".api_get_utc_datetime($sessionTime));
error_log("Time spent in exercise: $duration just before an update");
}
if (!empty($durationFromObject)) {
$duration += $durationFromObject;
}
$duration = (int) $duration;
if (!empty($duration)) {
if ($debug) {
error_log("Exe_id: #".$exeId);
error_log("Key: $key");
error_log("Exercise to update: #$exerciseId for user: #$userId");
error_log("Accumulate duration to save in DB: $duration");
error_log("End date to save in DB: ".$nowObject->format('Y-m-d H:i:s'));
}
$attempt
->setExeDuration($duration)
->setExeDate($nowObject);
$em->merge($attempt);
$em->flush();
}
} else {
if ($debug) {
error_log("Nothing to update, 'duration_time_previous' session not set");
error_log("Key: $key");
}
}
} else {
if ($debug) {
error_log("Cannot update, latest time diff is just $timeWithOutUpdate seconds");
}
}
}
}
break;
case 'get_live_stats':
if (!api_is_allowed_to_edit(null, true)) {
break;
@ -485,8 +568,10 @@ switch ($action) {
$exercise_stat_info['orig_lp_item_id']
);
if (isset($_SESSION['duration_time'][$key]) && !empty($_SESSION['duration_time'][$key])) {
$duration = $now - $_SESSION['duration_time'][$key];
$durationTime = Session::read('duration_time');
if (isset($durationTime[$key]) && !empty($durationTime[$key])) {
$duration = $now - $durationTime[$key];
if (!empty($exercise_stat_info['exe_duration'])) {
$duration += $exercise_stat_info['exe_duration'];
}
@ -497,7 +582,7 @@ switch ($action) {
}
}
$_SESSION['duration_time'][$key] = time();
Session::write('duration_time', [$key => time()]);
Event::updateEventExercise(
$exe_id,

@ -409,29 +409,29 @@ function api_get_timezone()
* Returns the given date as a DATETIME in UTC timezone.
* This function should be used before entering any date in the DB.
*
* @param mixed $time The date to be converted (can be a string supported by date() or a timestamp)
* @param bool $return_null_if_invalid_date if the date is not correct return null instead of the current date
* @param mixed $time date to be converted (can be a string supported by date() or a timestamp)
* @param bool $returnNullIfInvalidDate if the date is not correct return null instead of the current date
* @param bool $returnObj
*
* @return string The DATETIME in UTC to be inserted in the DB,
* @return string|DateTime The DATETIME in UTC to be inserted in the DB,
* or null if the format of the argument is not supported
* or datetime
*
* @author Julio Montoya - Adding the 2nd parameter
* @author Guillaume Viguier <guillaume.viguier@beeznest.com>
*/
function api_get_utc_datetime(
$time = null,
$return_null_if_invalid_date = false,
$returnNullIfInvalidDate = false,
$returnObj = false
) {
$from_timezone = api_get_timezone();
$to_timezone = 'UTC';
$fromTimezone = api_get_timezone();
if (is_null($time) || empty($time) || $time === '0000-00-00 00:00:00') {
if ($return_null_if_invalid_date) {
if ($returnNullIfInvalidDate) {
return null;
}
if ($returnObj) {
return $date = new DateTime(gmdate('Y-m-d H:i:s'));
return new DateTime(gmdate('Y-m-d H:i:s'), new DateTimeZone('UTC'));
}
return gmdate('Y-m-d H:i:s');
@ -439,13 +439,14 @@ function api_get_utc_datetime(
// If time is a timestamp, return directly in utc
if (is_numeric($time)) {
$time = intval($time);
$time = (int) $time;
return gmdate('Y-m-d H:i:s', $time);
}
try {
$date = new DateTime($time, new DateTimezone($from_timezone));
$date->setTimezone(new DateTimeZone($to_timezone));
$date = new DateTime($time, new DateTimezone($fromTimezone));
$date->setTimezone(new DateTimeZone('UTC'));
if ($returnObj) {
return $date;
} else {

@ -3404,6 +3404,10 @@ class learnpathItem
if ($debug) {
error_log('found asset - set time to '.$myTime);
}
} else {
if ($debug) {
error_log('Time not set');
}
}
} else {
switch ($format) {
@ -3422,11 +3426,16 @@ class learnpathItem
$totalSec = $hour * 3600 + $min * 60 + $sec;
if ($debug) {
error_log("totalSec : $totalSec");
error_log("Now calling to scorm_update_time()");
}
$this->scorm_update_time($totalSec);
}
break;
case 'int':
if ($debug) {
error_log("scorm_time = $scorm_time");
error_log("Now calling to scorm_update_time()");
}
$this->scorm_update_time($scorm_time);
break;
}

@ -61,7 +61,7 @@ function save_item(
$statusSignalReceived = 0
) {
//global $debug;
$debug = 0;
$debug = false;
$return = null;
if ($debug > 0) {

@ -148,6 +148,8 @@ if (isset($exerciseResult) || isset($_SESSION['exerciseResult'])) {
Session::erase('exerciseResult');
Session::erase('objExercise');
Session::erase('questionList');
Session::erase('duration_time_previous');
Session::erase('duration_time');
}
// additional APIs

@ -37,6 +37,8 @@ Session::write('id_session', $session_id);
// Clear the exercise session just in case
Session::erase('objExercise');
Session::erase('duration_time_previous');
Session::erase('duration_time');
$userId = api_get_user_id();
$session_info = SessionManager::fetch($session_id);

Loading…
Cancel
Save