evaluation.class.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. <?php
  2. /*
  3. ==============================================================================
  4. Dokeos - elearning and course management software
  5. Copyright (c) 2008 Dokeos Latinoamerica SAC
  6. Copyright (c) 2006 Dokeos SPRL
  7. Copyright (c) 2006 Ghent University (UGent)
  8. Copyright (c) various contributors
  9. For a full list of contributors, see "credits.txt".
  10. The full license can be read in "license.txt".
  11. This program is free software; you can redistribute it and/or
  12. modify it under the terms of the GNU General Public License
  13. as published by the Free Software Foundation; either version 2
  14. of the License, or (at your option) any later version.
  15. See the GNU General Public License for more details.
  16. Contact address: Dokeos, rue du Corbeau, 108, B-1030 Brussels, Belgium
  17. Mail: info@dokeos.com
  18. ==============================================================================
  19. */
  20. /**
  21. * Defines a gradebook Evaluation object
  22. * @author Bert Stepp�, Stijn Konings
  23. * @package dokeos.gradebook
  24. */
  25. class Evaluation implements GradebookItem
  26. {
  27. // PROPERTIES
  28. private $id;
  29. private $name;
  30. private $description;
  31. private $user_id;
  32. private $course_code;
  33. private $category;
  34. private $eval_date;
  35. private $weight;
  36. private $eval_max;
  37. private $visible;
  38. // CONSTRUCTORS
  39. function Evaluation() {
  40. }
  41. // GETTERS AND SETTERS
  42. public function get_id() {
  43. return $this->id;
  44. }
  45. public function get_name() {
  46. return $this->name;
  47. }
  48. public function get_description() {
  49. return $this->description;
  50. }
  51. public function get_user_id() {
  52. return $this->user_id;
  53. }
  54. public function get_course_code() {
  55. return $this->course_code;
  56. }
  57. public function get_category_id() {
  58. return $this->category;
  59. }
  60. public function get_date() {
  61. return $this->eval_date;
  62. }
  63. public function get_weight() {
  64. return $this->weight;
  65. }
  66. public function get_max() {
  67. return $this->eval_max;
  68. }
  69. public function is_visible() {
  70. return $this->visible;
  71. }
  72. public function set_id ($id) {
  73. $this->id = $id;
  74. }
  75. public function set_name ($name) {
  76. $this->name = $name;
  77. }
  78. public function set_description ($description) {
  79. $this->description = $description;
  80. }
  81. public function set_user_id ($user_id) {
  82. $this->user_id = $user_id;
  83. }
  84. public function set_course_code ($course_code) {
  85. $this->course_code = $course_code;
  86. }
  87. public function set_category_id ($category_id) {
  88. $this->category = $category_id;
  89. }
  90. public function set_date ($date) {
  91. $this->eval_date = $date;
  92. }
  93. public function set_weight ($weight) {
  94. $this->weight = $weight;
  95. }
  96. public function set_max ($max) {
  97. $this->eval_max = $max;
  98. }
  99. public function set_visible ($visible) {
  100. $this->visible = $visible;
  101. }
  102. // CRUD FUNCTIONS
  103. /**
  104. * Retrieve evaluations and return them as an array of Evaluation objects
  105. * @param $id evaluation id
  106. * @param $user_id user id (evaluation owner)
  107. * @param $course_code course code
  108. * @param $category_id parent category
  109. * @param $visible visible
  110. */
  111. public function load ($id = null, $user_id = null, $course_code = null, $category_id = null, $visible = null)
  112. {
  113. $tbl_grade_evaluations = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_EVALUATION);
  114. $sql='SELECT id,name,description,user_id,course_code,category_id,date,weight,max,visible FROM '.$tbl_grade_evaluations;
  115. $paramcount = 0;
  116. if (isset ($id)) {
  117. $sql.= ' WHERE id = '.$id;
  118. $paramcount ++;
  119. }
  120. if (isset ($user_id)) {
  121. if ($paramcount != 0) $sql .= ' AND';
  122. else $sql .= ' WHERE';
  123. $sql .= ' user_id = '.$user_id;
  124. $paramcount ++;
  125. }
  126. if (isset ($course_code)) {
  127. if ($paramcount != 0) $sql .= ' AND';
  128. else $sql .= ' WHERE';
  129. $sql .= " course_code = '".$course_code."'";
  130. $paramcount ++;
  131. }
  132. if (isset ($category_id)) {
  133. if ($paramcount != 0) $sql .= ' AND';
  134. else $sql .= ' WHERE';
  135. $sql .= ' category_id = '.$category_id;
  136. $paramcount ++;
  137. }
  138. if (isset ($visible)) {
  139. if ($paramcount != 0) $sql .= ' AND';
  140. else $sql .= ' WHERE';
  141. $sql .= ' visible = '.$visible;
  142. $paramcount ++;
  143. }
  144. $result = Database::query($sql);
  145. $alleval = Evaluation::create_evaluation_objects_from_sql_result($result);
  146. return $alleval;
  147. }
  148. private function create_evaluation_objects_from_sql_result($result)
  149. {
  150. $alleval=array();
  151. while ($data=Database::fetch_array($result)) {
  152. $eval= new Evaluation();
  153. $eval->set_id($data['id']);
  154. $eval->set_name($data['name']);
  155. $eval->set_description($data['description']);
  156. $eval->set_user_id($data['user_id']);
  157. $eval->set_course_code($data['course_code']);
  158. $eval->set_category_id($data['category_id']);
  159. $eval->set_date(api_get_local_time($data['date']));
  160. $eval->set_weight($data['weight']);
  161. $eval->set_max($data['max']);
  162. $eval->set_visible($data['visible']);
  163. $alleval[]=$eval;
  164. }
  165. return $alleval;
  166. }
  167. /**
  168. * Insert this evaluation into the database
  169. */
  170. public function add()
  171. {
  172. if (isset($this->name) && isset($this->user_id) && isset($this->weight) && isset ($this->eval_max) && isset($this->visible)) {
  173. $tbl_grade_evaluations = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_EVALUATION);
  174. $sql = 'INSERT INTO '.$tbl_grade_evaluations
  175. .' (name,user_id,weight,max,visible';
  176. if (isset($this->description)) {
  177. $sql .= ',description';
  178. }
  179. if (isset($this->course_code)) {
  180. $sql .= ',course_code';
  181. }
  182. if (isset($this->category)) {
  183. $sql .= ',category_id';
  184. }
  185. if (isset($this->eval_date)) {
  186. $sql .= ',date';
  187. }
  188. $sql .= ") VALUES ('".Database::escape_string(Security::remove_XSS($this->get_name()))."'"
  189. .','.$this->get_user_id()
  190. .','.$this->get_weight()
  191. .','.$this->get_max()
  192. .','.$this->is_visible();
  193. if (isset($this->description)) {
  194. $sql .= ",'".Database::escape_string(Security::remove_XSS($this->get_description()))."'";
  195. }
  196. if (isset($this->course_code)) {
  197. $sql .= ",'".$this->get_course_code()."'";
  198. }
  199. if (isset($this->category)) {
  200. $sql .= ','.$this->get_category_id();
  201. }
  202. //if (isset($this->eval_date)) {
  203. $sql .= ','.strtotime(date('Y-m-d H:i:s',time()));
  204. //}
  205. $sql .= ")";
  206. Database::query($sql);
  207. $this->set_id(Database::insert_id());
  208. }
  209. else {
  210. die('Error in Evaluation add: required field empty');
  211. }
  212. }
  213. public function add_evaluation_log($idevaluation){
  214. if (!empty($idevaluation)) {
  215. $tbl_grade_evaluations = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_EVALUATION);
  216. $tbl_grade_linkeval_log = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_LINKEVAL_LOG);
  217. $eval=new Evaluation();
  218. $dateobject=$eval->load ($idevaluation,null,null,null,null);
  219. $arreval=get_object_vars($dateobject[0]);
  220. if (!empty($arreval['id'])) {
  221. $sql_eval='SELECT weight from '.$tbl_grade_evaluations.' WHERE id='.$arreval['id'];
  222. $rs=Database::query($sql_eval);
  223. $row_old_weight=Database::fetch_array($rs,'ASSOC');
  224. $current_date=strtotime(date('Y-m-d H:i:s',time()));
  225. $sql="INSERT INTO ".$tbl_grade_linkeval_log."(id_linkeval_log,name,description,date_log,weight,visible,type,user_id_log)VALUES('".Database::escape_string($arreval['id'])."','".Database::escape_string($arreval['name'])."','".Database::escape_string($arreval['description'])."','".Database::escape_string($current_date)."','".Database::escape_string($row_old_weight['weight'])."','".Database::escape_string($arreval['visible'])."','evaluation',".api_get_user_id().")";
  226. Database::query($sql);
  227. }
  228. }
  229. }
  230. /**
  231. * Update the properties of this evaluation in the database
  232. */
  233. public function save() {
  234. $tbl_grade_evaluations = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_EVALUATION);
  235. $sql = 'UPDATE '.$tbl_grade_evaluations
  236. ." SET name = '".Database::escape_string(Security::remove_XSS($this->get_name()))."'"
  237. .', description = ';
  238. if (isset($this->description)) {
  239. $sql .= "'".Database::escape_string(Security::remove_XSS($this->get_description()))."'";
  240. }else {
  241. $sql .= 'null';
  242. }
  243. $sql .= ', user_id = '.$this->get_user_id()
  244. .', course_code = ';
  245. if (isset($this->course_code)) {
  246. $sql .= "'".$this->get_course_code()."'";
  247. } else {
  248. $sql .= 'null';
  249. }
  250. $sql .= ', category_id = ';
  251. if (isset($this->category)) {
  252. $sql .= $this->get_category_id();
  253. } else {
  254. $sql .= 'null';
  255. }
  256. $sql .= ', weight = '.$this->get_weight()
  257. .', max = '.$this->get_max()
  258. .', visible = '.$this->is_visible()
  259. .' WHERE id = '.$this->id;
  260. //recorded history
  261. $eval_log=new Evaluation();
  262. $eval_log->add_evaluation_log($this->id);
  263. Database::query($sql);
  264. }
  265. /**
  266. * Delete this evaluation from the database
  267. */
  268. public function delete() {
  269. $tbl_grade_evaluations = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_EVALUATION);
  270. $sql = 'DELETE FROM '.$tbl_grade_evaluations.' WHERE id = '.$this->id;
  271. Database::query($sql);
  272. }
  273. // OTHER FUNCTIONS
  274. /**
  275. * Check if an evaluation name (with the same parent category) already exists
  276. * @param $name name to check (if not given, the name property of this object will be checked)
  277. * @param $parent parent category
  278. */
  279. public function does_name_exist($name, $parent) {
  280. if (!isset ($name)) {
  281. $name = $this->name;
  282. $parent = $this->category;
  283. }
  284. $tbl_grade_evaluations = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_EVALUATION);
  285. $sql = 'SELECT count(id) AS number'
  286. .' FROM '.$tbl_grade_evaluations
  287. ." WHERE name = '".$name."'";
  288. if (api_is_allowed_to_create_course()) {
  289. $parent = Category::load($parent);
  290. $code = $parent[0]->get_course_code();
  291. if (isset($code) && $code != '0') {
  292. $main_course_user_table = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
  293. $sql .= ' AND user_id IN ('
  294. .' SELECT user_id FROM '.$main_course_user_table
  295. ." WHERE course_code = '".$code."'"
  296. .' AND status = '.COURSEMANAGER
  297. .')';
  298. } else {
  299. $sql .= ' AND user_id = '.api_get_user_id();
  300. }
  301. }else {
  302. $sql .= ' AND user_id = '.api_get_user_id();
  303. }
  304. if (!isset ($parent)) {
  305. $sql.= ' AND category_id is null';
  306. } else {
  307. $sql.= ' AND category_id = '.$parent;
  308. }
  309. $result = Database::query($sql);
  310. $number=Database::fetch_row($result);
  311. return ($number[0] != 0);
  312. }
  313. /**
  314. * Are there any results for this evaluation yet ?
  315. * The 'max' property should not be changed then.
  316. */
  317. public function has_results() {
  318. $tbl_grade_results = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_RESULT);
  319. $sql='SELECT count(id) AS number FROM '.$tbl_grade_results
  320. .' WHERE evaluation_id = '.$this->id;
  321. $result = Database::query($sql);
  322. $number=Database::fetch_row($result);
  323. return ($number[0] != 0);
  324. }
  325. /**
  326. * Does this evaluation have any results for a student ?
  327. */
  328. /* - not used anywhere (yet ?)
  329. public function has_results_for_student($stud_id)
  330. {
  331. $tbl_grade_results = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_RESULT);
  332. $sql="SELECT count(id) AS number FROM ".$tbl_grade_results
  333. ." WHERE evaluation_id = ".$this->id." AND user_id = ".$stud_id;
  334. $result = Database::query($sql);
  335. $number=Database::fetch_row($result);
  336. return ($number[0] != 0);
  337. }
  338. */
  339. /**
  340. * Delete all results for this evaluation
  341. */
  342. public function delete_results() {
  343. $tbl_grade_results = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_RESULT);
  344. $sql = 'DELETE FROM '.$tbl_grade_results.' WHERE evaluation_id = '.$this->id;
  345. Database::query($sql);
  346. }
  347. /**
  348. * Delete this evaluation and all underlying results.
  349. */
  350. public function delete_with_results(){
  351. $this->delete_results();
  352. $this->delete();
  353. }
  354. /**
  355. * Check if the given score is possible for this evaluation
  356. */
  357. public function is_valid_score ($score) {
  358. return (is_numeric($score) && $score >= 0 && $score <= $this->eval_max);
  359. }
  360. /**
  361. * Calculate the score of this evaluation
  362. * @param $stud_id student id (default: all students who have results for this eval - then the average is returned)
  363. * @return array (score, max) if student is given
  364. * array (sum of scores, number of scores) otherwise
  365. * or null if no scores available
  366. */
  367. public function calc_score ($stud_id = null) {
  368. $results = Result::load(null,$stud_id,$this->id);
  369. $rescount = 0;
  370. $sum = 0;
  371. foreach ($results as $res) {
  372. $score = $res->get_score();
  373. if ((!empty ($score)) || ($score == '0')) {
  374. $rescount++;
  375. $sum += ($score / $this->get_max());
  376. }
  377. }
  378. if ($rescount == 0) {
  379. return null;
  380. }
  381. else if (isset($stud_id)) {
  382. return array ($score, $this->get_max());
  383. } else {
  384. return array ($sum, $rescount);
  385. }
  386. }
  387. /**
  388. * Generate an array of possible categories where this evaluation can be moved to.
  389. * Notice: its own parent will be included in the list: it's up to the frontend
  390. * to disable this element.
  391. * @return array 2-dimensional array - every element contains 3 subelements (id, name, level)
  392. */
  393. public function get_target_categories() {
  394. // - course independent evaluation
  395. // -> movable to root or other course independent categories
  396. // - evaluation inside a course
  397. // -> movable to root, independent categories or categories inside the course
  398. $user = (api_is_platform_admin() ? null : api_get_user_id());
  399. $targets = array();
  400. $level = 0;
  401. $root = array(0, get_lang('RootCat'), $level);
  402. $targets[] = $root;
  403. if (isset($this->course_code) && !empty($this->course_code)) {
  404. $crscats = Category::load(null,null,$this->course_code,0);
  405. foreach ($crscats as $cat) {
  406. $targets[] = array ($cat->get_id(), $cat->get_name(), $level+1);
  407. $targets = $this->add_target_subcategories($targets, $level+1, $cat->get_id());
  408. }
  409. }
  410. $indcats = Category::load(null,$user,0,0);
  411. foreach ($indcats as $cat) {
  412. $targets[] = array ($cat->get_id(), $cat->get_name(), $level+1);
  413. $targets = $this->add_target_subcategories($targets, $level+1, $cat->get_id());
  414. }
  415. return $targets;
  416. }
  417. /**
  418. * Internal function used by get_target_categories()
  419. */
  420. private function add_target_subcategories($targets, $level, $catid) {
  421. $subcats = Category::load(null,null,null,$catid);
  422. foreach ($subcats as $cat) {
  423. $targets[] = array ($cat->get_id(), $cat->get_name(), $level+1);
  424. $targets = $this->add_target_subcategories($targets, $level+1, $cat->get_id());
  425. }
  426. return $targets;
  427. }
  428. /**
  429. * Move this evaluation to the given category.
  430. * If this evaluation moves from inside a course to outside,
  431. * its course code is also changed.
  432. */
  433. public function move_to_cat ($cat) {
  434. $this->set_category_id($cat->get_id());
  435. if ($this->get_course_code() != $cat->get_course_code()) {
  436. $this->set_course_code($cat->get_course_code());
  437. }
  438. $this->save();
  439. }
  440. /**
  441. * Retrieve evaluations where a student has results for
  442. * and return them as an array of Evaluation objects
  443. * @param $cat_id parent category (use 'null' to retrieve them in all categories)
  444. * @param $stud_id student id
  445. */
  446. public function get_evaluations_with_result_for_student ($cat_id = null, $stud_id) {
  447. $tbl_grade_evaluations = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_EVALUATION);
  448. $tbl_grade_results = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_RESULT);
  449. $sql = 'SELECT * FROM '.$tbl_grade_evaluations
  450. .' WHERE id IN'
  451. .'(SELECT evaluation_id FROM '.$tbl_grade_results
  452. .' WHERE user_id = '.$stud_id.' AND score IS NOT NULL)';
  453. if (!api_is_allowed_to_create_course()) {
  454. $sql .= ' AND visible = 1';
  455. }
  456. if (isset($cat_id)) {
  457. $sql .= ' AND category_id = '.$cat_id;
  458. } else {
  459. $sql .= ' AND category_id >= 0';
  460. }
  461. $result = Database::query($sql);
  462. $alleval = Evaluation::create_evaluation_objects_from_sql_result($result);
  463. return $alleval;
  464. }
  465. /**
  466. * Get a list of students that do not have a result record for this evaluation
  467. */
  468. public function get_not_subscribed_students ($first_letter_user = '') {
  469. $tbl_user = Database :: get_main_table(TABLE_MAIN_USER);
  470. $tbl_grade_results = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_RESULT);
  471. $sql = 'SELECT user_id,lastname,firstname,username FROM '.$tbl_user
  472. ." WHERE lastname LIKE '".$first_letter_user."%'"
  473. .' AND status = '.STUDENT
  474. .' AND user_id NOT IN'
  475. .' (SELECT user_id FROM '.$tbl_grade_results
  476. .' WHERE evaluation_id = '.$this->id
  477. .' )'
  478. .' ORDER BY lastname';
  479. $result = Database::query($sql);
  480. $db_users = Database::store_result($result);
  481. return $db_users;
  482. }
  483. /**
  484. * Find evaluations by name
  485. * @param string $name_mask search string
  486. * @return array evaluation objects matching the search criterium
  487. * @todo can be written more efficiently using a new (but very complex) sql query
  488. */
  489. public function find_evaluations ($name_mask,$selectcat) {
  490. $rootcat = Category::load($selectcat);
  491. $evals = $rootcat[0]->get_evaluations((api_is_allowed_to_create_course() ? null : api_get_user_id()), true);
  492. $foundevals = array();
  493. foreach ($evals as $eval) {
  494. if (!(api_strpos(api_strtolower($eval->get_name()), api_strtolower($name_mask)) === false)) {
  495. $foundevals[] = $eval;
  496. }
  497. }
  498. return $foundevals;
  499. }
  500. // Other methods implementing GradebookItem
  501. public function get_item_type() {
  502. return 'E';
  503. }
  504. public function get_icon_name() {
  505. return $this->has_results() ? 'evalnotempty' : 'evalempty';
  506. }
  507. }