courses_categories.php 20 KB

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