Browse Source

Merge branch '1.11.x' of github.com:chamilo/chamilo-lms into 1.11.x

jmontoyaa 8 years ago
parent
commit
78378cefc1

+ 1 - 0
app/config/mail.conf.dist.php

@@ -18,3 +18,4 @@ $platform_email['SMTP_CHARSET'] = 'UTF-8';
 $platform_email['SMTP_UNIQUE_SENDER'] = 0; // to send all mails from the same user
 $platform_email['SMTP_DEBUG'] = 0; // change to 1 to enable smtp debug
 $platform_email['SMTP_SECURE'] = 'tls'; // if you're using SSL: ssl; or TLS: tls. (only used if SMTP_AUTH==1)
+$platform_email['SMTP_UNIQUE_REPLY_TO'] = 0; // to use AWS SMS service, SMTP_UNIQUE_SENDER and this have to be = 1

+ 125 - 26
main/forum/editthread.php

@@ -27,7 +27,8 @@ require_once 'forumfunction.inc.php';
 $origin = api_get_origin();
 
 /* MAIN DISPLAY SECTION */
-$currentForum = get_forum_information($_GET['forum']);
+$forumId = (int) $_GET['forum'];
+$currentForum = get_forum_information($forumId);
 $currentForumCategory = get_forumcategory_information($currentForum['forum_category']);
 
 // the variable $forum_settings is declared in forumconfig.inc.php
@@ -49,6 +50,7 @@ if (!empty($gradebook) && $gradebook == 'view') {
 $threadId = isset($_GET['thread']) ? intval($_GET['thread']) : 0;
 $courseInfo = isset($_GET['cidReq']) ? api_get_course_info($_GET['cidReq']) : 0;
 $cId = isset($courseInfo['real_id']) ? intval($courseInfo['real_id']) : 0;
+$gradebookId = intval(api_is_in_gradebook());
 
 /* Is the user allowed here? */
 
@@ -101,12 +103,12 @@ if (!empty($groupId)) {
     $groupProperties = GroupManager :: get_group_properties($groupId);
     $interbreadcrumb[] = array('url' => api_get_path(WEB_CODE_PATH).'group/group.php?'.$cidreq, 'name' => get_lang('Groups'));
     $interbreadcrumb[] = array('url' => api_get_path(WEB_CODE_PATH).'group/group_space.php?'.$cidreq, 'name' => get_lang('GroupSpace').' '.$groupProperties['name']);
-    $interbreadcrumb[] = array('url' => api_get_path(WEB_CODE_PATH).'forum/viewforum.php?'.$cidreq.'&forum='.intval($_GET['forum']), 'name' => $currentForum['forum_title']);
-    $interbreadcrumb[] = array('url' => api_get_path(WEB_CODE_PATH).'forum/newthread.php?'.$cidreq.'&forum='.intval($_GET['forum']),'name' => get_lang('EditThread'));
+    $interbreadcrumb[] = array('url' => api_get_path(WEB_CODE_PATH).'forum/viewforum.php?'.$cidreq.'&forum='.$forumId, 'name' => $currentForum['forum_title']);
+    $interbreadcrumb[] = array('url' => api_get_path(WEB_CODE_PATH).'forum/newthread.php?'.$cidreq.'&forum='.$forumId,'name' => get_lang('EditThread'));
 } else {
     $interbreadcrumb[] = array('url' => api_get_path(WEB_CODE_PATH).'forum/index.php?'.$cidreq, 'name' => $nameTools);
     $interbreadcrumb[] = array('url' => api_get_path(WEB_CODE_PATH).'forum/viewforumcategory.php?'.$cidreq.'&forumcategory='.$currentForumCategory['cat_id'], 'name' => $currentForumCategory['cat_title']);
-    $interbreadcrumb[] = array('url' => api_get_path(WEB_CODE_PATH).'forum/viewforum.php?'.$cidreq.'&forum='.intval($_GET['forum']), 'name' => $currentForum['forum_title']);
+    $interbreadcrumb[] = array('url' => api_get_path(WEB_CODE_PATH).'forum/viewforum.php?'.$cidreq.'&forum='.$forumId, 'name' => $currentForum['forum_title']);
     $interbreadcrumb[] = array('url' => '#', 'name' => get_lang('EditThread'));
 }
 
@@ -139,35 +141,132 @@ $htmlHeadXtra[] = <<<JS
     </script>
 JS;
 
-if ($origin == 'learnpath') {
-    Display::display_reduced_header();
-} else {
-    Display :: display_header(null);
-}
-
-handle_forum_and_forumcategories();
-
 // Action links
-echo '<div class="actions">';
-echo '<span style="float:right;">'.search_link().'</span>';
-echo '<a href="viewforum.php?forum='.intval($_GET['forum']).'&'.$cidreq.'">'.
-    Display::return_icon('back.png',get_lang('BackToForum'),'',ICON_SIZE_MEDIUM).'</a>';
-echo '</div>';
+$actions = '
+    <div class="actions">
+        <span class="pull-right">'.search_link().'</span>
+        <a href="viewforum.php?forum='.$forumId.'&'.$cidreq.'">'
+            .Display::return_icon('back.png',get_lang('BackToForum'),'',ICON_SIZE_MEDIUM)
+        .'</a>
+    </div>
+';
 
 $threadData = getThreadInfo($threadId, $cId);
 
-$values = showUpdateThreadForm(
-    $currentForum,
-    $forumSettings,
-    $threadData
+$form = new FormValidator(
+    'thread',
+    'post',
+    api_get_self() . '?' . http_build_query([
+        'forum' => $forumId,
+        'thread' => $threadId,
+    ]) . '&' . api_get_cidreq()
 );
 
-if (!empty($values) && isset($values['SubmitPost'])) {
+$form->addElement('header', get_lang('EditThread'));
+$form->setConstants(array('forum' => '5'));
+$form->addElement('hidden', 'forum_id', $forumId);
+$form->addElement('hidden', 'thread_id', $threadId);
+$form->addElement('hidden', 'gradebook', $gradebookId);
+$form->addElement('text', 'thread_title', get_lang('Title'));
+$form->addElement('advanced_settings', 'advanced_params', get_lang('AdvancedParameters'));
+$form->addElement('html', '<div id="advanced_params_options" style="display:none">');
+
+if ((api_is_course_admin() || api_is_course_coach() || api_is_course_tutor()) && ($threadId)) {
+    // Thread qualify
+    if (Gradebook::is_active()) {
+        //Loading gradebook select
+        GradebookUtils::load_gradebook_select_in_tool($form);
+        $form->addElement(
+            'checkbox',
+            'thread_qualify_gradebook',
+            '',
+            get_lang('QualifyThreadGradebook'),
+            ['id' => 'thread_qualify_gradebook']
+        );
+    } else {
+        $form->addElement('hidden', 'thread_qualify_gradebook', false);
+    }
+
+    $form->addElement('html', '<div id="options_field" style="display:none">');
+    $form->addElement('text', 'numeric_calification', get_lang('QualificationNumeric'));
+    $form->applyFilter('numeric_calification', 'html_filter');
+    $form->addElement('text', 'calification_notebook_title', get_lang('TitleColumnGradebook'));
+    $form->applyFilter('calification_notebook_title', 'html_filter');
+    $form->addElement(
+        'number',
+        'weight_calification',
+        get_lang('QualifyWeight'),
+        ['value' => '0.00', 'step' => '0.01']
+    );
+    $form->applyFilter('weight_calification', 'html_filter');
+    $group = array();
+    $group[] = $form->createElement('radio', 'thread_peer_qualify', null, get_lang('Yes'), 1);
+    $group[] = $form->createElement('radio', 'thread_peer_qualify', null, get_lang('No'), 0);
+    $form->addGroup(
+        $group,
+        '',
+        [get_lang('ForumThreadPeerScoring'), get_lang('ForumThreadPeerScoringComment'),]
+    );
+    $form->addElement('html', '</div>');
+}
 
-    // update thread in table forum_thread.
-    updateThread($values);
+if ($forumSettings['allow_sticky'] && api_is_allowed_to_edit(null, true)) {
+    $form->addElement('checkbox', 'thread_sticky', '', get_lang('StickyPost'));
 }
 
-if (isset($origin) && $origin != 'learnpath') {
-    Display :: display_footer();
+$form->addElement('html', '</div>');
+
+if (!empty($threadData)) {
+    $defaults['thread_qualify_gradebook'] = ($threadData['threadQualifyMax'] > 0 && empty($_POST)) ? 1 : 0 ;
+    $defaults['thread_title'] = prepare4display($threadData['threadTitle']);
+    $defaults['thread_sticky'] = strval(intval($threadData['threadSticky']));
+    $defaults['thread_peer_qualify'] = intval($threadData['threadPeerQualify']);
+    $defaults['numeric_calification'] = $threadData['threadQualifyMax'];
+    $defaults['calification_notebook_title'] = $threadData['threadTitleQualify'];
+    $defaults['weight_calification'] = $threadData['threadWeight'];
+} else {
+    $defaults['thread_qualify_gradebook'] = 0;
+    $defaults['numeric_calification'] = 0;
+    $defaults['calification_notebook_title'] = '';
+    $defaults['weight_calification'] = 0;
+    $defaults['thread_peer_qualify'] = 0;
+}
+$form->setDefaults(isset($defaults) ? $defaults : null);
+
+$form->addButtonUpdate(get_lang('ModifyThread'), 'SubmitPost');
+
+if ($form->validate()) {
+    $redirectUrl = api_get_path(WEB_CODE_PATH).'forum/viewforum.php?forum='.$forumId;
+
+    $check = Security::check_token('post');
+    if ($check) {
+        $values = $form->exportValues();
+
+//        if (isset($values['thread_qualify_gradebook']) &&
+//            $values['thread_qualify_gradebook'] == '1' &&
+//            empty($values['weight_calification'])
+//        ) {
+//            Display::addFlash(
+//                Display::return_message(get_lang('YouMustAssignWeightOfQualification'), 'error', false)
+//            );
+//            header('Location: '.$redirectUrl);
+//            exit;
+//        }
+
+        Security::clear_token();
+        updateThread($values);
+        header('Location: '.$redirectUrl);
+        exit;
+    }
+} else {
+    $token = Security::get_token();
+    $form->addElement('hidden', 'sec_token');
+    $form->setConstants(array('sec_token' => $token));
 }
+
+$orginIsLearpath = $origin == 'learnpath';
+
+$view = new Template('', !$orginIsLearpath, !$orginIsLearpath, $orginIsLearpath, $orginIsLearpath);
+$view->assign('actions', $actions);
+$view->assign('content', $form->returnForm());
+$view->display_one_col_template();

+ 0 - 129
main/forum/forumfunction.inc.php

@@ -2747,135 +2747,6 @@ function store_thread($current_forum, $values, $courseInfo = array(), $showMessa
     return $lastThread->getIid();
 }
 
-/**
- * This function displays the form that is used to UPDATE a Thread.
- * @param array $currentForum
- * @param array $forumSetting
- * @param array $formValues
- * @return void HMTL
- * @author José Loguercio <jose.loguercio@beeznest.com>
- * @version february 2016, chamilo 1.10.4
- */
-function showUpdateThreadForm($currentForum, $forumSetting, $formValues = '')
-{
-    $myThread = isset($_GET['thread']) ? intval($_GET['thread']) : '';
-    $myForum = isset($_GET['forum']) ? intval($_GET['forum']) : '';
-    $myGradebook = isset($_GET['gradebook']) ? Security::remove_XSS($_GET['gradebook']) : '';
-    $form = new FormValidator(
-        'thread',
-        'post',
-        api_get_self() . '?' . http_build_query([
-            'forum' => $myForum,
-            'gradebook' => $myGradebook,
-            'thread' => $myThread,
-        ]) . '&' . api_get_cidreq()
-    );
-
-    $form->addElement('header', get_lang('EditThread'));
-    $form->setConstants(array('forum' => '5'));
-    $form->addElement('hidden', 'forum_id', $myForum);
-    $form->addElement('hidden', 'thread_id', $myThread);
-    $form->addElement('hidden', 'gradebook', $myGradebook);
-    $form->addElement('text', 'thread_title', get_lang('Title'));
-    $form->addElement('advanced_settings', 'advanced_params', get_lang('AdvancedParameters'));
-    $form->addElement('html', '<div id="advanced_params_options" style="display:none">');
-
-    if ((api_is_course_admin() || api_is_course_coach() || api_is_course_tutor()) && ($myThread)) {
-        // Thread qualify
-        if (Gradebook::is_active()) {
-            //Loading gradebook select
-            GradebookUtils::load_gradebook_select_in_tool($form);
-            $form->addElement(
-                'checkbox',
-                'thread_qualify_gradebook',
-                '',
-                get_lang('QualifyThreadGradebook'),
-                [
-                    'id' => 'thread_qualify_gradebook'
-                ]
-            );
-        } else {
-            $form->addElement('hidden', 'thread_qualify_gradebook', false);
-        }
-
-        $form->addElement('html', '<div id="options_field" style="display:none">');
-        $form->addElement('text', 'numeric_calification', get_lang('QualificationNumeric'));
-        $form->applyFilter('numeric_calification', 'html_filter');
-        $form->addElement('text', 'calification_notebook_title', get_lang('TitleColumnGradebook'));
-        $form->applyFilter('calification_notebook_title', 'html_filter');
-        $form->addElement(
-            'text',
-            'weight_calification',
-            get_lang('QualifyWeight'),
-            array('value' => '0.00', 'onfocus' => "javascript: this.select();")
-        );
-        $form->applyFilter('weight_calification', 'html_filter');
-        $group = array();
-        $group[] = $form->createElement('radio', 'thread_peer_qualify', null, get_lang('Yes'), 1);
-        $group[] = $form->createElement('radio', 'thread_peer_qualify', null, get_lang('No'), 0);
-        $form->addGroup(
-            $group,
-            '',
-            [
-                get_lang('ForumThreadPeerScoring'),
-                get_lang('ForumThreadPeerScoringComment'),
-            ]
-        );
-        $form->addElement('html', '</div>');
-    }
-
-    if ($forumSetting['allow_sticky'] && api_is_allowed_to_edit(null, true)) {
-        $form->addElement('checkbox', 'thread_sticky', '', get_lang('StickyPost'));
-    }
-
-    $form->addElement('html', '</div>');
-
-    if (!empty($formValues)) {
-        $defaults['thread_qualify_gradebook'] = ($formValues['threadQualifyMax'] > 0 && empty($_POST)) ? 1 : 0 ;
-        $defaults['thread_title'] = prepare4display($formValues['threadTitle']);
-        $defaults['thread_sticky'] = strval(intval($formValues['threadSticky']));
-        $defaults['thread_peer_qualify'] = intval($formValues['threadPeerQualify']);
-        $defaults['numeric_calification'] = $formValues['threadQualifyMax'];
-        $defaults['calification_notebook_title'] = $formValues['threadTitleQualify'];
-        $defaults['weight_calification'] = $formValues['threadWeight'];
-    } else {
-        $defaults['thread_qualify_gradebook'] = 0;
-        $defaults['numeric_calification'] = 0;
-        $defaults['calification_notebook_title'] = '';
-        $defaults['weight_calification'] = 0;
-        $defaults['thread_peer_qualify'] = 0;
-    }
-    $form->setDefaults(isset($defaults) ? $defaults : null);
-
-    $form->addButtonUpdate(get_lang('ModifyThread'), 'SubmitPost');
-
-    if ($form->validate()) {
-        $check = Security::check_token('post');
-        if ($check) {
-            $values = $form->exportValues();
-            if (isset($values['thread_qualify_gradebook']) &&
-                $values['thread_qualify_gradebook'] == '1' &&
-                empty($values['weight_calification'])
-            ) {
-                Display::addFlash(Display::return_message(
-                    get_lang('YouMustAssignWeightOfQualification').'&nbsp;<a href="javascript:window.history.go(-1);">'.
-                    get_lang('Back').'</a>',
-                    'error',
-                    false
-                ));
-                return false;
-            }
-            Security::clear_token();
-            return $values;
-        }
-    } else {
-        $token = Security::get_token();
-        $form->addElement('hidden', 'sec_token');
-        $form->setConstants(array('sec_token' => $token));
-        $form->display();
-    }
-}
-
 /**
  * This function displays the form that is used to add a post. This can be a new thread or a reply.
  * @param array $current_forum

+ 1 - 1
main/inc/lib/api.lib.php

@@ -7783,7 +7783,7 @@ function api_mail_html(
     $senderEmail = !empty($senderEmail) ? $senderEmail : $defaultEmail;
 
     // Reply to first
-    if (isset($extra_headers['reply_to'])) {
+    if (isset($extra_headers['reply_to']) && empty($platform_email['SMTP_UNIQUE_REPLY_TO'])) {
         $mail->AddReplyTo(
             $extra_headers['reply_to']['mail'],
             $extra_headers['reply_to']['name']

+ 31 - 6
main/inc/lib/course.lib.php

@@ -3563,7 +3563,9 @@ class CourseManager
                 } else {
                     $course_info['status'] = $courseUserInfo['status'];
                 }
-                $show_notification = Display::show_notification($course_info);
+                $show_notification = !api_get_configuration_value('hide_course_notification')
+                    ? Display::show_notification($course_info)
+                    : '';
                 $params['edit_actions'] = '';
                 $params['document'] = '';
                 if (api_is_platform_admin()) {
@@ -3737,7 +3739,9 @@ class CourseManager
             $course_info['status'] = $row['status'];
             // For each course, get if there is any notification icon to show
             // (something that would have changed since the user's last visit).
-            $showNotification = Display::show_notification($course_info);
+            $showNotification = !api_get_configuration_value('hide_course_notification')
+                ? Display::show_notification($course_info)
+                : '';
             $iconName = basename($course_info['course_image']);
 
             $params = array();
@@ -3881,7 +3885,9 @@ class CourseManager
 
             // For each course, get if there is any notification icon to show
             // (something that would have changed since the user's last visit).
-            $showNotification = Display::show_notification($course_info);
+            $showNotification = !api_get_configuration_value('hide_course_notification')
+                ? Display::show_notification($course_info)
+                : '';
 
             $thumbnails = null;
             $image = null;
@@ -4086,8 +4092,9 @@ class CourseManager
 
         // Display the "what's new" icons
         $notifications = '';
-        if ($course_visibility != COURSE_VISIBILITY_CLOSED &&
-            $course_visibility != COURSE_VISIBILITY_HIDDEN
+        if (
+            ($course_visibility != COURSE_VISIBILITY_CLOSED && $course_visibility != COURSE_VISIBILITY_HIDDEN) ||
+            !api_get_configuration_value('hide_course_notification')
         ) {
             $notifications .= Display::show_notification($course_info);
         }
@@ -4141,6 +4148,7 @@ class CourseManager
         $params['title'] = $session_title;
         $params['edit_actions'] = '';
         $params['document'] = '';
+        $params['category'] = $course_info['categoryName'];
 
         if ($course_visibility != COURSE_VISIBILITY_CLOSED &&
             $course_visibility != COURSE_VISIBILITY_HIDDEN
@@ -6049,7 +6057,9 @@ class CourseManager
 
         // For each course, get if there is any notification icon to show
         // (something that would have changed since the user's last visit).
-        $show_notification = Display::show_notification($course_info);
+        $show_notification = !api_get_configuration_value('hide_course_notification')
+            ? Display::show_notification($course_info)
+            : '';
 
         // New code displaying the user's status in respect to this course.
         $status_icon = Display::return_icon(
@@ -6285,4 +6295,19 @@ class CourseManager
         $courseFieldValue = new ExtraFieldValue('course');
         $courseFieldValue->saveFieldValues($params);
     }
+
+    /**
+     * Get the course categories form a course list
+     * @param array $courseList
+     * @return array
+     */
+    public static function getCourseCategoriesFromCourseList(array $courseList)
+    {
+        $allCategories = array_column($courseList, 'category');
+        $categories = array_unique($allCategories);
+
+        sort($categories);
+
+        return $categories;
+    }
 }

+ 67 - 95
main/inc/lib/javascript/annotation/js/annotation.js

@@ -1,12 +1,8 @@
 /* For licensing terms, see /license.txt */
 
-(function (window) {
-    /**
-     * @param referenceElement Element to get the point
-     * @param x MouseEvent's clientX
-     * @param y MouseEvent's clientY
-     * @returns {{x: number, y: number}}
-     */
+(function (window, $) {
+    "use strict";
+
     function getPointOnImage(referenceElement, x, y) {
         var pointerPosition = {
                 left: x + window.scrollX,
@@ -21,16 +17,12 @@
             x: Math.round(pointerPosition.left - canvasOffset.x),
             y: Math.round(pointerPosition.top - canvasOffset.y)
         };
-    };
+    }
 
-    /**
-     * @param Object attributes
-     * @constructor
-     */
     var SvgElementModel = function (attributes) {
         this.attributes = attributes;
         this.id = 0;
-        this.name = '';
+        this.name = "";
 
         this.changeEvent = null;
     };
@@ -48,16 +40,12 @@
         this.changeEvent = callback;
     };
     SvgElementModel.decode = function () {
-        return new this;
+        return new this();
     };
     SvgElementModel.prototype.encode = function () {
-        return '';
+        return "";
     };
 
-    /**
-     * @param Object attributes
-     * @constructor
-     */
     var SvgPathModel = function (attributes) {
         SvgElementModel.call(this, attributes);
     };
@@ -66,21 +54,21 @@
         x = parseInt(x);
         y = parseInt(y);
 
-        var points = this.get('points');
+        var points = this.get("points");
         points.push([x, y]);
 
-        this.set('points', points);
+        this.set("points", points);
     };
     SvgPathModel.prototype.encode = function () {
         var pairedPoints = [];
 
-        this.get('points').forEach(function (point) {
+        this.get("points").forEach(function (point) {
             pairedPoints.push(
-                point.join(';')
+                point.join(";")
             );
         });
 
-        return 'P)(' + pairedPoints.join(')(');
+        return "P)(" + pairedPoints.join(")(");
     };
     SvgPathModel.decode = function (pathInfo) {
         var points = [];
@@ -92,16 +80,12 @@
         return new SvgPathModel({points: points});
     };
 
-    /**
-     * @param userAttributes
-     * @constructor
-     */
     var TextModel = function (userAttributes) {
         var attributes = $.extend({
-            text: '',
+            text: "",
             x: 0,
             y: 0,
-            color: 'red',
+            color: "red",
             fontSize: 20
         }, userAttributes);
 
@@ -109,20 +93,16 @@
     };
     TextModel.prototype = Object.create(SvgElementModel.prototype);
     TextModel.prototype.encode = function () {
-        return 'T)(' + this.get('text') + ')(' + this.get('x') + ';' + this.get('y');
+        return "T)(" + this.get("text") + ")(" + this.get("x") + ";" + this.get("y");
     };
     TextModel.decode = function (textInfo) {
         return new TextModel({
             text: textInfo.text,
             x: textInfo.x,
             y: textInfo.y
-        })
+        });
     };
 
-    /**
-     * @param Object model
-     * @constructor
-     */
     var SvgPathView = function (model) {
         var self = this;
 
@@ -131,32 +111,27 @@
             self.render();
         });
 
-        this.el = document.createElementNS('http://www.w3.org/2000/svg', 'path');
-        this.el.setAttribute('fill', 'transparent');
-        this.el.setAttribute('stroke', 'red');
-        this.el.setAttribute('stroke-width', 3);
+        this.el = document.createElementNS("http://www.w3.org/2000/svg", "path");
+        this.el.setAttribute("fill", "transparent");
+        this.el.setAttribute("stroke", "red");
+        this.el.setAttribute("stroke-width", "3");
     };
     SvgPathView.prototype.render = function () {
-        var d = '',
-            points = this.model.get('points');
+        var d = "";
 
         $.each(
-            this.model.get('points'),
+            this.model.get("points"),
             function (i, point) {
-                d += (i === 0) ? 'M' : ' L ';
-                d += point[0] + ' ' + point[1];
+                d += (i === 0) ? "M" : " L ";
+                d += point[0] + " " + point[1];
             }
         );
 
-        this.el.setAttribute('d', d);
+        this.el.setAttribute("d", d);
 
         return this;
     };
 
-    /**
-     * @param model
-     * @constructor
-     */
     var TextView = function (model) {
         var self = this;
 
@@ -178,9 +153,6 @@
         return this;
     };
 
-    /**
-     * @constructor
-     */
     var ElementsCollection = function () {
         this.models = [];
         this.length = 0;
@@ -202,12 +174,6 @@
         this.addEvent = callback;
     };
 
-    /**
-     * @param elementsCollection
-     * @param image
-     * @param questionId
-     * @constructor
-     */
     var AnnotationCanvasView = function (elementsCollection, image, questionId) {
         var self = this;
 
@@ -256,7 +222,7 @@
             .on('click', function (e) {
                 e.preventDefault();
 
-                if (self.$rdbOptions.filter(':checked').val() != '1') {
+                if ("1" !== self.$rdbOptions.filter(':checked').val()) {
                     return;
                 }
 
@@ -275,7 +241,7 @@
 
                 var point = getPointOnImage(self.el, e.clientX, e.clientY);
 
-                if (isMoving || self.$rdbOptions.filter(':checked').val() != '0' || elementModel) {
+                if (isMoving || "0" !== self.$rdbOptions.filter(':checked').val() || elementModel) {
                     return;
                 }
 
@@ -288,7 +254,7 @@
             .on('mousemove', function (e) {
                 e.preventDefault();
 
-                if (!isMoving || self.$rdbOptions.filter(':checked').val() != '0' || !elementModel) {
+                if (!isMoving || "0" !== self.$rdbOptions.filter(':checked').val() || !elementModel) {
                     return;
                 }
 
@@ -299,7 +265,7 @@
             .on('mouseup', function (e) {
                 e.preventDefault();
 
-                if (!isMoving || self.$rdbOptions.filter(':checked').val() != '0' || !elementModel) {
+                if (!isMoving || "0" !== self.$rdbOptions.filter(':checked').val() || !elementModel) {
                     return;
                 }
 
@@ -368,43 +334,49 @@
 
     window.AnnotationQuestion = function (userSettings) {
         $(document).on('ready', function () {
-        var
-            settings = $.extend(
-                {questionId: 0, exerciseId: 0, relPath: '/'},
-                userSettings
-            ),
-            xhrUrl = 'exercise/annotation_user.php',
-            $container = $('#annotation-canvas-' + settings.questionId);
-
-        $
-            .getJSON(settings.relPath + xhrUrl, {
-                question_id: parseInt(settings.questionId),
-                exe_id: parseInt(settings.exerciseId)
-            })
-            .done(function (questionInfo) {
-                var image = new Image();
-                image.onload = function () {
-                    var elementsCollection = new ElementsCollection(),
-                        canvas = new AnnotationCanvasView(elementsCollection, this, settings.questionId);
+            var
+                settings = $.extend(
+                    {
+                        questionId: 0,
+                        exerciseId: 0,
+                        relPath: '/'
+                    },
+                    userSettings
+                ),
+                xhrUrl = 'exercise/annotation_user.php',
+                $container = $('#annotation-canvas-' + settings.questionId);
+
+            $
+                .getJSON(settings.relPath + xhrUrl, {
+                    question_id: parseInt(settings.questionId),
+                    exe_id: parseInt(settings.exerciseId)
+                })
+                .done(function (questionInfo) {
+                    var image = new Image();
+                    image.onload = function () {
+                        var elementsCollection = new ElementsCollection(),
+                            canvas = new AnnotationCanvasView(elementsCollection, this, settings.questionId);
 
-                    $container
-                        .html(canvas.render().el);
+                        $container
+                            .html(canvas.render().el);
 
-                    $.each(questionInfo.answers.paths, function (i, pathInfo) {
-                        var pathModel = SvgPathModel.decode(pathInfo);
+                        /** @namespace questionInfo.answers.paths */
+                        $.each(questionInfo.answers.paths, function (i, pathInfo) {
+                            var pathModel = SvgPathModel.decode(pathInfo);
 
-                        elementsCollection.add(pathModel);
-                    });
+                            elementsCollection.add(pathModel);
+                        });
 
-                    $(questionInfo.answers.texts).each(function (i, textInfo) {
-                        var textModel = TextModel.decode(textInfo);
+                        /** @namespace questionInfo.answers.texts */
+                        $(questionInfo.answers.texts).each(function (i, textInfo) {
+                            var textModel = TextModel.decode(textInfo);
 
-                        elementsCollection.add(textModel);
-                    });
-                };
-                image.src = questionInfo.image.path;
-            });
+                            elementsCollection.add(textModel);
+                        });
+                    };
+                    image.src = questionInfo.image.path;
+                });
 
         });
     };
-})(window);
+})(window, window.jQuery);

+ 125 - 117
main/inc/lib/userportal.lib.php

@@ -73,9 +73,9 @@ class IndexManager
                 );
 
                 foreach ($exercises as $exercise_item) {
-                    $exercise_item['course_code']     = $course_code;
-                    $exercise_item['session_id']     = $session_id;
-                    $exercise_item['tms']     = api_strtotime($exercise_item['end_time'], 'UTC');
+                    $exercise_item['course_code'] = $course_code;
+                    $exercise_item['session_id'] = $session_id;
+                    $exercise_item['tms'] = api_strtotime($exercise_item['end_time'], 'UTC');
 
                     $exercise_list[] = $exercise_item;
                 }
@@ -88,7 +88,10 @@ class IndexManager
                     api_get_path(WEB_CODE_PATH).'exercise/overview.php?exerciseId='.$my_exercise['id'].'&cidReq='.$my_exercise['course_code'].'&id_session='.$my_exercise['session_id']
                 );
                 $this->tpl->assign('exercise_url', $url);
-                $this->tpl->assign('exercise_end_date', api_convert_and_format_date($my_exercise['end_time'], DATE_FORMAT_SHORT));
+                $this->tpl->assign(
+                    'exercise_end_date',
+                    api_convert_and_format_date($my_exercise['end_time'], DATE_FORMAT_SHORT)
+                );
             }
         }
     }
@@ -140,7 +143,7 @@ class IndexManager
 
     /**
      * Alias for the online_logout() function
-     * @param   bool    $redirect   Whether to ask online_logout to redirect to index.php or not
+     * @param bool $redirect Whether to ask online_logout to redirect to index.php or not
      */
     public function logout($redirect = true)
     {
@@ -156,7 +159,7 @@ class IndexManager
     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);
+        $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);
@@ -215,16 +218,20 @@ class IndexManager
         if ($show_menu) {
             $html .= '<ul class="nav nav-pills nav-stacked">';
             if ($show_create_link) {
-                $html .= '<li class="add-course"><a href="' . api_get_path(WEB_CODE_PATH) . 'create_course/add_course.php">'.
-                    Display::return_icon('new-course.png',  get_lang('CourseCreate')).(api_get_setting('course_validation') == 'true' ? get_lang('CreateCourseRequest') : get_lang('CourseCreate')).'</a></li>';
+                $html .= '<li class="add-course"><a href="'.api_get_path(WEB_CODE_PATH).'create_course/add_course.php">'
+                    .Display::return_icon('new-course.png', get_lang('CourseCreate'))
+                    .(api_get_setting('course_validation') == 'true' ? get_lang('CreateCourseRequest') : get_lang('CourseCreate'))
+                    .'</a></li>';
             }
 
             if ($show_course_link) {
                 if (!api_is_drh() && !api_is_session_admin()) {
-                    $html .=  '<li class="list-course"><a href="'. api_get_path(WEB_CODE_PATH) . 'auth/courses.php">'.
-                        Display::return_icon('catalog-course.png', get_lang('CourseCatalog')) .get_lang('CourseCatalog').'</a></li>';
+                    $html .= '<li class="list-course"><a href="'.api_get_path(WEB_CODE_PATH).'auth/courses.php">'
+                        .Display::return_icon('catalog-course.png', get_lang('CourseCatalog'))
+                        .get_lang('CourseCatalog')
+                        .'</a></li>';
                 } else {
-                    $html .= '<li><a href="' . api_get_path(WEB_CODE_PATH) . 'dashboard/index.php">'.get_lang('Dashboard').'</a></li>';
+                    $html .= '<li><a href="'.api_get_path(WEB_CODE_PATH).'dashboard/index.php">'.get_lang('Dashboard').'</a></li>';
                 }
             }
             $html .= '</ul>';
@@ -283,15 +290,15 @@ class IndexManager
                     $home_top_temp = file_get_contents($this->home.'home_top.html');
                 } else {
                     if (file_exists($this->default_home.'home_top.html')) {
-                        $home_top_temp = file_get_contents($this->default_home . 'home_top.html');
+                        $home_top_temp = file_get_contents($this->default_home.'home_top.html');
                     }
                 }
             }
 
             if (trim($home_top_temp) == '' && api_is_platform_admin()) {
-                $home_top_temp = '<div class="welcome-mascot">' . get_lang('PortalHomepageDefaultIntroduction') . '</div>';
+                $home_top_temp = '<div class="welcome-mascot">'.get_lang('PortalHomepageDefaultIntroduction').'</div>';
             } else {
-                $home_top_temp = '<div class="welcome-home-top-temp">' . $home_top_temp . '</div>';
+                $home_top_temp = '<div class="welcome-home-top-temp">'.$home_top_temp.'</div>';
             }
             $open = str_replace('{rel_path}', api_get_path(REL_PATH), $home_top_temp);
             $html = api_to_system_encoding($open, api_detect_encoding(strip_tags($open)));
@@ -335,7 +342,7 @@ class IndexManager
     public function return_help()
     {
         $user_selected_language = api_get_interface_language();
-        $platformLanguage       = api_get_setting('platformLanguage');
+        $platformLanguage = api_get_setting('platformLanguage');
 
         // Help section.
         /* Hide right menu "general" and other parts on anonymous right menu. */
@@ -358,6 +365,7 @@ class IndexManager
                 'helpsCollapse'
             );
         }
+
         return $html;
     }
 
@@ -375,13 +383,7 @@ class IndexManager
                 $certificatesItem = Display::tag(
                     'li',
                     Display::url(
-                        Display::return_icon(
-                            'graduation.png',
-                            get_lang('MyCertificates'),
-                            null,
-                            ICON_SIZE_SMALL
-                        ).
-                        get_lang('MyCertificates'),
+                        Display::return_icon('graduation.png', get_lang('MyCertificates')).get_lang('MyCertificates'),
                         api_get_path(WEB_CODE_PATH)."gradebook/my_certificates.php"
                     )
                 );
@@ -393,14 +395,8 @@ class IndexManager
             $searchItem = Display::tag(
                 'li',
                 Display::url(
-                    Display::return_icon(
-                        'search_graduation.png',
-                        get_lang('Search'),
-                        null,
-                        ICON_SIZE_SMALL
-                    ).
-                    get_lang('Search'),
-                    api_get_path(WEB_CODE_PATH) . "gradebook/search.php"
+                    Display::return_icon('search_graduation.png', get_lang('Search')).get_lang('Search'),
+                    api_get_path(WEB_CODE_PATH)."gradebook/search.php"
                 )
             );
         }
@@ -416,12 +412,7 @@ class IndexManager
             $content .= Display::tag(
                 'li',
                 Display::url(
-                    Display::return_icon(
-                        'skill-badges.png',
-                        get_lang('MySkills'),
-                        null,
-                        ICON_SIZE_SMALL
-                    ).get_lang('MySkills'),
+                    Display::return_icon('skill-badges.png', get_lang('MySkills')).get_lang('MySkills'),
                     api_get_path(WEB_CODE_PATH).'social/my_skills_report.php'
                 )
             );
@@ -430,13 +421,8 @@ class IndexManager
                 $content .= Display::tag(
                     'li',
                     Display::url(
-                        Display::return_icon(
-                            'edit-skill.png',
-                            get_lang('MySkills'),
-                            null,
-                            ICON_SIZE_SMALL
-                        ) . get_lang('ManageSkills'),
-                        api_get_path(WEB_CODE_PATH) . 'admin/skills_wheel.php'
+                        Display::return_icon('edit-skill.png', get_lang('MySkills')).get_lang('ManageSkills'),
+                        api_get_path(WEB_CODE_PATH).'admin/skills_wheel.php'
                     )
                 );
             }
@@ -491,7 +477,7 @@ class IndexManager
 
         // Get list of courses in category $category.
         $sql = "SELECT * FROM $main_course_table cours
-                WHERE category_code = '" . $category . "'
+                WHERE category_code = '".$category."'
                 ORDER BY title, UPPER(visual_code)";
 
         // Showing only the courses of the current access_url_id.
@@ -537,7 +523,7 @@ class IndexManager
                     FROM $main_category_table t1
                     LEFT JOIN $main_category_table t2 ON t1.code=t2.parent_id
                     LEFT JOIN $main_course_table t3 ON (t3.category_code = t1.code $platform_visible_courses)
-                    WHERE t1.parent_id ". (empty($category) ? "IS NULL" : "='$category'")."
+                    WHERE t1.parent_id ".(empty($category) ? "IS NULL" : "='$category'")."
                     GROUP BY t1.name,t1.code,t1.parent_id,t1.children_count 
                     ORDER BY t1.tree_pos, t1.name";
 
@@ -594,7 +580,7 @@ class IndexManager
                     $thereIsSubCat = true;
                 } elseif (api_get_setting('show_empty_course_categories') == 'true') {
                     /* End changed code to eliminate the (0 courses) after empty categories. */
-                      $htmlListCat .= '<li>';
+                    $htmlListCat .= '<li>';
                     $htmlListCat .= $catLine['name'];
                     $htmlListCat .= "</li>";
                     $thereIsSubCat = true;
@@ -612,10 +598,10 @@ class IndexManager
         }
         $result .= $htmlTitre;
         if ($thereIsSubCat) {
-            $result .=  $htmlListCat;
+            $result .= $htmlListCat;
         }
         while ($categoryName = Database::fetch_array($resCats)) {
-            $result .= '<h3>' . $categoryName['name'] . "</h3>\n";
+            $result .= '<h3>'.$categoryName['name']."</h3>\n";
         }
         $numrows = Database::num_rows($sql_result_courses);
         $courses_list_string = '';
@@ -677,8 +663,9 @@ class IndexManager
                         || ($user_identified && $course['visibility'] == COURSE_VISIBILITY_OPEN_PLATFORM)
                         || ($user_identified && array_key_exists($course['code'], $courses_of_user)
                             && $course['visibility'] != COURSE_VISIBILITY_CLOSED)
-                            || $courses_of_user[$course['code']]['status'] == '1'
-                        || api_is_platform_admin()) {
+                        || $courses_of_user[$course['code']]['status'] == '1'
+                        || api_is_platform_admin()
+                    ) {
                         $courses_list_string .= '</a><br />';
                     }
                     $course_details = array();
@@ -715,24 +702,24 @@ class IndexManager
         }
         if ($courses_shown > 0) {
             // Only display the list of courses and categories if there was more than
-                    // 0 courses visible to the world (we're in the anonymous list here).
-            $result .=  $courses_list_string;
+            // 0 courses visible to the world (we're in the anonymous list here).
+            $result .= $courses_list_string;
         }
         if ($category != '') {
-            $result .=  '<p><a href="'.api_get_self().'"> ' .
-                Display :: return_icon('back.png', get_lang('BackToHomePage')).
-                get_lang('BackToHomePage') . '</a></p>';
+            $result .= '<p><a href="'.api_get_self().'">'
+                .Display:: return_icon('back.png', get_lang('BackToHomePage'))
+                .get_lang('BackToHomePage').'</a></p>';
         }
 
         return $result;
     }
 
     /**
-    * retrieves all the courses that the user has already subscribed to
-    * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
-    * @param int $user_id: the id of the user
-    * @return array an array containing all the information of the courses of the given user
-    */
+     * retrieves all the courses that the user has already subscribed to
+     * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
+     * @param int $user_id : the id of the user
+     * @return array an array containing all the information of the courses of the given user
+     */
     public function get_courses_of_user($user_id)
     {
         $table_course = Database::get_main_table(TABLE_MAIN_COURSE);
@@ -776,6 +763,7 @@ class IndexManager
                 'user_course_category' => $row['user_course_cat']
             );
         }
+
         return $courses;
     }
 
@@ -817,7 +805,7 @@ class IndexManager
             if (!empty($title)) {
                 $html .= '<div class="panel-heading">'.$title.'</div>';
             }
-            $html.= '<div class="panel-body">'.$content.'</div>';
+            $html .= '<div class="panel-body">'.$content.'</div>';
             $html = Display::div($html, $params);
         }
 
@@ -864,23 +852,27 @@ class IndexManager
             $usergroup_list = $usergroup->get_usergroup_by_user(api_get_user_id());
             $classes = '';
             if (!empty($usergroup_list)) {
-                foreach($usergroup_list as $group_id) {
+                foreach ($usergroup_list as $group_id) {
                     $data = $usergroup->get($group_id);
-                    $data['name'] = Display::url($data['name'], api_get_path(WEB_CODE_PATH).'user/classes.php?id='.$data['id']);
+                    $data['name'] = Display::url(
+                        $data['name'],
+                        api_get_path(WEB_CODE_PATH).'user/classes.php?id='.$data['id']
+                    );
                     $classes .= Display::tag('li', $data['name']);
                 }
             }
             if (api_is_platform_admin()) {
                 $classes .= Display::tag(
                     'li',
-                    Display::url(get_lang('AddClasses') ,api_get_path(WEB_CODE_PATH).'admin/usergroups.php?action=add')
+                    Display::url(get_lang('AddClasses'), api_get_path(WEB_CODE_PATH).'admin/usergroups.php?action=add')
                 );
             }
             if (!empty($classes)) {
-                $classes = Display::tag('ul', $classes, array('class'=>'nav nav-pills nav-stacked'));
+                $classes = Display::tag('ul', $classes, array('class' => 'nav nav-pills nav-stacked'));
                 $html .= self::show_right_block(get_lang('Classes'), $classes, 'classes_block');
             }
         }
+
         return $html;
     }
 
@@ -895,11 +887,11 @@ class IndexManager
             $content = null;
 
             if (api_get_setting('allow_social_tool') == 'true') {
-                $content .= '<a style="text-align:center" href="' . api_get_path(WEB_PATH) . 'main/social/home.php">
-                <img class="img-circle" src="' . $userPicture . '" ></a>';
+                $content .= '<a style="text-align:center" href="'.api_get_path(WEB_PATH).'main/social/home.php">
+                <img class="img-circle" src="'.$userPicture.'"></a>';
             } else {
-                $content .= '<a style="text-align:center" href="' . api_get_path(WEB_PATH) . 'main/auth/profile.php">
-                <img class="img-circle" title="' . get_lang('EditProfile') . '" src="' . $userPicture. '" ></a>';
+                $content .= '<a style="text-align:center" href="'.api_get_path(WEB_PATH).'main/auth/profile.php">
+                <img class="img-circle" title="'.get_lang('EditProfile').'" src="'.$userPicture.'"></a>';
             }
 
             $html = self::show_right_block(
@@ -951,20 +943,24 @@ class IndexManager
             if (api_get_setting('allow_social_tool') == 'true') {
                 $link = '?f=social';
             }
-            $profile_content .= '<li class="inbox-message-social"><a href="'.api_get_path(WEB_PATH).'main/messages/inbox.php'.$link.'">'.
-                Display::return_icon('inbox.png',get_lang('Inbox'),null,ICON_SIZE_SMALL).get_lang('Inbox').$cant_msg.' </a></li>';
-            $profile_content .= '<li class="new-message-social"><a href="'.api_get_path(WEB_PATH).'main/messages/new_message.php'.$link.'">'.
-                Display::return_icon('new-message.png',get_lang('Compose'),null,ICON_SIZE_SMALL).get_lang('Compose').' </a></li>';
+            $profile_content .= '<li class="inbox-message-social"><a href="'.api_get_path(WEB_PATH).'main/messages/inbox.php'.$link.'">'
+                .Display::return_icon('inbox.png', get_lang('Inbox'))
+                .get_lang('Inbox').$cant_msg.' </a></li>';
+            $profile_content .= '<li class="new-message-social"><a href="'.api_get_path(WEB_PATH).'main/messages/new_message.php'.$link.'">'
+                .Display::return_icon('new-message.png', get_lang('Compose'))
+                .get_lang('Compose').' </a></li>';
 
             if (api_get_setting('allow_social_tool') == 'true') {
                 $total_invitations = Display::badge($total_invitations);
-                $profile_content .= '<li class="invitations-social"><a href="'.api_get_path(WEB_PATH).'main/social/invitations.php">'.
-                    Display::return_icon('invitations.png',get_lang('PendingInvitations'),null,ICON_SIZE_SMALL).get_lang('PendingInvitations').$total_invitations.'</a></li>';
+                $profile_content .= '<li class="invitations-social"><a href="'.api_get_path(WEB_PATH).'main/social/invitations.php">'
+                    .Display::return_icon('invitations.png', get_lang('PendingInvitations'))
+                    .get_lang('PendingInvitations').$total_invitations.'</a></li>';
             }
 
             if (isset($_configuration['allow_my_files_link_in_homepage']) && $_configuration['allow_my_files_link_in_homepage']) {
-                $myFiles = '<li class="myfiles-social"><a href="'.api_get_path(WEB_PATH).'main/social/myfiles.php">'.
-                    Display::return_icon('sn-files.png',get_lang('Files'),null,ICON_SIZE_SMALL).get_lang('MyFiles').'</a></li>';
+                $myFiles = '<li class="myfiles-social"><a href="'.api_get_path(WEB_PATH).'main/social/myfiles.php">'
+                    .Display::return_icon('sn-files.png', get_lang('Files'))
+                    .get_lang('MyFiles').'</a></li>';
 
                 if (api_get_setting('allow_my_files') === 'false') {
                     $myFiles = '';
@@ -976,14 +972,9 @@ class IndexManager
 
         $editProfileUrl = Display::getProfileEditionLink($user_id);
 
-        $profile_content .= '<li class="profile-social"><a href="' . $editProfileUrl . '">'.
-            Display::return_icon(
-                'edit-profile.png',
-                get_lang('EditProfile'),
-                null,
-                ICON_SIZE_SMALL
-            ).
-            get_lang('EditProfile').'</a></li>';
+        $profile_content .= '<li class="profile-social"><a href="'.$editProfileUrl.'">'
+            .Display::return_icon('edit-profile.png', get_lang('EditProfile'))
+            .get_lang('EditProfile').'</a></li>';
         $profile_content .= '</ul>';
 
         $html = self::show_right_block(
@@ -1071,17 +1062,17 @@ class IndexManager
         if ($show_create_link) {
             $my_account_content .= '<li class="add-course"><a href="main/create_course/add_course.php">';
             if (api_get_setting('course_validation') == 'true' && !api_is_platform_admin()) {
-                $my_account_content .= Display::return_icon('new-course.png',get_lang('CreateCourseRequest'),null,ICON_SIZE_SMALL);
+                $my_account_content .= Display::return_icon('new-course.png', get_lang('CreateCourseRequest'));
                 $my_account_content .= get_lang('CreateCourseRequest');
             } else {
-                $my_account_content .= Display::return_icon('new-course.png',get_lang('CourseCreate'),null,ICON_SIZE_SMALL);
+                $my_account_content .= Display::return_icon('new-course.png', get_lang('CourseCreate'));
                 $my_account_content .= get_lang('CourseCreate');
             }
             $my_account_content .= '</a></li>';
 
             if (SessionManager::allowToManageSessions()) {
                 $my_account_content .= '<li class="add-course"><a href="main/session/session_add.php">';
-                $my_account_content .= Display::return_icon('session.png',get_lang('AddSession'),null,ICON_SIZE_SMALL);
+                $my_account_content .= Display::return_icon('session.png', get_lang('AddSession'));
                 $my_account_content .= get_lang('AddSession');
                 $my_account_content .= '</a></li>';
             }
@@ -1089,20 +1080,27 @@ class IndexManager
 
         //Sort courses
         $url = api_get_path(WEB_CODE_PATH).'auth/courses.php?action=sortmycourses';
-        $img_order= Display::return_icon('order-course.png',get_lang('SortMyCourses'),null,ICON_SIZE_SMALL);
-        $my_account_content .= '<li class="order-course">'.Display::url($img_order.get_lang('SortMyCourses'), $url, array('class' => 'sort course')).'</li>';
+        $img_order = Display::return_icon('order-course.png', get_lang('SortMyCourses'));
+        $my_account_content .= '<li class="order-course">'.Display::url($img_order.get_lang('SortMyCourses'), $url,
+                array('class' => 'sort course')).'</li>';
 
         // Session history
         if (isset($_GET['history']) && intval($_GET['history']) == 1) {
-            $my_account_content .= '<li class="history-course"><a href="user_portal.php">'.Display::return_icon('history-course.png',get_lang('DisplayTrainingList'),null,ICON_SIZE_SMALL).get_lang('DisplayTrainingList').'</a></li>';
+            $my_account_content .= '<li class="history-course"><a href="user_portal.php">'
+                .Display::return_icon('history-course.png', get_lang('DisplayTrainingList'))
+                .get_lang('DisplayTrainingList').'</a></li>';
         } else {
-            $my_account_content .= '<li class="history-course"><a href="user_portal.php?history=1" >'.Display::return_icon('history-course.png',get_lang('HistoryTrainingSessions'),null,ICON_SIZE_SMALL).get_lang('HistoryTrainingSessions').'</a></li>';
+            $my_account_content .= '<li class="history-course"><a href="user_portal.php?history=1">'
+                .Display::return_icon('history-course.png', get_lang('HistoryTrainingSessions'))
+                .get_lang('HistoryTrainingSessions').'</a></li>';
         }
 
         // Course catalog
         if ($show_course_link) {
             if (!api_is_drh()) {
-                $my_account_content .= '<li class="list-course"><a href="main/auth/courses.php" >'.Display::return_icon('catalog-course.png',get_lang('CourseCatalog'),null,ICON_SIZE_SMALL).get_lang('CourseCatalog').'</a></li>';
+                $my_account_content .= '<li class="list-course"><a href="main/auth/courses.php">'
+                    .Display::return_icon('catalog-course.png', get_lang('CourseCatalog'))
+                    .get_lang('CourseCatalog').'</a></li>';
             } else {
                 $my_account_content .= '<li><a href="main/dashboard/index.php">'.get_lang('Dashboard').'</a></li>';
             }
@@ -1135,7 +1133,7 @@ class IndexManager
         $listCourse = '';
         $specialCourseList = '';
         $load_history = isset($_GET['history']) && intval($_GET['history']) == 1 ? true : false;
-        $viewGridCourses = api_get_configuration_value('view_grid_courses');
+        $viewGridCourses = api_get_configuration_value('view_grid_courses') === 'true';
         $showSimpleSessionInfo = api_get_configuration_value('show_simple_session_info');
 
         $coursesWithoutCategoryTemplate = '/user_portal/classic_courses_without_category.tpl';
@@ -1304,7 +1302,7 @@ class IndexManager
                                 'id' => $session_id
                             );
                             $session_box = Display::get_session_title_box($session_id);
-                            $actions = api_get_path(WEB_CODE_PATH) .'session/resume_session.php?id_session='.$session_id;
+                            $actions = api_get_path(WEB_CODE_PATH).'session/resume_session.php?id_session='.$session_id;
                             $coachId = $session_box['id_coach'];
                             $extraFieldValue = new ExtraFieldValue('session');
                             $imageField = $extraFieldValue->get_values_by_handler_and_field_variable(
@@ -1315,7 +1313,7 @@ class IndexManager
                             $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_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,
@@ -1323,7 +1321,7 @@ class IndexManager
                             );
                             $params['date'] = $session_box['dates'];
                             $params['image'] = isset($imageField['value']) ? $imageField['value'] : null;
-                            $params['duration'] = isset($session_box['duration']) ? ' ' . $session_box['duration'] : null;
+                            $params['duration'] = isset($session_box['duration']) ? ' '.$session_box['duration'] : null;
                             $params['edit_actions'] = $actions;
                             $params['show_description'] = $session_box['show_description'];
                             $params['description'] = $session_box['description'];
@@ -1332,6 +1330,9 @@ class IndexManager
                             $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;
 
                             if ($showSimpleSessionInfo) {
@@ -1340,7 +1341,8 @@ class IndexManager
 
                             if ($gameModeIsActive) {
                                 $params['stars'] = GamificationUtils::getSessionStars($params['id'], $this->user_id);
-                                $params['progress'] = GamificationUtils::getSessionProgress($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;
@@ -1427,7 +1429,7 @@ class IndexManager
                                 $sessionParams[0]['date'] = $session_box['dates'];
                                 $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]['subtitle'] = (!empty($session_box['coach']) ? $session_box['coach'].' | ' : '').$session_box['dates'];
                                 $sessionParams[0]['show_actions'] = api_is_platform_admin();
                                 $sessionParams[0]['courses'] = $html_courses_session;
                                 $sessionParams[0]['show_simple_session_info'] = false;
@@ -1476,15 +1478,15 @@ class IndexManager
                             );
                         } else {
                             if (
-                                !empty($session_category_start_date)
+                            !empty($session_category_start_date)
                             ) {
-                                $categoryParams['subtitle'] = get_lang('From') . ' ' . $session_category_start_date;
+                                $categoryParams['subtitle'] = get_lang('From').' '.$session_category_start_date;
                             }
 
                             if (
-                                !empty($session_category_end_date)
+                            !empty($session_category_end_date)
                             ) {
-                                $categoryParams['subtitle'] = get_lang('Until') . ' ' . $session_category_end_date;
+                                $categoryParams['subtitle'] = get_lang('Until').' '.$session_category_end_date;
                             }
                         }
 
@@ -1509,10 +1511,10 @@ class IndexManager
 
             $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('show_tutor', (api_get_setting('show_session_coach') === 'true' ? true : false));
             $this->tpl->assign('gamification_mode', $gameModeIsActive);
 
-            if (api_get_configuration_value('view_grid_courses')) {
+            if ($viewGridCourses) {
                 $sessions_with_no_category = $this->tpl->fetch(
                     $this->tpl->get_template('/user_portal/grid_session.tpl')
                 );
@@ -1524,7 +1526,7 @@ class IndexManager
         }
 
         return [
-            'html' => $specialCourseList . $sessions_with_category.$sessions_with_no_category.$listCourse,
+            'html' => $specialCourseList.$sessions_with_category.$sessions_with_no_category.$listCourse,
             'session_count' => $sessionCount,
             'course_count' => $courseCount
         ];
@@ -1658,7 +1660,7 @@ class IndexManager
                         $htmlCategory .= '<div class="panel panel-default">';
                     }
                     $htmlCategory .= '<div class="panel-body">';
-                    $coursesInfo =  $listCourse['course'];
+                    $coursesInfo = $listCourse['course'];
 
                     $htmlCategory .= self::getHtmlForCourse(
                         $coursesInfo,
@@ -1692,7 +1694,7 @@ class IndexManager
                         $htmlSessionCategory .= $htmlSession;
                     }
                     $htmlSessionCategory .= '</div>'; // end session cat block
-                    $htmlCategory .=  $htmlSessionCategory .'</div></div>' ;
+                    $htmlCategory .= $htmlSessionCategory.'</div></div>';
                     $htmlCategory .= '';   // end course block
                 }
                 $userCategoryHtml .= $htmlCategory;
@@ -1897,16 +1899,20 @@ class IndexManager
         if ($listA['userCatTitle'] == $listB['userCatTitle']) {
             if ($listA['title'] == $listB['title']) {
                 return 0;
-            } else if($listA['title'] > $listB['title']) {
+            }
+
+            if ($listA['title'] > $listB['title']) {
                 return 1;
-            } else {
-                return -1;
             }
-        } else if ($listA['userCatTitle'] > $listB['userCatTitle']) {
-            return 1;
-        } else {
+
             return -1;
         }
+
+        if ($listA['userCatTitle'] > $listB['userCatTitle']) {
+            return 1;
+        }
+
+        return -1;
     }
 
     /**
@@ -1918,11 +1924,13 @@ class IndexManager
     {
         if ($listA['title'] == $listB['title']) {
             return 0;
-        } else if($listA['title'] > $listB['title']) {
+        }
+
+        if ($listA['title'] > $listB['title']) {
             return 1;
-        } else {
-            return -1;
         }
+
+        return -1;
     }
 
     /**

+ 5 - 4
main/install/configuration.dist.php

@@ -244,15 +244,14 @@ $_configuration['system_stable'] = NEW_VERSION_STABLE;
 //$_configuration['show_invisible_exercise_in_lp_list'] = false;
 // New grid view the list of courses
 //$_configuration['view_grid_courses'] = 'true';
+// Show courses grouped by categories when $_configuration['view_grid_courses'] is enabled
+//$_configuration['view_grid_courses_grouped_categories_in_sessions'] = true;
 // Chamilo is installed/downloaded. Packagers can change this
 // to reflect their packaging method. The default value is 'chamilo'. This will
 // be reflected on the https://version.chamilo.org/stats page in the future.
 //$_configuration['packager'] = 'chamilo';
 // If true exercises added in LP can be modified.
 //$_configuration['force_edit_exercise_in_lp'] = false;
-// to reflect their packaging method. The default value is 'chamilo'. This will
-// be reflected on the https://version.chamilo.org/stats page in the future.
-//$_configuration['packager'] = 'chamilo';
 // List of driver to plugin in ckeditor
 //$_configuration['editor_driver_list'] = ['PersonalDriver', 'CourseDriver'];
 // Hide send to hrm users options in announcements
@@ -297,4 +296,6 @@ $_configuration['system_stable'] = NEW_VERSION_STABLE;
 // Hide main navigation menu (left column in userportal)
 // $_configuration['hide_main_navigation_menu'] = false;
 // PDF image dpi value. Default value 96
-// $_configuration['pdf_img_dpi'] = 96;
+// $_configuration['pdf_img_dpi'] = 96;
+// Hide the "what's new" icon notifications in course list
+// $_configuration['hide_course_notification'] = true;

+ 82 - 59
main/template/default/user_portal/grid_session.tpl

@@ -1,3 +1,68 @@
+{% set group_courses = 'view_grid_courses_grouped_categories_in_sessions'|get_configuration_value %}
+
+{% macro course_block(course, show_category) %}
+    <div class="col-xs-12 col-sm-6 col-md-4">
+        <div class="items">
+            <div class="image">
+                <img src="{{ course.image }}" class="img-responsive">
+                {% if course.category != '' and show_category %}
+                    <span class="category">{{ course.category }}</span>
+                    <div class="cribbon"></div>
+                {% endif %}
+                <div class="black-shadow">
+                    <div class="author-card">
+                        {% for teacher in course.teachers %}
+                            {% set counter = counter + 1 %}
+                            {% if counter <= 3 %}
+                                <a href="{{ teacher.url }}" class="ajax"
+                                   data-title="{{ teacher.firstname }} {{ teacher.lastname }}">
+                                    <img src="{{ teacher.avatar }}"/>
+                                </a>
+                                <div class="teachers-details">
+                                    <h5>
+                                        <a href="{{ teacher.url }}" class="ajax"
+                                           data-title="{{ teacher.firstname }} {{ teacher.lastname }}">
+                                            {{ teacher.firstname }} {{ teacher.lastname }}
+                                        </a>
+                                    </h5>
+                                </div>
+                            {% endif %}
+                        {% endfor %}
+                    </div>
+                </div>
+                {% if course.edit_actions != '' %}
+                    <div class="admin-actions">
+                        {% if course.document == '' %}
+                            <a class="btn btn-default btn-sm" href="{{ course.edit_actions }}">
+                                <i class="fa fa-pencil" aria-hidden="true"></i>
+                            </a>
+                        {% else %}
+                            <div class="btn-group" role="group">
+                                <a class="btn btn-default btn-sm" href="{{ course.edit_actions }}">
+                                    <i class="fa fa-pencil" aria-hidden="true"></i>
+                                </a>
+                                {{ course.document }}
+                            </div>
+                        {% endif %}
+                    </div>
+                {% endif %}
+            </div>
+            <div class="description">
+                <h4 class="title">
+                    {% if course.visibility == constant('COURSE_VISIBILITY_CLOSED') %}
+                        {{ course.title }} {{ course.code_course }}
+                    {% else %}
+                        <a href="{{ course.link }}">{{ course.title }} {{ course.code_course }}</a>
+                    {% endif %}
+                </h4>
+                <div class="notifications">{{ course.notifications }}</div>
+            </div>
+        </div>
+    </div>
+{% endmacro %}
+
+{% import _self as blocks %}
+
 {% for row in session %}
     <div id="session-{{ item.id }}" class="session panel panel-default">
         <div class="panel-heading">
@@ -29,68 +94,26 @@
                 </span>
             </div>
             <div class="grid-courses">
-                <div class="row">
-                    {% for item in row.courses %}
-                        <div class="col-xs-12 col-sm-6 col-md-4">
-                            <div class="items">
-                                <div class="image">
-                                    <img src="{{ item.image }}" class="img-responsive">
-                                    {% if item.category != '' %}
-                                        <span class="category">{{ item.category }}</span>
-                                        <div class="cribbon"></div>
-                                    {% endif %}
-                                    <div class="black-shadow">
-                                        <div class="author-card">
-                                            {% for teacher in item.teachers %}
-                                                {% set counter = counter + 1 %}
-                                                {% if counter <= 3 %}
-                                                    <a href="{{ teacher.url }}" class="ajax"
-                                                       data-title="{{ teacher.firstname }} {{ teacher.lastname }}">
-                                                        <img src="{{ teacher.avatar }}"/>
-                                                    </a>
-                                                    <div class="teachers-details">
-                                                        <h5>
-                                                            <a href="{{ teacher.url }}" class="ajax"
-                                                               data-title="{{ teacher.firstname }} {{ teacher.lastname }}">
-                                                                {{ teacher.firstname }} {{ teacher.lastname }}
-                                                            </a>
-                                                        </h5>
-                                                    </div>
-                                                {% endif %}
-                                            {% endfor %}
-                                        </div>
-                                    </div>
-                                    {% if item.edit_actions != '' %}
-                                        <div class="admin-actions">
-                                            {% if item.document == '' %}
-                                                <a class="btn btn-default btn-sm" href="{{ item.edit_actions }}">
-                                                    <i class="fa fa-pencil" aria-hidden="true"></i>
-                                                </a>
-                                            {% else %}
-                                                <div class="btn-group" role="group">
-                                                    <a class="btn btn-default btn-sm" href="{{ item.edit_actions }}">
-                                                        <i class="fa fa-pencil" aria-hidden="true"></i>
-                                                    </a>
-                                                    {{ item.document }}
-                                                </div>
-                                            {% endif %}
-                                        </div>
-                                    {% endif %}
-                                </div>
-                                <div class="description">
-                                    <h4 class="title">
-                                        {% if item.visibility == constant('COURSE_VISIBILITY_CLOSED') %}
-                                            {{ item.title }} {{ item.code_course }}
-                                        {% else %}
-                                            <a href="{{ item.link }}">{{ item.title }} {{ item.code_course }}</a>
-                                        {% endif %}
-                                    </h4>
-                                    <div class="notifications">{{ item.notifications }}</div>
-                                </div>
+                {% if not group_courses %}
+                    <div class="row">
+                        {% for item in row.courses %}
+                            {{ blocks.course_block(item, true) }}
+                        {% endfor %}
+                    </div>
+                {% else %}
+                    {% for category_code in row.course_categories %}
+                        <div class="row">
+                            <div class="col-xs-12">
+                                <h4>{{ category_code }}</h4>
                             </div>
+                            {% for course in row.courses %}
+                                {% if course.category == category_code %}
+                                    {{ blocks.course_block(course, false) }}
+                                {% endif %}
+                            {% endfor %}
                         </div>
                     {% endfor %}
-                </div>
+                {% endif %}
             </div>
         </div>
     </div>