course_category.lib.php 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * Returns whether we are in a mode where multiple URLs are configured to work
  5. * with course categories
  6. * @return bool
  7. */
  8. function isMultipleUrlSupport()
  9. {
  10. global $_configuration;
  11. if (isset($_configuration['enable_multiple_url_support_for_course_category'])) {
  12. return $_configuration['enable_multiple_url_support_for_course_category'];
  13. }
  14. return false;
  15. }
  16. /**
  17. * Returns the category fields from the database from an int ID
  18. * @param int $categoryId The category ID
  19. * @return array
  20. */
  21. function getCategoryById($categoryId)
  22. {
  23. $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
  24. $categoryId = intval($categoryId);
  25. $sql = "SELECT * FROM $tbl_category WHERE id = $categoryId";
  26. $result = Database::query($sql);
  27. if (Database::num_rows($result)) {
  28. return Database::fetch_array($result, 'ASSOC');
  29. }
  30. return array();
  31. }
  32. /**
  33. * Get category details from a simple category code
  34. * @param string $category The literal category code
  35. * @return array
  36. */
  37. function getCategory($category)
  38. {
  39. $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
  40. $category = Database::escape_string($category);
  41. $sql = "SELECT * FROM $tbl_category WHERE code ='$category'";
  42. $result = Database::query($sql);
  43. if (Database::num_rows($result)) {
  44. return Database::fetch_array($result, 'ASSOC');
  45. }
  46. return array();
  47. }
  48. /**
  49. * @param string $category
  50. *
  51. * @return array
  52. */
  53. function getCategories($category)
  54. {
  55. $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
  56. $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
  57. $category = Database::escape_string($category);
  58. $conditions = null;
  59. $whereCondition = null;
  60. if (isMultipleUrlSupport()) {
  61. $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
  62. $conditions = " INNER JOIN $table a ON (t1.id = a.course_category_id)";
  63. $whereCondition = " AND a.access_url_id = ".api_get_current_access_url_id();
  64. }
  65. $sql = "SELECT
  66. t1.name,
  67. t1.code,
  68. t1.parent_id,
  69. t1.tree_pos,
  70. t1.children_count,
  71. COUNT(DISTINCT t3.code) AS nbr_courses
  72. FROM $tbl_category t1
  73. $conditions
  74. LEFT JOIN $tbl_category t2 ON t1.code=t2.parent_id
  75. LEFT JOIN $tbl_course t3 ON t3.category_code=t1.code
  76. WHERE
  77. t1.parent_id " . (empty($category) ? "IS NULL" : "='$category'") . "
  78. $whereCondition
  79. GROUP BY t1.name,
  80. t1.code,
  81. t1.parent_id,
  82. t1.tree_pos,
  83. t1.children_count
  84. ORDER BY t1.tree_pos";
  85. $result = Database::query($sql);
  86. return Database::store_result($result);
  87. }
  88. /**
  89. * @param string $code
  90. * @param string $name
  91. * @param string $canHaveCourses
  92. * @param int $parent_id
  93. *
  94. * @return bool
  95. */
  96. function addNode($code, $name, $canHaveCourses, $parent_id)
  97. {
  98. $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
  99. $code = trim(Database::escape_string($code));
  100. $name = trim(Database::escape_string($name));
  101. $parent_id = trim(Database::escape_string($parent_id));
  102. $canHaveCourses = Database::escape_string($canHaveCourses);
  103. $code = generate_course_code($code);
  104. $result = Database::query("SELECT 1 FROM $tbl_category WHERE code='$code'");
  105. if (Database::num_rows($result)) {
  106. return false;
  107. }
  108. $result = Database::query("SELECT MAX(tree_pos) AS maxTreePos FROM $tbl_category");
  109. $row = Database::fetch_array($result);
  110. $tree_pos = $row['maxTreePos'] + 1;
  111. $sql = "INSERT INTO $tbl_category(name, code, parent_id, tree_pos, children_count, auth_course_child)
  112. VALUES('$name', '$code', " .(empty($parent_id) ? "NULL" : "'$parent_id'") . ", '$tree_pos', '0', '$canHaveCourses')";
  113. Database::query($sql);
  114. $categoryId = Database::insert_id();
  115. updateParentCategoryChildrenCount($parent_id, 1);
  116. if (isMultipleUrlSupport()) {
  117. addToUrl($categoryId);
  118. }
  119. return $categoryId;
  120. }
  121. /**
  122. * Recursive function that updates the count of children in the parent
  123. * @param string $categoryId Category ID
  124. * @param int $delta The number to add or delete (1 to add one, -1 to remove one)
  125. */
  126. function updateParentCategoryChildrenCount($categoryId, $delta = 1)
  127. {
  128. $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
  129. $categoryId = Database::escape_string($categoryId);
  130. $delta = intval($delta);
  131. // First get to the highest level possible in the tree
  132. $result = Database::query("SELECT parent_id FROM $tbl_category WHERE code = '$categoryId'");
  133. $row = Database::fetch_array($result);
  134. if ($row !== false and $row['parent_id'] != 0) {
  135. // if a parent was found, enter there to see if he's got one more parent
  136. updateParentCategoryChildrenCount($row['parent_id'], $delta);
  137. }
  138. // Now we're at the top, get back down to update each child
  139. //$children_count = courseCategoryChildrenCount($categoryId);
  140. if ($delta >= 0) {
  141. $sql = "UPDATE $tbl_category SET children_count = (children_count + $delta) WHERE code = '$categoryId'";
  142. } else {
  143. $sql = "UPDATE $tbl_category SET children_count = (children_count - ".abs($delta).") WHERE code = '$categoryId'";
  144. }
  145. $result = Database::query($sql);
  146. }
  147. /**
  148. * @param string $node
  149. */
  150. function deleteNode($node)
  151. {
  152. $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
  153. $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
  154. $node = Database::escape_string($node);
  155. $result = Database::query("SELECT parent_id, tree_pos FROM $tbl_category WHERE code='$node'");
  156. if ($row = Database::fetch_array($result)) {
  157. if (!empty($row['parent_id'])) {
  158. Database::query("UPDATE $tbl_course SET category_code = '".$row['parent_id']."' WHERE category_code='$node'");
  159. Database::query("UPDATE $tbl_category SET parent_id='" . $row['parent_id'] . "' WHERE parent_id='$node'");
  160. } else {
  161. Database::query("UPDATE $tbl_course SET category_code='' WHERE category_code='$node'");
  162. Database::query("UPDATE $tbl_category SET parent_id=NULL WHERE parent_id='$node'");
  163. }
  164. Database::query("UPDATE $tbl_category SET tree_pos=tree_pos-1 WHERE tree_pos > '" . $row['tree_pos'] . "'");
  165. Database::query("DELETE FROM $tbl_category WHERE code='$node'");
  166. if (!empty($row['parent_id'])) {
  167. updateParentCategoryChildrenCount($row['parent_id'], -1);
  168. }
  169. }
  170. }
  171. /**
  172. * @param string $code
  173. * @param string $name
  174. * @param string $canHaveCourses
  175. * @param string $old_code
  176. * @return bool
  177. */
  178. function editNode($code, $name, $canHaveCourses, $old_code)
  179. {
  180. $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
  181. $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
  182. $code = trim(Database::escape_string($code));
  183. $name = trim(Database::escape_string($name));
  184. $old_code = Database::escape_string($old_code);
  185. $canHaveCourses = Database::escape_string($canHaveCourses);
  186. $code = generate_course_code($code);
  187. // Updating category
  188. $sql = "UPDATE $tbl_category SET name='$name', code='$code', auth_course_child = '$canHaveCourses'
  189. WHERE code = '$old_code'";
  190. Database::query($sql);
  191. // Updating children
  192. $sql = "UPDATE $tbl_category SET parent_id = '$code'
  193. WHERE parent_id = '$old_code'";
  194. Database::query($sql);
  195. // Updating course category
  196. $sql = "UPDATE $tbl_course SET category_code = '$code' WHERE category_code = '$old_code' ";
  197. Database::query($sql);
  198. return true;
  199. }
  200. /**
  201. * Move a node up on display
  202. * @param string $code
  203. * @param int $tree_pos
  204. * @param string $parent_id
  205. *
  206. * @return bool
  207. */
  208. function moveNodeUp($code, $tree_pos, $parent_id)
  209. {
  210. $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
  211. $code = Database::escape_string($code);
  212. $tree_pos = intval($tree_pos);
  213. $parent_id = Database::escape_string($parent_id);
  214. $parentIdCondition = " AND (parent_id IS NULL OR parent_id = '' )";
  215. if (!empty($parent_id)) {
  216. $parentIdCondition = " AND parent_id = '$parent_id' ";
  217. }
  218. $sql = "SELECT code,tree_pos
  219. FROM $tbl_category
  220. WHERE
  221. tree_pos < $tree_pos
  222. $parentIdCondition
  223. ORDER BY tree_pos DESC
  224. LIMIT 0,1";
  225. $result = Database::query($sql);
  226. if (!$row = Database::fetch_array($result)) {
  227. $sql = "SELECT code, tree_pos
  228. FROM $tbl_category
  229. WHERE
  230. tree_pos > $tree_pos
  231. $parentIdCondition
  232. ORDER BY tree_pos DESC
  233. LIMIT 0,1";
  234. $result2 = Database::query($sql);
  235. if (!$row = Database::fetch_array($result2)) {
  236. return false;
  237. }
  238. }
  239. $sql = "UPDATE $tbl_category
  240. SET tree_pos ='" . $row['tree_pos'] . "'
  241. WHERE code='$code'";
  242. Database::query($sql);
  243. $sql = "UPDATE $tbl_category
  244. SET tree_pos = '$tree_pos'
  245. WHERE code= '" . $row['code'] . "'";
  246. Database::query($sql);
  247. return true;
  248. }
  249. /**
  250. * Counts the number of children categories a category has
  251. * @param int $categoryId The ID of the category of which we want to count the children
  252. * @param int $count The number of subcategories we counted this far
  253. * @return mixed The number of subcategories this category has
  254. */
  255. function courseCategoryChildrenCount($categoryId)
  256. {
  257. $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
  258. $categoryId = intval($categoryId);
  259. $count = 0;
  260. if (empty($categoryId)) {
  261. return 0;
  262. }
  263. $sql = "SELECT id, code FROM $tbl_category WHERE parent_id = $categoryId";
  264. $result = Database::query($sql);
  265. while ($row = Database::fetch_array($result)) {
  266. $count += courseCategoryChildrenCount($row['id']);
  267. }
  268. $sql = "UPDATE $tbl_category SET children_count = $count WHERE id = $categoryId";
  269. Database::query($sql);
  270. return $count + 1;
  271. }
  272. /**
  273. * @param string $categoryCode
  274. *
  275. * @return array
  276. */
  277. function getChildren($categoryCode)
  278. {
  279. $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
  280. $categoryCode = Database::escape_string($categoryCode);
  281. $result = Database::query("SELECT code, id FROM $tbl_category WHERE parent_id = '$categoryCode'");
  282. $children = array();
  283. while ($row = Database::fetch_array($result, 'ASSOC')) {
  284. $children[] = $row;
  285. $subChildren = getChildren($row['code']);
  286. $children = array_merge($children, $subChildren);
  287. }
  288. return $children;
  289. }
  290. /**
  291. * @param string $categoryCode
  292. * @return array
  293. */
  294. function getParents($categoryCode)
  295. {
  296. if (empty($categoryCode)) {
  297. return array();
  298. }
  299. $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
  300. $categoryCode = Database::escape_string($categoryCode);
  301. $sql = "SELECT code, parent_id FROM $tbl_category WHERE code = '$categoryCode'";
  302. $result = Database::query($sql);
  303. $children = array();
  304. while ($row = Database::fetch_array($result, 'ASSOC')) {
  305. $parent = getCategory($row['parent_id']);
  306. $children[] = $row;
  307. $subChildren = getParents($parent['code']);
  308. $children = array_merge($children, $subChildren);
  309. }
  310. return $children;
  311. }
  312. /**
  313. * @param string $categoryCode
  314. * @return null|string
  315. */
  316. function getParentsToString($categoryCode)
  317. {
  318. $parents = getParents($categoryCode);
  319. if (!empty($parents)) {
  320. $parents = array_reverse($parents);
  321. $categories = array();
  322. foreach ($parents as $category) {
  323. $categories[] = $category['code'];
  324. }
  325. $categoriesInString = implode(' > ', $categories).' > ';
  326. return $categoriesInString;
  327. }
  328. return null;
  329. }
  330. /**
  331. * @param string $categorySource
  332. * @return string
  333. */
  334. function listCategories($categorySource)
  335. {
  336. $categorySource = isset($categorySource) ? $categorySource : null;
  337. $categories = getCategories($categorySource);
  338. if (count($categories) > 0) {
  339. $table = new HTML_Table(array('class' => 'data_table'));
  340. $column = 0;
  341. $row = 0;
  342. $headers = array(
  343. get_lang('Category'), get_lang('CategoriesNumber'), get_lang('Courses'), get_lang('Actions')
  344. );
  345. foreach ($headers as $header) {
  346. $table->setHeaderContents($row, $column, $header);
  347. $column++;
  348. }
  349. $row++;
  350. $mainUrl = api_get_path(WEB_CODE_PATH).'admin/course_category.php?category='.$categorySource;
  351. $editIcon = Display::return_icon('edit.png', get_lang('EditNode'), null, ICON_SIZE_SMALL);
  352. $deleteIcon = Display::return_icon('delete.png', get_lang('DeleteNode'), null, ICON_SIZE_SMALL);
  353. $moveIcon = Display::return_icon('up.png', get_lang('UpInSameLevel'), null, ICON_SIZE_SMALL);
  354. foreach ($categories as $category) {
  355. $editUrl = $mainUrl.'&id='.$category['code'].'&action=edit';
  356. $moveUrl = $mainUrl.'&id='.$category['code'].'&action=moveUp&tree_pos='.$category['tree_pos'];
  357. $deleteUrl = $mainUrl.'&id='.$category['code'].'&action=delete';
  358. $actions = Display::url($editIcon, $editUrl).Display::url($moveIcon, $moveUrl).Display::url($deleteIcon, $deleteUrl);
  359. $url = api_get_path(WEB_CODE_PATH).'admin/course_category.php?category='.$category['code'];
  360. $title = Display::url(
  361. Display::return_icon('folder_document.gif', get_lang('OpenNode'), null, ICON_SIZE_SMALL).' '.$category['name'],
  362. $url
  363. );
  364. $content = array(
  365. $title,
  366. $category['children_count'],
  367. $category['nbr_courses'],
  368. $actions
  369. );
  370. $column = 0;
  371. foreach ($content as $value) {
  372. $table->setCellContents($row, $column, $value);
  373. $column++;
  374. }
  375. $row++;
  376. }
  377. return $table->toHtml();
  378. } else {
  379. return Display::return_message(get_lang("NoCategories"), 'warning');
  380. }
  381. }
  382. /**
  383. * @return array
  384. */
  385. function getCategoriesToDisplayInHomePage()
  386. {
  387. $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
  388. $sql = "SELECT name FROM $tbl_category WHERE parent_id IS NULL ORDER BY tree_pos";
  389. return Database::store_result(Database::query($sql));
  390. }
  391. /**
  392. * @param int $id
  393. * @return bool
  394. */
  395. function addToUrl($id)
  396. {
  397. if (!isMultipleUrlSupport()) {
  398. return false;
  399. }
  400. UrlManager::addCourseCategoryListToUrl(array($id), array(api_get_current_access_url_id()));
  401. }
  402. /**
  403. * @param string $categoryCode
  404. * @return array
  405. */
  406. function getCategoriesCanBeAddedInCourse($categoryCode)
  407. {
  408. $conditions = null;
  409. $whereCondition = null;
  410. if (isMultipleUrlSupport()) {
  411. $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
  412. $conditions = " INNER JOIN $table a ON (c.id = a.course_category_id)";
  413. $whereCondition = " AND a.access_url_id = ".api_get_current_access_url_id();
  414. }
  415. $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
  416. $sql = "SELECT code, name
  417. FROM $tbl_category c
  418. $conditions
  419. WHERE (auth_course_child = 'TRUE' OR code = '".Database::escape_string($categoryCode)."')
  420. $whereCondition
  421. ORDER BY tree_pos";
  422. $res = Database::query($sql);
  423. $categories[''] = '-';
  424. while ($cat = Database::fetch_array($res)) {
  425. $categories[$cat['code']] = '('.$cat['code'].') '.$cat['name'];
  426. ksort($categories);
  427. }
  428. return $categories;
  429. }
  430. /**
  431. * @return array
  432. */
  433. function browseCourseCategories()
  434. {
  435. $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
  436. $conditions = null;
  437. $whereCondition = null;
  438. if (isMultipleUrlSupport()) {
  439. $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
  440. $conditions = " INNER JOIN $table a ON (c.id = a.course_category_id)";
  441. $whereCondition = " WHERE a.access_url_id = ".api_get_current_access_url_id();
  442. }
  443. $sql = "SELECT c.* FROM $tbl_category c
  444. $conditions
  445. $whereCondition
  446. ORDER BY tree_pos ASC";
  447. $result = Database::query($sql);
  448. $url_access_id = 1;
  449. if (api_is_multiple_url_enabled()) {
  450. $url_access_id = api_get_current_access_url_id();
  451. }
  452. $countCourses = CourseManager :: countAvailableCourses($url_access_id);
  453. $categories = array();
  454. $categories[0][0] = array(
  455. 'id' => 0,
  456. 'name' => get_lang('DisplayAll'),
  457. 'code' => 'ALL',
  458. 'parent_id' => null,
  459. 'tree_pos' => 0,
  460. 'count_courses' => $countCourses
  461. );
  462. while ($row = Database::fetch_array($result)) {
  463. $count_courses = countCoursesInCategory($row['code']);
  464. $row['count_courses'] = $count_courses;
  465. if (!isset($row['parent_id'])) {
  466. $categories[0][$row['tree_pos']] = $row;
  467. } else {
  468. $categories[$row['parent_id']][$row['tree_pos']] = $row;
  469. }
  470. }
  471. $count_courses = countCoursesInCategory();
  472. $categories[0][count($categories[0])+1] = array(
  473. 'id' =>0,
  474. 'name' => get_lang('None'),
  475. 'code' => 'NONE',
  476. 'parent_id' => null,
  477. 'tree_pos' => $row['tree_pos']+1,
  478. 'children_count' => 0,
  479. 'auth_course_child' => true,
  480. 'auth_cat_child' => true,
  481. 'count_courses' => $count_courses
  482. );
  483. return $categories;
  484. }
  485. /**
  486. * @param string $category_code
  487. * @param string $searchTerm
  488. * @return int
  489. */
  490. function countCoursesInCategory($category_code="", $searchTerm = '')
  491. {
  492. global $_configuration;
  493. $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
  494. $TABLE_COURSE_FIELD = Database :: get_main_table(TABLE_MAIN_COURSE_FIELD);
  495. $TABLE_COURSE_FIELD_VALUE = Database :: get_main_table(TABLE_MAIN_COURSE_FIELD_VALUES);
  496. $categoryCode = Database::escape_string($category_code);
  497. $searchTerm = Database::escape_string($searchTerm);
  498. $categoryFilter = '';
  499. $searchFilter = '';
  500. // get course list auto-register
  501. $sql = "SELECT course_code
  502. FROM $TABLE_COURSE_FIELD_VALUE tcfv
  503. INNER JOIN $TABLE_COURSE_FIELD tcf ON tcfv.field_id = tcf.id
  504. WHERE tcf.field_variable = 'special_course' AND tcfv.field_value = 1 ";
  505. $special_course_result = Database::query($sql);
  506. if (Database::num_rows($special_course_result) > 0) {
  507. $special_course_list = array();
  508. while ($result_row = Database::fetch_array($special_course_result)) {
  509. $special_course_list[] = '"' . $result_row['course_code'] . '"';
  510. }
  511. }
  512. $without_special_courses = '';
  513. if (!empty($special_course_list)) {
  514. $without_special_courses = ' AND course.code NOT IN (' . implode(',', $special_course_list) . ')';
  515. }
  516. $visibilityCondition = null;
  517. if (isset($_configuration['course_catalog_hide_private'])) {
  518. if ($_configuration['course_catalog_hide_private'] == true) {
  519. $courseInfo = api_get_course_info();
  520. $courseVisibility = $courseInfo['visibility'];
  521. $visibilityCondition = ' AND course.visibility <> 1';
  522. }
  523. }
  524. if ($categoryCode == 'ALL') {
  525. // Nothing to do
  526. } elseif ($categoryCode == 'NONE') {
  527. $categoryFilter = ' AND category_code = "" ';
  528. } else {
  529. $categoryFilter = ' AND category_code = "' . $categoryCode . '" ';
  530. }
  531. if (!empty($searchTerm)) {
  532. $searchFilter = ' AND (code LIKE "%' . $searchTerm . '%"
  533. OR title LIKE "%' . $searchTerm . '%"
  534. OR tutor_name LIKE "%' . $searchTerm . '%") ';
  535. }
  536. $sql = "SELECT * FROM $tbl_course
  537. WHERE
  538. visibility != '0' AND
  539. visibility != '4'
  540. $categoryFilter
  541. $searchFilter
  542. $without_special_courses
  543. $visibilityCondition
  544. ";
  545. // Showing only the courses of the current portal access_url_id.
  546. if (api_is_multiple_url_enabled()) {
  547. $url_access_id = api_get_current_access_url_id();
  548. if ($url_access_id != -1) {
  549. $tbl_url_rel_course = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
  550. $sql = "SELECT * FROM $tbl_course as course
  551. INNER JOIN $tbl_url_rel_course as url_rel_course
  552. ON (url_rel_course.course_code=course.code)
  553. WHERE
  554. access_url_id = $url_access_id AND
  555. course.visibility != '0' AND
  556. course.visibility != '4' AND
  557. category_code = '$category_code'
  558. $searchTerm
  559. $without_special_courses
  560. $visibilityCondition
  561. ";
  562. }
  563. }
  564. return Database::num_rows(Database::query($sql));
  565. }
  566. /**
  567. * @param string $category_code
  568. * @param int $random_value
  569. * @param array $limit will be used if $random_value is not set.
  570. * This array should contains 'start' and 'length' keys
  571. * @return array
  572. */
  573. function browseCoursesInCategory($category_code, $random_value = null, $limit = array())
  574. {
  575. global $_configuration;
  576. $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
  577. $TABLE_COURSE_FIELD = Database::get_main_table(TABLE_MAIN_COURSE_FIELD);
  578. $TABLE_COURSE_FIELD_VALUE = Database::get_main_table(TABLE_MAIN_COURSE_FIELD_VALUES);
  579. // Get course list auto-register
  580. $sql = "SELECT course_code
  581. FROM $TABLE_COURSE_FIELD_VALUE tcfv
  582. INNER JOIN $TABLE_COURSE_FIELD tcf ON tcfv.field_id = tcf.id
  583. WHERE tcf.field_variable = 'special_course' AND tcfv.field_value = 1 ";
  584. $special_course_result = Database::query($sql);
  585. if (Database::num_rows($special_course_result) > 0) {
  586. $special_course_list = array();
  587. while ($result_row = Database::fetch_array($special_course_result)) {
  588. $special_course_list[] = '"' . $result_row['course_code'] . '"';
  589. }
  590. }
  591. $without_special_courses = '';
  592. if (!empty($special_course_list)) {
  593. $without_special_courses = ' AND course.code NOT IN (' . implode(',', $special_course_list) . ')';
  594. }
  595. $visibilityCondition = null;
  596. if (isset($_configuration['course_catalog_hide_private'])) {
  597. if ($_configuration['course_catalog_hide_private'] == true) {
  598. $courseInfo = api_get_course_info();
  599. $courseVisibility = $courseInfo['visibility'];
  600. $visibilityCondition = ' AND course.visibility <> 1';
  601. }
  602. }
  603. if (!empty($random_value)) {
  604. $random_value = intval($random_value);
  605. $sql = "SELECT COUNT(*) FROM $tbl_course";
  606. $result = Database::query($sql);
  607. list($num_records) = Database::fetch_row($result);
  608. if (api_is_multiple_url_enabled()) {
  609. $url_access_id = api_get_current_access_url_id();
  610. $tbl_url_rel_course = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
  611. $sql = "SELECT COUNT(*) FROM $tbl_course course
  612. INNER JOIN $tbl_url_rel_course as url_rel_course ON (url_rel_course.course_code=course.code)
  613. WHERE access_url_id = $url_access_id ";
  614. $result = Database::query($sql);
  615. list($num_records) = Database::fetch_row($result);
  616. $sql = "SELECT course.id FROM $tbl_course course INNER JOIN $tbl_url_rel_course as url_rel_course
  617. ON (url_rel_course.course_code=course.code)
  618. WHERE access_url_id = $url_access_id AND
  619. RAND()*$num_records< $random_value
  620. $without_special_courses $visibilityCondition
  621. ORDER BY RAND() LIMIT 0, $random_value";
  622. } else {
  623. $sql = "SELECT id FROM $tbl_course course
  624. WHERE RAND()*$num_records< $random_value $without_special_courses $visibilityCondition
  625. ORDER BY RAND() LIMIT 0, $random_value";
  626. }
  627. $result = Database::query($sql);
  628. $id_in = null;
  629. while (list($id) = Database::fetch_row($result)) {
  630. if ($id_in) {
  631. $id_in.=",$id";
  632. } else {
  633. $id_in = "$id";
  634. }
  635. }
  636. $sql = "SELECT * FROM $tbl_course WHERE id IN($id_in)";
  637. } else {
  638. $limitFilter = getLimitFilterFromArray($limit);
  639. $category_code = Database::escape_string($category_code);
  640. if (empty($category_code) || $category_code == "ALL") {
  641. $sql = "SELECT * FROM $tbl_course
  642. WHERE 1=1 $without_special_courses $visibilityCondition
  643. ORDER BY title $limitFilter ";
  644. } else {
  645. if ($category_code == 'NONE') {
  646. $category_code = '';
  647. }
  648. $sql = "SELECT * FROM $tbl_course
  649. WHERE category_code='$category_code' $without_special_courses $visibilityCondition
  650. ORDER BY title $limitFilter ";
  651. }
  652. //showing only the courses of the current Chamilo access_url_id
  653. if (api_is_multiple_url_enabled()) {
  654. $url_access_id = api_get_current_access_url_id();
  655. $tbl_url_rel_course = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
  656. if ($category_code != "ALL") {
  657. $sql = "SELECT * FROM $tbl_course as course INNER JOIN $tbl_url_rel_course as url_rel_course
  658. ON (url_rel_course.course_code=course.code)
  659. WHERE access_url_id = $url_access_id AND category_code='$category_code' $without_special_courses $visibilityCondition
  660. ORDER BY title $limitFilter";
  661. } else {
  662. $sql = "SELECT * FROM $tbl_course as course INNER JOIN $tbl_url_rel_course as url_rel_course
  663. ON (url_rel_course.course_code=course.code)
  664. WHERE access_url_id = $url_access_id $without_special_courses $visibilityCondition
  665. ORDER BY title $limitFilter";
  666. }
  667. }
  668. }
  669. $result = Database::query($sql);
  670. $courses = array();
  671. while ($row = Database::fetch_array($result)) {
  672. $row['registration_code'] = !empty($row['registration_code']);
  673. $count_users = CourseManager::get_users_count_in_course($row['code']);
  674. $count_connections_last_month = Tracking::get_course_connections_count(
  675. $row['code'],
  676. 0,
  677. api_get_utc_datetime(time() - (30 * 86400))
  678. );
  679. if ($row['tutor_name'] == '0') {
  680. $row['tutor_name'] = get_lang('NoManager');
  681. }
  682. $point_info = CourseManager::get_course_ranking($row['id'], 0);
  683. $courses[] = array(
  684. 'real_id' => $row['id'],
  685. 'point_info' => $point_info,
  686. 'code' => $row['code'],
  687. 'directory' => $row['directory'],
  688. 'db' => $row['db_name'],
  689. 'visual_code' => $row['visual_code'],
  690. 'title' => $row['title'],
  691. 'tutor' => $row['tutor_name'],
  692. 'subscribe' => $row['subscribe'],
  693. 'unsubscribe' => $row['unsubscribe'],
  694. 'registration_code' => $row['registration_code'],
  695. 'creation_date' => $row['creation_date'],
  696. 'visibility' => $row['visibility'],
  697. 'count_users' => $count_users,
  698. 'count_connections' => $count_connections_last_month
  699. );
  700. }
  701. return $courses;
  702. }
  703. /**
  704. * create recursively all categories as option of the select passed in parameter.
  705. *
  706. * @param HTML_QuickForm_Element $element
  707. * @param string $defaultCode the option value to select by default (used mainly for edition of courses)
  708. * @param string $parentCode the parent category of the categories added (default=null for root category)
  709. * @param string $padding the indent param (you shouldn't indicate something here)
  710. */
  711. function setCategoriesInForm($element, $defaultCode = null, $parentCode = null, $padding = null)
  712. {
  713. $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
  714. $conditions = null;
  715. $whereCondition = null;
  716. if (isMultipleUrlSupport()) {
  717. $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
  718. $conditions = " INNER JOIN $table a ON (c.id = a.course_category_id)";
  719. $whereCondition = " AND a.access_url_id = ".api_get_current_access_url_id();
  720. }
  721. $sql = "SELECT code, name, auth_course_child, auth_cat_child
  722. FROM ".$tbl_category." c
  723. $conditions
  724. WHERE parent_id ".(empty($parentCode) ? "IS NULL" : "='".Database::escape_string($parentCode)."'")."
  725. $whereCondition
  726. ORDER BY name, code";
  727. $res = Database::query($sql);
  728. while ($cat = Database::fetch_array($res, 'ASSOC')) {
  729. $params = $cat['auth_course_child'] == 'TRUE' ? '' : 'disabled';
  730. $params .= ($cat['code'] == $defaultCode) ? ' selected' : '';
  731. $option = $padding.' '.$cat['name'].' ('.$cat['code'].')';
  732. $element->addOption($option, $cat['code'], $params);
  733. if ($cat['auth_cat_child'] == 'TRUE') {
  734. setCategoriesInForm($element, $defaultCode, $cat['code'], $padding.' - ');
  735. }
  736. }
  737. }
  738. /**
  739. * @param array $list
  740. * @return array
  741. */
  742. function getCourseCategoryNotInList($list)
  743. {
  744. $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
  745. if (empty($list)) {
  746. return array();
  747. }
  748. $list = array_map('intval', $list);
  749. $listToString = implode("','", $list);
  750. $sql = "SELECT * FROM $table WHERE id NOT IN ('$listToString') AND (parent_id IS NULL) ";
  751. $result = Database::query($sql);
  752. return Database::store_result($result, 'ASSOC');
  753. }
  754. /**
  755. * @param string $keyword
  756. * @return array|null
  757. */
  758. function searchCategoryByKeyword($keyword)
  759. {
  760. if (empty($keyword)) {
  761. return null;
  762. }
  763. $tableCategory = Database::get_main_table(TABLE_MAIN_CATEGORY);
  764. $conditions = null;
  765. $whereCondition = null;
  766. if (isMultipleUrlSupport()) {
  767. $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
  768. $conditions = " INNER JOIN $table a ON (c.id = a.course_category_id)";
  769. $whereCondition = " AND a.access_url_id = ".api_get_current_access_url_id();
  770. }
  771. $keyword = Database::escape_string($keyword);
  772. $sql = "SELECT c.*, c.name as text
  773. FROM $tableCategory c $conditions
  774. WHERE
  775. (
  776. c.code LIKE '%$keyword%' OR name LIKE '%$keyword%'
  777. ) AND
  778. auth_course_child = 'TRUE'
  779. $whereCondition ";
  780. $result = Database::query($sql);
  781. return Database::store_result($result, 'ASSOC');
  782. }
  783. /**
  784. * @param array $list
  785. * @return array
  786. */
  787. function searchCategoryById($list)
  788. {
  789. if (empty($list)) {
  790. return array();
  791. } else {
  792. $list = array_map('intval', $list);
  793. $list = implode("','", $list);
  794. }
  795. $tableCategory = Database::get_main_table(TABLE_MAIN_CATEGORY);
  796. $conditions = null;
  797. $whereCondition = null;
  798. if (isMultipleUrlSupport()) {
  799. $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
  800. $conditions = " INNER JOIN $table a ON (c.id = a.course_category_id)";
  801. $whereCondition = " AND a.access_url_id = ".api_get_current_access_url_id();
  802. }
  803. $sql = "SELECT c.*, c.name as text FROM $tableCategory c $conditions
  804. WHERE c.id IN $list $whereCondition";
  805. $result = Database::query($sql);
  806. return Database::store_result($result, 'ASSOC');
  807. }
  808. /**
  809. * @return array
  810. */
  811. function getLimitArray()
  812. {
  813. $pageCurrent = isset($_REQUEST['pageCurrent']) ?
  814. intval($_GET['pageCurrent']) :
  815. 1;
  816. $pageLength = isset($_REQUEST['pageLength']) ?
  817. intval($_GET['pageLength']) :
  818. 10;
  819. return array(
  820. 'start' => ($pageCurrent - 1) * $pageLength,
  821. 'current' => $pageCurrent,
  822. 'length' => $pageLength,
  823. );
  824. }
  825. /**
  826. * Return LIMIT to filter SQL query
  827. * @param array $limit
  828. * @return string
  829. */
  830. function getLimitFilterFromArray($limit)
  831. {
  832. $limitFilter = '';
  833. if (!empty($limit) && is_array($limit)) {
  834. $limitStart = isset($limit['start']) ? $limit['start'] : 0;
  835. $limitLength = isset($limit['length']) ? $limit['length'] : 10;
  836. $limitFilter = 'LIMIT ' . $limitStart . ', ' . $limitLength;
  837. }
  838. return $limitFilter;
  839. }
  840. /**
  841. * Get Pagination HTML div
  842. * @param $pageCurrent
  843. * @param $pageLength
  844. * @param $pageTotal
  845. * @return string
  846. */
  847. function getCataloguePagination($pageCurrent, $pageLength, $pageTotal)
  848. {
  849. // Start empty html
  850. $pageDiv = '';
  851. $pageBottom = max(1, $pageCurrent - 3);
  852. $pageTop = min($pageTotal, $pageCurrent + 3);
  853. if ($pageBottom > 1) {
  854. $pageDiv .= getPageNumberItem(1, $pageLength);
  855. if ($pageBottom > 2) {
  856. $pageDiv .= getPageNumberItem($pageBottom - 1, $pageLength, null, '...');
  857. }
  858. } else {
  859. // Nothing to do
  860. }
  861. // For each page add its page button to html
  862. for (
  863. $i = $pageBottom;
  864. $i <= $pageTop;
  865. $i++
  866. ) {
  867. if ($i === $pageCurrent) {
  868. $pageItemAttributes = array('class' => 'active');
  869. } else {
  870. $pageItemAttributes = array();
  871. }
  872. $pageDiv .= getPageNumberItem($i, $pageLength, $pageItemAttributes);
  873. }
  874. // Check if current page is the last page
  875. if ($pageTop < $pageTotal) {
  876. if ($pageTop < ($pageTotal - 1)) {
  877. $pageDiv .= getPageNumberItem($pageTop + 1, $pageLength, null, '...');
  878. }
  879. $pageDiv .= getPageNumberItem($pageTotal, $pageLength);
  880. } else {
  881. // Nothing to do
  882. }
  883. // Complete pagination html
  884. $pageDiv = Display::div(
  885. Display::tag(
  886. 'ul',
  887. $pageDiv
  888. ),
  889. array(
  890. 'class' => 'pagination pagination-centered',
  891. )
  892. );
  893. return $pageDiv;
  894. }
  895. /**
  896. * Return URL to course catalog
  897. * @param int $pageCurrent
  898. * @param int $pageLength
  899. * @param string $categoryCode
  900. * @param int $hiddenLinks
  901. * @param string $action
  902. * @return string
  903. */
  904. function getCourseCategoryUrl(
  905. $pageCurrent,
  906. $pageLength,
  907. $categoryCode = null,
  908. $hiddenLinks = null,
  909. $action = null
  910. ) {
  911. $action = isset($action) ? Security::remove_XSS($action) : Security::remove_XSS($_REQUEST['action']);
  912. $searchTerm = isset($_REQUEST['search_term']) ? Security::remove_XSS($_REQUEST['search_term']) : null;
  913. // Start URL with params
  914. $pageUrl = api_get_self() .
  915. '?action=' . $action .
  916. '&category_code=' . (
  917. isset($categoryCode) ? $categoryCode :
  918. Security::remove_XSS($_REQUEST['category_code'])
  919. ) .
  920. '&hidden_links=' . (
  921. isset($hiddenLinks) ? $hiddenLinks :
  922. Security::remove_XSS($_REQUEST['hidden_links'])
  923. ).
  924. '&pageCurrent=' . $pageCurrent .
  925. '&pageLength=' . $pageLength
  926. ;
  927. switch ($action) {
  928. case 'subscribe' :
  929. // for search
  930. $pageUrl .=
  931. '&search_term=' . $searchTerm .
  932. '&search_course=1' .
  933. '&sec_token=' . $_SESSION['sec_token'];
  934. break;
  935. case 'display_courses' :
  936. // No break
  937. default :
  938. break;
  939. }
  940. return $pageUrl;
  941. }
  942. /**
  943. * Get li HTML of page number
  944. * @param $pageNumber
  945. * @param $pageLength
  946. * @param array $liAttributes
  947. * @param string $content
  948. * @return string
  949. */
  950. function getPageNumberItem($pageNumber, $pageLength, $liAttributes = array(), $content = '')
  951. {
  952. // Get page URL
  953. $url = getCourseCategoryUrl(
  954. $pageNumber,
  955. $pageLength
  956. );
  957. // If is current page ('active' class) clear URL
  958. if (isset($liAttributes) && is_array($liAttributes)) {
  959. if (strpos('active', $liAttributes['class']) !== false) {
  960. $url = '';
  961. }
  962. }
  963. $content = !empty($content) ? $content : $pageNumber;
  964. return Display::tag(
  965. 'li',
  966. Display::url(
  967. $content,
  968. $url
  969. ),
  970. $liAttributes
  971. );
  972. }
  973. /**
  974. * Return the name tool by action
  975. * @param string $action
  976. * @return string
  977. */
  978. function getCourseCatalogNameTools($action)
  979. {
  980. $nameTools = get_lang('SortMyCourses');
  981. if (empty($action)) {
  982. return $nameTools; //should never happen
  983. }
  984. switch ($action) {
  985. case 'createcoursecategory' :
  986. $nameTools = get_lang('CreateCourseCategory');
  987. break;
  988. case 'subscribe' :
  989. $nameTools = get_lang('CourseManagement');
  990. break;
  991. case 'subscribe_user_with_password' :
  992. $nameTools = get_lang('CourseManagement');
  993. break;
  994. case 'display_random_courses' :
  995. // No break
  996. case 'display_courses' :
  997. $nameTools = get_lang('CourseManagement');
  998. break;
  999. case 'display_sessions' :
  1000. $nameTools = get_lang('Sessions');
  1001. break;
  1002. default :
  1003. // Nothing to do
  1004. break;
  1005. }
  1006. return $nameTools;
  1007. }
  1008. /**
  1009. CREATE TABLE IF NOT EXISTS access_url_rel_course_category (access_url_id int unsigned NOT NULL, course_category_id int unsigned NOT NULL, PRIMARY KEY (access_url_id, course_category_id));
  1010. */