Posto qui di seguito i bug che ho trovato:
1) Durante un quiz anche se ha impostato dei tentativi massimi è possibile, tramite il pulsante indietro/back, modificare l'ultima domanda e sottomettere le risposte INFINITE volte.
nel file ->appLms\modules\test\do.test.php sostituire l'intera funzione showResult con:
Code: Select all
function showResult( $object_test, $id_param ) {
if(!checkPerm('view', true, 'organization') && !checkPerm('view', true, 'storage')) die("You can't access");
##FIX LUCA GIARDINA SU BACK BUTTON E NUOVA SOTTOMISSIONE
$lang =& DoceboLanguage::createInstance('test');
if(!isset($_POST['page_to_save']) || (($_POST['page_to_save'] == $_POST['previous_page']) && isset($_SESSION['test_date_begin']) && $_SESSION['test_date_begin']))
{
require_once(_base_.'/lib/lib.form.php');
require_once($GLOBALS['where_lms'].'/class.module/track.test.php');
require_once($GLOBALS['where_lms'].'/lib/lib.param.php' );
require_once($GLOBALS['where_lms'].'/lib/lib.test.php' );
//$lang =& DoceboLanguage::createInstance('test');
$id_test = $object_test->getId();
$id_reference = getLoParam($id_param, 'idReference');
$url_coded = urlencode(serialize($object_test->back_url));
$id_track = retriveTrack($id_reference, $id_test, Docebo::user()->getIdst());
if($id_track === false) {
$GLOBALS['page']->add(getErrorUi($lang->def('_TEST_TRACK_FAILURE')
.getBackUi(Util::str_replace_once('&', '&', $object_test->back_url), $lang->def('_BACK'))), 'content');
}
$test_man = new TestManagement($id_test);
$play_man = new PlayTestManagement($id_test, Docebo::user()->getIdst(), $id_track, $test_man);
$test_info = $test_man->getTestAllInfo();
$track_info = $play_man->getTrackAllInfo();
$previous_page = importVar('previous_page', false, false);
$new_info = array(
'last_page_seen' => $previous_page,
'score_status' => 'doing' );
if(isset($_POST['page_to_save']) && (($_POST['page_to_save'] > $track_info['last_page_saved']) || $test_info['mod_doanswer'])) {
$play_man->storePage($_POST['page_to_save'], $test_info['mod_doanswer']);
$play_man->closeTrackPageSession($_POST['page_to_save']);
}
$now = date('Y-m-d H:i:s');
$point_do = 0;
$max_score = 0;
$num_manual = 0;
$manual_score = 0;
$point_do_cat = array();
$re_visu_quest = sql_query("SELECT idQuest
FROM ".$GLOBALS['prefix_lms']."_testtrack_quest
WHERE idTrack = '".$id_track."' ");
while(list($id_q) = sql_fetch_row($re_visu_quest)) $quest_see[] = $id_q;
$reQuest = sql_query("
SELECT q.idQuest, q.type_quest, t.type_file, t.type_class, q.idCategory
FROM %lms_testquest AS q JOIN ".$GLOBALS['prefix_lms']."_quest_type AS t
WHERE q.idTest = '".$id_test."' AND q.type_quest = t.type_quest AND q.idQuest IN (".implode($quest_see, ',').")
ORDER BY q.sequence");
//#2093: Conto le domande
$tot_questions=0;
$tot_answers=0;
$tot_rightanswers=0;
$tot_questions= $test_man->getNumberOfQuestion();
while(list($id_quest, $type_quest, $type_file, $type_class, $id_cat) = sql_fetch_row($reQuest)) {
require_once($GLOBALS['where_lms'].'/modules/question/'.$type_file);
$quest_point_do = 0;
$quest_obj = new $type_class( $id_quest );
$quest_point_do = $quest_obj->userScore($id_track);
$quest_max_score = $quest_obj->getMaxScore();
if($quest_obj->getScoreSetType() == 'manual') {
++$num_manual;
$manual_score = round($manual_score + $quest_max_score, 2);
}
//#2093: Conto le risposte, conto le risposte corrette
$tot_answers++;
if($quest_point_do == $quest_max_score) $tot_rightanswers++;
$point_do = round($point_do + $quest_point_do, 2);
$max_score = round($max_score + $quest_max_score, 2);
if(isset($point_do_cat[$id_cat])) {
$point_do_cat[$id_cat] = round($quest_point_do + $point_do_cat[$id_cat], 2);
} else {
$point_do_cat[$id_cat] = round($quest_point_do, 2);
}
}
if($test_info['point_type'] == '1') { // percentage score (%)
// x:100=$point_do:$max_score
//#2093: calcolo effettivo solo se ho tutte le risposte
if ($tot_questions==$tot_answers){
$point_do =round(100*$point_do/$max_score);//$max_score$test_info['point_required']
}
else{
$point_do =round(100*$tot_rightanswers/$tot_questions);//$max_score$test_info['point_required']
}
}
$save_score = $point_do;
// save new status in track
if($point_do >= $test_info['point_required']) {
$next_status = 'passed';
if($test_info['show_only_status']) $score_status = 'passed';
} else {
$next_status = 'failed';
if($test_info['show_only_status']) $score_status = 'not_passed';
}
if(!$test_info['show_only_status']) {
if($num_manual != 0) $score_status = 'not_checked';
else $score_status = 'valid';
}
$test_track = new Track_Test($id_track);
$test_track->setDate($now);
$test_track->status = $next_status;
$test_track->update();
// --
require_once(_lms_.'/lib/lib.assessment_rule.php');
$score_arr =array();
$i =0;
foreach($point_do_cat as $cat_id=>$score) {
$score_arr[$i]['score']=$score;
$score_arr[$i]['category_id']=$cat_id;
$i++;
}
// final score:
$score_arr[$i]['score']=$point_do;
$score_arr[$i]['category_id']=0;
$asrule =new AssessmentRuleManager($id_test);
$feedback_txt = $asrule->setRulesFromScore($score_arr);
$asrule->loadJs();
// --
$GLOBALS['page']->add(
getTitleArea($lang->def('_TITLE').' : '.$test_info['title'], 'test', $lang->def('_TEST_INFO'))
.'<div class="std_block">'
.( $next_status == 'failed'
? '<b>'.$lang->def('_TEST_FAILED').'</b>'
: $lang->def('_TEST_COMPLETED') )
.'<br />', 'content');
if($test_info['point_type'] != '1') {
$save_score = $point_do;
} else {
$save_score = $point_do;//round(round($point_do / $max_score, 2) * 100, 2);
}
$track_info = Track_Test::getTrackInfo( Docebo::user()->getIdst(), $id_test, $id_reference );
if($score_status == 'valid' || $score_status == 'not_checked' || $score_status == 'passed' || $score_status == 'not_passed') {
$new_info['date_end_attempt'] = $now;
$new_info['number_of_save'] = $track_info['number_of_save'] + 1;
$new_info['score'] = $save_score;
$new_info['score_status'] = $score_status;
$new_info['number_of_attempt'] = $track_info['number_of_attempt'] + 1;
$re_update = Track_Test::updateTrack($id_track, $new_info);
if (!isset($_POST['show_review'])) {
$time = fromDatetimeToTimestamp(date('Y-m-d H:i:s')) - fromDatetimeToTimestamp($_SESSION['test_date_begin']);
sql_query("
INSERT INTO ".$GLOBALS['prefix_lms']."_testtrack_times
(idTrack, idReference, idTest, date_attempt, number_time, score, score_status, date_begin, date_end, time) VALUES
('".$id_track."', '".$id_reference."', '".$id_test."', now(), '".$new_info['number_of_save']."', '".$new_info['score']."', '".$new_info['score_status']."', '".$_SESSION['test_date_begin']."', '".date('Y-m-d H:i:s')."', '".$time."')");
unset($_SESSION['test_date_begin']);
}
}
//--- check suspension conditions ----------------------------------------------
if ($test_info['use_suspension']) {
$suspend_info = array();
if ($next_status == 'failed') {
$suspend_info['attempts_for_suspension'] = $track_info['attempts_for_suspension'] + 1;
if ($suspend_info['attempts_for_suspension'] >= $test_info['suspension_num_attempts'] && $test_info['suspension_num_hours'] > 0) {
//should we reset learning_test.suspension_num_attempts ??
$suspend_info['attempts_for_suspension'] = 0; //from now on, it uses the suspended_until parameter, so only the date is needed, we can reset the attempts count
$suspend_info['suspended_until'] = date("Y-m-d H:i:s", time()+$test_info['suspension_num_hours']*3600);
} //if num_hours is <= 0, never update attempts counter, so user won't never be de-suspended
$re = Track_Test::updateTrack($id_track, $suspend_info);
} else {
if ($next_status == 'completed' || $next_status == 'passed') {
$suspend_info['attempts_for_suspension'] = 0;
$re = Track_Test::updateTrack($id_track, $suspend_info);
}
}
}
//--- end suspensions check ----------------------------------------------------
list($bonus_score, $score_status) = sql_fetch_row( sql_query("
SELECT bonus_score, score_status
FROM ".$GLOBALS['prefix_lms']."_testtrack
WHERE idTrack = '".(int)$id_track."'"));
if($test_info['show_score'] && $test_info['point_type'] != '1') {
//$GLOBALS['page']->add('<span class="test_score_note">'.$lang->def('_TEST_TOTAL_SCORE').'</span> '.($point_do + $bonus_score).' / '.$max_score.'<br />', 'content');
$GLOBALS['page']->add('<span class="test_score_note">'.$lang->def('_TEST_TOTAL_SCORE').'</span> '.($point_do + $bonus_score).' / 100<br />', 'content');
if($num_manual != 0 && $score_status != 'valid') {
$GLOBALS['page']->add('<br />'
.'<span class="test_score_note">'.$lang->def('_TEST_MANUAL_SCORE').'</span> '.$manual_score.' '.$lang->def('_TEST_SCORES').'<br />', 'content');
}
if($test_info['point_required'] != 0) {
$GLOBALS['page']->add('<br />'
.'<span class="test_score_note">'.$lang->def('_TEST_REQUIREDSCORE_RESULT').'</span> '.$test_info['point_required'].'<br />', 'content');
}
}
if($test_info['show_score'] && $test_info['point_type'] == '1') {
$GLOBALS['page']->add('<span class="test_score_note">'.$lang->def('_TEST_TOTAL_SCORE').'</span> '.$save_score.' %'.'<br />', 'content');
if($num_manual != 0) {
$GLOBALS['page']->add('<br />'
.'<span class="test_score_note">'.$lang->def('_TEST_MANUAL_SCORE').'</span> '.$manual_score.' '.$lang->def('_TEST_SCORES').'<br />', 'content');
}
}
if($test_info['show_score_cat']) {
$re_category = sql_query("
SELECT c.idCategory, c.name, COUNT(q.idQuest)
FROM ".$GLOBALS['prefix_lms']."_testquest AS q
JOIN ".$GLOBALS['prefix_lms']."_quest_category AS c
WHERE c.idCategory = q.idCategory AND q.idTest = '".$id_test."' AND q.idCategory != 0
GROUP BY c.idCategory
ORDER BY c.name");
if(sql_num_rows($re_category)) {
$GLOBALS['page']->add('<br />'
.'<table summary="'.$lang->def('_TEST_CATEGORY_SCORE').'" class="category_score">'
.'<caption>'.$lang->def('_TEST_CATEGORY_SCORE').'</caption>'
.'<thead>'
.'<tr>'
.'<th>'.$lang->def('_TEST_QUEST_CATEGORY').'</th>'
.'<th class="number">'.$lang->def('_TEST_QUEST_NUMBER').'</th'
.'<th class="number">'.$lang->def('_TEST_TOTAL_SCORE').'</th>'
.'</tr>'
.'</thead>'
.'<tbody>', 'content');
while(list($id_cat, $name_cat, $quest_number) = sql_fetch_row($re_category)) {
$GLOBALS['page']->add('<tr><td>'.$name_cat.'</td>'
.'<td class="number">'.$quest_number.'</td>'
.'<td class="number">'.( isset($point_do_cat[$id_cat]) ? $point_do_cat[$id_cat] : 0 ).'</td></tr>'
, 'content');
}
/*
$GLOBALS['page']->add('<br />'
.'<span class="test_score_note">'.$lang->def('_TEST_CATEGORY_SCORE').'</span><br />', 'content');
while(list($id_cat, $name_cat, $quest_number) = sql_fetch_row($re_category)) {
$GLOBALS['page']->add($name_cat.', '.$lang->def('_TEST_SCORES').': '
.( isset($point_do_cat[$id_cat]) ? $point_do_cat[$id_cat] : 0 ).'<br />', 'content');
}
*/
$GLOBALS['page']->add('</tbody></table>', 'content');
}
}
$GLOBALS['page']->add('<br /><br />', 'content');
//--- if chart visualization enabled, then show it ---------------------------
require_once(_base_.'/lib/lib.json.php');
$json = new Services_JSON();
if ($test_info['chart_options'] !== "")
$chart_options = $json->decode($test_info['chart_options']);
else
$chart_options = new stdClass();
if (!property_exists($chart_options, 'use_charts')) $chart_options->use_charts = false;
if (!property_exists($chart_options, 'selected_chart')) $chart_options->selected_chart = 'column';
if (!property_exists($chart_options, 'show_chart')) $chart_options->show_chart = 'teacher';
if ($chart_options->use_charts && $chart_options->show_chart=='course') {
cout('<div class="align-center">', 'content');
$chart = new Test_Charts($test_info['idTest'], Docebo::user()->getIdSt());
$chart->render($chart_options->selected_chart, true);
cout('</div><br /><br />', 'content');
}
//--- end show chart ---------------------------------------------------------
if($feedback_txt) cout('<p>'.$feedback_txt.'</p><br />', 'content');
$points = $point_do + $bonus_score;
if($test_info['show_solution'] == 2 && $points >= $test_info['point_required'])
{
$GLOBALS['page']->add(Form::openForm('test_show', 'index.php?modname=test&op=play')
.Form::getHidden('next_step', 'next_step', 'test_review')
.Form::getHidden('id_test', 'id_test', $id_test)
.Form::getHidden('id_param', 'id_param', $id_param)
.Form::getHidden('back_url', 'back_url', $url_coded)
.Form::getHidden('idTrack', 'idTrack', $id_track)
.Form::getButton('review', 'review', $lang->def('_TEST_REVIEW_ANSWER'))
.Form::closeForm(), 'content');
}
elseif($test_info['show_doanswer'] == 2 && $points >= $test_info['point_required'])
{
$GLOBALS['page']->add(Form::openForm('test_show', 'index.php?modname=test&op=play')
.Form::getHidden('next_step', 'next_step', 'test_review')
.Form::getHidden('id_test', 'id_test', $id_test)
.Form::getHidden('id_param', 'id_param', $id_param)
.Form::getHidden('back_url', 'back_url', $url_coded)
.Form::getHidden('idTrack', 'idTrack', $id_track)
.Form::getButton('review', 'review', $lang->def('_TEST_REVIEW_ANSWER'))
.Form::closeForm(), 'content');
}
elseif($test_info['show_solution'] != 2 && $test_info['show_doanswer'] != 2)
if($test_info['show_solution'] || $test_info['show_doanswer'])
{
$GLOBALS['page']->add(Form::openForm('test_show', 'index.php?modname=test&op=play')
.Form::getHidden('next_step', 'next_step', 'test_review')
.Form::getHidden('id_test', 'id_test', $id_test)
.Form::getHidden('id_param', 'id_param', $id_param)
.Form::getHidden('back_url', 'back_url', $url_coded)
.Form::getHidden('idTrack', 'idTrack', $id_track)
.Form::getButton('review', 'review', $lang->def('_TEST_REVIEW_ANSWER'))
.Form::closeForm(), 'content');
}
$GLOBALS['page']->add(Form::openForm('test_show', Util::str_replace_once('&', '&', $object_test->back_url))
.'<div class="align_right">'
.Form::getButton('end_test', 'end_test', $lang->def('_TEST_END_BACKTOLESSON'))
.'</div>'
.Form::closeForm(), 'content');
$GLOBALS['page']->add('</div>', 'content');
}
else
{
$GLOBALS['page']->add($lang->def('_TEST_BUG_BACK'). '<div align="center"><a href="/appLms/"> Torna alla homepage</a></div>', 'content');
}
}
2) Immagine gif che non viene visualizzata perchè manca l'estensione, nel forum (community)
nel file ->appLms\modules\forum\forum.php sostituire alla riga 340
Code: Select all
.'<img src="'.getPathImage().'emoticons/'.$emoticons.'" title="'.$lang->def('_EMOTICONS').'" alt="'.$lang->def('_EMOTICONS').'" />'
Code: Select all
.'<img src="'.getPathImage().'emoticons/'.$emoticons.'.gif" title="'.$lang->def('_EMOTICONS').'" alt="'.$lang->def('_EMOTICONS').'" />'