From bb78e5e3033f4e79cdbc1b2e9e4ca9798e56dbc4 Mon Sep 17 00:00:00 2001 From: Julio Montoya Date: Tue, 31 Mar 2020 09:46:14 +0200 Subject: [PATCH] Admin: Add configuration setting 'allow_course_extra_field_in_catalog' Add course extra fields filters in the course catalog BT#16817 --- main/auth/courses.php | 350 ++- main/auth/layout.php | 19 - main/auth/sort_my_courses.php | 5 +- .../lib/CoursesAndSessionsCatalog.class.php | 421 ++- main/inc/lib/auth.lib.php | 97 +- main/inc/lib/course.lib.php | 71 +- main/inc/lib/course_category.lib.php | 230 +- main/inc/lib/userportal.lib.php | 2677 +++++++++-------- main/install/configuration.dist.php | 3 + .../default/catalog/course_catalog.tpl | 29 + .../default/catalog/course_item_catalog.tpl | 82 + .../{auth => catalog}/session_catalog.tpl | 1 + 12 files changed, 2092 insertions(+), 1893 deletions(-) delete mode 100755 main/auth/layout.php create mode 100644 main/template/default/catalog/course_catalog.tpl create mode 100644 main/template/default/catalog/course_item_catalog.tpl rename main/template/default/{auth => catalog}/session_catalog.tpl (99%) diff --git a/main/auth/courses.php b/main/auth/courses.php index 97787ead78..7310ccf9c3 100755 --- a/main/auth/courses.php +++ b/main/auth/courses.php @@ -17,14 +17,16 @@ $limit = CoursesAndSessionsCatalog::getLimitArray(); // Section for the tabs. $this_section = SECTION_CATALOG; -if (api_get_setting('course_catalog_published') !== 'true') { +if ('true' !== api_get_setting('course_catalog_published')) { // Access rights: anonymous users can't do anything useful here. api_block_anonymous_users(); } +$allowExtraFields = api_get_configuration_value('allow_course_extra_field_in_catalog'); + // For students $userCanViewPage = true; -if (api_get_setting('allow_students_to_browse_courses') === 'false') { +if ('false' === api_get_setting('allow_students_to_browse_courses')) { $userCanViewPage = false; } @@ -35,7 +37,9 @@ if (api_is_platform_admin() || api_is_course_admin() || api_is_allowed_to_create $defaultAction = CoursesAndSessionsCatalog::is(CATALOG_SESSIONS) ? 'display_sessions' : 'display_courses'; $action = isset($_REQUEST['action']) ? Security::remove_XSS($_REQUEST['action']) : $defaultAction; -$categoryCode = isset($_GET['category_code']) && !empty($_GET['category_code']) ? $_GET['category_code'] : 'ALL'; +$categoryCode = isset($_REQUEST['category_code']) && !empty($_REQUEST['category_code']) ? Security::remove_XSS( + $_REQUEST['category_code'] +) : 'ALL'; $searchTerm = isset($_REQUEST['search_term']) ? Security::remove_XSS($_REQUEST['search_term']) : ''; $nameTools = CourseCategory::getCourseCatalogNameTools($action); @@ -138,42 +142,129 @@ switch ($action) { if (!$userCanViewPage) { api_not_allowed(true); } + $listCategories = CoursesAndSessionsCatalog::getCourseCategoriesTree(); - $countCoursesInCategory = CourseCategory::countCoursesInCategory($categoryCode, $searchTerm); - if ($action === 'display_random_courses') { + + $form = new FormValidator('search', 'get', '', null, null, FormValidator::LAYOUT_BOX); + $form->addHidden('action', 'search_course'); + $form->addText('search_term', get_lang('Title')); + + $jqueryReadyContent = ''; + if ($allowExtraFields) { + $extraField = new ExtraField('course'); + $returnParams = $extraField->addElements($form, null, [], true); + $jqueryReadyContent = $returnParams['jquery_ready_content']; + } + + if ('display_random_courses' === $action) { // Random value is used instead limit filter - $browse_courses_in_category = CoursesAndSessionsCatalog::getCoursesInCategory(null, 12); - $countCoursesInCategory = count($data['browse_courses_in_category']); - } elseif($action === 'search_course' && $categoryCode !== 'ALL') { - $browse_courses_in_category = CoursesAndSessionsCatalog::search_courses( - $searchTerm, - $limit - ); - $countCoursesInCategory = CourseCategory::countCoursesInCategory('ALL', $searchTerm); + $courses = CoursesAndSessionsCatalog::getCoursesInCategory(null, 12); + $countCoursesInCategory = count($courses); + } elseif ('search_course' === $action) { + $values = $_REQUEST; + + if (!empty($values) && $form->hasElement('extra_tags')) { + $tagElement = $form->getElement('extra_tags'); + if (isset($values['extra_tags']) && !empty($values['extra_tags'])) { + + $tags = []; + foreach ($values['extra_tags'] as $tag) { + $tag = Security::remove_XSS($tag); + $tags[] = $tag; + $tagElement->addOption( + $tag, + $tag + ); + } + $form->setDefaults( + [ + 'extra_tags' => $tags, + ] + ); + } + } + + $conditions = []; + $fields = []; + + if ($allowExtraFields) { + // Parse params. + foreach ($values as $key => $value) { + if (substr($key, 0, 6) !== 'extra_' && substr($key, 0, 7) !== '_extra_') { + continue; + } + if (!empty($value)) { + $fields[$key] = $value; + } + } + + $extraFields = $extraField->get_all(['visible_to_self = ? AND filter = ?' => [1, 1]], 'option_order'); + $extraFields = array_column($extraFields, 'variable'); + $filter = new stdClass(); + foreach ($fields as $variable => $col) { + if (isset($values[$variable]) && !empty($values[$variable]) && + in_array(str_replace('extra_', '', $variable), $extraFields) + ) { + $rule = new stdClass(); + $rule->field = $variable; + $rule->op = 'in'; + $data = $col; + if (is_array($data) && array_key_exists($variable, $data)) { + $data = $col; + } + $rule->data = $data; + $filter->rules[] = $rule; + $filter->groupOp = 'AND'; + } + } + $result = $extraField->getExtraFieldRules($filter); + $conditionArray = $result['condition_array']; + + $whereCondition = ''; + $extraCondition = ''; + if (!empty($conditionArray)) { + $extraCondition = ' ( '; + $extraCondition .= implode(' AND ', $conditionArray); + $extraCondition .= ' ) '; + } + $whereCondition .= $extraCondition; + $options = ['where' => $whereCondition, 'extra' => $result['extra_fields']]; + $conditions = $extraField->parseConditions($options, 'course'); + } + + $courses = CoursesAndSessionsCatalog::searchCourses($searchTerm, $limit, false, $conditions); + $countCoursesInCategory = CourseCategory::countCoursesInCategory('ALL', $searchTerm, true, $conditions); } else { if (!isset($categoryCode)) { $categoryCode = $listCategories['ALL']['code']; // by default first category } - $browse_courses_in_category = CoursesAndSessionsCatalog::getCoursesInCategory($categoryCode, null, $limit); + $courses = CoursesAndSessionsCatalog::getCoursesInCategory($categoryCode, null, $limit); + $countCoursesInCategory = CourseCategory::countCoursesInCategory($categoryCode, $searchTerm); } - $list_categories = $listCategories; - $code = Security::remove_XSS($categoryCode); + $showCourses = CoursesAndSessionsCatalog::showCourses(); + $showSessions = CoursesAndSessionsCatalog::showSessions(); + $pageCurrent = isset($_GET['pageCurrent']) ? (int) $_GET['pageCurrent'] : 1; + $pageLength = isset($_GET['pageLength']) ? (int) $_GET['pageLength'] : CoursesAndSessionsCatalog::PAGE_LENGTH; + $pageTotal = (int) ceil($countCoursesInCategory / $pageLength); + + $url = CoursesAndSessionsCatalog::getCatalogUrl(1, $pageLength, 'ALL', 0, 'search_course', $fields); + $form->setAttribute('action', $url); // getting all the courses to which the user is subscribed to - $user_courses = $auth->get_courses_of_user($userId); + $user_courses = CourseManager::getCoursesByUserCourseCategory($userId); $user_coursecodes = []; // we need only the course codes as these will be used to match against the courses of the category - if ($user_courses != '') { + if ('' != $user_courses) { foreach ($user_courses as $key => $value) { $user_coursecodes[] = $value['code']; } } if (api_is_drh()) { - $courses = CourseManager::get_courses_followed_by_drh($userId); - foreach ($courses as $course) { + $coursesDrh = CourseManager::get_courses_followed_by_drh($userId); + foreach ($coursesDrh as $course) { $user_coursecodes[] = $course['code']; } } @@ -184,27 +275,22 @@ switch ($action) { $catalogShowCoursesSessions = $showCoursesSessions; } - $showCourses = CoursesAndSessionsCatalog::showCourses(); - $showSessions = CoursesAndSessionsCatalog::showSessions(); - $pageCurrent = isset($_GET['pageCurrent']) ? (int) $_GET['pageCurrent'] : 1; - $pageLength = isset($_GET['pageLength']) ? (int) $_GET['pageLength'] : CoursesAndSessionsCatalog::PAGE_LENGTH; - $pageTotal = (int) ceil($countCoursesInCategory / $pageLength); $catalogPagination = ''; if ($pageTotal > 1) { - $catalogPagination = CourseCategory::getCatalogPagination( + $catalogPagination = CoursesAndSessionsCatalog::getCatalogPagination( $pageCurrent, $pageLength, $pageTotal, $categoryCode, - $action + $action, + $fields ); } - $date = date('Y-m-d'); + /*$date = date('Y-m-d'); if ($showSessions && isset($_POST['date'])) { $date = $_POST['date']; - } + }*/ $userInfo = api_get_user_info(); - $code = isset($code) ? $code : null; $extraDate = ''; if ($showSessions) { @@ -246,32 +332,26 @@ switch ($action) {
'; if ($showCourses) { $content .= '
'; - if (!isset($_GET['hidden_links']) || intval($_GET['hidden_links']) != 1) { - $content .= ' -
- - -
- -
- -
-
-
'; + if (!isset($_GET['hidden_links']) || 1 != intval($_GET['hidden_links'])) { + $htmlHeadXtra[] = ''; + + $form->addButtonSearch(get_lang('Search')); + $content .= $form->returnForm(); } $content .= '
'; $content .= '
'; - $listCategories = CoursesAndSessionsCatalog::getCourseCategoriesTree(); + //$listCategories = CoursesAndSessionsCatalog::getCourseCategoriesTree(); $categoriesSelect = CoursesAndSessionsCatalog::getOptionSelect($listCategories, $categoryCode); $webAction = api_get_path(WEB_CODE_PATH).'auth/courses.php'; + $form = '
'; - $form .= ''; + $form .= ''; $form .= ''; $form .= ''; $form .= '
'; @@ -287,10 +367,10 @@ switch ($action) { if ($showCourses) { if (!empty($searchTerm)) { - $content .= "

".get_lang('SearchResultsFor')." ".$searchTerm."
"; + $content .= '

'.get_lang('SearchResultsFor').' '.$searchTerm.'
'; } - $showTeacher = api_get_setting('display_teacher_in_courselist') === 'true'; + $showTeacher = 'true' === api_get_setting('display_teacher_in_courselist'); $ajax_url = api_get_path(WEB_AJAX_PATH).'course.ajax.php?a=add_course_vote'; $user_id = api_get_user_id(); $categoryListFromDatabase = CourseCategory::getAllCategories(); @@ -302,121 +382,196 @@ switch ($action) { } } - if (!empty($browse_courses_in_category)) { - $content .= '

'; - foreach ($browse_courses_in_category as $course) { - $course_hidden = $course['visibility'] == COURSE_VISIBILITY_HIDDEN; + if ($allowExtraFields) { + $extraFieldValues = new ExtraFieldValue('course'); + $em = Database::getManager(); + $fieldsRepo = $em->getRepository('ChamiloCoreBundle:ExtraField'); + $fieldTagsRepo = $em->getRepository('ChamiloCoreBundle:ExtraFieldRelTag'); + + $tagField = $fieldsRepo->findOneBy( + [ + 'extraFieldType' => \Chamilo\CoreBundle\Entity\ExtraField::COURSE_FIELD_TYPE, + 'variable' => 'tags', + ] + ); + } - if ($course_hidden) { + $courseUrl = api_get_path(WEB_COURSE_PATH); + $hideRating = api_get_configuration_value('hide_course_rating'); + if (!empty($courses)) { + foreach ($courses as &$course) { + $courseId = $course['real_id']; + if (COURSE_VISIBILITY_HIDDEN == $course['visibility']) { continue; } + $courseTags = []; + if ($allowExtraFields && !is_null($tagField)) { + $courseTags = $fieldTagsRepo->getTags($tagField, $courseId); + } $userRegisteredInCourse = CourseManager::is_user_subscribed_in_course($user_id, $course['code']); $userRegisteredInCourseAsTeacher = CourseManager::is_course_teacher($user_id, $course['code']); $userRegistered = $userRegisteredInCourse && $userRegisteredInCourseAsTeacher; - $course_public = $course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD; - $course_open = $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM; - $course_private = $course['visibility'] == COURSE_VISIBILITY_REGISTERED; - $course_closed = $course['visibility'] == COURSE_VISIBILITY_CLOSED; - - $course_subscribe_allowed = $course['subscribe'] == 1; - $course_unsubscribe_allowed = $course['unsubscribe'] == 1; + $course_public = COURSE_VISIBILITY_OPEN_WORLD == $course['visibility']; + $course_open = COURSE_VISIBILITY_OPEN_PLATFORM == $course['visibility']; + $course_private = COURSE_VISIBILITY_REGISTERED == $course['visibility']; + $courseClosed = COURSE_VISIBILITY_CLOSED == $course['visibility']; + $course_subscribe_allowed = 1 == $course['subscribe']; + $course_unsubscribe_allowed = 1 == $course['unsubscribe']; $count_connections = $course['count_connections']; $creation_date = substr($course['creation_date'], 0, 10); // display the course bloc - $html = '
'; - $course['category_title'] = ''; if (isset($course['category'])) { $course['category_title'] = isset($categoryList[$course['category']]) ? $categoryList[$course['category']] : ''; } // Display thumbnail - $html .= CoursesAndSessionsCatalog::returnThumbnail($course, $userRegistered); + $course['thumbnail'] = CoursesAndSessionsCatalog::returnThumbnail($course); + $course['description_button'] = CourseManager::returnDescriptionButton($course); + $subscribeButton = CoursesAndSessionsCatalog::return_register_button( + $course, + $stok, + $categoryCode, + $searchTerm + ); - $separator = null; - $subscribeButton = CoursesAndSessionsCatalog::return_register_button($course, $stok, $code, $searchTerm); // Start buy course validation // display the course price and buy button if the buycourses plugin is enabled and this course is configured $plugin = BuyCoursesPlugin::create(); $isThisCourseInSale = $plugin->buyCoursesForGridCatalogValidator( - $course['real_id'], + $courseId, BuyCoursesPlugin::PRODUCT_TYPE_COURSE ); + $separator = ''; if ($isThisCourseInSale) { // set the Price label $separator = $isThisCourseInSale['html']; // set the Buy button instead register. if ($isThisCourseInSale['verificator']) { $subscribeButton = $plugin->returnBuyCourseButton( - $course['real_id'], + $courseId, BuyCoursesPlugin::PRODUCT_TYPE_COURSE ); } } - // end buy course validation - // display course title and button bloc - $html .= '
'; - $html .= CoursesAndSessionsCatalog::return_title($course, $userRegisteredInCourse); + // end buy course validation + $course['title_formatted'] = CoursesAndSessionsCatalog::return_title($course, $userRegisteredInCourse); + $course['rating'] = ''; + if ($hideRating === false) { + $ajax_url = api_get_path(WEB_AJAX_PATH).'course.ajax.php?a=add_course_vote'; + $rating = Display::return_rating_system( + 'star_'.$course['real_id'], + $ajax_url.'&course_id='.$course['real_id'], + $course['point_info'] + ); + $course['rating'] = '
'.$rating.'
'; + } if ($showTeacher) { - $html .= CoursesAndSessionsCatalog::return_teacher($course); + $course['teacher_info'] = CoursesAndSessionsCatalog::return_teacher($course); } // display button line - $html .= '
'; - $html .= $separator ? '
'.$separator.'
' : ''; - $html .= '
'; + $course['buy_course'] = $separator; + + if ($allowExtraFields) { + $course['extra_data'] = ''; + $values = $extraFieldValues->getAllValuesForAnItem($courseId, true, true); + foreach ($values as $valueItem) { + /** @var \Chamilo\CoreBundle\Entity\ExtraFieldValues $value */ + $value = $valueItem['value']; + if ($value) { + $data = $value->getValue(); + if (!empty($data)) { + $course['extra_data'] .= $value->getField()->getDisplayText().': '; + switch ($value->getField()->getFieldType()) { + case ExtraField::FIELD_TYPE_CHECKBOX: + if ($value->getValue() == 1) { + $course['extra_data'] .= get_lang('Yes').'
'; + } else { + $course['extra_data'] .= get_lang('No').'
'; + } + break; + default: + $course['extra_data'] .= $value->getValue().'
'; + break; + } + } + } + } + + $course['extra_data_tags'] = []; + if (!empty($courseTags)) { + /** @var \Chamilo\CoreBundle\Entity\Tag $tag */ + foreach ($courseTags as $tag) { + $tagUrl = Display::url($tag->getTag(), $url.'&extra_tags%5B%5D='.$tag->getTag()); + $course['extra_data_tags'][] = $tagUrl; + } + } + } + // if user registered as student if ($userRegisteredInCourse) { - $html .= CoursesAndSessionsCatalog::return_already_registered_label('student'); - if (!$course_closed) { + $course['already_registered_formatted'] = Display::url( + Display::returnFontAwesomeIcon('external-link').' '. + get_lang('GoToCourse'), + $courseUrl.$course['directory'].'/index.php?id_session=0', + ['class' => 'btn btn-primary'] + ); + if (!$courseClosed) { if ($course_unsubscribe_allowed) { - $html .= CoursesAndSessionsCatalog::return_unregister_button($course, $stok, $searchTerm, $code); + $course['unregister_formatted'] = CoursesAndSessionsCatalog::return_unregister_button( + $course, + $stok, + $searchTerm, + $categoryCode + ); } } } elseif ($userRegisteredInCourseAsTeacher) { // if user registered as teacher if ($course_unsubscribe_allowed) { - $html .= CoursesAndSessionsCatalog::return_unregister_button($course, $stok, $searchTerm, $code); + $course['unregister_formatted'] = CoursesAndSessionsCatalog::return_unregister_button( + $course, + $stok, + $searchTerm, + $categoryCode + ); } } else { // if user not registered in the course - if (!$course_closed) { + if (!$courseClosed) { if (!$course_private) { if ($course_subscribe_allowed) { - $html .= $subscribeButton; + $course['subscribe_formatted'] = $subscribeButton; } } } } - $html .= '
'; - $html .= '
'; - $html .= '
'; - $html .= '
'; - $html .= '
'; - $content .= $html; } - $content .= '
'; } else { if (!isset($_REQUEST['subscribe_user_with_password']) && !isset($_REQUEST['subscribe_course']) ) { - $content .= Display::return_message( + Display::addFlash(Display::return_message( get_lang('ThereAreNoCoursesInThisCategory'), 'warning' - ); + )); } } } - $content .= '
'; - $content .= $catalogPagination; - $content .= '
'; + $template = new Template($toolTitle, true, true, false, false, false); + $template->assign('content', $content); + $template->assign('courses', $courses); + $template->assign('pagination', $catalogPagination); + $template->display($template->get_template('catalog/course_catalog.tpl')); + exit; break; case 'display_sessions': if (!$userCanViewPage) { @@ -449,10 +604,9 @@ switch ($action) { } $registrationAllowed = api_get_setting('catalog_allow_session_auto_subscription'); - if ($registrationAllowed === 'true') { + if ('true' === $registrationAllowed) { $entityManager = Database::getManager(); $repository = $entityManager->getRepository('ChamiloCoreBundle:SequenceResource'); - $sequences = $repository->getRequirements( $sessionId, SequenceResource::SESSION_TYPE @@ -487,7 +641,7 @@ switch ($action) { if ($count <= 0) { // no course in session -> return to catalog $url = api_get_path(WEB_CODE_PATH).'auth/courses.php'; - } elseif ($count == 1) { + } elseif (1 == $count) { // only one course, so redirect directly to this course foreach ($coursesList as $course) { $url = api_get_path(WEB_COURSE_PATH).$course['directory'].'/index.php?id_session='.$sessionId; diff --git a/main/auth/layout.php b/main/auth/layout.php deleted file mode 100755 index 4cee822aa8..0000000000 --- a/main/auth/layout.php +++ /dev/null @@ -1,19 +0,0 @@ - - Beeznest - * - * @package chamilo.auth - */ - -// Header -Display::display_header(''); - -// Display -echo $content; - -// Footer -Display::display_footer(); diff --git a/main/auth/sort_my_courses.php b/main/auth/sort_my_courses.php index 1e2d6f5f2e..6c26c863fc 100644 --- a/main/auth/sort_my_courses.php +++ b/main/auth/sort_my_courses.php @@ -1,4 +1,5 @@ get_courses_in_category(); +$courses_in_category = $auth->getCoursesInCategory(); $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : ''; $currentUrl = api_get_self(); @@ -188,7 +189,7 @@ switch ($action) { } $table = Database::get_main_table(TABLE_USER_COURSE_CATEGORY); - $sql = "UPDATE $table + $sql = "UPDATE $table SET collapsed = $option WHERE user_id = $userId AND id = $categoryId"; Database::query($sql); diff --git a/main/inc/lib/CoursesAndSessionsCatalog.class.php b/main/inc/lib/CoursesAndSessionsCatalog.class.php index b662ab9a3c..c3f5c73957 100644 --- a/main/inc/lib/CoursesAndSessionsCatalog.class.php +++ b/main/inc/lib/CoursesAndSessionsCatalog.class.php @@ -181,7 +181,6 @@ class CoursesAndSessionsCatalog ]; $allCategories = CourseCategory::getAllCategories(); - foreach ($allCategories as $category) { if (empty($category['parent_id'])) { $list[$category['code']] = $category; @@ -214,58 +213,7 @@ class CoursesAndSessionsCatalog return array_merge($list, $categories); } - /** - * @return array - */ - public static function getCourseCategories() - { - $urlId = 1; - if (api_is_multiple_url_enabled()) { - $urlId = api_get_current_access_url_id(); - } - - $countCourses = self::countAvailableCoursesToShowInCatalog($urlId); - - $categories = []; - $categories[0][0] = [ - 'id' => 0, - 'name' => get_lang('DisplayAll'), - 'code' => 'ALL', - 'parent_id' => null, - 'tree_pos' => 0, - 'count_courses' => $countCourses, - ]; - - $categoriesFromDatabase = CourseCategory::getCategories(); - - foreach ($categoriesFromDatabase as $row) { - $countCourses = CourseCategory::countCoursesInCategory($row['code']); - $row['count_courses'] = $countCourses; - if (empty($row['parent_id'])) { - $categories[0][$row['tree_pos']] = $row; - } else { - $categories[$row['parent_id']][$row['tree_pos']] = $row; - } - } - - // count courses that are in no category - $countCourses = CourseCategory::countCoursesInCategory(); - $categories[0][count($categories[0]) + 1] = [ - 'id' => 0, - 'name' => get_lang('None'), - 'code' => 'NONE', - 'parent_id' => null, - 'tree_pos' => $row['tree_pos'] + 1, - 'children_count' => 0, - 'auth_course_child' => true, - 'auth_cat_child' => true, - 'count_courses' => $countCourses, - ]; - - return $categories; - } - - /** + /** * Return LIMIT to filter SQL query. * * @param array $limit @@ -285,21 +233,21 @@ class CoursesAndSessionsCatalog } /** - * @param string $category_code - * @param int $random_value - * @param array $limit will be used if $random_value is not set. + * @param string $categoryCode + * @param int $randomValue + * @param array $limit will be used if $randomValue is not set. * This array should contains 'start' and 'length' keys * * @return array */ - public static function getCoursesInCategory($category_code, $random_value = null, $limit = []) + public static function getCoursesInCategory($categoryCode, $randomValue = null, $limit = []) { $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE); $avoidCoursesCondition = self::getAvoidCourseCondition(); $visibilityCondition = CourseManager::getCourseVisibilitySQLCondition('course', true); - if (!empty($random_value)) { - $random_value = (int) $random_value; + if (!empty($randomValue)) { + $randomValue = (int) $randomValue; $sql = "SELECT COUNT(*) FROM $tbl_course"; $result = Database::query($sql); @@ -328,19 +276,19 @@ class CoursesAndSessionsCatalog ON (url_rel_course.c_id = course.id) WHERE $urlCondition AND - RAND()*$num_records< $random_value + RAND()*$num_records< $randomValue $avoidCoursesCondition $visibilityCondition ORDER BY RAND() - LIMIT 0, $random_value"; + LIMIT 0, $randomValue"; } else { $sql = "SELECT id, id as real_id FROM $tbl_course course WHERE - RAND()*$num_records< $random_value + RAND()*$num_records< $randomValue $avoidCoursesCondition $visibilityCondition ORDER BY RAND() - LIMIT 0, $random_value"; + LIMIT 0, $randomValue"; } $result = Database::query($sql); @@ -358,24 +306,24 @@ class CoursesAndSessionsCatalog $sql = "SELECT *, id as real_id FROM $tbl_course WHERE id IN($id_in)"; } else { $limitFilter = self::getLimitFilterFromArray($limit); - $category_code = Database::escape_string($category_code); - $listCode = self::childrenCategories($category_code); + $categoryCode = Database::escape_string($categoryCode); + $listCode = self::childrenCategories($categoryCode); $conditionCode = ' '; if (empty($listCode)) { - if ($category_code === 'NONE') { + if ($categoryCode === 'NONE') { $conditionCode .= " category_code='' "; } else { - $conditionCode .= " category_code='$category_code' "; + $conditionCode .= " category_code='$categoryCode' "; } } else { foreach ($listCode as $code) { $conditionCode .= " category_code='$code' OR "; } - $conditionCode .= " category_code='$category_code' "; + $conditionCode .= " category_code='$categoryCode' "; } - if (empty($category_code) || $category_code == 'ALL') { + if (empty($categoryCode) || $categoryCode == 'ALL') { $sql = "SELECT *, id as real_id FROM $tbl_course course WHERE @@ -398,7 +346,7 @@ class CoursesAndSessionsCatalog $tbl_url_rel_course = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE); $urlCondition = ' access_url_id = '.$urlId.' '; - if ($category_code != 'ALL') { + if ($categoryCode !== 'ALL') { $sql = "SELECT *, course.id real_id FROM $tbl_course as course INNER JOIN $tbl_url_rel_course as url_rel_course ON (url_rel_course.c_id = course.id) @@ -426,7 +374,7 @@ class CoursesAndSessionsCatalog while ($row = Database::fetch_array($result)) { $row['registration_code'] = !empty($row['registration_code']); $count_users = CourseManager::get_users_count_in_course($row['code']); - $count_connections_last_month = Tracking::get_course_connections_count( + $connectionsLastMonth = Tracking::get_course_connections_count( $row['id'], 0, api_get_utc_datetime(time() - (30 * 86400)) @@ -435,10 +383,10 @@ class CoursesAndSessionsCatalog if ($row['tutor_name'] == '0') { $row['tutor_name'] = get_lang('NoManager'); } - $point_info = CourseManager::get_course_ranking($row['id'], 0); + $courses[] = [ 'real_id' => $row['real_id'], - 'point_info' => $point_info, + 'point_info' => CourseManager::get_course_ranking($row['id'], 0), 'code' => $row['code'], 'directory' => $row['directory'], 'visual_code' => $row['visual_code'], @@ -451,7 +399,7 @@ class CoursesAndSessionsCatalog 'visibility' => $row['visibility'], 'category' => $row['category_code'], 'count_users' => $count_users, - 'count_connections' => $count_connections_last_month, + 'count_connections' => $connectionsLastMonth, ]; } @@ -462,25 +410,43 @@ class CoursesAndSessionsCatalog * Search the courses database for a course that matches the search term. * The search is done on the code, title and tutor field of the course table. * - * @param string $search_term The string that the user submitted, what we are looking for + * @param string $keyword The string that the user submitted * @param array $limit * @param bool $justVisible search only on visible courses in the catalogue + * @param array $conditions * * @return array an array containing a list of all the courses matching the the search term */ - public static function search_courses($search_term, $limit, $justVisible = false) + public static function searchCourses($keyword, $limit, $justVisible = false, $conditions = []) { $courseTable = Database::get_main_table(TABLE_MAIN_COURSE); $limitFilter = self::getLimitFilterFromArray($limit); $avoidCoursesCondition = self::getAvoidCourseCondition(); - $visibilityCondition = $justVisible ? CourseManager::getCourseVisibilitySQLCondition('course', true) : ''; - $search_term_safe = Database::escape_string($search_term); - $sql = "SELECT * FROM $courseTable course + $visibilityCondition = $justVisible ? CourseManager::getCourseVisibilitySQLCondition('s', true) : ''; + $keyword = Database::escape_string($keyword); + + $sqlInjectJoins = ''; + $where = ' 1 = 1 '; + $sqlInjectWhere = ''; + $injectExtraFields = '1'; + if (!empty($conditions)) { + $sqlInjectJoins = $conditions['inject_joins']; + $where = $conditions['where']; + $sqlInjectWhere = $conditions['inject_where']; + $injectExtraFields = !empty($conditions['inject_extra_fields']) ? $conditions['inject_extra_fields'] : 1; + $injectExtraFields = rtrim($injectExtraFields, ', '); + } + + $sql = "SELECT DISTINCT course.*, $injectExtraFields + FROM $courseTable course + $sqlInjectJoins WHERE ( - course.code LIKE '%".$search_term_safe."%' OR - course.title LIKE '%".$search_term_safe."%' OR - course.tutor_name LIKE '%".$search_term_safe."%' + course.code LIKE '%".$keyword."%' OR + course.title LIKE '%".$keyword."%' OR + course.tutor_name LIKE '%".$keyword."%' ) + $where + $sqlInjectWhere $avoidCoursesCondition $visibilityCondition ORDER BY title, visual_code ASC @@ -491,24 +457,26 @@ class CoursesAndSessionsCatalog $urlId = api_get_current_access_url_id(); if ($urlId != -1) { $tbl_url_rel_course = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE); - $urlCondition = ' access_url_id = '.$urlId.' AND'; $allowBaseCategories = api_get_configuration_value('allow_base_course_category'); if ($allowBaseCategories) { $urlCondition = ' (access_url_id = '.$urlId.' OR access_url_id = 1) AND '; } - $sql = "SELECT course.* + $sql = "SELECT DISTINCT course.*, $injectExtraFields FROM $courseTable as course INNER JOIN $tbl_url_rel_course as url_rel_course ON (url_rel_course.c_id = course.id) + $sqlInjectJoins WHERE access_url_id = $urlId AND ( - code LIKE '%".$search_term_safe."%' OR - title LIKE '%".$search_term_safe."%' OR - tutor_name LIKE '%".$search_term_safe."%' + code LIKE '%".$keyword."%' OR + title LIKE '%".$keyword."%' OR + tutor_name LIKE '%".$keyword."%' ) + $where + $sqlInjectWhere $avoidCoursesCondition $visibilityCondition ORDER BY title, visual_code ASC @@ -516,9 +484,9 @@ class CoursesAndSessionsCatalog "; } } - $result_find = Database::query($sql); + $result = Database::query($sql); $courses = []; - while ($row = Database::fetch_array($result_find)) { + while ($row = Database::fetch_array($result)) { $row['registration_code'] = !empty($row['registration_code']); $countUsers = CourseManager::get_user_list_from_course_code( $row['code'], @@ -534,11 +502,10 @@ class CoursesAndSessionsCatalog api_get_utc_datetime(time() - (30 * 86400)) ); - $point_info = CourseManager::get_course_ranking($row['id'], 0); - + $ranking = CourseManager::get_course_ranking($row['id'], 0); $courses[] = [ 'real_id' => $row['id'], - 'point_info' => $point_info, + 'point_info' => $ranking, 'code' => $row['code'], 'directory' => $row['directory'], 'visual_code' => $row['visual_code'], @@ -626,12 +593,12 @@ class CoursesAndSessionsCatalog if (!is_null($date)) { $qb->andWhere( - $qb->expr()->orX( - $qb->expr()->isNull('s.accessEndDate'), + $qb->expr()->orX( + $qb->expr()->isNull('s.accessEndDate'), $qb->expr()->andX( $qb->expr()->isNotNull('s.accessStartDate'), $qb->expr()->isNotNull('s.accessEndDate'), - $qb->expr()->lte('s.accessStartDate', $date), + $qb->expr()->lte('s.accessStartDate', $date), $qb->expr()->gte('s.accessEndDate', $date) ), $qb->expr()->andX( @@ -871,7 +838,7 @@ class CoursesAndSessionsCatalog $list = []; $row = []; - if ($code != 'ALL' and $code != 'NONE') { + if ($code !== 'ALL' and $code !== 'NONE') { foreach ($allCategories as $category) { if ($category['code'] === $code) { $list = self::buildCourseCategoryTree($allCategories, $category['code'], 0); @@ -914,16 +881,11 @@ class CoursesAndSessionsCatalog * Display the course catalog image of a course. * * @param array $course - * @param bool $registeredUser * * @return string HTML string */ - public static function returnThumbnail($course, $registeredUser) + public static function returnThumbnail($course) { - $html = ''; - $title = cut($course['title'], 70); - $linkCourse = api_get_path(WEB_PATH).'course/'.$course['real_id'].'/about'; - // course path $course_path = api_get_path(SYS_COURSE_PATH).$course['directory']; if (file_exists($course_path.'/course-pic.png')) { @@ -941,22 +903,7 @@ class CoursesAndSessionsCatalog ); } - $html .= '
'; - $html .= '' - .''; - - $categoryTitle = isset($course['category_title']) ? $course['category_title'] : ''; - if (!empty($categoryTitle)) { - $html .= ''.$categoryTitle.''; - $html .= '
'; - } - - $html .= '
'; - - return $html; + return $courseMediumImage; } /** @@ -1022,43 +969,31 @@ class CoursesAndSessionsCatalog * Display the title of a course in course catalog. * * @param array $course - * @param bool $registeredUser * * @return string HTML string */ - public static function return_title($course, $registeredUser) + public static function return_title($course) { - //$linkCourse = api_get_course_url($course['code']); $linkCourse = api_get_path(WEB_PATH).'course/'.$course['real_id'].'/about'; $html = '

'; $html .= ''.$course['title'].''; $html .= '

'; - if (api_get_configuration_value('hide_course_rating') === false) { - $ajax_url = api_get_path(WEB_AJAX_PATH).'course.ajax.php?a=add_course_vote'; - $rating = Display::return_rating_system( - 'star_'.$course['real_id'], - $ajax_url.'&course_id='.$course['real_id'], - $course['point_info'] - ); - $html .= '
'.$rating.'
'; - } - return $html; } /** * Display the already registerd text in a course in the course catalog. * - * @param $in_status + * @param $status * * @return string HTML string */ - public static function return_already_registered_label($in_status) + public static function return_already_registered_label($status) { $icon = ''; $title = get_lang('YouAreATeacherOfThisCourse'); - if ($in_status == 'student') { + if ($status === 'student') { $icon = ''; $title = get_lang('AlreadySubscribed'); } @@ -1082,12 +1017,12 @@ class CoursesAndSessionsCatalog * * @param $course * @param $stok - * @param $code + * @param $categoryCode * @param $search_term * * @return string */ - public static function return_register_button($course, $stok, $code, $search_term) + public static function return_register_button($course, $stok, $categoryCode, $search_term) { $title = get_lang('Subscribe'); $action = 'subscribe_course'; @@ -1098,7 +1033,7 @@ class CoursesAndSessionsCatalog return Display::url( Display::returnFontAwesomeIcon('check').' '.$title, api_get_self().'?action='.$action.'&sec_token='.$stok. - '&course_code='.$course['code'].'&search_term='.$search_term.'&category_code='.$code, + '&course_code='.$course['code'].'&search_term='.$search_term.'&category_code='.$categoryCode, ['class' => 'btn btn-success btn-sm', 'title' => $title, 'aria-label' => $title] ); } @@ -1109,19 +1044,19 @@ class CoursesAndSessionsCatalog * @param $course * @param $stok * @param $search_term - * @param $code + * @param $categoryCode * * @return string */ - public static function return_unregister_button($course, $stok, $search_term, $code) + public static function return_unregister_button($course, $stok, $search_term, $categoryCode) { $title = get_lang('Unsubscription'); return Display::url( - Display::returnFontAwesomeIcon('sign-in').' '.$title, + Display::returnFontAwesomeIcon('sign-in').' '.$title, api_get_self().'?action=unsubscribe&sec_token='.$stok - .'&course_code='.$course['code'].'&search_term='.$search_term.'&category_code='.$code, - ['class' => 'btn btn-danger btn-sm', 'title' => $title, 'aria-label' => $title] + .'&course_code='.$course['code'].'&search_term='.$search_term.'&category_code='.$categoryCode, + ['class' => 'btn btn-danger', 'title' => $title, 'aria-label' => $title] ); } @@ -1296,11 +1231,11 @@ class CoursesAndSessionsCatalog $pageTotal = ceil($countSessions / $limit['length']); // Do NOT show pagination if only one page or less - $pagination = $pageTotal > 1 ? CourseCategory::getCatalogPagination($limit['current'], $limit['length'], $pageTotal) : ''; + $pagination = $pageTotal > 1 ? self::getCatalogPagination($limit['current'], $limit['length'], $pageTotal) : ''; $sessionsBlocks = self::getFormattedSessionsBlock($sessions); // Get session search catalogue URL - $courseUrl = CourseCategory::getCourseCategoryUrl( + $courseUrl = self::getCatalogUrl( 1, $limit['length'], null, @@ -1323,7 +1258,7 @@ class CoursesAndSessionsCatalog $tpl->assign('already_subscribed_label', self::getAlreadyRegisteredInSessionLabel()); $tpl->assign('catalog_settings', self::getCatalogSearchSettings()); - $contentTemplate = $tpl->get_template('auth/session_catalog.tpl'); + $contentTemplate = $tpl->get_template('catalog/session_catalog.tpl'); $tpl->display($contentTemplate); } @@ -1337,7 +1272,7 @@ class CoursesAndSessionsCatalog { $keyword = isset($_POST['keyword']) ? $_POST['keyword'] : null; $hiddenLinks = isset($_GET['hidden_links']) ? (int) $_GET['hidden_links'] == 1 : false; - $courseUrl = CourseCategory::getCourseCategoryUrl( + $courseUrl = self::getCatalogUrl( 1, $limit['length'], null, @@ -1361,7 +1296,7 @@ class CoursesAndSessionsCatalog $tpl->assign('sessions', $sessionsBlocks); $tpl->assign('catalog_settings', self::getCatalogSearchSettings()); - $contentTemplate = $tpl->get_template('auth/session_catalog.tpl'); + $contentTemplate = $tpl->get_template('catalog/session_catalog.tpl'); $tpl->display($contentTemplate); } @@ -1394,7 +1329,7 @@ class CoursesAndSessionsCatalog { $pageLength = isset($_GET['pageLength']) ? (int) $_GET['pageLength'] : self::PAGE_LENGTH; - $url = CourseCategory::getCourseCategoryUrl(1, $pageLength, null, 0, 'display_sessions'); + $url = self::getCatalogUrl(1, $pageLength, null, 0, 'display_sessions'); $headers = []; if (self::showCourses()) { $headers[] = [ @@ -1423,7 +1358,7 @@ class CoursesAndSessionsCatalog $searchTag = isset($_POST['search_tag']) ? $_POST['search_tag'] : null; $searchDate = isset($_POST['date']) ? $_POST['date'] : date('Y-m-d'); $hiddenLinks = isset($_GET['hidden_links']) ? (int) $_GET['hidden_links'] == 1 : false; - $courseUrl = CourseCategory::getCourseCategoryUrl( + $courseUrl = self::getCatalogUrl( 1, $limit['length'], null, @@ -1446,7 +1381,7 @@ class CoursesAndSessionsCatalog $tpl->assign('search_tag', Security::remove_XSS($searchTag)); $tpl->assign('sessions', $sessionsBlocks); - $contentTemplate = $tpl->get_template('auth/session_catalog.tpl'); + $contentTemplate = $tpl->get_template('catalog/session_catalog.tpl'); $tpl->display($contentTemplate); } @@ -1603,4 +1538,190 @@ class CoursesAndSessionsCatalog return $sessionsBlocks; } + + /** + * Get Pagination HTML div. + * + * @param int $pageCurrent + * @param int $pageLength + * @param int $pageTotal + * @param string $categoryCode + * @param string $action + * @param array $fields + * + * @return string + */ + public static function getCatalogPagination($pageCurrent, $pageLength, $pageTotal, $categoryCode = '', $action = '', $fields = []) + { + // Start empty html + $pageDiv = ''; + $html = ''; + $pageBottom = max(1, $pageCurrent - 3); + $pageTop = min($pageTotal, $pageCurrent + 3); + + if ($pageBottom > 1) { + $pageDiv .= self::getPageNumberItem(1, $pageLength); + if ($pageBottom > 2) { + $pageDiv .= self::getPageNumberItem( + $pageBottom - 1, + $pageLength, + null, + '...', + $categoryCode, + $action, + $fields + ); + } + } + + // For each page add its page button to html + for ($i = $pageBottom; $i <= $pageTop; $i++) { + if ($i === $pageCurrent) { + $pageItemAttributes = ['class' => 'active']; + } else { + $pageItemAttributes = []; + } + $pageDiv .= self::getPageNumberItem( + $i, + $pageLength, + $pageItemAttributes, + '', + $categoryCode, + $action, + $fields + ); + } + + // Check if current page is the last page + if ($pageTop < $pageTotal) { + if ($pageTop < ($pageTotal - 1)) { + $pageDiv .= self::getPageNumberItem( + $pageTop + 1, + $pageLength, + null, + '...', + $categoryCode, + $action, + $fields + ); + } + $pageDiv .= self::getPageNumberItem($pageTotal, $pageLength, [], '', $categoryCode, $action, $fields); + } + + // Complete pagination html + $pageDiv = Display::tag('ul', $pageDiv, ['class' => 'pagination']); + $html .= ''; + + return $html; + } + + + /** + * Get li HTML of page number. + * + * @param $pageNumber + * @param $pageLength + * @param array $liAttributes + * @param string $content + * @param string $categoryCode + * @param string $action + * @param array $fields + * + * @return string + */ + public static function getPageNumberItem( + $pageNumber, + $pageLength, + $liAttributes = [], + $content = '', + $categoryCode = '', + $action = '', + $fields = [] + ) { + // Get page URL + $url = self::getCatalogUrl($pageNumber, $pageLength, $categoryCode, null, $action, $fields); + + // If is current page ('active' class) clear URL + if (isset($liAttributes) && is_array($liAttributes) && isset($liAttributes['class'])) { + if (strpos('active', $liAttributes['class']) !== false) { + $url = ''; + } + } + + $content = !empty($content) ? $content : $pageNumber; + + return Display::tag( + 'li', + Display::url( + $content, + $url + ), + $liAttributes + ); + } + + /** + * Return URL to course catalog. + * + * @param int $pageCurrent + * @param int $pageLength + * @param string $categoryCode + * @param int $hiddenLinks + * @param string $action + * + * @return string + */ + public static function getCatalogUrl( + $pageCurrent, + $pageLength, + $categoryCode = null, + $hiddenLinks = null, + $action = null, + $extraFields = [] + ) { + $requestAction = isset($_REQUEST['action']) ? Security::remove_XSS($_REQUEST['action']) : null; + $action = isset($action) ? Security::remove_XSS($action) : $requestAction; + $searchTerm = isset($_REQUEST['search_term']) ? Security::remove_XSS($_REQUEST['search_term']) : null; + + if ($action === 'subscribe_user_with_password') { + $action = 'subscribe'; + } + + $categoryCodeRequest = isset($_REQUEST['category_code']) ? Security::remove_XSS($_REQUEST['category_code']) : null; + $categoryCode = !empty($categoryCode) ? Security::remove_XSS($categoryCode) : $categoryCodeRequest; + $hiddenLinksRequest = !empty($_REQUEST['hidden_links']) ? Security::remove_XSS($_REQUEST['hidden_links']) : null; + $hiddenLinks = !empty($hiddenLinks) ? Security::remove_XSS($hiddenLinksRequest) : $categoryCodeRequest; + + // Start URL with params + $pageUrl = api_get_self(). + '?action='.$action. + '&category_code='.$categoryCode. + '&hidden_links='.$hiddenLinks. + '&pageCurrent='.$pageCurrent. + '&pageLength='.$pageLength; + + if (!empty($extraFields)) { + $params = []; + foreach ($extraFields as $variable => $value) { + $params[Security::remove_XSS($variable)] = Security::remove_XSS($value); + } + if (!empty($params)) { + $pageUrl .= '&'.http_build_query($params); + } + } + + switch ($action) { + case 'subscribe': + // for search + $pageUrl .= + '&search_term='.$searchTerm. + '&sec_token='.Security::getTokenFromSession(); + break; + case 'display_courses': + default: + break; + } + + return $pageUrl; + } } diff --git a/main/inc/lib/auth.lib.php b/main/inc/lib/auth.lib.php index 06ecd61313..f41d04f082 100755 --- a/main/inc/lib/auth.lib.php +++ b/main/inc/lib/auth.lib.php @@ -19,72 +19,12 @@ class Auth { } - /** - * retrieves all the courses that the user has already subscribed to. - * - * @param int $user_id - * - * @return array an array containing all the information of the courses of the given user - */ - public function get_courses_of_user($user_id) - { - $TABLECOURS = Database::get_main_table(TABLE_MAIN_COURSE); - $TABLECOURSUSER = Database::get_main_table(TABLE_MAIN_COURSE_USER); - $avoidCoursesCondition = CoursesAndSessionsCatalog::getAvoidCourseCondition(); - $visibilityCondition = CourseManager::getCourseVisibilitySQLCondition('course', true); - - // Secondly we select the courses that are in a category (user_course_cat<>0) and - // sort these according to the sort of the category - $user_id = (int) $user_id; - $sql = "SELECT - course.code k, - course.visual_code vc, - course.subscribe subscr, - course.unsubscribe unsubscr, - course.title i, - course.tutor_name t, - course.category_code cat, - course.directory dir, - course_rel_user.status status, - course_rel_user.sort sort, - course_rel_user.user_course_cat user_course_cat - FROM $TABLECOURS course, $TABLECOURSUSER course_rel_user - WHERE - course.id = course_rel_user.c_id AND - course_rel_user.relation_type <> ".COURSE_RELATION_TYPE_RRHH." AND - course_rel_user.user_id = '".$user_id."' - $avoidCoursesCondition - $visibilityCondition - ORDER BY course_rel_user.sort ASC"; - - $result = Database::query($sql); - $courses = []; - while ($row = Database::fetch_array($result)) { - //we only need the database name of the course - $courses[] = [ - 'code' => $row['k'], - 'visual_code' => $row['vc'], - 'title' => $row['i'], - 'directory' => $row['dir'], - 'status' => $row['status'], - 'tutor' => $row['t'], - 'subscribe' => $row['subscr'], - 'category' => $row['cat'], - 'unsubscribe' => $row['unsubscr'], - 'sort' => $row['sort'], - 'user_course_category' => $row['user_course_cat'], - ]; - } - - return $courses; - } - /** * This function get all the courses in the particular user category. * * @return array */ - public function get_courses_in_category() + public function getCoursesInCategory() { $user_id = api_get_user_id(); @@ -122,7 +62,7 @@ class Auth * (moving a course to a different course category). * * @param int $courseId - * @param int Category id + * @param int Category id * * @return bool True if it success */ @@ -154,9 +94,9 @@ class Auth /** * moves the course one place up or down. * - * @param string Direction (up/down) - * @param string Course code - * @param int Category id + * @param string Direction (up/down) + * @param string Course code + * @param int Category id * * @return bool True if it success */ @@ -166,7 +106,7 @@ class Auth $table = Database::get_main_table(TABLE_MAIN_COURSE_USER); $current_user_id = api_get_user_id(); - $all_user_courses = $this->get_courses_of_user($current_user_id); + $all_user_courses = $this->getCoursesOfUser($current_user_id); // we need only the courses of the category we are moving in $user_courses = []; @@ -227,7 +167,7 @@ class Auth /** * Moves the course one place up or down. * - * @param string $direction Direction up/down + * @param string $direction Direction up/down * @param string $category2move Category id * * @return bool True If it success @@ -235,7 +175,7 @@ class Auth public function move_category($direction, $category2move) { $userId = api_get_user_id(); - $userCategories = CourseManager::get_user_course_categories(api_get_user_id()); + $userCategories = CourseManager::get_user_course_categories($userId); $categories = array_values($userCategories); $previous = null; @@ -246,7 +186,7 @@ class Auth // source_course is the course where we clicked the up or down icon $source_category = $userCategories[$category2move]; // target_course is the course before/after the source_course (depending on the up/down icon) - if ($direction == 'up') { + if ($direction === 'up') { if (isset($categories[$key - 1])) { $target_category = $userCategories[$categories[$key - 1]['id']]; } @@ -280,8 +220,8 @@ class Auth /** * Updates the user course category in the chamilo_user database. * - * @param string Category title - * @param int Category id + * @param string Category title + * @param int Category id * * @return bool True if it success */ @@ -305,7 +245,7 @@ class Auth /** * deletes a course category and moves all the courses that were in this category to main category. * - * @param int Category id + * @param int Category id * * @return bool True if it success */ @@ -396,7 +336,7 @@ class Auth /** * stores the user course category in the chamilo_user database. * - * @param string Category title + * @param string Category title * * @return bool True if it success */ @@ -407,7 +347,6 @@ class Auth // protect data $current_user_id = api_get_user_id(); $category_title = Database::escape_string($category_title); - $result = false; // step 1: we determine the max value of the user defined course categories $sql = "SELECT sort FROM $table @@ -425,15 +364,19 @@ class Auth title='".$category_title."' ORDER BY sort DESC"; $rs = Database::query($sql); + + $result = false; if (Database::num_rows($rs) == 0) { $sql = "INSERT INTO $table (user_id, title,sort) - VALUES ('".$current_user_id."', '".api_htmlentities($category_title, ENT_QUOTES, api_get_system_encoding())."', '".$nextsort."')"; + VALUES ('".$current_user_id."', '".api_htmlentities( + $category_title, + ENT_QUOTES, + api_get_system_encoding() + )."', '".$nextsort."')"; $resultQuery = Database::query($sql); if (Database::affected_rows($resultQuery)) { $result = true; } - } else { - $result = false; } return $result; diff --git a/main/inc/lib/course.lib.php b/main/inc/lib/course.lib.php index 4a6252bb07..929eb22842 100755 --- a/main/inc/lib/course.lib.php +++ b/main/inc/lib/course.lib.php @@ -22,8 +22,6 @@ use ChamiloSession as Session; * but not available in standard Chamilo). * * There are probably some places left with the wrong code. - * - * @package chamilo.library */ class CourseManager { @@ -2911,7 +2909,7 @@ class CourseManager * * @return array Course codes allowed or not to see in catalogue by some user or the user */ - public static function getCatalogueCourseList($allowed = true, $byUserId = -1) + public static function getCatalogCourseList($allowed = true, $byUserId = -1) { $courseTable = Database::get_main_table(TABLE_MAIN_COURSE); $tblCourseRelUserCatalogue = Database::get_main_table(TABLE_MAIN_COURSE_CATALOGUE_USER); @@ -5257,16 +5255,16 @@ class CourseManager // Check if course have users allowed to see it in the catalogue, then show only if current user is allowed to see it $currentUserId = api_get_user_id(); - $restrictedCourses = self::getCatalogueCourseList(true); - $allowedCoursesToCurrentUser = self::getCatalogueCourseList(true, $currentUserId); + $restrictedCourses = self::getCatalogCourseList(true); + $allowedCoursesToCurrentUser = self::getCatalogCourseList(true, $currentUserId); if (!empty($restrictedCourses)) { $visibilityCondition .= ' AND ('.$courseTableAlias.'.code NOT IN ("'.implode('","', $restrictedCourses).'")'; $visibilityCondition .= ' OR '.$courseTableAlias.'.code IN ("'.implode('","', $allowedCoursesToCurrentUser).'"))'; } // Check if course have users denied to see it in the catalogue, then show only if current user is not denied to see it - $restrictedCourses = self::getCatalogueCourseList(false); - $notAllowedCoursesToCurrentUser = self::getCatalogueCourseList(false, $currentUserId); + $restrictedCourses = self::getCatalogCourseList(false); + $notAllowedCoursesToCurrentUser = self::getCatalogCourseList(false, $currentUserId); if (!empty($restrictedCourses)) { $visibilityCondition .= ' AND ('.$courseTableAlias.'.code NOT IN ("'.implode('","', $restrictedCourses).'")'; $visibilityCondition .= ' OR '.$courseTableAlias.'.code NOT IN ("'.implode('","', $notAllowedCoursesToCurrentUser).'"))'; @@ -6715,4 +6713,63 @@ class CourseManager $courseFieldValue = new ExtraFieldValue('course'); $courseFieldValue->saveFieldValues($params); } + + /** + * retrieves all the courses that the user has already subscribed to. + * + * @param int $user_id + * + * @return array an array containing all the information of the courses of the given user + */ + public static function getCoursesByUserCourseCategory($user_id) + { + $course = Database::get_main_table(TABLE_MAIN_COURSE); + $courseRelUser = Database::get_main_table(TABLE_MAIN_COURSE_USER); + $avoidCoursesCondition = CoursesAndSessionsCatalog::getAvoidCourseCondition(); + $visibilityCondition = self::getCourseVisibilitySQLCondition('course', true); + + // Secondly we select the courses that are in a category (user_course_cat<>0) and + // sort these according to the sort of the category + $user_id = (int) $user_id; + $sql = "SELECT + course.code k, + course.visual_code vc, + course.subscribe subscr, + course.unsubscribe unsubscr, + course.title i, + course.tutor_name t, + course.category_code cat, + course.directory dir, + course_rel_user.status status, + course_rel_user.sort sort, + course_rel_user.user_course_cat user_course_cat + FROM $course course, $courseRelUser course_rel_user + WHERE + course.id = course_rel_user.c_id AND + course_rel_user.relation_type <> ".COURSE_RELATION_TYPE_RRHH." AND + course_rel_user.user_id = '".$user_id."' + $avoidCoursesCondition + $visibilityCondition + ORDER BY course_rel_user.sort ASC"; + + $result = Database::query($sql); + $courses = []; + while ($row = Database::fetch_array($result, 'ASOC')) { + $courses[] = [ + 'code' => $row['k'], + 'visual_code' => $row['vc'], + 'title' => $row['i'], + 'directory' => $row['dir'], + 'status' => $row['status'], + 'tutor' => $row['t'], + 'subscribe' => $row['subscr'], + 'category' => $row['cat'], + 'unsubscribe' => $row['unsubscr'], + 'sort' => $row['sort'], + 'user_course_category' => $row['user_course_cat'], + ]; + } + + return $courses; + } } diff --git a/main/inc/lib/course_category.lib.php b/main/inc/lib/course_category.lib.php index 45dc27b44a..a9bd7c9c70 100755 --- a/main/inc/lib/course_category.lib.php +++ b/main/inc/lib/course_category.lib.php @@ -377,35 +377,6 @@ class CourseCategory return true; } - /** - * Counts the number of children categories a category has. - * - * @param int $categoryId The ID of the category of which we want to count the children - * - * @return mixed The number of subcategories this category has - */ - public static function courseCategoryChildrenCount($categoryId) - { - $table = Database::get_main_table(TABLE_MAIN_CATEGORY); - $categoryId = (int) $categoryId; - $count = 0; - if (empty($categoryId)) { - return 0; - } - $sql = "SELECT id, code FROM $table - WHERE parent_id = $categoryId"; - $result = Database::query($sql); - while ($row = Database::fetch_array($result)) { - $count += self::courseCategoryChildrenCount($row['id']); - } - $sql = "UPDATE $table SET - children_count = $count - WHERE id = $categoryId"; - Database::query($sql); - - return $count + 1; - } - /** * @param string $categoryCode * @@ -472,9 +443,8 @@ class CourseCategory foreach ($parents as $category) { $categories[] = $category['code']; } - $categoriesInString = implode(' > ', $categories).' > '; - return $categoriesInString; + return implode(' > ', $categories).' > '; } return null; @@ -568,9 +538,9 @@ class CourseCategory } return $table->toHtml(); - } else { - return Display::return_message(get_lang('NoCategories'), 'warning'); } + + return Display::return_message(get_lang('NoCategories'), 'warning'); } /** @@ -619,14 +589,15 @@ class CourseCategory * @param string $category_code * @param string $searchTerm * @paran bool $avoidCourses + * @paran array $conditions * * @return int */ - public static function countCoursesInCategory($category_code = '', $searchTerm = '', $avoidCourses = true) + public static function countCoursesInCategory($category_code = '', $keyword = '', $avoidCourses = true, $conditions = []) { $tbl_course = Database::get_main_table(TABLE_MAIN_COURSE); $categoryCode = Database::escape_string($category_code); - $searchTerm = Database::escape_string($searchTerm); + $keyword = Database::escape_string($keyword); $avoidCoursesCondition = ''; if ($avoidCourses) { @@ -635,6 +606,15 @@ class CourseCategory $visibilityCondition = CourseManager::getCourseVisibilitySQLCondition('course', true); + $sqlInjectJoins = ''; + $where = ' AND 1 = 1 '; + $sqlInjectWhere = ''; + if (!empty($conditions)) { + $sqlInjectJoins = $conditions['inject_joins']; + $where = $conditions['where']; + $sqlInjectWhere = $conditions['inject_where']; + } + $categoryFilter = ''; if ($categoryCode === 'ALL') { // Nothing to do @@ -645,20 +625,21 @@ class CourseCategory } $searchFilter = ''; - if (!empty($searchTerm)) { + if (!empty($keyword)) { $searchFilter = ' AND ( - code LIKE "%'.$searchTerm.'%" OR - title LIKE "%'.$searchTerm.'%" OR - tutor_name LIKE "%'.$searchTerm.'%" + code LIKE "%'.$keyword.'%" OR + title LIKE "%'.$keyword.'%" OR + tutor_name LIKE "%'.$keyword.'%" ) '; } $urlCondition = ' access_url_id = '.api_get_current_access_url_id().' AND'; $tbl_url_rel_course = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE); - $sql = "SELECT count(*) as count + $sql = "SELECT count(DISTINCT course.id) as count FROM $tbl_course as course INNER JOIN $tbl_url_rel_course as url_rel_course ON (url_rel_course.c_id = course.id) + $sqlInjectJoins WHERE $urlCondition course.visibility != '0' AND @@ -667,6 +648,8 @@ class CourseCategory $searchFilter $avoidCoursesCondition $visibilityCondition + $where + $sqlInjectWhere "; $result = Database::query($sql); @@ -737,173 +720,6 @@ class CourseCategory return Database::store_result($result, 'ASSOC'); } - /** - * Get Pagination HTML div. - * - * @param $pageCurrent - * @param $pageLength - * @param $pageTotal - * @param $categoryCode - * @param $action - * - * @return string - */ - public static function getCatalogPagination($pageCurrent, $pageLength, $pageTotal, $categoryCode = '', $action = '') - { - // Start empty html - $pageDiv = ''; - $html = ''; - $pageBottom = max(1, $pageCurrent - 3); - $pageTop = min($pageTotal, $pageCurrent + 3); - - if ($pageBottom > 1) { - $pageDiv .= self::getPageNumberItem(1, $pageLength); - if ($pageBottom > 2) { - $pageDiv .= self::getPageNumberItem( - $pageBottom - 1, - $pageLength, - null, - '...', - $categoryCode, - $action - ); - } - } - - // For each page add its page button to html - for ($i = $pageBottom; $i <= $pageTop; $i++) { - if ($i === $pageCurrent) { - $pageItemAttributes = ['class' => 'active']; - } else { - $pageItemAttributes = []; - } - $pageDiv .= self::getPageNumberItem( - $i, - $pageLength, - $pageItemAttributes, - '', - $categoryCode, - $action - ); - } - - // Check if current page is the last page - if ($pageTop < $pageTotal) { - if ($pageTop < ($pageTotal - 1)) { - $pageDiv .= self::getPageNumberItem( - $pageTop + 1, - $pageLength, - null, - '...', - $categoryCode, - $action - ); - } - $pageDiv .= self::getPageNumberItem($pageTotal, $pageLength, [], '', $categoryCode, $action); - } - - // Complete pagination html - $pageDiv = Display::tag('ul', $pageDiv, ['class' => 'pagination']); - $html .= ''; - - return $html; - } - - /** - * Return URL to course catalog. - * - * @param int $pageCurrent - * @param int $pageLength - * @param string $categoryCode - * @param int $hiddenLinks - * @param string $action - * - * @return string - */ - public static function getCourseCategoryUrl( - $pageCurrent, - $pageLength, - $categoryCode = null, - $hiddenLinks = null, - $action = null - ) { - $requestAction = isset($_REQUEST['action']) ? Security::remove_XSS($_REQUEST['action']) : null; - $action = isset($action) ? Security::remove_XSS($action) : $requestAction; - $searchTerm = isset($_REQUEST['search_term']) ? Security::remove_XSS($_REQUEST['search_term']) : null; - - if ($action === 'subscribe_user_with_password') { - $action = 'subscribe'; - } - - $categoryCodeRequest = isset($_REQUEST['category_code']) ? Security::remove_XSS($_REQUEST['category_code']) : null; - $categoryCode = !empty($categoryCode) ? Security::remove_XSS($categoryCode) : $categoryCodeRequest; - $hiddenLinksRequest = !empty($_REQUEST['hidden_links']) ? Security::remove_XSS($_REQUEST['hidden_links']) : null; - $hiddenLinks = !empty($hiddenLinks) ? Security::remove_XSS($hiddenLinksRequest) : $categoryCodeRequest; - - // Start URL with params - $pageUrl = api_get_self(). - '?action='.$action. - '&category_code='.$categoryCode. - '&hidden_links='.$hiddenLinks. - '&pageCurrent='.$pageCurrent. - '&pageLength='.$pageLength; - - switch ($action) { - case 'subscribe': - // for search - $pageUrl .= - '&search_term='.$searchTerm. - '&search_course=1'. - '&sec_token='.Security::getTokenFromSession(); - break; - case 'display_courses': - default: - break; - } - - return $pageUrl; - } - - /** - * Get li HTML of page number. - * - * @param $pageNumber - * @param $pageLength - * @param array $liAttributes - * @param string $content - * - * @return string - */ - public static function getPageNumberItem( - $pageNumber, - $pageLength, - $liAttributes = [], - $content = '', - $categoryCode = '', - $action = '' - ) { - // Get page URL - $url = self::getCourseCategoryUrl($pageNumber, $pageLength, $categoryCode, null, $action); - - // If is current page ('active' class) clear URL - if (isset($liAttributes) && is_array($liAttributes) && isset($liAttributes['class'])) { - if (strpos('active', $liAttributes['class']) !== false) { - $url = ''; - } - } - - $content = !empty($content) ? $content : $pageNumber; - - return Display::tag( - 'li', - Display::url( - $content, - $url - ), - $liAttributes - ); - } - /** * Return the name tool by action. * diff --git a/main/inc/lib/userportal.lib.php b/main/inc/lib/userportal.lib.php index 1cd1199dcd..c47bd91643 100755 --- a/main/inc/lib/userportal.lib.php +++ b/main/inc/lib/userportal.lib.php @@ -1,4 +1,5 @@ $listB['title']) { + return 1; + } + + return -1; + } + + /** + * @param $view + * @param $userId + */ + public static function setDefaultMyCourseView($view, $userId) + { + setcookie('defaultMyCourseView'.$userId, $view); + } + + /** + * @param $listA + * @param $listB + * + * @return int + */ + private static function compareByCourse($listA, $listB) + { + if ($listA['userCatTitle'] == $listB['userCatTitle']) { + if ($listA['title'] == $listB['title']) { + return 0; + } + + if ($listA['title'] > $listB['title']) { + return 1; + } + + return -1; + } + + if ($listA['userCatTitle'] > $listB['userCatTitle']) { + return 1; + } + + return -1; + } + /** * @param bool $setLoginForm */ @@ -157,37 +213,6 @@ class IndexManager Event::courseLogout($logoutInfo); } - /** - * This function checks if there are courses that are open to the world in the platform course categories (=faculties). - * - * @param string $category - * - * @return bool - */ - public function category_has_open_courses($category) - { - $setting_show_also_closed_courses = api_get_setting('show_closed_courses') == 'true'; - $main_course_table = Database::get_main_table(TABLE_MAIN_COURSE); - $category = Database::escape_string($category); - $sql_query = "SELECT * FROM $main_course_table WHERE category_code='$category'"; - $sql_result = Database::query($sql_query); - while ($course = Database::fetch_array($sql_result)) { - if (!$setting_show_also_closed_courses) { - if ((api_get_user_id() > 0 && $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM) || - ($course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD) - ) { - return true; //at least one open course - } - } else { - if (isset($course['visibility'])) { - return true; // At least one course (it does not matter weither it's open or not because $setting_show_also_closed_courses = true). - } - } - } - - return false; - } - /** * Includes a created page. * @@ -370,8 +395,8 @@ class IndexManager * * @version 1.1 * - * @author Patrick Cool , Ghent University - refactoring and code cleaning - * @author Julio Montoya , Beeznest template modifs + * @author Patrick Cool , Ghent University - refactoring and code cleaning + * @author Julio Montoya , Beeznest template modifs */ public function return_courses_in_categories() { @@ -530,7 +555,13 @@ class IndexManager $courses_list_string .= Display::page_header(get_lang('CourseList')); $courses_list_string .= "
    "; if (api_get_user_id()) { - $courses_of_user = self::get_courses_of_user(api_get_user_id()); + $courses_of_user = []; + $coursesByUserCategory = CourseManager::getCoursesByUserCourseCategory(api_get_user_id()); + if (!empty($coursesByUserCategory)) { + foreach ($coursesByUserCategory as $courseItem) { + $courses_of_user[$courseItem['code']] = $courseItem; + } + } } foreach ($course_list as $course) { // $setting_show_also_closed_courses @@ -593,7 +624,7 @@ class IndexManager $courses_list_string .= '
    '; } $course_details = []; - if (api_get_setting('display_coursecode_in_courselist') == 'true') { + if (api_get_setting('display_coursecode_in_courselist') === 'true') { $course_details[] = '('.$course['visual_code'].')'; } if (api_get_setting('display_teacher_in_courselist') === 'true') { @@ -641,13 +672,45 @@ class IndexManager } /** - * retrieves all the courses that the user has already subscribed to. + * This function checks if there are courses that are open to the world in the platform course categories + * (=faculties). * - * @author Patrick Cool , Ghent University, Belgium + * @param string $category + * + * @return bool + */ + public function category_has_open_courses($category) + { + $setting_show_also_closed_courses = api_get_setting('show_closed_courses') == 'true'; + $main_course_table = Database::get_main_table(TABLE_MAIN_COURSE); + $category = Database::escape_string($category); + $sql_query = "SELECT * FROM $main_course_table WHERE category_code='$category'"; + $sql_result = Database::query($sql_query); + while ($course = Database::fetch_array($sql_result)) { + if (!$setting_show_also_closed_courses) { + if ((api_get_user_id() > 0 && $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM) || + ($course['visibility'] == COURSE_VISIBILITY_OPEN_WORLD) + ) { + return true; //at least one open course + } + } else { + if (isset($course['visibility'])) { + return true; // At least one course (it does not matter weither it's open or not because $setting_show_also_closed_courses = true). + } + } + } + + return false; + } + + /** + * retrieves all the courses that the user has already subscribed to. * * @param int $user_id : the id of the user * * @return array an array containing all the information of the courses of the given user + * @author Patrick Cool , Ghent University, Belgium + * */ public function get_courses_of_user($user_id) { @@ -697,16 +760,48 @@ class IndexManager } /** - * @todo use the template system + * Adds a form to let users login. * - * @param $title - * @param $content + * @version 1.1 + */ + public function display_login_form() + { + return $this->tpl->displayLoginForm(); + } + + /** + * @return string + * @todo use FormValidator + * + */ + public function return_search_block() + { + $html = ''; + if (api_get_setting('search_enabled') == 'true') { + $search_btn = get_lang('Search'); + $search_content = ' +
    + + +
    '; + $html .= $this->showRightBlock(get_lang('Search'), $search_content, 'search_block'); + } + + return $html; + } + + /** + * @param $title + * @param $content * @param string $id * @param array $params * @param string $idAccordion * @param string $idCollapse * * @return string + * @todo use the template system + * */ public function showRightBlock( $title, @@ -742,38 +837,6 @@ class IndexManager return $html; } - /** - * Adds a form to let users login. - * - * @version 1.1 - */ - public function display_login_form() - { - return $this->tpl->displayLoginForm(); - } - - /** - * @todo use FormValidator - * - * @return string - */ - public function return_search_block() - { - $html = ''; - if (api_get_setting('search_enabled') == 'true') { - $search_btn = get_lang('Search'); - $search_content = '
    -
    - - -
    '; - $html .= $this->showRightBlock(get_lang('Search'), $search_content, 'search_block'); - } - - return $html; - } - /** * @return string */ @@ -820,6 +883,28 @@ class IndexManager return $html; } + /** + * Generate the HTML code for items when displaying the right-side blocks. + * + * @return string + */ + private static function returnRightBlockItems(array $items) + { + $my_account_content = ''; + foreach ($items as $item) { + if (empty($item['link']) && empty($item['title'])) { + continue; + } + + $my_account_content .= '
  • ' + .(empty($item['icon']) ? '' : ''.$item['icon'].'') + .''.$item['title'].'' + .'
  • '; + } + + return '
      '.$my_account_content.'
    '; + } + /** * @return string */ @@ -1105,813 +1190,588 @@ class IndexManager } /** - * Prints the session and course list (user_portal.php). - * - * @param int $user_id - * @param bool $showSessions - * @param string $categoryCodeFilter - * @param bool $useUserLanguageFilterIfAvailable - * @param bool $loadHistory - * - * @return array + * Shows a welcome message when the user doesn't have any content in the course list. */ - public function returnCoursesAndSessions( - $user_id, - $showSessions = true, - $categoryCodeFilter = '', - $useUserLanguageFilterIfAvailable = true, - $loadHistory = false - ) { - $gameModeIsActive = api_get_setting('gamification_mode'); - $viewGridCourses = api_get_configuration_value('view_grid_courses'); - $showSimpleSessionInfo = api_get_configuration_value('show_simple_session_info'); - $coursesWithoutCategoryTemplate = '/user_portal/classic_courses_without_category.tpl'; - $coursesWithCategoryTemplate = '/user_portal/classic_courses_with_category.tpl'; - $showAllSessions = api_get_configuration_value('show_all_sessions_on_my_course_page') === true; + public function return_welcome_to_course_block() + { + $count_courses = CourseManager::count_courses(); + $tpl = $this->tpl->get_template('layout/welcome_to_course.tpl'); - if ($loadHistory) { - // Load sessions in category in *history* - $session_categories = UserManager::get_sessions_by_category($user_id, true); - } else { - // Load sessions in category - $session_categories = UserManager::get_sessions_by_category($user_id, false); - } + $course_catalog_url = api_get_path(WEB_CODE_PATH).'auth/courses.php'; + $course_list_url = api_get_path(WEB_PATH).'user_portal.php'; - $sessionCount = 0; - $courseCount = 0; + $this->tpl->assign('course_catalog_url', $course_catalog_url); + $this->tpl->assign('course_list_url', $course_list_url); + $this->tpl->assign('course_catalog_link', Display::url(get_lang('Here'), $course_catalog_url)); + $this->tpl->assign('course_list_link', Display::url(get_lang('Here'), $course_list_url)); + $this->tpl->assign('count_courses', $count_courses); - // Student info code check (shows student progress information on - // courses list - $studentInfo = api_get_configuration_value('course_student_info'); + return $this->tpl->fetch($tpl); + } - $studentInfoProgress = !empty($studentInfo['progress']) && $studentInfo['progress'] === true; - $studentInfoScore = !empty($studentInfo['score']) && $studentInfo['score'] === true; - $studentInfoCertificate = !empty($studentInfo['certificate']) && $studentInfo['certificate'] === true; - $courseCompleteList = []; - $coursesInCategoryCount = 0; - $coursesNotInCategoryCount = 0; - $listCourse = ''; - $specialCourseList = ''; + /** + * @return array + */ + public function return_hot_courses() + { + return CourseManager::return_hot_courses(30, 6); + } + + /** + * UserPortal view for session, return the HTML of the course list. + * + * @param $user_id + * + * @return string + */ + public function returnCoursesAndSessionsViewBySession($user_id) + { + $sessionCount = 0; + $courseCount = 0; + $load_history = (isset($_GET['history']) && intval($_GET['history']) == 1) ? true : false; + + if ($load_history) { + // Load sessions in category in *history* + $session_categories = UserManager::get_sessions_by_category($user_id, true); + } else { + // Load sessions in category + $session_categories = UserManager::get_sessions_by_category($user_id, false); + } + + $html = ''; + $loadDirs = $this->load_directories_preview; // If we're not in the history view... - if ($loadHistory === false) { - // Display special courses. - $specialCourses = CourseManager::returnSpecialCourses( + $listCoursesInfo = []; + if (!isset($_GET['history'])) { + // Display special courses + $specialCoursesResult = CourseManager::returnSpecialCourses( $user_id, - $this->load_directories_preview, - $useUserLanguageFilterIfAvailable + $loadDirs ); + $specialCourses = $specialCoursesResult; - // Display courses. - $courses = CourseManager::returnCourses( + if ($specialCourses) { + $this->tpl->assign('courses', $specialCourses); + $html = $this->tpl->fetch( + $this->tpl->get_template('/user_portal/classic_courses_without_category.tpl') + ); + } + + // Display courses + // [code=>xxx, real_id=>000] + $listCourses = CourseManager::get_courses_list_by_user_id( $user_id, - $this->load_directories_preview, - $useUserLanguageFilterIfAvailable + false ); - // Course option (show student progress) - // This code will add new variables (Progress, Score, Certificate) - if ($studentInfoProgress || $studentInfoScore || $studentInfoCertificate) { - if (!empty($specialCourses)) { - foreach ($specialCourses as $key => $specialCourseInfo) { - if ($studentInfoProgress) { - $progress = Tracking::get_avg_student_progress( - $user_id, - $specialCourseInfo['course_code'] - ); - $specialCourses[$key]['student_info']['progress'] = $progress === false ? null : $progress; - } + foreach ($listCourses as $i => $listCourseCodeId) { + if (isset($listCourseCodeId['special_course'])) { + continue; + } + $courseCategory = CourseManager::getUserCourseCategoryForCourse( + $user_id, + $listCourseCodeId['real_id'] + ); - if ($studentInfoScore) { - $percentage_score = Tracking::get_avg_student_score( - $user_id, - $specialCourseInfo['course_code'], - [] - ); - $specialCourses[$key]['student_info']['score'] = $percentage_score; - } + $userCatTitle = ''; + $userCategoryId = 0; + if ($courseCategory) { + $userCategoryId = $courseCategory['user_course_cat']; + $userCatTitle = $courseCategory['title']; + } - if ($studentInfoCertificate) { - $category = Category::load( - null, - null, - $specialCourseInfo['course_code'], - null, - null, - null + $listCourse = api_get_course_info_by_id($listCourseCodeId['real_id']); + $listCoursesInfo[] = [ + 'course' => $listCourse, + 'code' => $listCourseCodeId['code'], + 'id' => $listCourseCodeId['real_id'], + 'title' => $listCourse['title'], + 'userCatId' => $userCategoryId, + 'userCatTitle' => $userCatTitle, + ]; + $courseCount++; + } + usort($listCoursesInfo, 'self::compareByCourse'); + } + + $listCoursesInSession = []; + if (is_array($session_categories)) { + // all courses that are in a session + $listCoursesInSession = SessionManager::getNamedSessionCourseForCoach($user_id); + } + + // we got all courses + // for each user category, sorted alphabetically, display courses + $listUserCategories = CourseManager::get_user_course_categories($user_id); + $listCoursesAlreadyDisplayed = []; + uasort($listUserCategories, "self::compareListUserCategory"); + $listUserCategories[0] = ''; + + $html .= '
    '; + foreach ($listUserCategories as $userCategoryId => $userCat) { + // add user category + $userCategoryHtml = ''; + if ($userCategoryId != 0) { + $userCategoryHtml = '
    '; + $userCategoryHtml .= self::getHtmlForUserCategory($userCategoryId, $userCat['title']); + } + // look for course in this userCat in session courses : $listCoursesInSession + $htmlCategory = ''; + if (isset($listCoursesInSession[$userCategoryId])) { + // list of courses in this user cat + foreach ($listCoursesInSession[$userCategoryId]['courseInUserCatList'] as $i => $listCourse) { + // add course + $listCoursesAlreadyDisplayed[$listCourse['courseId']] = 1; + if ($userCategoryId == 0) { + $htmlCategory .= '
    '; + } else { + $htmlCategory .= '
    '; + } + $htmlCategory .= '
    '; + $coursesInfo = $listCourse['course']; + + $htmlCategory .= self::getHtmlForCourse( + $coursesInfo, + $userCategoryId, + 1, + $loadDirs + ); + // list of session category + $htmlSessionCategory = ''; // end session cat block + $htmlCategory .= $htmlSessionCategory.'
    '; + $htmlCategory .= ''; // end course block } + $userCategoryHtml .= $htmlCategory; + } - if (isset($courses['in_category'])) { - foreach ($courses['in_category'] as $key1 => $value) { - if (isset($courses['in_category'][$key1]['courses'])) { - foreach ($courses['in_category'][$key1]['courses'] as $key2 => $courseInCatInfo) { - $courseCode = $courseInCatInfo['course_code']; - if ($studentInfoProgress) { - $progress = Tracking::get_avg_student_progress( - $user_id, - $courseCode - ); - $courses['in_category'][$key1]['courses'][$key2]['student_info']['progress'] = $progress === false ? null : $progress; - } - - if ($studentInfoScore) { - $percentage_score = Tracking::get_avg_student_score( - $user_id, - $courseCode, - [] - ); - $courses['in_category'][$key1]['courses'][$key2]['student_info']['score'] = $percentage_score; - } + // look for courses in this userCat in not in session courses : $listCoursesInfo + // if course not already added + $htmlCategory = ''; + foreach ($listCoursesInfo as $i => $listCourse) { + if ($listCourse['userCatId'] == $userCategoryId && + !isset($listCoursesAlreadyDisplayed[$listCourse['id']]) + ) { + if ($userCategoryId != 0) { + $htmlCategory .= '
    '; + } else { + $htmlCategory .= '
    '; + } - if ($studentInfoCertificate) { - $category = Category::load( - null, - null, - $courseCode, - null, - null, - null - ); - $courses['in_category'][$key1]['student_info']['certificate'] = null; - $isCertificateAvailable = $category[0]->is_certificate_available($user_id); - if (isset($category[0])) { - if ($viewGridCourses) { - if ($isCertificateAvailable) { - $courses['in_category'][$key1]['student_info']['certificate'] = get_lang( - 'Yes' - ); - } else { - $courses['in_category'][$key1]['student_info']['certificate'] = get_lang( - 'No' - ); - } - } else { - if ($isCertificateAvailable) { - $courses['in_category'][$key1]['student_info']['certificate'] = Display::label( - get_lang('Yes'), - 'success' - ); - } else { - $courses['in_category'][$key1]['student_info']['certificate'] = Display::label( - get_lang('No'), - 'danger' - ); - } - } - } - } - } - } - } - } - - if (isset($courses['not_category'])) { - foreach ($courses['not_category'] as $key => $courseNotInCatInfo) { - $courseCode = $courseNotInCatInfo['course_code']; - if ($studentInfoProgress) { - $progress = Tracking::get_avg_student_progress( - $user_id, - $courseCode - ); - $courses['not_category'][$key]['student_info']['progress'] = $progress === false ? null : $progress; - } - - if ($studentInfoScore) { - $percentage_score = Tracking::get_avg_student_score( - $user_id, - $courseCode, - [] - ); - $courses['not_category'][$key]['student_info']['score'] = $percentage_score; - } - - if ($studentInfoCertificate) { - $category = Category::load( - null, - null, - $courseCode, - null, - null, - null - ); - $courses['not_category'][$key]['student_info']['certificate'] = null; - - if (isset($category[0])) { - $certificateAvailable = $category[0]->is_certificate_available($user_id); - if ($viewGridCourses) { - if ($certificateAvailable) { - $courses['not_category'][$key]['student_info']['certificate'] = get_lang('Yes'); - } else { - $courses['not_category'][$key]['student_info']['certificate'] = get_lang('No'); - } - } else { - if ($certificateAvailable) { - $courses['not_category'][$key]['student_info']['certificate'] = Display::label( - get_lang('Yes'), - 'success' - ); - } else { - $courses['not_category'][$key]['student_info']['certificate'] = Display::label( - get_lang('No'), - 'danger' - ); - } - } - } - } - } + $htmlCategory .= '
    '; + $htmlCategory .= self::getHtmlForCourse( + $listCourse['course'], + $userCategoryId, + 0, + $loadDirs + ); + $htmlCategory .= '
    '; } } - - if ($viewGridCourses) { - $coursesWithoutCategoryTemplate = '/user_portal/grid_courses_without_category.tpl'; - $coursesWithCategoryTemplate = '/user_portal/grid_courses_with_category.tpl'; + $htmlCategory .= ''; + $userCategoryHtml .= $htmlCategory; // end user cat block + if ($userCategoryId != 0) { + $userCategoryHtml .= '
    '; } + $html .= $userCategoryHtml; + } + $html .= '
    '; - if ($specialCourses) { - if ($categoryCodeFilter) { - $specialCourses = self::filterByCategory($specialCourses, $categoryCodeFilter); - } - $this->tpl->assign('courses', $specialCourses); - $specialCourseList = $this->tpl->fetch($this->tpl->get_template($coursesWithoutCategoryTemplate)); - $courseCompleteList = array_merge($courseCompleteList, $specialCourses); - } + return [ + 'html' => $html, + 'sessions' => $session_categories, + 'courses' => $listCoursesInfo, + 'session_count' => $sessionCount, + 'course_count' => $courseCount, + ]; + } - if ($courses['in_category'] || $courses['not_category']) { - foreach ($courses['in_category'] as $courseData) { - if (!empty($courseData['courses'])) { - $coursesInCategoryCount += count($courseData['courses']); - $courseCompleteList = array_merge($courseCompleteList, $courseData['courses']); - } - } + /** + * Return HTML code for personal user course category. + * + * @param $id + * @param $title + * + * @return string + */ + private static function getHtmlForUserCategory($id, $title) + { + if ($id == 0) { + return ''; + } + $icon = Display::return_icon( + 'folder_yellow.png', + $title, + ['class' => 'sessionView'], + ICON_SIZE_LARGE + ); - $coursesNotInCategoryCount += count($courses['not_category']); - $courseCompleteList = array_merge($courseCompleteList, $courses['not_category']); + return "
    $icon$title
    "; + } - if ($categoryCodeFilter) { - $courses['in_category'] = self::filterByCategory( - $courses['in_category'], - $categoryCodeFilter - ); - $courses['not_category'] = self::filterByCategory( - $courses['not_category'], - $categoryCodeFilter - ); - } + /** + * return HTML code for course display in session view. + * + * @param array $courseInfo + * @param $userCategoryId + * @param bool $displayButton + * @param $loadDirs + * + * @return string + */ + private static function getHtmlForCourse( + $courseInfo, + $userCategoryId, + $displayButton = false, + $loadDirs + ) { + if (empty($courseInfo)) { + return ''; + } - $this->tpl->assign('courses', $courses['not_category']); - $this->tpl->assign('categories', $courses['in_category']); + $id = $courseInfo['real_id']; + $title = $courseInfo['title']; + $code = $courseInfo['code']; - $listCourse = $this->tpl->fetch($this->tpl->get_template($coursesWithCategoryTemplate)); - $listCourse .= $this->tpl->fetch($this->tpl->get_template($coursesWithoutCategoryTemplate)); - } + $class = 'session-view-lvl-6'; + if ($userCategoryId != 0 && !$displayButton) { + $class = 'session-view-lvl-7'; + } - $courseCount = count($specialCourses) + $coursesInCategoryCount + $coursesNotInCategoryCount; + $class2 = 'session-view-lvl-6'; + if ($displayButton || $userCategoryId != 0) { + $class2 = 'session-view-lvl-7'; } - $sessions_with_category = ''; - $sessions_with_no_category = ''; - $collapsable = api_get_configuration_value('allow_user_session_collapsable'); - $collapsableLink = ''; - if ($collapsable) { - $collapsableLink = api_get_path(WEB_PATH).'user_portal.php?action=collapse_session'; + $button = ''; + if ($displayButton) { + $button = ''; } - $extraFieldValue = new ExtraFieldValue('session'); - if ($showSessions) { - $coursesListSessionStyle = api_get_configuration_value('courses_list_session_title_link'); - $coursesListSessionStyle = $coursesListSessionStyle === false ? 1 : $coursesListSessionStyle; - if (api_is_drh()) { - $coursesListSessionStyle = 1; - } + $icon = Display::return_icon( + 'blackboard.png', + $title, + ['class' => 'sessionView'], + ICON_SIZE_LARGE + ); - $portalShowDescription = api_get_setting('show_session_description') === 'true'; + $courseLink = $courseInfo['course_public_url'].'?id_session=0'; - // Declared listSession variable - $listSession = []; - // Get timestamp in UTC to compare to DB values (in UTC by convention) - $session_now = strtotime(api_get_utc_datetime(time())); - if (is_array($session_categories)) { - foreach ($session_categories as $session_category) { - $session_category_id = $session_category['session_category']['id']; - // Sessions and courses that are not in a session category - if (empty($session_category_id) && - isset($session_category['sessions']) - ) { - // Independent sessions - foreach ($session_category['sessions'] as $session) { - $session_id = $session['session_id']; + // get html course params + $courseParams = CourseManager::getCourseParamsForDisplay($id, $loadDirs); + $teachers = ''; + $rightActions = ''; - // Don't show empty sessions. - if (count($session['courses']) < 1) { - continue; - } + // teacher list + if (!empty($courseParams['teachers'])) { + $teachers = '

    '.$courseParams['teachers'].'

    '; + } - // Courses inside the current session. - $date_session_start = $session['access_start_date']; - $date_session_end = $session['access_end_date']; - $coachAccessStartDate = $session['coach_access_start_date']; - $coachAccessEndDate = $session['coach_access_end_date']; - $count_courses_session = 0; + // notification + if (!empty($courseParams['right_actions'])) { + $rightActions = '
    '.$courseParams['right_actions'].'
    '; + } - // Loop course content - $html_courses_session = []; - $atLeastOneCourseIsVisible = false; - $markAsOld = false; - $markAsFuture = false; - - foreach ($session['courses'] as $course) { - $is_coach_course = api_is_coach($session_id, $course['real_id']); - $allowed_time = 0; - $allowedEndTime = true; - - if (!empty($date_session_start)) { - if ($is_coach_course) { - $allowed_time = api_strtotime($coachAccessStartDate); - } else { - $allowed_time = api_strtotime($date_session_start); - } - - $endSessionToTms = null; - if (!isset($_GET['history'])) { - if (!empty($date_session_end)) { - if ($is_coach_course) { - // if coach end date is empty we use the default end date - if (empty($coachAccessEndDate)) { - $endSessionToTms = api_strtotime($date_session_end); - if ($session_now > $endSessionToTms) { - $allowedEndTime = false; - } - } else { - $endSessionToTms = api_strtotime($coachAccessEndDate); - if ($session_now > $endSessionToTms) { - $allowedEndTime = false; - } - } - } else { - $endSessionToTms = api_strtotime($date_session_end); - if ($session_now > $endSessionToTms) { - $allowedEndTime = false; - } - } - } - } - } - - if ($showAllSessions) { - if ($allowed_time < $session_now && $allowedEndTime === false) { - $markAsOld = true; - } - if ($allowed_time > $session_now && $endSessionToTms > $session_now) { - $markAsFuture = true; - } - $allowedEndTime = true; - $allowed_time = 0; - } - - if ($session_now >= $allowed_time && $allowedEndTime) { - // Read only and accessible. - $atLeastOneCourseIsVisible = true; - if (api_get_setting('hide_courses_in_sessions') === 'false') { - $courseUserHtml = CourseManager::get_logged_user_course_html( - $course, - $session_id, - 'session_course_item', - true, - $this->load_directories_preview - ); - if (isset($courseUserHtml[1])) { - $course_session = $courseUserHtml[1]; - $course_session['skill'] = isset($courseUserHtml['skill']) ? $courseUserHtml['skill'] : ''; - - // Course option (show student progress) - // This code will add new variables (Progress, Score, Certificate) - if ($studentInfoProgress || $studentInfoScore || $studentInfoCertificate) { - if ($studentInfoProgress) { - $progress = Tracking::get_avg_student_progress( - $user_id, - $course['course_code'], - [], - $session_id - ); - $course_session['student_info']['progress'] = $progress === false ? null : $progress; - } - - if ($studentInfoScore) { - $percentage_score = Tracking::get_avg_student_score( - $user_id, - $course['course_code'], - [], - $session_id - ); - $course_session['student_info']['score'] = $percentage_score; - } - - if ($studentInfoCertificate) { - $category = Category::load( - null, - null, - $course['course_code'], - null, - null, - $session_id - ); - $course_session['student_info']['certificate'] = null; - if (isset($category[0])) { - if ($category[0]->is_certificate_available($user_id)) { - $course_session['student_info']['certificate'] = Display::label( - get_lang('Yes'), - 'success' - ); - } else { - $course_session['student_info']['certificate'] = Display::label( - get_lang('No') - ); - } - } - } - } - $html_courses_session[] = $course_session; - } - } - $count_courses_session++; - } - } - - // No courses to show. - if ($atLeastOneCourseIsVisible === false) { - if (empty($html_courses_session)) { - continue; - } - } - - if ($count_courses_session > 0) { - $params = [ - 'id' => $session_id, - ]; - $session_box = Display::getSessionTitleBox($session_id); - $coachId = $session_box['id_coach']; - $imageField = $extraFieldValue->get_values_by_handler_and_field_variable( - $session_id, - 'image' - ); - - $params['category_id'] = $session_box['category_id']; - $params['title'] = $session_box['title']; - $params['id_coach'] = $coachId; - $params['coach_url'] = api_get_path(WEB_AJAX_PATH). - 'user_manager.ajax.php?a=get_user_popup&user_id='.$coachId; - $params['coach_name'] = !empty($session_box['coach']) ? $session_box['coach'] : null; - $params['coach_avatar'] = UserManager::getUserPicture( - $coachId, - USER_IMAGE_SIZE_SMALL - ); - $params['date'] = $session_box['dates']; - $params['image'] = isset($imageField['value']) ? $imageField['value'] : null; - $params['duration'] = isset($session_box['duration']) ? ' '.$session_box['duration'] : null; - $params['show_actions'] = SessionManager::cantEditSession($session_id); - - if ($collapsable) { - $collapsableData = SessionManager::getCollapsableData( - $user_id, - $session_id, - $extraFieldValue, - $collapsableLink - ); - $params['collapsed'] = $collapsableData['collapsed']; - $params['collapsable_link'] = $collapsableData['collapsable_link']; - } - - $params['show_description'] = $session_box['show_description'] == 1 && $portalShowDescription; - $params['description'] = $session_box['description']; - $params['visibility'] = $session_box['visibility']; - $params['show_simple_session_info'] = $showSimpleSessionInfo; - $params['course_list_session_style'] = $coursesListSessionStyle; - $params['num_users'] = $session_box['num_users']; - $params['num_courses'] = $session_box['num_courses']; - $params['course_categories'] = CourseManager::getCourseCategoriesFromCourseList( - $html_courses_session - ); - $params['courses'] = $html_courses_session; - $params['is_old'] = $markAsOld; - $params['is_future'] = $markAsFuture; - - if ($showSimpleSessionInfo) { - $params['subtitle'] = self::getSimpleSessionDetails( - $session_box['coach'], - $session_box['dates'], - isset($session_box['duration']) ? $session_box['duration'] : null - ); - } - - if ($gameModeIsActive) { - $params['stars'] = GamificationUtils::getSessionStars( - $params['id'], - $this->user_id - ); - $params['progress'] = GamificationUtils::getSessionProgress( - $params['id'], - $this->user_id - ); - $params['points'] = GamificationUtils::getSessionPoints( - $params['id'], - $this->user_id - ); - } - $listSession[] = $params; - $sessionCount++; - } - } - } else { - // All sessions included in - $count_courses_session = 0; - $html_sessions = ''; - if (isset($session_category['sessions'])) { - foreach ($session_category['sessions'] as $session) { - $session_id = $session['session_id']; - - // Don't show empty sessions. - if (count($session['courses']) < 1) { - continue; - } - - $date_session_start = $session['access_start_date']; - $date_session_end = $session['access_end_date']; - $coachAccessStartDate = $session['coach_access_start_date']; - $coachAccessEndDate = $session['coach_access_end_date']; - $html_courses_session = []; - $count = 0; - $markAsOld = false; - $markAsFuture = false; + $notifications = isset($courseParams['notifications']) ? $courseParams['notifications'] : ''; - foreach ($session['courses'] as $course) { - $is_coach_course = api_is_coach($session_id, $course['real_id']); - $allowed_time = 0; - $allowedEndTime = true; + return "
    + $button + $icon + $title + + $notifications + $rightActions +
    + $teachers"; + } - if (!empty($date_session_start)) { - if ($is_coach_course) { - $allowed_time = api_strtotime($coachAccessStartDate); - } else { - $allowed_time = api_strtotime($date_session_start); - } + /** + * return HTML code for session category. + * + * @param $id + * @param $title + * + * @return string + */ + private static function getHtmlSessionCategory($id, $title) + { + if ($id == 0) { + return ''; + } - if (!isset($_GET['history'])) { - if (!empty($date_session_end)) { - if ($is_coach_course) { - // if coach end date is empty we use the default end date - if (empty($coachAccessEndDate)) { - $endSessionToTms = api_strtotime($date_session_end); - if ($session_now > $endSessionToTms) { - $allowedEndTime = false; - } - } else { - $endSessionToTms = api_strtotime($coachAccessEndDate); - if ($session_now > $endSessionToTms) { - $allowedEndTime = false; - } - } - } else { - $endSessionToTms = api_strtotime($date_session_end); - if ($session_now > $endSessionToTms) { - $allowedEndTime = false; - } - } - } - } - } + $icon = Display::return_icon( + 'folder_blue.png', + $title, + ['class' => 'sessionView'], + ICON_SIZE_LARGE + ); - if ($showAllSessions) { - if ($allowed_time < $session_now && $allowedEndTime == false) { - $markAsOld = true; - } - if ($allowed_time > $session_now && $endSessionToTms > $session_now) { - $markAsFuture = true; - } - $allowedEndTime = true; - $allowed_time = 0; - } + return "
    + + $icon + $title + +
    "; + } - if ($session_now >= $allowed_time && $allowedEndTime) { - if (api_get_setting('hide_courses_in_sessions') === 'false') { - $c = CourseManager::get_logged_user_course_html( - $course, - $session_id, - 'session_course_item' - ); - if (isset($c[1])) { - $html_courses_session[] = $c[1]; - } - } - $count_courses_session++; - $count++; - } - } + /** + * return HTML code for session. + * + * @param int $id session id + * @param string $title session title + * @param int $categorySessionId + * @param array $courseInfo + * + * @return string + */ + private static function getHtmlForSession($id, $title, $categorySessionId, $courseInfo) + { + $html = ''; + if ($categorySessionId == 0) { + $class1 = 'session-view-lvl-2'; // session + $class2 = 'session-view-lvl-4'; // got to course in session link + } else { + $class1 = 'session-view-lvl-3'; // session + $class2 = 'session-view-lvl-5'; // got to course in session link + } - $sessionParams = []; - // Category - if ($count > 0) { - $session_box = Display::getSessionTitleBox($session_id); - $sessionParams[0]['id'] = $session_id; - $sessionParams[0]['date'] = $session_box['dates']; - $sessionParams[0]['duration'] = isset($session_box['duration']) ? ' '.$session_box['duration'] : null; - $sessionParams[0]['course_list_session_style'] = $coursesListSessionStyle; - $sessionParams[0]['title'] = $session_box['title']; - $sessionParams[0]['subtitle'] = (!empty($session_box['coach']) ? $session_box['coach'].' | ' : '').$session_box['dates']; - $sessionParams[0]['show_actions'] = SessionManager::cantEditSession($session_id); - $sessionParams[0]['courses'] = $html_courses_session; - $sessionParams[0]['show_simple_session_info'] = $showSimpleSessionInfo; - $sessionParams[0]['coach_name'] = !empty($session_box['coach']) ? $session_box['coach'] : null; - $sessionParams[0]['is_old'] = $markAsOld; - $sessionParams[0]['is_future'] = $markAsFuture; + $icon = Display::return_icon( + 'session.png', + $title, + ['class' => 'sessionView'], + ICON_SIZE_LARGE + ); + $courseLink = $courseInfo['course_public_url'].'?id_session='.intval($id); - if ($collapsable) { - $collapsableData = SessionManager::getCollapsableData( - $user_id, - $session_id, - $extraFieldValue, - $collapsableLink - ); - $sessionParams[0]['collapsable_link'] = $collapsableData['collapsable_link']; - $sessionParams[0]['collapsed'] = $collapsableData['collapsed']; - } + $html .= "$icon$title"; + $html .= ''; - if ($showSimpleSessionInfo) { - $sessionParams[0]['subtitle'] = self::getSimpleSessionDetails( - $session_box['coach'], - $session_box['dates'], - isset($session_box['duration']) ? $session_box['duration'] : null - ); - } + return '
    '.$html.'
    '; + } - $this->tpl->assign('session', $sessionParams); - $this->tpl->assign('show_tutor', api_get_setting('show_session_coach') === 'true'); - $this->tpl->assign('gamification_mode', $gameModeIsActive); - $this->tpl->assign('remove_session_url', api_get_configuration_value('remove_session_url')); - $this->tpl->assign( - 'hide_session_dates_in_user_portal', - api_get_configuration_value('hide_session_dates_in_user_portal') - ); + /** + * @param int $userId + * + * @return array + */ + public function returnCourseCategoryListFromUser($userId) + { + $sessionCount = 0; + $courseList = CourseManager::get_courses_list_by_user_id($userId); + $categoryCodes = CourseManager::getCourseCategoriesFromCourseList($courseList); + $categories = []; + foreach ($categoryCodes as $categoryCode) { + $categories[] = CourseCategory::getCategory($categoryCode); + } - if ($viewGridCourses) { - $html_sessions .= $this->tpl->fetch( - $this->tpl->get_template('/user_portal/grid_session.tpl') - ); - } else { - $html_sessions .= $this->tpl->fetch( - $this->tpl->get_template('user_portal/classic_session.tpl') - ); - } - $sessionCount++; - } - } - } + $template = new Template('', false, false, false, true, false, false); + $layout = $template->get_template('user_portal/course_categories.tpl'); + $template->assign('course_categories', $categories); - if ($count_courses_session > 0) { - $categoryParams = [ - 'id' => $session_category['session_category']['id'], - 'title' => $session_category['session_category']['name'], - 'show_actions' => api_is_platform_admin(), - 'subtitle' => '', - 'sessions' => $html_sessions, - ]; + return [ + 'courses' => $courseList, + 'html' => $template->fetch($layout), + 'course_count' => count($courseList), + 'session_count' => $sessionCount, + ]; + } - $session_category_start_date = $session_category['session_category']['date_start']; - $session_category_end_date = $session_category['session_category']['date_end']; - if ($session_category_start_date == '0000-00-00') { - $session_category_start_date = ''; - } + /** + * Set grade book dependency progress bar see BT#13099. + * + * @param $userId + * + * @return bool + */ + public function setGradeBookDependencyBar($userId) + { + $allow = api_get_configuration_value('gradebook_dependency'); - if ($session_category_end_date == '0000-00-00') { - $session_category_end_date = ''; - } + if (api_is_anonymous()) { + return false; + } - if (!empty($session_category_start_date) && - !empty($session_category_end_date) - ) { - $categoryParams['subtitle'] = sprintf( - get_lang('FromDateXToDateY'), - $session_category_start_date, - $session_category_end_date - ); - } else { - if (!empty($session_category_start_date)) { - $categoryParams['subtitle'] = get_lang('From').' '.$session_category_start_date; - } + if ($allow) { + $courseAndSessions = $this->returnCoursesAndSessions( + $userId, + false, + '', + false, + false + ); - if (!empty($session_category_end_date)) { - $categoryParams['subtitle'] = get_lang('Until').' '.$session_category_end_date; - } - } + $courseList = api_get_configuration_value('gradebook_dependency_mandatory_courses'); + $courseList = isset($courseList['courses']) ? $courseList['courses'] : []; + $mandatoryCourse = []; + if (!empty($courseList)) { + foreach ($courseList as $courseId) { + $courseInfo = api_get_course_info_by_id($courseId); + $mandatoryCourse[] = $courseInfo['code']; + } + } - $this->tpl->assign('session_category', $categoryParams); - $sessions_with_category .= $this->tpl->fetch( - $this->tpl->get_template('user_portal/session_category.tpl') - ); + // @todo improve calls of course info + $subscribedCourses = !empty($courseAndSessions['courses']) ? $courseAndSessions['courses'] : []; + $mainCategoryList = []; + foreach ($subscribedCourses as $courseInfo) { + $courseCode = $courseInfo['code']; + $categories = Category::load(null, null, $courseCode); + /** @var Category $category */ + $category = !empty($categories[0]) ? $categories[0] : []; + if (!empty($category)) { + $mainCategoryList[] = $category; + } + } + + $result20 = 0; + $result80 = 0; + $countCoursesPassedNoDependency = 0; + /** @var Category $category */ + foreach ($mainCategoryList as $category) { + $userFinished = Category::userFinishedCourse( + $userId, + $category, + true + ); + + if ($userFinished) { + if (in_array($category->get_course_code(), $mandatoryCourse)) { + if ($result20 < 20) { + $result20 += 10; + } + } else { + $countCoursesPassedNoDependency++; + if ($result80 < 80) { + $result80 += 10; } } } + } - $allCoursesInSessions = []; - foreach ($listSession as $currentSession) { - $coursesInSessions = $currentSession['courses']; - unset($currentSession['courses']); - foreach ($coursesInSessions as $coursesInSession) { - $coursesInSession['session'] = $currentSession; - $allCoursesInSessions[] = $coursesInSession; + $finalResult = $result20 + $result80; + + $gradeBookList = api_get_configuration_value('gradebook_badge_sidebar'); + $gradeBookList = isset($gradeBookList['gradebooks']) ? $gradeBookList['gradebooks'] : []; + $badgeList = []; + foreach ($gradeBookList as $id) { + $categories = Category::load($id); + /** @var Category $category */ + $category = !empty($categories[0]) ? $categories[0] : []; + $badgeList[$id]['name'] = $category->get_name(); + $badgeList[$id]['finished'] = false; + $badgeList[$id]['skills'] = []; + if (!empty($category)) { + $minToValidate = $category->getMinimumToValidate(); + $dependencies = $category->getCourseListDependency(); + $gradeBooksToValidateInDependence = $category->getGradeBooksToValidateInDependence(); + $countDependenciesPassed = 0; + foreach ($dependencies as $courseId) { + $courseInfo = api_get_course_info_by_id($courseId); + $courseCode = $courseInfo['code']; + $categories = Category::load(null, null, $courseCode); + $subCategory = !empty($categories[0]) ? $categories[0] : null; + if (!empty($subCategory)) { + $score = Category::userFinishedCourse( + $userId, + $subCategory, + true + ); + if ($score) { + $countDependenciesPassed++; + } + } } - } - $this->tpl->assign('all_courses', $allCoursesInSessions); - $this->tpl->assign('session', $listSession); - $this->tpl->assign('show_tutor', (api_get_setting('show_session_coach') === 'true' ? true : false)); - $this->tpl->assign('gamification_mode', $gameModeIsActive); - $this->tpl->assign('remove_session_url', api_get_configuration_value('remove_session_url')); - $this->tpl->assign( - 'hide_session_dates_in_user_portal', - api_get_configuration_value('hide_session_dates_in_user_portal') - ); + $userFinished = + $countDependenciesPassed >= $gradeBooksToValidateInDependence && + $countCoursesPassedNoDependency >= $minToValidate; - if ($viewGridCourses) { - $sessions_with_no_category = $this->tpl->fetch( - $this->tpl->get_template('/user_portal/grid_session.tpl') - ); - } else { - $sessions_with_no_category = $this->tpl->fetch( - $this->tpl->get_template('user_portal/classic_session.tpl') - ); + if ($userFinished) { + $badgeList[$id]['finished'] = true; + } + + $objSkill = new Skill(); + $skills = $category->get_skills(); + $skillList = []; + foreach ($skills as $skill) { + $skillList[] = $objSkill->get($skill['id']); + } + $badgeList[$id]['skills'] = $skillList; } } - } - - return [ - 'courses' => $courseCompleteList, - 'sessions' => $session_categories, - 'html' => trim($specialCourseList.$sessions_with_category.$sessions_with_no_category.$listCourse), - 'session_count' => $sessionCount, - 'course_count' => $courseCount, - ]; - } - - /** - * Shows a welcome message when the user doesn't have any content in the course list. - */ - public function return_welcome_to_course_block() - { - $count_courses = CourseManager::count_courses(); - $tpl = $this->tpl->get_template('layout/welcome_to_course.tpl'); - $course_catalog_url = api_get_path(WEB_CODE_PATH).'auth/courses.php'; - $course_list_url = api_get_path(WEB_PATH).'user_portal.php'; + $this->tpl->assign( + 'grade_book_sidebar', + true + ); - $this->tpl->assign('course_catalog_url', $course_catalog_url); - $this->tpl->assign('course_list_url', $course_list_url); - $this->tpl->assign('course_catalog_link', Display::url(get_lang('Here'), $course_catalog_url)); - $this->tpl->assign('course_list_link', Display::url(get_lang('Here'), $course_list_url)); - $this->tpl->assign('count_courses', $count_courses); + $this->tpl->assign( + 'grade_book_progress', + $finalResult + ); + $this->tpl->assign('grade_book_badge_list', $badgeList); - return $this->tpl->fetch($tpl); - } + return true; + } - /** - * @return array - */ - public function return_hot_courses() - { - return CourseManager::return_hot_courses(30, 6); + return false; } /** - * UserPortal view for session, return the HTML of the course list. + * Prints the session and course list (user_portal.php). * - * @param $user_id + * @param int $user_id + * @param bool $showSessions + * @param string $categoryCodeFilter + * @param bool $useUserLanguageFilterIfAvailable + * @param bool $loadHistory * - * @return string + * @return array */ - public function returnCoursesAndSessionsViewBySession($user_id) - { - $sessionCount = 0; - $courseCount = 0; - $load_history = (isset($_GET['history']) && intval($_GET['history']) == 1) ? true : false; + public function returnCoursesAndSessions( + $user_id, + $showSessions = true, + $categoryCodeFilter = '', + $useUserLanguageFilterIfAvailable = true, + $loadHistory = false + ) { + $gameModeIsActive = api_get_setting('gamification_mode'); + $viewGridCourses = api_get_configuration_value('view_grid_courses'); + $showSimpleSessionInfo = api_get_configuration_value('show_simple_session_info'); + $coursesWithoutCategoryTemplate = '/user_portal/classic_courses_without_category.tpl'; + $coursesWithCategoryTemplate = '/user_portal/classic_courses_with_category.tpl'; + $showAllSessions = api_get_configuration_value('show_all_sessions_on_my_course_page') === true; - if ($load_history) { + if ($loadHistory) { // Load sessions in category in *history* $session_categories = UserManager::get_sessions_by_category($user_id, true); } else { @@ -1919,589 +1779,764 @@ class IndexManager $session_categories = UserManager::get_sessions_by_category($user_id, false); } - $html = ''; - $loadDirs = $this->load_directories_preview; + $sessionCount = 0; + $courseCount = 0; + + // Student info code check (shows student progress information on + // courses list + $studentInfo = api_get_configuration_value('course_student_info'); + + $studentInfoProgress = !empty($studentInfo['progress']) && $studentInfo['progress'] === true; + $studentInfoScore = !empty($studentInfo['score']) && $studentInfo['score'] === true; + $studentInfoCertificate = !empty($studentInfo['certificate']) && $studentInfo['certificate'] === true; + $courseCompleteList = []; + $coursesInCategoryCount = 0; + $coursesNotInCategoryCount = 0; + $listCourse = ''; + $specialCourseList = ''; // If we're not in the history view... - $listCoursesInfo = []; - if (!isset($_GET['history'])) { - // Display special courses - $specialCoursesResult = CourseManager::returnSpecialCourses( + if ($loadHistory === false) { + // Display special courses. + $specialCourses = CourseManager::returnSpecialCourses( $user_id, - $loadDirs + $this->load_directories_preview, + $useUserLanguageFilterIfAvailable ); - $specialCourses = $specialCoursesResult; - - if ($specialCourses) { - $this->tpl->assign('courses', $specialCourses); - $html = $this->tpl->fetch( - $this->tpl->get_template('/user_portal/classic_courses_without_category.tpl') - ); - } - // Display courses - // [code=>xxx, real_id=>000] - $listCourses = CourseManager::get_courses_list_by_user_id( + // Display courses. + $courses = CourseManager::returnCourses( $user_id, - false + $this->load_directories_preview, + $useUserLanguageFilterIfAvailable ); - foreach ($listCourses as $i => $listCourseCodeId) { - if (isset($listCourseCodeId['special_course'])) { - continue; - } - $courseCategory = CourseManager::getUserCourseCategoryForCourse( - $user_id, - $listCourseCodeId['real_id'] - ); + // Course option (show student progress) + // This code will add new variables (Progress, Score, Certificate) + if ($studentInfoProgress || $studentInfoScore || $studentInfoCertificate) { + if (!empty($specialCourses)) { + foreach ($specialCourses as $key => $specialCourseInfo) { + if ($studentInfoProgress) { + $progress = Tracking::get_avg_student_progress( + $user_id, + $specialCourseInfo['course_code'] + ); + $specialCourses[$key]['student_info']['progress'] = $progress === false ? null : $progress; + } + + if ($studentInfoScore) { + $percentage_score = Tracking::get_avg_student_score( + $user_id, + $specialCourseInfo['course_code'], + [] + ); + $specialCourses[$key]['student_info']['score'] = $percentage_score; + } + + if ($studentInfoCertificate) { + $category = Category::load( + null, + null, + $specialCourseInfo['course_code'], + null, + null, + null + ); + $specialCourses[$key]['student_info']['certificate'] = null; + if (isset($category[0])) { + if ($category[0]->is_certificate_available($user_id)) { + $specialCourses[$key]['student_info']['certificate'] = Display::label( + get_lang('Yes'), + 'success' + ); + } else { + $specialCourses[$key]['student_info']['certificate'] = Display::label( + get_lang('No'), + 'danger' + ); + } + } + } + } + } + + if (isset($courses['in_category'])) { + foreach ($courses['in_category'] as $key1 => $value) { + if (isset($courses['in_category'][$key1]['courses'])) { + foreach ($courses['in_category'][$key1]['courses'] as $key2 => $courseInCatInfo) { + $courseCode = $courseInCatInfo['course_code']; + if ($studentInfoProgress) { + $progress = Tracking::get_avg_student_progress( + $user_id, + $courseCode + ); + $courses['in_category'][$key1]['courses'][$key2]['student_info']['progress'] = $progress === false ? null : $progress; + } + + if ($studentInfoScore) { + $percentage_score = Tracking::get_avg_student_score( + $user_id, + $courseCode, + [] + ); + $courses['in_category'][$key1]['courses'][$key2]['student_info']['score'] = $percentage_score; + } + + if ($studentInfoCertificate) { + $category = Category::load( + null, + null, + $courseCode, + null, + null, + null + ); + $courses['in_category'][$key1]['student_info']['certificate'] = null; + $isCertificateAvailable = $category[0]->is_certificate_available($user_id); + if (isset($category[0])) { + if ($viewGridCourses) { + if ($isCertificateAvailable) { + $courses['in_category'][$key1]['student_info']['certificate'] = get_lang( + 'Yes' + ); + } else { + $courses['in_category'][$key1]['student_info']['certificate'] = get_lang( + 'No' + ); + } + } else { + if ($isCertificateAvailable) { + $courses['in_category'][$key1]['student_info']['certificate'] = Display::label( + get_lang('Yes'), + 'success' + ); + } else { + $courses['in_category'][$key1]['student_info']['certificate'] = Display::label( + get_lang('No'), + 'danger' + ); + } + } + } + } + } + } + } + } + + if (isset($courses['not_category'])) { + foreach ($courses['not_category'] as $key => $courseNotInCatInfo) { + $courseCode = $courseNotInCatInfo['course_code']; + if ($studentInfoProgress) { + $progress = Tracking::get_avg_student_progress( + $user_id, + $courseCode + ); + $courses['not_category'][$key]['student_info']['progress'] = $progress === false ? null : $progress; + } + + if ($studentInfoScore) { + $percentage_score = Tracking::get_avg_student_score( + $user_id, + $courseCode, + [] + ); + $courses['not_category'][$key]['student_info']['score'] = $percentage_score; + } + + if ($studentInfoCertificate) { + $category = Category::load( + null, + null, + $courseCode, + null, + null, + null + ); + $courses['not_category'][$key]['student_info']['certificate'] = null; - $userCatTitle = ''; - $userCategoryId = 0; - if ($courseCategory) { - $userCategoryId = $courseCategory['user_course_cat']; - $userCatTitle = $courseCategory['title']; + if (isset($category[0])) { + $certificateAvailable = $category[0]->is_certificate_available($user_id); + if ($viewGridCourses) { + if ($certificateAvailable) { + $courses['not_category'][$key]['student_info']['certificate'] = get_lang('Yes'); + } else { + $courses['not_category'][$key]['student_info']['certificate'] = get_lang('No'); + } + } else { + if ($certificateAvailable) { + $courses['not_category'][$key]['student_info']['certificate'] = Display::label( + get_lang('Yes'), + 'success' + ); + } else { + $courses['not_category'][$key]['student_info']['certificate'] = Display::label( + get_lang('No'), + 'danger' + ); + } + } + } + } + } } - - $listCourse = api_get_course_info_by_id($listCourseCodeId['real_id']); - $listCoursesInfo[] = [ - 'course' => $listCourse, - 'code' => $listCourseCodeId['code'], - 'id' => $listCourseCodeId['real_id'], - 'title' => $listCourse['title'], - 'userCatId' => $userCategoryId, - 'userCatTitle' => $userCatTitle, - ]; - $courseCount++; } - usort($listCoursesInfo, 'self::compareByCourse'); - } - - $listCoursesInSession = []; - if (is_array($session_categories)) { - // all courses that are in a session - $listCoursesInSession = SessionManager::getNamedSessionCourseForCoach($user_id); - } - - // we got all courses - // for each user category, sorted alphabetically, display courses - $listUserCategories = CourseManager::get_user_course_categories($user_id); - $listCoursesAlreadyDisplayed = []; - uasort($listUserCategories, "self::compareListUserCategory"); - $listUserCategories[0] = ''; - $html .= '
    '; - foreach ($listUserCategories as $userCategoryId => $userCat) { - // add user category - $userCategoryHtml = ''; - if ($userCategoryId != 0) { - $userCategoryHtml = '
    '; - $userCategoryHtml .= self::getHtmlForUserCategory($userCategoryId, $userCat['title']); + if ($viewGridCourses) { + $coursesWithoutCategoryTemplate = '/user_portal/grid_courses_without_category.tpl'; + $coursesWithCategoryTemplate = '/user_portal/grid_courses_with_category.tpl'; } - // look for course in this userCat in session courses : $listCoursesInSession - $htmlCategory = ''; - if (isset($listCoursesInSession[$userCategoryId])) { - // list of courses in this user cat - foreach ($listCoursesInSession[$userCategoryId]['courseInUserCatList'] as $i => $listCourse) { - // add course - $listCoursesAlreadyDisplayed[$listCourse['courseId']] = 1; - if ($userCategoryId == 0) { - $htmlCategory .= '
    '; - } else { - $htmlCategory .= '
    '; - } - $htmlCategory .= '
    '; - $coursesInfo = $listCourse['course']; - $htmlCategory .= self::getHtmlForCourse( - $coursesInfo, - $userCategoryId, - 1, - $loadDirs - ); - // list of session category - $htmlSessionCategory = ''; // end session cat block - $htmlCategory .= $htmlSessionCategory.'
    '; - $htmlCategory .= ''; // end course block + if ($specialCourses) { + if ($categoryCodeFilter) { + $specialCourses = self::filterByCategory($specialCourses, $categoryCodeFilter); } - $userCategoryHtml .= $htmlCategory; + $this->tpl->assign('courses', $specialCourses); + $specialCourseList = $this->tpl->fetch($this->tpl->get_template($coursesWithoutCategoryTemplate)); + $courseCompleteList = array_merge($courseCompleteList, $specialCourses); } - // look for courses in this userCat in not in session courses : $listCoursesInfo - // if course not already added - $htmlCategory = ''; - foreach ($listCoursesInfo as $i => $listCourse) { - if ($listCourse['userCatId'] == $userCategoryId && - !isset($listCoursesAlreadyDisplayed[$listCourse['id']]) - ) { - if ($userCategoryId != 0) { - $htmlCategory .= '
    '; - } else { - $htmlCategory .= '
    '; + if ($courses['in_category'] || $courses['not_category']) { + foreach ($courses['in_category'] as $courseData) { + if (!empty($courseData['courses'])) { + $coursesInCategoryCount += count($courseData['courses']); + $courseCompleteList = array_merge($courseCompleteList, $courseData['courses']); } + } - $htmlCategory .= '
    '; - $htmlCategory .= self::getHtmlForCourse( - $listCourse['course'], - $userCategoryId, - 0, - $loadDirs + $coursesNotInCategoryCount += count($courses['not_category']); + $courseCompleteList = array_merge($courseCompleteList, $courses['not_category']); + + if ($categoryCodeFilter) { + $courses['in_category'] = self::filterByCategory( + $courses['in_category'], + $categoryCodeFilter + ); + $courses['not_category'] = self::filterByCategory( + $courses['not_category'], + $categoryCodeFilter ); - $htmlCategory .= '
    '; } - } - $htmlCategory .= ''; - $userCategoryHtml .= $htmlCategory; // end user cat block - if ($userCategoryId != 0) { - $userCategoryHtml .= '
    '; - } - $html .= $userCategoryHtml; - } - $html .= '
    '; - return [ - 'html' => $html, - 'sessions' => $session_categories, - 'courses' => $listCoursesInfo, - 'session_count' => $sessionCount, - 'course_count' => $courseCount, - ]; - } + $this->tpl->assign('courses', $courses['not_category']); + $this->tpl->assign('categories', $courses['in_category']); - /** - * @param $listA - * @param $listB - * - * @return int - */ - public static function compareListUserCategory($listA, $listB) - { - if ($listA['title'] == $listB['title']) { - return 0; + $listCourse = $this->tpl->fetch($this->tpl->get_template($coursesWithCategoryTemplate)); + $listCourse .= $this->tpl->fetch($this->tpl->get_template($coursesWithoutCategoryTemplate)); + } + + $courseCount = count($specialCourses) + $coursesInCategoryCount + $coursesNotInCategoryCount; } - if ($listA['title'] > $listB['title']) { - return 1; + $sessions_with_category = ''; + $sessions_with_no_category = ''; + $collapsable = api_get_configuration_value('allow_user_session_collapsable'); + $collapsableLink = ''; + if ($collapsable) { + $collapsableLink = api_get_path(WEB_PATH).'user_portal.php?action=collapse_session'; } - return -1; - } + $extraFieldValue = new ExtraFieldValue('session'); + if ($showSessions) { + $coursesListSessionStyle = api_get_configuration_value('courses_list_session_title_link'); + $coursesListSessionStyle = $coursesListSessionStyle === false ? 1 : $coursesListSessionStyle; + if (api_is_drh()) { + $coursesListSessionStyle = 1; + } - /** - * @param $view - * @param $userId - */ - public static function setDefaultMyCourseView($view, $userId) - { - setcookie('defaultMyCourseView'.$userId, $view); - } + $portalShowDescription = api_get_setting('show_session_description') === 'true'; - /** - * @param int $userId - * - * @return array - */ - public function returnCourseCategoryListFromUser($userId) - { - $sessionCount = 0; - $courseList = CourseManager::get_courses_list_by_user_id($userId); - $categoryCodes = CourseManager::getCourseCategoriesFromCourseList($courseList); - $categories = []; - foreach ($categoryCodes as $categoryCode) { - $categories[] = CourseCategory::getCategory($categoryCode); - } + // Declared listSession variable + $listSession = []; + // Get timestamp in UTC to compare to DB values (in UTC by convention) + $session_now = strtotime(api_get_utc_datetime(time())); + if (is_array($session_categories)) { + foreach ($session_categories as $session_category) { + $session_category_id = $session_category['session_category']['id']; + // Sessions and courses that are not in a session category + if (empty($session_category_id) && + isset($session_category['sessions']) + ) { + // Independent sessions + foreach ($session_category['sessions'] as $session) { + $session_id = $session['session_id']; - $template = new Template('', false, false, false, true, false, false); - $layout = $template->get_template('user_portal/course_categories.tpl'); - $template->assign('course_categories', $categories); + // Don't show empty sessions. + if (count($session['courses']) < 1) { + continue; + } - return [ - 'courses' => $courseList, - 'html' => $template->fetch($layout), - 'course_count' => count($courseList), - 'session_count' => $sessionCount, - ]; - } + // Courses inside the current session. + $date_session_start = $session['access_start_date']; + $date_session_end = $session['access_end_date']; + $coachAccessStartDate = $session['coach_access_start_date']; + $coachAccessEndDate = $session['coach_access_end_date']; + $count_courses_session = 0; - /** - * Set grade book dependency progress bar see BT#13099. - * - * @param $userId - * - * @return bool - */ - public function setGradeBookDependencyBar($userId) - { - $allow = api_get_configuration_value('gradebook_dependency'); + // Loop course content + $html_courses_session = []; + $atLeastOneCourseIsVisible = false; + $markAsOld = false; + $markAsFuture = false; - if (api_is_anonymous()) { - return false; - } + foreach ($session['courses'] as $course) { + $is_coach_course = api_is_coach($session_id, $course['real_id']); + $allowed_time = 0; + $allowedEndTime = true; - if ($allow) { - $courseAndSessions = $this->returnCoursesAndSessions( - $userId, - false, - '', - false, - false - ); + if (!empty($date_session_start)) { + if ($is_coach_course) { + $allowed_time = api_strtotime($coachAccessStartDate); + } else { + $allowed_time = api_strtotime($date_session_start); + } - $courseList = api_get_configuration_value('gradebook_dependency_mandatory_courses'); - $courseList = isset($courseList['courses']) ? $courseList['courses'] : []; - $mandatoryCourse = []; - if (!empty($courseList)) { - foreach ($courseList as $courseId) { - $courseInfo = api_get_course_info_by_id($courseId); - $mandatoryCourse[] = $courseInfo['code']; - } - } + $endSessionToTms = null; + if (!isset($_GET['history'])) { + if (!empty($date_session_end)) { + if ($is_coach_course) { + // if coach end date is empty we use the default end date + if (empty($coachAccessEndDate)) { + $endSessionToTms = api_strtotime($date_session_end); + if ($session_now > $endSessionToTms) { + $allowedEndTime = false; + } + } else { + $endSessionToTms = api_strtotime($coachAccessEndDate); + if ($session_now > $endSessionToTms) { + $allowedEndTime = false; + } + } + } else { + $endSessionToTms = api_strtotime($date_session_end); + if ($session_now > $endSessionToTms) { + $allowedEndTime = false; + } + } + } + } + } - // @todo improve calls of course info - $subscribedCourses = !empty($courseAndSessions['courses']) ? $courseAndSessions['courses'] : []; - $mainCategoryList = []; - foreach ($subscribedCourses as $courseInfo) { - $courseCode = $courseInfo['code']; - $categories = Category::load(null, null, $courseCode); - /** @var Category $category */ - $category = !empty($categories[0]) ? $categories[0] : []; - if (!empty($category)) { - $mainCategoryList[] = $category; - } - } + if ($showAllSessions) { + if ($allowed_time < $session_now && $allowedEndTime === false) { + $markAsOld = true; + } + if ($allowed_time > $session_now && $endSessionToTms > $session_now) { + $markAsFuture = true; + } + $allowedEndTime = true; + $allowed_time = 0; + } - $result20 = 0; - $result80 = 0; - $countCoursesPassedNoDependency = 0; - /** @var Category $category */ - foreach ($mainCategoryList as $category) { - $userFinished = Category::userFinishedCourse( - $userId, - $category, - true - ); + if ($session_now >= $allowed_time && $allowedEndTime) { + // Read only and accessible. + $atLeastOneCourseIsVisible = true; + if (api_get_setting('hide_courses_in_sessions') === 'false') { + $courseUserHtml = CourseManager::get_logged_user_course_html( + $course, + $session_id, + 'session_course_item', + true, + $this->load_directories_preview + ); + if (isset($courseUserHtml[1])) { + $course_session = $courseUserHtml[1]; + $course_session['skill'] = isset($courseUserHtml['skill']) ? $courseUserHtml['skill'] : ''; - if ($userFinished) { - if (in_array($category->get_course_code(), $mandatoryCourse)) { - if ($result20 < 20) { - $result20 += 10; - } - } else { - $countCoursesPassedNoDependency++; - if ($result80 < 80) { - $result80 += 10; - } - } - } - } + // Course option (show student progress) + // This code will add new variables (Progress, Score, Certificate) + if ($studentInfoProgress || $studentInfoScore || $studentInfoCertificate) { + if ($studentInfoProgress) { + $progress = Tracking::get_avg_student_progress( + $user_id, + $course['course_code'], + [], + $session_id + ); + $course_session['student_info']['progress'] = $progress === false ? null : $progress; + } - $finalResult = $result20 + $result80; + if ($studentInfoScore) { + $percentage_score = Tracking::get_avg_student_score( + $user_id, + $course['course_code'], + [], + $session_id + ); + $course_session['student_info']['score'] = $percentage_score; + } - $gradeBookList = api_get_configuration_value('gradebook_badge_sidebar'); - $gradeBookList = isset($gradeBookList['gradebooks']) ? $gradeBookList['gradebooks'] : []; - $badgeList = []; - foreach ($gradeBookList as $id) { - $categories = Category::load($id); - /** @var Category $category */ - $category = !empty($categories[0]) ? $categories[0] : []; - $badgeList[$id]['name'] = $category->get_name(); - $badgeList[$id]['finished'] = false; - $badgeList[$id]['skills'] = []; - if (!empty($category)) { - $minToValidate = $category->getMinimumToValidate(); - $dependencies = $category->getCourseListDependency(); - $gradeBooksToValidateInDependence = $category->getGradeBooksToValidateInDependence(); - $countDependenciesPassed = 0; - foreach ($dependencies as $courseId) { - $courseInfo = api_get_course_info_by_id($courseId); - $courseCode = $courseInfo['code']; - $categories = Category::load(null, null, $courseCode); - $subCategory = !empty($categories[0]) ? $categories[0] : null; - if (!empty($subCategory)) { - $score = Category::userFinishedCourse( - $userId, - $subCategory, - true - ); - if ($score) { - $countDependenciesPassed++; + if ($studentInfoCertificate) { + $category = Category::load( + null, + null, + $course['course_code'], + null, + null, + $session_id + ); + $course_session['student_info']['certificate'] = null; + if (isset($category[0])) { + if ($category[0]->is_certificate_available($user_id)) { + $course_session['student_info']['certificate'] = Display::label( + get_lang('Yes'), + 'success' + ); + } else { + $course_session['student_info']['certificate'] = Display::label( + get_lang('No') + ); + } + } + } + } + $html_courses_session[] = $course_session; + } + } + $count_courses_session++; + } } - } - } - - $userFinished = - $countDependenciesPassed >= $gradeBooksToValidateInDependence && - $countCoursesPassedNoDependency >= $minToValidate; - - if ($userFinished) { - $badgeList[$id]['finished'] = true; - } - $objSkill = new Skill(); - $skills = $category->get_skills(); - $skillList = []; - foreach ($skills as $skill) { - $skillList[] = $objSkill->get($skill['id']); - } - $badgeList[$id]['skills'] = $skillList; - } - } + // No courses to show. + if ($atLeastOneCourseIsVisible === false) { + if (empty($html_courses_session)) { + continue; + } + } - $this->tpl->assign( - 'grade_book_sidebar', - true - ); + if ($count_courses_session > 0) { + $params = [ + 'id' => $session_id, + ]; + $session_box = Display::getSessionTitleBox($session_id); + $coachId = $session_box['id_coach']; + $imageField = $extraFieldValue->get_values_by_handler_and_field_variable( + $session_id, + 'image' + ); - $this->tpl->assign( - 'grade_book_progress', - $finalResult - ); - $this->tpl->assign('grade_book_badge_list', $badgeList); + $params['category_id'] = $session_box['category_id']; + $params['title'] = $session_box['title']; + $params['id_coach'] = $coachId; + $params['coach_url'] = api_get_path(WEB_AJAX_PATH). + 'user_manager.ajax.php?a=get_user_popup&user_id='.$coachId; + $params['coach_name'] = !empty($session_box['coach']) ? $session_box['coach'] : null; + $params['coach_avatar'] = UserManager::getUserPicture( + $coachId, + USER_IMAGE_SIZE_SMALL + ); + $params['date'] = $session_box['dates']; + $params['image'] = isset($imageField['value']) ? $imageField['value'] : null; + $params['duration'] = isset($session_box['duration']) ? ' '.$session_box['duration'] : null; + $params['show_actions'] = SessionManager::cantEditSession($session_id); - return true; - } + if ($collapsable) { + $collapsableData = SessionManager::getCollapsableData( + $user_id, + $session_id, + $extraFieldValue, + $collapsableLink + ); + $params['collapsed'] = $collapsableData['collapsed']; + $params['collapsable_link'] = $collapsableData['collapsable_link']; + } - return false; - } + $params['show_description'] = $session_box['show_description'] == 1 && $portalShowDescription; + $params['description'] = $session_box['description']; + $params['visibility'] = $session_box['visibility']; + $params['show_simple_session_info'] = $showSimpleSessionInfo; + $params['course_list_session_style'] = $coursesListSessionStyle; + $params['num_users'] = $session_box['num_users']; + $params['num_courses'] = $session_box['num_courses']; + $params['course_categories'] = CourseManager::getCourseCategoriesFromCourseList( + $html_courses_session + ); + $params['courses'] = $html_courses_session; + $params['is_old'] = $markAsOld; + $params['is_future'] = $markAsFuture; - /** - * Generate the HTML code for items when displaying the right-side blocks. - * - * @return string - */ - private static function returnRightBlockItems(array $items) - { - $my_account_content = ''; - foreach ($items as $item) { - if (empty($item['link']) && empty($item['title'])) { - continue; - } + if ($showSimpleSessionInfo) { + $params['subtitle'] = self::getSimpleSessionDetails( + $session_box['coach'], + $session_box['dates'], + isset($session_box['duration']) ? $session_box['duration'] : null + ); + } - $my_account_content .= '
  • ' - .(empty($item['icon']) ? '' : ''.$item['icon'].'') - .''.$item['title'].'' - .'
  • '; - } + if ($gameModeIsActive) { + $params['stars'] = GamificationUtils::getSessionStars( + $params['id'], + $this->user_id + ); + $params['progress'] = GamificationUtils::getSessionProgress( + $params['id'], + $this->user_id + ); + $params['points'] = GamificationUtils::getSessionPoints( + $params['id'], + $this->user_id + ); + } + $listSession[] = $params; + $sessionCount++; + } + } + } else { + // All sessions included in + $count_courses_session = 0; + $html_sessions = ''; + if (isset($session_category['sessions'])) { + foreach ($session_category['sessions'] as $session) { + $session_id = $session['session_id']; - return '
      '.$my_account_content.'
    '; - } + // Don't show empty sessions. + if (count($session['courses']) < 1) { + continue; + } - /** - * Return HTML code for personal user course category. - * - * @param $id - * @param $title - * - * @return string - */ - private static function getHtmlForUserCategory($id, $title) - { - if ($id == 0) { - return ''; - } - $icon = Display::return_icon( - 'folder_yellow.png', - $title, - ['class' => 'sessionView'], - ICON_SIZE_LARGE - ); + $date_session_start = $session['access_start_date']; + $date_session_end = $session['access_end_date']; + $coachAccessStartDate = $session['coach_access_start_date']; + $coachAccessEndDate = $session['coach_access_end_date']; + $html_courses_session = []; + $count = 0; + $markAsOld = false; + $markAsFuture = false; - return "
    $icon$title
    "; - } + foreach ($session['courses'] as $course) { + $is_coach_course = api_is_coach($session_id, $course['real_id']); + $allowed_time = 0; + $allowedEndTime = true; - /** - * return HTML code for course display in session view. - * - * @param array $courseInfo - * @param $userCategoryId - * @param bool $displayButton - * @param $loadDirs - * - * @return string - */ - private static function getHtmlForCourse( - $courseInfo, - $userCategoryId, - $displayButton = false, - $loadDirs - ) { - if (empty($courseInfo)) { - return ''; - } + if (!empty($date_session_start)) { + if ($is_coach_course) { + $allowed_time = api_strtotime($coachAccessStartDate); + } else { + $allowed_time = api_strtotime($date_session_start); + } - $id = $courseInfo['real_id']; - $title = $courseInfo['title']; - $code = $courseInfo['code']; + if (!isset($_GET['history'])) { + if (!empty($date_session_end)) { + if ($is_coach_course) { + // if coach end date is empty we use the default end date + if (empty($coachAccessEndDate)) { + $endSessionToTms = api_strtotime($date_session_end); + if ($session_now > $endSessionToTms) { + $allowedEndTime = false; + } + } else { + $endSessionToTms = api_strtotime($coachAccessEndDate); + if ($session_now > $endSessionToTms) { + $allowedEndTime = false; + } + } + } else { + $endSessionToTms = api_strtotime($date_session_end); + if ($session_now > $endSessionToTms) { + $allowedEndTime = false; + } + } + } + } + } - $class = 'session-view-lvl-6'; - if ($userCategoryId != 0 && !$displayButton) { - $class = 'session-view-lvl-7'; - } + if ($showAllSessions) { + if ($allowed_time < $session_now && $allowedEndTime == false) { + $markAsOld = true; + } + if ($allowed_time > $session_now && $endSessionToTms > $session_now) { + $markAsFuture = true; + } + $allowedEndTime = true; + $allowed_time = 0; + } - $class2 = 'session-view-lvl-6'; - if ($displayButton || $userCategoryId != 0) { - $class2 = 'session-view-lvl-7'; - } + if ($session_now >= $allowed_time && $allowedEndTime) { + if (api_get_setting('hide_courses_in_sessions') === 'false') { + $c = CourseManager::get_logged_user_course_html( + $course, + $session_id, + 'session_course_item' + ); + if (isset($c[1])) { + $html_courses_session[] = $c[1]; + } + } + $count_courses_session++; + $count++; + } + } - $button = ''; - if ($displayButton) { - $button = ''; - } + $sessionParams = []; + // Category + if ($count > 0) { + $session_box = Display::getSessionTitleBox($session_id); + $sessionParams[0]['id'] = $session_id; + $sessionParams[0]['date'] = $session_box['dates']; + $sessionParams[0]['duration'] = isset($session_box['duration']) ? ' '.$session_box['duration'] : null; + $sessionParams[0]['course_list_session_style'] = $coursesListSessionStyle; + $sessionParams[0]['title'] = $session_box['title']; + $sessionParams[0]['subtitle'] = (!empty($session_box['coach']) ? $session_box['coach'].' | ' : '').$session_box['dates']; + $sessionParams[0]['show_actions'] = SessionManager::cantEditSession($session_id); + $sessionParams[0]['courses'] = $html_courses_session; + $sessionParams[0]['show_simple_session_info'] = $showSimpleSessionInfo; + $sessionParams[0]['coach_name'] = !empty($session_box['coach']) ? $session_box['coach'] : null; + $sessionParams[0]['is_old'] = $markAsOld; + $sessionParams[0]['is_future'] = $markAsFuture; - $icon = Display::return_icon( - 'blackboard.png', - $title, - ['class' => 'sessionView'], - ICON_SIZE_LARGE - ); + if ($collapsable) { + $collapsableData = SessionManager::getCollapsableData( + $user_id, + $session_id, + $extraFieldValue, + $collapsableLink + ); + $sessionParams[0]['collapsable_link'] = $collapsableData['collapsable_link']; + $sessionParams[0]['collapsed'] = $collapsableData['collapsed']; + } - $courseLink = $courseInfo['course_public_url'].'?id_session=0'; + if ($showSimpleSessionInfo) { + $sessionParams[0]['subtitle'] = self::getSimpleSessionDetails( + $session_box['coach'], + $session_box['dates'], + isset($session_box['duration']) ? $session_box['duration'] : null + ); + } - // get html course params - $courseParams = CourseManager::getCourseParamsForDisplay($id, $loadDirs); - $teachers = ''; - $rightActions = ''; + $this->tpl->assign('session', $sessionParams); + $this->tpl->assign('show_tutor', api_get_setting('show_session_coach') === 'true'); + $this->tpl->assign('gamification_mode', $gameModeIsActive); + $this->tpl->assign( + 'remove_session_url', + api_get_configuration_value('remove_session_url') + ); + $this->tpl->assign( + 'hide_session_dates_in_user_portal', + api_get_configuration_value('hide_session_dates_in_user_portal') + ); - // teacher list - if (!empty($courseParams['teachers'])) { - $teachers = '

    '.$courseParams['teachers'].'

    '; - } + if ($viewGridCourses) { + $html_sessions .= $this->tpl->fetch( + $this->tpl->get_template('/user_portal/grid_session.tpl') + ); + } else { + $html_sessions .= $this->tpl->fetch( + $this->tpl->get_template('user_portal/classic_session.tpl') + ); + } + $sessionCount++; + } + } + } - // notification - if (!empty($courseParams['right_actions'])) { - $rightActions = '
    '.$courseParams['right_actions'].'
    '; - } + if ($count_courses_session > 0) { + $categoryParams = [ + 'id' => $session_category['session_category']['id'], + 'title' => $session_category['session_category']['name'], + 'show_actions' => api_is_platform_admin(), + 'subtitle' => '', + 'sessions' => $html_sessions, + ]; - $notifications = isset($courseParams['notifications']) ? $courseParams['notifications'] : ''; + $session_category_start_date = $session_category['session_category']['date_start']; + $session_category_end_date = $session_category['session_category']['date_end']; + if ($session_category_start_date == '0000-00-00') { + $session_category_start_date = ''; + } - return "
    - $button - $icon - $title - - $notifications - $rightActions -
    - $teachers"; - } + if ($session_category_end_date == '0000-00-00') { + $session_category_end_date = ''; + } - /** - * return HTML code for session category. - * - * @param $id - * @param $title - * - * @return string - */ - private static function getHtmlSessionCategory($id, $title) - { - if ($id == 0) { - return ''; - } + if (!empty($session_category_start_date) && + !empty($session_category_end_date) + ) { + $categoryParams['subtitle'] = sprintf( + get_lang('FromDateXToDateY'), + $session_category_start_date, + $session_category_end_date + ); + } else { + if (!empty($session_category_start_date)) { + $categoryParams['subtitle'] = get_lang('From').' '.$session_category_start_date; + } - $icon = Display::return_icon( - 'folder_blue.png', - $title, - ['class' => 'sessionView'], - ICON_SIZE_LARGE - ); + if (!empty($session_category_end_date)) { + $categoryParams['subtitle'] = get_lang('Until').' '.$session_category_end_date; + } + } - return "
    - - $icon - $title - -
    "; - } + $this->tpl->assign('session_category', $categoryParams); + $sessions_with_category .= $this->tpl->fetch( + $this->tpl->get_template('user_portal/session_category.tpl') + ); + } + } + } - /** - * return HTML code for session. - * - * @param int $id session id - * @param string $title session title - * @param int $categorySessionId - * @param array $courseInfo - * - * @return string - */ - private static function getHtmlForSession($id, $title, $categorySessionId, $courseInfo) - { - $html = ''; - if ($categorySessionId == 0) { - $class1 = 'session-view-lvl-2'; // session - $class2 = 'session-view-lvl-4'; // got to course in session link - } else { - $class1 = 'session-view-lvl-3'; // session - $class2 = 'session-view-lvl-5'; // got to course in session link - } + $allCoursesInSessions = []; + foreach ($listSession as $currentSession) { + $coursesInSessions = $currentSession['courses']; + unset($currentSession['courses']); + foreach ($coursesInSessions as $coursesInSession) { + $coursesInSession['session'] = $currentSession; + $allCoursesInSessions[] = $coursesInSession; + } + } - $icon = Display::return_icon( - 'session.png', - $title, - ['class' => 'sessionView'], - ICON_SIZE_LARGE - ); - $courseLink = $courseInfo['course_public_url'].'?id_session='.intval($id); + $this->tpl->assign('all_courses', $allCoursesInSessions); + $this->tpl->assign('session', $listSession); + $this->tpl->assign('show_tutor', (api_get_setting('show_session_coach') === 'true' ? true : false)); + $this->tpl->assign('gamification_mode', $gameModeIsActive); + $this->tpl->assign('remove_session_url', api_get_configuration_value('remove_session_url')); + $this->tpl->assign( + 'hide_session_dates_in_user_portal', + api_get_configuration_value('hide_session_dates_in_user_portal') + ); - $html .= "$icon$title"; - $html .= ''; + if ($viewGridCourses) { + $sessions_with_no_category = $this->tpl->fetch( + $this->tpl->get_template('/user_portal/grid_session.tpl') + ); + } else { + $sessions_with_no_category = $this->tpl->fetch( + $this->tpl->get_template('user_portal/classic_session.tpl') + ); + } + } + } - return '
    '.$html.'
    '; + return [ + 'courses' => $courseCompleteList, + 'sessions' => $session_categories, + 'html' => trim($specialCourseList.$sessions_with_category.$sessions_with_no_category.$listCourse), + 'session_count' => $sessionCount, + 'course_count' => $courseCount, + ]; } /** - * @param $listA - * @param $listB + * Filter the course list by category code. * - * @return int + * @param array $courseList course list + * @param string $categoryCode + * + * @return array */ - private static function compareByCourse($listA, $listB) + private static function filterByCategory($courseList, $categoryCode) { - if ($listA['userCatTitle'] == $listB['userCatTitle']) { - if ($listA['title'] == $listB['title']) { - return 0; - } + return array_filter( + $courseList, + function ($courseInfo) use ($categoryCode) { + if (isset($courseInfo['category_code']) && + $courseInfo['category_code'] === $categoryCode + ) { + return true; + } - if ($listA['title'] > $listB['title']) { - return 1; + return false; } - - return -1; - } - - if ($listA['userCatTitle'] > $listB['userCatTitle']) { - return 1; - } - - return -1; + ); } /** @@ -2510,7 +2545,7 @@ class IndexManager * * @param string $coachName * @param string $dates - * @param string|null $duration Optional + * @param string|null $duration Optional * * @return string */ @@ -2525,28 +2560,4 @@ class IndexManager return implode(' | ', $strDetails); } - - /** - * Filter the course list by category code. - * - * @param array $courseList course list - * @param string $categoryCode - * - * @return array - */ - private static function filterByCategory($courseList, $categoryCode) - { - return array_filter( - $courseList, - function ($courseInfo) use ($categoryCode) { - if (isset($courseInfo['category_code']) && - $courseInfo['category_code'] === $categoryCode - ) { - return true; - } - - return false; - } - ); - } } diff --git a/main/install/configuration.dist.php b/main/install/configuration.dist.php index 8175940af2..061e080f9b 100755 --- a/main/install/configuration.dist.php +++ b/main/install/configuration.dist.php @@ -1425,6 +1425,9 @@ ALTER TABLE notification_event ADD COLUMN event_id INT NULL; // Course chat: Send message on button click only, if false then send on enter too. //$_configuration['course_chat_send_message_only_on_button'] = true; +// Course catalog show extra fields (visible and filtered) +//$_configuration['allow_course_extra_field_in_catalog'] = false; + // KEEP THIS AT THE END // -------- Custom DB changes // Add user activation by confirmation email diff --git a/main/template/default/catalog/course_catalog.tpl b/main/template/default/catalog/course_catalog.tpl new file mode 100644 index 0000000000..924e305736 --- /dev/null +++ b/main/template/default/catalog/course_catalog.tpl @@ -0,0 +1,29 @@ +{% extends 'layout/layout_1_col.tpl'|get_template %} + +{% block content %} + {{ content }} + + {% block course_grid %} +
    + {% for course in courses %} +
    +
    + {% include 'catalog/course_item_catalog.tpl'|get_template %} +
    +
    + {% endfor %} +
    + {% endblock %} +
    + {{ pagination }} +
    +{% endblock %} diff --git a/main/template/default/catalog/course_item_catalog.tpl b/main/template/default/catalog/course_item_catalog.tpl new file mode 100644 index 0000000000..dce1494793 --- /dev/null +++ b/main/template/default/catalog/course_item_catalog.tpl @@ -0,0 +1,82 @@ +{% block course_item %} + {% block course_image %} +
    + {% block course_thumbnail %} + + {{ course.title }} + + {% endblock %} + + {% if course.category_title %} + {{ course.category_title }} +
    + {% endif %} + + {% block course_description_button %} + + {% endblock %} +
    + {% endblock %} + + {% block course_description %} +
    + {% block course_title %} + {{ course.title_formatted }} + {% endblock %} + + {% block course_rating %} + {{ course.rating }} + {% endblock %} + + {% block course_extras %} + {% if course.extra_data %} +
    +
    + {{ course.extra_data }} + + {% if course.extra_data_tags %} +
    +
      +
    • {{ 'Tags' | get_lang }}
    • + {% for tag in course.extra_data_tags %} +
    • + {{ tag }} +
    • + {% endfor %} +
    +
    + {% endif %} +
    +
    + {% endif %} + {% endblock %} + + {% block course_teacher_info %} + {{ course.teacher_info }} + {% endblock %} + + {% block course_buy_course %} + {{ course.buy_course }} + {% endblock %} + + {% block course_toolbar %} +
    + {% if course.already_registered_formatted %} +
    + {{ course.unregister_formatted }} +
    +
    + {{ course.already_registered_formatted }} +
    + {% else %} +
    + {{ course.subscribe_formatted }} +
    + {% endif %} +
    + {% endblock %} +
    + {% endblock %} +{% endblock %} \ No newline at end of file diff --git a/main/template/default/auth/session_catalog.tpl b/main/template/default/catalog/session_catalog.tpl similarity index 99% rename from main/template/default/auth/session_catalog.tpl rename to main/template/default/catalog/session_catalog.tpl index 442ca0d3b5..312791a86c 100644 --- a/main/template/default/auth/session_catalog.tpl +++ b/main/template/default/catalog/session_catalog.tpl @@ -235,6 +235,7 @@
    + {{ catalog_pagination }} {% endblock %} \ No newline at end of file