courses_categories.php 19 KB

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