courses_categories.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * View (MVC patter) for courses categories.
  5. *
  6. * @author Christian Fasanando <christian1827@gmail.com> - Beeznest
  7. *
  8. * @package chamilo.auth
  9. */
  10. if (isset($_REQUEST['action']) && Security::remove_XSS($_REQUEST['action']) !== 'subscribe') {
  11. $stok = Security::get_token();
  12. } else {
  13. $stok = Security::getTokenFromSession();
  14. }
  15. $action = !empty($_REQUEST['action']) ? Security::remove_XSS($_REQUEST['action']) : 'display_courses';
  16. global $actions;
  17. $action = in_array($action, $actions) ? $action : 'display_courses';
  18. $showCourses = CoursesAndSessionsCatalog::showCourses();
  19. $showSessions = CoursesAndSessionsCatalog::showSessions();
  20. $pageCurrent = isset($pageCurrent) ? $pageCurrent : isset($_GET['pageCurrent']) ? (int) $_GET['pageCurrent'] : 1;
  21. $pageLength = isset($pageLength) ? $pageLength : isset($_GET['pageLength']) ? (int) $_GET['pageLength'] : CoursesAndSessionsCatalog::PAGE_LENGTH;
  22. $pageTotal = (int) ceil((int) $countCoursesInCategory / $pageLength);
  23. $cataloguePagination = $pageTotal > 1 ? CourseCategory::getCatalogPagination($pageCurrent, $pageLength, $pageTotal) : '';
  24. $searchTerm = isset($_REQUEST['search_term']) ? Security::remove_XSS($_REQUEST['search_term']) : '';
  25. $codeType = isset($_REQUEST['category_code']) ? Security::remove_XSS($_REQUEST['category_code']) : '';
  26. $date = date('Y-m-d');
  27. if ($showSessions && isset($_POST['date'])) {
  28. $date = $_POST['date'];
  29. }
  30. $userInfo = api_get_user_info();
  31. $code = isset($code) ? $code : null;
  32. ?>
  33. <script>
  34. $(function() {
  35. $('.star-rating li a').on('click', function(event) {
  36. var id = $(this).parents('ul').attr('id');
  37. $('#vote_label2_' + id).html("<?php echo get_lang('Loading'); ?>");
  38. $.ajax({
  39. url: $(this).attr('data-link'),
  40. success: function(data) {
  41. $("#rating_wrapper_"+id).html(data);
  42. if (data == 'added') {
  43. //$('#vote_label2_' + id).html("{'Saved'|get_lang}");
  44. }
  45. if (data == 'updated') {
  46. //$('#vote_label2_' + id).html("{'Saved'|get_lang}");
  47. }
  48. }
  49. });
  50. });
  51. var getSessionId = function (el) {
  52. var parts = el.id.split('_');
  53. return parseInt(parts[1], 10);
  54. };
  55. <?php if ($showSessions) {
  56. ?>
  57. $('#date').datepicker({
  58. dateFormat: 'yy-mm-dd'
  59. });
  60. <?php
  61. } ?>
  62. });
  63. </script>
  64. <?php
  65. echo '<div class="row">
  66. <div class="col-md-12">
  67. <h2 class="title-courses">'.get_lang('CourseManagement').'</h2>
  68. <div class="search-courses">
  69. <div class="row">';
  70. if ($showCourses) {
  71. echo '<div class="col-md-'.($showSessions ? '4' : '6').'">';
  72. if (!isset($_GET['hidden_links']) || intval($_GET['hidden_links']) != 1) {
  73. ?>
  74. <form method="post"
  75. action="<?php echo CourseCategory::getCourseCategoryUrl(1, $pageLength, 'ALL', 0, 'subscribe'); ?>">
  76. <input type="hidden" name="sec_token" value="<?php echo $stok; ?>">
  77. <input type="hidden" name="search_course" value="1"/>
  78. <label><?php echo get_lang('Search'); ?></label>
  79. <div class="input-group">
  80. <input class="form-control" type="text" name="search_term"
  81. value="<?php echo empty($_POST['search_term']) ? '' : api_htmlentities($searchTerm); ?>"/>
  82. <div class="input-group-btn">
  83. <button class="btn btn-default" type="submit">
  84. <em class="fa fa-search"></em> <?php echo get_lang('Search'); ?>
  85. </button>
  86. </div>
  87. </div>
  88. </form>
  89. <?php
  90. }
  91. echo '</div>';
  92. echo '<div class="col-md-'.($showSessions ? '4' : '6').'">';
  93. $listCategories = CoursesAndSessionsCatalog::getCourseCategoriesTree();
  94. $categoriesSelect = getOptionSelect($listCategories, $codeType);
  95. $webAction = api_get_path(WEB_CODE_PATH).'auth/courses.php';
  96. $form = '<form action="'.$webAction.'" method="GET">';
  97. $form .= '<input type="hidden" name="action" value="'.$action.'">';
  98. $form .= '<input type="hidden" name="pageCurrent" value="'.$pageCurrent.'">';
  99. $form .= '<input type="hidden" name="pageLength" value="'.$pageLength.'">';
  100. $form .= '<div class="form-group">';
  101. $form .= '<label>'.get_lang('CourseCategories').'</label>';
  102. $form .= $categoriesSelect;
  103. $form .= '</div>';
  104. $form .= '</form>';
  105. echo $form;
  106. echo '</div>';
  107. }
  108. if ($showSessions) {
  109. $url = CourseCategory::getCourseCategoryUrl(1, $pageLength, null, 0, 'display_sessions');
  110. echo '<div class="col-md-4">
  111. <div class="return-catalog">
  112. <a class="btn btn-default btn-lg btn-block"
  113. href="'.$url.'">
  114. <em class="fa fa-arrow-right"></em>'.get_lang('SessionList').'
  115. </a>
  116. </div>
  117. </div>
  118. ';
  119. }
  120. echo '</div></div></div></div>';
  121. if ($showCourses && $action != 'display_sessions') {
  122. if (!empty($message)) {
  123. echo Display::return_message($message, 'confirmation', false);
  124. }
  125. if (!empty($error)) {
  126. echo Display::return_message($error, 'error', false);
  127. }
  128. if (!empty($content)) {
  129. echo $content;
  130. }
  131. if (!empty($searchTerm)) {
  132. echo "<p><strong>".get_lang('SearchResultsFor')." ".$searchTerm."</strong><br />";
  133. }
  134. $showTeacher = api_get_setting('display_teacher_in_courselist') === 'true';
  135. $ajax_url = api_get_path(WEB_AJAX_PATH).'course.ajax.php?a=add_course_vote';
  136. $user_id = api_get_user_id();
  137. $categoryListFromDatabase = CourseCategory::getCategories();
  138. $categoryList = [];
  139. if (!empty($categoryListFromDatabase)) {
  140. foreach ($categoryListFromDatabase as $categoryItem) {
  141. $categoryList[$categoryItem['code']] = $categoryItem['name'];
  142. }
  143. }
  144. if (!empty($browse_courses_in_category)) {
  145. echo '<div class="grid-courses row">';
  146. foreach ($browse_courses_in_category as $course) {
  147. $course_hidden = $course['visibility'] == COURSE_VISIBILITY_HIDDEN;
  148. if ($course_hidden) {
  149. continue;
  150. }
  151. $userRegisteredInCourse = CourseManager::is_user_subscribed_in_course($user_id, $course['code']);
  152. $userRegisteredInCourseAsTeacher = CourseManager::is_course_teacher($user_id, $course['code']);
  153. $userRegistered = $userRegisteredInCourse && $userRegisteredInCourseAsTeacher;
  154. $course_public = $course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD;
  155. $course_open = $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM;
  156. $course_private = $course['visibility'] == COURSE_VISIBILITY_REGISTERED;
  157. $course_closed = $course['visibility'] == COURSE_VISIBILITY_CLOSED;
  158. $course_subscribe_allowed = $course['subscribe'] == 1;
  159. $course_unsubscribe_allowed = $course['unsubscribe'] == 1;
  160. $count_connections = $course['count_connections'];
  161. $creation_date = substr($course['creation_date'], 0, 10);
  162. // display the course bloc
  163. $html = '<div class="col-xs-12 col-sm-6 col-md-4"><div class="items items-courses">';
  164. $course['category_title'] = '';
  165. if (isset($course['category'])) {
  166. $course['category_title'] = isset($categoryList[$course['category']]) ? $categoryList[$course['category']] : '';
  167. }
  168. // Display thumbnail
  169. $html .= returnThumbnail($course, $userRegistered);
  170. $separator = null;
  171. $subscribeButton = return_register_button($course, $stok, $code, $searchTerm);
  172. // Start buy course validation
  173. // display the course price and buy button if the buycourses plugin is enabled and this course is configured
  174. $plugin = BuyCoursesPlugin::create();
  175. $isThisCourseInSale = $plugin->buyCoursesForGridCatalogValidator(
  176. $course['real_id'],
  177. BuyCoursesPlugin::PRODUCT_TYPE_COURSE
  178. );
  179. if ($isThisCourseInSale) {
  180. // set the Price label
  181. $separator = $isThisCourseInSale['html'];
  182. // set the Buy button instead register.
  183. if ($isThisCourseInSale['verificator']) {
  184. $subscribeButton = $plugin->returnBuyCourseButton(
  185. $course['real_id'],
  186. BuyCoursesPlugin::PRODUCT_TYPE_COURSE
  187. );
  188. }
  189. }
  190. // end buy course validation
  191. // display course title and button bloc
  192. $html .= '<div class="description">';
  193. $html .= return_title($course, $userRegisteredInCourse);
  194. if ($showTeacher) {
  195. $html .= return_teacher($course);
  196. }
  197. // display button line
  198. $html .= '<div class="toolbar row">';
  199. $html .= $separator ? '<div class="col-sm-4">'.$separator.'</div>' : '';
  200. $html .= '<div class="col-sm-8">';
  201. // if user registered as student
  202. if ($userRegisteredInCourse) {
  203. $html .= return_already_registered_label('student');
  204. if (!$course_closed) {
  205. if ($course_unsubscribe_allowed) {
  206. $html .= return_unregister_button($course, $stok, $searchTerm, $code);
  207. }
  208. }
  209. } elseif ($userRegisteredInCourseAsTeacher) {
  210. // if user registered as teacher
  211. if ($course_unsubscribe_allowed) {
  212. $html .= return_unregister_button($course, $stok, $searchTerm, $code);
  213. }
  214. } else {
  215. // if user not registered in the course
  216. if (!$course_closed) {
  217. if (!$course_private) {
  218. if ($course_subscribe_allowed) {
  219. $html .= $subscribeButton;
  220. }
  221. }
  222. }
  223. }
  224. $html .= '</div>';
  225. $html .= '</div>';
  226. $html .= '</div>';
  227. $html .= '</div>';
  228. $html .= '</div>';
  229. echo $html;
  230. }
  231. echo '</div>';
  232. } else {
  233. if (!isset($_REQUEST['subscribe_user_with_password']) &&
  234. !isset($_REQUEST['subscribe_course'])
  235. ) {
  236. echo Display::return_message(
  237. get_lang('ThereAreNoCoursesInThisCategory'),
  238. 'warning'
  239. );
  240. }
  241. }
  242. }
  243. echo '<div class="col-md-12">';
  244. echo $cataloguePagination;
  245. echo '</div>';
  246. function getOptionSelect($categories, $codeType)
  247. {
  248. $html = '';
  249. $html .= '<select name="category_code" onchange="submit();" class="selectpicker form-control">';
  250. foreach ($categories as $category) {
  251. $categoryCode = Security::remove_XSS($category['code']);
  252. $categoryName = Security::remove_XSS($category['name']);
  253. $countCourse = (int) $category['number_courses'];
  254. $level = $category['level'];
  255. if (empty($countCourse)) {
  256. continue;
  257. }
  258. if ($level > 0) {
  259. $separate = str_repeat('--', $level);
  260. } else {
  261. $separate = '';
  262. }
  263. $html .= '<option '.($categoryCode == $codeType ? 'selected="selected" ' : '')
  264. .' value="'.$categoryCode.'">'.$separate.' '.$categoryName.' ('.$countCourse.') </option>';
  265. }
  266. $html .= '</select>';
  267. return $html;
  268. }
  269. /**
  270. * Display the course catalog image of a course.
  271. *
  272. * @param array $course
  273. * @param bool $registeredUser
  274. *
  275. * @return string HTML string
  276. */
  277. function returnThumbnail($course, $registeredUser)
  278. {
  279. $html = '';
  280. $title = cut($course['title'], 70);
  281. //$linkCourse = api_get_course_url($course['code']);
  282. $linkCourse = api_get_path(WEB_PATH).'course/'.$course['real_id'].'/about';
  283. // course path
  284. $course_path = api_get_path(SYS_COURSE_PATH).$course['directory'];
  285. if (file_exists($course_path.'/course-pic.png')) {
  286. // redimensioned image 85x85
  287. $courseMediumImage = api_get_path(WEB_COURSE_PATH).$course['directory'].'/course-pic.png';
  288. } else {
  289. // without picture
  290. $courseMediumImage = Display::return_icon(
  291. 'session_default.png',
  292. null,
  293. null,
  294. null,
  295. null,
  296. true
  297. );
  298. }
  299. $html .= '<div class="image">';
  300. $html .= '<a href="'.$linkCourse.'" title="'.$course['title'].'">'
  301. .'<img class="img-responsive" src="'.$courseMediumImage.'" '
  302. .'alt="'.api_htmlentities($title).'"/></a>';
  303. $categoryTitle = isset($course['category_title']) ? $course['category_title'] : '';
  304. if (!empty($categoryTitle)) {
  305. $html .= '<span class="category">'.$categoryTitle.'</span>';
  306. $html .= '<div class="cribbon"></div>';
  307. }
  308. $html .= '<div class="user-actions">';
  309. $html .= CourseManager::returnDescriptionButton($course);
  310. $html .= '</div></div>';
  311. return $html;
  312. }
  313. /**
  314. * @param array $courseInfo
  315. *
  316. * @return string
  317. */
  318. function return_teacher($courseInfo)
  319. {
  320. $teachers = CourseManager::getTeachersFromCourse($courseInfo['real_id']);
  321. $length = count($teachers);
  322. if (!$length) {
  323. return '';
  324. }
  325. $html = '<div class="block-author">';
  326. if ($length > 6) {
  327. $html .= '<a
  328. id="plist"
  329. data-trigger="focus"
  330. tabindex="0" role="button"
  331. class="btn btn-default panel_popover"
  332. data-toggle="popover"
  333. title="'.addslashes(get_lang('CourseTeachers')).'"
  334. data-html="true"
  335. >
  336. <i class="fa fa-graduation-cap" aria-hidden="true"></i>
  337. </a>';
  338. $html .= '<div id="popover-content-plist" class="hide">';
  339. foreach ($teachers as $value) {
  340. $name = $value['firstname'].' '.$value['lastname'];
  341. $html .= '<div class="popover-teacher">';
  342. $html .= '<a href="'.$value['url'].'" class="ajax" data-title="'.$name.'" title="'.$name.'">
  343. <img src="'.$value['avatar'].'" title="'.$name.'" alt="'.get_lang('UserPicture').'"/></a>';
  344. $html .= '<div class="teachers-details"><h5>
  345. <a href="'.$value['url'].'" class="ajax" data-title="'.$name.'" title="'.$name.'">'
  346. .$name.'</a></h5></div>';
  347. $html .= '</div>';
  348. }
  349. $html .= '</div>';
  350. } else {
  351. foreach ($teachers as $value) {
  352. $name = $value['firstname'].' '.$value['lastname'];
  353. if ($length > 2) {
  354. $html .= '<a href="'.$value['url'].'" class="ajax" data-title="'.$name.'" title="'.$name.'">
  355. <img src="'.$value['avatar'].'" title="'.$name.'" alt="'.get_lang('UserPicture').'"/></a>';
  356. } else {
  357. $html .= '<a href="'.$value['url'].'" class="ajax" data-title="'.$name.'" title="'.$name.'">
  358. <img src="'.$value['avatar'].'" title="'.$name.'" alt="'.get_lang('UserPicture').'"/></a>';
  359. $html .= '<div class="teachers-details"><h5>
  360. <a href="'.$value['url'].'" class="ajax" data-title="'.$name.'">'
  361. .$name.'</a></h5><p>'.get_lang('Teacher').'</p></div>';
  362. }
  363. }
  364. }
  365. $html .= '</div>';
  366. return $html;
  367. }
  368. /**
  369. * Display the title of a course in course catalog.
  370. *
  371. * @param array $course
  372. * @param bool $registeredUser
  373. *
  374. * @return string HTML string
  375. */
  376. function return_title($course, $registeredUser)
  377. {
  378. //$linkCourse = api_get_course_url($course['code']);
  379. $linkCourse = api_get_path(WEB_PATH).'course/'.$course['real_id'].'/about';
  380. $html = '<div class="block-title"><h4 class="title">';
  381. $html .= '<a title="'.$course['title'].'" href="'.$linkCourse.'">'.$course['title'].'</a>';
  382. $html .= '</h4></div>';
  383. if (api_get_configuration_value('hide_course_rating') === false) {
  384. $ajax_url = api_get_path(WEB_AJAX_PATH).'course.ajax.php?a=add_course_vote';
  385. $rating = Display::return_rating_system(
  386. 'star_'.$course['real_id'],
  387. $ajax_url.'&course_id='.$course['real_id'],
  388. $course['point_info']
  389. );
  390. $html .= '<div class="ranking">'.$rating.'</div>';
  391. }
  392. return $html;
  393. }
  394. /**
  395. * Display the goto course button of a course in the course catalog.
  396. *
  397. * @param $course
  398. *
  399. * @return string HTML string
  400. */
  401. function return_goto_button($course)
  402. {
  403. $title = get_lang('GoToCourse');
  404. $html = Display::url(
  405. Display::returnFontAwesomeIcon('share'),
  406. api_get_course_url($course['code']),
  407. [
  408. 'class' => 'btn btn-default btn-sm',
  409. 'title' => $title,
  410. 'aria-label' => $title,
  411. ]
  412. );
  413. return $html.PHP_EOL;
  414. }
  415. /**
  416. * Display the already registerd text in a course in the course catalog.
  417. *
  418. * @param $in_status
  419. *
  420. * @return string HTML string
  421. */
  422. function return_already_registered_label($in_status)
  423. {
  424. $icon = '<em class="fa fa-check"></em>';
  425. $title = get_lang("YouAreATeacherOfThisCourse");
  426. if ($in_status == 'student') {
  427. $icon = '<em class="fa fa-check"></em>';
  428. $title = get_lang("AlreadySubscribed");
  429. }
  430. $html = Display::tag(
  431. 'span',
  432. $icon.' '.$title,
  433. [
  434. 'id' => 'register',
  435. 'class' => 'label-subscribed text-success',
  436. 'title' => $title,
  437. 'aria-label' => $title,
  438. ]
  439. );
  440. return $html.PHP_EOL;
  441. }
  442. /**
  443. * Display the register button of a course in the course catalog.
  444. *
  445. * @param $course
  446. * @param $stok
  447. * @param $code
  448. * @param $search_term
  449. *
  450. * @return string
  451. */
  452. function return_register_button($course, $stok, $code, $search_term)
  453. {
  454. $title = get_lang('Subscribe');
  455. $action = 'subscribe_course';
  456. if (!empty($course['registration_code'])) {
  457. $action = 'subscribe_course_validation';
  458. }
  459. $html = Display::url(
  460. Display::returnFontAwesomeIcon('check').' '.$title,
  461. api_get_self().'?action='.$action.'&sec_token='.$stok.
  462. '&subscribe_course='.$course['code'].'&search_term='.$search_term.'&category_code='.$code,
  463. ['class' => 'btn btn-success btn-sm', 'title' => $title, 'aria-label' => $title]
  464. );
  465. return $html;
  466. }
  467. /**
  468. * Display the unregister button of a course in the course catalog.
  469. *
  470. * @param $course
  471. * @param $stok
  472. * @param $search_term
  473. * @param $code
  474. *
  475. * @return string
  476. */
  477. function return_unregister_button($course, $stok, $search_term, $code)
  478. {
  479. $title = get_lang('Unsubscription');
  480. $html = Display::url(
  481. Display::returnFontAwesomeIcon('sign-in').' '.$title,
  482. api_get_self().'?action=unsubscribe&sec_token='.$stok
  483. .'&unsubscribe='.$course['code'].'&search_term='.$search_term.'&category_code='.$code,
  484. ['class' => 'btn btn-danger btn-sm', 'title' => $title, 'aria-label' => $title]
  485. );
  486. return $html;
  487. }