* @version $Id: exercise.lib.php 22247 2009-07-20 15:57:25Z ivantcholakov $
*/
// The initialization class for the online editor is needed here.
require_once dirname(__FILE__).'/../inc/lib/fckeditor/fckeditor.php';
/**
* Shows a question
*
* @param int question id
* @param bool if true only show the questions, no exercise title
* @param bool origin i.e = learnpath
* @param int current item from the list of questions
* @param int number of total questions
* */
function showQuestion($questionId, $only_questions = false, $origin = false, $current_item = '', $show_title = true, $freeze = false) {
// Text direction for the current language
$is_ltr_text_direction = api_get_text_direction() != 'rtl';
// Change false to true in the following line to enable answer hinting.
$debug_mark_answer = api_is_allowed_to_edit() && false;
// Reads question information
if (!$objQuestionTmp = Question::read($questionId)) {
// Question not found
return false;
}
$answerType = $objQuestionTmp->selectType();
$pictureName = $objQuestionTmp->selectPicture();
if ($answerType != HOT_SPOT) {
// Question is not a hotspot
if (!$only_questions) {
$questionName = $objQuestionTmp->selectTitle();
$questionDescription = $objQuestionTmp->selectDescription();
$questionName = text_filter($questionName);
if ($show_title) {
$s='
'.get_lang('Question').' ';
$s.=$current_item;
//@todo I need the get the feedback type
//if($answerType != 1)
//$s.=' / '.$total_item;
echo $s;
echo ' : ';
echo $questionName.'
';
// construction of the Answer object (also gets all answers details)
$objAnswerTmp = new Answer($questionId);
$nbrAnswers = $objAnswerTmp->selectNbrAnswers();
$quiz_question_options = Question::readQuestionOption($questionId);
// For "matching" type here, we need something a little bit special
// because the match between the suggestions and the answers cannot be
// done easily (suggestions and answers are in the same table), so we
// have to go through answers first (elems with "correct" value to 0).
$select_items = array();
//This will contain the number of answers on the left side. We call them
// suggestions here, for the sake of comprehensions, while the ones
// on the right side are called answers
$num_suggestions = 0;
if ($answerType == MATCHING) {
$x = 1; //iterate through answers
$letter = 'A'; //mark letters for each answer
$answer_matching = $cpt1 = array();
$answer_suggestions = $nbrAnswers;
for ($answerId=1;$answerId <= $nbrAnswers;$answerId++) {
$answerCorrect = $objAnswerTmp->isCorrect($answerId);
$numAnswer = $objAnswerTmp->selectAutoId($answerId);
$answer=$objAnswerTmp->selectAnswer($answerId);
if ($answerCorrect==0) {
// options (A, B, C, ...) that will be put into the list-box
// have the "correct" field set to 0 because they are answer
$cpt1[$x] = $letter;
$answer_matching[$x]=$objAnswerTmp->selectAnswerByAutoId($numAnswer);
$x++; $letter++;
}
}
$i = 1;
foreach ($answer_matching as $id => $value) {
$select_items[$i]['id'] = $value['id'];
$select_items[$i]['letter'] = $cpt1[$id];
$select_items[$i]['answer'] = $value['answer'];
$i ++;
}
$num_suggestions = ($nbrAnswers - $x) + 1;
} elseif ($answerType == FREE_ANSWER) {
$oFCKeditor = new FCKeditor("choice[".$questionId."]") ;
$oFCKeditor->ToolbarSet = 'TestFreeAnswer';
$oFCKeditor->Width = '100%';
$oFCKeditor->Height = '200';
$oFCKeditor->Value = '' ;
$s .= '
';
$s .= $oFCKeditor->CreateHtml();
$s .= '
';
}
?>
options as $key=>$item) {
$header .= Display::tag('th', $item);
}
$s.=Display::tag('tr',$header, array('style'=>'text-align:left;'));
}
for ($answerId=1;$answerId <= $nbrAnswers;$answerId++) {
$answer = $objAnswerTmp->selectAnswer($answerId);
$answerCorrect = $objAnswerTmp->isCorrect($answerId);
$numAnswer = $objAnswerTmp->selectAutoId($answerId);
if ($answerType == FILL_IN_BLANKS) {
// splits text and weightings that are joined with the character '::'
list($answer) = explode('::',$answer);
// because [] is parsed here we follow this procedure:
$answer = text_filter($answer);
//getting the matches
$answer = api_ereg_replace('\[[^]]+\]','',($answer));
}
// Unique answer
if ($answerType == UNIQUE_ANSWER || $answerType == UNIQUE_ANSWER_NO_OPTION) {
// set $debug_mark_answer to true at function start to
// show the correct answer with a suffix '-x'
$help = $selected = '';
if ($debug_mark_answer) {
if ($answerCorrect) {
$help = 'x-';
$selected = 'checked';
}
}
$answer = text_filter($answer);
$answer = Security::remove_XSS($answer, STUDENT);
$s .= Display::input('hidden','choice2['.$questionId.']','0').
'
';
} elseif ($answerType == FILL_IN_BLANKS) {
// fill in blanks
$s .= '
'.$answer.'
';
} else {
// matching type, showing suggestions and answers
// TODO: replace $answerId by $numAnswer
if ($answerCorrect != 0) {
// only show elements to be answered (not the contents of
// the select boxes, who are corrrect = 0)
$s .= '
';
$lines_count++;
//if the left side of the "matching" has been completely
// shown but the right side still has values to show...
if (($lines_count -1) == $num_suggestions) {
// if it remains answers to shown at the right side
while (isset($select_items[$lines_count])) {
$s .= '
";
$lines_count++;
} // end while()
} // end if()
}
}
} // end for()
/*
//Adding divs for the new MATCHING interface
if ($answerType == MATCHING && !$freeze) {
echo '
';
// destruction of the Answer object
unset($objAnswerTmp);
// destruction of the Question object
unset($objQuestionTmp);
if ($origin != 'export') {
echo $s;
} else {
return($s);
}
} elseif ($answerType == HOT_SPOT) {
// Question is a HOT_SPOT
//checking document/images visibility
if (api_is_platform_admin() || api_is_course_admin()) {
require_once api_get_path(LIBRARY_PATH).'document.lib.php';
$course = api_get_course_info();
$doc_id = DocumentManager::get_document_id($course, '/images/'.$pictureName);
if (is_numeric($doc_id)) {
$images_folder_visibility = api_get_item_visibility($course,'document', $doc_id, api_get_session_id());
if (!$images_folder_visibility) {
//This message is shown only to the course/platform admin if the image is set to visibility = false
Display::display_warning_message(get_lang('ChangeTheVisibilityOfTheCurrentImage'));
}
}
}
$questionName = $objQuestionTmp->selectTitle();
$questionDescription = $objQuestionTmp->selectDescription();
if ($freeze) {
echo Display::img($objQuestionTmp->selectPicturePath());
return;
}
// Get the answers, make a list
$objAnswerTmp = new Answer($questionId);
$nbrAnswers = $objAnswerTmp->selectNbrAnswers();
// get answers of hotpost
$answers_hotspot = array();
for ($answerId=1;$answerId <= $nbrAnswers;$answerId++) {
$answers = $objAnswerTmp->selectAnswerByAutoId($objAnswerTmp->selectAutoId($answerId));
$answers_hotspot[$answers['id']] = $objAnswerTmp->selectAnswer($answerId);
}
// display answers of hotpost order by id
$answer_list = '
'.get_lang('HotspotZones').'
';
if (!empty($answers_hotspot)) {
ksort($answers_hotspot);
foreach ($answers_hotspot as $key => $value) {
$answer_list .= '
'.$key.'.- '.$value.'
';
}
}
$answer_list .= '
';
if (!$only_questions) {
if ($show_title) {
echo '
';
return $nbrAnswers;
}
function get_exercise_track_exercise_info($exe_id) {
$TBL_EXERCICES = Database::get_course_table(TABLE_QUIZ_TEST);
$TBL_TRACK_EXERCICES = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
$exe_id = intval($exe_id);
$result = array();
if (!empty($exe_id)) {
$sql_fb_type = 'SELECT * FROM '.$TBL_EXERCICES.' as e INNER JOIN '.$TBL_TRACK_EXERCICES.' as te ON (e.id=te.exe_exo_id) WHERE te.exe_id='.$exe_id;
$res_fb_type = Database::query($sql_fb_type);
$result = Database::fetch_array($res_fb_type, 'ASSOC');
}
return $result;
}
/**
* Validates the time control key
*/
function exercise_time_control_is_valid($exercise_id) {
//Fast check
$exercise_id = intval($exercise_id);
$TBL_EXERCICES = Database::get_course_table(TABLE_QUIZ_TEST);
$sql = "SELECT expired_time FROM $TBL_EXERCICES WHERE id = $exercise_id";
$result = Database::query($sql);
$row = Database::fetch_array($result, 'ASSOC');
if (!empty($row['expired_time']) ) {
$current_expired_time_key = get_time_control_key($exercise_id);
if (isset($_SESSION['expired_time'][$current_expired_time_key])) {
$current_time = time();
$expired_time = api_strtotime($_SESSION['expired_time'][$current_expired_time_key], 'UTC');
$total_time_allowed = $expired_time + 30;
//error_log('expired time converted + 30: '.$total_time_allowed);
//error_log('$current_time: '.$current_time);
if ($total_time_allowed < $current_time) {
return false;
}
return true;
} else {
return false;
}
} else {
return true;
}
}
/**
Deletes the time control token
*/
function exercise_time_control_delete($exercise_id) {
$current_expired_time_key = get_time_control_key($exercise_id);
unset($_SESSION['expired_time'][$current_expired_time_key]);
}
/**
Generates the time control key
*/
function generate_time_control_key($exercise_id) {
$exercise_id = intval($exercise_id);
return api_get_course_int_id().'_'.api_get_session_id().'_'.$exercise_id.'_'.api_get_user_id();
}
/**
Returns the time controller key
@todo this function is the same as generate_time_control_key
*/
function get_time_control_key($exercise_id) {
$exercise_id = intval($exercise_id);
return api_get_course_int_id().'_'.api_get_session_id().'_'.$exercise_id.'_'.api_get_user_id();
}
/**
* @todo use this function instead of get_time_control_key
*/
function get_session_time_control_key($exercise_id) {
$time_control_key = get_time_control_key($exercise_id);
$return_value = $_SESSION['expired_time'][$time_control_key];
return $return_value;
}
/**
* Gets count of exam results
* @todo this function should be moved in a library + no global calls
*/
function get_count_exam_results($exercise_id = null) {
//@todo replace all this globals
global $is_allowedToEdit, $is_tutor,$TBL_USER, $TBL_EXERCICES,$TBL_TRACK_EXERCICES, $TBL_TRACK_HOTPOTATOES, $TBL_TRACK_ATTEMPT_RECORDING,$filter_by_not_revised,$filter_by_revised,$documentPath;
$session_id_and = ' AND te.session_id = ' . api_get_session_id() . ' ';
$exercise_id = intval($_GET['exerciseId']);
$exercise_where = '';
if (!empty($exercise_id)) {
$exercise_where = ' AND te.exe_exo_id = '.$exercise_id.' ';
}
$hotpotatoe_where = '';
if (!empty($_GET['path'])) {
$hotpotatoe_path = Database::escape_string($_GET['path']);
$hotpotatoe_where .= ' AND exe_name = "'.$hotpotatoe_path.'" ';
}
$user_id_hotpotato_and = ' AND exe_user_id = ' . api_get_user_id() . ' ';
if ($is_allowedToEdit || $is_tutor) {
$user_id_and = '';
if (!empty ($_POST['filter_by_user'])) {
if ($_POST['filter_by_user'] == 'all') {
$user_id_and = " AND user_id like '%'";
} else {
$user_id_and = " AND user_id = '" . Database :: escape_string((int) $_POST['filter_by_user']) . "' ";
}
}
if ($_GET['gradebook'] == 'view') {
$exercise_where_query = 'te.exe_exo_id =ce.id AND ';
}
//@todo fix to work with COURSE_RELATION_TYPE_RRHH in both queries
/*$sql="SELECT ".(api_is_western_name_order() ? "firstname as userpart1, lastname col1" : "lastname as userpart1, firstname as col1").", ce.title as extitle, te.exe_result as exresult ,
te.exe_weighting as exweight, te.exe_date as exdate, te.exe_id as exid, email as exemail, te.start_date as exstart, steps_counter as exstep,cuser.user_id as excruid,te.exe_duration as exduration
FROM $TBL_EXERCICES AS ce , $TBL_TRACK_EXERCICES AS te, $TBL_USER AS user,$tbl_course_rel_user AS cuser
WHERE user.user_id=cuser.user_id AND cuser.relation_type<>".COURSE_RELATION_TYPE_RRHH." AND te.exe_exo_id = ce.id AND te.status != 'incomplete' AND cuser.user_id=te.exe_user_id AND te.exe_cours_id='" . Database :: escape_string($_cid) . "'
$user_id_and $session_id_and AND ce.active <>-1 AND orig_lp_id = 0 AND orig_lp_item_id = 0
AND cuser.course_code=te.exe_cours_id ORDER BY col1, te.exe_cours_id ASC, ce.title ASC, te.exe_date DESC";*/
$sql="SELECT DISTINCT te.exe_id
FROM $TBL_EXERCICES AS ce INNER JOIN $TBL_TRACK_EXERCICES AS te ON (te.exe_exo_id = ce.id) INNER JOIN $TBL_USER AS user ON (user.user_id = exe_user_id)
WHERE te.status != 'incomplete' AND te.exe_cours_id='" . api_get_course_id() . "' $user_id_and $session_id_and AND ce.active <>-1 AND orig_lp_id = 0 AND orig_lp_item_id = 0 $exercise_where ";
//Seems that the $TBL_TRACK_HOTPOTATOES does not have an exercise id that's weird ... we are removing $exercise_where
$hpsql="SELECT count(*) as count
FROM $TBL_TRACK_HOTPOTATOES tth, $TBL_USER tu
WHERE tu.user_id=tth.exe_user_id AND tth.exe_cours_id = '" . api_get_course_id() . "' $user_id_hotpotato_and $hotpotatoe_where
ORDER BY tth.exe_cours_id ASC, tth.exe_date DESC";
} else {
// get only this user's results
$user_id_and = ' AND te.exe_user_id = ' . api_get_user_id() . ' ';
/*$sql="SELECT ".(api_is_western_name_order() ? "firstname as col0, lastname col1" : "lastname as col0, firstname as col1").", ce.title as extitle, te.exe_result as exresult, " .
"te.exe_weighting as exweight, te.exe_date as exdate, te.exe_id as exid, email as exemail, " .
"te.start_date as exstart, steps_counter as exstep, cuser.user_id as excruid, te.exe_duration as exduration, ce.results_disabled as exdisabled
FROM $TBL_EXERCICES AS ce , $TBL_TRACK_EXERCICES AS te, $TBL_USER AS user,$tbl_course_rel_user AS cuser
WHERE user.user_id=cuser.user_id AND te.exe_exo_id = ce.id AND te.status != 'incomplete' AND cuser.user_id=te.exe_user_id
AND te.exe_cours_id='" . Database :: escape_string($_cid) . "'
AND cuser.relation_type<>".COURSE_RELATION_TYPE_RRHH." $user_id_and $session_id_and AND ce.active <>-1 AND" .
" orig_lp_id = 0 AND orig_lp_item_id = 0 AND cuser.course_code=te.exe_cours_id ORDER BY col1, te.exe_cours_id ASC, ce.title ASC, te.exe_date DESC";*/
$sql="SELECT count(*) as count
FROM $TBL_EXERCICES AS ce INNER JOIN $TBL_TRACK_EXERCICES AS te ON (te.exe_exo_id = ce.id) INNER JOIN $TBL_USER AS user ON (user.user_id = exe_user_id)
WHERE te.status != 'incomplete' AND te.exe_cours_id='" . api_get_course_id() . "' $user_id_and $session_id_and AND ce.active <>-1 AND orig_lp_id = 0 AND orig_lp_item_id = 0 $exercise_where";
$hpsql = "SELECT count(*) as count
FROM $TBL_TRACK_HOTPOTATOES
WHERE exe_user_id = '" . api_get_user_id() . "' AND exe_cours_id = '" . api_get_course_id() . "' $user_id_hotpotato_and $hotpotatoe_where
ORDER BY exe_cours_id ASC, exe_date DESC";
}
$count = 0;
//Chamilo results
if (empty($hotpotatoe_where)) {
$resx = Database::query($sql);
if (Database::num_rows($resx) > 0) {
if ($is_allowedToEdit || $is_tutor) {
while ($rowx = Database::fetch_array($resx,'ASSOC')) {
$results[] = $rowx;
}
//Special modification to show corretly the pagination
if (is_array($results)) {
if ($_GET['gradebook'] == 'view') {
$filter_by_no_revised = true;
$from_gradebook = true;
}
$sizeof = count($results);
$user_list_id = array ();
$user_last_name = '';
$user_first_name = '';
$quiz_name_list = '';
$duration_list = '';
$date_list = '';
$result_list = '';
$more_details_list = '';
for ($i = 0; $i < $sizeof; $i++) {
$revised = false;
$sql_exe = 'SELECT exe_id FROM ' . $TBL_TRACK_ATTEMPT_RECORDING . ' WHERE author != "" AND exe_id = ' . Database :: escape_string($results[$i]['exe_id']) .' LIMIT 1';
$query = Database::query($sql_exe);
if (Database :: num_rows($query) > 0) {
$revised = true;
}
if ($filter_by_not_revised && $revised) {
continue;
}
if ($filter_by_revised && !$revised) {
continue;
}
$count++;
}
}
} else {
$rowx = Database::fetch_array($resx,'ASSOC');
$count = $rowx['count'];
}
}
} else {
//Hotpotatoes results
$hpres = Database::query($hpsql);
if (Database::num_rows($hpres) > 0) {
$rowx = Database::fetch_array($hpres,'ASSOC');
$count += $rowx['count'];
}
}
return $count;
}
/**
* Gets the exam'data results
* @todo this function should be moved in a library + no global calls
*/
function get_exam_results_data($from, $number_of_items, $column, $direction) {
//@todo replace all this globals
global $is_allowedToEdit, $is_tutor,$TBL_USER, $TBL_EXERCICES,$TBL_TRACK_HOTPOTATOES, $TBL_TRACK_EXERCICES, $TBL_TRACK_ATTEMPT_RECORDING,$filter_by_not_revised,$filter_by_revised,$documentPath,$filter;
$session_id_and = ' AND te.session_id = ' . api_get_session_id() . ' ';
$exercise_id = intval($_GET['exerciseId']);
$exercise_where = '';
if (!empty($exercise_id)) {
$exercise_where .= ' AND te.exe_exo_id = '.$exercise_id.' ';
}
$hotpotatoe_where = '';
if (!empty($_GET['path'])) {
$hotpotatoe_path = Database::escape_string($_GET['path']);
$hotpotatoe_where .= ' AND exe_name = "'.$hotpotatoe_path.'" ';
}
if ($is_allowedToEdit || $is_tutor) {
$user_id_and = '';
if (!empty ($_POST['filter_by_user'])) {
if ($_POST['filter_by_user'] == 'all') {
$user_id_and = " AND user_id like '%'";
} else {
$user_id_and = " AND user_id = '" . intval($_POST['filter_by_user']) . "' ";
}
}
if ($_GET['gradebook'] == 'view') {
$exercise_where_query = ' te.exe_exo_id =ce.id AND ';
}
//@todo fix to work with COURSE_RELATION_TYPE_RRHH in both queries
/*$sql="SELECT ".(api_is_western_name_order() ? "firstname as col0, lastname col1" : "lastname as col0, firstname as col1").", ce.title as extitle, te.exe_result as exresult ,
te.exe_weighting as exweight, te.exe_date as exdate, te.exe_id as exid, email as exemail, te.start_date as exstart, steps_counter as exstep,cuser.user_id as excruid,te.exe_duration as exduration
FROM $TBL_EXERCICES AS ce , $TBL_TRACK_EXERCICES AS te, $TBL_USER AS user,$tbl_course_rel_user AS cuser
WHERE user.user_id=cuser.user_id AND cuser.relation_type<>".COURSE_RELATION_TYPE_RRHH." AND te.exe_exo_id = ce.id AND te.status != 'incomplete' AND cuser.user_id=te.exe_user_id AND te.exe_cours_id='" . Database :: escape_string(api_get_course_id()) . "'
$user_id_and $session_id_and AND ce.active <>-1 AND orig_lp_id = 0 AND orig_lp_item_id = 0
AND cuser.course_code=te.exe_cours_id ORDER BY col1, te.exe_cours_id ASC, ce.title ASC, te.exe_date DESC";*/
$sql="SELECT ".(api_is_western_name_order() ? "firstname as col0, lastname col1" : "lastname as col0, firstname as col1").", ce.title as col2, te.exe_result as exresult , te.exe_weighting as exweight,
te.exe_date as exdate, te.exe_id as exid, email as exemail, te.start_date as col4, steps_counter as exstep, exe_user_id as excruid,te.exe_duration as exduration, propagate_neg
FROM $TBL_EXERCICES AS ce INNER JOIN $TBL_TRACK_EXERCICES AS te ON (te.exe_exo_id = ce.id) INNER JOIN $TBL_USER AS user ON (user.user_id = exe_user_id)
WHERE te.status != 'incomplete' AND te.exe_cours_id='" . api_get_course_id() . "' $user_id_and $session_id_and AND ce.active <>-1 AND orig_lp_id = 0 AND orig_lp_item_id = 0 $exercise_where ";
$hpsql="SELECT ".(api_is_western_name_order() ? "firstname as col0, lastname col1" : "lastname as col0, firstname as col1").", tth.exe_name, tth.exe_result , tth.exe_weighting, tth.exe_date
FROM $TBL_TRACK_HOTPOTATOES tth, $TBL_USER tu
WHERE tu.user_id=tth.exe_user_id AND tth.exe_cours_id = '" . api_get_course_id()."' $hotpotatoe_where
ORDER BY tth.exe_cours_id ASC, tth.exe_date DESC";
} else {
// get only this user's results
$user_id_and = ' AND te.exe_user_id = ' . api_get_user_id() . ' ';
/*$sql="SELECT ".(api_is_western_name_order() ? "firstname as col0, lastname col1" : "lastname as col0, firstname as col1").", ce.title as extitle, te.exe_result as exresult, " .
"te.exe_weighting as exweight, te.exe_date as exdate, te.exe_id as exid, email as exemail, " .
"te.start_date as exstart, steps_counter as exstep, cuser.user_id as excruid, te.exe_duration as exduration, ce.results_disabled as exdisabled
FROM $TBL_EXERCICES AS ce , $TBL_TRACK_EXERCICES AS te, $TBL_USER AS user,$tbl_course_rel_user AS cuser
WHERE user.user_id=cuser.user_id AND te.exe_exo_id = ce.id AND te.status != 'incomplete' AND cuser.user_id=te.exe_user_id
AND te.exe_cours_id='" . Database :: escape_string($_cid) . "'
AND cuser.relation_type<>".COURSE_RELATION_TYPE_RRHH." $user_id_and $session_id_and AND ce.active <>-1 AND" .
" orig_lp_id = 0 AND orig_lp_item_id = 0 AND cuser.course_code=te.exe_cours_id ORDER BY col1, te.exe_cours_id ASC, ce.title ASC, te.exe_date DESC";*/
$sql="SELECT ce.title as col0, ce.title as col1, te.exe_duration as exduration, firstname, lastname, te.exe_result as exresult, te.exe_weighting as exweight, te.exe_date as exdate, te.exe_id as exid, email as exemail, " .
"te.start_date as col2, steps_counter as exstep, exe_user_id as excruid, ce.results_disabled as exdisabled, propagate_neg
FROM $TBL_EXERCICES AS ce INNER JOIN $TBL_TRACK_EXERCICES AS te ON (te.exe_exo_id = ce.id) INNER JOIN $TBL_USER AS user ON (user.user_id = exe_user_id)
WHERE te.status != 'incomplete' AND te.exe_cours_id='" . api_get_course_id() . "' $user_id_and $session_id_and AND ce.active <>-1 AND orig_lp_id = 0 AND orig_lp_item_id = 0 $exercise_where";
$hpsql = "SELECT '', '', exe_name, exe_result , exe_weighting, exe_date
FROM $TBL_TRACK_HOTPOTATOES
WHERE exe_user_id = '" . api_get_user_id() . "' AND exe_cours_id = '" . api_get_course_id() . "' $hotpotatoe_where
ORDER BY exe_cours_id ASC, exe_date DESC";
}
if (empty($hotpotatoe_where)) {
$column = intval($column);
$from = intval($from);
$number_of_items = intval($number_of_items);
$sql .= " ORDER BY col$column $direction ";
$sql .= " LIMIT $from, $number_of_items";
$results = array();
$resx = Database::query($sql);
while ($rowx = Database::fetch_array($resx,'ASSOC')) {
$results[] = $rowx;
}
$list_info = array();
// Print test results.
$lang_nostartdate = get_lang('NoStartDate') . ' / ';
if (is_array($results)) {
$users_array_id = array ();
if ($_GET['gradebook'] == 'view') {
$filter_by_no_revised = true;
$from_gradebook = true;
}
$sizeof = count($results);
$user_list_id = array ();
$user_last_name = '';
$user_first_name = '';
$quiz_name_list = '';
$duration_list = '';
$date_list = '';
$result_list = '';
$more_details_list = '';
for ($i = 0; $i < $sizeof; $i++) {
$revised = false;
$sql_exe = 'SELECT exe_id FROM ' . $TBL_TRACK_ATTEMPT_RECORDING . ' WHERE author != "" AND exe_id = ' . Database :: escape_string($results[$i]['exid']) .' LIMIT 1';
$query = Database::query($sql_exe);
if (Database :: num_rows($query) > 0) {
$revised = true;
}
if ($filter_by_not_revised && $revised) {
continue;
}
if ($filter_by_revised && !$revised) {
continue;
}
if ($from_gradebook && ($is_allowedToEdit || $is_tutor)) {
if (in_array($results[$i]['col2'] . $results[$i]['col0'] . $results[$i]['col1'], $users_array_id)) {
continue;
}
$users_array_id[] = $results[$i]['col2'] . $results[$i]['col0'] . $results[$i]['col1'];
}
if ($is_allowedToEdit || $is_tutor) {
$user_first_name = $results[$i]['col0'];
$user_last_name = $results[$i]['col1'];
$user = $results[$i]['col0'] . $results[$i]['col1'];
$test = $results[$i]['col2'];
} else {
$user_first_name = $results[$i]['firstname'];
$user_last_name = $results[$i]['lastname'];
$user = $results[$i]['firstname'] . $results[$i]['lastname'];
$test = $results[$i]['col0'];
}
$user_list_id[] = $results[$i]['excruid'];
$id = $results[$i]['exid'];
$quiz_name_list = $test;
$dt = api_convert_and_format_date($results[$i]['exweight'], null, date_default_timezone_get());
$res = $results[$i]['exresult'];
$duration = intval($results[$i]['exduration']);
// we filter the results if we have the permission to
if (isset ($results[$i]['exdisabled']))
$result_disabled = intval($results[$i]['exdisabled']);
else
$result_disabled = 0;
if ($result_disabled == 0) {
$add_start_date = $lang_nostartdate;
if ($is_allowedToEdit || $is_tutor) {
$user = $results[$i]['col0'] . $results[$i]['col1'];
$date_value = $results[$i]['col4'];
} else {
$date_value = $results[$i]['col2'];
}
if ($date_value != "0000-00-00 00:00:00") {
//echo ceil((($results[$i][4] - $results[$i][7]) / 60)) . ' ' . get_lang('MinMinutes');
$exe_date_timestamp = api_strtotime($results[$i]['exdate'], date_default_timezone_get());
$start_date_timestamp = api_strtotime($date_value, date_default_timezone_get());
$my_duration = ceil((($exe_date_timestamp - $start_date_timestamp) / 60));
if ($my_duration == 1 ) {
$duration_list = $my_duration . ' ' . get_lang('MinMinute');
} else {
$duration_list = $my_duration. ' ' . get_lang('MinMinutes');
}
if ($results[$i]['exstep'] > 1) {
//echo ' ( ' . $results[$i][8] . ' ' . get_lang('Steps') . ' )';
$duration_list = ' ( ' . $results[$i]['exstep'] . ' ' . get_lang('Steps') . ' )';
}
$add_start_date = api_convert_and_format_date($date_value, null, date_default_timezone_get()) . ' / ';
} else {
$duration_list = get_lang('NoLogOfDuration');
//echo get_lang('NoLogOfDuration');
}
// Date conversion
$date_list = api_get_local_time($results[$i]['col4']). ' / ' . api_get_local_time($results[$i]['exdate']);
// there are already a duration test period calculated??
//echo '