category.class.php 75 KB

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