Add "allow_gradebook_stats" config to improve gradebook speed

See BT#14357
Requires:
- DB changes see configuration.dist.php
- editing the entities: GradebookLink.php and GradebookEvaluation
pull/2864/head
Julio 7 years ago
parent 48fcdbb6f0
commit efcd6d14dd
  1. 149
      main/exercise/exercise.class.php
  2. 8
      main/gradebook/gradebook_add_eval.php
  3. 13
      main/gradebook/gradebook_add_result.php
  4. 93
      main/gradebook/gradebook_display_summary.php
  5. 11
      main/gradebook/gradebook_edit_result.php
  6. 6
      main/gradebook/gradebook_view_result.php
  7. 133
      main/gradebook/index.php
  8. 28
      main/gradebook/lib/GradebookUtils.php
  9. 52
      main/gradebook/lib/be/abstractlink.class.php
  10. 12
      main/gradebook/lib/be/category.class.php
  11. 111
      main/gradebook/lib/be/evaluation.class.php
  12. 72
      main/gradebook/lib/be/exerciselink.class.php
  13. 4
      main/gradebook/lib/be/linkfactory.class.php
  14. 5
      main/gradebook/lib/be/result.class.php
  15. 200
      main/gradebook/lib/fe/gradebooktable.class.php
  16. 155
      main/gradebook/lib/gradebook_data_generator.class.php
  17. 10
      main/inc/lib/exercise.lib.php
  18. 13
      main/inc/lib/pdf.lib.php
  19. 9
      main/inc/lib/text.lib.php
  20. 7
      main/install/configuration.dist.php
  21. 112
      src/Chamilo/CoreBundle/Entity/GradebookEvaluation.php
  22. 112
      src/Chamilo/CoreBundle/Entity/GradebookLink.php

@ -2767,6 +2767,7 @@ class Exercise
*/ */
public function cleanResults($cleanLpTests = false, $cleanResultBeforeDate = null) public function cleanResults($cleanLpTests = false, $cleanResultBeforeDate = null)
{ {
$sessionId = api_get_session_id();
$table_track_e_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES); $table_track_e_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
$table_track_e_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT); $table_track_e_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
@ -2796,7 +2797,7 @@ class Exercise
WHERE WHERE
c_id = ".api_get_course_int_id()." AND c_id = ".api_get_course_int_id()." AND
exe_exo_id = ".$this->id." AND exe_exo_id = ".$this->id." AND
session_id = ".api_get_session_id()." ". session_id = ".$sessionId." ".
$sql_where; $sql_where;
$result = Database::query($sql); $result = Database::query($sql);
@ -2814,15 +2815,16 @@ class Exercise
} }
} }
$session_id = api_get_session_id();
// delete TRACK_E_EXERCISES table // delete TRACK_E_EXERCISES table
$sql = "DELETE FROM $table_track_e_exercises $sql = "DELETE FROM $table_track_e_exercises
WHERE WHERE
c_id = ".api_get_course_int_id()." AND c_id = ".api_get_course_int_id()." AND
exe_exo_id = ".$this->id." $sql_where AND exe_exo_id = ".$this->id." $sql_where AND
session_id = ".$session_id; session_id = ".$sessionId;
Database::query($sql); Database::query($sql);
$this->generateStats($this->id, api_get_course_info(), $sessionId);
Event::addEvent( Event::addEvent(
LOG_EXERCISE_RESULT_DELETE, LOG_EXERCISE_RESULT_DELETE,
LOG_EXERCISE_ID, LOG_EXERCISE_ID,
@ -2830,7 +2832,7 @@ class Exercise
null, null,
null, null,
api_get_course_int_id(), api_get_course_int_id(),
$session_id $sessionId
); );
return $i; return $i;
@ -7962,6 +7964,145 @@ class Exercise
return $questionList; return $questionList;
} }
/**
* @param int $exerciseId
* @param array $courseInfo
* @param int $sessionId
*
* @return bool
* @throws \Doctrine\ORM\OptimisticLockException
*/
public function generateStats($exerciseId, $courseInfo, $sessionId)
{
$allowStats = api_get_configuration_value('allow_gradebook_stats');
if (!$allowStats) {
return false;
}
if (empty($courseInfo)) {
return false;
}
$courseId = $courseInfo['real_id'];
$sessionId = (int) $sessionId;
$result = $this->read($exerciseId);
if (empty($result)) {
api_not_allowed(true);
}
$statusToFilter = empty($sessionId) ? STUDENT : 0;
$studentList = CourseManager::get_user_list_from_course_code(
api_get_course_id(),
$sessionId,
null,
null,
$statusToFilter
);
if (empty($studentList)) {
Display::addFlash(Display::return_message(get_lang('NoUsersInCourse')));
header('Location: '.api_get_path(WEB_CODE_PATH).'exercise/exercise.php?'.api_get_cidreq());
exit;
}
$tblStats = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
$studentIdList = [];
if (!empty($studentList)) {
$studentIdList = array_column($studentList, 'user_id');
}
if ($this->exercise_was_added_in_lp == false) {
$sql = "SELECT * FROM $tblStats
WHERE
exe_exo_id = $exerciseId AND
orig_lp_id = 0 AND
orig_lp_item_id = 0 AND
status <> 'incomplete' AND
session_id = $sessionId AND
c_id = $courseId
";
} else {
$lpId = null;
if (!empty($this->lpList)) {
// Taking only the first LP
$lpId = current($this->lpList);
$lpId = $lpId['lp_id'];
}
$sql = "SELECT *
FROM $tblStats
WHERE
exe_exo_id = $exerciseId AND
orig_lp_id = $lpId AND
status <> 'incomplete' AND
session_id = $sessionId AND
c_id = $courseId ";
}
$sql .= ' ORDER BY exe_id DESC';
$studentCount = 0;
$sum = 0;
$bestResult = 0;
$weight = 0;
$sumResult = 0;
$result = Database::query($sql);
while ($data = Database::fetch_array($result, 'ASSOC')) {
// Only take into account users in the current student list.
if (!empty($studentIdList)) {
if (!in_array($data['exe_user_id'], $studentIdList)) {
continue;
}
}
if (!isset($students[$data['exe_user_id']])) {
if ($data['exe_weighting'] != 0) {
$students[$data['exe_user_id']] = $data['exe_result'];
$studentCount++;
if ($data['exe_result'] > $bestResult) {
$bestResult = $data['exe_result'];
}
$sum += $data['exe_result'] / $data['exe_weighting'];
$sumResult += $data['exe_result'];
$weight = $data['exe_weighting'];
}
}
}
$count = count($studentList);
$average = $sumResult / $count;
$em = Database::getManager();
$links = AbstractLink::getGradebookLinksFromItem(
$this->selectId(),
LINK_EXERCISE,
api_get_course_id(),
api_get_session_id()
);
$repo = $em->getRepository('ChamiloCoreBundle:GradebookLink');
foreach ($links as $link) {
$linkId = $link['id'];
/** @var \Chamilo\CoreBundle\Entity\GradebookLink $exerciseLink */
$exerciseLink = $repo->find($linkId);
if ($exerciseLink) {
$exerciseLink
->setUserScoreList($students)
->setBestScore($bestResult)
->setAverageScore($average)
->setScoreWeight($this->get_max_score())
;
$em->persist($exerciseLink);
$em->flush();
}
}
}
/** /**
* Gets the question list ordered by the question_order setting (drag and drop). * Gets the question list ordered by the question_order setting (drag and drop).
* *

@ -19,7 +19,7 @@ $evaladd = new Evaluation();
$evaladd->set_user_id($_user['user_id']); $evaladd->set_user_id($_user['user_id']);
if (!empty($select_cat)) { if (!empty($select_cat)) {
$evaladd->set_category_id($_GET['selectcat']); $evaladd->set_category_id($_GET['selectcat']);
$cat = Category :: load($_GET['selectcat']); $cat = Category::load($_GET['selectcat']);
$evaladd->set_course_code($cat[0]->get_course_code()); $evaladd->set_course_code($cat[0]->get_course_code());
} else { } else {
$evaladd->set_category_id(0); $evaladd->set_category_id(0);
@ -49,18 +49,16 @@ if ($form->validate()) {
$eval->set_course_code(api_get_course_id()); $eval->set_course_code(api_get_course_id());
$eval->set_category_id($values['hid_category_id']); $eval->set_category_id($values['hid_category_id']);
$parent_cat = Category :: load($values['hid_category_id']); $parent_cat = Category::load($values['hid_category_id']);
$global_weight = $cat[0]->get_weight(); $global_weight = $cat[0]->get_weight();
//$values['weight'] = $values['weight_mask']/$global_weight*$parent_cat[0]->get_weight(); //$values['weight'] = $values['weight_mask']/$global_weight*$parent_cat[0]->get_weight();
$values['weight'] = $values['weight_mask']; $values['weight'] = $values['weight_mask'];
$eval->set_weight($values['weight']); $eval->set_weight($values['weight']);
$eval->set_max($values['max']); $eval->set_max($values['max']);
$visible = 1;
if (empty($values['visible'])) { if (empty($values['visible'])) {
$visible = 0; $visible = 0;
} else {
$visible = 1;
} }
$eval->set_visible($visible); $eval->set_visible($visible);
$eval->add(); $eval->add();

@ -37,18 +37,25 @@ if ($add_result_form->validate()) {
header('Location: gradebook_view_result.php?addresultnostudents=&selecteval='.$selectEval.'&'.api_get_cidreq()); header('Location: gradebook_view_result.php?addresultnostudents=&selecteval='.$selectEval.'&'.api_get_cidreq());
exit; exit;
} }
$scores = ($values['score']);
foreach ($scores as $row) { $scores = $values['score'];
$sumResult = 0;
$bestResult = 0;
$studentScoreList = [];
foreach ($scores as $userId => $row) {
$res = new Result(); $res = new Result();
$res->set_evaluation_id($values['evaluation_id']); $res->set_evaluation_id($values['evaluation_id']);
$res->set_user_id(key($scores)); $res->set_user_id(key($scores));
//if no scores are given, don't set the score //if no scores are given, don't set the score
if ((!empty($row)) || ($row == '0')) { if (!empty($row) || $row == '0') {
$res->set_score($row); $res->set_score($row);
} }
$res->add(); $res->add();
next($scores); next($scores);
} }
Evaluation::generateStats($values['evaluation_id']);
Display::addFlash(Display::return_message(get_lang('ResultAdded'), 'confirmation', false)); Display::addFlash(Display::return_message(get_lang('ResultAdded'), 'confirmation', false));
header('Location: gradebook_view_result.php?addresult=&selecteval='.$selectEval.'&'.api_get_cidreq()); header('Location: gradebook_view_result.php?addresult=&selecteval='.$selectEval.'&'.api_get_cidreq());
exit; exit;

@ -9,7 +9,7 @@ use ChamiloSession as Session;
require_once __DIR__.'/../inc/global.inc.php'; require_once __DIR__.'/../inc/global.inc.php';
$current_course_tool = TOOL_GRADEBOOK; $current_course_tool = TOOL_GRADEBOOK;
api_protect_course_script(); api_protect_course_script(true);
api_set_more_memory_and_time_limits(); api_set_more_memory_and_time_limits();
api_block_anonymous_users(); api_block_anonymous_users();
GradebookUtils::block_students(); GradebookUtils::block_students();
@ -18,6 +18,7 @@ $cat_id = isset($_GET['selectcat']) ? (int) $_GET['selectcat'] : null;
$action = isset($_GET['action']) && $_GET['action'] ? $_GET['action'] : null; $action = isset($_GET['action']) && $_GET['action'] ? $_GET['action'] : null;
$sessionId = api_get_session_id(); $sessionId = api_get_session_id();
$courseInfo = api_get_course_info();
$statusToFilter = empty($sessionId) ? STUDENT : 0; $statusToFilter = empty($sessionId) ? STUDENT : 0;
$userList = CourseManager::get_user_list_from_course_code( $userList = CourseManager::get_user_list_from_course_code(
@ -28,19 +29,68 @@ $userList = CourseManager::get_user_list_from_course_code(
$statusToFilter $statusToFilter
); );
$loadStats = [];
if (api_get_setting('gradebook_detailed_admin_view') === 'true') {
$loadStats = [1, 2, 3];
} else {
if (api_get_configuration_value('gradebook_enable_best_score') !== false) {
$loadStats = [2];
}
}
/*Session::write('use_gradebook_cache', false);
$useCache = api_get_configuration_value('gradebook_use_apcu_cache');
$cacheAvailable = api_get_configuration_value('apc') && $useCache;
if ($cacheAvailable) {
$cacheDriver = new \Doctrine\Common\Cache\ApcuCache();
$cacheDriver->deleteAll();
$cacheDriver->flushAll();
}*/
switch ($action) { switch ($action) {
case 'export_all': case 'export_all':
//Session::write('use_gradebook_cache', true);
$cats = Category::load($cat_id, null, null, null, null, null, false); $cats = Category::load($cat_id, null, null, null, null, null, false);
$studentList = CourseManager::get_user_list_from_course_code( /** @var Category $cat */
$cat = $cats[0];
$allcat = $cat->get_subcategories(
null,
api_get_course_id(), api_get_course_id(),
$sessionId, api_get_session_id()
);
$alleval = $cat->get_evaluations(
null,
true,
api_get_course_id(),
api_get_session_id()
);
$alllink = $cat->get_links(
null, null,
true,
api_get_course_id(),
api_get_session_id()
);
$gradebooktable = new GradebookTable(
$cat,
$allcat,
$alleval,
$alllink,
null, // params
true, // $exportToPdf
false, // showteacher
null, null,
$statusToFilter $userList,
$loadStats
); );
$key = $gradebooktable->getPreloadDataKey();
// preloads data
Session::erase($key);
$defaultData = $gradebooktable->preloadData();
$tpl = new Template('', false, false, false); $tpl = new Template('', false, false, false);
$courseInfo = api_get_course_info();
$params = [ $params = [
'pdf_title' => sprintf(get_lang('GradeFromX'), $courseInfo['name']), 'pdf_title' => sprintf(get_lang('GradeFromX'), $courseInfo['name']),
'session_info' => '', 'session_info' => '',
@ -54,44 +104,53 @@ switch ($action) {
'orientation' => 'P', 'orientation' => 'P',
]; ];
$pdf = new PDF('A4', $params['orientation'], $params, $tpl); $pdf = new PDF('A4', $params['orientation'], $params, $tpl);
$counter = 0;
$htmlList = []; $htmlList = [];
foreach ($userList as $index => $value) { foreach ($userList as $index => $value) {
$htmlList[] = GradebookUtils::generateTable( $htmlList[] = GradebookUtils::generateTable(
$courseInfo,
$value['user_id'], $value['user_id'],
$cats, $cats,
false,
true, true,
true, $userList,
$studentList,
$pdf $pdf
); );
$counter++;
} }
if (!empty($htmlList)) { if (!empty($htmlList)) {
// Print certificates (without the common header/footer/watermark $counter = 0;
// stuff) and return as one multiple-pages PDF //error_log('Loading html list');
/*$address = api_get_setting('institution_address'); $content = '';
$phone = api_get_setting('administratorTelephone'); foreach ($htmlList as $value) {
$address = str_replace('\n', '<br />', $address); $content .= $value.'<pagebreak>';
$pdf->custom_header = array('html' => "<h5 align='right'>$address <br />$phone</h5>");*/ //error_log('Loading html: '.$counter);
// stuff) and return as one multiple-pages PDF $counter++;
}
$tempFile = api_get_path(SYS_ARCHIVE_PATH).uniqid('gradebook_export_all').'.html';
file_put_contents($tempFile, $content);
//error_log('generating pdf');
$pdf->html_to_pdf( $pdf->html_to_pdf(
$htmlList, $tempFile,
null, null,
null, null,
false, false,
true, true,
true true
); );
//error_log('End generating');
} }
// Delete calc_score session data // Delete calc_score session data
Session::erase('calc_score'); Session::erase('calc_score');
break; break;
case 'download': case 'download':
//Session::write('use_gradebook_cache', true);
$userId = isset($_GET['user_id']) && $_GET['user_id'] ? $_GET['user_id'] : null; $userId = isset($_GET['user_id']) && $_GET['user_id'] ? $_GET['user_id'] : null;
$cats = Category::load($cat_id, null, null, null, null, null, false); $cats = Category::load($cat_id, null, null, null, null, null, false);
GradebookUtils::generateTable($userId, $cats); GradebookUtils::generateTable($courseInfo, $userId, $cats);
break; break;
} }

@ -17,6 +17,9 @@ if (empty($select_eval)) {
$resultedit = Result::load(null, null, $select_eval); $resultedit = Result::load(null, null, $select_eval);
$evaluation = Evaluation::load($select_eval); $evaluation = Evaluation::load($select_eval);
$evaluation[0]->check_lock_permissions(); $evaluation[0]->check_lock_permissions();
$courseInfo = api_get_course_info();
$sessionId = api_get_session_id();
$edit_result_form = new EvalForm( $edit_result_form = new EvalForm(
EvalForm::TYPE_ALL_RESULTS_EDIT, EvalForm::TYPE_ALL_RESULTS_EDIT,
$evaluation[0], $evaluation[0],
@ -28,6 +31,8 @@ $edit_result_form = new EvalForm(
if ($edit_result_form->validate()) { if ($edit_result_form->validate()) {
$values = $edit_result_form->exportValues(); $values = $edit_result_form->exportValues();
$scores = $values['score']; $scores = $values['score'];
$bestResult = 0;
$scoreFinalList = [];
foreach ($scores as $userId => $score) { foreach ($scores as $userId => $score) {
/** @var array $resultedit */ /** @var array $resultedit */
$resultedit = Result::load($userId); $resultedit = Result::load($userId);
@ -37,6 +42,12 @@ if ($edit_result_form->validate()) {
if (empty($score)) { if (empty($score)) {
$score = 0; $score = 0;
} }
$scoreFinalList[$result->get_user_id()] = $score;
if ($score > $bestResult) {
$bestResult = $score;
}
$score = api_number_format($score, api_get_setting('gradebook_number_decimals')); $score = api_number_format($score, api_get_setting('gradebook_number_decimals'));
$result->set_score($score); $result->set_score($score);
$result->save(); $result->save();

@ -25,13 +25,13 @@ $interbreadcrumb[] = [
]; ];
//load the evaluation & category //load the evaluation & category
$select_eval = intval($_GET['selecteval']); $select_eval = (int) $_GET['selecteval'];
if (empty($select_eval)) { if (empty($select_eval)) {
api_not_allowed(); api_not_allowed();
} }
$displayscore = ScoreDisplay::instance(); $displayscore = ScoreDisplay::instance();
$eval = Evaluation :: load($select_eval); $eval = Evaluation::load($select_eval);
$overwritescore = 0; $overwritescore = 0;
if ($eval[0]->get_category_id() < 0) { if ($eval[0]->get_category_id() < 0) {
// if category id is negative, then the evaluation's origin is a link // if category id is negative, then the evaluation's origin is a link
@ -43,7 +43,7 @@ if ($eval[0]->get_category_id() < 0) {
//load the result with the evaluation id //load the result with the evaluation id
if (isset($_GET['delete_mark'])) { if (isset($_GET['delete_mark'])) {
$result = Result :: load($_GET['delete_mark']); $result = Result::load($_GET['delete_mark']);
if (!empty($result[0])) { if (!empty($result[0])) {
$result[0]->delete(); $result[0]->delete();
} }

@ -17,12 +17,66 @@ $current_course_tool = TOOL_GRADEBOOK;
api_block_anonymous_users(); api_block_anonymous_users();
api_protect_course_script(true); api_protect_course_script(true);
ob_start();
$course_code = api_get_course_id(); $course_code = api_get_course_id();
$stud_id = api_get_user_id(); $stud_id = api_get_user_id();
$session_id = api_get_session_id(); $session_id = api_get_session_id();
$course_id = api_get_course_int_id(); $course_id = api_get_course_int_id();
$courseInfo = api_get_course_info();
$action = isset($_GET['action']) ? $_GET['action'] : null;
$itemId = isset($_GET['itemId']) ? $_GET['itemId'] : 0;
switch ($action) {
case 'generate_eval_stats':
if (!empty($itemId)) {
Evaluation::generateStats($itemId);
Display::addFlash(Display::return_message(get_lang('Updated')));
}
header('Location: '.api_get_self().'?'.api_get_cidreq());
exit;
break;
case 'generate_link_stats':
if (!empty($itemId)) {
$link = LinkFactory::create(LINK_EXERCISE);
$links = $link::load($itemId);
/** @var ExerciseLink $link */
foreach ($links as $link) {
$exercise = new Exercise(api_get_course_int_id());
$exercise->read($link->get_ref_id());
$exercise->generateStats($link->get_ref_id(), api_get_course_info(), api_get_session_id());
}
Display::addFlash(Display::return_message(get_lang('Updated')));
}
header('Location: '.api_get_self().'?'.api_get_cidreq());
exit;
break;
case 'lock':
$category_to_lock = Category::load($_GET['category_id']);
$category_to_lock[0]->lockAllItems(1);
$confirmation_message = get_lang('GradebookLockedAlert');
break;
case 'unlock':
if (api_is_platform_admin()) {
$category_to_lock = Category::load($_GET['category_id']);
$category_to_lock[0]->lockAllItems(0);
$confirmation_message = get_lang('EvaluationHasBeenUnLocked');
}
break;
case 'export_table':
$hidePdfReport = api_get_configuration_value('gradebook_hide_pdf_report_button');
if ($hidePdfReport) {
api_not_allowed(true);
}
if (isset($_GET['category_id'])) {
$cats = Category::load($_GET['category_id'], null, null, null, null, null, false);
GradebookUtils::generateTable($courseInfo, api_get_user_id(), $cats);
exit;
}
break;
}
ob_start();
// Make sure the destination for scripts is index.php instead of gradebook.php // Make sure the destination for scripts is index.php instead of gradebook.php
Category::setUrl('index.php'); Category::setUrl('index.php');
@ -262,15 +316,16 @@ if (isset($_GET['moveeval'])) {
//move a link //move a link
if (isset($_GET['movelink'])) { if (isset($_GET['movelink'])) {
$moveLink = (int) $_GET['movelink'];
GradebookUtils::block_students(); GradebookUtils::block_students();
$link = LinkFactory::load($_GET['movelink']); $link = LinkFactory::load($moveLink);
$move_form = new LinkForm( $move_form = new LinkForm(
LinkForm::TYPE_MOVE, LinkForm::TYPE_MOVE,
null, null,
$link[0], $link[0],
'move_link_form', 'move_link_form',
null, null,
api_get_self().'?movelink='.$_GET['movelink'].'&selectcat='.$selectCat.'&'.api_get_cidreq() api_get_self().'?movelink='.$moveLink.'&selectcat='.$selectCat.'&'.api_get_cidreq()
); );
if ($move_form->validate()) { if ($move_form->validate()) {
@ -323,10 +378,9 @@ if (isset($_GET['deletecat'])) {
// Parameters for evaluations. // Parameters for evaluations.
if (isset($_GET['visibleeval'])) { if (isset($_GET['visibleeval'])) {
GradebookUtils::block_students(); GradebookUtils::block_students();
$visibility_command = 0;
if (isset($_GET['set_visible'])) { if (isset($_GET['set_visible'])) {
$visibility_command = 1; $visibility_command = 1;
} else {
$visibility_command = 0;
} }
$eval = Evaluation::load($_GET['visibleeval']); $eval = Evaluation::load($_GET['visibleeval']);
$eval[0]->set_visible($visibility_command); $eval[0]->set_visible($visibility_command);
@ -344,7 +398,7 @@ if (isset($_GET['visibleeval'])) {
// Parameters for evaluations. // Parameters for evaluations.
if (isset($_GET['lockedeval'])) { if (isset($_GET['lockedeval'])) {
GradebookUtils::block_students(); GradebookUtils::block_students();
$locked = Security::remove_XSS($_GET['lockedeval']); $locked = (int) $_GET['lockedeval'];
if (isset($_GET['typelocked']) && api_is_platform_admin()) { if (isset($_GET['typelocked']) && api_is_platform_admin()) {
$type_locked = 0; $type_locked = 0;
$confirmation_message = get_lang('EvaluationHasBeenUnLocked'); $confirmation_message = get_lang('EvaluationHasBeenUnLocked');
@ -373,10 +427,9 @@ if (isset($_GET['deleteeval'])) {
// Parameters for links. // Parameters for links.
if (isset($_GET['visiblelink'])) { if (isset($_GET['visiblelink'])) {
GradebookUtils::block_students(); GradebookUtils::block_students();
$visibility_command = 0;
if (isset($_GET['set_visible'])) { if (isset($_GET['set_visible'])) {
$visibility_command = 1; $visibility_command = 1;
} else {
$visibility_command = 0;
} }
$link = LinkFactory::load($_GET['visiblelink']); $link = LinkFactory::load($_GET['visiblelink']);
if (isset($link) && isset($link[0])) { if (isset($link) && isset($link[0])) {
@ -395,7 +448,7 @@ if (isset($_GET['visiblelink'])) {
if (isset($_GET['deletelink'])) { if (isset($_GET['deletelink'])) {
GradebookUtils::block_students(); GradebookUtils::block_students();
$get_delete_link = intval($_GET['deletelink']); $get_delete_link = (int) $_GET['deletelink'];
//fixing #5229 //fixing #5229
if (!empty($get_delete_link)) { if (!empty($get_delete_link)) {
$link = LinkFactory::load($get_delete_link); $link = LinkFactory::load($get_delete_link);
@ -441,38 +494,13 @@ if (!empty($course_to_crsind) && !isset($_GET['confirm'])) {
$filter_warning_msg = false; $filter_warning_msg = false;
} }
$action = isset($_GET['action']) ? $_GET['action'] : null;
switch ($action) {
case 'lock':
$category_to_lock = Category::load($_GET['category_id']);
$category_to_lock[0]->lockAllItems(1);
$confirmation_message = get_lang('GradebookLockedAlert');
break;
case 'unlock':
if (api_is_platform_admin()) {
$category_to_lock = Category::load($_GET['category_id']);
$category_to_lock[0]->lockAllItems(0);
$confirmation_message = get_lang('EvaluationHasBeenUnLocked');
}
break;
case 'export_table':
$hidePdfReport = api_get_configuration_value('gradebook_hide_pdf_report_button');
if ($hidePdfReport) {
api_not_allowed(true);
}
//table will be export below
ob_start();
break;
}
// Actions on the sortabletable. // Actions on the sortabletable.
if (isset($_POST['action'])) { if (isset($_POST['action'])) {
GradebookUtils::block_students(); GradebookUtils::block_students();
$number_of_selected_items = count($_POST['id']); $number_of_selected_items = count($_POST['id']);
if ($number_of_selected_items == '0') { if ($number_of_selected_items == 0) {
$warning_message = get_lang('NoItemsSelected'); $warning_message = get_lang('NoItemsSelected');
$filter_warning_msg = false; $filter_warning_msg = false;
} else { } else {
@ -751,11 +779,9 @@ if (isset($_GET['studentoverview'])) {
} }
$cats = Category::load($selectCat, null, null, null, null, null, false); $cats = Category::load($selectCat, null, null, null, null, null, false);
//with this fix the teacher only can view 1 gradebook // With this fix the teacher only can view 1 gradebook
if (api_is_platform_admin()) { if (api_is_platform_admin()) {
$stud_id = (api_is_allowed_to_edit() ? null : api_get_user_id()); $stud_id = (api_is_allowed_to_edit() ? null : api_get_user_id());
} else {
$stud_id = $stud_id;
} }
$allcat = $cats[0]->get_subcategories($stud_id, $course_code, $session_id); $allcat = $cats[0]->get_subcategories($stud_id, $course_code, $session_id);
@ -787,7 +813,6 @@ if (!empty($selectCat)) {
$cat = new Category(); $cat = new Category();
$course_id = CourseManager::get_course_by_category($selectCat); $course_id = CourseManager::get_course_by_category($selectCat);
$show_message = $cat->show_message_resource_delete($course_id); $show_message = $cat->show_message_resource_delete($course_id);
if ($show_message == '') { if ($show_message == '') {
// Student // Student
if (!api_is_allowed_to_edit() && !api_is_excluded_user_type()) { if (!api_is_allowed_to_edit() && !api_is_excluded_user_type()) {
@ -819,7 +844,7 @@ if (!api_is_allowed_to_edit(null, true)) {
if ($allowButton) { if ($allowButton) {
$actionsLeft .= Display::url( $actionsLeft .= Display::url(
Display::returnFontAwesomeIcon('file-pdf-o').get_lang('DownloadReportPdf'), Display::returnFontAwesomeIcon('file-pdf-o').get_lang('DownloadReportPdf'),
api_get_self().'?action=export_table&'.api_get_cidreq(), api_get_self().'?action=export_table&'.api_get_cidreq().'&category_id='.$selectCat,
['class' => 'btn btn-default'] ['class' => 'btn btn-default']
); );
} }
@ -960,7 +985,7 @@ if (isset($first_time) && $first_time == 1 && api_is_allowed_to_edit(null, true)
if (api_is_allowed_to_edit(null, true) && if (api_is_allowed_to_edit(null, true) &&
api_get_setting('gradebook_enable_grade_model') === 'true' api_get_setting('gradebook_enable_grade_model') === 'true'
) { ) {
//Showing the grading system // Showing the grading system
if (!empty($grade_models[$grade_model_id])) { if (!empty($grade_models[$grade_model_id])) {
echo Display::return_message( echo Display::return_message(
get_lang('GradeModel').': '.$grade_models[$grade_model_id]['name'] get_lang('GradeModel').': '.$grade_models[$grade_model_id]['name']
@ -1002,28 +1027,6 @@ if (isset($first_time) && $first_time == 1 && api_is_allowed_to_edit(null, true)
$gradebookTable->td_attributes = [ $gradebookTable->td_attributes = [
4 => 'class="text-center"', 4 => 'class="text-center"',
]; ];
} else {
/*if (empty($model)) {
$gradebookTable->td_attributes = [
3 => 'class="text-right"',
4 => 'class="text-center"',
];
if (!empty($loadStats)) {
for ($z = 5; $z < count($loadStats); $z++) {
$gradebookTable->td_attributes[$z] = 'class="text-center"';
}
}
} else {
$gradebookTable->td_attributes = [
3 => 'class="text-right"',
4 => 'class="text-center"',
];
}
if ($action == 'export_table') {
unset($gradebookTable->td_attributes[7]);
}*/
} }
$table = $gradebookTable->return_table(); $table = $gradebookTable->return_table();
@ -1034,7 +1037,7 @@ if (isset($first_time) && $first_time == 1 && api_is_allowed_to_edit(null, true)
$graph = $gradebookTable->getGraph(); $graph = $gradebookTable->getGraph();
} }
if ($action == 'export_table') { if ($action === 'export_table') {
ob_clean(); ob_clean();
$params = [ $params = [
'pdf_title' => sprintf(get_lang('GradeFromX'), $courseInfo['name']), 'pdf_title' => sprintf(get_lang('GradeFromX'), $courseInfo['name']),

@ -378,6 +378,7 @@ class GradebookUtils
ICON_SIZE_SMALL ICON_SIZE_SMALL
). ).
'</a>'; '</a>';
if (api_is_allowed_to_edit(null, true)) { if (api_is_allowed_to_edit(null, true)) {
$modify_icons .= '&nbsp;<a href="gradebook_showlog_eval.php?visiblelog='.$eval->get_id().'&selectcat='.$selectcat.' &'.$courseParams.'">'. $modify_icons .= '&nbsp;<a href="gradebook_showlog_eval.php?visiblelog='.$eval->get_id().'&selectcat='.$selectcat.' &'.$courseParams.'">'.
Display::return_icon( Display::return_icon(
@ -387,6 +388,14 @@ class GradebookUtils
ICON_SIZE_SMALL ICON_SIZE_SMALL
). ).
'</a>'; '</a>';
$allowStats = api_get_configuration_value('allow_gradebook_stats');
if ($allowStats) {
$modify_icons .= Display::url(
Display::return_icon('reload.png', get_lang('GenerateStats')),
api_get_self().'?itemId='.$eval->get_id().'&action=generate_eval_stats&selectcat='.$selectcat.'&'.$courseParams
);
}
} }
if ($is_locked && !api_is_platform_admin()) { if ($is_locked && !api_is_platform_admin()) {
@ -466,6 +475,7 @@ class GradebookUtils
ICON_SIZE_SMALL ICON_SIZE_SMALL
). ).
'</a>'; '</a>';
$modify_icons .= '&nbsp;<a href="gradebook_showlog_link.php?visiblelink='.$link->get_id().'&selectcat='.$selectcat.'&'.$courseParams.'">'. $modify_icons .= '&nbsp;<a href="gradebook_showlog_link.php?visiblelink='.$link->get_id().'&selectcat='.$selectcat.'&'.$courseParams.'">'.
Display::return_icon( Display::return_icon(
'history.png', 'history.png',
@ -475,6 +485,14 @@ class GradebookUtils
). ).
'</a>'; '</a>';
$allowStats = api_get_configuration_value('allow_gradebook_stats');
if ($allowStats && $link->get_type() == LINK_EXERCISE) {
$modify_icons .= Display::url(
Display::return_icon('reload.png', get_lang('GenerateStats')),
api_get_self().'?itemId='.$link->get_id().'&action=generate_link_stats&selectcat='.$selectcat.'&'.$courseParams
);
}
//If a work is added in a gradebook you can only delete the link in the work tool //If a work is added in a gradebook you can only delete the link in the work tool
if ($is_locked && !api_is_platform_admin()) { if ($is_locked && !api_is_platform_admin()) {
$modify_icons .= '&nbsp;'. $modify_icons .= '&nbsp;'.
@ -1523,6 +1541,8 @@ class GradebookUtils
} }
/** /**
* @param GradebookTable $gradebooktable
* @param array $courseInfo
* @param int $userId * @param int $userId
* @param array $cats * @param array $cats
* @param bool $saveToFile * @param bool $saveToFile
@ -1533,6 +1553,7 @@ class GradebookUtils
* @return string * @return string
*/ */
public static function generateTable( public static function generateTable(
$courseInfo,
$userId, $userId,
$cats, $cats,
$saveToFile = false, $saveToFile = false,
@ -1540,9 +1561,7 @@ class GradebookUtils
$studentList = [], $studentList = [],
$pdf = null $pdf = null
) { ) {
$courseInfo = api_get_course_info();
$userInfo = api_get_user_info($userId); $userInfo = api_get_user_info($userId);
$cat = $cats[0]; $cat = $cats[0];
$allcat = $cats[0]->get_subcategories( $allcat = $cats[0]->get_subcategories(
$userId, $userId,
@ -1577,9 +1596,6 @@ class GradebookUtils
$gradebooktable->userId = $userId; $gradebooktable->userId = $userId;
if (api_is_allowed_to_edit(null, true)) { if (api_is_allowed_to_edit(null, true)) {
/*$gradebooktable->td_attributes = [
4 => 'class=centered',
];*/
} else { } else {
$gradebooktable->td_attributes = [ $gradebooktable->td_attributes = [
3 => 'class=centered', 3 => 'class=centered',
@ -1589,7 +1605,6 @@ class GradebookUtils
7 => 'class=centered', 7 => 'class=centered',
]; ];
} }
$table = $gradebooktable->return_table(); $table = $gradebooktable->return_table();
$graph = $gradebooktable->getGraph(); $graph = $gradebooktable->getGraph();
@ -1626,6 +1641,7 @@ class GradebookUtils
); );
if ($saveToHtmlFile) { if ($saveToHtmlFile) {
return $result;
file_put_contents($file, $result); file_put_contents($file, $result);
return $file; return $file;

@ -28,6 +28,8 @@ abstract class AbstractLink implements GradebookItem
protected $weight; protected $weight;
protected $visible; protected $visible;
protected $session_id; protected $session_id;
/** @var \Chamilo\CoreBundle\Entity\GradebookLink */
public $entity;
/** /**
* Constructor. * Constructor.
@ -699,6 +701,12 @@ abstract class AbstractLink implements GradebookItem
private static function create_objects_from_sql_result($result) private static function create_objects_from_sql_result($result)
{ {
$links = []; $links = [];
$allow = api_get_configuration_value('allow_gradebook_stats');
if ($allow) {
$em = Database::getManager();
$repo = $em->getRepository('ChamiloCoreBundle:GradebookLink');
}
while ($data = Database::fetch_array($result)) { while ($data = Database::fetch_array($result)) {
$link = LinkFactory::create($data['type']); $link = LinkFactory::create($data['type']);
$link->set_id($data['id']); $link->set_id($data['id']);
@ -714,8 +722,11 @@ abstract class AbstractLink implements GradebookItem
//session id should depend of the category --> $data['category_id'] //session id should depend of the category --> $data['category_id']
$session_id = api_get_session_id(); $session_id = api_get_session_id();
$link->set_session_id($session_id); $link->set_session_id($session_id);
if ($allow) {
$link->entity = $repo->find($data['id']);
}
$links[] = $link; $links[] = $link;
} }
@ -745,4 +756,43 @@ abstract class AbstractLink implements GradebookItem
return $targets; return $targets;
} }
/**
* @param int $itemId
* @param int $linkType
* @param string $courseCode
* @param int $sessionId
*
* @return array|bool|\Doctrine\DBAL\Driver\Statement
*/
public static function getGradebookLinksFromItem($itemId, $linkType, $courseCode, $sessionId = 0)
{
if (empty($courseCode) || empty($itemId) || empty($linkType)) {
return false;
}
$table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
$tableCategory = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
$itemId = (int) $itemId;
$linkType = (int) $linkType;
$sessionId = (int) $sessionId;
$courseCode = Database::escape_string($courseCode);
$sql = "SELECT DISTINCT l.*
FROM $table l INNER JOIN $tableCategory c
ON (c.course_code = l.course_code AND c.id = l.category_id)
WHERE
ref_id = $itemId AND
type = $linkType AND
l.course_code = '$courseCode' AND
c.session_id = $sessionId";
$result = Database::query($sql);
if (Database::num_rows($result)) {
$result = Database::store_result($result);
return $result;
}
return false;
}
} }

@ -34,6 +34,8 @@ class Category implements GradebookItem
private $minimumToValidate; private $minimumToValidate;
/** @var int */ /** @var int */
private $gradeBooksToValidateInDependence; private $gradeBooksToValidateInDependence;
/** @var GradebookCategory */
public $entity;
/** /**
* Consctructor. * Consctructor.
@ -2571,6 +2573,12 @@ class Category implements GradebookItem
private static function create_category_objects_from_sql_result($result) private static function create_category_objects_from_sql_result($result)
{ {
$categories = []; $categories = [];
$allow = api_get_configuration_value('allow_gradebook_stats');
if ($allow) {
$em = Database::getManager();
$repo = $em->getRepository('ChamiloCoreBundle:GradebookCategory');
}
while ($data = Database::fetch_array($result)) { while ($data = Database::fetch_array($result)) {
$cat = new Category(); $cat = new Category();
$cat->set_id($data['id']); $cat->set_id($data['id']);
@ -2591,6 +2599,10 @@ class Category implements GradebookItem
$cat->setMinimumToValidate(isset($data['minimum_to_validate']) ? $data['minimum_to_validate'] : null); $cat->setMinimumToValidate(isset($data['minimum_to_validate']) ? $data['minimum_to_validate'] : null);
$cat->setGradeBooksToValidateInDependence(isset($data['gradebooks_to_validate_in_dependence']) ? $data['gradebooks_to_validate_in_dependence'] : null); $cat->setGradeBooksToValidateInDependence(isset($data['gradebooks_to_validate_in_dependence']) ? $data['gradebooks_to_validate_in_dependence'] : null);
if ($allow) {
$cat->entity = $repo->find($data['id']);
}
$categories[] = $cat; $categories[] = $cat;
} }

@ -23,6 +23,8 @@ class Evaluation implements GradebookItem
private $eval_max; private $eval_max;
private $visible; private $visible;
private $sessionId; private $sessionId;
/** @var \Chamilo\CoreBundle\Entity\GradebookEvaluation */
public $entity;
/** /**
* Construct. * Construct.
@ -534,6 +536,55 @@ class Evaluation implements GradebookItem
*/ */
public function calc_score($stud_id = null, $type = null) public function calc_score($stud_id = null, $type = null)
{ {
$allowStats = api_get_configuration_value('allow_gradebook_stats');
if ($allowStats) {
$evaluation = $this->entity;
if (!empty($evaluation)) {
$weight = $evaluation->getMax();
switch ($type) {
case 'best':
$bestResult = $evaluation->getBestScore();
$result = [$bestResult, $weight];
return $result;
break;
case 'average':
$count = count($evaluation->getUserScoreList());
if (empty($count)) {
$result = [0, $weight];
return $result;
}
$sumResult = array_sum($evaluation->getUserScoreList());
$result = [$sumResult / $count, $weight];
return $result;
break;
case 'ranking':
$ranking = AbstractLink::getCurrentUserRanking($stud_id, $evaluation->getUserScoreList());
return $ranking;
break;
default:
$weight = $evaluation->getMax();
if (!empty($stud_id)) {
$scoreList = $evaluation->getUserScoreList();
$result = [0, $weight];
if (isset($scoreList[$stud_id])) {
$result = [$scoreList[$stud_id], $weight];
}
return $result;
} else {
$studentCount = count($evaluation->getUserScoreList());
$sumResult = array_sum($evaluation->getUserScoreList());
$result = [$sumResult, $studentCount];
}
return $result;
break;
}
}
}
$useSession = true; $useSession = true;
if (isset($stud_id) && empty($type)) { if (isset($stud_id) && empty($type)) {
$key = 'result_score_student_list_'.api_get_course_int_id().'_'.api_get_session_id().'_'.$this->id.'_'.$stud_id; $key = 'result_score_student_list_'.api_get_course_int_id().'_'.api_get_session_id().'_'.$this->id.'_'.$stud_id;
@ -803,16 +854,66 @@ class Evaluation implements GradebookItem
{ {
} }
/**
* @return mixed
*/
public function getStudentList() public function getStudentList()
{ {
return $this->studentList; return $this->studentList;
} }
/**
* @param $list
*/
public function setStudentList($list) public function setStudentList($list)
{ {
$this->studentList = $list; $this->studentList = $list;
} }
/**
* @param int $evaluationId
*
*/
public static function generateStats($evaluationId)
{
$allowStats = api_get_configuration_value('allow_gradebook_stats');
if ($allowStats) {
$evaluation = self::load($evaluationId);
$results = Result::load(null, null, $evaluationId);
$sumResult = 0;
$bestResult = 0;
$average = 0;
$scoreList = [];
if (!empty($results)) {
/** @var Result $result */
foreach ($results as $result) {
$score = $result->get_score();
$scoreList[$result->get_user_id()] = $score;
$sumResult += $score;
if ($score > $bestResult) {
$bestResult = $score;
}
}
$average = $sumResult / count($results);
}
/** @var Evaluation $evaluation */
$evaluation = $evaluation[0];
$evaluation = $evaluation->entity;
$evaluation
->setBestScore($bestResult)
->setAverageScore($average)
->setUserScoreList($scoreList)
;
$em = Database::getManager();
$em->persist($evaluation);
$em->flush();
}
}
/** /**
* @param array $result * @param array $result
* *
@ -821,6 +922,12 @@ class Evaluation implements GradebookItem
private static function create_evaluation_objects_from_sql_result($result) private static function create_evaluation_objects_from_sql_result($result)
{ {
$alleval = []; $alleval = [];
$allow = api_get_configuration_value('allow_gradebook_stats');
if ($allow) {
$em = Database::getManager();
$repo = $em->getRepository('ChamiloCoreBundle:GradebookEvaluation');
}
if (Database::num_rows($result)) { if (Database::num_rows($result)) {
while ($data = Database::fetch_array($result)) { while ($data = Database::fetch_array($result)) {
$eval = new Evaluation(); $eval = new Evaluation();
@ -838,6 +945,10 @@ class Evaluation implements GradebookItem
$eval->set_locked($data['locked']); $eval->set_locked($data['locked']);
$eval->setSessionId(api_get_session_id()); $eval->setSessionId(api_get_session_id());
if ($allow) {
$eval->entity = $repo->find($data['id']);
}
$alleval[] = $eval; $alleval[] = $eval;
} }
} }

@ -1,6 +1,8 @@
<?php <?php
/* For licensing terms, see /license.txt */ /* For licensing terms, see /license.txt */
use ChamiloSession as Session;
/** /**
* Class ExerciseLink * Class ExerciseLink
* Defines a gradebook ExerciseLink object. * Defines a gradebook ExerciseLink object.
@ -176,6 +178,61 @@ class ExerciseLink extends AbstractLink
*/ */
public function calc_score($stud_id = null, $type = null) public function calc_score($stud_id = null, $type = null)
{ {
$allowStats = api_get_configuration_value('allow_gradebook_stats');
if ($allowStats) {
$link = $this->entity;
if (!empty($link)) {
$weight = $link->getScoreWeight();
switch ($type) {
case 'best':
$bestResult = $link->getBestScore();
$result = [$bestResult, $weight];
return $result;
break;
case 'average':
$count = count($this->getStudentList());
if (empty($count)) {
$result = [0, $weight];
return $result;
}
$sumResult = array_sum($link->getUserScoreList());
$result = [$sumResult / $count, $weight];
return $result;
break;
case 'ranking':
return '';
$newList = [];
var_dump($this->getStudentList());exit;
foreach ($this->getStudentList() as $userId) {
}
$ranking = AbstractLink::getCurrentUserRanking($stud_id, $link->getUserScoreList());
return $ranking;
break;
default:
if (!empty($stud_id)) {
$scoreList = $link->getUserScoreList();
$result = [0, $weight];
if (isset($scoreList[$stud_id])) {
$result = [$scoreList[$stud_id], $weight];
}
return $result;
} else {
$studentCount = count($this->getStudentList());
$sumResult = array_sum($link->getUserScoreList());
$result = [$sumResult, $studentCount];
}
return $result;
break;
}
}
}
$tblStats = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES); $tblStats = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
$tblHp = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTPOTATOES); $tblHp = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTPOTATOES);
$tblDoc = Database::get_course_table(TABLE_DOCUMENT); $tblDoc = Database::get_course_table(TABLE_DOCUMENT);
@ -185,6 +242,7 @@ class ExerciseLink extends AbstractLink
$sessionId = $this->get_session_id(); $sessionId = $this->get_session_id();
$courseId = $this->getCourseId(); $courseId = $this->getCourseId();
$exerciseData = $this->get_exercise_data(); $exerciseData = $this->get_exercise_data();
$exerciseId = isset($exerciseData['id']) ? $exerciseData['id'] : 0; $exerciseId = isset($exerciseData['id']) ? $exerciseData['id'] : 0;
$stud_id = (int) $stud_id; $stud_id = (int) $stud_id;
@ -559,4 +617,18 @@ class ExerciseLink extends AbstractLink
return $this->exercise_data; return $this->exercise_data;
} }
public function getBestScore()
{
return $this->getStats('best');
}
public function getStats($type)
{
switch ($type) {
case 'best':
break;
}
}
} }

@ -74,11 +74,11 @@ class LinkFactory
/** /**
* Static method to create specific link objects. * Static method to create specific link objects.
* *
* @param $type link type * @param int $type link type
*/ */
public static function create($type) public static function create($type)
{ {
$type = intval($type); $type = (int) $type;
switch ($type) { switch ($type) {
case LINK_EXERCISE: case LINK_EXERCISE:
return new ExerciseLink(); return new ExerciseLink();

@ -179,7 +179,6 @@ class Result
$sql .= ' WHERE'; $sql .= ' WHERE';
} }
$sql .= ' gr.evaluation_id = '.intval($evaluation_id); $sql .= ' gr.evaluation_id = '.intval($evaluation_id);
$paramcount++;
} }
$sql .= ' ORDER BY u.lastname, u.firstname'; $sql .= ' ORDER BY u.lastname, u.firstname';
@ -273,6 +272,8 @@ class Result
$sql .= ' WHERE id = '.$this->id; $sql .= ' WHERE id = '.$this->id;
// no need to update creation date // no need to update creation date
Database::query($sql); Database::query($sql);
Evaluation::generateStats($this->get_evaluation_id());
} }
/** /**
@ -289,6 +290,8 @@ class Result
$sql = "DELETE FROM $table WHERE result_id = ".$this->id; $sql = "DELETE FROM $table WHERE result_id = ".$this->id;
Database::query($sql); Database::query($sql);
} }
Evaluation::generateStats($this->get_evaluation_id());
} }
/** /**

@ -4,6 +4,7 @@
use CpChart\Cache as pCache; use CpChart\Cache as pCache;
use CpChart\Data as pData; use CpChart\Data as pData;
use CpChart\Image as pImage; use CpChart\Image as pImage;
use ChamiloSession as Session;
/** /**
* GradebookTable Class * GradebookTable Class
@ -63,6 +64,7 @@ class GradebookTable extends SortableTable
$this->teacherView = is_null($showTeacherView) ? api_is_allowed_to_edit(null, true) : $showTeacherView; $this->teacherView = is_null($showTeacherView) ? api_is_allowed_to_edit(null, true) : $showTeacherView;
$this->userId = is_null($userId) ? api_get_user_id() : $userId; $this->userId = is_null($userId) ? api_get_user_id() : $userId;
$this->exportToPdf = $exportToPdf; $this->exportToPdf = $exportToPdf;
$this->studentList = $studentList;
parent::__construct( parent::__construct(
'gradebooklist', 'gradebooklist',
@ -79,6 +81,8 @@ class GradebookTable extends SortableTable
$this->cats = $cats; $this->cats = $cats;
$this->loadStats = $loadStats; $this->loadStats = $loadStats;
$this->datagen = new GradebookDataGenerator($cats, $evals, $links); $this->datagen = new GradebookDataGenerator($cats, $evals, $links);
$this->datagen->preLoadDataKey = $this->getPreloadDataKey();
$this->datagen->hidePercentage = api_get_configuration_value('hide_gradebook_percentage_user_result'); $this->datagen->hidePercentage = api_get_configuration_value('hide_gradebook_percentage_user_result');
if (!empty($userId)) { if (!empty($userId)) {
@ -182,6 +186,105 @@ class GradebookTable extends SortableTable
return $this->datagen->get_total_items_count(); return $this->datagen->get_total_items_count();
} }
/**
* @return string
*/
public function getPreloadDataKey()
{
return 'default_data_'.api_get_course_id().'_'.api_get_session_id();
}
public function preloadData()
{
$allitems = $this->datagen->items;
usort($allitems, ['GradebookDataGenerator', 'sort_by_name']);
//$visibleItems = $this->datagen->items;
$visibleItems = array_merge($this->datagen->items, $this->evals_links);
//Session::erase($this->getPreloadDataKey());
$defaultDataFromSession = Session::read($this->getPreloadDataKey());
if (empty($defaultDataFromSession)) {
$defaultData = [];
/** @var GradebookItem $item */
foreach ($visibleItems as $item) {
$item->setStudentList($this->studentList);
$itemType = get_class($item);
switch ($itemType) {
case 'Evaluation':
// Best
$best = $this->datagen->buildBestResultColumn($item);
$defaultData[$item->get_id()]['best'] = $best;
// Average
$average = $this->datagen->buildAverageResultColumn($item);
$defaultData[$item->get_id()]['average'] = $average;
break;
case 'ExerciseLink':
/** @var ExerciseLink $item */
// Best
$best = $this->datagen->buildBestResultColumn($item);
$defaultData[$item->get_id()]['best'] = $best;
// Average
$average = $this->datagen->buildAverageResultColumn($item);
$defaultData[$item->get_id()]['average'] = $average;
// Ranking
/*if (!empty($this->studentList)) {
$invalidateRanking = true;
foreach ($this->studentList as $user) {
$score = $this->datagen->build_result_column(
$user['user_id'],
$item,
false,
true
);
if (!empty($score['score'])) {
$invalidateRanking = false;
}
$rankingStudentList[$user['user_id']] = $score['score'][0];
$defaultData[$item->get_id()]['ranking'] = $rankingStudentList;
$defaultData[$item->get_id()]['ranking_invalidate'] = $invalidateRanking;
}
}*/
break;
default:
// Best
$best = $this->datagen->buildBestResultColumn($item);
$defaultData[$item->get_id()]['best'] = $best;
// Average
$average = $this->datagen->buildAverageResultColumn($item);
$defaultData[$item->get_id()]['average'] = $average;
// Ranking
if (!empty($this->studentList)) {
$invalidateRanking = true;
foreach ($this->studentList as $user) {
$score = $this->datagen->build_result_column(
$user['user_id'],
$item,
false,
true
);
if (!empty($score['score'])) {
$invalidateRanking = false;
}
$rankingStudentList[$user['user_id']] = $score['score'][0];
$defaultData[$item->get_id()]['ranking'] = $rankingStudentList;
$defaultData[$item->get_id()]['ranking_invalidate'] = $invalidateRanking;
}
//exit;
}
break;
}
}
Session::write($this->getPreloadDataKey(), $defaultData);
} else {
$defaultData = $defaultDataFromSession;
}
return $defaultData;
}
/** /**
* Function used by SortableTable to generate the data to display. * Function used by SortableTable to generate the data to display.
* *
@ -292,12 +395,16 @@ class GradebookTable extends SortableTable
$userExerciseScoreInCategory = api_get_configuration_value( $userExerciseScoreInCategory = api_get_configuration_value(
'gradebook_use_exercise_score_settings_in_categories' 'gradebook_use_exercise_score_settings_in_categories'
); );
$course_code = api_get_course_id();
$session_id = api_get_session_id();
$defaultData = Session::read($this->getPreloadDataKey());
// Categories. // Categories.
if (!empty($data_array)) { if (!empty($data_array)) {
foreach ($data_array as $data) { foreach ($data_array as $data) {
// list of items inside the gradebook (exercises, lps, forums, etc) // list of items inside the gradebook (exercises, lps, forums, etc)
$row = []; $row = [];
/** @var AbstractLink $item */ /** @var AbstractLink $item */
$item = $mainCategory = $data[0]; $item = $mainCategory = $data[0];
@ -316,7 +423,7 @@ class GradebookTable extends SortableTable
$row[] = $this->build_type_column($item); $row[] = $this->build_type_column($item);
// Name. // Name.
if (get_class($item) == 'Category') { if (get_class($item) === 'Category') {
$row[] = $invisibility_span_open.'<strong>'.$item->get_name().'</strong>'.$invisibility_span_close; $row[] = $invisibility_span_open.'<strong>'.$item->get_name().'</strong>'.$invisibility_span_close;
$main_categories[$item->get_id()]['name'] = $item->get_name(); $main_categories[$item->get_id()]['name'] = $item->get_name();
} else { } else {
@ -383,7 +490,7 @@ class GradebookTable extends SortableTable
} }
// Students get the results and certificates columns // Students get the results and certificates columns
if (1) {
$value_data = isset($data[4]) ? $data[4] : null; $value_data = isset($data[4]) ? $data[4] : null;
$best = isset($data['best']) ? $data['best'] : null; $best = isset($data['best']) ? $data['best'] : null;
$average = isset($data['average']) ? $data['average'] : null; $average = isset($data['average']) ? $data['average'] : null;
@ -460,29 +567,20 @@ class GradebookTable extends SortableTable
} }
} }
if (get_class($item) == 'Category') { if (get_class($item) === 'Category') {
if ($this->exportToPdf == false) {
$row[] = $this->build_edit_column($item);
}
}
} else {
$row[] = $scoreToDisplay;
if (!empty($this->cats)) {
if ($this->exportToPdf == false) { if ($this->exportToPdf == false) {
$row[] = $this->build_edit_column($item); $row[] = $this->build_edit_column($item);
} }
} }
} }
}
// Category added. // Category added.
$sortable_data[] = $row; $sortable_data[] = $row;
// Loading children // Loading children
if (get_class($item) == 'Category') { if (get_class($item) === 'Category') {
$course_code = api_get_course_id();
$session_id = api_get_session_id();
$parent_id = $item->get_id(); $parent_id = $item->get_id();
$cats = Category::load( $cats = Category::load(
$parent_id, $parent_id,
null, null,
@ -500,6 +598,7 @@ class GradebookTable extends SortableTable
$alllink = $subCategory->get_links($this->userId); $alllink = $subCategory->get_links($this->userId);
$sub_cat_info = new GradebookDataGenerator($allcat, $alleval, $alllink); $sub_cat_info = new GradebookDataGenerator($allcat, $alleval, $alllink);
$sub_cat_info->preLoadDataKey = $this->getPreloadDataKey();
$sub_cat_info->userId = $user_id; $sub_cat_info->userId = $user_id;
$data_array2 = $sub_cat_info->get_data( $data_array2 = $sub_cat_info->get_data(
$sorting, $sorting,
@ -534,7 +633,7 @@ class GradebookTable extends SortableTable
$row[] = $this->build_type_column($item, ['style' => 'padding-left:5px']); $row[] = $this->build_type_column($item, ['style' => 'padding-left:5px']);
// Name. // Name.
$row[] = $invisibility_span_open."&nbsp;&nbsp;&nbsp; ". $row[] = $invisibility_span_open.'&nbsp;&nbsp;&nbsp; '.
$this->build_name_link($item, $type).$invisibility_span_close; $this->build_name_link($item, $type).$invisibility_span_close;
// Description. // Description.
@ -652,7 +751,7 @@ class GradebookTable extends SortableTable
foreach ($main_cat as $myCat) { foreach ($main_cat as $myCat) {
$myParentId = $myCat->get_parent_id(); $myParentId = $myCat->get_parent_id();
if ($myParentId == 0) { if ($myParentId == 0) {
$main_weight = intval($myCat->get_weight()); $main_weight = (int) $myCat->get_weight();
} }
} }
} }
@ -682,22 +781,18 @@ class GradebookTable extends SortableTable
} else { } else {
// Total for student. // Total for student.
if (count($main_cat) > 1) { if (count($main_cat) > 1) {
$weights = []; $main_weight = (int) $main_cat[0]->get_weight();
foreach ($main_categories as $cat) {
$weights[] = $cat['weight'];
}
$main_weight = intval($main_cat[0]->get_weight());
$global = null; $global = null;
$average = null; $average = null;
$myTotal = 0; $myTotal = 0;
foreach ($this->dataForGraph['my_result_no_float'] as $result) { foreach ($this->dataForGraph['my_result_no_float'] as $result) {
$myTotal += $scoredisplay->format_score($result); $myTotal += $result;
} }
$totalResult[0] = $myTotal; $totalResult[0] = $myTotal;
// Overwrite main weight // Overwrite main weight
$totalResult[1] = $main_weight; $totalResult[1] = $main_weight;
$totalResult = $scoredisplay->display_score( $totalResult = $scoredisplay->display_score(
$totalResult, $totalResult,
SCORE_DIV SCORE_DIV
@ -714,8 +809,13 @@ class GradebookTable extends SortableTable
$row[] = $main_weight; $row[] = $main_weight;
$row[] = $totalResult; $row[] = $totalResult;
$categoryId = $main_cat[0]->get_id();
if (in_array(1, $this->loadStats)) { if (in_array(1, $this->loadStats)) {
if (isset($defaultData[$categoryId]) && isset($defaultData[$categoryId]['ranking'])) {
$totalRanking = $defaultData[$categoryId]['ranking'];
$invalidateRanking = $defaultData[$categoryId]['ranking_invalidate'];
} else {
$totalRanking = []; $totalRanking = [];
$invalidateRanking = true; $invalidateRanking = true;
$average = 0; $average = 0;
@ -733,6 +833,10 @@ class GradebookTable extends SortableTable
$totalRanking[$student['user_id']] = $score[0]; $totalRanking[$student['user_id']] = $score[0];
$average += $score[0]; $average += $score[0];
} }
$defaultData[$categoryId]['ranking'] = $totalRanking;
$defaultData[$categoryId]['ranking_invalidate'] = $invalidateRanking;
Session::write($this->getPreloadDataKey(), $defaultData);
}
$totalRanking = AbstractLink::getCurrentUserRanking($user_id, $totalRanking); $totalRanking = AbstractLink::getCurrentUserRanking($user_id, $totalRanking);
$totalRanking = $scoredisplay->display_score( $totalRanking = $scoredisplay->display_score(
@ -750,8 +854,13 @@ class GradebookTable extends SortableTable
} }
if (in_array(2, $this->loadStats)) { if (in_array(2, $this->loadStats)) {
if (isset($defaultData[$categoryId]) && isset($defaultData[$categoryId]['best'])) {
$totalBest = $defaultData[$categoryId]['best'];
} else {
// Overwrite main weight // Overwrite main weight
$totalBest[1] = $main_weight; $totalBest[1] = $main_weight;
$defaultData[$categoryId]['best'] = $totalBest;
}
$totalBest = $scoredisplay->display_score( $totalBest = $scoredisplay->display_score(
$totalBest, $totalBest,
SCORE_DIV, SCORE_DIV,
@ -760,10 +869,17 @@ class GradebookTable extends SortableTable
); );
$row[] = $totalBest; $row[] = $totalBest;
} }
if (in_array(3, $this->loadStats)) { if (in_array(3, $this->loadStats)) {
if (isset($defaultData[$categoryId]) && isset($defaultData[$categoryId]['average'])) {
$totalAverage = $defaultData[$categoryId]['average'];
} else {
// Overwrite main weight // Overwrite main weight
$totalAverage[0] = $average / count($this->studentList); $totalAverage[0] = $average / count($this->studentList);
$totalAverage[1] = $main_weight; $totalAverage[1] = $main_weight;
$defaultData[$categoryId]['average'] = $totalBest;
}
$totalAverage = $scoredisplay->display_score( $totalAverage = $scoredisplay->display_score(
$totalAverage, $totalAverage,
SCORE_DIV, SCORE_DIV,
@ -773,23 +889,25 @@ class GradebookTable extends SortableTable
$row[] = $totalAverage; $row[] = $totalAverage;
} }
if (!empty($row)) { if (!empty($row)) {
$sortable_data[] = $row; $sortable_data[] = $row;
} }
} }
} }
Session::write('default_data', $defaultData);
// Warning messages // Warning messages
$view = isset($_GET['view']) ? $_GET['view'] : null; $view = isset($_GET['view']) ? $_GET['view'] : null;
if ($this->teacherView) { if ($this->teacherView) {
if (isset($_GET['selectcat']) && if (isset($_GET['selectcat']) &&
$_GET['selectcat'] > 0 && $_GET['selectcat'] > 0 &&
$view != 'presence' $view != 'presence'
) { ) {
$id_cat = intval($_GET['selectcat']); $id_cat = (int) $_GET['selectcat'];
$category = Category::load($id_cat); $category = Category::load($id_cat);
$weight_category = intval($this->build_weight($category[0])); $weight_category = (int) $this->build_weight($category[0]);
$course_code = $this->build_course_code($category[0]); $course_code = $this->build_course_code($category[0]);
$weight_total_links = round($weight_total_links); $weight_total_links = round($weight_total_links);
@ -798,7 +916,8 @@ class GradebookTable extends SortableTable
$weight_total_links > $weight_category $weight_total_links > $weight_category
) { ) {
$warning_message = sprintf(get_lang('TotalWeightMustBeX'), $weight_category); $warning_message = sprintf(get_lang('TotalWeightMustBeX'), $weight_category);
$modify_icons = '<a href="gradebook_edit_cat.php?editcat='.$id_cat.'&cidReq='.$course_code.'&id_session='.api_get_session_id().'">'. $modify_icons =
'<a href="gradebook_edit_cat.php?editcat='.$id_cat.'&cidReq='.$course_code.'&id_session='.api_get_session_id().'">'.
Display::return_icon('edit.png', $warning_message, [], ICON_SIZE_SMALL).'</a>'; Display::return_icon('edit.png', $warning_message, [], ICON_SIZE_SMALL).'</a>';
$warning_message .= $modify_icons; $warning_message .= $modify_icons;
echo Display::return_message($warning_message, 'warning', false); echo Display::return_message($warning_message, 'warning', false);
@ -853,7 +972,9 @@ class GradebookTable extends SortableTable
if (empty($certificate_min_score) || if (empty($certificate_min_score) ||
($certificate_min_score > $weight_category) ($certificate_min_score > $weight_category)
) { ) {
$warning_message .= $course_code.'&nbsp;-&nbsp;'.get_lang('CertificateMinimunScoreIsRequiredAndMustNotBeMoreThan').'&nbsp;'.$weight_category.'<br />'; $warning_message .= $course_code.
'&nbsp;-&nbsp;'.get_lang('CertificateMinimunScoreIsRequiredAndMustNotBeMoreThan').
'&nbsp;'.$weight_category.'<br />';
} }
} }
@ -864,27 +985,6 @@ class GradebookTable extends SortableTable
} }
} }
if (!$this->teacherView) {
/*$rowTotal = [];
$rowTotal[] = ' ';
$rowTotal[] = '<strong>'.get_lang('FinalScore').'</strong>';
if (!$this->exportToPdf) {
$rowTotal[] = ' ';
}
$rowTotal[] = ' ';
$rowTotal[] = $scoredisplay->display_score(
$totalUserResult,
SCORE_DIV_PERCENT_WITH_CUSTOM
);
foreach ($this->loadStats as $col) {
$rowTotal[] = ' ';
}
$sortable_data[] = $rowTotal;*/
}
return $sortable_data; return $sortable_data;
} }

@ -1,6 +1,8 @@
<?php <?php
/* For licensing terms, see /license.txt */ /* For licensing terms, see /license.txt */
use ChamiloSession as Session;
/** /**
* Class GradebookDataGenerator * Class GradebookDataGenerator
* Class to select, sort and transform object data into array data, * Class to select, sort and transform object data into array data,
@ -24,8 +26,9 @@ class GradebookDataGenerator
public $userId; public $userId;
public $hidePercentage = false; public $hidePercentage = false;
private $items; public $items;
private $evals_links; private $evals_links;
public $preLoadDataKey;
/** /**
* @param array $cats * @param array $cats
@ -113,7 +116,9 @@ class GradebookDataGenerator
// Generate the data to display // Generate the data to display
$data = []; $data = [];
$totalWeight = 0; $allowStats = api_get_configuration_value('allow_gradebook_stats');
$scoreDisplay = ScoreDisplay::instance();
$defaultData = Session::read($this->preLoadDataKey);
/** @var GradebookItem $item */ /** @var GradebookItem $item */
foreach ($visibleItems as $item) { foreach ($visibleItems as $item) {
@ -124,11 +129,12 @@ class GradebookDataGenerator
// on mouseover (https://support.chamilo.org/issues/6588) // on mouseover (https://support.chamilo.org/issues/6588)
$row[] = '<span title="'.api_remove_tags_with_space($item->get_description()).'">'. $row[] = '<span title="'.api_remove_tags_with_space($item->get_description()).'">'.
api_get_short_text_from_html($item->get_description(), 160).'</span>'; api_get_short_text_from_html($item->get_description(), 160).'</span>';
$totalWeight += $item->get_weight();
$row[] = $item->get_weight(); $row[] = $item->get_weight();
$item->setStudentList($studentList); $item->setStudentList($studentList);
$itemType = get_class($item);
if (get_class($item) == 'Evaluation') { switch ($itemType) {
case 'Evaluation':
// Items inside a category. // Items inside a category.
$resultColumn = $this->build_result_column( $resultColumn = $this->build_result_column(
$userId, $userId,
@ -141,13 +147,22 @@ class GradebookDataGenerator
$row['result_score_weight'] = $resultColumn['score_weight']; $row['result_score_weight'] = $resultColumn['score_weight'];
// Best // Best
if (isset($defaultData[$item->get_id()]) && isset($defaultData[$item->get_id()]['best'])) {
$best = $defaultData[$item->get_id()]['best'];
} else {
$best = $this->buildBestResultColumn($item); $best = $this->buildBestResultColumn($item);
}
$row['best'] = $best['display']; $row['best'] = $best['display'];
$row['best_score'] = $best['score']; $row['best_score'] = $best['score'];
// Average // Average
$average = $this->buildAverageResultColumn($item); if (isset($defaultData[$item->get_id()]) && isset($defaultData[$item->get_id()]['average'])) {
$average = $defaultData[$item->get_id()]['average'];
} else {
$average = $this->buildBestResultColumn($item);
}
$row['average'] = $average['display']; $row['average'] = $average['display'];
$row['average_score'] = $average['score']; $row['average_score'] = $average['score'];
@ -156,7 +171,102 @@ class GradebookDataGenerator
$row['ranking'] = $ranking['display']; $row['ranking'] = $ranking['display'];
$row['ranking_score'] = $ranking['score']; $row['ranking_score'] = $ranking['score'];
$row[] = $item; $row[] = $item;
break;
case 'ExerciseLink':
/** @var ExerciseLink $item */
// Category.
$result = $this->build_result_column(
$userId,
$item,
$ignore_score_color,
true
);
$row[] = $result['display'];
$row['result_score'] = $result['score'];
$row['result_score_weight'] = $result['score'];
// Best
if (isset($defaultData[$item->get_id()]) && isset($defaultData[$item->get_id()]['best'])) {
$best = $defaultData[$item->get_id()]['best'];
} else {
$best = $this->buildBestResultColumn($item);
}
$row['best'] = $best['display'];
$row['best_score'] = $best['score'];
$rankingStudentList = [];
$invalidateResults = false;
$debug = $item->get_id() == 1177;
// Average
if (isset($defaultData[$item->get_id()]) && isset($defaultData[$item->get_id()]['average'])) {
$average = $defaultData[$item->get_id()]['average'];
} else {
$average = $this->buildAverageResultColumn($item);
}
$row['average'] = $average['display'];
$row['average_score'] = $average['score'];
// Ranking
if ($allowStats) {
// Ranking
if (isset($defaultData[$item->get_id()]) && isset($defaultData[$item->get_id()]['ranking'])) {
$rankingStudentList = $defaultData[$item->get_id()]['ranking'];
$invalidateResults = $defaultData[$item->get_id()]['ranking_invalidate'];
$score = AbstractLink::getCurrentUserRanking($userId, $rankingStudentList);
} else {
if (!empty($studentList)) {
foreach ($studentList as $user) {
$score = $this->build_result_column(
$user['user_id'],
$item,
$ignore_score_color,
true
);
if (!empty($score['score'][0])) {
$invalidateResults = false;
}
$rankingStudentList[$user['user_id']] = $score['score'][0];
}
$defaultData[$item->get_id()]['ranking'] = $rankingStudentList;
$defaultData[$item->get_id()]['ranking_invalidate'] = $invalidateResults;
Session::write($this->preLoadDataKey, $defaultData);
}
$score = AbstractLink::getCurrentUserRanking($userId, $rankingStudentList);
}
} else { } else {
if (!empty($studentList)) {
foreach ($studentList as $user) {
$score = $this->build_result_column(
$user['user_id'],
$item,
$ignore_score_color,
true
);
if (!empty($score['score'][0])) {
$invalidateResults = false;
}
$rankingStudentList[$user['user_id']] = $score['score'][0];
}
}
$score = AbstractLink::getCurrentUserRanking($userId, $rankingStudentList);
}
$row['ranking'] = $scoreDisplay->display_score(
$score,
SCORE_DIV,
SCORE_BOTH,
true,
true
);
if ($invalidateResults) {
$row['ranking'] = null;
}
break;
default:
// Category. // Category.
$result = $this->build_result_column( $result = $this->build_result_column(
$userId, $userId,
@ -169,7 +279,12 @@ class GradebookDataGenerator
$row['result_score_weight'] = $result['score']; $row['result_score_weight'] = $result['score'];
// Best // Best
if (isset($defaultData[$item->get_id()]) && isset($defaultData[$item->get_id()]['best'])) {
$best = $defaultData[$item->get_id()]['best'];
} else {
$best = $this->buildBestResultColumn($item); $best = $this->buildBestResultColumn($item);
}
$row['best'] = $best['display']; $row['best'] = $best['display'];
$row['best_score'] = $best['score']; $row['best_score'] = $best['score'];
@ -177,11 +292,21 @@ class GradebookDataGenerator
$invalidateResults = true; $invalidateResults = true;
// Average // Average
if (isset($defaultData[$item->get_id()]) && isset($defaultData[$item->get_id()]['average'])) {
$average = $defaultData[$item->get_id()]['average'];
} else {
$average = $this->buildAverageResultColumn($item); $average = $this->buildAverageResultColumn($item);
}
$row['average'] = $average['display']; $row['average'] = $average['display'];
$row['average_score'] = $average['score']; $row['average_score'] = $average['score'];
// Ranking // Ranking
if (isset($defaultData[$item->get_id()]) && isset($defaultData[$item->get_id()]['ranking'])) {
$rankingStudentList = $defaultData[$item->get_id()]['ranking'];
$invalidateResults = $defaultData[$item->get_id()]['ranking_invalidate'];
$invalidateResults = false;
$score = AbstractLink::getCurrentUserRanking($userId, $rankingStudentList);
} else {
if (!empty($studentList)) { if (!empty($studentList)) {
foreach ($studentList as $user) { foreach ($studentList as $user) {
$score = $this->build_result_column( $score = $this->build_result_column(
@ -196,9 +321,10 @@ class GradebookDataGenerator
$rankingStudentList[$user['user_id']] = $score['score'][0]; $rankingStudentList[$user['user_id']] = $score['score'][0];
} }
} }
error_log('loading not cACHE');
$scoreDisplay = ScoreDisplay::instance();
$score = AbstractLink::getCurrentUserRanking($userId, $rankingStudentList); $score = AbstractLink::getCurrentUserRanking($userId, $rankingStudentList);
}
$row['ranking'] = $scoreDisplay->display_score( $row['ranking'] = $scoreDisplay->display_score(
$score, $score,
SCORE_DIV, SCORE_DIV,
@ -206,9 +332,11 @@ class GradebookDataGenerator
true, true,
true true
); );
if ($invalidateResults) { if ($invalidateResults) {
$row['ranking'] = null; $row['ranking'] = null;
} }
break;
} }
$data[] = $row; $data[] = $row;
} }
@ -244,7 +372,7 @@ class GradebookDataGenerator
* *
* @return int * @return int
*/ */
public function sort_by_name($item1, $item2) public static function sort_by_name($item1, $item2)
{ {
return api_strnatcmp($item1->get_name(), $item2->get_name()); return api_strnatcmp($item1->get_name(), $item2->get_name());
} }
@ -345,7 +473,7 @@ class GradebookDataGenerator
* *
* @return array * @return array
*/ */
private function buildBestResultColumn(GradebookItem $item) public function buildBestResultColumn(GradebookItem $item)
{ {
$score = $item->calc_score( $score = $item->calc_score(
null, null,
@ -382,7 +510,7 @@ class GradebookDataGenerator
* *
* @return array * @return array
*/ */
private function buildAverageResultColumn(GradebookItem $item) public function buildAverageResultColumn(GradebookItem $item)
{ {
$score = $item->calc_score(null, 'average'); $score = $item->calc_score(null, 'average');
$scoreDisplay = ScoreDisplay::instance(); $scoreDisplay = ScoreDisplay::instance();
@ -421,7 +549,7 @@ class GradebookDataGenerator
* *
* @return array * @return array
*/ */
private function buildRankingColumn(GradebookItem $item, $userId = null, $userCount = 0) public function buildRankingColumn(GradebookItem $item, $userId = null, $userCount = 0)
{ {
$score = $item->calc_score($userId, 'ranking'); $score = $item->calc_score($userId, 'ranking');
$score[1] = $userCount; $score[1] = $userCount;
@ -448,9 +576,9 @@ class GradebookDataGenerator
* @param GradebookItem $item * @param GradebookItem $item
* @param bool $ignore_score_color * @param bool $ignore_score_color
* *
* @return string|null * @return null|string
*/ */
private function build_result_column( public function build_result_column(
$userId, $userId,
$item, $item,
$ignore_score_color, $ignore_score_color,
@ -491,7 +619,6 @@ class GradebookDataGenerator
]; ];
} }
break; break;
// evaluation and link
case 'E': case 'E':
case 'L': case 'L':
//if ($parentId == 0) { //if ($parentId == 0) {

@ -2847,6 +2847,7 @@ HOTSPOT;
$weight = float_format($weight, 1, $decimalSeparator, $thousandSeparator); $weight = float_format($weight, 1, $decimalSeparator, $thousandSeparator);
} }
$html = '';
if ($show_percentage) { if ($show_percentage) {
$percentageSign = '%'; $percentageSign = '%';
if ($hidePercentageSign) { if ($hidePercentageSign) {
@ -4828,6 +4829,15 @@ EOT;
$exercise_stat_info['exe_duration'], $exercise_stat_info['exe_duration'],
$question_list $question_list
); );
$allowStats = api_get_configuration_value('allow_gradebook_stats');
if ($allowStats) {
$objExercise->generateStats(
$objExercise->selectId(),
api_get_course_info(),
api_get_session_id()
);
}
} }
} }

@ -147,12 +147,17 @@ class PDF
$html = $tpl->fetch($tableTemplate); $html = $tpl->fetch($tableTemplate);
$html = api_utf8_encode($html); $html = api_utf8_encode($html);
if ($returnHtml) {
return $html;
}
$css_file = api_get_path(SYS_CSS_PATH).'themes/'.$tpl->theme.'/print.css'; $css_file = api_get_path(SYS_CSS_PATH).'themes/'.$tpl->theme.'/print.css';
if (!file_exists($css_file)) { if (!file_exists($css_file)) {
$css_file = api_get_path(SYS_CSS_PATH).'print.css'; $css_file = api_get_path(SYS_CSS_PATH).'print.css';
} }
$css = file_get_contents($css_file); $css = file_get_contents($css_file);
$html = self::content_to_pdf(
self::content_to_pdf(
$html, $html,
$css, $css,
$this->params['filename'], $this->params['filename'],
@ -163,10 +168,6 @@ class PDF
$returnHtml, $returnHtml,
$addDefaultCss $addDefaultCss
); );
if ($returnHtml) {
return $html;
}
} }
/** /**
@ -382,7 +383,7 @@ class PDF
return false; return false;
} }
//clean styles and javascript document // clean styles and javascript document
$clean_search = [ $clean_search = [
'@<script[^>]*?>.*?</script>@si', '@<script[^>]*?>.*?</script>@si',
'@<style[^>]*?>.*?</style>@siU', '@<style[^>]*?>.*?</style>@siU',

@ -73,12 +73,21 @@ function api_set_encoding_html(&$string, $encoding)
} }
} else { } else {
$count = 1; $count = 1;
if (strpos('</head>', strtolower($string)) !== false) {
$string = str_ireplace( $string = str_ireplace(
'</head>', '</head>',
'<meta http-equiv="Content-Type" content="text/html; charset='.$encoding.'"/></head>', '<meta http-equiv="Content-Type" content="text/html; charset='.$encoding.'"/></head>',
$string, $string,
$count $count
); );
} else {
$string = str_ireplace(
'<body>',
'<head><meta http-equiv="Content-Type" content="text/html; charset='.$encoding.'"/></head><body>',
$string,
$count
);
}
} }
$string = api_convert_encoding($string, $encoding, $old_encoding); $string = api_convert_encoding($string, $encoding, $old_encoding);
} }

@ -1082,6 +1082,13 @@ VALUES (2, 13, 'session_courses_read_only_mode', 'Lock Course In Session', 1, 1,
// Allow to session admins login as teachers // Allow to session admins login as teachers
//$_configuration['allow_session_admin_login_as_teacher'] = false; //$_configuration['allow_session_admin_login_as_teacher'] = false;
// Allow gradebook stats
// Requires to edit the GradebookLink.php And GradebookEvaluation.php files adding the "@" in the ORM phpdoc block
/* ALTER TABLE gradebook_link ADD score_weight DOUBLE PRECISION DEFAULT NULL, ADD average_score DOUBLE PRECISION DEFAULT NULL, ADD best_score DOUBLE PRECISION DEFAULT NULL, ADD user_score_list LONGTEXT DEFAULT NULL COMMENT '(DC2Type:array)' ;
ALTER TABLE gradebook_evaluation ADD average_score DOUBLE PRECISION DEFAULT NULL, ADD best_score DOUBLE PRECISION DEFAULT NULL, ADD user_score_list LONGTEXT DEFAULT NULL COMMENT '(DC2Type:array)' ;
//$_configuration['allow_gradebook_stats'] = false;
// Hide social media links // Hide social media links
//$_configuration['hide_social_media_links'] = false; //$_configuration['hide_social_media_links'] = false;

@ -99,6 +99,34 @@ class GradebookEvaluation
*/ */
protected $locked; protected $locked;
/**
* @var float
*
* ORM\Column(name="best_score", type="float", precision=6, scale=2, nullable=true)
*/
protected $bestScore;
/**
* @var float
*
* ORM\Column(name="average_score", type="float", precision=6, scale=2, nullable=true)
*/
protected $averageScore;
/**
* @var float
*
* ORM\Column(name="score_weight", type="float", precision=6, scale=2, nullable=true)
*/
protected $scoreWeight;
/**
* @var array
*
* ORM\Column(name="user_score_list", type="array", nullable=true)
*/
protected $userScoreList;
/** /**
* Set name. * Set name.
* *
@ -372,4 +400,88 @@ class GradebookEvaluation
{ {
return $this->id; return $this->id;
} }
/**
* @return float
*/
public function getBestScore()
{
return $this->bestScore;
}
/**
* @param float $bestScore
*
* @return GradebookEvaluation
*/
public function setBestScore($bestScore)
{
$this->bestScore = $bestScore;
return $this;
}
/**
* @return float
*/
public function getAverageScore()
{
return $this->averageScore;
}
/**
* @param float $averageScore
*
* @return GradebookEvaluation
*/
public function setAverageScore($averageScore)
{
$this->averageScore = $averageScore;
return $this;
}
/**
* @return array
*/
public function getUserScoreList()
{
if (empty($this->userScoreList)) {
return [];
}
return $this->userScoreList;
}
/**
* @param array $userScoreList
*
* @return GradebookEvaluation
*/
public function setUserScoreList($userScoreList)
{
$this->userScoreList = $userScoreList;
return $this;
}
/**
* @return float
*/
public function getScoreWeight()
{
return $this->scoreWeight;
}
/**
* @param float $scoreWeight
*
* @return GradebookEvaluation
*/
public function setScoreWeight($scoreWeight)
{
$this->scoreWeight = $scoreWeight;
return $this;
}
} }

@ -85,6 +85,34 @@ class GradebookLink
*/ */
protected $locked; protected $locked;
/**
* @var float
*
* ORM\Column(name="best_score", type="float", precision=6, scale=2, nullable=true)
*/
protected $bestScore;
/**
* @var float
*
* ORM\Column(name="average_score", type="float", precision=6, scale=2, nullable=true)
*/
protected $averageScore;
/**
* @var float
*
* ORM\Column(name="score_weight", type="float", precision=6, scale=2, nullable=true)
*/
protected $scoreWeight;
/**
* @var array
*
* ORM\Column(name="user_score_list", type="array", nullable=true)
*/
protected $userScoreList;
/** /**
* Set type. * Set type.
* *
@ -310,4 +338,88 @@ class GradebookLink
{ {
return $this->id; return $this->id;
} }
/**
* @return float
*/
public function getBestScore()
{
return $this->bestScore;
}
/**
* @param float $bestScore
*
* @return GradebookLink
*/
public function setBestScore($bestScore)
{
$this->bestScore = $bestScore;
return $this;
}
/**
* @return float
*/
public function getAverageScore()
{
return $this->averageScore;
}
/**
* @param float $averageScore
*
* @return GradebookLink
*/
public function setAverageScore($averageScore)
{
$this->averageScore = $averageScore;
return $this;
}
/**
* @return array
*/
public function getUserScoreList()
{
if (empty($this->userScoreList)) {
return [];
}
return $this->userScoreList;
}
/**
* @param array $userScoreList
*
* @return GradebookLink
*/
public function setUserScoreList($userScoreList)
{
$this->userScoreList = $userScoreList;
return $this;
}
/**
* @return float
*/
public function getScoreWeight()
{
return $this->scoreWeight;
}
/**
* @param float $scoreWeight
*
* @return GradebookLink
*/
public function setScoreWeight($scoreWeight)
{
$this->scoreWeight = $scoreWeight;
return $this;
}
} }

Loading…
Cancel
Save