gradebooktable.class.php 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090
  1. <?php
  2. /* For licensing terms, see license.txt */
  3. use ChamiloSession as Session;
  4. use CpChart\Cache as pCache;
  5. use CpChart\Data as pData;
  6. use CpChart\Image as pImage;
  7. /**
  8. * GradebookTable Class
  9. * Table to display categories, evaluations and links
  10. * @author Stijn Konings
  11. * @author Bert Steppé (refactored, optimised)
  12. * @package chamilo.gradebook
  13. */
  14. class GradebookTable extends SortableTable
  15. {
  16. private $currentcat;
  17. private $datagen;
  18. private $evals_links;
  19. private $dataForGraph;
  20. public $cats;
  21. public $exportToPdf;
  22. public $teacherView;
  23. public $userId;
  24. public $studentList;
  25. /**
  26. * GradebookTable constructor.
  27. * @param Category $currentcat
  28. * @param array $cats
  29. * @param array $evals
  30. * @param array $links
  31. * @param null $addparams
  32. * @param bool $exportToPdf
  33. * @param null $showTeacherView
  34. * @param int $userId
  35. * @param array $studentList
  36. */
  37. public function __construct(
  38. $currentcat,
  39. $cats = array(),
  40. $evals = array(),
  41. $links = array(),
  42. $addparams = null,
  43. $exportToPdf = false,
  44. $showTeacherView = null,
  45. $userId = null,
  46. $studentList = array()
  47. ) {
  48. $this->teacherView = is_null($showTeacherView) ? api_is_allowed_to_edit(null, true) : $showTeacherView;
  49. $this->userId = is_null($userId) ? api_get_user_id() : $userId;
  50. $this->exportToPdf = $exportToPdf;
  51. parent::__construct(
  52. 'gradebooklist',
  53. null,
  54. null,
  55. api_is_allowed_to_edit() ? 1 : 0,
  56. 20,
  57. 'ASC',
  58. 'gradebook_list'
  59. );
  60. $this->evals_links = array_merge($evals, $links);
  61. $this->currentcat = $currentcat;
  62. $this->cats = $cats;
  63. $this->datagen = new GradebookDataGenerator($cats, $evals, $links);
  64. if (!empty($userId)) {
  65. $this->datagen->userId = $userId;
  66. }
  67. if (isset($addparams)) {
  68. $this->set_additional_parameters($addparams);
  69. }
  70. $column = 0;
  71. if ($this->teacherView) {
  72. if ($this->exportToPdf == false) {
  73. $this->set_header($column++, '', '', 'width="25px"');
  74. }
  75. }
  76. $this->set_header($column++, get_lang('Type'), '', 'width="35px"');
  77. $this->set_header($column++, get_lang('Name'), false);
  78. if ($this->exportToPdf == false) {
  79. $this->set_header($column++, get_lang('Description'), false);
  80. }
  81. $model = ExerciseLib::getCourseScoreModel();
  82. if ($this->teacherView) {
  83. $this->set_header(
  84. $column++,
  85. get_lang('Weight'),
  86. '',
  87. 'width="100px"'
  88. );
  89. } else {
  90. $this->set_header($column++, get_lang('Weight'), false);
  91. $this->set_header($column++, get_lang('Result'), false);
  92. if (empty($model)) {
  93. $this->set_header($column++, get_lang('Ranking'), false);
  94. $this->set_header($column++, get_lang('BestScore'), false);
  95. $this->set_header($column++, get_lang('Average'), false);
  96. }
  97. if (!empty($cats)) {
  98. if ($this->exportToPdf == false) {
  99. $this->set_header($column++, get_lang('Actions'), false);
  100. }
  101. }
  102. }
  103. // Deactivates the odd/even alt rows in order that the +/- buttons work see #4047
  104. $this->odd_even_rows_enabled = false;
  105. // Admins get an edit column.
  106. if ($this->teacherView) {
  107. $this->set_header($column++, get_lang('Modify'), false, 'width="195px"');
  108. // Actions on multiple selected documents.
  109. $this->set_form_actions(
  110. array(
  111. 'setvisible' => get_lang('SetVisible'),
  112. 'setinvisible' => get_lang('SetInvisible'),
  113. 'deleted' => get_lang('DeleteSelected')
  114. )
  115. );
  116. } else {
  117. if (empty($_GET['selectcat']) && !$this->teacherView) {
  118. if ($this->exportToPdf == false) {
  119. $this->set_header(
  120. $column++,
  121. get_lang('Certificates'),
  122. false
  123. );
  124. }
  125. }
  126. }
  127. }
  128. /**
  129. * @return GradebookDataGenerator
  130. */
  131. public function get_data()
  132. {
  133. return $this->datagen;
  134. }
  135. /**
  136. * Function used by SortableTable to get total number of items in the table
  137. * @return int
  138. */
  139. public function get_total_number_of_items()
  140. {
  141. return $this->datagen->get_total_items_count();
  142. }
  143. /**
  144. * Function used by SortableTable to generate the data to display
  145. * @param int $from
  146. * @param int $per_page
  147. * @param int $column
  148. * @param string $direction
  149. * @param int $sort
  150. * @return array|mixed
  151. */
  152. public function get_table_data($from = 1, $per_page = null, $column = null, $direction = null, $sort = null)
  153. {
  154. //variables load in index.php
  155. global $certificate_min_score;
  156. // determine sorting type
  157. $col_adjust = api_is_allowed_to_edit() ? 1 : 0;
  158. // By id
  159. $this->column = 5;
  160. switch ($this->column) {
  161. // Type
  162. case (0 + $col_adjust):
  163. $sorting = GradebookDataGenerator::GDG_SORT_TYPE;
  164. break;
  165. case (1 + $col_adjust):
  166. $sorting = GradebookDataGenerator::GDG_SORT_NAME;
  167. break;
  168. case (2 + $col_adjust):
  169. $sorting = GradebookDataGenerator::GDG_SORT_DESCRIPTION;
  170. break;
  171. case (3 + $col_adjust):
  172. $sorting = GradebookDataGenerator::GDG_SORT_WEIGHT;
  173. break;
  174. case (4 + $col_adjust):
  175. $sorting = GradebookDataGenerator::GDG_SORT_DATE;
  176. break;
  177. case (5 + $col_adjust):
  178. $sorting = GradebookDataGenerator::GDG_SORT_ID;
  179. break;
  180. }
  181. if ($this->direction == 'DESC') {
  182. $sorting |= GradebookDataGenerator::GDG_SORT_DESC;
  183. } else {
  184. $sorting |= GradebookDataGenerator::GDG_SORT_ASC;
  185. }
  186. // Status of user in course.
  187. $user_id = $this->userId;
  188. $course_code = api_get_course_id();
  189. $session_id = api_get_session_id();
  190. if (empty($session_id)) {
  191. $statusToFilter = STUDENT;
  192. } else {
  193. $statusToFilter = 0;
  194. }
  195. if (empty($this->studentList)) {
  196. $studentList = CourseManager::get_user_list_from_course_code(
  197. $course_code,
  198. $session_id,
  199. null,
  200. null,
  201. $statusToFilter
  202. );
  203. $this->studentList = $studentList;
  204. }
  205. $this->datagen->userId = $this->userId;
  206. $data_array = $this->datagen->get_data(
  207. $sorting,
  208. $from,
  209. $this->per_page,
  210. false,
  211. $this->studentList
  212. );
  213. // generate the data to display
  214. $sortable_data = array();
  215. $weight_total_links = 0;
  216. $main_cat = Category::load(
  217. null,
  218. null,
  219. $course_code,
  220. null,
  221. null,
  222. $session_id,
  223. 'ORDER BY id'
  224. );
  225. $total_categories_weight = 0;
  226. $scoredisplay = ScoreDisplay::instance();
  227. $totalResult = [0, 0];
  228. $totalBest = [0, 0];
  229. $totalAverage = [0, 0];
  230. $type = 'detail';
  231. if ($this->exportToPdf) {
  232. $type = 'simple';
  233. }
  234. $model = ExerciseLib::getCourseScoreModel();
  235. // Categories.
  236. if (!empty($data_array)) {
  237. foreach ($data_array as $data) {
  238. // list of items inside the gradebook (exercises, lps, forums, etc)
  239. $row = array();
  240. /** @var AbstractLink $item */
  241. $item = $mainCategory = $data[0];
  242. //if the item is invisible, wrap it in a span with class invisible
  243. $invisibility_span_open = api_is_allowed_to_edit() && $item->is_visible() == '0' ? '<span class="text-muted">' : '';
  244. $invisibility_span_close = api_is_allowed_to_edit() && $item->is_visible() == '0' ? '</span>' : '';
  245. // Id
  246. if ($this->teacherView) {
  247. if ($this->exportToPdf == false) {
  248. $row[] = $this->build_id_column($item);
  249. }
  250. }
  251. // Type.
  252. $row[] = $this->build_type_column($item);
  253. // Name.
  254. if (get_class($item) == 'Category') {
  255. $row[] = $invisibility_span_open.'<strong>'.$item->get_name().'</strong>'.$invisibility_span_close;
  256. $main_categories[$item->get_id()]['name'] = $item->get_name();
  257. } else {
  258. $name = $this->build_name_link($item, $type);
  259. $row[] = $invisibility_span_open.$name.$invisibility_span_close;
  260. $main_categories[$item->get_id()]['name'] = $name;
  261. }
  262. $this->dataForGraph['categories'][] = $item->get_name();
  263. $main_categories[$item->get_id()]['weight'] = $item->get_weight();
  264. $total_categories_weight += $item->get_weight();
  265. // Description.
  266. if ($this->exportToPdf == false) {
  267. $row[] = $invisibility_span_open.$data[2].$invisibility_span_close;
  268. }
  269. // Weight.
  270. $weight = $scoredisplay->display_score(
  271. array(
  272. $data['3'],
  273. $this->currentcat->get_weight()
  274. ),
  275. SCORE_SIMPLE,
  276. SCORE_BOTH,
  277. true
  278. );
  279. if ($this->teacherView) {
  280. $row[] = $invisibility_span_open.
  281. Display::tag('p', $weight, array('class' => 'score')).
  282. $invisibility_span_close;
  283. } else {
  284. $row[] = $invisibility_span_open.$weight.$invisibility_span_close;
  285. }
  286. $category_weight = $item->get_weight();
  287. $mainCategoryWeight = $main_cat[0]->get_weight();
  288. if ($this->teacherView) {
  289. $weight_total_links += $data[3];
  290. } else {
  291. $cattotal = Category::load($_GET['selectcat']);
  292. $scoretotal = $cattotal[0]->calc_score($this->userId);
  293. $item_value = $scoredisplay->display_score($scoretotal, SCORE_SIMPLE);
  294. }
  295. // Edit (for admins).
  296. if ($this->teacherView) {
  297. $cat = new Category();
  298. $show_message = $cat->show_message_resource_delete($item->get_course_code());
  299. if ($show_message === false) {
  300. $row[] = $this->build_edit_column($item);
  301. }
  302. } else {
  303. $score = $item->calc_score($this->userId);
  304. if (!empty($score[1])) {
  305. $completeScore = $scoredisplay->display_score($score, SCORE_DIV_PERCENT);
  306. $score = $score[0] / $score[1] * $item->get_weight();
  307. $score = $scoredisplay->display_score(array($score, null), SCORE_SIMPLE);
  308. $scoreToDisplay = Display::tip($score, $completeScore);
  309. } else {
  310. $scoreToDisplay = '-';
  311. $categoryScore = null;
  312. }
  313. // Students get the results and certificates columns
  314. //if (count($this->evals_links) > 0 && $status_user != 1) {
  315. if (1) {
  316. $value_data = isset($data[4]) ? $data[4] : null;
  317. $best = isset($data['best']) ? $data['best'] : null;
  318. $average = isset($data['average']) ? $data['average'] : null;
  319. $ranking = isset($data['ranking']) ? $data['ranking'] : null;
  320. $totalResult = [
  321. $data['result_score'][0],
  322. $data['result_score'][1],
  323. ];
  324. $totalBest = [
  325. $totalBest[0] + $data['best_score'][0],
  326. $totalBest[1] + $data['best_score'][1],
  327. ];
  328. $totalAverage = [
  329. $data['average_score'][0],
  330. $data['average_score'][1],
  331. ];
  332. // Student result
  333. if (empty($model)) {
  334. $row[] = $value_data;
  335. } else {
  336. $row[] = ExerciseLib::show_score(
  337. $data['result_score'][0],
  338. $data['result_score'][1]
  339. );
  340. }
  341. $totalResultAverageValue = strip_tags(
  342. $scoredisplay->display_score(
  343. $totalResult,
  344. SCORE_AVERAGE
  345. )
  346. );
  347. $this->dataForGraph['my_result'][] = floatval($totalResultAverageValue);
  348. $totalAverageValue = strip_tags($scoredisplay->display_score($totalAverage, SCORE_AVERAGE));
  349. $this->dataForGraph['average'][] = floatval($totalAverageValue);
  350. if (empty($model)) {
  351. // Ranking
  352. $row[] = $ranking;
  353. // Best
  354. $row[] = $best;
  355. // Average
  356. $row[] = $average;
  357. }
  358. if (get_class($item) == 'Category') {
  359. if ($this->exportToPdf == false) {
  360. $row[] = $this->build_edit_column($item);
  361. }
  362. }
  363. } else {
  364. $row[] = $scoreToDisplay;
  365. if (!empty($this->cats)) {
  366. if ($this->exportToPdf == false) {
  367. $row[] = $this->build_edit_column($item);
  368. }
  369. }
  370. }
  371. }
  372. // Category added.
  373. $sortable_data[] = $row;
  374. // Loading children
  375. if (get_class($item) == 'Category') {
  376. $course_code = api_get_course_id();
  377. $session_id = api_get_session_id();
  378. $parent_id = $item->get_id();
  379. $cats = Category::load(
  380. $parent_id,
  381. null,
  382. null,
  383. null,
  384. null,
  385. null
  386. );
  387. if (isset($cats[0])) {
  388. $allcat = $cats[0]->get_subcategories($this->userId, $course_code, $session_id);
  389. $alleval = $cats[0]->get_evaluations($this->userId);
  390. $alllink = $cats[0]->get_links($this->userId);
  391. $sub_cat_info = new GradebookDataGenerator($allcat, $alleval, $alllink);
  392. $sub_cat_info->userId = $user_id;
  393. $data_array2 = $sub_cat_info->get_data(
  394. $sorting,
  395. $from,
  396. $this->per_page,
  397. false,
  398. $this->studentList
  399. );
  400. $total_weight = 0;
  401. // Links.
  402. foreach ($data_array2 as $data) {
  403. $row = array();
  404. $item = $data[0];
  405. //if the item is invisible, wrap it in a span with class invisible
  406. $invisibility_span_open = api_is_allowed_to_edit() && $item->is_visible() == '0' ? '<span class="text-muted">' : '';
  407. $invisibility_span_close = api_is_allowed_to_edit() && $item->is_visible() == '0' ? '</span>' : '';
  408. if (isset($item)) {
  409. $main_categories[$parent_id]['children'][$item->get_id()]['name'] = $item->get_name();
  410. $main_categories[$parent_id]['children'][$item->get_id()]['weight'] = $item->get_weight();
  411. }
  412. if ($this->teacherView) {
  413. if ($this->exportToPdf == false) {
  414. $row[] = $this->build_id_column($item);
  415. }
  416. }
  417. // Type
  418. $row[] = $this->build_type_column($item, array('style' => 'padding-left:5px'));
  419. // Name.
  420. $row[] = $invisibility_span_open."&nbsp;&nbsp;&nbsp; ".
  421. $this->build_name_link($item, $type).$invisibility_span_close;
  422. // Description.
  423. if ($this->exportToPdf == false) {
  424. $row[] = $invisibility_span_open.$data[2].$invisibility_span_close;
  425. }
  426. $weight = $data[3];
  427. $total_weight += $weight;
  428. // Weight
  429. $row[] = $invisibility_span_open.$weight.$invisibility_span_close;
  430. if ($this->teacherView) {
  431. //$weight_total_links += intval($data[3]);
  432. } else {
  433. $cattotal = Category::load($_GET['selectcat']);
  434. $scoretotal = $cattotal[0]->calc_score($this->userId);
  435. $item_value = $scoretotal[0];
  436. }
  437. // Admins get an edit column.
  438. if (api_is_allowed_to_edit(null, true) &&
  439. isset($_GET['user_id']) == false &&
  440. (isset($_GET['action']) && $_GET['action'] != 'export_all' || !isset($_GET['action'])
  441. )
  442. ) {
  443. $cat = new Category();
  444. $show_message = $cat->show_message_resource_delete($item->get_course_code());
  445. if ($show_message === false) {
  446. if ($this->exportToPdf == false) {
  447. $row[] = $this->build_edit_column($item);
  448. }
  449. }
  450. } else {
  451. // Students get the results and certificates columns
  452. $eval_n_links = array_merge($alleval, $alllink);
  453. if (count($eval_n_links) > 0) {
  454. $value_data = isset($data[4]) ? $data[4] : null;
  455. if (!is_null($value_data)) {
  456. //$score = $item->calc_score(api_get_user_id());
  457. //$new_score = $data[3] * $score[0] / $score[1];
  458. //$new_score = floatval(number_format($new_score, api_get_setting('gradebook_number_decimals')));
  459. // Result
  460. $row[] = $value_data;
  461. $best = isset($data['best']) ? $data['best'] : null;
  462. $average = isset($data['average']) ? $data['average'] : null;
  463. $ranking = isset($data['ranking']) ? $data['ranking'] : null;
  464. // Ranking
  465. $row[] = $ranking;
  466. // Best
  467. $row[] = $best;
  468. // Average
  469. $row[] = $average;
  470. }
  471. }
  472. if (!empty($cats)) {
  473. if ($this->exportToPdf == false) {
  474. $row[] = null;
  475. }
  476. }
  477. }
  478. if ($this->exportToPdf == false) {
  479. $row['child_of'] = $parent_id;
  480. }
  481. $sortable_data[] = $row;
  482. }
  483. // "Warning row"
  484. if (!empty($data_array)) {
  485. if ($this->teacherView) {
  486. // Compare the category weight to the sum of all weights inside the category
  487. if (intval($total_weight) == $category_weight) {
  488. $label = null;
  489. $total = GradebookUtils::score_badges(
  490. array(
  491. $total_weight.' / '.$category_weight,
  492. '100'
  493. )
  494. );
  495. } else {
  496. $label = Display::return_icon(
  497. 'warning.png',
  498. sprintf(get_lang('TotalWeightMustBeX'), $category_weight)
  499. );
  500. $total = Display::badge($total_weight.' / '.$category_weight, 'warning');
  501. }
  502. $row = array(
  503. null,
  504. null,
  505. "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<h5>".get_lang('SubTotal').'</h5>',
  506. null,
  507. $total.' '.$label,
  508. 'child_of' => $parent_id
  509. );
  510. $sortable_data[] = $row;
  511. }
  512. }
  513. }
  514. }
  515. }
  516. } //end looping categories
  517. $main_weight = 0;
  518. if (count($main_cat) > 1) {
  519. /** @var Category $myCat */
  520. foreach ($main_cat as $myCat) {
  521. $myParentId = $myCat->get_parent_id();
  522. if ($myParentId == 0) {
  523. $main_weight = intval($myCat->get_weight());
  524. }
  525. }
  526. }
  527. if ($this->teacherView) {
  528. // Total for teacher.
  529. if (count($main_cat) > 1) {
  530. if (intval($total_categories_weight) == $main_weight) {
  531. $total = GradebookUtils::score_badges(
  532. array(
  533. $total_categories_weight.' / '.$main_weight,
  534. '100'
  535. )
  536. );
  537. } else {
  538. $total = Display::badge($total_categories_weight.' / '.$main_weight, 'warning');
  539. }
  540. $row = array(
  541. null,
  542. null,
  543. '<strong>'.get_lang('Total').'</strong>',
  544. null,
  545. $total
  546. );
  547. $sortable_data[] = $row;
  548. }
  549. } else {
  550. // Total for student.
  551. if (count($main_cat) > 1) {
  552. $main_weight = intval($main_cat[0]->get_weight());
  553. $global = null;
  554. $average = null;
  555. // Overwrite main weight
  556. $totalResult[1] = $main_weight;
  557. $totalResult = $scoredisplay->display_score(
  558. $totalResult,
  559. SCORE_DIV
  560. );
  561. $totalRanking = array();
  562. $invalidateRanking = true;
  563. $average = 0;
  564. foreach ($this->studentList as $student) {
  565. $score = $main_cat[0]->calc_score($student['user_id']);
  566. if (!empty($score[0])) {
  567. $invalidateRanking = false;
  568. }
  569. $totalRanking[$student['user_id']] = $score[0];
  570. $average += $score[0];
  571. }
  572. $totalRanking = AbstractLink::getCurrentUserRanking($user_id, $totalRanking);
  573. $totalRanking = $scoredisplay->display_score(
  574. $totalRanking,
  575. SCORE_DIV,
  576. SCORE_BOTH,
  577. true
  578. );
  579. if ($invalidateRanking) {
  580. $totalRanking = null;
  581. }
  582. // Overwrite main weight
  583. $totalBest[1] = $main_weight;
  584. $totalBest = $scoredisplay->display_score(
  585. $totalBest,
  586. SCORE_DIV,
  587. SCORE_BOTH,
  588. true
  589. );
  590. // Overwrite main weight
  591. $totalAverage[0] = $average / count($this->studentList);
  592. $totalAverage[1] = $main_weight;
  593. $totalAverage = $scoredisplay->display_score(
  594. $totalAverage,
  595. SCORE_DIV,
  596. SCORE_BOTH,
  597. true
  598. );
  599. if ($this->exportToPdf) {
  600. $row = array(
  601. null,
  602. '<h3>'.get_lang('Total').'</h3>',
  603. $main_weight,
  604. $totalResult,
  605. $totalRanking,
  606. $totalBest,
  607. $totalAverage
  608. );
  609. } else {
  610. $row = array(
  611. null,
  612. '<h3>'.get_lang('Total').'</h3>',
  613. null,
  614. $main_weight,
  615. $totalResult,
  616. $totalRanking,
  617. $totalBest,
  618. $totalAverage
  619. );
  620. }
  621. $sortable_data[] = $row;
  622. }
  623. }
  624. // Warning messages
  625. $view = isset($_GET['view']) ? $_GET['view'] : null;
  626. if ($this->teacherView) {
  627. if (isset($_GET['selectcat']) &&
  628. $_GET['selectcat'] > 0 &&
  629. $view <> 'presence'
  630. ) {
  631. $id_cat = intval($_GET['selectcat']);
  632. $category = Category::load($id_cat);
  633. $weight_category = intval($this->build_weight($category[0]));
  634. $course_code = $this->build_course_code($category[0]);
  635. $weight_total_links = round($weight_total_links);
  636. if ($weight_total_links > $weight_category ||
  637. $weight_total_links < $weight_category ||
  638. $weight_total_links > $weight_category
  639. ) {
  640. $warning_message = sprintf(get_lang('TotalWeightMustBeX'), $weight_category);
  641. $modify_icons = '<a href="gradebook_edit_cat.php?editcat='.$id_cat.'&cidReq='.$course_code.'&id_session='.api_get_session_id().'">'.
  642. Display::return_icon('edit.png', $warning_message, array(), ICON_SIZE_SMALL).'</a>';
  643. $warning_message .= $modify_icons;
  644. echo Display::return_message($warning_message, 'warning', false);
  645. }
  646. $content_html = DocumentManager::replace_user_info_into_html(
  647. api_get_user_id(),
  648. $course_code,
  649. api_get_session_id()
  650. );
  651. if (!empty($content_html)) {
  652. $new_content = explode('</head>', $content_html['content']);
  653. }
  654. if (empty($new_content[0])) {
  655. // Set default certificate
  656. $courseData = api_get_course_info($course_code);
  657. DocumentManager::generateDefaultCertificate($courseData);
  658. }
  659. }
  660. if (empty($_GET['selectcat'])) {
  661. $categories = Category::load();
  662. $weight_categories = $certificate_min_scores = $course_codes = array();
  663. foreach ($categories as $category) {
  664. $course_code_category = $this->build_course_code($category);
  665. if (!empty($course_code)) {
  666. if ($course_code_category == $course_code) {
  667. $weight_categories[] = intval($this->build_weight($category));
  668. $certificate_min_scores[] = intval($this->build_certificate_min_score($category));
  669. $course_codes[] = $course_code;
  670. break;
  671. }
  672. } else {
  673. $weight_categories[] = intval($this->build_weight($category));
  674. $certificate_min_scores[] = intval($this->build_certificate_min_score($category));
  675. $course_codes[] = $course_code_category;
  676. }
  677. }
  678. if (is_array($weight_categories) &&
  679. is_array($certificate_min_scores) &&
  680. is_array($course_codes)
  681. ) {
  682. $warning_message = '';
  683. for ($x = 0; $x < count($weight_categories); $x++) {
  684. $weight_category = intval($weight_categories[$x]);
  685. $certificate_min_score = intval($certificate_min_scores[$x]);
  686. $course_code = $course_codes[$x];
  687. if (empty($certificate_min_score) ||
  688. ($certificate_min_score > $weight_category)
  689. ) {
  690. $warning_message .= $course_code.'&nbsp;-&nbsp;'.get_lang('CertificateMinimunScoreIsRequiredAndMustNotBeMoreThan').'&nbsp;'.$weight_category.'<br />';
  691. }
  692. }
  693. if (!empty($warning_message)) {
  694. echo Display::return_message($warning_message, 'warning', false);
  695. }
  696. }
  697. }
  698. }
  699. return $sortable_data;
  700. }
  701. /**
  702. * @return array
  703. */
  704. private function getDataForGraph()
  705. {
  706. return $this->dataForGraph;
  707. }
  708. /**
  709. * @return string
  710. */
  711. public function getGraph()
  712. {
  713. $data = $this->getDataForGraph();
  714. if (!empty($data) &&
  715. isset($data['categories']) &&
  716. isset($data['my_result']) &&
  717. isset($data['average'])
  718. ) {
  719. $dataSet = new pData();
  720. $dataSet->addPoints($data['my_result'], get_lang('Me'));
  721. // In order to generate random values
  722. // $data['average'] = array(rand(0,50), rand(0,50));
  723. $dataSet->addPoints($data['average'], get_lang('Average'));
  724. $dataSet->addPoints($data['categories'], 'categories');
  725. $dataSet->setAbscissa("categories");
  726. $xSize = 600;
  727. $ySize = 400;
  728. $pChart = new pImage($xSize, $ySize, $dataSet);
  729. /* Turn of Antialiasing */
  730. $pChart->Antialias = false;
  731. /* Add a border to the picture */
  732. $pChart->drawRectangle(
  733. 0,
  734. 0,
  735. $xSize - 1,
  736. $ySize - 1,
  737. array("R" => 0, "G" => 0, "B" => 0)
  738. );
  739. $pChart->drawText(
  740. 10,
  741. 16,
  742. get_lang('Results'),
  743. array("FontSize" => 11, "Align" => TEXT_ALIGN_BOTTOMMIDDLE)
  744. );
  745. $pChart->setGraphArea(50, 30, $xSize - 50, $ySize - 70);
  746. $pChart->setFontProperties(
  747. array(
  748. 'FontName' => api_get_path(SYS_FONTS_PATH).'opensans/OpenSans-Regular.ttf',
  749. 'FontSize' => 10,
  750. )
  751. );
  752. /* Draw the scale */
  753. $scaleSettings = array(
  754. "XMargin" => AUTO,
  755. "YMargin" => 10,
  756. "Floating" => true,
  757. "GridR" => 200,
  758. "GridG" => 200,
  759. "GridB" => 200,
  760. "DrawSubTicks" => true,
  761. "CycleBackground" => true,
  762. 'LabelRotation' => 10
  763. );
  764. $pChart->drawScale($scaleSettings);
  765. /* Draw the line chart */
  766. $pChart->drawLineChart();
  767. $pChart->drawPlotChart(
  768. array(
  769. "DisplayValues" => true,
  770. "PlotBorder" => true,
  771. "BorderSize" => 2,
  772. "Surrounding" => -60,
  773. "BorderAlpha" => 80,
  774. )
  775. );
  776. /* Write the chart legend */
  777. $pChart->drawLegend(
  778. $xSize - 180,
  779. 9,
  780. array(
  781. "Style" => LEGEND_NOBORDER,
  782. "Mode" => LEGEND_HORIZONTAL,
  783. "FontR" => 0,
  784. "FontG" => 0,
  785. "FontB" => 0,
  786. )
  787. );
  788. $cachePath = api_get_path(SYS_ARCHIVE_PATH);
  789. $myCache = new pCache(array('CacheFolder' => substr($cachePath, 0, strlen($cachePath) - 1)));
  790. $chartHash = $myCache->getHash($dataSet);
  791. $myCache->writeToCache($chartHash, $pChart);
  792. $imgSysPath = api_get_path(SYS_ARCHIVE_PATH).$chartHash;
  793. $myCache->saveFromCache($chartHash, $imgSysPath);
  794. $imgWebPath = api_get_path(WEB_ARCHIVE_PATH).$chartHash;
  795. if (file_exists($imgSysPath)) {
  796. $result = '<div id="contentArea" style="text-align: center;" >';
  797. $result .= '<img src="'.$imgWebPath.'" >';
  798. $result .= '</div>';
  799. return $result;
  800. }
  801. }
  802. return '';
  803. }
  804. /**
  805. * @param $item
  806. * @return mixed
  807. */
  808. private function build_certificate_min_score($item)
  809. {
  810. return $item->getCertificateMinScore();
  811. }
  812. /**
  813. * @param $item
  814. * @return mixed
  815. */
  816. private function build_weight($item)
  817. {
  818. return $item->get_weight();
  819. }
  820. /**
  821. * @param $item
  822. * @return mixed
  823. */
  824. private function build_course_code($item)
  825. {
  826. return $item->get_course_code();
  827. }
  828. /**
  829. * @param $item
  830. * @return string
  831. */
  832. private function build_id_column($item)
  833. {
  834. switch ($item->get_item_type()) {
  835. // category
  836. case 'C':
  837. return 'CATE'.$item->get_id();
  838. // evaluation
  839. case 'E':
  840. return 'EVAL'.$item->get_id();
  841. // link
  842. case 'L':
  843. return 'LINK'.$item->get_id();
  844. }
  845. }
  846. /**
  847. * @param $item
  848. * @param array $attributes
  849. * @return string
  850. */
  851. private function build_type_column($item, $attributes = array())
  852. {
  853. return GradebookUtils::build_type_icon_tag($item->get_icon_name(), $attributes);
  854. }
  855. /**
  856. * Generate name column
  857. * @param GradebookItem $item
  858. * @param string $type simple|detail
  859. * @return string
  860. */
  861. private function build_name_link($item, $type = 'detail')
  862. {
  863. $view = isset($_GET['view']) ? Security::remove_XSS($_GET['view']) : null;
  864. $categoryId = $item->getCategory()->get_id();
  865. switch ($item->get_item_type()) {
  866. // category
  867. case 'C':
  868. $prms_uri = '?selectcat='.$item->get_id().'&view='.$view;
  869. $isStudentView = api_is_student_view_active();
  870. if (isset($is_student) || $isStudentView) {
  871. $prms_uri = $prms_uri.'&amp;isStudentView=studentview';
  872. }
  873. $cat = new Category();
  874. $show_message = $cat->show_message_resource_delete($item->get_course_code());
  875. return '&nbsp;<a href="'.Category::getUrl().$prms_uri.'">'
  876. .$item->get_name()
  877. .'</a>'
  878. .($item->is_course() ? ' &nbsp;['.$item->get_course_code().']'.$show_message : '');
  879. // evaluation
  880. //no break because of return
  881. case 'E':
  882. $cat = new Category();
  883. $course_id = CourseManager::get_course_by_category($categoryId);
  884. $show_message = $cat->show_message_resource_delete($course_id);
  885. // course/platform admin can go to the view_results page
  886. if (api_is_allowed_to_edit() && $show_message === false) {
  887. if ($item->get_type() == 'presence') {
  888. return '&nbsp;'
  889. .'<a href="gradebook_view_result.php?cidReq='.$course_id.'&amp;selecteval='.$item->get_id().'">'
  890. .$item->get_name()
  891. .'</a>';
  892. } else {
  893. $extra = Display::label(get_lang('Evaluation'));
  894. if ($type == 'simple') {
  895. $extra = '';
  896. }
  897. return '&nbsp;'
  898. .'<a href="gradebook_view_result.php?'.api_get_cidreq().'&selecteval='.$item->get_id().'">'
  899. .$item->get_name()
  900. .'</a>&nbsp;'.$extra;
  901. }
  902. } elseif (ScoreDisplay::instance()->is_custom() && $show_message === false) {
  903. // students can go to the statistics page (if custom display enabled)
  904. return '&nbsp;'
  905. .'<a href="gradebook_statistics.php?'.api_get_cidreq().'&selecteval='.$item->get_id().'">'
  906. .$item->get_name()
  907. .'</a>';
  908. } elseif ($show_message === false && !api_is_allowed_to_edit() && !ScoreDisplay::instance()->is_custom()) {
  909. return '&nbsp;'
  910. .'<a href="gradebook_statistics.php?'.api_get_cidreq().'&selecteval='.$item->get_id().'">'
  911. .$item->get_name()
  912. .'</a>';
  913. } else {
  914. return '['.get_lang('Evaluation').']&nbsp;&nbsp;'.$item->get_name().$show_message;
  915. }
  916. // no break because of return
  917. case 'L':
  918. // link
  919. $cat = new Category();
  920. $course_id = CourseManager::get_course_by_category($categoryId);
  921. $show_message = $cat->show_message_resource_delete($course_id);
  922. $url = $item->get_link();
  923. if (isset($url) && $show_message === false) {
  924. $text = '&nbsp;<a href="'.$item->get_link().'">'
  925. .$item->get_name()
  926. .'</a>';
  927. } else {
  928. $text = $item->get_name();
  929. }
  930. $extra = Display::label($item->get_type_name(), 'info');
  931. if ($type == 'simple') {
  932. $extra = '';
  933. }
  934. $text .= "&nbsp;".$extra.$show_message;
  935. $cc = $this->currentcat->get_course_code();
  936. if (empty($cc)) {
  937. $text .= '&nbsp;[<a href="'.api_get_path(REL_COURSE_PATH).$item->get_course_code().'/">'.$item->get_course_code().'</a>]';
  938. }
  939. return $text;
  940. }
  941. }
  942. /**
  943. * @param AbstractLink $item
  944. * @return null|string
  945. */
  946. private function build_edit_column($item)
  947. {
  948. switch ($item->get_item_type()) {
  949. // category
  950. case 'C':
  951. return GradebookUtils::build_edit_icons_cat($item, $this->currentcat);
  952. // evaluation
  953. case 'E':
  954. return GradebookUtils::build_edit_icons_eval($item, $this->currentcat->get_id());
  955. // link
  956. case 'L':
  957. return GradebookUtils::build_edit_icons_link($item, $this->currentcat->get_id());
  958. }
  959. }
  960. }