course_category.lib.php 32 KB

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