course_category.lib.php 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
  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. *
  11. * @param int $categoryId The category ID
  12. *
  13. * @return array
  14. */
  15. public static function getCategoryById($categoryId)
  16. {
  17. $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
  18. $categoryId = (int) $categoryId;
  19. $sql = "SELECT * FROM $table WHERE id = $categoryId";
  20. $result = Database::query($sql);
  21. if (Database::num_rows($result)) {
  22. return Database::fetch_array($result, 'ASSOC');
  23. }
  24. return [];
  25. }
  26. /**
  27. * Get category details from a simple category code.
  28. *
  29. * @param string $categoryCode The literal category code
  30. *
  31. * @return array
  32. */
  33. public static function getCategory($categoryCode)
  34. {
  35. $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
  36. $categoryCode = Database::escape_string($categoryCode);
  37. $sql = "SELECT * FROM $table WHERE code ='$categoryCode'";
  38. $result = Database::query($sql);
  39. if (Database::num_rows($result)) {
  40. $category = Database::fetch_array($result, 'ASSOC');
  41. if ($category) {
  42. // Get access url id
  43. $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
  44. $sql = "SELECT * FROM $table WHERE course_category_id = ".$category['id'];
  45. $result = Database::query($sql);
  46. $result = Database::fetch_array($result);
  47. if ($result) {
  48. $category['access_url_id'] = $result['access_url_id'];
  49. }
  50. return $category;
  51. }
  52. }
  53. return [];
  54. }
  55. /**
  56. * @param string $category Optional. Parent category code
  57. *
  58. * @return array
  59. */
  60. public static function getCategories($category = '')
  61. {
  62. $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
  63. $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
  64. $category = Database::escape_string($category);
  65. $conditions = null;
  66. $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
  67. $conditions = " INNER JOIN $table a ON (t1.id = a.course_category_id)";
  68. $whereCondition = " AND a.access_url_id = ".api_get_current_access_url_id();
  69. $allowBaseCategories = api_get_configuration_value('allow_base_course_category');
  70. if ($allowBaseCategories) {
  71. $whereCondition = " AND (a.access_url_id = ".api_get_current_access_url_id()." OR a.access_url_id = 1) ";
  72. }
  73. $parentIdCondition = " AND (t1.parent_id IS NULL OR t1.parent_id = '' )";
  74. if (!empty($category)) {
  75. $parentIdCondition = " AND t1.parent_id = '$category' ";
  76. }
  77. $sql = "SELECT
  78. t1.name,
  79. t1.code,
  80. t1.parent_id,
  81. t1.tree_pos,
  82. t1.children_count,
  83. COUNT(DISTINCT t3.code) AS nbr_courses,
  84. a.access_url_id
  85. FROM $tbl_category t1
  86. $conditions
  87. LEFT JOIN $tbl_category t2
  88. ON t1.code = t2.parent_id
  89. LEFT JOIN $tbl_course t3
  90. ON t3.category_code=t1.code
  91. WHERE
  92. 1 = 1
  93. $parentIdCondition
  94. $whereCondition
  95. GROUP BY t1.name,
  96. t1.code,
  97. t1.parent_id,
  98. t1.tree_pos,
  99. t1.children_count
  100. ORDER BY t1.tree_pos";
  101. $result = Database::query($sql);
  102. $categories = Database::store_result($result, 'ASSOC');
  103. return $categories;
  104. }
  105. /**
  106. * Returns a flat list of all course categories in this URL. If the
  107. * allow_base_course_category option is true, then also show the
  108. * course categories of the base URL.
  109. *
  110. * @return array [id, name, code, parent_id, tree_pos, children_count, number_courses]
  111. */
  112. public static function getAllCategories()
  113. {
  114. $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
  115. $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
  116. $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
  117. $conditions = " INNER JOIN $table a ON (t1.id = a.course_category_id)";
  118. $whereCondition = " AND a.access_url_id = ".api_get_current_access_url_id();
  119. $allowBaseCategories = api_get_configuration_value('allow_base_course_category');
  120. if ($allowBaseCategories) {
  121. $whereCondition = " AND (a.access_url_id = ".api_get_current_access_url_id()." OR a.access_url_id = 1) ";
  122. }
  123. $sql = "SELECT
  124. t1.id,
  125. t1.name,
  126. t1.code,
  127. t1.parent_id,
  128. t1.tree_pos,
  129. t1.children_count,
  130. COUNT(DISTINCT t3.code) AS number_courses
  131. FROM $tbl_category t1
  132. $conditions
  133. LEFT JOIN $tbl_course t3
  134. ON t3.category_code=t1.code
  135. WHERE 1=1
  136. $whereCondition
  137. GROUP BY
  138. t1.name,
  139. t1.code,
  140. t1.parent_id,
  141. t1.tree_pos,
  142. t1.children_count
  143. ORDER BY t1.parent_id, t1.tree_pos";
  144. $result = Database::query($sql);
  145. $categories = Database::store_result($result, 'ASSOC');
  146. return $categories;
  147. }
  148. /**
  149. * @param string $code
  150. * @param string $name
  151. * @param string $canHaveCourses
  152. * @param int $parent_id
  153. *
  154. * @return bool
  155. */
  156. public static function addNode($code, $name, $canHaveCourses, $parent_id)
  157. {
  158. $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
  159. $code = trim($code);
  160. $name = trim($name);
  161. $parent_id = trim($parent_id);
  162. $code = CourseManager::generate_course_code($code);
  163. $sql = "SELECT 1 FROM $table
  164. WHERE code = '".Database::escape_string($code)."'";
  165. $result = Database::query($sql);
  166. if (Database::num_rows($result)) {
  167. return false;
  168. }
  169. $result = Database::query("SELECT MAX(tree_pos) AS maxTreePos FROM $table");
  170. $row = Database::fetch_array($result);
  171. $tree_pos = $row['maxTreePos'] + 1;
  172. $params = [
  173. 'name' => $name,
  174. 'code' => $code,
  175. 'parent_id' => empty($parent_id) ? null : $parent_id,
  176. 'tree_pos' => $tree_pos,
  177. 'children_count' => 0,
  178. 'auth_course_child' => $canHaveCourses,
  179. 'auth_cat_child' => 'TRUE',
  180. ];
  181. $categoryId = Database::insert($table, $params);
  182. if ($categoryId) {
  183. self::updateParentCategoryChildrenCount($parent_id, 1);
  184. UrlManager::addCourseCategoryListToUrl(
  185. [$categoryId],
  186. [api_get_current_access_url_id()]
  187. );
  188. return $categoryId;
  189. }
  190. return false;
  191. }
  192. /**
  193. * Recursive function that updates the count of children in the parent.
  194. *
  195. * @param string $categoryId Category ID
  196. * @param int $delta The number to add or delete (1 to add one, -1 to remove one)
  197. */
  198. public static function updateParentCategoryChildrenCount($categoryId, $delta = 1)
  199. {
  200. $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
  201. $categoryId = Database::escape_string($categoryId);
  202. $delta = (int) $delta;
  203. // First get to the highest level possible in the tree
  204. $result = Database::query("SELECT parent_id FROM $table WHERE code = '$categoryId'");
  205. $row = Database::fetch_array($result);
  206. if ($row !== false and $row['parent_id'] != 0) {
  207. // if a parent was found, enter there to see if he's got one more parent
  208. self::updateParentCategoryChildrenCount($row['parent_id'], $delta);
  209. }
  210. // Now we're at the top, get back down to update each child
  211. $sql = "UPDATE $table SET children_count = (children_count - ".abs($delta).") WHERE code = '$categoryId'";
  212. if ($delta >= 0) {
  213. $sql = "UPDATE $table SET children_count = (children_count + $delta) WHERE code = '$categoryId'";
  214. }
  215. Database::query($sql);
  216. }
  217. /**
  218. * @param string $node
  219. *
  220. * @return bool
  221. */
  222. public static function deleteNode($node)
  223. {
  224. $category = self::getCategory($node);
  225. if (empty($category)) {
  226. return false;
  227. }
  228. $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
  229. $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
  230. $node = Database::escape_string($node);
  231. $result = Database::query("SELECT parent_id, tree_pos FROM $tbl_category WHERE code='$node'");
  232. if ($row = Database::fetch_array($result)) {
  233. if (!empty($row['parent_id'])) {
  234. Database::query(
  235. "UPDATE $tbl_course SET category_code = '".$row['parent_id']."' WHERE category_code='$node'"
  236. );
  237. Database::query("UPDATE $tbl_category SET parent_id='".$row['parent_id']."' WHERE parent_id='$node'");
  238. } else {
  239. Database::query("UPDATE $tbl_course SET category_code='' WHERE category_code='$node'");
  240. Database::query("UPDATE $tbl_category SET parent_id=NULL WHERE parent_id='$node'");
  241. }
  242. $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
  243. $sql = "DELETE FROM $table WHERE course_category_id = ".$category['id'];
  244. Database::query($sql);
  245. Database::query("UPDATE $tbl_category SET tree_pos=tree_pos-1 WHERE tree_pos > '".$row['tree_pos']."'");
  246. Database::query("DELETE FROM $tbl_category WHERE code='$node'");
  247. if (!empty($row['parent_id'])) {
  248. self::updateParentCategoryChildrenCount($row['parent_id'], -1);
  249. }
  250. return true;
  251. }
  252. }
  253. /**
  254. * @param string $code
  255. * @param string $name
  256. * @param string $canHaveCourses
  257. * @param string $old_code
  258. *
  259. * @return bool
  260. */
  261. public static function editNode($code, $name, $canHaveCourses, $old_code)
  262. {
  263. $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
  264. $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
  265. $code = trim(Database::escape_string($code));
  266. $name = trim(Database::escape_string($name));
  267. $old_code = Database::escape_string($old_code);
  268. $canHaveCourses = Database::escape_string($canHaveCourses);
  269. $code = CourseManager::generate_course_code($code);
  270. // Updating category
  271. $sql = "UPDATE $tbl_category SET
  272. name='$name',
  273. code='$code',
  274. auth_course_child = '$canHaveCourses'
  275. WHERE code = '$old_code'";
  276. Database::query($sql);
  277. // Updating children
  278. $sql = "UPDATE $tbl_category SET parent_id = '$code'
  279. WHERE parent_id = '$old_code'";
  280. Database::query($sql);
  281. // Updating course category
  282. $sql = "UPDATE $tbl_course SET category_code = '$code'
  283. WHERE category_code = '$old_code' ";
  284. Database::query($sql);
  285. return true;
  286. }
  287. /**
  288. * Move a node up on display.
  289. *
  290. * @param string $code
  291. * @param int $tree_pos
  292. * @param string $parent_id
  293. *
  294. * @return bool
  295. */
  296. public static function moveNodeUp($code, $tree_pos, $parent_id)
  297. {
  298. $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
  299. $code = Database::escape_string($code);
  300. $tree_pos = (int) $tree_pos;
  301. $parent_id = Database::escape_string($parent_id);
  302. $parentIdCondition = " AND (parent_id IS NULL OR parent_id = '' )";
  303. if (!empty($parent_id)) {
  304. $parentIdCondition = " AND parent_id = '$parent_id' ";
  305. }
  306. $sql = "SELECT code,tree_pos
  307. FROM $table
  308. WHERE
  309. tree_pos < $tree_pos
  310. $parentIdCondition
  311. ORDER BY tree_pos DESC
  312. LIMIT 0,1";
  313. $result = Database::query($sql);
  314. if (!$row = Database::fetch_array($result)) {
  315. $sql = "SELECT code, tree_pos
  316. FROM $table
  317. WHERE
  318. tree_pos > $tree_pos
  319. $parentIdCondition
  320. ORDER BY tree_pos DESC
  321. LIMIT 0,1";
  322. $result2 = Database::query($sql);
  323. if (!$row = Database::fetch_array($result2)) {
  324. return false;
  325. }
  326. }
  327. $sql = "UPDATE $table
  328. SET tree_pos ='".$row['tree_pos']."'
  329. WHERE code='$code'";
  330. Database::query($sql);
  331. $sql = "UPDATE $table
  332. SET tree_pos = '$tree_pos'
  333. WHERE code= '".$row['code']."'";
  334. Database::query($sql);
  335. return true;
  336. }
  337. /**
  338. * Counts the number of children categories a category has.
  339. *
  340. * @param int $categoryId The ID of the category of which we want to count the children
  341. *
  342. * @return mixed The number of subcategories this category has
  343. */
  344. public static function courseCategoryChildrenCount($categoryId)
  345. {
  346. $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
  347. $categoryId = (int) $categoryId;
  348. $count = 0;
  349. if (empty($categoryId)) {
  350. return 0;
  351. }
  352. $sql = "SELECT id, code FROM $table
  353. WHERE parent_id = $categoryId";
  354. $result = Database::query($sql);
  355. while ($row = Database::fetch_array($result)) {
  356. $count += self::courseCategoryChildrenCount($row['id']);
  357. }
  358. $sql = "UPDATE $table SET
  359. children_count = $count
  360. WHERE id = $categoryId";
  361. Database::query($sql);
  362. return $count + 1;
  363. }
  364. /**
  365. * @param string $categoryCode
  366. *
  367. * @return array
  368. */
  369. public static function getChildren($categoryCode)
  370. {
  371. $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
  372. $categoryCode = Database::escape_string($categoryCode);
  373. $sql = "SELECT code, id FROM $table
  374. WHERE parent_id = '$categoryCode'";
  375. $result = Database::query($sql);
  376. $children = [];
  377. while ($row = Database::fetch_array($result, 'ASSOC')) {
  378. $children[] = $row;
  379. $subChildren = self::getChildren($row['code']);
  380. $children = array_merge($children, $subChildren);
  381. }
  382. return $children;
  383. }
  384. /**
  385. * @param string $categoryCode
  386. *
  387. * @return array
  388. */
  389. public static function getParents($categoryCode)
  390. {
  391. if (empty($categoryCode)) {
  392. return [];
  393. }
  394. $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
  395. $categoryCode = Database::escape_string($categoryCode);
  396. $sql = "SELECT code, parent_id
  397. FROM $table
  398. WHERE code = '$categoryCode'";
  399. $result = Database::query($sql);
  400. $children = [];
  401. while ($row = Database::fetch_array($result, 'ASSOC')) {
  402. $parent = self::getCategory($row['parent_id']);
  403. $children[] = $row;
  404. $subChildren = self::getParents($parent ? $parent['code'] : null);
  405. $children = array_merge($children, $subChildren);
  406. }
  407. return $children;
  408. }
  409. /**
  410. * @param string $categoryCode
  411. *
  412. * @return string|null
  413. */
  414. public static function getParentsToString($categoryCode)
  415. {
  416. $parents = self::getParents($categoryCode);
  417. if (!empty($parents)) {
  418. $parents = array_reverse($parents);
  419. $categories = [];
  420. foreach ($parents as $category) {
  421. $categories[] = $category['code'];
  422. }
  423. $categoriesInString = implode(' > ', $categories).' > ';
  424. return $categoriesInString;
  425. }
  426. return null;
  427. }
  428. /**
  429. * @param string $categorySource
  430. *
  431. * @return string
  432. */
  433. public static function listCategories($categorySource)
  434. {
  435. $categories = self::getCategories($categorySource);
  436. $categorySource = Security::remove_XSS($categorySource);
  437. if (count($categories) > 0) {
  438. $table = new HTML_Table(['class' => 'data_table']);
  439. $column = 0;
  440. $row = 0;
  441. $headers = [
  442. get_lang('Category'),
  443. get_lang('Sub-categories'),
  444. get_lang('Courses'),
  445. get_lang('Detail'),
  446. ];
  447. foreach ($headers as $header) {
  448. $table->setHeaderContents($row, $column, $header);
  449. $column++;
  450. }
  451. $row++;
  452. $mainUrl = api_get_path(WEB_CODE_PATH).'admin/course_category.php?category='.$categorySource;
  453. $editIcon = Display::return_icon(
  454. 'edit.png',
  455. get_lang('Edit this category'),
  456. null,
  457. ICON_SIZE_SMALL
  458. );
  459. $deleteIcon = Display::return_icon(
  460. 'delete.png',
  461. get_lang('Delete this category'),
  462. null,
  463. ICON_SIZE_SMALL
  464. );
  465. $moveIcon = Display::return_icon(
  466. 'up.png',
  467. get_lang('Up in same level'),
  468. null,
  469. ICON_SIZE_SMALL
  470. );
  471. $urlId = api_get_current_access_url_id();
  472. foreach ($categories as $category) {
  473. $editUrl = $mainUrl.'&id='.$category['code'].'&action=edit';
  474. $moveUrl = $mainUrl.'&id='.$category['code'].'&action=moveUp&tree_pos='.$category['tree_pos'];
  475. $deleteUrl = $mainUrl.'&id='.$category['code'].'&action=delete';
  476. $actions = [];
  477. if ($urlId == $category['access_url_id']) {
  478. $actions[] = Display::url($editIcon, $editUrl);
  479. $actions[] = Display::url($moveIcon, $moveUrl);
  480. $actions[] = Display::url($deleteIcon, $deleteUrl);
  481. }
  482. $url = api_get_path(WEB_CODE_PATH).'admin/course_category.php?category='.$category['code'];
  483. $title = Display::url(
  484. Display::return_icon(
  485. 'folder_document.gif',
  486. get_lang('Open this category'),
  487. null,
  488. ICON_SIZE_SMALL
  489. ).' '.$category['name'].' ('.$category['code'].')',
  490. $url
  491. );
  492. $content = [
  493. $title,
  494. $category['children_count'],
  495. $category['nbr_courses'],
  496. implode('', $actions),
  497. ];
  498. $column = 0;
  499. foreach ($content as $value) {
  500. $table->setCellContents($row, $column, $value);
  501. $column++;
  502. }
  503. $row++;
  504. }
  505. return $table->toHtml();
  506. } else {
  507. return Display::return_message(get_lang('There are no categories here'), 'warning');
  508. }
  509. }
  510. /**
  511. * @return array
  512. */
  513. public static function getCategoriesToDisplayInHomePage()
  514. {
  515. $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
  516. $sql = "SELECT name FROM $table
  517. WHERE parent_id IS NULL
  518. ORDER BY tree_pos";
  519. return Database::store_result(Database::query($sql));
  520. }
  521. /**
  522. * @param string $categoryCode
  523. *
  524. * @return array
  525. */
  526. public static function getCategoriesCanBeAddedInCourse($categoryCode)
  527. {
  528. $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
  529. $conditions = " INNER JOIN $table a ON (c.id = a.course_category_id)";
  530. $whereCondition = ' AND a.access_url_id = '.api_get_current_access_url_id();
  531. $tbl_category = Database::get_main_table(TABLE_MAIN_CATEGORY);
  532. $sql = "SELECT code, name
  533. FROM $tbl_category c
  534. $conditions
  535. WHERE (auth_course_child = 'TRUE' OR code = '".Database::escape_string($categoryCode)."')
  536. $whereCondition
  537. ORDER BY tree_pos";
  538. $res = Database::query($sql);
  539. $categories[''] = '-';
  540. while ($cat = Database::fetch_array($res)) {
  541. $categories[$cat['code']] = '('.$cat['code'].') '.$cat['name'];
  542. ksort($categories);
  543. }
  544. return $categories;
  545. }
  546. /**
  547. * @param string $category_code
  548. * @param string $searchTerm
  549. *
  550. * @return int
  551. */
  552. public static function countCoursesInCategory($category_code = '', $searchTerm = '')
  553. {
  554. $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
  555. $categoryCode = Database::escape_string($category_code);
  556. $searchTerm = Database::escape_string($searchTerm);
  557. $avoidCoursesCondition = CoursesAndSessionsCatalog::getAvoidCourseCondition();
  558. $visibilityCondition = CourseManager::getCourseVisibilitySQLCondition('course', true);
  559. $categoryFilter = '';
  560. if ($categoryCode === 'ALL') {
  561. // Nothing to do
  562. } elseif ($categoryCode === 'NONE') {
  563. $categoryFilter = ' AND category_code = "" ';
  564. } else {
  565. $categoryFilter = ' AND category_code = "'.$categoryCode.'" ';
  566. }
  567. $searchFilter = '';
  568. if (!empty($searchTerm)) {
  569. $searchFilter = ' AND (
  570. code LIKE "%'.$searchTerm.'%" OR
  571. title LIKE "%'.$searchTerm.'%" OR
  572. tutor_name LIKE "%'.$searchTerm.'%"
  573. ) ';
  574. }
  575. $urlCondition = ' access_url_id = '.api_get_current_access_url_id().' AND';
  576. $tbl_url_rel_course = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
  577. $sql = "SELECT count(*) as count
  578. FROM $tbl_course as course
  579. INNER JOIN $tbl_url_rel_course as url_rel_course
  580. ON (url_rel_course.c_id = course.id)
  581. WHERE
  582. $urlCondition
  583. course.visibility != '0' AND
  584. course.visibility != '4'
  585. $categoryFilter
  586. $searchFilter
  587. $avoidCoursesCondition
  588. $visibilityCondition
  589. ";
  590. $result = Database::query($sql);
  591. $row = Database::fetch_array($result);
  592. return (int) $row['count'];
  593. }
  594. /**
  595. * @param array $list
  596. *
  597. * @return array
  598. */
  599. public static function getCourseCategoryNotInList($list)
  600. {
  601. $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
  602. if (empty($list)) {
  603. $sql = "SELECT * FROM $table
  604. WHERE (parent_id IS NULL) ";
  605. $result = Database::query($sql);
  606. return Database::store_result($result, 'ASSOC');
  607. }
  608. $list = array_map('intval', $list);
  609. $listToString = implode("','", $list);
  610. $sql = "SELECT * FROM $table
  611. WHERE id NOT IN ('$listToString') AND (parent_id IS NULL) ";
  612. $result = Database::query($sql);
  613. return Database::store_result($result, 'ASSOC');
  614. }
  615. /**
  616. * @param string $keyword
  617. *
  618. * @return array|null
  619. */
  620. public static function searchCategoryByKeyword($keyword)
  621. {
  622. if (empty($keyword)) {
  623. return null;
  624. }
  625. $tableCategory = Database::get_main_table(TABLE_MAIN_CATEGORY);
  626. $table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE_CATEGORY);
  627. $conditions = " INNER JOIN $table a ON (c.id = a.course_category_id)";
  628. $whereCondition = " AND a.access_url_id = ".api_get_current_access_url_id();
  629. $keyword = Database::escape_string($keyword);
  630. $sql = "SELECT c.*, c.name as text
  631. FROM $tableCategory c $conditions
  632. WHERE
  633. (
  634. c.code LIKE '%$keyword%' OR name LIKE '%$keyword%'
  635. ) AND auth_course_child = 'TRUE'
  636. $whereCondition ";
  637. $result = Database::query($sql);
  638. return Database::store_result($result, 'ASSOC');
  639. }
  640. /**
  641. * Get Pagination HTML div.
  642. *
  643. * @param $pageCurrent
  644. * @param $pageLength
  645. * @param $pageTotal
  646. *
  647. * @return string
  648. */
  649. public static function getCatalogPagination($pageCurrent, $pageLength, $pageTotal)
  650. {
  651. // Start empty html
  652. $pageDiv = '';
  653. $html = '';
  654. $pageBottom = max(1, $pageCurrent - 3);
  655. $pageTop = min($pageTotal, $pageCurrent + 3);
  656. if ($pageBottom > 1) {
  657. $pageDiv .= self::getPageNumberItem(1, $pageLength);
  658. if ($pageBottom > 2) {
  659. $pageDiv .= self::getPageNumberItem(
  660. $pageBottom - 1,
  661. $pageLength,
  662. null,
  663. '...'
  664. );
  665. }
  666. }
  667. // For each page add its page button to html
  668. for ($i = $pageBottom; $i <= $pageTop; $i++) {
  669. if ($i === $pageCurrent) {
  670. $pageItemAttributes = ['class' => 'page-item active'];
  671. } else {
  672. $pageItemAttributes = ['class' => 'page-item'];
  673. }
  674. $pageDiv .= self::getPageNumberItem(
  675. $i,
  676. $pageLength,
  677. $pageItemAttributes
  678. );
  679. }
  680. // Check if current page is the last page
  681. if ($pageTop < $pageTotal) {
  682. if ($pageTop < ($pageTotal - 1)) {
  683. $pageDiv .= self::getPageNumberItem(
  684. $pageTop + 1,
  685. $pageLength,
  686. null,
  687. '...'
  688. );
  689. }
  690. $pageDiv .= self::getPageNumberItem($pageTotal, $pageLength);
  691. }
  692. // Complete pagination html
  693. $pageDiv = Display::tag('ul', $pageDiv, ['class' => 'pagination']);
  694. $html .= '<nav>'.$pageDiv.'</nav>';
  695. return $html;
  696. }
  697. /**
  698. * Return URL to course catalog.
  699. *
  700. * @param int $pageCurrent
  701. * @param int $pageLength
  702. * @param string $categoryCode
  703. * @param int $hiddenLinks
  704. * @param string $action
  705. *
  706. * @return string
  707. */
  708. public static function getCourseCategoryUrl(
  709. $pageCurrent,
  710. $pageLength,
  711. $categoryCode = null,
  712. $hiddenLinks = null,
  713. $action = null
  714. ) {
  715. $requestAction = isset($_REQUEST['action']) ? Security::remove_XSS($_REQUEST['action']) : null;
  716. $action = isset($action) ? Security::remove_XSS($action) : $requestAction;
  717. $searchTerm = isset($_REQUEST['search_term']) ? Security::remove_XSS($_REQUEST['search_term']) : null;
  718. if ($action === 'subscribe_user_with_password') {
  719. $action = 'subscribe';
  720. }
  721. $categoryCodeRequest = isset($_REQUEST['category_code']) ? Security::remove_XSS($_REQUEST['category_code']) : null;
  722. $categoryCode = isset($categoryCode) ? Security::remove_XSS($categoryCode) : $categoryCodeRequest;
  723. $hiddenLinksRequest = isset($_REQUEST['hidden_links']) ? Security::remove_XSS($_REQUEST['hidden_links']) : null;
  724. $hiddenLinks = isset($hiddenLinks) ? Security::remove_XSS($hiddenLinksRequest) : $categoryCodeRequest;
  725. // Start URL with params
  726. $pageUrl = api_get_self().
  727. '?action='.$action.
  728. '&category_code='.$categoryCode.
  729. '&hidden_links='.$hiddenLinks.
  730. '&pageCurrent='.$pageCurrent.
  731. '&pageLength='.$pageLength;
  732. switch ($action) {
  733. case 'subscribe':
  734. // for search
  735. $pageUrl .=
  736. '&search_term='.$searchTerm.
  737. '&search_course=1'.
  738. '&sec_token='.Security::getTokenFromSession();
  739. break;
  740. case 'display_courses':
  741. default:
  742. break;
  743. }
  744. return $pageUrl;
  745. }
  746. /**
  747. * Get li HTML of page number.
  748. *
  749. * @param $pageNumber
  750. * @param $pageLength
  751. * @param array $liAttributes
  752. * @param string $content
  753. *
  754. * @return string
  755. */
  756. public static function getPageNumberItem(
  757. $pageNumber,
  758. $pageLength,
  759. $liAttributes = [],
  760. $content = ''
  761. ) {
  762. // Get page URL
  763. $url = self::getCourseCategoryUrl(
  764. $pageNumber,
  765. $pageLength
  766. );
  767. // If is current page ('active' class) clear URL
  768. if (isset($liAttributes) && is_array($liAttributes) && isset($liAttributes['class'])) {
  769. if (strpos('active', $liAttributes['class']) !== false) {
  770. $url = '';
  771. }
  772. }
  773. $content = !empty($content) ? $content : $pageNumber;
  774. return Display::tag(
  775. 'li',
  776. Display::url(
  777. $content,
  778. $url,
  779. ['class' => 'page-link']
  780. ),
  781. $liAttributes
  782. );
  783. }
  784. /**
  785. * Return the name tool by action.
  786. *
  787. * @param string $action
  788. *
  789. * @return string
  790. */
  791. public static function getCourseCatalogNameTools($action)
  792. {
  793. $nameTools = get_lang('My courses');
  794. if (empty($action)) {
  795. return $nameTools; //should never happen
  796. }
  797. switch ($action) {
  798. case 'subscribe':
  799. case 'subscribe_user_with_password':
  800. case 'display_random_courses':
  801. case 'display_courses':
  802. $nameTools = get_lang('Courses catalog');
  803. break;
  804. case 'display_sessions':
  805. $nameTools = get_lang('Course sessions');
  806. break;
  807. default:
  808. // Nothing to do
  809. break;
  810. }
  811. return $nameTools;
  812. }
  813. /**
  814. * Save image for a course category.
  815. *
  816. * @param int $categoryId Course category ID
  817. * @param array $fileData File data from $_FILES
  818. */
  819. public static function saveImage($categoryId, $fileData)
  820. {
  821. $categoryInfo = self::getCategoryById($categoryId);
  822. if (empty($categoryInfo)) {
  823. return;
  824. }
  825. if (!empty($fileData['error'])) {
  826. return;
  827. }
  828. $extension = getextension($fileData['name']);
  829. $dirName = 'course_category/';
  830. $fileDir = api_get_path(SYS_UPLOAD_PATH).$dirName;
  831. $fileName = "cc_$categoryId.{$extension[0]}";
  832. if (!file_exists($fileDir)) {
  833. mkdir($fileDir, api_get_permissions_for_new_directories(), true);
  834. }
  835. $image = new Image($fileData['tmp_name']);
  836. $image->send_image($fileDir.$fileName);
  837. $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
  838. Database::update(
  839. $table,
  840. ['image' => $dirName.$fileName],
  841. ['id = ?' => $categoryId]
  842. );
  843. }
  844. /**
  845. * @param $categoryId
  846. * @param string $description
  847. *
  848. * @return string
  849. */
  850. public static function saveDescription($categoryId, $description)
  851. {
  852. $categoryInfo = self::getCategoryById($categoryId);
  853. if (empty($categoryInfo)) {
  854. return false;
  855. }
  856. $table = Database::get_main_table(TABLE_MAIN_CATEGORY);
  857. Database::update(
  858. $table,
  859. ['description' => $description],
  860. ['id = ?' => $categoryId]
  861. );
  862. return true;
  863. }
  864. }