gradebooktable.class.php 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. <?php
  2. /* For licensing terms, see license.txt */
  3. /**
  4. * Script
  5. * @package chamilo.gradebook
  6. */
  7. /**
  8. * Init
  9. */
  10. require_once dirname(__FILE__).'/../../../inc/global.inc.php';
  11. require_once dirname(__FILE__).'/../be.inc.php';
  12. /**
  13. * Table to display categories, evaluations and links
  14. * @author Stijn Konings
  15. * @author Bert Steppé (refactored, optimised)
  16. * @package chamilo.gradebook
  17. */
  18. class GradebookTable extends SortableTable {
  19. private $currentcat;
  20. private $datagen;
  21. private $evals_links;
  22. public $cats;
  23. /**
  24. * Constructor
  25. */
  26. function GradebookTable ($currentcat, $cats = array(), $evals = array(), $links = array(), $addparams = null) {
  27. //$status = CourseManager::get_user_in_course_status(api_get_user_id(), api_get_course_id());
  28. parent :: __construct ('gradebooklist', null, null, (api_is_allowed_to_edit()?1:0));
  29. $this->evals_links = array_merge($evals, $links);
  30. $this->currentcat = $currentcat;
  31. $this->cats = $cats;
  32. $this->datagen = new GradebookDataGenerator($cats, $evals, $links);
  33. if (isset($addparams)) {
  34. $this->set_additional_parameters($addparams);
  35. }
  36. $column= 0;
  37. if (api_is_allowed_to_edit(null, true)) {
  38. $this->set_header($column++,'','','width="25px"');
  39. }
  40. $this->set_header($column++, get_lang('Type'),'','width="35px"');
  41. $this->set_header($column++, get_lang('Name'), false);
  42. $this->set_header($column++, get_lang('Description'), false);
  43. if (api_is_allowed_to_edit(null, true)) {
  44. $this->set_header($column++, get_lang('Weight'),'','width="20px"');
  45. } else {
  46. $this->set_header($column++, get_lang('Weight'), false);
  47. $this->set_header($column++, get_lang('Result'), false);
  48. if (!empty($cats)) {
  49. $this->set_header($column++, get_lang('Actions'), false);
  50. }
  51. }
  52. /*if (api_is_allowed_to_edit(null, true)) {
  53. //$this->set_header($column++, get_lang('CreationDate'),true, 'width="100px"');
  54. } elseif (($status<>1) && !api_is_allowed_to_edit() && (!isset($_GET['selectcat']) || $_GET['selectcat']==0)) {
  55. //$this->set_header($column++, get_lang('Date'),true, 'width="100px"');
  56. }*/
  57. //admins get an edit column
  58. if (api_is_allowed_to_edit(null, true)) {
  59. $this->set_header($column++, get_lang('Modify'), false, 'width="180px"');
  60. //actions on multiple selected documents
  61. $this->set_form_actions(array (
  62. 'setvisible' => get_lang('SetVisible'),
  63. 'setinvisible' => get_lang('SetInvisible'),
  64. 'deleted' => get_lang('DeleteSelected')
  65. ));
  66. } else {
  67. if (empty($_GET['selectcat']) && !api_is_allowed_to_edit()) {
  68. $this->set_header($column++, get_lang('Certificates'),false);
  69. } else {
  70. //$evals_links = array_merge($evals, $links);
  71. //if (count($evals_links)>0) {
  72. //$this->set_header($column++, get_lang('Results'), false);
  73. //}
  74. }
  75. }
  76. }
  77. function get_data() {
  78. return $this->datagen;
  79. }
  80. /**
  81. * Function used by SortableTable to get total number of items in the table
  82. */
  83. function get_total_number_of_items() {
  84. return $this->datagen->get_total_items_count();
  85. }
  86. /**
  87. * Function used by SortableTable to generate the data to display
  88. */
  89. function get_table_data($from = 1) {
  90. //variables load in index.php
  91. global $my_score_in_gradebook, $certificate_min_score;
  92. $scoretotal = 0;
  93. // determine sorting type
  94. $col_adjust = (api_is_allowed_to_edit() ? 1 : 0);
  95. // By id
  96. $this->column = 5;
  97. switch ($this->column) {
  98. // Type
  99. case (0 + $col_adjust) :
  100. $sorting = GradebookDataGenerator :: GDG_SORT_TYPE;
  101. break;
  102. case (1 + $col_adjust) :
  103. $sorting = GradebookDataGenerator :: GDG_SORT_NAME;
  104. break;
  105. case (2 + $col_adjust) :
  106. $sorting = GradebookDataGenerator :: GDG_SORT_DESCRIPTION;
  107. break;
  108. case (3 + $col_adjust) :
  109. $sorting = GradebookDataGenerator :: GDG_SORT_WEIGHT;
  110. break;
  111. case (4 + $col_adjust) :
  112. $sorting = GradebookDataGenerator :: GDG_SORT_DATE;
  113. case (5 + $col_adjust) :
  114. $sorting = GradebookDataGenerator :: GDG_SORT_ID;
  115. break;
  116. }
  117. if ($this->direction == 'DESC') {
  118. $sorting |= GradebookDataGenerator :: GDG_SORT_DESC;
  119. } else {
  120. $sorting |= GradebookDataGenerator :: GDG_SORT_ASC;
  121. }
  122. //status of user in course
  123. $user_id = api_get_user_id();
  124. $course_code = api_get_course_id();
  125. $session_id = api_get_session_id();
  126. $status_user = api_get_status_of_user_in_course($user_id, $course_code);
  127. $data_array = $this->datagen->get_data($sorting, $from, $this->per_page);
  128. // generate the data to display
  129. $sortable_data = array();
  130. $weight_total_links = 0;
  131. $main_categories = array();
  132. $main_cat = Category :: load(null, null, $course_code, null, null, $session_id, false);
  133. $total_categories_weight = 0;
  134. $scoredisplay = ScoreDisplay :: instance();
  135. //Categories
  136. foreach ($data_array as $data) {
  137. // list of items inside the gradebook (exercises, lps, forums, etc)
  138. $row = array();
  139. $item = $item_category = $data[0];
  140. $id = $item->get_id();
  141. //if the item is invisible, wrap it in a span with class invisible
  142. $invisibility_span_open = (api_is_allowed_to_edit() && $item->is_visible() == '0') ? '<span class="invisible">' : '';
  143. $invisibility_span_close = (api_is_allowed_to_edit() && $item->is_visible() == '0') ? '</span>' : '';
  144. if (api_is_allowed_to_edit(null, true)) {
  145. //id
  146. $row[] = $this->build_id_column($item);
  147. }
  148. //Type
  149. $row[] = $this->build_type_column($item);
  150. //Name
  151. if (get_class($item) == 'Category') {
  152. $row[] = $invisibility_span_open.'<h3>'.$item->get_name().'</h3>'.$invisibility_span_close;
  153. $main_categories[$item->get_id()]['name'] = $item->get_name();
  154. } else {
  155. $row[] = $invisibility_span_open.$this->build_name_link($item) . $invisibility_span_close;
  156. $main_categories[$item->get_id()] = $this->build_name_link($item);
  157. }
  158. $main_categories[$item->get_id()]['weight'] = $item->get_weight();
  159. $total_categories_weight += $item->get_weight();
  160. //Description
  161. $row[] = $invisibility_span_open.$data[2].$invisibility_span_close;
  162. //Weight
  163. //$row[] = $invisibility_span_open .Display::tag('h4', $data['3'] .' / '.$this->currentcat->get_weight()).$invisibility_span_close;
  164. //$average = $data['3']/$this->currentcat->get_weight()*100;
  165. $average = $scoredisplay->display_score(array($data['3'], $this->currentcat->get_weight()), SCORE_PERCENT, SCORE_BOTH, true);
  166. if (api_is_allowed_to_edit(null, true)) {
  167. $row[] = $invisibility_span_open .Display::tag('h4', $average).$invisibility_span_close;
  168. } else {
  169. $row[] = $invisibility_span_open .$average.$invisibility_span_close;
  170. }
  171. $category_weight = $item->get_weight();
  172. if (api_is_allowed_to_edit(null, true)) {
  173. $weight_total_links += $data[3];
  174. } else {
  175. $cattotal = Category :: load($_GET['selectcat']);
  176. $scoretotal = $cattotal[0]->calc_score(api_get_user_id());
  177. $item_value = $scoredisplay->display_score($scoretotal, SCORE_SIMPLE);
  178. }
  179. //Date
  180. //$row[] = $invisibility_span_open.$data[4].$invisibility_span_close;
  181. //Edit (for admins)
  182. if (api_is_allowed_to_edit(null, true)) {
  183. $cat = new Category();
  184. $show_message = $cat->show_message_resource_delete($item->get_course_code());
  185. if ($show_message === false) {
  186. $row[] = $this->build_edit_column($item);
  187. }
  188. } else {
  189. //students get the results and certificates columns
  190. if (count($this->evals_links) > 0 && $status_user != 1) {
  191. $value_data = isset($data[4]) ? $data[4] : null;
  192. if (!is_null($value_data)) {
  193. $row[] = Display::tag('h4', $value_data);
  194. } else {
  195. $row[] = $this->build_edit_column($item);
  196. }
  197. } else {
  198. $score = $item->calc_score(api_get_user_id());
  199. if (!empty($score[1])) {
  200. $complete_score = $scoredisplay->display_score($score, SCORE_DIV_PERCENT);
  201. $score = $score[0]/$score[1]*$item->get_weight();
  202. $score = $scoredisplay->display_score(array($score, null), SCORE_SIMPLE);
  203. $row[] = Display::tip($score, $complete_score);
  204. } else {
  205. $row[] = '-';
  206. }
  207. if (!empty($this->cats)) {
  208. $row[] = $this->build_edit_column($item);
  209. }
  210. }
  211. }
  212. //Category added
  213. $sortable_data[] = $row;
  214. // Loading childrens
  215. if (get_class($item) == 'Category') {
  216. $stud_id = api_get_user_id();
  217. $course_code = api_get_course_id();
  218. $session_id = api_get_session_id();
  219. $parent_id = $item->get_id();
  220. $cats = Category :: load ($parent_id, null, null, null, null, null);
  221. $allcat = $cats[0]->get_subcategories($stud_id, $course_code, $session_id);
  222. $alleval = $cats[0]->get_evaluations($stud_id);
  223. $alllink = $cats[0]->get_links($stud_id);
  224. $sub_cat_info = new GradebookDataGenerator($allcat, $alleval, $alllink);
  225. $data_array = $sub_cat_info->get_data($sorting, $from, $this->per_page);
  226. $total_weight = 0;
  227. //Links
  228. foreach ($data_array as $data) {
  229. $row = array();
  230. $item = $data[0];
  231. $id = $item->get_id();
  232. //if the item is invisible, wrap it in a span with class invisible
  233. $invisibility_span_open = (api_is_allowed_to_edit() && $item->is_visible() == '0') ? '<span class="invisible">' : '';
  234. $invisibility_span_close = (api_is_allowed_to_edit() && $item->is_visible() == '0') ? '</span>' : '';
  235. $main_categories[$parent_id]['children'][$item->get_id()]['name'] = $item->get_name();
  236. $main_categories[$parent_id]['children'][$item->get_id()]['weight'] = $item->get_weight();
  237. if (api_is_allowed_to_edit(null, true)) {
  238. $row[] = $this->build_id_column($item);
  239. }
  240. $row[] = $this->build_type_column($item);
  241. //Name
  242. $row[] = $invisibility_span_open."&nbsp;&nbsp;&nbsp; ".$this->build_name_link($item) . $invisibility_span_close;
  243. //Description
  244. $row[] = $invisibility_span_open.$data[2].$invisibility_span_close;
  245. //Weight
  246. //$weight = $data[3]/$category_weight*$main_cat[0]->get_weight();
  247. /*$weight = $category_weight * $data[3] / $main_cat[0]->get_weight();
  248. $weight = $main_cat[0]->get_weight()*$weight/$category_weight;*/
  249. $weight = $data[3];
  250. //$extra = " - $data[3] $category_weight -".$main_cat[0]->get_weight();
  251. $total_weight += $weight;
  252. $row[] = $invisibility_span_open.$weight.$extra.$invisibility_span_close;
  253. if (api_is_allowed_to_edit(null, true)) {
  254. //$weight_total_links += intval($data[3]);
  255. } else {
  256. $cattotal = Category :: load($_GET['selectcat']);
  257. $scoretotal = $cattotal[0]->calc_score(api_get_user_id());
  258. $item_value = $scoretotal[0];
  259. }
  260. //Date
  261. //$row[] = $invisibility_span_open.$data[4].$invisibility_span_close;
  262. //Admins get an edit column
  263. if (api_is_allowed_to_edit(null, true)) {
  264. $cat = new Category();
  265. $show_message = $cat->show_message_resource_delete($item->get_course_code());
  266. if ($show_message === false) {
  267. $row[] = $this->build_edit_column($item);
  268. }
  269. } else {
  270. //students get the results and certificates columns
  271. $eval_n_links = array_merge($alleval, $alllink);
  272. if (count($eval_n_links)> 0 && $status_user!=1 ) {
  273. $value_data = isset($data[4]) ? $data[4] : null;
  274. if (!is_null($value_data)) {
  275. $score = $item->calc_score(api_get_user_id());
  276. $new_score = $data[3]* $score[0] / $score[1];
  277. $row[] = Display::tip($new_score, $data[4]);
  278. }
  279. }
  280. if (!empty($cats)) {
  281. $row[] = null;
  282. }
  283. }
  284. $row['child_of'] = $parent_id;
  285. $sortable_data[] = $row;
  286. }
  287. //"Warning row"
  288. if (!empty($data_array)) {
  289. if (api_is_allowed_to_edit()) {
  290. $main_weight = intval($main_cat[0]->get_weight());
  291. if (intval($total_weight) == $main_weight) {
  292. $label = null;
  293. $total = score_badges(array($total_weight.' / '.$main_weight, '100%'));
  294. } else {
  295. $label = Display::return_icon('warning.png', sprintf(get_lang('TotalWeightMustBeX'), $main_weight) );
  296. $total = Display::badge($total_weight.' / '.$main_weight, 'warning');
  297. }
  298. $row = array(null, null, "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<h5>".get_lang('SubTotal').'</h5>',null, $total.' '.$label, 'child_of' =>$parent_id);
  299. $sortable_data[] = $row;
  300. }
  301. }
  302. }
  303. } //end looping categories
  304. if (api_is_allowed_to_edit()) {
  305. if (count($main_cat) > 1) {
  306. $main_weight = intval($main_cat[0]->get_weight());
  307. if (intval($total_categories_weight) == $main_weight) {
  308. $total = score_badges(array($total_categories_weight.' / '.$main_weight, '100%'));
  309. } else {
  310. $total = Display::badge($total_categories_weight.' / '.$main_weight, 'warning');
  311. }
  312. $row = array(null, null, '<h3>'.get_lang('Total').'</h3>', null, $total);
  313. $sortable_data[] = $row;
  314. }
  315. }
  316. // warning messages
  317. $view = isset($_GET['view']) ? $_GET['view']: null;
  318. if (api_is_allowed_to_edit()) {
  319. if (isset($_GET['selectcat']) && $_GET['selectcat'] > 0 && $view <> 'presence') {
  320. $id_cat = intval($_GET['selectcat']);
  321. $category = Category :: load($id_cat);
  322. //$weight_category = intval($this->build_weight($category[0]));
  323. $weight_category = intval($this->build_weight($category[0]));
  324. $course_code = $this->build_course_code($category[0]);
  325. $weight_total_links = round($weight_total_links);
  326. if ($weight_total_links > $weight_category) {
  327. $warning_message = get_lang('TotalWeightMustNotBeMoreThan').'&nbsp;'.$weight_category;
  328. Display::display_warning_message($warning_message,false);
  329. }
  330. if ($weight_total_links < $weight_category ||$weight_total_links > $weight_category) {
  331. $warning_message = sprintf(get_lang('TotalWeightMustBeX'), $weight_category);
  332. Display::display_warning_message($warning_message,false);
  333. }
  334. $content_html = DocumentManager::replace_user_info_into_html(api_get_user_id(), $course_code);
  335. if (!empty($content_html)) {
  336. $new_content = explode('</head>',$content_html['content']);
  337. }
  338. if (empty($new_content[0])) {
  339. $warning_message = get_lang('ThereIsNotACertificateAvailableByDefault');
  340. Display::display_warning_message($warning_message);
  341. }
  342. }
  343. if (empty($_GET['selectcat'])) {
  344. $categories = Category :: load();
  345. $weight_categories = $certificate_min_scores = $course_codes = array();
  346. foreach ($categories as $category) {
  347. $course_code_category = $this->build_course_code($category);
  348. if (!empty($course_code)) {
  349. if ($course_code_category == $course_code) {
  350. $weight_categories[] = intval($this->build_weight($category));
  351. $certificate_min_scores[] = intval($this->build_certificate_min_score($category));
  352. $course_codes[] = $course_code;
  353. break;
  354. }
  355. } else {
  356. $weight_categories[] = intval($this->build_weight($category));
  357. $certificate_min_scores[] = intval($this->build_certificate_min_score($category));
  358. $course_codes[] = $course_code_category;
  359. }
  360. }
  361. if (is_array($weight_categories) && is_array($certificate_min_scores) && is_array($course_codes)) {
  362. $warning_message = '';
  363. for ($x = 0; $x<count($weight_categories);$x++) {
  364. $weight_category = intval($weight_categories[$x]);
  365. $certificate_min_score = intval($certificate_min_scores[$x]);
  366. $course_code = $course_codes[$x];
  367. if (empty($certificate_min_score) || ($certificate_min_score > $weight_category)) {
  368. $warning_message .= $course_code .'&nbsp;-&nbsp;'.get_lang('CertificateMinimunScoreIsRequiredAndMustNotBeMoreThan').'&nbsp;'.$weight_category.'<br />';
  369. }
  370. }
  371. if (!empty($warning_message)) {
  372. Display::display_warning_message($warning_message,false);
  373. }
  374. }
  375. }
  376. }
  377. return $sortable_data;
  378. }
  379. // Other functions
  380. private function build_certificate_min_score ($item) {
  381. return $item->get_certificate_min_score();
  382. }
  383. private function build_weight ($item) {
  384. return $item->get_weight();
  385. }
  386. private function build_course_code ($item) {
  387. return $item->get_course_code();
  388. }
  389. private function build_id_column ($item) {
  390. switch ($item->get_item_type()) {
  391. // category
  392. case 'C' :
  393. return 'CATE' . $item->get_id();
  394. // evaluation
  395. case 'E' :
  396. return 'EVAL' . $item->get_id();
  397. // link
  398. case 'L' :
  399. return 'LINK' . $item->get_id();
  400. }
  401. }
  402. private function build_type_column ($item) {
  403. return build_type_icon_tag($item->get_icon_name());
  404. }
  405. /**
  406. *
  407. * Generate name column
  408. * @param unknown_type $item
  409. * @return string
  410. */
  411. private function build_name_link ($item) {
  412. //$session_id = api_get_session_id();
  413. switch ($item->get_item_type()) {
  414. // category
  415. case 'C' :
  416. $prms_uri='?selectcat=' . $item->get_id() . '&amp;view='.Security::remove_XSS($_GET['view']);
  417. if (isset($_GET['isStudentView'])) {
  418. if ( isset($is_student) || ( isset($_SESSION['studentview']) && $_SESSION['studentview']=='studentview') ) {
  419. $prms_uri=$prms_uri.'&amp;isStudentView='.Security::remove_XSS($_GET['isStudentView']);
  420. }
  421. }
  422. $cat = new Category();
  423. $show_message=$cat->show_message_resource_delete($item->get_course_code());
  424. return '&nbsp;<a href="'.Security::remove_XSS($_SESSION['gradebook_dest']).$prms_uri.'">'
  425. . $item->get_name()
  426. . '</a>'
  427. . ($item->is_course() ? ' &nbsp;[' . $item->get_course_code() . ']'.$show_message : '');
  428. // evaluation
  429. case 'E' :
  430. $cat = new Category();
  431. $course_id = Database::get_course_by_category($_GET['selectcat']);
  432. $show_message = $cat->show_message_resource_delete($course_id);
  433. // course/platform admin can go to the view_results page
  434. if (api_is_allowed_to_edit() && $show_message===false) {
  435. if ($item->get_type() == 'presence') {
  436. return '&nbsp;'
  437. . '<a href="gradebook_view_result.php?cidReq='.$course_id.'&amp;selecteval=' . $item->get_id() . '">'
  438. . $item->get_name()
  439. . '</a>';
  440. } else {
  441. return '&nbsp;'
  442. . '<a href="gradebook_view_result.php?cidReq='.$course_id.'&amp;selecteval=' . $item->get_id() . '">'
  443. . $item->get_name()
  444. . '</a>&nbsp;'.Display::label(get_lang('Evaluation'));
  445. }
  446. } elseif (ScoreDisplay :: instance()->is_custom() && $show_message===false) {
  447. // students can go to the statistics page (if custom display enabled)
  448. return '&nbsp;'
  449. . '<a href="gradebook_statistics.php?selecteval=' . $item->get_id() . '">'
  450. . $item->get_name()
  451. . '</a>';
  452. } elseif ($show_message===false && !api_is_allowed_to_edit() && !(ScoreDisplay :: instance()->is_custom())) {
  453. return '&nbsp;'
  454. . '<a href="gradebook_statistics.php?selecteval=' . $item->get_id() . '">'
  455. . $item->get_name()
  456. . '</a>';
  457. } else {
  458. return '['.get_lang('Evaluation').']&nbsp;&nbsp;'.$item->get_name().$show_message;
  459. }
  460. // link
  461. case 'L' :
  462. $cat = new Category();
  463. $course_id = Database::get_course_by_category($_GET['selectcat']);
  464. $show_message = $cat->show_message_resource_delete($course_id);
  465. $url = $item->get_link();
  466. if (isset($url) && $show_message===false) {
  467. $text = '&nbsp;<a href="' . $item->get_link() . '">'
  468. . $item->get_name()
  469. . '</a>';
  470. } else {
  471. $text = $item->get_name();
  472. }
  473. $text .= "&nbsp;".Display::label($item->get_type_name(), 'info').$show_message;
  474. $cc = $this->currentcat->get_course_code();
  475. if (empty($cc)) {
  476. $text .= '&nbsp;[<a href="'.api_get_path(REL_COURSE_PATH).$item->get_course_code().'/">'.$item->get_course_code().'</a>]';
  477. }
  478. return $text;
  479. }
  480. }
  481. private function build_edit_column($item) {
  482. switch ($item->get_item_type()) {
  483. // category
  484. case 'C' :
  485. return build_edit_icons_cat($item, $this->currentcat);
  486. // evaluation
  487. case 'E' :
  488. return build_edit_icons_eval($item, $this->currentcat->get_id());
  489. // link
  490. case 'L' :
  491. return build_edit_icons_link($item, $this->currentcat->get_id());
  492. }
  493. }
  494. }