category.class.php 75 KB

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