course_category.lib.php 36 KB

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