category.class.php 69 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * Class Category
  5. * Defines a gradebook Category object
  6. * @package chamilo.gradebook
  7. */
  8. class Category implements GradebookItem
  9. {
  10. private $id;
  11. private $name;
  12. private $description;
  13. private $user_id;
  14. private $course_code;
  15. private $parent;
  16. private $weight;
  17. private $visible;
  18. private $certificate_min_score;
  19. private $session_id;
  20. private $skills = array();
  21. private $grade_model_id;
  22. private $generateCertificates;
  23. private $isRequirement;
  24. /**
  25. * Consctructor
  26. */
  27. public function __construct()
  28. {
  29. $this->id = 0;
  30. $this->name = null;
  31. $this->description = null;
  32. $this->user_id = 0;
  33. $this->course_code = null;
  34. $this->parent = 0;
  35. $this->weight = 0;
  36. $this->visible = false;
  37. $this->certificate_min_score = 0;
  38. $this->session_id = 0;
  39. $this->grade_model_id = 0;
  40. $this->generateCertificates = false;
  41. $this->isRequirement = false;
  42. }
  43. /**
  44. * @return int
  45. */
  46. public function get_id()
  47. {
  48. return $this->id;
  49. }
  50. /**
  51. * @return string
  52. */
  53. public function get_name()
  54. {
  55. return $this->name;
  56. }
  57. /**
  58. * @return string
  59. */
  60. public function get_description()
  61. {
  62. return $this->description;
  63. }
  64. /**
  65. * @return int
  66. */
  67. public function get_user_id()
  68. {
  69. return $this->user_id;
  70. }
  71. /**
  72. * @return float
  73. */
  74. public function get_certificate_min_score()
  75. {
  76. if (!empty($this->certificate_min_score)) {
  77. return $this->certificate_min_score;
  78. } else {
  79. return null;
  80. }
  81. }
  82. /**
  83. * @return string
  84. */
  85. public function get_course_code()
  86. {
  87. return $this->course_code;
  88. }
  89. /**
  90. * @return mixed
  91. */
  92. public function get_parent_id()
  93. {
  94. return $this->parent;
  95. }
  96. /**
  97. * @return mixed
  98. */
  99. public function get_weight()
  100. {
  101. return $this->weight;
  102. }
  103. /**
  104. * @return bool
  105. */
  106. public function is_locked()
  107. {
  108. return isset($this->locked) && $this->locked == 1 ? true : false;
  109. }
  110. /**
  111. * @return mixed
  112. */
  113. public function is_visible()
  114. {
  115. return $this->visible;
  116. }
  117. /**
  118. * Get $isRequirement
  119. * @return int
  120. */
  121. public function getIsRequirement()
  122. {
  123. return $this->isRequirement;
  124. }
  125. /**
  126. * @param int $id
  127. */
  128. public function set_id($id)
  129. {
  130. $this->id = $id;
  131. }
  132. /**
  133. * @param string $name
  134. */
  135. public function set_name($name)
  136. {
  137. $this->name = $name;
  138. }
  139. /**
  140. * @param string $description
  141. */
  142. public function set_description($description)
  143. {
  144. $this->description = $description;
  145. }
  146. /**
  147. * @param int $user_id
  148. */
  149. public function set_user_id($user_id)
  150. {
  151. $this->user_id = $user_id;
  152. }
  153. /**
  154. * @param string $course_code
  155. */
  156. public function set_course_code($course_code)
  157. {
  158. $this->course_code = $course_code;
  159. }
  160. /**
  161. * @param float $min_score
  162. */
  163. public function set_certificate_min_score($min_score = null)
  164. {
  165. $this->certificate_min_score = $min_score;
  166. }
  167. /**
  168. * @param int $parent
  169. */
  170. public function set_parent_id($parent)
  171. {
  172. $this->parent = intval($parent);
  173. }
  174. /**
  175. * Filters to int and sets the session ID
  176. * @param int The session ID from the Dokeos course session
  177. */
  178. public function set_session_id($session_id = 0)
  179. {
  180. $this->session_id = (int)$session_id;
  181. }
  182. /**
  183. * @param $weight
  184. */
  185. public function set_weight($weight)
  186. {
  187. $this->weight = $weight;
  188. }
  189. /**
  190. * @param $visible
  191. */
  192. public function set_visible($visible)
  193. {
  194. $this->visible = $visible;
  195. }
  196. /**
  197. * @param int $id
  198. */
  199. public function set_grade_model_id($id)
  200. {
  201. $this->grade_model_id = $id;
  202. }
  203. /**
  204. * @param $locked
  205. */
  206. public function set_locked($locked)
  207. {
  208. $this->locked = $locked;
  209. }
  210. /**
  211. * Set $isRequirement
  212. * @param int $isRequirement
  213. */
  214. public function setIsRequirement($isRequirement)
  215. {
  216. $this->isRequirement = $isRequirement;
  217. }
  218. /**
  219. * @return int
  220. */
  221. public function get_grade_model_id()
  222. {
  223. return $this->grade_model_id;
  224. }
  225. public function get_type()
  226. {
  227. return 'category';
  228. }
  229. /**
  230. * @param bool $from_db
  231. * @return array|resource
  232. */
  233. public function get_skills($from_db = true)
  234. {
  235. if ($from_db) {
  236. $cat_id = $this->get_id();
  237. $gradebook = new Gradebook();
  238. $skills = $gradebook->get_skills_by_gradebook($cat_id);
  239. } else {
  240. $skills = $this->skills;
  241. }
  242. return $skills;
  243. }
  244. /**
  245. * @return array
  246. */
  247. public function get_skills_for_select()
  248. {
  249. $skills = $this->get_skills();
  250. $skill_select = array();
  251. if (!empty($skills)) {
  252. foreach($skills as $skill) {
  253. $skill_select[$skill['id']] = $skill['name'];
  254. }
  255. }
  256. return $skill_select;
  257. }
  258. /**
  259. * Set the generate_certificates value
  260. * @param int $generateCertificates
  261. */
  262. public function setGenerateCertificates($generateCertificates)
  263. {
  264. $this->generateCertificates = $generateCertificates;
  265. }
  266. /**
  267. * Get the generate_certificates value
  268. * @return int
  269. */
  270. public function getGenerateCertificates()
  271. {
  272. return $this->generateCertificates;
  273. }
  274. /**
  275. * @param int $id
  276. * @param int $session_id
  277. *
  278. * @return array
  279. */
  280. public static function load_session_categories($id = null, $session_id = null)
  281. {
  282. if (isset($id) && (int)$id === 0) {
  283. $cats = array();
  284. $cats[] = Category::create_root_category();
  285. return $cats;
  286. }
  287. $courseCode = api_get_course_info_by_id(api_get_course_int_id());
  288. $courseCode = $courseCode['code'];
  289. $session_id = intval($session_id);
  290. if (!empty($session_id)) {
  291. $tbl_grade_categories = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  292. $sql = 'SELECT id, course_code
  293. FROM '.$tbl_grade_categories. '
  294. WHERE session_id = '.$session_id;
  295. $result_session = Database::query($sql);
  296. if (Database::num_rows($result_session) > 0) {
  297. $categoryList = array();
  298. while ($data_session = Database::fetch_array($result_session)) {
  299. $parent_id = $data_session['id'];
  300. if ($data_session['course_code'] == $courseCode) {
  301. $categories = Category::load($parent_id);
  302. $categoryList = array_merge($categoryList, $categories);
  303. //$allSubCategories = Category::load(null,null,null, $parent_id, null, $session_id, null);
  304. }
  305. }
  306. return $categoryList;
  307. }
  308. }
  309. }
  310. /**
  311. * Retrieve categories and return them as an array of Category objects
  312. * @param int $id category id
  313. * @param int $user_id (category owner)
  314. * @param string $course_code
  315. * @param int $parent_id parent category
  316. * @param bool $visible
  317. * @param int $session_id (in case we are in a session)
  318. * @param bool $order_by Whether to show all "session"
  319. * categories (true) or hide them (false) in case there is no session id
  320. */
  321. public static function load(
  322. $id = null,
  323. $user_id = null,
  324. $course_code = null,
  325. $parent_id = null,
  326. $visible = null,
  327. $session_id = null,
  328. $order_by = null
  329. ) {
  330. //if the category given is explicitly 0 (not null), then create
  331. // a root category object (in memory)
  332. if (isset($id) && (int)$id === 0) {
  333. $cats = array();
  334. $cats[] = Category::create_root_category();
  335. return $cats;
  336. }
  337. $tbl_grade_categories = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  338. $sql = 'SELECT * FROM '.$tbl_grade_categories;
  339. $paramcount = 0;
  340. if (isset($id)) {
  341. $sql.= ' WHERE id = '.intval($id);
  342. $paramcount ++;
  343. }
  344. if (isset($user_id)) {
  345. $user_id = intval($user_id);
  346. if ($paramcount != 0) {
  347. $sql .= ' AND';
  348. } else {
  349. $sql .= ' WHERE';
  350. }
  351. $sql .= ' user_id = '.intval($user_id);
  352. $paramcount++;
  353. }
  354. if (isset($course_code)) {
  355. if ($paramcount != 0) {
  356. $sql .= ' AND';
  357. } else {
  358. $sql .= ' WHERE';
  359. }
  360. if ($course_code == '0') {
  361. $sql .= ' course_code is null ';
  362. } else {
  363. $sql .= " course_code = '".Database::escape_string($course_code)."'";
  364. }
  365. /*if ($show_session_categories !== true) {
  366. // a query on the course should show all
  367. // the categories inside sessions for this course
  368. // otherwise a special parameter is given to ask explicitely
  369. $sql .= " AND (session_id IS NULL OR session_id = 0) ";
  370. } else {*/
  371. if (empty($session_id)) {
  372. $sql .= ' AND (session_id IS NULL OR session_id = 0) ';
  373. } else {
  374. $sql .= ' AND session_id = '.(int)$session_id.' ';
  375. }
  376. //}
  377. $paramcount ++;
  378. }
  379. if (isset($parent_id)) {
  380. if ($paramcount != 0) {
  381. $sql .= ' AND ';
  382. } else {
  383. $sql .= ' WHERE ';
  384. }
  385. $sql .= ' parent_id = '.intval($parent_id);
  386. $paramcount++;
  387. }
  388. if (isset($visible)) {
  389. if ($paramcount != 0) {
  390. $sql .= ' AND';
  391. } else {
  392. $sql .= ' WHERE';
  393. }
  394. $sql .= ' visible = '.intval($visible);
  395. }
  396. if (!empty($order_by)) {
  397. if (!empty($order_by) && $order_by != '') {
  398. $sql .= ' '.$order_by;
  399. }
  400. }
  401. $result = Database::query($sql);
  402. $categories = array();
  403. if (Database::num_rows($result) > 0) {
  404. $categories = Category::create_category_objects_from_sql_result(
  405. $result
  406. );
  407. }
  408. return $categories;
  409. }
  410. /**
  411. * @return Category
  412. */
  413. private static function create_root_category()
  414. {
  415. $cat = new Category();
  416. $cat->set_id(0);
  417. $cat->set_name(get_lang('RootCat'));
  418. $cat->set_description(null);
  419. $cat->set_user_id(0);
  420. $cat->set_course_code(null);
  421. $cat->set_parent_id(null);
  422. $cat->set_weight(0);
  423. $cat->set_visible(1);
  424. $cat->setGenerateCertificates(0);
  425. $cat->setIsRequirement(false);
  426. return $cat;
  427. }
  428. /**
  429. * @param $result
  430. *
  431. * @return array
  432. */
  433. private static function create_category_objects_from_sql_result($result)
  434. {
  435. $categories = array();
  436. while ($data = Database::fetch_array($result)) {
  437. $cat = new Category();
  438. $cat->set_id($data['id']);
  439. $cat->set_name($data['name']);
  440. $cat->set_description($data['description']);
  441. $cat->set_user_id($data['user_id']);
  442. $cat->set_course_code($data['course_code']);
  443. $cat->set_parent_id($data['parent_id']);
  444. $cat->set_weight($data['weight']);
  445. $cat->set_visible($data['visible']);
  446. $cat->set_session_id($data['session_id']);
  447. $cat->set_certificate_min_score($data['certif_min_score']);
  448. $cat->set_grade_model_id($data['grade_model_id']);
  449. $cat->set_locked($data['locked']);
  450. $cat->setGenerateCertificates($data['generate_certificates']);
  451. $cat->setIsRequirement($data['is_requirement']);
  452. $categories[] = $cat;
  453. }
  454. return $categories;
  455. }
  456. /**
  457. * Create a category object from a GradebookCategory entity
  458. * @param Chamilo\CoreBundle\Entity\GradebookCategory $gradebookCategory
  459. * The entity
  460. * @return \Category
  461. */
  462. public static function createCategoryObjectFromEntity(
  463. Chamilo\CoreBundle\Entity\GradebookCategory $gradebookCategory
  464. )
  465. {
  466. $category = new Category();
  467. $category->set_id($gradebookCategory->getId());
  468. $category->set_name($gradebookCategory->getName());
  469. $category->set_description($gradebookCategory->getDescription());
  470. $category->set_user_id($gradebookCategory->getUserId());
  471. $category->set_course_code($gradebookCategory->getCourseCode());
  472. $category->set_parent_id($gradebookCategory->getParentId());
  473. $category->set_weight($gradebookCategory->getWeight());
  474. $category->set_visible($gradebookCategory->getVisible());
  475. $category->set_session_id($gradebookCategory->getSessionId());
  476. $category->set_certificate_min_score(
  477. $gradebookCategory->getCertifMinScore()
  478. );
  479. $category->set_grade_model_id($gradebookCategory->getGradeModelId());
  480. $category->set_locked($gradebookCategory->getLocked());
  481. $category->setGenerateCertificates(
  482. $gradebookCategory->getGenerateCertificates()
  483. );
  484. $category->setIsRequirement($gradebookCategory->getIsRequirement());
  485. return $category;
  486. }
  487. /**
  488. * Insert this category into the database
  489. */
  490. public function add()
  491. {
  492. if (isset($this->name) && '-1' == $this->name) {
  493. return false;
  494. }
  495. if (isset($this->name) && isset($this->user_id)) {
  496. $em = Database::getManager();
  497. $category = new \Chamilo\CoreBundle\Entity\GradebookCategory();
  498. $category->setName($this->name);
  499. $category->setDescription($this->description);
  500. $category->setUserId($this->user_id);
  501. $category->setCourseCode($this->course_code);
  502. $category->setParentId($this->parent);
  503. $category->setWeight($this->weight);
  504. $category->setVisible($this->visible);
  505. $category->setCertifMinScore($this->certificate_min_score);
  506. $category->setSessionId($this->session_id);
  507. $category->setGenerateCertificates($this->generateCertificates);
  508. $category->setGradeModelId($this->grade_model_id);
  509. $category->setIsRequirement($this->isRequirement);
  510. $category->setLocked(false);
  511. $em->persist($category);
  512. $em->flush();
  513. $id = $category->getId();
  514. $this->set_id($id);
  515. if (!empty($id)) {
  516. $parent_id = $this->get_parent_id();
  517. $grade_model_id = $this->get_grade_model_id();
  518. if ($parent_id == 0) {
  519. //do something
  520. if (isset($grade_model_id) && !empty($grade_model_id) && $grade_model_id != '-1') {
  521. $obj = new GradeModel();
  522. $components = $obj->get_components($grade_model_id);
  523. $default_weight_setting = api_get_setting('gradebook_default_weight');
  524. $default_weight = 100;
  525. if (isset($default_weight_setting)) {
  526. $default_weight = $default_weight_setting;
  527. }
  528. foreach ($components as $component) {
  529. $gradebook = new Gradebook();
  530. $params = array();
  531. $params['name'] = $component['acronym'];
  532. $params['description'] = $component['title'];
  533. $params['user_id'] = api_get_user_id();
  534. $params['parent_id'] = $id;
  535. $params['weight'] = $component['percentage'] / 100 * $default_weight;
  536. $params['session_id'] = api_get_session_id();
  537. $params['course_code'] = $this->get_course_code();
  538. $gradebook->save($params);
  539. }
  540. }
  541. }
  542. }
  543. $gradebook= new Gradebook();
  544. $gradebook->update_skills_to_gradebook($this->id, $this->get_skills(false));
  545. return $id;
  546. }
  547. }
  548. /**
  549. * Update the properties of this category in the database
  550. * @todo fix me
  551. */
  552. public function save()
  553. {
  554. $em = Database::getManager();
  555. $gradebookCategory = $em
  556. ->getRepository('ChamiloCoreBundle:GradebookCategory')
  557. ->find($this->id);
  558. if (empty($gradebookCategory)) {
  559. return false;
  560. }
  561. $gradebookCategory->setName($this->name);
  562. $gradebookCategory->setDescription($this->description);
  563. $gradebookCategory->setUserId($this->user_id);
  564. $gradebookCategory->setCourseCode($this->course_code);
  565. $gradebookCategory->setParentId($this->parent);
  566. $gradebookCategory->setWeight($this->weight);
  567. $gradebookCategory->setVisible($this->visible);
  568. $gradebookCategory->setCertifMinScore($this->certificate_min_score);
  569. $gradebookCategory->setGenerateCertificates(
  570. $this->generateCertificates
  571. );
  572. $gradebookCategory->setGradeModelId($this->grade_model_id);
  573. $gradebookCategory->setIsRequirement($this->isRequirement);
  574. $em->persist($gradebookCategory);
  575. $em->flush();
  576. if (!empty($this->id)) {
  577. $parent_id = $this->get_parent_id();
  578. $grade_model_id = $this->get_grade_model_id();
  579. if ($parent_id == 0) {
  580. if (isset($grade_model_id) && !empty($grade_model_id) && $grade_model_id != '-1') {
  581. $obj = new GradeModel();
  582. $components = $obj->get_components($grade_model_id);
  583. $default_weight_setting = api_get_setting('gradebook_default_weight');
  584. $default_weight = 100;
  585. if (isset($default_weight_setting)) {
  586. $default_weight = $default_weight_setting;
  587. }
  588. $final_weight = $this->get_weight();
  589. if (!empty($final_weight)) {
  590. $default_weight = $this->get_weight();
  591. }
  592. foreach ($components as $component) {
  593. $gradebook = new Gradebook();
  594. $params = array();
  595. $params['name'] = $component['acronym'];
  596. $params['description'] = $component['title'];
  597. $params['user_id'] = api_get_user_id();
  598. $params['parent_id'] = $this->id;
  599. $params['weight'] = $component['percentage']/100*$default_weight;
  600. $params['session_id'] = api_get_session_id();
  601. $params['course_code'] = $this->get_course_code();
  602. $gradebook->save($params);
  603. }
  604. }
  605. }
  606. }
  607. $gradebook= new Gradebook();
  608. $gradebook->update_skills_to_gradebook(
  609. $this->id,
  610. $this->get_skills(false),
  611. false
  612. );
  613. }
  614. /**
  615. * Update link weights see #5168
  616. * @param type $new_weight
  617. */
  618. public function update_children_weight($new_weight)
  619. {
  620. $links = $this->get_links();
  621. $old_weight = $this->get_weight();
  622. if (!empty($links)) {
  623. foreach ($links as $link_item) {
  624. if (isset($link_item)) {
  625. $new_item_weight = $new_weight * $link_item->get_weight() / $old_weight;
  626. $link_item->set_weight($new_item_weight);
  627. $link_item->save();
  628. }
  629. }
  630. }
  631. }
  632. /**
  633. * Delete this evaluation from the database
  634. */
  635. public function delete()
  636. {
  637. $tbl_grade_categories = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  638. $sql = 'DELETE FROM '.$tbl_grade_categories.' WHERE id = '.intval($this->id);
  639. Database::query($sql);
  640. }
  641. /**
  642. * Not delete this category from the database,when visible=3 is category eliminated
  643. */
  644. public function update_category_delete($course_id)
  645. {
  646. $tbl_grade_categories = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  647. $sql = 'UPDATE '.$tbl_grade_categories.' SET visible=3
  648. WHERE course_code ="'.Database::escape_string($course_id).'"';
  649. Database::query($sql);
  650. }
  651. /**
  652. * Show message resource delete
  653. */
  654. public function show_message_resource_delete($course_id)
  655. {
  656. $tbl_grade_categories = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  657. $sql = 'SELECT count(*) AS num from '.$tbl_grade_categories.'
  658. WHERE
  659. course_code = "'.Database::escape_string($course_id).'" AND
  660. visible=3';
  661. $res = Database::query($sql);
  662. $option = Database::fetch_array($res, 'ASSOC');
  663. if ($option['num']>=1) {
  664. return '&nbsp;&nbsp;<span class="resource-deleted">(&nbsp;'.get_lang('ResourceDeleted').'&nbsp;)</span>';
  665. } else {
  666. return false;
  667. }
  668. }
  669. /**
  670. * Shows all information of an category
  671. */
  672. public function shows_all_information_an_category($selectcat = '')
  673. {
  674. if ($selectcat == '') {
  675. return null;
  676. } else {
  677. $tbl_category = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  678. $sql = 'SELECT name,description,user_id,course_code,parent_id,weight,visible,certif_min_score,session_id, generate_certificates, is_requirement
  679. FROM '.$tbl_category.' c
  680. WHERE c.id='.intval($selectcat);
  681. $result = Database::query($sql);
  682. $row = Database::fetch_array($result, 'ASSOC');
  683. return $row;
  684. }
  685. }
  686. /**
  687. * Check if a category name (with the same parent category) already exists
  688. * @param $name name to check (if not given, the name property of this object will be checked)
  689. * @param $parent parent category
  690. */
  691. public function does_name_exist($name, $parent)
  692. {
  693. if (!isset ($name)) {
  694. $name = $this->name;
  695. $parent = $this->parent;
  696. }
  697. $tbl_grade_categories = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  698. $sql = 'SELECT count(id) AS number'
  699. .' FROM '.$tbl_grade_categories
  700. ." WHERE name = '".Database::escape_string($name)."'";
  701. if (api_is_allowed_to_edit()) {
  702. $parent = Category::load($parent);
  703. $code = $parent[0]->get_course_code();
  704. $courseInfo = api_get_course_info($code);
  705. $courseId = $courseInfo['real_id'];
  706. if (isset($code) && $code != '0') {
  707. $main_course_user_table = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
  708. $sql .= ' AND user_id IN (
  709. SELECT user_id FROM '.$main_course_user_table.'
  710. WHERE c_id = '.$courseId.' AND status = '.COURSEMANAGER.'
  711. )';
  712. } else {
  713. $sql .= ' AND user_id = '.api_get_user_id();
  714. }
  715. } else {
  716. $sql .= ' AND user_id = '.api_get_user_id();
  717. }
  718. if (!isset ($parent)) {
  719. $sql.= ' AND parent_id is null';
  720. } else {
  721. $sql.= ' AND parent_id = '.intval($parent);
  722. }
  723. $result = Database::query($sql);
  724. $number = Database::fetch_row($result);
  725. return ($number[0] != 0);
  726. }
  727. /**
  728. * Checks if the certificate is available for the given user in this category
  729. * @param integer $user_id User ID
  730. * @return boolean True if conditions match, false if fails
  731. */
  732. public function is_certificate_available($user_id)
  733. {
  734. $score = $this->calc_score(
  735. $user_id,
  736. null,
  737. $this->course_code,
  738. $this->session_id
  739. );
  740. if (isset($score) && isset($score[0])) {
  741. // Get a percentage score to compare to minimum certificate score
  742. //$certification_score = $score[0] / $score[1] * 100;
  743. // Get real score not a percentage.
  744. $certification_score = $score[0];
  745. if ($certification_score >= $this->certificate_min_score) {
  746. return true;
  747. }
  748. }
  749. return false;
  750. }
  751. /**
  752. * Is this category a course ?
  753. * A category is a course if it has a course code and no parent category.
  754. */
  755. public function is_course()
  756. {
  757. return (isset($this->course_code) && !empty($this->course_code)
  758. && (!isset($this->parent) || $this->parent == 0));
  759. }
  760. /**
  761. * Calculate the score of this category
  762. * @param $stud_id student id (default: all students - then the average is returned)
  763. * @return array (score sum, weight sum)
  764. * or null if no scores available
  765. */
  766. public function calc_score(
  767. $stud_id = null,
  768. $type = null,
  769. $course_code = '',
  770. $session_id = null
  771. ) {
  772. // Get appropriate subcategories, evaluations and links
  773. if (!empty($course_code)) {
  774. $cats = $this->get_subcategories($stud_id, $course_code, $session_id);
  775. $evals = $this->get_evaluations($stud_id, false, $course_code);
  776. $links = $this->get_links($stud_id, false, $course_code);
  777. } else {
  778. $cats = $this->get_subcategories($stud_id);
  779. $evals = $this->get_evaluations($stud_id);
  780. $links = $this->get_links($stud_id);
  781. }
  782. // Calculate score
  783. $rescount = 0;
  784. $ressum = 0;
  785. $weightsum = 0;
  786. $bestResult = 0;
  787. $students = [];
  788. if (!empty($cats)) {
  789. /** @var Category $cat */
  790. foreach ($cats as $cat) {
  791. $score = $cat->calc_score(
  792. $stud_id,
  793. $type,
  794. $course_code,
  795. $session_id
  796. );
  797. if ($cat->get_weight() != 0) {
  798. $catweight = $cat->get_weight();
  799. $rescount++;
  800. $weightsum += $catweight;
  801. }
  802. if (isset($score)) {
  803. $ressum += $score[0]/$score[1] * $catweight;
  804. $bestResult += $ressum;
  805. }
  806. }
  807. }
  808. if (!empty($evals)) {
  809. /** @var Evaluation $eval */
  810. foreach ($evals as $eval) {
  811. $evalres = $eval->calc_score($stud_id, $type);
  812. $students[$stud_id] = $evalres[0];
  813. if (isset($evalres) && $eval->get_weight() != 0) {
  814. $evalweight = $eval->get_weight();
  815. $weightsum += $evalweight;
  816. $rescount++;
  817. $ressum += $evalres[0] / $evalres[1] * $evalweight;
  818. } else {
  819. if ($eval->get_weight() != 0) {
  820. $evalweight = $eval->get_weight();
  821. $weightsum += $evalweight;
  822. }
  823. }
  824. }
  825. }
  826. if (!empty($links)) {
  827. $bestResult = 0;
  828. $weight = 0;
  829. /** @var EvalLink|ExerciseLink $link */
  830. foreach ($links as $link) {
  831. $linkres = $link->calc_score($stud_id, $type);
  832. if (!empty($linkres) && $link->get_weight() != 0) {
  833. $students[$stud_id] = $linkres[0];
  834. $linkweight = $link->get_weight();
  835. $link_res_denom = $linkres[1] == 0 ? 1 : $linkres[1];
  836. $rescount++;
  837. $weightsum += $linkweight;
  838. $ressum += $linkres[0] / $link_res_denom * $linkweight;
  839. } else {
  840. // Adding if result does not exists
  841. if ($link->get_weight() != 0) {
  842. $linkweight = $link->get_weight();
  843. $weightsum += $linkweight;
  844. }
  845. }
  846. }
  847. }
  848. if ($rescount == 0) {
  849. return null;
  850. } else {
  851. switch ($type) {
  852. case 'best':
  853. return array($ressum, $weightsum);
  854. break;
  855. case 'average':
  856. return array($ressum, $weightsum);
  857. break;
  858. case 'ranking':
  859. return null;
  860. return AbstractLink::getCurrentUserRanking($stud_id, $students);
  861. break;
  862. default:
  863. return array($ressum, $weightsum);
  864. break;
  865. }
  866. }
  867. }
  868. /**
  869. * Delete this category and every subcategory, evaluation and result inside
  870. */
  871. public function delete_all()
  872. {
  873. $cats = Category::load(null, null, $this->course_code, $this->id, null);
  874. $evals = Evaluation::load(null, null, $this->course_code, $this->id, null);
  875. $links = LinkFactory::load(null, null, null, null, $this->course_code, $this->id, null);
  876. if (!empty($cats)) {
  877. foreach ($cats as $cat) {
  878. $cat->delete_all();
  879. $cat->delete();
  880. }
  881. }
  882. if (!empty($evals)) {
  883. foreach ($evals as $eval) {
  884. $eval->delete_with_results();
  885. }
  886. }
  887. if (!empty($links)) {
  888. foreach ($links as $link) {
  889. $link->delete();
  890. }
  891. }
  892. $this->delete();
  893. }
  894. /**
  895. * Return array of Category objects where a student is subscribed to.
  896. * @param int student id
  897. * @param string Course code
  898. * @param int Session id
  899. */
  900. public function get_root_categories_for_student($stud_id, $course_code = null, $session_id = null)
  901. {
  902. $main_course_user_table = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
  903. $courseTable = Database :: get_main_table(TABLE_MAIN_COURSE);
  904. $tbl_grade_categories = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  905. $sql = "SELECT * FROM $tbl_grade_categories WHERE parent_id = 0";
  906. if (!api_is_allowed_to_edit()) {
  907. $sql .= ' AND visible = 1';
  908. //proceed with checks on optional parameters course & session
  909. if (!empty($course_code)) {
  910. // TODO: considering it highly improbable that a user would get here
  911. // if he doesn't have the rights to view this course and this
  912. // session, we don't check his registration to these, but this
  913. // could be an improvement
  914. if (!empty($session_id)) {
  915. $sql .= " AND course_code = '".Database::escape_string($course_code)."' AND session_id = ".(int)$session_id;
  916. } else {
  917. $sql .= " AND course_code = '".Database::escape_string($course_code)."' AND session_id is null OR session_id=0";
  918. }
  919. } else {
  920. //no optional parameter, proceed as usual
  921. $sql .= ' AND course_code in
  922. (
  923. SELECT c.code
  924. FROM '.$main_course_user_table.' cu INNER JOIN '.$courseTable.' c
  925. ON (cu.c_id = c.id)
  926. WHERE cu.user_id = '.intval($stud_id).'
  927. AND cu.status = '.STUDENT.'
  928. )';
  929. }
  930. } elseif (api_is_allowed_to_edit() && !api_is_platform_admin()) {
  931. //proceed with checks on optional parameters course & session
  932. if (!empty($course_code)) {
  933. // TODO: considering it highly improbable that a user would get here
  934. // if he doesn't have the rights to view this course and this
  935. // session, we don't check his registration to these, but this
  936. // could be an improvement
  937. $sql .= " AND course_code = '".Database::escape_string($course_code)."'";
  938. if (!empty($session_id)) {
  939. $sql .= " AND session_id = ".(int)$session_id;
  940. } else {
  941. $sql .="AND session_id IS NULL OR session_id=0";
  942. }
  943. } else {
  944. $sql .= ' AND course_code IN
  945. (
  946. SELECT c.code
  947. FROM '.$main_course_user_table.' cu INNER JOIN '.$courseTable.' c
  948. ON (cu.c_id = c.id)
  949. WHERE
  950. cu.user_id = '.api_get_user_id().' AND
  951. cu.status = '.COURSEMANAGER.'
  952. )';
  953. }
  954. }elseif (api_is_platform_admin()) {
  955. if (isset($session_id) && $session_id!=0) {
  956. $sql.=' AND session_id='.intval($session_id);
  957. } else {
  958. $sql.=' AND coalesce(session_id,0)=0';
  959. }
  960. }
  961. $result = Database::query($sql);
  962. $cats = Category::create_category_objects_from_sql_result($result);
  963. // course independent categories
  964. if (empty($course_code)) {
  965. $cats = Category::get_independent_categories_with_result_for_student (0, $stud_id, $cats);
  966. }
  967. return $cats;
  968. }
  969. /**
  970. * Return array of Category objects where a teacher is admin for.
  971. * @param int user id (to return everything, use 'null' here)
  972. * @param string course code (optional)
  973. * @param int session id (optional)
  974. */
  975. public function get_root_categories_for_teacher($user_id, $course_code = null, $session_id = null)
  976. {
  977. if ($user_id == null) {
  978. return Category::load(null,null,$course_code,0,null,$session_id);
  979. }
  980. $courseTable = Database :: get_main_table(TABLE_MAIN_COURSE);
  981. $main_course_user_table = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
  982. $tbl_grade_categories = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  983. $sql = 'SELECT * FROM '.$tbl_grade_categories.'
  984. WHERE parent_id = 0';
  985. if (!empty($course_code)) {
  986. $sql .= " AND course_code = '".Database::escape_string($course_code)."' ";
  987. if (!empty($session_id)) {
  988. $sql .= " AND session_id = ".(int)$session_id;
  989. }
  990. } else {
  991. $sql .= ' AND course_code in
  992. (
  993. SELECT c.code
  994. FROM '.$main_course_user_table.' cu
  995. INNER JOIN '.$courseTable.' c
  996. ON (cu.c_id = c.id)
  997. WHERE user_id = '.intval($user_id).'
  998. )';
  999. }
  1000. $result = Database::query($sql);
  1001. $cats = Category::create_category_objects_from_sql_result($result);
  1002. // course independent categories
  1003. if (isset($course_code)) {
  1004. $indcats = Category::load(null,$user_id,$course_code,0,null,$session_id);
  1005. $cats = array_merge($cats, $indcats);
  1006. }
  1007. return $cats;
  1008. }
  1009. /**
  1010. * Can this category be moved to somewhere else ?
  1011. * The root and courses cannot be moved.
  1012. */
  1013. public function is_movable()
  1014. {
  1015. return (!(!isset ($this->id) || $this->id == 0 || $this->is_course()));
  1016. }
  1017. /**
  1018. * Generate an array of possible categories where this category can be moved to.
  1019. * Notice: its own parent will be included in the list: it's up to the frontend
  1020. * to disable this element.
  1021. * @return array 2-dimensional array - every element contains 3 subelements (id, name, level)
  1022. */
  1023. public function get_target_categories()
  1024. {
  1025. // the root or a course -> not movable
  1026. if (!$this->is_movable()) {
  1027. return null;
  1028. } else {
  1029. // otherwise:
  1030. // - course independent category
  1031. // -> movable to root or other independent categories
  1032. // - category inside a course
  1033. // -> movable to root, independent categories or categories inside the course
  1034. $user = (api_is_platform_admin() ? null : api_get_user_id());
  1035. $targets = array();
  1036. $level = 0;
  1037. $root = array(0, get_lang('RootCat'), $level);
  1038. $targets[] = $root;
  1039. if (isset($this->course_code) && !empty($this->course_code)) {
  1040. $crscats = Category::load(null,null,$this->course_code,0);
  1041. foreach ($crscats as $cat) {
  1042. if ($this->can_be_moved_to_cat($cat)) {
  1043. $targets[] = array ($cat->get_id(), $cat->get_name(), $level+1);
  1044. $targets = $this->add_target_subcategories($targets, $level+1, $cat->get_id());
  1045. }
  1046. }
  1047. }
  1048. $indcats = Category::load(null,$user,0,0);
  1049. foreach ($indcats as $cat) {
  1050. if ($this->can_be_moved_to_cat($cat)) {
  1051. $targets[] = array ($cat->get_id(), $cat->get_name(), $level+1);
  1052. $targets = $this->add_target_subcategories($targets, $level+1, $cat->get_id());
  1053. }
  1054. }
  1055. return $targets;
  1056. }
  1057. }
  1058. /**
  1059. * Internal function used by get_target_categories()
  1060. */
  1061. private function add_target_subcategories($targets, $level, $catid)
  1062. {
  1063. $subcats = Category::load(null,null,null,$catid);
  1064. foreach ($subcats as $cat) {
  1065. if ($this->can_be_moved_to_cat($cat)) {
  1066. $targets[] = array ($cat->get_id(), $cat->get_name(), $level+1);
  1067. $targets = $this->add_target_subcategories($targets, $level+1, $cat->get_id());
  1068. }
  1069. }
  1070. return $targets;
  1071. }
  1072. /**
  1073. * Internal function used by get_target_categories() and add_target_subcategories()
  1074. * Can this category be moved to the given category ?
  1075. * Impossible when origin and target are the same... children won't be processed
  1076. * either. (a category can't be moved to one of its own children)
  1077. */
  1078. private function can_be_moved_to_cat ($cat)
  1079. {
  1080. return $cat->get_id() != $this->get_id();
  1081. }
  1082. /**
  1083. * Move this category to the given category.
  1084. * If this category moves from inside a course to outside,
  1085. * its course code must be changed, as well as the course code
  1086. * of all underlying categories and evaluations. All links will
  1087. * be deleted as well !
  1088. */
  1089. public function move_to_cat($cat)
  1090. {
  1091. $this->set_parent_id($cat->get_id());
  1092. if ($this->get_course_code() != $cat->get_course_code()) {
  1093. $this->set_course_code($cat->get_course_code());
  1094. $this->apply_course_code_to_children();
  1095. }
  1096. $this->save();
  1097. }
  1098. /**
  1099. * Internal function used by move_to_cat()
  1100. */
  1101. private function apply_course_code_to_children()
  1102. {
  1103. $cats = Category::load(null, null, null, $this->id, null);
  1104. $evals = Evaluation::load(null, null, null, $this->id, null);
  1105. $links = LinkFactory::load(null,null,null,null,null,$this->id,null);
  1106. foreach ($cats as $cat) {
  1107. $cat->set_course_code($this->get_course_code());
  1108. $cat->save();
  1109. $cat->apply_course_code_to_children();
  1110. }
  1111. foreach ($evals as $eval) {
  1112. $eval->set_course_code($this->get_course_code());
  1113. $eval->save();
  1114. }
  1115. foreach ($links as $link) {
  1116. $link->delete();
  1117. }
  1118. }
  1119. /**
  1120. * Generate an array of all categories the user can navigate to
  1121. */
  1122. public function get_tree()
  1123. {
  1124. $targets = array();
  1125. $level = 0;
  1126. $root = array(0, get_lang('RootCat'), $level);
  1127. $targets[] = $root;
  1128. // course or platform admin
  1129. if (api_is_allowed_to_edit()) {
  1130. $user = (api_is_platform_admin() ? null : api_get_user_id());
  1131. $cats = Category::get_root_categories_for_teacher($user);
  1132. foreach ($cats as $cat) {
  1133. $targets[] = array ($cat->get_id(), $cat->get_name(), $level+1);
  1134. $targets = Category::add_subtree($targets, $level+1, $cat->get_id(),null);
  1135. }
  1136. } else {
  1137. // student
  1138. $cats = Category::get_root_categories_for_student(api_get_user_id());
  1139. foreach ($cats as $cat) {
  1140. $targets[] = array ($cat->get_id(), $cat->get_name(), $level+1);
  1141. $targets = Category::add_subtree($targets, $level+1, $cat->get_id(), 1);
  1142. }
  1143. }
  1144. return $targets;
  1145. }
  1146. /**
  1147. * Internal function used by get_tree()
  1148. */
  1149. private function add_subtree ($targets, $level, $catid, $visible)
  1150. {
  1151. $subcats = Category::load(null,null,null,$catid,$visible);
  1152. if (!empty($subcats)) {
  1153. foreach ($subcats as $cat) {
  1154. $targets[] = array ($cat->get_id(), $cat->get_name(), $level+1);
  1155. $targets = Category::add_subtree($targets, $level+1, $cat->get_id(),$visible);
  1156. }
  1157. }
  1158. return $targets;
  1159. }
  1160. /**
  1161. * Generate an array of courses that a teacher hasn't created a category for.
  1162. * @return array 2-dimensional array - every element contains 2 subelements (code, title)
  1163. */
  1164. public function get_not_created_course_categories ($user_id)
  1165. {
  1166. $tbl_main_courses = Database :: get_main_table(TABLE_MAIN_COURSE);
  1167. $tbl_main_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
  1168. $tbl_grade_categories = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  1169. $sql = 'SELECT DISTINCT(code), title
  1170. FROM '.$tbl_main_courses.' cc, '.$tbl_main_course_user.' cu'
  1171. .' WHERE cc.id = cu.c_id '
  1172. .' AND cu.status = '.COURSEMANAGER;
  1173. if (!api_is_platform_admin()) {
  1174. $sql .= ' AND cu.user_id = '.$user_id;
  1175. }
  1176. $sql .= ' AND cc.code NOT IN
  1177. (
  1178. SELECT course_code FROM '.$tbl_grade_categories.'
  1179. WHERE
  1180. parent_id = 0 AND
  1181. course_code IS NOT NULL
  1182. )';
  1183. $result = Database::query($sql);
  1184. $cats=array();
  1185. while ($data=Database::fetch_array($result)) {
  1186. $cats[] = array ($data['code'], $data['title']);
  1187. }
  1188. return $cats;
  1189. }
  1190. /**
  1191. * Generate an array of all courses that a teacher is admin of.
  1192. * @return array 2-dimensional array - every element contains 2 subelements (code, title)
  1193. */
  1194. public function get_all_courses ($user_id)
  1195. {
  1196. $tbl_main_courses = Database :: get_main_table(TABLE_MAIN_COURSE);
  1197. $tbl_main_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
  1198. $sql = 'SELECT DISTINCT(code), title
  1199. FROM '.$tbl_main_courses.' cc, '.$tbl_main_course_user.' cu
  1200. WHERE cc.id = cu.c_id AND cu.status = '.COURSEMANAGER;
  1201. if (!api_is_platform_admin()) {
  1202. $sql .= ' AND cu.user_id = '.intval($user_id);
  1203. }
  1204. $result = Database::query($sql);
  1205. $cats = array();
  1206. while ($data = Database::fetch_array($result)) {
  1207. $cats[] = array ($data['code'], $data['title']);
  1208. }
  1209. return $cats;
  1210. }
  1211. /**
  1212. * Apply the same visibility to every subcategory, evaluation and link
  1213. */
  1214. public function apply_visibility_to_children()
  1215. {
  1216. $cats = Category::load(null, null, null, $this->id, null);
  1217. $evals = Evaluation::load(null, null, null, $this->id, null);
  1218. $links = LinkFactory::load(null,null,null,null,null,$this->id,null);
  1219. if (!empty($cats)) {
  1220. foreach ($cats as $cat) {
  1221. $cat->set_visible($this->is_visible());
  1222. $cat->save();
  1223. $cat->apply_visibility_to_children();
  1224. }
  1225. }
  1226. if (!empty($evals)) {
  1227. foreach ($evals as $eval) {
  1228. $eval->set_visible($this->is_visible());
  1229. $eval->save();
  1230. }
  1231. }
  1232. if (!empty($links)) {
  1233. foreach ($links as $link) {
  1234. $link->set_visible($this->is_visible());
  1235. $link->save();
  1236. }
  1237. }
  1238. }
  1239. /**
  1240. * Check if a category contains evaluations with a result for a given student
  1241. */
  1242. public function has_evaluations_with_results_for_student($stud_id)
  1243. {
  1244. $evals = Evaluation::get_evaluations_with_result_for_student($this->id, $stud_id);
  1245. if (count($evals) != 0) {
  1246. return true;
  1247. } else {
  1248. $cats = Category::load(
  1249. null,
  1250. null,
  1251. null,
  1252. $this->id,
  1253. api_is_allowed_to_edit() ? null : 1
  1254. );
  1255. foreach ($cats as $cat) {
  1256. if ($cat->has_evaluations_with_results_for_student($stud_id)) {
  1257. return true;
  1258. }
  1259. }
  1260. return false;
  1261. }
  1262. }
  1263. /**
  1264. * Retrieve all categories inside a course independent category
  1265. * that should be visible to a student.
  1266. * @param $cat_id parent category
  1267. * @param $stud_id student id
  1268. * @param $cats optional: if defined, the categories will be added to this array
  1269. */
  1270. public function get_independent_categories_with_result_for_student($cat_id, $stud_id, $cats = array())
  1271. {
  1272. $creator = api_is_allowed_to_edit() && !api_is_platform_admin() ? api_get_user_id() : null;
  1273. $crsindcats = Category::load(
  1274. null,
  1275. $creator,
  1276. '0',
  1277. $cat_id,
  1278. api_is_allowed_to_edit() ? null : 1
  1279. );
  1280. if (!empty($crsindcats)) {
  1281. foreach ($crsindcats as $crsindcat) {
  1282. if ($crsindcat->has_evaluations_with_results_for_student($stud_id)) {
  1283. $cats[] = $crsindcat;
  1284. }
  1285. }
  1286. }
  1287. return $cats;
  1288. }
  1289. /**
  1290. * Return the session id (in any case, even if it's null or 0)
  1291. * @return int Session id (can be null)
  1292. */
  1293. public function get_session_id()
  1294. {
  1295. return $this->session_id;
  1296. }
  1297. /**
  1298. * Get appropriate subcategories visible for the user (and optionally the course and session)
  1299. * @param int $stud_id student id (default: all students)
  1300. * @param string $course_code Course code (optional)
  1301. * @param int $session_id Session ID (optional)
  1302. * @param bool $order
  1303. * @return array Array of subcategories
  1304. */
  1305. public function get_subcategories($stud_id = null, $course_code = null, $session_id = null, $order = null)
  1306. {
  1307. if (!empty($session_id)) {
  1308. /*$tbl_grade_categories = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  1309. $sql = 'SELECT id FROM '.$tbl_grade_categories. ' WHERE session_id = '.$session_id;
  1310. $result_session = Database::query($sql);
  1311. if (Database::num_rows($result_session) > 0) {
  1312. $data_session = Database::fetch_array($result_session);
  1313. $parent_id = $data_session['id'];
  1314. return Category::load(null, null, null, $parent_id, null, null, $order);
  1315. }*/
  1316. }
  1317. // 1 student
  1318. if (isset($stud_id)) {
  1319. // Special case: this is the root
  1320. if ($this->id == 0) {
  1321. return Category::get_root_categories_for_student($stud_id, $course_code, $session_id);
  1322. } else {
  1323. return Category::load(
  1324. null,
  1325. null,
  1326. $course_code,
  1327. $this->id,
  1328. api_is_allowed_to_edit() ? null : 1,
  1329. $session_id,
  1330. $order
  1331. );
  1332. }
  1333. } else {
  1334. // All students
  1335. // Course admin
  1336. if (api_is_allowed_to_edit() && !api_is_platform_admin()) {
  1337. // root
  1338. if ($this->id == 0) {
  1339. return $this->get_root_categories_for_teacher(api_get_user_id(), $course_code, $session_id, false);
  1340. // inside a course
  1341. } elseif (!empty($this->course_code)) {
  1342. return Category::load(null, null, $this->course_code, $this->id, null, $session_id, $order);
  1343. } elseif (!empty($course_code)) {
  1344. return Category::load(null, null, $course_code, $this->id, null, $session_id, $order);
  1345. // course independent
  1346. } else {
  1347. return Category::load(null, api_get_user_id(), 0, $this->id, null);
  1348. }
  1349. } elseif (api_is_platform_admin()) {
  1350. // platform admin
  1351. // we explicitly avoid listing subcats from another session
  1352. return Category::load(null, null, $course_code, $this->id, null, $session_id, $order);
  1353. }
  1354. }
  1355. return array();
  1356. }
  1357. /**
  1358. * Get appropriate evaluations visible for the user
  1359. * @param int $stud_id student id (default: all students)
  1360. * @param boolean $recursive process subcategories (default: no recursion)
  1361. * @param string $course_code
  1362. * @param int $sessionId
  1363. *
  1364. * @return array
  1365. */
  1366. public function get_evaluations(
  1367. $stud_id = null,
  1368. $recursive = false,
  1369. $course_code = '',
  1370. $sessionId = 0
  1371. ) {
  1372. $evals = array();
  1373. if (empty($course_code)) {
  1374. $course_code = api_get_course_id();
  1375. }
  1376. if (empty($sessionId)) {
  1377. $sessionId = api_get_session_id();
  1378. }
  1379. // 1 student
  1380. if (isset($stud_id) && !empty($stud_id)) {
  1381. // Special case: this is the root
  1382. if ($this->id == 0) {
  1383. $evals = Evaluation::get_evaluations_with_result_for_student(0, $stud_id);
  1384. } else {
  1385. $evals = Evaluation::load(
  1386. null,
  1387. null,
  1388. $course_code,
  1389. $this->id,
  1390. api_is_allowed_to_edit() ? null : 1
  1391. );
  1392. }
  1393. } else {
  1394. // All students
  1395. // course admin
  1396. if ((api_is_allowed_to_edit() || api_is_drh() || api_is_session_admin()) &&
  1397. !api_is_platform_admin()
  1398. ) {
  1399. // root
  1400. if ($this->id == 0) {
  1401. $evals = Evaluation::load(null, api_get_user_id(), null, $this->id, null);
  1402. } elseif (isset($this->course_code) && !empty($this->course_code)) {
  1403. // inside a course
  1404. $evals = Evaluation::load(null, null, $course_code, $this->id, null);
  1405. } else {
  1406. // course independent
  1407. $evals = Evaluation::load(null, api_get_user_id(), null, $this->id, null);
  1408. }
  1409. } else {
  1410. $evals = Evaluation::load(null, null, $course_code, $this->id, null);
  1411. }
  1412. }
  1413. if ($recursive) {
  1414. $subcats = $this->get_subcategories($stud_id, $course_code, $sessionId);
  1415. if (!empty($subcats)) {
  1416. foreach ($subcats as $subcat) {
  1417. $subevals = $subcat->get_evaluations($stud_id, true, $course_code);
  1418. $evals = array_merge($evals, $subevals);
  1419. }
  1420. }
  1421. }
  1422. return $evals;
  1423. }
  1424. /**
  1425. * Get appropriate links visible for the user
  1426. * @param int $stud_id student id (default: all students)
  1427. * @param boolean $recursive process subcategories (default: no recursion)
  1428. * @param string $course_code
  1429. * @param int $sessionId
  1430. *
  1431. * @return array
  1432. */
  1433. public function get_links(
  1434. $stud_id = null,
  1435. $recursive = false,
  1436. $course_code = '',
  1437. $sessionId = 0
  1438. ) {
  1439. $links = array();
  1440. if (empty($course_code)) {
  1441. $course_code = api_get_course_id();
  1442. }
  1443. if (empty($sessionId)) {
  1444. $sessionId = api_get_session_id();
  1445. }
  1446. // no links in root or course independent categories
  1447. if ($this->id == 0) {
  1448. } elseif (isset($stud_id)) {
  1449. // 1 student $stud_id
  1450. $links = LinkFactory::load(
  1451. null,
  1452. null,
  1453. null,
  1454. null,
  1455. empty($this->course_code) ? null : $course_code,
  1456. $this->id,
  1457. api_is_allowed_to_edit() ? null : 1
  1458. );
  1459. //} elseif (api_is_allowed_to_edit() || api_is_drh() || api_is_session_admin()) {
  1460. } else {
  1461. // All students -> only for course/platform admin
  1462. $links = LinkFactory::load(
  1463. null,
  1464. null,
  1465. null,
  1466. null,
  1467. empty($this->course_code) ? null : $this->course_code,
  1468. $this->id,
  1469. null
  1470. );
  1471. }
  1472. if ($recursive) {
  1473. $subcats = $this->get_subcategories(
  1474. $stud_id,
  1475. $course_code,
  1476. $sessionId
  1477. );
  1478. if (!empty($subcats)) {
  1479. /** @var Category $subcat */
  1480. foreach ($subcats as $subcat) {
  1481. $sublinks = $subcat->get_links(
  1482. $stud_id,
  1483. false,
  1484. $course_code,
  1485. $sessionId
  1486. );
  1487. $links = array_merge($links, $sublinks);
  1488. }
  1489. }
  1490. }
  1491. return $links;
  1492. }
  1493. /**
  1494. * Get all the categories from with the same given direct parent
  1495. * @param int $catId Category parent ID
  1496. * @return array Array of Category objects
  1497. */
  1498. public function getCategories($catId)
  1499. {
  1500. $tblGradeCategories = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  1501. $sql = 'SELECT * FROM '.$tblGradeCategories.'
  1502. WHERE parent_id = '.intval($catId);
  1503. $result = Database::query($sql);
  1504. $allcats = Category::create_category_objects_from_sql_result($result);
  1505. return $allcats;
  1506. }
  1507. /**
  1508. * Gets the type for the current object
  1509. * @return string 'C' to represent "Category" object type
  1510. */
  1511. public function get_item_type()
  1512. {
  1513. return 'C';
  1514. }
  1515. /**
  1516. * @param array $skills
  1517. */
  1518. public function set_skills($skills)
  1519. {
  1520. $this->skills = $skills;
  1521. }
  1522. /**
  1523. * @return null
  1524. */
  1525. public function get_date()
  1526. {
  1527. return null;
  1528. }
  1529. /**
  1530. * @return string
  1531. */
  1532. public function get_icon_name()
  1533. {
  1534. return 'cat';
  1535. }
  1536. /**
  1537. * Find category by name
  1538. * @param string $name_mask search string
  1539. * @return array category objects matching the search criterium
  1540. */
  1541. public function find_category($name_mask,$allcat)
  1542. {
  1543. $foundcats = array();
  1544. foreach ($allcat as $search_cat) {
  1545. if (!(strpos(strtolower($search_cat->get_name()), strtolower($name_mask)) === false)) {
  1546. $foundcats[] = $search_cat;
  1547. }
  1548. }
  1549. return $foundcats;
  1550. }
  1551. /**
  1552. * This function, locks a category , only one who can unlock it is
  1553. * the platform administrator.
  1554. * @param int locked 1 or unlocked 0
  1555. * @return bool
  1556. * */
  1557. public function lock($locked)
  1558. {
  1559. $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  1560. $sql = "UPDATE $table SET locked = '".intval($locked)."'
  1561. WHERE id='".intval($this->id)."'";
  1562. Database::query($sql);
  1563. }
  1564. /**
  1565. * @param $locked
  1566. */
  1567. public function lock_all_items($locked)
  1568. {
  1569. if (api_get_setting('gradebook_locking_enabled') == 'true') {
  1570. $this->lock($locked);
  1571. $evals_to_lock = $this->get_evaluations();
  1572. if (!empty($evals_to_lock)) {
  1573. foreach ($evals_to_lock as $item) {
  1574. $item->lock($locked);
  1575. }
  1576. }
  1577. $link_to_lock= $this->get_links();
  1578. if (!empty($link_to_lock)) {
  1579. foreach ($link_to_lock as $item ) {
  1580. $item->lock($locked);
  1581. }
  1582. }
  1583. $event_type = LOG_GRADEBOOK_UNLOCKED;
  1584. if ($locked == 1) {
  1585. $event_type = LOG_GRADEBOOK_LOCKED;
  1586. }
  1587. Event::addEvent($event_type, LOG_GRADEBOOK_ID, $this->id);
  1588. }
  1589. }
  1590. /**
  1591. * @param int $category_id
  1592. * @param int $user_id
  1593. * @return bool|string
  1594. */
  1595. public static function register_user_certificate($category_id, $user_id)
  1596. {
  1597. $sessionId = api_get_session_id();
  1598. // Generating the total score for a course
  1599. $cats_course = Category::load(
  1600. $category_id,
  1601. null,
  1602. null,
  1603. null,
  1604. null,
  1605. $sessionId,
  1606. false
  1607. );
  1608. /** @var Category $category */
  1609. $category = $cats_course[0];
  1610. if (!$category->getGenerateCertificates()) {
  1611. $skill = new Skill();
  1612. $skill->add_skill_to_user(
  1613. $user_id,
  1614. $category_id,
  1615. api_get_course_int_id(),
  1616. $sessionId
  1617. );
  1618. return false;
  1619. }
  1620. //@todo move these in a function
  1621. $sum_categories_weight_array = array();
  1622. if (isset($cats_course) && !empty($cats_course)) {
  1623. $categories = Category::load(null, null, null, $category_id);
  1624. if (!empty($categories)) {
  1625. foreach ($categories as $category) {
  1626. $sum_categories_weight_array[$category->get_id()] = $category->get_weight();
  1627. }
  1628. } else {
  1629. $sum_categories_weight_array[$category_id] = $cats_course[0]->get_weight();
  1630. }
  1631. }
  1632. $main_weight = $cats_course[0]->get_weight();
  1633. $cattotal = Category::load($category_id);
  1634. $scoretotal = $cattotal[0]->calc_score($user_id);
  1635. // Do not remove this the gradebook/lib/fe/gradebooktable.class.php
  1636. // file load this variable as a global
  1637. $scoredisplay = ScoreDisplay::instance();
  1638. $my_score_in_gradebook = $scoredisplay->display_score($scoretotal, SCORE_SIMPLE);
  1639. // A student always sees only the teacher's repartition
  1640. $scoretotal_display = $scoredisplay->display_score($scoretotal, SCORE_DIV_PERCENT);
  1641. if (!self::userFinishedCourse($user_id, $cats_course[0])) {
  1642. return false;
  1643. }
  1644. $my_certificate = GradebookUtils::get_certificate_by_user_id(
  1645. $cats_course[0]->get_id(),
  1646. $user_id
  1647. );
  1648. if (empty($my_certificate)) {
  1649. GradebookUtils::register_user_info_about_certificate(
  1650. $category_id,
  1651. $user_id,
  1652. $my_score_in_gradebook,
  1653. api_get_utc_datetime()
  1654. );
  1655. $my_certificate = GradebookUtils::get_certificate_by_user_id(
  1656. $cats_course[0]->get_id(),
  1657. $user_id
  1658. );
  1659. }
  1660. $html = array();
  1661. if (!empty($my_certificate)) {
  1662. $certificate_obj = new Certificate($my_certificate['id']);
  1663. $fileWasGenerated = $certificate_obj->html_file_is_generated();
  1664. if (!empty($fileWasGenerated)) {
  1665. $url = api_get_path(WEB_PATH) . 'certificates/index.php?id=' . $my_certificate['id'];
  1666. $certificates = Display::url(
  1667. '&nbsp;'.get_lang('DownloadCertificate'),
  1668. $url,
  1669. array(
  1670. 'target' => '_blank',
  1671. 'class' => 'btn btn-default'
  1672. )
  1673. );
  1674. $exportToPDF = Display::url(
  1675. Display::return_icon(
  1676. 'pdf.png',
  1677. get_lang('ExportToPDF'),
  1678. array(),
  1679. ICON_SIZE_MEDIUM
  1680. ),
  1681. "$url&action=export"
  1682. );
  1683. $hideExportLink = api_get_setting('hide_certificate_export_link');
  1684. $hideExportLinkStudent = api_get_setting('hide_certificate_export_link_students');
  1685. if ($hideExportLink === 'true' || (api_is_student() && $hideExportLinkStudent === 'true') ) {
  1686. $exportToPDF = null;
  1687. }
  1688. $html = array(
  1689. 'certificate_link' => $certificates,
  1690. 'pdf_link' => $exportToPDF,
  1691. 'pdf_url' => "$url&action=export"
  1692. );
  1693. if (api_get_setting('allow_skills_tool') == 'true') {
  1694. $courseId = api_get_course_int_id();
  1695. $sessionId = api_get_session_id();
  1696. $objSkillRelUser = new SkillRelUser();
  1697. $userSkills = $objSkillRelUser->get_user_skills($user_id, $courseId, $sessionId);
  1698. if (!empty($userSkills)) {
  1699. $html['badge_link'] = Display::url(
  1700. get_lang('DownloadBadges'),
  1701. api_get_path(WEB_CODE_PATH) . "gradebook/get_badges.php?user=$user_id",
  1702. array(
  1703. 'target' => '_blank',
  1704. 'class' => 'btn'
  1705. )
  1706. );
  1707. }
  1708. }
  1709. }
  1710. return $html;
  1711. }
  1712. }
  1713. /**
  1714. * @param int $catId
  1715. * @param array $userList
  1716. */
  1717. public static function generateCertificatesInUserList($catId, $userList)
  1718. {
  1719. if (!empty($userList)) {
  1720. foreach ($userList as $userInfo) {
  1721. self::register_user_certificate($catId, $userInfo['user_id']);
  1722. }
  1723. }
  1724. }
  1725. /**
  1726. * @param int $catId
  1727. * @param array $userList
  1728. */
  1729. public static function exportAllCertificates(
  1730. $catId,
  1731. $userList = array()
  1732. ) {
  1733. $orientation = api_get_configuration_value('certificate_pdf_orientation');
  1734. $params['orientation'] = 'landscape';
  1735. if (!empty($orientation)) {
  1736. $params['orientation'] = $orientation;
  1737. }
  1738. $params['left'] = 0;
  1739. $params['right'] = 0;
  1740. $params['top'] = 0;
  1741. $params['bottom'] = 0;
  1742. $page_format = $params['orientation'] == 'landscape' ? 'A4-L' : 'A4';
  1743. $pdf = new PDF($page_format, $params['orientation'], $params);
  1744. $certificate_list = GradebookUtils::get_list_users_certificates($catId, $userList);
  1745. $certificate_path_list = array();
  1746. if (!empty($certificate_list)) {
  1747. foreach ($certificate_list as $index=>$value) {
  1748. $list_certificate = GradebookUtils::get_list_gradebook_certificates_by_user_id(
  1749. $value['user_id'],
  1750. $catId
  1751. );
  1752. foreach ($list_certificate as $value_certificate) {
  1753. $certificate_obj = new Certificate($value_certificate['id']);
  1754. $certificate_obj->generate(array('hide_print_button' => true));
  1755. if ($certificate_obj->html_file_is_generated()) {
  1756. $certificate_path_list[]= $certificate_obj->html_file;
  1757. }
  1758. }
  1759. }
  1760. }
  1761. if (!empty($certificate_path_list)) {
  1762. // Print certificates (without the common header/footer/watermark
  1763. // stuff) and return as one multiple-pages PDF
  1764. $pdf->html_to_pdf(
  1765. $certificate_path_list,
  1766. get_lang('Certificates'),
  1767. null,
  1768. false,
  1769. false
  1770. );
  1771. }
  1772. }
  1773. /**
  1774. * @param int $catId
  1775. */
  1776. public static function deleteAllCertificates($catId)
  1777. {
  1778. $certificate_list = GradebookUtils::get_list_users_certificates($catId);
  1779. if (!empty($certificate_list)) {
  1780. foreach ($certificate_list as $index=>$value) {
  1781. $list_certificate = GradebookUtils::get_list_gradebook_certificates_by_user_id($value['user_id'], $catId);
  1782. foreach ($list_certificate as $value_certificate) {
  1783. $certificate_obj = new Certificate($value_certificate['id']);
  1784. $certificate_obj->delete(true);
  1785. }
  1786. }
  1787. }
  1788. }
  1789. /**
  1790. * Check whether a user has finished a course by its gradebook
  1791. * @param int $userId The user ID
  1792. * @param \Category $category Optional. The gradebook category.
  1793. * To check by the gradebook category
  1794. * @param int $categoryId Optional. The gradebook category ID.
  1795. * To check by the category ID
  1796. * @param string $courseCode Optional. The course code
  1797. * @param int $sessionId Optional. The session ID
  1798. * @return boolean
  1799. */
  1800. public static function userFinishedCourse(
  1801. $userId,
  1802. \Category $category = null,
  1803. $categoryId = 0,
  1804. $courseCode = null,
  1805. $sessionId = 0
  1806. )
  1807. {
  1808. if (is_null($category) && empty($categoryId)) {
  1809. return false;
  1810. }
  1811. $courseCode = empty($courseCode) ? api_get_course_id() : $courseCode;
  1812. $sessionId = empty($sessionId) ? api_get_session_id() : $sessionId;
  1813. if (is_null($category) && !empty($categoryId)) {
  1814. $cats_course = Category::load(
  1815. $categoryId,
  1816. null,
  1817. $courseCode,
  1818. null,
  1819. null,
  1820. $sessionId,
  1821. false
  1822. );
  1823. if (empty($cats_course)) {
  1824. return false;
  1825. }
  1826. $category = $cats_course[0];
  1827. }
  1828. $currentScore = self::getCurrentScore($userId, $category->get_id(), $courseCode, $sessionId);
  1829. $minCertificateScore = $category->get_certificate_min_score();
  1830. return !empty($minCertificateScore) && $currentScore >= $minCertificateScore;
  1831. }
  1832. /**
  1833. * Get the current score (as percentage) on a gradebook category for a user
  1834. * @param int $userId The user id
  1835. * @param int $categoryId The gradebook category
  1836. * @param int $courseCode The course code
  1837. * @param int $sessionId Optional. The session id
  1838. * @return float The score
  1839. */
  1840. public static function getCurrentScore($userId, $categoryId, $courseCode, $sessionId = 0, $recalculate = false)
  1841. {
  1842. if ($recalculate) {
  1843. return self::calculateCurrentScore($userId, $categoryId, $courseCode, $sessionId);
  1844. }
  1845. $resultData = Database::select(
  1846. '*',
  1847. Database::get_main_table(TABLE_MAIN_GRADEBOOK_SCORE_LOG),
  1848. [
  1849. 'where' => [
  1850. 'category_id = ? AND user_id = ?' => [$categoryId, $userId],
  1851. ],
  1852. 'order' => 'registered_at DESC',
  1853. 'limit' => '1'
  1854. ],
  1855. 'fisrt'
  1856. );
  1857. if (empty($resultData)) {
  1858. return 0;
  1859. }
  1860. return $resultData['score'];
  1861. }
  1862. /**
  1863. * Calculate the current score on a gradebook category for a user
  1864. * @param int $userId The user id
  1865. * @param int $categoryId The gradebook category
  1866. * @param int $courseCode The course code
  1867. * @param int $sessionId Optional. The session id
  1868. * @return float The score
  1869. */
  1870. private static function calculateCurrentScore($userId, $categoryId, $courseCode, $sessionId)
  1871. {
  1872. $cats_course = Category::load(
  1873. $categoryId,
  1874. null,
  1875. $courseCode,
  1876. null,
  1877. null,
  1878. $sessionId,
  1879. false
  1880. );
  1881. if (empty($cats_course)) {
  1882. return 0;
  1883. }
  1884. $category = $cats_course[0];
  1885. $courseEvaluations = $category->get_evaluations($userId, true);
  1886. $courseLinks = $category->get_links($userId, true);
  1887. $evaluationsAndLinks = array_merge($courseEvaluations, $courseLinks);
  1888. $categoryScore = 0;
  1889. for ($i = 0; $i < count($evaluationsAndLinks); $i++) {
  1890. $item = $evaluationsAndLinks[$i];
  1891. $score = $item->calc_score($userId);
  1892. $itemValue = 0;
  1893. if (!empty($score)) {
  1894. $divider = $score[1] == 0 ? 1 : $score[1];
  1895. $itemValue = $score[0] / $divider * $item->get_weight();
  1896. }
  1897. $categoryScore += $itemValue;
  1898. }
  1899. return floatval($categoryScore);
  1900. }
  1901. /**
  1902. * Register the current score for a user on a category gradebook
  1903. * @param float $score The achieved score
  1904. * @param int $userId The user id
  1905. * @param int $categoryId The gradebook category
  1906. * @return int The insert id
  1907. */
  1908. public static function registerCurrentScore($score, $userId, $categoryId)
  1909. {
  1910. return Database::insert(
  1911. Database::get_main_table(TABLE_MAIN_GRADEBOOK_SCORE_LOG),
  1912. [
  1913. 'category_id' => intval($categoryId),
  1914. 'user_id' => intval($userId),
  1915. 'score' => floatval($score),
  1916. 'registered_at' => api_get_utc_datetime()
  1917. ]
  1918. );
  1919. }
  1920. }