course_category.lib.php 39 KB

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