Browse Source

Merge with 1.11.x

Julio Montoya 5 years ago
parent
commit
942ef02749
54 changed files with 890 additions and 722 deletions
  1. 1 1
      composer.json
  2. 1 1
      main/admin/user_list.php
  3. 1 1
      main/auth/courses_list.php
  4. 6 0
      main/course_info/infocours.php
  5. 12 8
      main/exercise/exercise.class.php
  6. 7 30
      main/exercise/exercise_show.php
  7. 89 77
      main/forum/forumfunction.inc.php
  8. 6 9
      main/forum/index.php
  9. 0 2
      main/gradebook/gradebook_edit_cat.php
  10. 5 7
      main/gradebook/index.php
  11. 20 14
      main/gradebook/lib/GradebookUtils.php
  12. 4 2
      main/gradebook/lib/be/abstractlink.class.php
  13. 16 10
      main/gradebook/lib/be/category.class.php
  14. 11 9
      main/gradebook/lib/be/evaluation.class.php
  15. 4 0
      main/gradebook/lib/fe/catform.class.php
  16. 4 4
      main/gradebook/lib/fe/displaygradebook.php
  17. 3 1
      main/gradebook/lib/scoredisplay.class.php
  18. 0 2
      main/inc/ajax/lp.ajax.php
  19. 2 2
      main/inc/ajax/message.ajax.php
  20. 8 9
      main/inc/ajax/social.ajax.php
  21. 26 63
      main/inc/lib/Compilatio.php
  22. 2 2
      main/inc/lib/CourseChatUtils.php
  23. 20 18
      main/inc/lib/api.lib.php
  24. 1 1
      main/inc/lib/certificate.lib.php
  25. 2 18
      main/inc/lib/chat.lib.php
  26. 55 0
      main/inc/lib/course.lib.php
  27. 2 2
      main/inc/lib/document.lib.php
  28. 73 15
      main/inc/lib/events.lib.php
  29. 20 41
      main/inc/lib/exercise.lib.php
  30. 17 21
      main/inc/lib/exercise_show_functions.lib.php
  31. 6 2
      main/inc/lib/extra_field.lib.php
  32. 2 2
      main/inc/lib/formvalidator/Element/UserAvatar.php
  33. 36 29
      main/inc/lib/message.lib.php
  34. 1 1
      main/inc/lib/sessionmanager.lib.php
  35. 7 3
      main/inc/lib/social.lib.php
  36. 26 78
      main/inc/lib/tracking.lib.php
  37. 21 6
      main/inc/lib/usermanager.lib.php
  38. 15 12
      main/inc/lib/userportal.lib.php
  39. 9 0
      main/install/configuration.dist.php
  40. 69 17
      main/lp/learnpath.class.php
  41. 30 117
      main/lp/learnpathItem.class.php
  42. 42 0
      main/lp/lp_controller.php
  43. 11 3
      main/lp/lp_view.php
  44. 178 44
      main/mySpace/access_details_session.php
  45. 3 5
      main/session/session_edit.php
  46. 0 12
      main/social/view_promoted_message.php
  47. 1 1
      main/template/default/export/pdf_footer.tpl
  48. 1 8
      main/template/default/learnpath/view.tpl
  49. 1 1
      main/template/default/social/user_block.tpl
  50. 1 1
      main/template/default/user_portal/grid_courses_with_category.tpl
  51. 0 1
      main/wiki/wiki.inc.php
  52. 10 8
      main/work/work.lib.php
  53. 1 0
      plugin/customcertificate/src/index.php
  54. 1 1
      plugin/grading_electronic/generate.php

+ 1 - 1
composer.json

@@ -33,7 +33,7 @@
         ]
     },
     "require": {
-        "php": ">=5.5",
+        "php": ">=5.6",
         "ext-intl": "*",
         "ext-gd": "*",
         "ext-curl": "*",

+ 1 - 1
main/admin/user_list.php

@@ -1060,7 +1060,7 @@ $data = $extraField->addElements($form, 0, [], true, false, $variablesToShow);
 
 $htmlHeadXtra[] = '
     <script>
-    $(document).ready(function() {
+    $(function () {
         '.$data['jquery_ready_content'].'
     })
     </script>

+ 1 - 1
main/auth/courses_list.php

@@ -51,7 +51,7 @@ if (!empty($user_course_categories)) {
         }
         if ($action != 'unsubscribe') {
             if ($allowCollapsable) {
-                if ($row['collapsed'] == 0) {
+                if (isset($row['collapsed']) && $row['collapsed'] == 0) {
                     echo Display::url(
                         '<i class="fa fa-folder-open"></i>',
                         $url.'&action=set_collapsable&option=1'

+ 6 - 0
main/course_info/infocours.php

@@ -875,9 +875,15 @@ $groupNotification = [
     $form->createElement('radio', 'hide_forum_notifications', null, get_lang('No'), 2),
 ];
 
+$addUsers = [
+    $form->createElement('radio', 'subscribe_users_to_forum_notifications', null, get_lang('Yes'), 1),
+    $form->createElement('radio', 'subscribe_users_to_forum_notifications', null, get_lang('No'), 2),
+];
+
 $globalGroup = [
     get_lang('EnableForumAutoLaunch') => $group,
     get_lang('HideForumNotifications') => $groupNotification,
+    get_lang('SubscribeUsersToAllForumNotifications') => $addUsers,
     '' => $myButton,
 ];
 

+ 12 - 8
main/exercise/exercise.class.php

@@ -3590,10 +3590,11 @@ class Exercise
 
         $organs_at_risk_hit = 0;
         $questionScore = 0;
-        $orderedHotSpots = [];
+        $answer_correct_array = [];
+        $orderedHotspots = [];
 
         if ($answerType == HOT_SPOT || $answerType == ANNOTATION) {
-            $orderedHotSpots = $em->getRepository('ChamiloCoreBundle:TrackEHotspot')->findBy(
+            $orderedHotspots = $em->getRepository('ChamiloCoreBundle:TrackEHotspot')->findBy(
                 [
                     'hotspotQuestionId' => $questionId,
                     'cId' => $course_id,
@@ -3636,7 +3637,7 @@ class Exercise
                         $sql = "SELECT answer FROM $TBL_TRACK_ATTEMPT
                                 WHERE
                                     exe_id = $exeId AND
-                                    question_id = $questionId ";
+                                    question_id = $questionId";
                         $result = Database::query($sql);
                         $choice = Database::result($result, 0, 'answer');
 
@@ -3834,7 +3835,7 @@ class Exercise
                     if ($from_database) {
                         $choice = [];
                         $sql = "SELECT answer FROM $TBL_TRACK_ATTEMPT
-                                WHERE exe_id = $exeId AND question_id= $questionId";
+                                WHERE exe_id = $exeId AND question_id = $questionId";
                         $resultans = Database::query($sql);
                         while ($row = Database::fetch_array($resultans)) {
                             $choice[$row['answer']] = 1;
@@ -4460,7 +4461,7 @@ class Exercise
                             }
 
                             if ($show_result) {
-                                if ($this->showExpectedChoice() == false &&
+                                if ($this->showExpectedChoice() === false &&
                                     $showTotalScoreAndUserChoicesInLastAttempt === false
                                 ) {
                                     $user_answer = '';
@@ -4585,7 +4586,7 @@ class Exercise
                                 WHERE
                                     hotspot_exe_id = $exeId AND
                                     hotspot_question_id= $questionId AND
-                                    hotspot_answer_id = ".intval($answerAutoId)."
+                                    hotspot_answer_id = $answerAutoId
                                 ORDER BY hotspot_id ASC";
                         $result = Database::query($sql);
                         if (Database::num_rows($result)) {
@@ -4727,6 +4728,10 @@ class Exercise
                         }
                         $user_array = substr($user_array, 0, -1);
                     } else {
+                        if (!empty($studentChoice)) {
+                            $newquestionList[] = $questionId;
+                        }
+
                         if ($answerId === 1) {
                             $studentChoice = $choice[$answerId];
                             $questionScore += $answerWeighting;
@@ -5287,7 +5292,6 @@ class Exercise
                             break;
                         case HOT_SPOT_DELINEATION:
                             $user_answer = $user_array;
-                            error_log($next);
                             if ($next) {
                                 $user_answer = $user_array;
                                 // we compare only the delineation not the other points
@@ -5484,7 +5488,7 @@ class Exercise
             'threadhold3' => $threadhold3,
         ];
 
-        if ($from === 'exercise_result') {
+        if ($from == 'exercise_result') {
             // if answer is hotspot. To the difference of exercise_show.php,
             //  we use the results from the session (from_db=0)
             // TODO Change this, because it is wrong to show the user

+ 7 - 30
main/exercise/exercise_show.php

@@ -16,7 +16,7 @@ use ChamiloSession as Session;
  * @todo small letters for table variables
  */
 require_once __DIR__.'/../inc/global.inc.php';
-$debug = false;
+
 $origin = api_get_origin();
 $currentUserId = api_get_user_id();
 $printHeaders = $origin === 'learnpath';
@@ -309,29 +309,24 @@ if ($show_results || $show_only_total_score || $showTotalScoreAndUserChoicesInLa
 }
 
 $i = $totalScore = $totalWeighting = 0;
-if ($debug > 0) {
-    error_log("ExerciseResult: ".print_r($exerciseResult, 1));
-    error_log("QuestionList: ".print_r($questionList, 1));
-}
-
 $arrques = [];
 $arrans = [];
-$user_restriction = $is_allowedToEdit ? '' : "AND user_id=".intval($student_id)." ";
+$user_restriction = $is_allowedToEdit ? '' : " AND user_id= $student_id ";
 $sql = "SELECT attempts.question_id, answer
         FROM $TBL_TRACK_ATTEMPT as attempts
-        INNER JOIN ".$TBL_TRACK_EXERCISES." AS stats_exercises
-        ON stats_exercises.exe_id=attempts.exe_id
+        INNER JOIN $TBL_TRACK_EXERCISES AS stats_exercises
+        ON stats_exercises.exe_id = attempts.exe_id
         INNER JOIN $TBL_EXERCISE_QUESTION AS quizz_rel_questions
         ON
             quizz_rel_questions.exercice_id=stats_exercises.exe_exo_id AND
             quizz_rel_questions.question_id = attempts.question_id AND
             quizz_rel_questions.c_id=".api_get_course_int_id()."
-        INNER JOIN ".$TBL_QUESTIONS." AS questions
+        INNER JOIN $TBL_QUESTIONS AS questions
         ON
             questions.id = quizz_rel_questions.question_id AND
             questions.c_id = ".api_get_course_int_id()."
         WHERE
-            attempts.exe_id = ".$id." $user_restriction
+            attempts.exe_id = $id $user_restriction
 		GROUP BY quizz_rel_questions.question_order, attempts.question_id";
 $result = Database::query($sql);
 $question_list_from_database = [];
@@ -592,7 +587,7 @@ foreach ($questionList as $questionId) {
                 $url_name = get_lang('EditCommentsAndMarks');
             } else {
                 $url_name = get_lang('AddComments');
-                if ($action == 'edit') {
+                if ($action === 'edit') {
                     $url_name = get_lang('EditIndividualComment');
                 }
             }
@@ -696,24 +691,6 @@ foreach ($questionList as $questionId) {
                 }
 
                 $formMark->display();
-
-                /*echo '<form name="smarksform_'.$questionId.'" method="post" action="">';
-                echo get_lang('AssignMarks');
-                echo "&nbsp;<select name='marks' id='select_marks_".$questionId."' class='selectpicker exercise_mark_select'>";
-
-                if (empty($model)) {
-                    for ($i = 0; $i <= $questionWeighting; $i++) {
-                        echo '<option value="'.$i.'" '.(($i == $questionScore) ? "selected='selected'" : '').'>'.$i.'</option>';
-                    }
-                } else {
-                    foreach ($model['score_list'] as $item) {
-                        $i = api_number_format($item['score_to_qualify'] / 100 * $questionWeighting, 2);
-                        $model = ExerciseLib::getModelStyle($item, $i);
-                        echo '<option class = "'.$item['css_class'].'" value="'.$i.'" '.(($i == $questionScore) ? "selected='selected'" : '').'>'.$model.'</option>';
-                    }
-                }
-                echo '</select>';
-                echo '</form><br /></div>';*/
                 echo '</div>';
                 if ($questionScore == -1) {
                     $questionScore = 0;

+ 89 - 77
main/forum/forumfunction.inc.php

@@ -99,7 +99,7 @@ function handle_forum_and_forumcategories($lp_id = null)
     $get_content = isset($_GET['content']) ? $_GET['content'] : '';
     $post_submit_cat = isset($_POST['SubmitForumCategory']) ? true : false;
     $post_submit_forum = isset($_POST['SubmitForum']) ? true : false;
-    $get_id = isset($_GET['id']) ? intval($_GET['id']) : '';
+    $get_id = isset($_GET['id']) ? (int) $_GET['id'] : 0;
     $forum_categories_list = get_forum_categories();
 
     // Verify if forum category exists
@@ -110,23 +110,23 @@ function handle_forum_and_forumcategories($lp_id = null)
     $content = '';
 
     // Adding a forum category
-    if (($action_forum_cat == 'add' && $get_content == 'forumcategory') || $post_submit_cat) {
+    if (($action_forum_cat === 'add' && $get_content === 'forumcategory') || $post_submit_cat) {
         $content = show_add_forumcategory_form([], $lp_id); //$lp_id when is called from learning path
     }
 
     // Adding a forum
-    if ((($action_forum_cat == 'add' || $action_forum_cat == 'edit') && $get_content == 'forum') ||
+    if ((($action_forum_cat === 'add' || $action_forum_cat === 'edit') && $get_content === 'forum') ||
         $post_submit_forum
     ) {
         $inputvalues = [];
-        if ($action_forum_cat == 'edit' && $get_id || $post_submit_forum) {
+        if ($action_forum_cat === 'edit' && $get_id || $post_submit_forum) {
             $inputvalues = get_forums($get_id);
         }
         $content = show_add_forum_form($inputvalues, $lp_id);
     }
 
     // Edit a forum category
-    if (($action_forum_cat == 'edit' && $get_content == 'forumcategory') ||
+    if (($action_forum_cat === 'edit' && $get_content === 'forumcategory') ||
     (isset($_POST['SubmitEditForumCategory'])) ? true : false
     ) {
         $forum_category = get_forum_categories($get_id);
@@ -134,10 +134,8 @@ function handle_forum_and_forumcategories($lp_id = null)
     }
 
     // Delete a forum category
-    if ($action_forum_cat == 'delete') {
-        $id_forum = intval($get_id);
-        $list_threads = get_threads($id_forum);
-
+    if ($action_forum_cat === 'delete') {
+        $list_threads = get_threads($get_id);
         for ($i = 0; $i < count($list_threads); $i++) {
             deleteForumCategoryThread('thread', $list_threads[$i]['thread_id']);
             $link_info = GradebookUtils::isResourceInCourseGradebook(
@@ -154,21 +152,21 @@ function handle_forum_and_forumcategories($lp_id = null)
     }
 
     // Change visibility of a forum or a forum category.
-    if ($action_forum_cat == 'invisible' || $action_forum_cat == 'visible') {
+    if ($action_forum_cat === 'invisible' || $action_forum_cat === 'visible') {
         $return_message = change_visibility($get_content, $get_id, $action_forum_cat);
         Display::addFlash(
             Display::return_message($return_message, 'confirmation', false)
         );
     }
     // Change lock status of a forum or a forum category.
-    if ($action_forum_cat == 'lock' || $action_forum_cat == 'unlock') {
+    if ($action_forum_cat === 'lock' || $action_forum_cat === 'unlock') {
         $return_message = change_lock_status($get_content, $get_id, $action_forum_cat);
         Display::addFlash(
             Display::return_message($return_message, 'confirmation', false)
         );
     }
     // Move a forum or a forum category.
-    if ($action_forum_cat == 'move' && isset($_GET['direction'])) {
+    if ($action_forum_cat === 'move' && isset($_GET['direction'])) {
         $return_message = move_up_down($get_content, $_GET['direction'], $get_id);
         Display::addFlash(
             Display::return_message($return_message, 'confirmation', false)
@@ -267,14 +265,14 @@ function show_add_forum_form($inputvalues = [], $lp_id)
         $form_title = get_lang('EditForum');
     }
 
-    $form->addElement('header', $form_title);
+    $form->addHeader($form_title);
 
     // We have a hidden field if we are editing.
     if (!empty($inputvalues) && is_array($inputvalues)) {
         $my_forum_id = isset($inputvalues['forum_id']) ? $inputvalues['forum_id'] : null;
         $form->addElement('hidden', 'forum_id', $my_forum_id);
     }
-    $lp_id = intval($lp_id);
+    $lp_id = (int) $lp_id;
 
     // hidden field if from learning path
     $form->addElement('hidden', 'lp_id', $lp_id);
@@ -892,7 +890,6 @@ function store_forum($values, $courseInfo = [], $returnId = false)
         $logInfo = [
             'tool' => TOOL_FORUM,
             'tool_id' => $values['forum_id'],
-            'tool_id_detail' => 0,
             'action' => 'update-forum',
             'action_details' => 'forum',
             'info' => $values['forum_title'],
@@ -921,7 +918,7 @@ function store_forum($values, $courseInfo = [], $returnId = false)
             'end_time' => !empty($values['end_time']) ? api_get_utc_datetime($values['end_time']) : null,
             'forum_order' => isset($new_max) ? $new_max : null,
             'session_id' => $session_id,
-            'lp_id' => isset($values['lp_id']) ? intval($values['lp_id']) : 0,
+            'lp_id' => isset($values['lp_id']) ? (int) $values['lp_id'] : 0,
             'locked' => 0,
             'forum_id' => 0,
         ];
@@ -930,6 +927,25 @@ function store_forum($values, $courseInfo = [], $returnId = false)
         if ($forumId > 0) {
             $sql = "UPDATE $table_forums SET forum_id = iid WHERE iid = $forumId";
             Database::query($sql);
+            $courseCode = $courseInfo['code'];
+            $subscribe = (int) api_get_course_setting('subscribe_users_to_forum_notifications', $courseCode);
+
+            $status = STUDENT;
+            if (!empty($session_id)) {
+                $status = 0;
+            }
+            if ($subscribe === 1) {
+                $userList = CourseManager::get_user_list_from_course_code(
+                    $courseCode,
+                    $session_id,
+                    null,
+                    null,
+                    $status
+                );
+                foreach ($userList as $userInfo) {
+                    set_notification('forum', $forumId, false, $userInfo, $courseInfo);
+                }
+            }
 
             api_item_property_update(
                 $courseInfo,
@@ -950,7 +966,6 @@ function store_forum($values, $courseInfo = [], $returnId = false)
             $logInfo = [
                 'tool' => TOOL_FORUM,
                 'tool_id' => $forumId,
-                'tool_id_detail' => 0,
                 'action' => 'new-forum',
                 'action_details' => 'forum',
                 'info' => $values['forum_title'],
@@ -999,7 +1014,7 @@ function deleteForumCategoryThread($content, $id)
     $groupId = api_get_group_id();
     $groupInfo = GroupManager::get_group_properties($groupId);
     $userId = api_get_user_id();
-    $id = intval($id);
+    $id = (int) $id;
 
     // Delete all attachment file about this tread id.
     $sql = "SELECT post_id FROM $table_forums_post
@@ -1011,7 +1026,7 @@ function deleteForumCategoryThread($content, $id)
 
     $tool_constant = null;
     $return_message = '';
-    if ($content == 'forumcategory') {
+    if ($content === 'forumcategory') {
         $tool_constant = TOOL_FORUM_CATEGORY;
         $return_message = get_lang('ForumCategoryDeleted');
 
@@ -1033,7 +1048,7 @@ function deleteForumCategoryThread($content, $id)
         }
     }
 
-    if ($content == 'forum') {
+    if ($content === 'forum') {
         $tool_constant = TOOL_FORUM;
         $return_message = get_lang('ForumDeleted');
 
@@ -1055,7 +1070,7 @@ function deleteForumCategoryThread($content, $id)
         }
     }
 
-    if ($content == 'thread') {
+    if ($content === 'thread') {
         $tool_constant = TOOL_FORUM_THREAD;
         $return_message = get_lang('ThreadDeleted');
         Skill::deleteSkillsFromItem($id, ITEM_TYPE_FORUM_THREAD);
@@ -5621,58 +5636,68 @@ function get_forums_of_group($groupInfo)
 /**
  * This function stores which users have to be notified of which forums or threads.
  *
- * @param string $content does the user want to be notified about a forum or about a thread
- * @param int    $id      the id of the forum or thread
+ * @param string $content    does the user want to be notified about a forum or about a thread
+ * @param int    $id         the id of the forum or thread
+ * @param bool   $addOnly
+ * @param array  $userInfo
+ * @param array  $courseInfo
  *
  * @return string language variable
  *
- * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
- *
- * @version May 2008, dokeos 1.8.5
+ * @author  Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
+ * @author  Julio Montoya
  *
- * @since May 2008, dokeos 1.8.5
+ * @since   May 2008 v1.8.5
  */
-function set_notification($content, $id, $add_only = false)
+function set_notification($content, $id, $addOnly = false, $userInfo = [], $courseInfo = [])
 {
-    $_user = api_get_user_info();
+    $userInfo = empty($userInfo) ? api_get_user_info() : $userInfo;
+    $courseInfo = empty($courseInfo) ? api_get_course_info() : $courseInfo;
+    $id = (int) $id;
+
+    if (empty($userInfo) || empty($courseInfo) || empty($id) || empty($content)) {
+        return false;
+    }
+
     // Database table definition
     $table_notification = Database::get_course_table(TABLE_FORUM_NOTIFICATION);
 
-    $course_id = api_get_course_int_id();
+    $course_id = $courseInfo['real_id'];
 
     // Which database field do we have to store the id in?
-    if ($content == 'forum') {
-        $database_field = 'forum_id';
-    } else {
-        $database_field = 'thread_id';
+    $field = 'thread_id';
+    if ($content === 'forum') {
+        $field = 'forum_id';
     }
 
+    $userId = $userInfo['user_id'];
+
     // First we check if the notification is already set for this.
     $sql = "SELECT * FROM $table_notification
             WHERE
                 c_id = $course_id AND
-                $database_field = '".Database::escape_string($id)."' AND
-                user_id = '".intval($_user['user_id'])."'";
+                $field = $id AND
+                user_id = $userId ";
     $result = Database::query($sql);
     $total = Database::num_rows($result);
 
     // If the user did not indicate that (s)he wanted to be notified already
     // then we store the notification request (to prevent double notification requests).
     if ($total <= 0) {
-        $sql = "INSERT INTO $table_notification (c_id, $database_field, user_id)
-                VALUES (".$course_id.", '".Database::escape_string($id)."','".intval($_user['user_id'])."')";
+        $sql = "INSERT INTO $table_notification (c_id, $field, user_id)
+                VALUES ($course_id, '$id','$userId')";
         Database::query($sql);
         Session::erase('forum_notification');
         getNotificationsPerUser(0, true);
 
         return get_lang('YouWillBeNotifiedOfNewPosts');
     } else {
-        if (!$add_only) {
+        if (!$addOnly) {
             $sql = "DELETE FROM $table_notification
                     WHERE
                         c_id = $course_id AND
-                        $database_field = '".Database::escape_string($id)."' AND
-                        user_id = '".intval($_user['user_id'])."'";
+                        $field = $id AND
+                        user_id = $userId ";
             Database::query($sql);
             Session::erase('forum_notification');
             getNotificationsPerUser(0, true);
@@ -5692,6 +5717,7 @@ function set_notification($content, $id, $add_only = false)
  * @return array returns
  *
  * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University, Belgium
+ * @author Julio Montoya
  *
  * @version May 2008, dokeos 1.8.5
  *
@@ -5705,18 +5731,19 @@ function get_notifications($content, $id)
     $course_id = api_get_course_int_id();
 
     // Which database field contains the notification?
-    if ($content == 'forum') {
-        $database_field = 'forum_id';
-    } else {
-        $database_field = 'thread_id';
+    $field = 'thread_id';
+    if ($content === 'forum') {
+        $field = 'forum_id';
     }
 
+    $id = (int) $id;
+
     $sql = "SELECT user.user_id, user.firstname, user.lastname, user.email, user.user_id user
             FROM $table_users user, $table_notification notification
             WHERE 
                 notification.c_id = $course_id AND user.active = 1 AND
                 user.user_id = notification.user_id AND
-                notification.$database_field= '".Database::escape_string($id)."'";
+                notification.$field = $id ";
 
     $result = Database::query($sql);
     $return = [];
@@ -5746,20 +5773,7 @@ function get_notifications($content, $id)
  */
 function send_notifications($forum_id = 0, $thread_id = 0, $post_id = 0)
 {
-    //$_course = api_get_course_info();
-
-    /*$forumCourseId = api_get_configuration_value('global_forums_course_id');
-    if (!empty($forumCourseId)) {
-        if ($_course['real_id'] == $forumCourseId) {
-            return false;
-        }
-    }*/
-
     $forum_id = (int) $forum_id;
-
-    // The content of the mail
-    //$thread_link = api_get_path(WEB_CODE_PATH).'forum/viewthread.php?'.api_get_cidreq().'&forum='.$forum_id.'&thread='.$thread_id;
-
     // Users who subscribed to the forum
     if ($forum_id != 0) {
         $users_to_be_notified_by_forum = get_notifications('forum', $forum_id);
@@ -5768,8 +5782,6 @@ function send_notifications($forum_id = 0, $thread_id = 0, $post_id = 0)
     }
 
     $current_thread = get_thread_information($forum_id, $thread_id);
-    //$current_forum = get_forum_information($current_thread['forum_id']);
-    //$subject = get_lang('NewForumPost').' - '.$_course['official_code'].' - '.$current_forum['forum_title'].' - '.$current_thread['thread_title'];
 
     // User who subscribed to the thread
     if ($thread_id != 0) {
@@ -6225,8 +6237,8 @@ function editAttachedFile($array, $id, $courseId = null)
 {
     // Init variables
     $setString = '';
-    $id = intval($id);
-    $courseId = intval($courseId);
+    $id = (int) $id;
+    $courseId = (int) $courseId;
     if (empty($courseId)) {
         // $courseId can be null, use api method
         $courseId = api_get_course_int_id();
@@ -6274,8 +6286,7 @@ function editAttachedFile($array, $id, $courseId = null)
  */
 function getAttachmentsAjaxTable($postId = 0)
 {
-    // Init variables
-    $postId = intval($postId);
+    $postId = (int) $postId;
     $courseId = api_get_course_int_id();
     $attachIds = getAttachmentIdsByPostId($postId, $courseId);
     $fileDataContent = '';
@@ -6354,10 +6365,10 @@ function getAttachedFiles(
     $attachId = 0,
     $courseId = 0
 ) {
-    $forumId = intval($forumId);
-    $courseId = intval($courseId);
-    $attachId = intval($attachId);
-    $postId = intval($postId);
+    $forumId = (int) $forumId;
+    $courseId = (int) $courseId;
+    $attachId = (int) $attachId;
+    $postId = (int) $postId;
     $threadId = !empty($threadId) ? intval($threadId) : isset($_REQUEST['thread']) ? intval($_REQUEST['thread']) : '';
     if (empty($courseId)) {
         // $courseId can be null, use api method
@@ -6365,7 +6376,7 @@ function getAttachedFiles(
     }
     if (empty($forumId)) {
         if (!empty($_REQUEST['forum'])) {
-            $forumId = intval($_REQUEST['forum']);
+            $forumId = (int) $_REQUEST['forum'];
         } else {
             // if forum ID is empty, cannot generate delete url
 
@@ -6435,11 +6446,11 @@ function getAttachedFiles(
  *
  * @return array
  */
-function clearAttachedFiles($postId = null, $courseId = null)
+function clearAttachedFiles($postId = 0, $courseId = 0)
 {
     // Init variables
-    $courseId = intval($courseId);
-    $postId = intval($postId);
+    $courseId = (int) $courseId;
+    $postId = (int) $postId;
     $array = [];
     if (empty($courseId)) {
         // $courseId can be null, use api method
@@ -6485,8 +6496,8 @@ function clearAttachedFiles($postId = null, $courseId = null)
 function getAttachmentIdsByPostId($postId, $courseId = 0)
 {
     $array = [];
-    $courseId = intval($courseId);
-    $postId = intval($postId);
+    $courseId = (int) $courseId;
+    $postId = (int) $postId;
     if (empty($courseId)) {
         // $courseId can be null, use api method
         $courseId = api_get_course_int_id();
@@ -6517,7 +6528,8 @@ function getAttachmentIdsByPostId($postId, $courseId = 0)
  */
 function getForumCategoryByTitle($title, $courseId, $sessionId = 0)
 {
-    $sessionId = intval($sessionId);
+    $sessionId = (int) $sessionId;
+    $courseId = (int) $courseId;
     $forumCategoryTable = Database::get_course_table(TABLE_FORUM_CATEGORY);
     $itemProperty = Database::get_course_table(TABLE_ITEM_PROPERTY);
 
@@ -6547,7 +6559,7 @@ function getForumCategoryByTitle($title, $courseId, $sessionId = 0)
                 'ip.tool = ? AND ' => TOOL_FORUM_CATEGORY,
                 'fc.session_id = ? AND ' => $sessionId,
                 'fc.cat_title = ? AND ' => $title,
-                'fc.c_id = ?' => intval($courseId),
+                'fc.c_id = ?' => $courseId,
             ],
         ],
         'first'

+ 6 - 9
main/forum/index.php

@@ -62,9 +62,9 @@ if (api_is_in_gradebook()) {
 $search_forum = isset($_GET['search']) ? Security::remove_XSS($_GET['search']) : '';
 
 /* ACTIONS */
-$actions = isset($_GET['action']) ? $_GET['action'] : '';
+$action = isset($_GET['action']) ? $_GET['action'] : '';
 
-if ($actions === 'add') {
+if ($action === 'add') {
     switch ($_GET['content']) {
         case 'forum':
             $interbreadcrumb[] = [
@@ -102,12 +102,12 @@ $form_count = 0;
 $formContent = '';
 if (api_is_allowed_to_edit(false, true)) {
     //if is called from a learning path lp_id
-    $lp_id = isset($_REQUEST['lp_id']) ? intval($_REQUEST['lp_id']) : null;
+    $lp_id = isset($_REQUEST['lp_id']) ? (int) $_REQUEST['lp_id'] : null;
     $formContent = handle_forum_and_forumcategories($lp_id);
 }
 
 // Notification
-if ($actions == 'notify' && isset($_GET['content']) && isset($_GET['id'])) {
+if ($action == 'notify' && isset($_GET['content']) && isset($_GET['id'])) {
     if (api_get_session_id() != 0 &&
         api_is_allowed_to_session_edit(false, true) == false
     ) {
@@ -120,14 +120,11 @@ if ($actions == 'notify' && isset($_GET['content']) && isset($_GET['id'])) {
 get_whats_new();
 $whatsnew_post_info = Session::read('whatsnew_post_info');
 
-/* TRACKING */
 Event::event_access_tool(TOOL_FORUM);
 
 $logInfo = [
     'tool' => TOOL_FORUM,
-    'tool_id' => 0,
-    'tool_id_detail' => 0,
-    'action' => !empty($actions) ? $actions : 'list-category',
+    'action' => !empty($action) ? $action : 'list-category',
     'action_details' => isset($_GET['content']) ? $_GET['content'] : '',
 ];
 Event::registerLog($logInfo);
@@ -557,7 +554,7 @@ if (is_array($forumCategories)) {
                             }
                         }
 
-                        if (!api_is_anonymous() && api_is_allowed_to_session_edit(false, true) && $hideNotifications == false) {
+                        if ($hideNotifications == false && !api_is_anonymous() && api_is_allowed_to_session_edit(false, true)) {
                             $toolActions .= '<a href="'.api_get_self().'?'.api_get_cidreq()
                                 .'&action=notify&content=forum&id='.$forum['forum_id'].'">'
                                 .Display::return_icon($iconnotify, get_lang('NotifyMe'), null, ICON_SIZE_SMALL)

+ 0 - 2
main/gradebook/gradebook_edit_cat.php

@@ -2,8 +2,6 @@
 /* For licensing terms, see /license.txt */
 
 /**
- * Script.
- *
  * @package chamilo.gradebook
  */
 require_once __DIR__.'/../inc/global.inc.php';

+ 5 - 7
main/gradebook/index.php

@@ -178,8 +178,6 @@ $my_actions = implode(';', $list_actions);
 $my_actions_values = implode(';', $list_values);
 $logInfo = [
     'tool' => TOOL_GRADEBOOK,
-    'tool_id' => 0,
-    'tool_id_detail' => 0,
     'action' => $my_actions,
     'action_details' => $my_actions_values,
 ];
@@ -260,19 +258,19 @@ if (isset($_GET['visiblelog'])) {
 //move a category
 if (isset($_GET['movecat'])) {
     GradebookUtils::block_students();
-    $cats = Category::load($_GET['movecat']);
+    $moveCategoryId = isset($_GET['movecat']) ? (int) $_GET['movecat'] : 0;
+    $cats = Category::load($moveCategoryId);
     if (!isset($_GET['targetcat'])) {
         $move_form = new CatForm(
             CatForm::TYPE_MOVE,
             $cats[0],
             'move_cat_form',
             null,
-            api_get_self().'?movecat='.intval($_GET['movecat']).'&selectcat='.$selectCat
+            api_get_self().'?movecat='.$moveCategoryId.'&selectcat='.$selectCat
         );
         if ($move_form->validate()) {
             header('Location: '.api_get_self().'?selectcat='.$selectCat
-                .'&movecat='.intval($_GET['movecat'])
-                .'&targetcat='.$move_form->exportValue('move_cat'));
+                .'&movecat='.$moveCategoryId.'&targetcat='.$move_form->exportValue('move_cat'));
             exit;
         }
     } else {
@@ -492,7 +490,7 @@ if (!empty($course_to_crsind) && !isset($_GET['confirm'])) {
         die('Error: movecat or moveeval not defined');
     }
     $button = '<form name="confirm" method="post" action="'.api_get_self().'?confirm='
-        .(isset($_GET['movecat']) ? '&movecat='.intval($_GET['movecat'])
+        .(isset($_GET['movecat']) ? '&movecat='.$moveCategoryId
             : '&moveeval='.intval($_GET['moveeval'])).'&selectcat='.$selectCat.'&targetcat='.intval($_GET['targetcat']).'">
 			   <input type="submit" value="'.get_lang('Ok').'">
 			   </form>';

+ 20 - 14
main/gradebook/lib/GradebookUtils.php

@@ -707,9 +707,12 @@ class GradebookUtils
         $date_certificate
     ) {
         $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
-        $sql = 'SELECT COUNT(id) as count
-                FROM '.$table.' gc
-                WHERE gc.cat_id="'.intval($cat_id).'" AND user_id="'.intval($user_id).'" ';
+        $cat_id = (int) $cat_id;
+        $user_id = (int) $user_id;
+
+        $sql = "SELECT COUNT(id) as count
+                FROM $table gc
+                WHERE gc.cat_id = $cat_id AND user_id = $user_id ";
         $rs_exist = Database::query($sql);
         $row = Database::fetch_array($rs_exist);
         if ($row['count'] == 0) {
@@ -734,8 +737,11 @@ class GradebookUtils
     public static function get_certificate_by_user_id($cat_id, $user_id)
     {
         $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
-        $sql = 'SELECT * FROM '.$table.'
-                WHERE cat_id="'.intval($cat_id).'" AND user_id="'.intval($user_id).'"';
+        $cat_id = (int) $cat_id;
+        $user_id = (int) $user_id;
+
+        $sql = "SELECT * FROM $table
+                WHERE cat_id = $cat_id AND user_id = $user_id ";
 
         $result = Database::query($sql);
         $row = Database::fetch_array($result, 'ASSOC');
@@ -792,12 +798,12 @@ class GradebookUtils
     ) {
         $user_id = (int) $user_id;
         $table_certificate = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
-        $sql = 'SELECT 
-                    gc.score_certificate, 
-                    gc.created_at, 
-                    gc.path_certificate, 
-                    gc.cat_id, 
-                    gc.user_id, 
+        $sql = 'SELECT
+                    gc.score_certificate,
+                    gc.created_at,
+                    gc.path_certificate,
+                    gc.cat_id,
+                    gc.user_id,
                     gc.id
                 FROM  '.$table_certificate.' gc
                 WHERE gc.user_id = "'.$user_id.'" ';
@@ -849,9 +855,9 @@ class GradebookUtils
 
         //add print header
         if (!$hide_print_button) {
-            $print = '<style>#print_div {               
+            $print = '<style>#print_div {
                 padding:4px;border: 0 none;position: absolute;top: 0px;right: 0px;
-            }            
+            }
             @media print {
                 #print_div  {
                     display: none !important;
@@ -1184,7 +1190,7 @@ class GradebookUtils
                     ";
         } else {
             $sql = 'SELECT user.user_id, user.username, lastname, firstname, official_code
-                    FROM '.$tbl_course_user.' as course_rel_user 
+                    FROM '.$tbl_course_user.' as course_rel_user
                     INNER JOIN '.$tbl_user.' as user
                     ON (course_rel_user.user_id = user.id)
                     WHERE

+ 4 - 2
main/gradebook/lib/be/abstractlink.class.php

@@ -713,6 +713,8 @@ abstract class AbstractLink implements GradebookItem
         $itemId = (int) $itemId;
         $linkType = (int) $linkType;
         $sessionId = (int) $sessionId;
+
+        $sessionCondition = api_get_session_condition($sessionId, true, false, 'c.session_id');
         $courseCode = Database::escape_string($courseCode);
 
         $sql = "SELECT DISTINCT l.* 
@@ -721,8 +723,8 @@ abstract class AbstractLink implements GradebookItem
                 WHERE 
                     ref_id = $itemId AND 
                     type = $linkType AND 
-                    l.course_code = '$courseCode' AND 
-                    c.session_id = $sessionId";
+                    l.course_code = '$courseCode' 
+                    $sessionCondition ";
 
         $result = Database::query($sql);
         if (Database::num_rows($result)) {

+ 16 - 10
main/gradebook/lib/be/category.class.php

@@ -100,9 +100,9 @@ class Category implements GradebookItem
     {
         if (!empty($this->certificate_min_score)) {
             return $this->certificate_min_score;
-        } else {
-            return null;
         }
+
+        return null;
     }
 
     /**
@@ -2060,7 +2060,7 @@ class Category implements GradebookItem
         $category_id = (int) $category_id;
 
         // Generating the total score for a course
-        $cats_course = self::load(
+        $category = self::load(
             $category_id,
             null,
             null,
@@ -2071,7 +2071,7 @@ class Category implements GradebookItem
         );
 
         /** @var Category $category */
-        $category = $cats_course[0];
+        $category = $category[0];
 
         if (empty($category)) {
             return false;
@@ -2131,20 +2131,18 @@ class Category implements GradebookItem
             return false;
         }
 
-        $cattotal = self::load($category_id);
-        $scoretotal = $cattotal[0]->calc_score($user_id);
+        $scoretotal = $category->calc_score($user_id);
 
         // Do not remove this the gradebook/lib/fe/gradebooktable.class.php
         // file load this variable as a global
         $scoredisplay = ScoreDisplay::instance();
-
         $my_score_in_gradebook = $scoredisplay->display_score(
             $scoretotal,
             SCORE_SIMPLE
         );
 
         $my_certificate = GradebookUtils::get_certificate_by_user_id(
-            $category->get_id(),
+            $category_id,
             $user_id
         );
 
@@ -2156,7 +2154,7 @@ class Category implements GradebookItem
                 api_get_utc_datetime()
             );
             $my_certificate = GradebookUtils::get_certificate_by_user_id(
-                $category->get_id(),
+                $category_id,
                 $user_id
             );
         }
@@ -2171,8 +2169,16 @@ class Category implements GradebookItem
 
             $fileWasGenerated = $certificate_obj->isHtmlFileGenerated();
 
+            // Fix when using custom certificate BT#15937
+            if (api_get_plugin_setting('customcertificate', 'enable_plugin_customcertificate') === 'true') {
+                $infoCertificate = CustomCertificatePlugin::getCertificateData($my_certificate['id'], $user_id);
+                if (!empty($infoCertificate)) {
+                    $fileWasGenerated = true;
+                }
+            }
+
             if (!empty($fileWasGenerated)) {
-                $url = api_get_path(WEB_PATH).'certificates/index.php?id='.$my_certificate['id'];
+                $url = api_get_path(WEB_PATH).'certificates/index.php?id='.$my_certificate['id'].'&user_id='.$user_id;
                 $certificates = Display::toolbarButton(
                     get_lang('DisplayCertificate'),
                     $url,

+ 11 - 9
main/gradebook/lib/be/evaluation.class.php

@@ -74,7 +74,7 @@ class Evaluation implements GradebookItem
      */
     public function get_id()
     {
-        return $this->id;
+        return (int) $this->id;
     }
 
     /**
@@ -424,7 +424,7 @@ class Evaluation implements GradebookItem
     {
         $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_EVALUATION);
         $sql = 'DELETE FROM '.$table.' 
-                WHERE id = '.intval($this->id);
+                WHERE id = '.$this->get_id();
         Database::query($sql);
     }
 
@@ -490,7 +490,7 @@ class Evaluation implements GradebookItem
         $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_RESULT);
         $sql = 'SELECT count(id) AS number
                 FROM '.$table.'
-                WHERE evaluation_id = '.intval($this->id);
+                WHERE evaluation_id = '.intval($this->get_id());
         $result = Database::query($sql);
         $number = Database::fetch_row($result);
 
@@ -504,7 +504,7 @@ class Evaluation implements GradebookItem
     {
         $table = Database::get_main_table(TABLE_MAIN_GRADEBOOK_RESULT);
         $sql = 'DELETE FROM '.$table.'
-                WHERE evaluation_id = '.intval($this->id);
+                WHERE evaluation_id = '.$this->get_id();
         Database::query($sql);
     }
 
@@ -784,7 +784,7 @@ class Evaluation implements GradebookItem
                     lastname LIKE '".Database::escape_string($first_letter_user)."%' AND 
                     status = ".STUDENT." AND user_id NOT IN (
                         SELECT user_id FROM $table 
-                        WHERE evaluation_id = ".intval($this->id)."
+                        WHERE evaluation_id = ".$this->get_id()."
                     )
                 ORDER BY lastname";
 
@@ -840,7 +840,7 @@ class Evaluation implements GradebookItem
         $table_evaluation = Database::get_main_table(TABLE_MAIN_GRADEBOOK_EVALUATION);
         $sql = "UPDATE $table_evaluation 
                 SET locked = '".intval($locked)."' 
-                WHERE id='".intval($this->id)."'";
+                WHERE id='".$this->get_id()."'";
         Database::query($sql);
     }
 
@@ -963,13 +963,15 @@ class Evaluation implements GradebookItem
     /**
      * Internal function used by get_target_categories().
      *
-     * @param int $level
+     * @param array $targets
+     * @param int   $level
+     * @param int   $categoryId
      *
      * @return array
      */
-    private function addTargetSubcategories($targets, $level, $catid)
+    private function addTargetSubcategories($targets, $level, $categoryId)
     {
-        $subcats = Category::load(null, null, null, $catid);
+        $subcats = Category::load(null, null, null, $categoryId);
         foreach ($subcats as $cat) {
             $targets[] = [$cat->get_id(), $cat->get_name(), $level + 1];
             $targets = $this->addTargetSubcategories(

+ 4 - 0
main/gradebook/lib/fe/catform.class.php

@@ -273,6 +273,10 @@ class CatForm extends FormValidator
         }
 
         $defaultCertification = 0;
+        if (!empty($this->category_object)) {
+            $defaultCertification = $this->category_object->getCertificateMinScore();
+        }
+
         if (isset($this->category_object) &&
             $this->category_object->get_parent_id() == 0
         ) {

+ 4 - 4
main/gradebook/lib/fe/displaygradebook.php

@@ -393,7 +393,8 @@ class DisplayGradebook
                 isset($_GET['selectcat']) && $_GET['selectcat'] != 0) &&
                 isset($_GET['studentoverview'])
             ) {
-                $header .= '<td style="vertical-align: top;"><a href="'.api_get_self().'?'.api_get_cidreq().'&studentoverview=&exportpdf=&selectcat='.$catobj->get_id().'" target="_blank">
+                $header .= '<td style="vertical-align: top;">
+                                <a href="'.api_get_self().'?'.api_get_cidreq().'&studentoverview=&exportpdf=&selectcat='.$catobj->get_id().'" target="_blank">
 							 '.Display::return_icon('pdf.png', get_lang('ExportPDF'), [], ICON_SIZE_MEDIUM).'
 							'.get_lang('ExportPDF').'</a>';
             }
@@ -550,17 +551,16 @@ class DisplayGradebook
                 '</a>';
         }
 
-        if (api_is_allowed_to_edit(null, true) || $isCoach) {
+        if ($isCoach || api_is_allowed_to_edit(null, true)) {
             echo $toolbar = Display::toolbarAction(
                 'gradebook-actions',
                 [$actionsLeft, $actionsRight]
             );
         }
 
-        if (api_is_allowed_to_edit(null, true) || $accessToEdit) {
+        if ($accessToEdit || api_is_allowed_to_edit(null, true)) {
             $weight = intval($catobj->get_weight()) > 0 ? $catobj->get_weight() : 0;
             $weight = '<strong>'.get_lang('TotalWeight').' : </strong>'.$weight;
-
             $min_certification = intval($catobj->getCertificateMinScore() > 0) ? $catobj->getCertificateMinScore() : 0;
 
             if (!empty($min_certification)) {

+ 3 - 1
main/gradebook/lib/scoredisplay.class.php

@@ -21,6 +21,8 @@ class ScoreDisplay
 
     /**
      * Protected constructor - call instance() to instantiate.
+     *
+     * @param int $category_id
      */
     public function __construct($category_id = 0)
     {
@@ -55,7 +57,7 @@ class ScoreDisplay
                 foreach ($displays as $display) {
                     $data = explode('::', $display['selected_value']);
                     if (empty($data[1])) {
-                        $data[1] = "";
+                        $data[1] = '';
                     }
                     $portal_displays[$data[0]] = [
                         'score' => $data[0],

+ 0 - 2
main/inc/ajax/lp.ajax.php

@@ -80,8 +80,6 @@ switch ($action) {
         if (api_is_allowed_to_edit(null, true)) {
             $new_order = $_POST['new_order'];
             $sections = explode('^', $new_order);
-            $new_array = [];
-
             // We have to update parent_item_id, previous_item_id, next_item_id, display_order in the database
             $itemList = new LpItemOrderList();
             foreach ($sections as $items) {

+ 2 - 2
main/inc/ajax/message.ajax.php

@@ -112,7 +112,7 @@ switch ($action) {
 
         /** @var User $user */
         foreach ($users as $user) {
-            $userName = $user->getCompleteNameWithUsername();
+            $userName = UserManager::formatUserFullName($user, true);
 
             if ($showEmail) {
                 $userName .= " ({$user->getEmail()})";
@@ -123,7 +123,7 @@ switch ($action) {
                 'id' => $user->getId(),
             ];
         }
-
+        header('Content-type:application/json');
         echo json_encode($return);
         break;
     default:

+ 8 - 9
main/inc/ajax/social.ajax.php

@@ -219,19 +219,12 @@ switch ($action) {
             $comment = isset($_REQUEST['comment']) ? $_REQUEST['comment'] : '';
             if (!empty($comment)) {
                 $messageId = SocialManager::sendWallMessage(
-                    api_get_user_id(),
+                    $userId,
                     $messageInfo['user_receiver_id'],
                     $comment,
                     $messageId,
                     MESSAGE_STATUS_WALL
                 );
-                /*if ($messageId && !empty($_FILES['picture']['tmp_name'])) {
-                    self::sendWallMessageAttachmentFile(
-                        $friendId,
-                        $_FILES['picture'],
-                        $messageId
-                    );
-                }*/
                 if ($messageId) {
                     $messageInfo = MessageManager::get_message_by_id($messageId);
                     echo SocialManager::processPostComment($messageInfo);
@@ -273,6 +266,7 @@ switch ($action) {
         $start = isset($_REQUEST['start']) ? (int) $_REQUEST['start'] : 0;
         $length = isset($_REQUEST['length']) ? (int) $_REQUEST['length'] : 10;
         $userId = isset($_REQUEST['u']) ? (int) $_REQUEST['u'] : api_get_user_id();
+
         $html = '';
         if ($userId == api_get_user_id()) {
             $threadList = SocialManager::getThreadList($userId);
@@ -281,7 +275,12 @@ switch ($action) {
                 $threadIdList = array_column($threadList, 'id');
             }
 
-            $html = SocialManager::getMyWallMessages($userId, $start, SocialManager::DEFAULT_SCROLL_NEW_POST, $threadIdList);
+            $html = SocialManager::getMyWallMessages(
+                $userId,
+                $start,
+                SocialManager::DEFAULT_SCROLL_NEW_POST,
+                $threadIdList
+            );
             $html = $html['posts'];
         } else {
             $messages = SocialManager::getWallMessages(

+ 26 - 63
main/inc/lib/Compilatio.php

@@ -5,9 +5,7 @@
  * Build the comunication with the SOAP server Compilatio.net
  * call severals methods for the file management in Compilatio.net.
  *
- * Date: 26/05/16
- *
- * @version:1.0
+ * @version: 2.0
  */
 class Compilatio
 {
@@ -402,62 +400,33 @@ class Compilatio
     }
 
     /**
-     * Fonction  affichage de la barre de progression d'analyse version 3.1.
+     * Fonction affichage de la barre de progression d'analyse version 3.1.
      *
      * @param string $status From the document
-     * @param $pour
-     * @param string $imagesPath
-     * @param array  $text       Array includes the extract from the text
+     * @param int    $pour
+     * @param array  $text   Array includes the extract from the text
      *
      * @return string
      */
-    public static function getProgressionAnalyseDocv31($status, $pour = 0, $imagesPath = '', $text = [])
+    public static function getProgressionAnalyseDocv31($status, $pour = 0, $text = [])
     {
-        $refreshReturn = "<a href='javascript:window.location.reload(false);'><img src='"
-            .$imagesPath
-            ."ajax-loader_green.gif' title='"
-            .$text['refresh']
-            ."' alt='"
-            .$text['refresh']
-            ."'/></a> ";
-        $startReturn = "<table cellpadding='0' cellspacing='0' style='border:0;margin:0;padding:0;'><tr>";
-        $startReturn .= "<td width='25' style='border:0;margin:0;padding:0;'>&nbsp;</td>";
-        $startReturn .= "<td valign='middle' align='right' style='border:0;margin:0;padding-right:10px;'>"
-            .$refreshReturn
-            ."</td>";
-        $startReturn .= "<td style='border:0;margin:0;padding:0;'>";
-        $startReturnLittleWidth = "<table cellpadding='0' cellspacing='0' style='border:0;margin:0;padding:0;'><tr>";
-        $startReturnLittleWidth .= "<td width='25' valign='middle' align='right' style='border:0;margin:0;padding:0;'>"
-            .$refreshReturn
-            ."</td>";
-        $finretour = "</td></tr></table>";
-
-        if ($status == 'ANALYSE_IN_QUEUE') {
-            return $startReturn."<span style='font-size:11px'>".$text['analysisinqueue']."</span>".$finretour;
-        }
-        if ($status == 'ANALYSE_PROCESSING') {
-            if ($pour == 100) {
-                return $startReturn
-                    ."<span style='font-size:11px'>"
-                    .$text['analysisinfinalization']
-                    ."</span>"
-                    .$finretour;
-            } else {
-                return $startReturnLittleWidth
-                    ."<td align=\"right\" style=\"border:0;margin:0;padding-right:10px;\">"
-                    .$pour
-                    ."%</td><td style=\"border:0;margin:0;padding:0;\"><div style=\"background"
-                    .":transparent url("
-                    .$imagesPath
-                    ."mini-jauge_fond.png) no-repeat scroll 0;height:12px;padding:0 0 0 2px;width:55px;\"><div style=\""
-                    ."background:transparent url("
-                    .$imagesPath
-                    ."mini-jauge_gris.png) no-repeat scroll 0;height:12px;width:"
-                    .$pour / 2
-                    ."px;\"></div></div>"
-                    .$finretour;
-            }
+        $loading = Display::returnFontAwesomeIcon('spinner', null, true, 'fa-spin');
+        $loading .= '&nbsp;';
+        //$refreshReturn = Display::url('javascript:window.location.reload(false);', $loading);
+
+        switch ($status) {
+            case 'ANALYSE_IN_QUEUE':
+                $content = $loading.$text['analysisinqueue'];
+                break;
+            case 'ANALYSE_PROCESSING':
+                $content = $loading.$text['analysisinfinalization'];
+                break;
+            default:
+                $content = Display::bar_progress($pour, true);
+                break;
         }
+
+        return $content;
     }
 
     /**
@@ -604,7 +573,11 @@ class Compilatio
                             10,
                             35
                         )
-                        ."<a href='".$urlRapport."' target='_blank'>".get_lang('CompilatioAnalysis')."</a>";
+                        .Display::url(
+                            get_lang('CompilatioAnalysis'),
+                            $urlRapport,
+                            ['class' => 'btn btn-primary btn-xs', 'target' => '_blank']
+                        );
                     break;
                 case 'ANALYSE_PROCESSING':
                     $actionCompilatio .= "<div style='font-weight:bold;text-align:left'>"
@@ -620,7 +593,6 @@ class Compilatio
                     $actionCompilatio .= self::getProgressionAnalyseDocv31(
                         $status,
                         $soapRes->documentStatus->progression,
-                        $compilatioImgFolder,
                         $text
                     );
                     break;
@@ -637,15 +609,6 @@ class Compilatio
                     $actionCompilatio .= get_lang('CompilatioFileIsTooBig');
                     break;
             }
-
-            /*
-            } elseif ($status != 'NOT_IN_COMPILATIO') {
-                $actionCompilatio .= "<div style='font-style:italic'>"
-                    .get_lang('compilatioMomentarilyUnavailableResult')
-                    ." : [ "
-                    .$status
-                    ."].</div>";
-            }*/
         }
 
         $result = $workId.'|'.$actionCompilatio.'|'.$status.'|';

+ 2 - 2
main/inc/lib/CourseChatUtils.php

@@ -177,7 +177,7 @@ class CourseChatUtils
             $fileContent = '
                 <div class="message-teacher">
                     <div class="content-message">
-                        <div class="chat-message-block-name">'.$user->getCompleteName().'</div>
+                        <div class="chat-message-block-name">'.UserManager::formatUserFullName($user).'</div>
                         <div class="chat-message-block-content">'.$message.'</div>
                         <div class="message-date">'.$timeNow.'</div>
                     </div>
@@ -191,7 +191,7 @@ class CourseChatUtils
                     <img class="chat-image" src="'.$userPhoto.'">
                     <div class="icon-message"></div>
                     <div class="content-message">
-                        <div class="chat-message-block-name">'.$user->getCompleteName().'</div>
+                        <div class="chat-message-block-name">'.UserManager::formatUserFullName($user).'</div>
                         <div class="chat-message-block-content">'.$message.'</div>
                         <div class="message-date">'.$timeNow.'</div>
                     </div>

+ 20 - 18
main/inc/lib/api.lib.php

@@ -17,12 +17,8 @@ use Symfony\Component\Finder\Finder;
  * @package chamilo.library
  */
 
-/**
- * Constants declaration.
- */
-
 // PHP version requirement.
-define('REQUIRED_PHP_VERSION', '5.5');
+define('REQUIRED_PHP_VERSION', '5.6');
 define('REQUIRED_MIN_MEMORY_LIMIT', '128');
 define('REQUIRED_MIN_UPLOAD_MAX_FILESIZE', '10');
 define('REQUIRED_MIN_POST_MAX_SIZE', '10');
@@ -2610,7 +2606,6 @@ function api_get_session_visibility(
     }
 
     $now = time();
-
     if (empty($session_id)) {
         return 0; // Means that the session is still available.
     }
@@ -8796,10 +8791,11 @@ function api_create_protected_dir($name, $parentDirectory)
  * @param string    email body
  * @param string    sender name
  * @param string    sender e-mail
- * @param array     extra headers in form $headers = array($name => $value) to allow parsing
- * @param array     data file (path and filename)
- * @param bool      True for attaching a embedded file inside content html (optional)
- * @param array     Additional parameters
+ * @param array  $extra_headers        in form $headers = array($name => $value) to allow parsing
+ * @param array  $data_file            (path and filename)
+ * @param bool   $embedded_image       True for attaching a embedded file inside content html (optional)
+ * @param array  $additionalParameters
+ * @param string $sendErrorTo          If there's an error while sending the email, $sendErrorTo will receive a notification
  *
  * @return int true if mail was sent
  *
@@ -8815,7 +8811,8 @@ function api_mail_html(
     $extra_headers = [],
     $data_file = [],
     $embedded_image = false,
-    $additionalParameters = []
+    $additionalParameters = [],
+    $sendErrorTo = ''
 ) {
     global $platform_email;
 
@@ -8847,6 +8844,10 @@ function api_mail_html(
         !empty($extra_headers['reply_to']) ? $extra_headers['reply_to'] : []
     );
 
+    if (!empty($sendErrorTo) && PHPMailer::ValidateAddress($sendErrorTo)) {
+        $mail->AddCustomHeader('Errors-To: '.$sendErrorTo);
+    }
+
     unset($extra_headers['reply_to']);
 
     $mail->Subject = $subject;
@@ -8857,7 +8858,6 @@ function api_mail_html(
     $list = api_get_configuration_value('send_all_emails_to');
     if (!empty($list) && isset($list['emails'])) {
         foreach ($list['emails'] as $email) {
-            //$mail->AddBCC($email);
             $mail->AddAddress($email);
         }
     }
@@ -8902,7 +8902,7 @@ function api_mail_html(
 
     $noReply = api_get_setting('noreply_email_address');
     if (!empty($noReply)) {
-        $message .= "<br />".get_lang('ThisIsAutomaticEmailNoReply');
+        $message .= '<br />'.get_lang('ThisIsAutomaticEmailNoReply');
     }
     $mailView->assign('content', $message);
 
@@ -8914,7 +8914,7 @@ function api_mail_html(
     $layout = $mailView->get_template('mail/mail.tpl');
     $mail->Body = $mailView->fetch($layout);
 
-    // Attachment ...
+    // Attachment.
     if (!empty($data_file)) {
         foreach ($data_file as $file_attach) {
             if (!empty($file_attach['path']) && !empty($file_attach['filename'])) {
@@ -9459,18 +9459,20 @@ function api_set_noreply_and_from_address_to_mailer(PHPMailer $mailer, array $se
     $senderName = !empty($sender['name']) ? $sender['name'] : $notification->getDefaultPlatformSenderName();
     $senderEmail = !empty($sender['email']) ? $sender['email'] : $notification->getDefaultPlatformSenderEmail();
 
+    // Send errors to the platform admin
+    $adminEmail = api_get_setting('emailAdministrator');
+    if (PHPMailer::ValidateAddress($adminEmail)) {
+        $mailer->AddCustomHeader('Errors-To: '.$adminEmail);
+    }
+
     // Reply to first
     if (!$avoidReplyToAddress) {
-        $mailer->AddCustomHeader('Errors-To: '.$notification->getDefaultPlatformSenderEmail());
-
         if (
             !empty($replyToAddress) &&
             isset($platformEmail['SMTP_UNIQUE_REPLY_TO']) && $platformEmail['SMTP_UNIQUE_REPLY_TO'] &&
             PHPMailer::ValidateAddress($replyToAddress['mail'])
         ) {
             $mailer->AddReplyTo($replyToAddress['email'], $replyToAddress['name']);
-            // Errors to sender
-            $mailer->AddCustomHeader('Errors-To: '.$replyToAddress['mail']);
             $mailer->Sender = $replyToAddress['mail'];
         }
     }

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

@@ -211,6 +211,7 @@ class Certificate extends Model
 
         $params['hide_print_button'] = isset($params['hide_print_button']) ? true : false;
         $categoryId = 0;
+        $my_category = [];
         if (isset($this->certificate_data) && isset($this->certificate_data['cat_id'])) {
             $categoryId = $this->certificate_data['cat_id'];
             $my_category = Category::load($categoryId);
@@ -227,7 +228,6 @@ class Certificate extends Model
             $sessionId = $category->get_session_id();
 
             $skill = new Skill();
-
             $skill->addSkillToUser(
                 $this->user_id,
                 $category,

+ 2 - 18
main/inc/lib/chat.lib.php

@@ -330,27 +330,11 @@ class Chat extends Model
             ];
         }
 
-        /*if (!empty($_SESSION['openChatBoxes'])) {
-            foreach ($_SESSION['openChatBoxes'] as $userId => $time) {
-                if (!isset($_SESSION['tsChatBoxes'][$userId])) {
-                    $now = time() - $time;
-                    $time = api_convert_and_format_date($time, DATE_TIME_FORMAT_SHORT_TIME_FIRST);
-                    $message = sprintf(get_lang('SentAtX'), $time);
-
-                    if ($now > 180) {
-                        if (isset($chatHistory[$userId])) {
-                            $chatHistory[$userId]['items'][] = $item;
-                        }
-                        $_SESSION['tsChatBoxes'][$userId] = 1;
-                    }
-                }
-            }
-        }*/
         Session::write('chatHistory', $chatHistory);
 
         $sql = "UPDATE ".$this->table."
                 SET recd = 1
-                WHERE to_user = '".$currentUserId."' AND recd = 0";
+                WHERE to_user = $currentUserId AND recd = 0";
         Database::query($sql);
 
         echo json_encode(['items' => $chatHistory]);
@@ -439,7 +423,7 @@ class Chat extends Model
     /**
      * Close a specific chat box (user ID taken from $_POST['chatbox']).
      *
-     * @param $userId
+     * @param int $userId
      */
     public function closeWindow($userId)
     {

+ 55 - 0
main/inc/lib/course.lib.php

@@ -731,6 +731,16 @@ class CourseManager
                     );
                 }
 
+                $subscribe = (int) api_get_course_setting('subscribe_users_to_forum_notifications', $courseCode);
+                if ($subscribe === 1) {
+                    require_once api_get_path(SYS_CODE_PATH).'forum/forumfunction.inc.php';
+                    $forums = get_forums(0, $courseCode, true, $sessionId);
+                    foreach ($forums as $forum) {
+                        $forumId = $forum['iid'];
+                        set_notification('forum', $forumId, false, $userInfo, $courseInfo);
+                    }
+                }
+
                 // Add event to the system log
                 Event::addEvent(
                     LOG_SUBSCRIBE_USER_TO_COURSE,
@@ -5277,6 +5287,7 @@ class CourseManager
             'student_delete_own_publication',
             'hide_forum_notifications',
             'quiz_question_limit_per_day',
+            'subscribe_users_to_forum_notifications',
         ];
 
         $courseModels = ExerciseLib::getScoreModels();
@@ -6331,6 +6342,50 @@ class CourseManager
         return api_get_path(WEB_COURSE_PATH).$course->getDirectory().'/course-pic85x85.png';
     }
 
+    /**
+     * @return int
+     */
+    public static function getCountOpenCourses()
+    {
+        $visibility = [
+            COURSE_VISIBILITY_REGISTERED,
+            COURSE_VISIBILITY_OPEN_PLATFORM,
+            COURSE_VISIBILITY_OPEN_WORLD,
+        ];
+
+        $table = Database::get_main_table(TABLE_MAIN_COURSE);
+        $sql = "SELECT count(id) count 
+                FROM $table 
+                WHERE visibility IN (".implode(',', $visibility).")";
+        $result = Database::query($sql);
+        $row = Database::fetch_array($result);
+
+        return (int) $row['count'];
+    }
+
+    /**
+     * @return int
+     */
+    public static function getCountExercisesFromOpenCourse()
+    {
+        $visibility = [
+            COURSE_VISIBILITY_REGISTERED,
+            COURSE_VISIBILITY_OPEN_PLATFORM,
+            COURSE_VISIBILITY_OPEN_WORLD,
+        ];
+
+        $table = Database::get_main_table(TABLE_MAIN_COURSE);
+        $tableExercise = Database::get_course_table(TABLE_QUIZ_TEST);
+        $sql = "SELECT count(e.iid) count 
+                FROM $table c INNER JOIN $tableExercise e
+                ON (c.id = e.c_id)
+                WHERE e.active <> -1 AND visibility IN (".implode(',', $visibility).")";
+        $result = Database::query($sql);
+        $row = Database::fetch_array($result);
+
+        return (int) $row['count'];
+    }
+
     /**
      * Check if a specific access-url-related setting is a problem or not.
      *

+ 2 - 2
main/inc/lib/document.lib.php

@@ -1835,7 +1835,7 @@ class DocumentManager
     public static function get_default_certificate_id($course_id, $session_id = 0)
     {
         $tbl_category = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
-        $session_id = intval($session_id);
+        $session_id = (int) $session_id;
         if (empty($session_id)) {
             $session_id = api_get_session_id();
         }
@@ -1843,7 +1843,7 @@ class DocumentManager
         if (empty($session_id)) {
             $sql_session = 'AND (session_id = 0 OR isnull(session_id)) ';
         } elseif ($session_id > 0) {
-            $sql_session = 'AND session_id='.intval($session_id);
+            $sql_session = 'AND session_id='.$session_id;
         } else {
             $sql_session = '';
         }

+ 73 - 15
main/inc/lib/events.lib.php

@@ -97,9 +97,35 @@ class Event
         return true;
     }
 
+    /**
+     * @param int $sessionId
+     *
+     * @return bool
+     */
+    public static function isSessionLogNeedToBeSave($sessionId)
+    {
+        if (!empty($sessionId)) {
+            $visibility = api_get_session_visibility($sessionId);
+            if (!empty($visibility) && $visibility != SESSION_AVAILABLE) {
+                $extraFieldValue = new ExtraFieldValue('session');
+                $value = $extraFieldValue->get_values_by_handler_and_field_variable(
+                    $sessionId,
+                    'disable_log_after_session_ends'
+                );
+                if (!empty($value) && isset($value['value']) && (int) $value['value'] == 1) {
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
     /**
      * @author Sebastien Piraux <piraux_seb@hotmail.com>
      * @desc Record information for access event for courses
+     *
+     * @return bool
      */
     public static function accessCourse()
     {
@@ -108,22 +134,26 @@ class Event
         }
 
         $TABLETRACK_ACCESS = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS);
-        //for "what's new" notification
+        // For "what's new" notification
         $TABLETRACK_LASTACCESS = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
 
-        $id_session = api_get_session_id();
+        $sessionId = api_get_session_id();
         $now = api_get_utc_datetime();
         $courseId = api_get_course_int_id();
         $userId = api_get_user_id();
         $ip = Database::escape_string(api_get_real_ip());
 
+        if (self::isSessionLogNeedToBeSave($sessionId) === false) {
+            return false;
+        }
+
         if ($userId) {
             $userId = $userId;
         } else {
-            $userId = "0"; // no one
+            $userId = '0'; // no one
         }
         $sql = "INSERT INTO $TABLETRACK_ACCESS  (user_ip, access_user_id, c_id, access_date, access_session_id) 
-                VALUES ('$ip', $userId, $courseId, '$now', $id_session)";
+                VALUES ('$ip', $userId, $courseId, '$now', $sessionId)";
 
         Database::query($sql);
 
@@ -133,16 +163,16 @@ class Event
                   access_user_id = $userId AND
                   c_id = $courseId AND 
                   access_tool IS NULL AND 
-                  access_session_id = $id_session";
+                  access_session_id = $sessionId";
         $result = Database::query($sql);
 
         if (Database::affected_rows($result) == 0) {
             $sql = "INSERT INTO $TABLETRACK_LASTACCESS (access_user_id, c_id, access_date, access_session_id)
-                    VALUES ($userId, $courseId, '$now', $id_session)";
+                    VALUES ($userId, $courseId, '$now', $sessionId)";
             Database::query($sql);
         }
 
-        return 1;
+        return true;
     }
 
     /**
@@ -182,6 +212,11 @@ class Event
         if (empty($courseInfo)) {
             return false;
         }
+
+        if (self::isSessionLogNeedToBeSave($sessionId) === false) {
+            return false;
+        }
+
         $courseId = $courseInfo['real_id'];
 
         $tableAccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS);
@@ -1989,6 +2024,12 @@ class Event
         if (Session::read('login_as')) {
             return false;
         }
+
+        $sessionId = (int) $sessionId;
+        if (self::isSessionLogNeedToBeSave($sessionId) === false) {
+            return false;
+        }
+
         $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
         $loginDate = $logoutDate = api_get_utc_datetime();
 
@@ -1996,7 +2037,6 @@ class Event
         $counter = 1;
         $courseId = (int) $courseId;
         $user_id = (int) $user_id;
-        $sessionId = (int) $sessionId;
         $ip = Database::escape_string(api_get_real_ip());
 
         $sql = "INSERT INTO $table(c_id, user_ip, user_id, login_course_date, logout_course_date, counter, session_id)
@@ -2043,9 +2083,14 @@ class Event
             return false;
         }
 
+        $sessionId = (int) $sessionId;
+
+        if (self::isSessionLogNeedToBeSave($sessionId) === false) {
+            return false;
+        }
+
         $courseId = (int) $courseId;
         $userId = (int) $userId;
-        $sessionId = (int) $sessionId;
 
         $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
         $sql = "SELECT course_access_id, logout_course_date 
@@ -2115,13 +2160,19 @@ class Event
             $sessionLifetime = 3600; // 1 hour
         }
         if (!empty($logoutInfo) && !empty($logoutInfo['cid'])) {
-            $tableCourseAccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
-            $userId = (int) $logoutInfo['uid'];
-            $courseId = (int) $logoutInfo['cid'];
             $sessionId = 0;
             if (!empty($logoutInfo['sid'])) {
                 $sessionId = (int) $logoutInfo['sid'];
             }
+
+            if (self::isSessionLogNeedToBeSave($sessionId) === false) {
+                return false;
+            }
+
+            $tableCourseAccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
+            $userId = (int) $logoutInfo['uid'];
+            $courseId = (int) $logoutInfo['cid'];
+
             $currentDate = api_get_utc_datetime();
             // UTC time
             $diff = time() - $sessionLifetime;
@@ -2356,7 +2407,14 @@ class Event
      */
     public static function registerLog($logInfo)
     {
-        if (!Tracking::minimumTimeAvailable(api_get_session_id(), api_get_course_int_id())) {
+        $sessionId = api_get_session_id();
+        $courseId = api_get_course_int_id();
+
+        if (!Tracking::minimumTimeAvailable($sessionId, $courseId)) {
+            return false;
+        }
+
+        if (self::isSessionLogNeedToBeSave($sessionId) === false) {
             return false;
         }
 
@@ -2371,8 +2429,8 @@ class Event
         $logInfo['action_details'] = !empty($logInfo['action_details']) ? $logInfo['action_details'] : '';
         $logInfo['ip_user'] = api_get_real_ip();
         $logInfo['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
-        $logInfo['session_id'] = api_get_session_id();
-        $logInfo['c_id'] = api_get_course_int_id();
+        $logInfo['session_id'] = $sessionId;
+        $logInfo['c_id'] = $courseId;
         $logInfo['ch_sid'] = session_id();
         $logInfo['login_as'] = $loginAs;
         $logInfo['info'] = !empty($logInfo['info']) ? $logInfo['info'] : '';

+ 20 - 41
main/inc/lib/exercise.lib.php

@@ -2827,6 +2827,7 @@ HOTSPOT;
             $score = $result['score'];
             $weight = $result['weight'];
         }
+
         $percentage = (100 * $score) / ($weight != 0 ? $weight : 1);
         // Formats values
         $percentage = float_format($percentage, 1);
@@ -2884,6 +2885,13 @@ HOTSPOT;
             $html = $scoreBasedInModel;
         }
 
+        // Ignore other formats and use the configuratio['exercise_score_format'] value
+        // But also keep the round values settings.
+        $format = api_get_configuration_value('exercise_score_format');
+        if (!empty($format)) {
+            $html = ScoreDisplay::instance()->display_score([$score, $weight], $format);
+        }
+
         $html = Display::span($html, ['class' => 'score_exercise']);
 
         return $html;
@@ -3183,17 +3191,16 @@ EOT;
         }
 
         $now = api_get_utc_datetime();
-        $time_conditions = '';
-
+        $timeConditions = '';
         if ($check_publication_dates) {
-            //start and end are set
-            $time_conditions = " AND ((start_time <> '' AND start_time < '$now' AND end_time <> '' AND end_time > '$now' )  OR ";
+            // Start and end are set
+            $timeConditions = " AND ((start_time <> '' AND start_time < '$now' AND end_time <> '' AND end_time > '$now' )  OR ";
             // only start is set
-            $time_conditions .= " (start_time <> '' AND start_time < '$now' AND end_time is NULL) OR ";
+            $timeConditions .= " (start_time <> '' AND start_time < '$now' AND end_time is NULL) OR ";
             // only end is set
-            $time_conditions .= " (start_time IS NULL AND end_time <> '' AND end_time > '$now') OR ";
+            $timeConditions .= " (start_time IS NULL AND end_time <> '' AND end_time > '$now') OR ";
             // nothing is set
-            $time_conditions .= ' (start_time IS NULL AND end_time IS NULL)) ';
+            $timeConditions .= ' (start_time IS NULL AND end_time IS NULL)) ';
         }
 
         $needle_where = !empty($search) ? " AND title LIKE '?' " : '';
@@ -3212,7 +3219,7 @@ EOT;
         if ($search_all_sessions == true) {
             $conditions = [
                 'where' => [
-                    $active_sql.' c_id = ? '.$needle_where.$time_conditions => [
+                    $active_sql.' c_id = ? '.$needle_where.$timeConditions => [
                         $course_id,
                         $needle,
                     ],
@@ -3223,7 +3230,7 @@ EOT;
             if (empty($session_id)) {
                 $conditions = [
                     'where' => [
-                        $active_sql.' (session_id = 0 OR session_id IS NULL) AND c_id = ? '.$needle_where.$time_conditions => [
+                        $active_sql.' (session_id = 0 OR session_id IS NULL) AND c_id = ? '.$needle_where.$timeConditions => [
                             $course_id,
                             $needle,
                         ],
@@ -3233,7 +3240,7 @@ EOT;
             } else {
                 $conditions = [
                     'where' => [
-                        $active_sql.' (session_id = 0 OR session_id IS NULL OR session_id = ? ) AND c_id = ? '.$needle_where.$time_conditions => [
+                        $active_sql.' (session_id = 0 OR session_id IS NULL OR session_id = ? ) AND c_id = ? '.$needle_where.$timeConditions => [
                             $session_id,
                             $course_id,
                             $needle,
@@ -3249,32 +3256,6 @@ EOT;
         return Database::select('*', $table, $conditions);
     }
 
-    /**
-     * Get exercise information by id.
-     *
-     * @param int $exerciseId Exercise Id
-     * @param int $courseId   The course ID (necessary as c_quiz.id is not unique)
-     *
-     * @return array Exercise info
-     */
-    public static function get_exercise_by_id($exerciseId = 0, $courseId = 0)
-    {
-        $table = Database::get_course_table(TABLE_QUIZ_TEST);
-        if (empty($courseId)) {
-            $courseId = api_get_course_int_id();
-        } else {
-            $courseId = intval($courseId);
-        }
-        $conditions = [
-            'where' => [
-                'id = ?' => [$exerciseId],
-                ' AND c_id = ? ' => $courseId,
-            ],
-        ];
-
-        return Database::select('*', $table, $conditions);
-    }
-
     /**
      * Getting all exercises (active only or all)
      * from a course from a session
@@ -3789,10 +3770,10 @@ EOT;
         $track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
 
-        $question_id = intval($question_id);
-        $exercise_id = intval($exercise_id);
+        $question_id = (int) $question_id;
+        $exercise_id = (int) $exercise_id;
         $course_code = Database::escape_string($course_code);
-        $session_id = intval($session_id);
+        $session_id = (int) $session_id;
         $courseId = api_get_course_int_id($course_code);
 
         $sql = "SELECT MAX(marks) as max, MIN(marks) as min, AVG(marks) as average
@@ -3980,7 +3961,6 @@ EOT;
         $track_hotspot = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTSPOT);
         $courseUser = Database::get_main_table(TABLE_MAIN_COURSE_USER);
         $courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
-
         $courseUserSession = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
 
         $question_id = (int) $question_id;
@@ -5060,7 +5040,6 @@ EOT;
             $ribbon .= '<h3>'.get_lang('YourTotalScore').':&nbsp;';
             $ribbon .= self::show_score($score, $weight, false, true);
             $ribbon .= '</h3>';
-
             $ribbon .= '</div>';
         }
 

+ 17 - 21
main/inc/lib/exercise_show_functions.lib.php

@@ -339,23 +339,12 @@ class ExerciseShowFunctions
 
         $studentChoiceInt = (int) $studentChoice;
         $answerCorrectChoice = (int) $answerCorrect;
-        $hideStudentChoice = false;
-        $hide_expected_answer = false;
-
-        $status = '';
-        if ($exercise->showExpectedChoice()) {
-            $status = Display::label(get_lang('Incorrect'), 'danger');
-            if ($answerCorrect || ($answerCorrect && $studentChoiceInt === $answerCorrectChoice)) {
-                $status = Display::label(get_lang('Correct'), 'success');
-            }
-        }
 
+        $hide_expected_answer = false;
         $showComment = false;
         switch ($resultsDisabled) {
             case RESULT_DISABLE_SHOW_ONLY_IN_CORRECT_ANSWER:
-                $hideStudentChoice = false;
                 $hide_expected_answer = true;
-                $status = Display::label(get_lang('Correct'), 'success');
                 $showComment = true;
                 if (!$answerCorrect && empty($studentChoice)) {
                     return '';
@@ -397,17 +386,20 @@ class ExerciseShowFunctions
         }
 
         echo '<tr class="'.$studentChoiceClass.'">';
-        if ($hideStudentChoice === false) {
-            echo '<td width="5%">';
-            echo Display::return_icon($icon, null, null, ICON_SIZE_TINY);
-            echo '</td>';
-        }
 
-        if (!$hide_expected_answer) {
-            if ($exercise->showExpectedChoiceColumn()) {
+        echo '<td width="5%">';
+        echo Display::return_icon($icon, null, null, ICON_SIZE_TINY);
+        echo '</td>';
+
+        if ($exercise->showExpectedChoiceColumn()) {
+            if ($hide_expected_answer === false) {
                 echo '<td width="5%">';
                 echo Display::return_icon($iconAnswer, null, null, ICON_SIZE_TINY);
                 echo '</td>';
+            } else {
+                echo '<td width="5%">';
+                echo '-';
+                echo '</td>';
             }
         }
 
@@ -416,6 +408,10 @@ class ExerciseShowFunctions
         echo '</td>';
 
         if ($exercise->showExpectedChoice()) {
+            $status = Display::label(get_lang('Incorrect'), 'danger');
+            if ($answerCorrect || ($answerCorrect && $studentChoiceInt === $answerCorrectChoice)) {
+                $status = Display::label(get_lang('Correct'), 'success');
+            }
             echo '<td width="20%">';
             echo $status;
             echo '</td>';
@@ -510,8 +506,8 @@ class ExerciseShowFunctions
         }
 
         // Expected choice
-        if (!$hide_expected_answer) {
-            if ($exercise->showExpectedChoiceColumn()) {
+        if ($exercise->showExpectedChoiceColumn()) {
+            if (!$hide_expected_answer) {
                 $content .= '<td width="5%">';
                 if (isset($new_options[$answerCorrect])) {
                     $content .= get_lang($new_options[$answerCorrect]['name']);

+ 6 - 2
main/inc/lib/extra_field.lib.php

@@ -2447,7 +2447,11 @@ JAVASCRIPT;
 
                 return " $col {$this->ops[$oper]} $val ";
             } else {
-                $val = '%'.$val.'%';
+                if (is_string($val)) {
+                    $val = '%'.$val.'%';
+                } else {
+                    $val = '';
+                }
             }
         }
         $val = \Database::escape_string($val);
@@ -2516,7 +2520,7 @@ JAVASCRIPT;
                         }
                     } else {
                         if (isset($rule->data)) {
-                            if ($rule->data == -1) {
+                            if (isset($rule->data) && is_int($rule->data) && $rule->data == -1) {
                                 continue;
                             }
                             $condition_array[] = ' ('

+ 2 - 2
main/inc/lib/formvalidator/Element/UserAvatar.php

@@ -73,10 +73,10 @@ class UserAvatar extends HTML_QuickForm_input
         $html .= '
             <div class="media">
                 <div class="media-left">
-                    <img src="'.$userPicture.'" alt="'.$this->user->getCompleteName().'">
+                    <img src="'.$userPicture.'" alt="'.UserManager::formatUserFullName($this->user).'">
                 </div>
                 <div class="media-body">
-                    <h4 class="media-heading">'.$this->user->getCompleteName().'</h4>
+                    <h4 class="media-heading">'.UserManager::formatUserFullName($this->user).'</h4>
                     '.$this->subTitle.'
                 </div>
             </div>

+ 36 - 29
main/inc/lib/message.lib.php

@@ -63,7 +63,7 @@ class MessageManager
         $messageStatusCondition = implode("','", $messageStatus);
 
         $table = Database::get_main_table(TABLE_MESSAGE);
-        $keyword = isset($params['keyword']) ? $params['keyword'] : '';
+        $keyword = isset($params['keyword']) && !empty($params['keyword']) ? $params['keyword'] : '';
 
         $keywordCondition = '';
         if (!empty($keyword)) {
@@ -125,8 +125,11 @@ class MessageManager
             $column = 2;
         }
 
-        $keyword = isset($extraParams['keyword']) ? $extraParams['keyword'] : '';
-        $viewUrl = isset($extraParams['view_url']) ? $extraParams['view_url'] : api_get_path(WEB_CODE_PATH).'message/view_message.php';
+        $keyword = isset($extraParams['keyword']) && !empty($extraParams['keyword']) ? $extraParams['keyword'] : '';
+        $viewUrl = api_get_path(WEB_CODE_PATH).'messages/view_message.php';
+        if (isset($extraParams['view_url']) && !empty($extraParams['view_url'])) {
+            $viewUrl = $extraParams['view_url'];
+        }
 
         $keywordCondition = '';
         if (!empty($keyword)) {
@@ -1190,7 +1193,7 @@ class MessageManager
         }
         $table = Database::get_main_table(TABLE_MESSAGE);
         $request = api_is_xml_http_request();
-        $keyword = isset($extraParams['keyword']) ? $extraParams['keyword'] : '';
+        $keyword = isset($extraParams['keyword']) && !empty($extraParams['keyword']) ? $extraParams['keyword'] : '';
         $keywordCondition = '';
         if (!empty($keyword)) {
             $keyword = Database::escape_string($keyword);
@@ -1270,38 +1273,43 @@ class MessageManager
      *
      * @return string html with the message content
      */
-    public static function showMessageBox($messageId, $source = 'inbox')
+    public static function showMessageBox($messageId, $source)
     {
         $table = Database::get_main_table(TABLE_MESSAGE);
         $messageId = (int) $messageId;
+
+        if (empty($messageId)) {
+            return '';
+        }
         $currentUserId = api_get_user_id();
 
-        if ($source === 'outbox') {
-            if (isset($messageId) && is_numeric($messageId)) {
-                $query = "SELECT * FROM $table
-                          WHERE
-                            user_sender_id = ".$currentUserId." AND
-                            id = $messageId AND
-                            msg_status = ".MESSAGE_STATUS_OUTBOX;
-                $result = Database::query($query);
-            }
-        } else {
-            if (is_numeric($messageId) && !empty($messageId)) {
+        switch ($source) {
+            case 'outbox':
+                $status = MESSAGE_STATUS_OUTBOX;
+                $userCondition = " user_sender_id = $currentUserId AND ";
+
+                break;
+            case 'inbox':
+                $status = MESSAGE_STATUS_NEW;
+                $userCondition = " user_receiver_id = $currentUserId AND ";
+
                 $query = "UPDATE $table SET
                           msg_status = '".MESSAGE_STATUS_NEW."'
-                          WHERE
-                            user_receiver_id=".$currentUserId." AND
-                            id = '".$messageId."'";
+                          WHERE id = $messageId ";
                 Database::query($query);
-
-                $query = "SELECT * FROM $table
-                          WHERE
-                            msg_status<> ".MESSAGE_STATUS_OUTBOX." AND
-                            user_receiver_id = ".$currentUserId." AND
-                            id = '".$messageId."'";
-                $result = Database::query($query);
-            }
-        }
+                break;
+            case 'promoted_messages':
+                $status = MESSAGE_STATUS_PROMOTED;
+                $userCondition = " user_receiver_id = $currentUserId AND ";
+                break;
+        }
+
+        $query = "SELECT * FROM $table
+                          WHERE                            
+                            id = $messageId AND 
+                            $userCondition
+                            msg_status = $status";
+        $result = Database::query($query);
         $row = Database::fetch_array($result, 'ASSOC');
 
         if (empty($row)) {
@@ -2503,7 +2511,6 @@ class MessageManager
         $i = 1;
         while (!feof($file)) {
             $line = fgets($file);
-            // $line = trim($line);
 
             if (trim($line) == '') {
                 continue;

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

@@ -979,7 +979,7 @@ class SessionManager
         $date_to,
         $options
     ) {
-        $sessionId = intval($sessionId);
+        $sessionId = (int) $sessionId;
 
         $getAllSessions = false;
         if (empty($sessionId)) {

+ 7 - 3
main/inc/lib/social.lib.php

@@ -2518,7 +2518,7 @@ class SocialManager extends UserManager
         foreach ($messages as $message) {
             $post = $message['html'];
             $comments = '';
-            if ($message['msg_status'] == MESSAGE_STATUS_WALL_POST) {
+            if (in_array($message['msg_status'], [MESSAGE_STATUS_WALL_POST, MESSAGE_STATUS_PROMOTED])) {
                 $comments = self::getWallPostComments($userId, $message);
             }
 
@@ -2548,7 +2548,10 @@ class SocialManager extends UserManager
     }
 
     /**
-     * @param int $userId
+     * @param int   $userId
+     * @param array $groupList
+     * @param array $friendList
+     * @param array $threadList
      *
      * @return int
      */
@@ -2619,7 +2622,8 @@ class SocialManager extends UserManager
     }
 
     /**
-     * @param int $user_id
+     * @param int  $user_id
+     * @param bool $isArray
      *
      * @return string|array
      */

+ 26 - 78
main/inc/lib/tracking.lib.php

@@ -4206,9 +4206,9 @@ class Tracking
             $count = $row[0];
 
             return $count;
-        } else {
-            return null;
         }
+
+        return 0;
     }
 
     /**
@@ -4238,7 +4238,7 @@ class Tracking
 
         $condition_session = '';
         if (isset($session_id)) {
-            $session_id = intval($session_id);
+            $session_id = (int) $session_id;
             $condition_session = ' AND f.session_id = '.$session_id;
         }
 
@@ -4274,9 +4274,9 @@ class Tracking
             $count = $row[0];
 
             return $count;
-        } else {
-            return null;
         }
+
+        return 0;
     }
 
     /**
@@ -4303,11 +4303,11 @@ class Tracking
 
         $condition_session = '';
         if (isset($session_id)) {
-            $session_id = intval($session_id);
+            $session_id = (int) $session_id;
             $condition_session = ' AND f.session_id = '.$session_id;
         }
 
-        $groupId = intval($groupId);
+        $groupId = (int) $groupId;
         if (!empty($groupId)) {
             $groupCondition = " i.to_group_id = $groupId ";
         } else {
@@ -4332,9 +4332,9 @@ class Tracking
             $count = $row[0];
 
             return $count;
-        } else {
-            return null;
         }
+
+        return 0;
     }
 
     /**
@@ -4358,8 +4358,9 @@ class Tracking
         $course_id = $course_info['real_id'];
 
         // Protect data
-        $last_days = intval($last_days);
-        $session_id = intval($session_id);
+        $last_days = (int) $last_days;
+        $session_id = (int) $session_id;
+
         $tbl_stats_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS);
         $now = api_get_utc_datetime();
 
@@ -4368,16 +4369,16 @@ class Tracking
                     DATE_SUB('$now',INTERVAL $last_days DAY) <= access_date AND
                     c_id = '$course_id' AND
                     access_tool='".TOOL_CHAT."' AND
-                    access_session_id='$session_id' ";
+                    access_session_id = '$session_id' ";
         $result = Database::query($sql);
         if (Database::num_rows($result)) {
             $row = Database::fetch_row($result);
             $count = $row[0];
 
             return $count;
-        } else {
-            return null;
         }
+
+        return 0;
     }
 
     /**
@@ -4394,9 +4395,9 @@ class Tracking
         $courseId,
         $session_id = 0
     ) {
-        $student_id = intval($student_id);
-        $courseId = intval($courseId);
-        $session_id = intval($session_id);
+        $student_id = (int) $student_id;
+        $courseId = (int) $courseId;
+        $session_id = (int) $session_id;
         $date_time = '';
 
         // table definition
@@ -4433,9 +4434,9 @@ class Tracking
      */
     public static function count_student_visited_links($student_id, $courseId, $session_id = 0)
     {
-        $student_id = intval($student_id);
-        $courseId = intval($courseId);
-        $session_id = intval($session_id);
+        $student_id = (int) $student_id;
+        $courseId = (int) $courseId;
+        $session_id = (int) $session_id;
 
         // table definition
         $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LINKS);
@@ -4463,9 +4464,9 @@ class Tracking
      */
     public static function count_student_downloaded_documents($student_id, $courseId, $session_id = 0)
     {
-        $student_id = intval($student_id);
-        $courseId = intval($courseId);
-        $session_id = intval($session_id);
+        $student_id = (int) $student_id;
+        $courseId = (int) $courseId;
+        $session_id = (int) $session_id;
 
         // table definition
         $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_DOWNLOADS);
@@ -4595,59 +4596,6 @@ class Tracking
         return $users;
     }
 
-    /**
-     * Get count login per student.
-     *
-     * @param int $student_id Student id
-     * @param int $courseId
-     * @param int $session_id Session id (optional)
-     *
-     * @return int count login
-     */
-    public static function count_login_per_student($student_id, $courseId, $session_id = 0)
-    {
-        $student_id = intval($student_id);
-        $courseId = intval($courseId);
-        $session_id = intval($session_id);
-        $table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS);
-
-        $sql = 'SELECT '.$student_id.'
-                FROM '.$table.'
-                WHERE
-                    access_user_id='.$student_id.' AND
-                    c_id="'.$courseId.'" AND
-                    access_session_id = "'.$session_id.'" ';
-
-        $rs = Database::query($sql);
-        $nb_login = Database::num_rows($rs);
-
-        return $nb_login;
-    }
-
-    /**
-     * Get students followed by a human resources manager.
-     *
-     * @param    int        Drh id
-     *
-     * @return array Student list
-     */
-    public static function get_student_followed_by_drh($hr_dept_id)
-    {
-        $hr_dept_id = intval($hr_dept_id);
-        $a_students = [];
-        $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
-
-        $sql = 'SELECT DISTINCT user_id FROM '.$tbl_user.' as user
-                WHERE hr_dept_id='.$hr_dept_id;
-        $rs = Database::query($sql);
-
-        while ($user = Database::fetch_array($rs)) {
-            $a_students[$user['user_id']] = $user['user_id'];
-        }
-
-        return $a_students;
-    }
-
     /**
      * get count clicks about tools most used by course.
      *
@@ -4660,12 +4608,12 @@ class Tracking
      */
     public static function get_tools_most_used_by_course($courseId, $session_id = null)
     {
-        $courseId = intval($courseId);
+        $courseId = (int) $courseId;
         $data = [];
         $TABLETRACK_ACCESS = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
         $condition_session = '';
         if (isset($session_id)) {
-            $session_id = intval($session_id);
+            $session_id = (int) $session_id;
             $condition_session = ' AND access_session_id = '.$session_id;
         }
         $sql = "SELECT

+ 21 - 6
main/inc/lib/usermanager.lib.php

@@ -219,6 +219,9 @@ class UserManager
         $redirectToURLAfterLogin = ''
     ) {
         $creatorId = empty($creatorId) ? api_get_user_id() : 0;
+        $creatorInfo = api_get_user_info($creatorId);
+        $creatorEmail = isset($creatorInfo['email']) ? $creatorInfo['email'] : '';
+
         $hook = HookCreateUser::create();
         if (!empty($hook)) {
             $hook->notifyCreateUser(HOOK_EVENT_TYPE_PRE);
@@ -421,7 +424,7 @@ class UserManager
                 'false'
             );
 
-            if (api_get_configuration_value('plugin_redirection_enabled') && !empty($redirectToURLAfterLogin)) {
+            if (!empty($redirectToURLAfterLogin) && api_get_configuration_value('plugin_redirection_enabled')) {
                 RedirectionPlugin::insert($userId, $redirectToURLAfterLogin);
             }
 
@@ -491,7 +494,6 @@ class UserManager
                     EventsDispatcher::events('user_registration', $values);
                 } else {
                     $phoneNumber = isset($extra['mobile_phone_number']) ? $extra['mobile_phone_number'] : null;
-
                     $additionalParameters = [
                         'smsType' => SmsPlugin::WELCOME_LOGIN_PASSWORD,
                         'userId' => $return,
@@ -536,7 +538,8 @@ class UserManager
                             null,
                             null,
                             null,
-                            $additionalParameters
+                            $additionalParameters,
+                            $creatorEmail
                         );
 
                         $layoutContent = $tplContent->get_template('mail/new_user_second_email_confirmation.tpl');
@@ -562,7 +565,8 @@ class UserManager
                             null,
                             null,
                             null,
-                            $additionalParameters
+                            $additionalParameters,
+                            $creatorEmail
                         );
                     } else {
                         if (!empty($emailBodyTemplate)) {
@@ -594,7 +598,8 @@ class UserManager
                                 null,
                                 null,
                                 null,
-                                $additionalParameters
+                                $additionalParameters,
+                                $creatorEmail
                             );
                         }
                     }
@@ -1160,6 +1165,7 @@ class UserManager
         }
         $original_password = $password;
         $user_id = (int) $user_id;
+        $creator_id = (int) $creator_id;
 
         if (empty($user_id)) {
             return false;
@@ -1311,13 +1317,22 @@ class UserManager
                 $userInfo = api_get_user_info($user_id);
                 $emailBody = $mailTemplateManager->parseTemplate($emailTemplate['user_edit_content.tpl'], $userInfo);
             }
+
+            $creatorInfo = api_get_user_info($creator_id);
+            $creatorEmail = isset($creatorInfo['email']) ? $creatorInfo['email'] : '';
+
             api_mail_html(
                 $recipient_name,
                 $email,
                 $emailsubject,
                 $emailBody,
                 $sender_name,
-                $email_admin
+                $email_admin,
+                null,
+                null,
+                null,
+                null,
+                $creatorEmail
             );
         }
 

+ 15 - 12
main/inc/lib/userportal.lib.php

@@ -1004,6 +1004,9 @@ class IndexManager
      */
     public function return_course_block()
     {
+        if (api_get_configuration_value('hide_course_sidebar')) {
+            return '';
+        }
         $isHrm = api_is_drh();
         $show_create_link = false;
         $show_course_link = false;
@@ -1118,7 +1121,7 @@ class IndexManager
         $loadHistory = false
     ) {
         $gameModeIsActive = api_get_setting('gamification_mode');
-        $viewGridCourses = api_get_configuration_value('view_grid_courses') === true;
+        $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';
@@ -1138,7 +1141,6 @@ class IndexManager
         // Student info code check (shows student progress information on
         // courses list
         $studentInfo = api_get_configuration_value('course_student_info');
-        $viewGrid = api_get_configuration_value('view_grid_courses');
 
         $studentInfoProgress = !empty($studentInfo['progress']) && $studentInfo['progress'] === true;
         $studentInfoScore = !empty($studentInfo['score']) && $studentInfo['score'] === true;
@@ -1150,7 +1152,7 @@ class IndexManager
         $specialCourseList = '';
 
         // If we're not in the history view...
-        if ($loadHistory == false) {
+        if ($loadHistory === false) {
             // Display special courses.
             $specialCourses = CourseManager::returnSpecialCourses(
                 $user_id,
@@ -1218,10 +1220,11 @@ class IndexManager
                     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,
-                                        $courseInCatInfo['course_code']
+                                        $courseCode
                                     );
                                     $courses['in_category'][$key1]['courses'][$key2]['student_info']['progress'] = $progress === false ? null : $progress;
                                 }
@@ -1229,7 +1232,7 @@ class IndexManager
                                 if ($studentInfoScore) {
                                     $percentage_score = Tracking::get_avg_student_score(
                                         $user_id,
-                                        $specialCourseInfo['course_code'],
+                                        $courseCode,
                                         []
                                     );
                                     $courses['in_category'][$key1]['courses'][$key2]['student_info']['score'] = $percentage_score;
@@ -1239,7 +1242,7 @@ class IndexManager
                                     $category = Category::load(
                                         null,
                                         null,
-                                        $courseInCatInfo['course_code'],
+                                        $courseCode,
                                         null,
                                         null,
                                         null
@@ -1247,7 +1250,7 @@ class IndexManager
                                     $courses['in_category'][$key1]['student_info']['certificate'] = null;
                                     $isCertificateAvailable = $category[0]->is_certificate_available($user_id);
                                     if (isset($category[0])) {
-                                        if ($viewGrid) {
+                                        if ($viewGridCourses) {
                                             if ($isCertificateAvailable) {
                                                 $courses['in_category'][$key1]['student_info']['certificate'] = get_lang(
                                                     'Yes'
@@ -1279,10 +1282,11 @@ class IndexManager
 
                 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,
-                                $courseNotInCatInfo['course_code']
+                                $courseCode
                             );
                             $courses['not_category'][$key]['student_info']['progress'] = $progress === false ? null : $progress;
                         }
@@ -1290,7 +1294,7 @@ class IndexManager
                         if ($studentInfoScore) {
                             $percentage_score = Tracking::get_avg_student_score(
                                 $user_id,
-                                $courseNotInCatInfo['course_code'],
+                                $courseCode,
                                 []
                             );
                             $courses['not_category'][$key]['student_info']['score'] = $percentage_score;
@@ -1300,7 +1304,7 @@ class IndexManager
                             $category = Category::load(
                                 null,
                                 null,
-                                $courseNotInCatInfo['course_code'],
+                                $courseCode,
                                 null,
                                 null,
                                 null
@@ -1309,7 +1313,7 @@ class IndexManager
 
                             if (isset($category[0])) {
                                 $certificateAvailable = $category[0]->is_certificate_available($user_id);
-                                if ($viewGrid) {
+                                if ($viewGridCourses) {
                                     if ($certificateAvailable) {
                                         $courses['not_category'][$key]['student_info']['certificate'] = get_lang('Yes');
                                     } else {
@@ -1382,7 +1386,6 @@ class IndexManager
 
         $sessions_with_category = '';
         $sessions_with_no_category = '';
-
         $collapsable = api_get_configuration_value('allow_user_session_collapsable');
         $collapsableLink = '';
         if ($collapsable) {

+ 9 - 0
main/install/configuration.dist.php

@@ -847,6 +847,7 @@ ALTER TABLE skill_rel_course ADD CONSTRAINT FK_E7CEC7FA613FECDF FOREIGN KEY (ses
     'display' => [
         'show_reporting_icon' => true,
         'hide_lp_arrow_navigation' => false,
+        'show_toolbar_by_default' => false,
     ],
 ];*/
 
@@ -1280,6 +1281,14 @@ requires extension "php-soap"  sudo apt-get install php-soap
 // Allow user to enter a LP item if it was validated in another session.
 // $_configuration['validate_lp_prerequisite_from_other_session'] = false;
 
+// 1 = SCORE_AVERAGE (5 / 10)
+// 2 = SCORE_PERCENT (50%)
+// 3 = SCORE_DIV_PERCENT (5 / 10 (50%))
+// $_configuration['exercise_score_format'] = 0;
+
+// Hide course sidebar
+//$_configuration['hide_course_sidebar'] = true;
+
 // KEEP THIS AT THE END
 // -------- Custom DB changes
 // Add user activation by confirmation email

+ 69 - 17
main/lp/learnpath.class.php

@@ -2004,12 +2004,14 @@ class learnpath
     /**
      * Gets the navigation bar for the learnpath display screen.
      *
+     * @param string $barId
+     *
      * @return string The HTML string to use as a navigation bar
      */
-    public function get_navigation_bar($idBar = null, $display = null)
+    public function get_navigation_bar($barId = '')
     {
-        if (empty($idBar)) {
-            $idBar = 'control-top';
+        if (empty($barId)) {
+            $barId = 'control-top';
         }
         $lpId = $this->lp_id;
         $mycurrentitemid = $this->get_current_item_id();
@@ -2032,7 +2034,7 @@ class learnpath
 
         if (!empty($display)) {
             $showReporting = isset($display['show_reporting_icon']) ? $display['show_reporting_icon'] : true;
-            if ($showReporting == false) {
+            if ($showReporting === false) {
                 $reportingIcon = '';
             }
         }
@@ -2060,7 +2062,7 @@ class learnpath
 
         if ($this->mode === 'fullscreen') {
             $navbar = '
-                  <span id="'.$idBar.'" class="buttons">
+                  <span id="'.$barId.'" class="buttons">
                     '.$reportingIcon.'
                     '.$previousIcon.'                    
                     '.$nextIcon.'
@@ -2071,11 +2073,11 @@ class learnpath
                   </span>';
         } else {
             $navbar = '
-            <span id="'.$idBar.'" class="buttons text-right">
-                '.$reportingIcon.'
-                '.$previousIcon.'
-                '.$nextIcon.'               
-            </span>';
+                 <span id="'.$barId.'" class="buttons text-right">
+                    '.$reportingIcon.'
+                    '.$previousIcon.'
+                    '.$nextIcon.'               
+                </span>';
         }
 
         return $navbar;
@@ -6213,13 +6215,41 @@ class learnpath
         $return_audio = null;
         $iconPath = api_get_path(SYS_CODE_PATH).'img/';
         $mainUrl = api_get_path(WEB_CODE_PATH).'lp/lp_controller.php?'.api_get_cidreq();
+        $countItems = count($arrLP);
 
-        for ($i = 0; $i < count($arrLP); $i++) {
+        $upIcon = Display::return_icon(
+            'up.png',
+            get_lang('Up'),
+            [],
+            ICON_SIZE_TINY
+        );
+
+        $disableUpIcon = Display::return_icon(
+            'up_na.png',
+            get_lang('Up'),
+            [],
+            ICON_SIZE_TINY
+        );
+
+        $downIcon = Display::return_icon(
+            'down.png',
+            get_lang('Down'),
+            [],
+            ICON_SIZE_TINY
+        );
+
+        $disableDownIcon = Display::return_icon(
+            'down_na.png',
+            get_lang('Down'),
+            [],
+            ICON_SIZE_TINY
+        );
+        for ($i = 0; $i < $countItems; $i++) {
+            $parent_id = $arrLP[$i]['parent_item_id'];
             $title = $arrLP[$i]['title'];
             $title_cut = cut($arrLP[$i]['title'], self::MAX_LP_ITEM_TITLE_LENGTH);
-
             // Link for the documents
-            if ($arrLP[$i]['item_type'] == 'document' || $arrLP[$i]['item_type'] == TOOL_READOUT_TEXT) {
+            if ($arrLP[$i]['item_type'] === 'document' || $arrLP[$i]['item_type'] == TOOL_READOUT_TEXT) {
                 $url = $mainUrl.'&action=view_item&mode=preview_document&id='.$arrLP[$i]['id'].'&lp_id='.$this->lp_id;
                 $title_cut = Display::url(
                     $title_cut,
@@ -6237,10 +6267,9 @@ class learnpath
                 Session::write('pathItem', $arrLP[$i]['path']);
             }
 
+            $oddClass = 'row_even';
             if (($i % 2) == 0) {
                 $oddClass = 'row_odd';
-            } else {
-                $oddClass = 'row_even';
             }
             $return_audio .= '<tr id ="lp_item_'.$arrLP[$i]['id'].'" class="'.$oddClass.'">';
             $icon_name = str_replace(' ', '', $arrLP[$i]['item_type']);
@@ -6293,6 +6322,7 @@ class learnpath
             $forumIcon = '';
             $previewIcon = '';
             $pluginCalendarIcon = '';
+            $orderIcons = '';
 
             $pluginCalendar = api_get_plugin_setting('learning_calendar', 'enabled') === 'true';
             $plugin = null;
@@ -6396,7 +6426,6 @@ class learnpath
                 if ($pluginCalendar) {
                     $pluginLink = $pluginUrl.
                         '&action=toggle_visibility&lp_item_id='.$arrLP[$i]['id'].'&lp_id='.$this->lp_id;
-
                     $iconCalendar = Display::return_icon('agenda_na.png', get_lang('OneDay'), [], ICON_SIZE_TINY);
                     $itemInfo = $plugin->getItemVisibility($arrLP[$i]['id']);
                     if ($itemInfo && $itemInfo['value'] == 1) {
@@ -6409,6 +6438,29 @@ class learnpath
                     );
                 }
 
+                if (in_array($arrLP[$i]['item_type'], ['dir', 'final_item'])) {
+                    /*if ($isFirst) {
+                        $orderIcons = Display::url($disableUpIcon, '#', ['class' => 'btn btn-default']);
+                    } else {
+                    }*/
+                    $orderIcons = Display::url(
+                        $upIcon,
+                        'javascript:void(0)',
+                        ['class' => 'btn btn-default order_items', 'data-dir' => 'up', 'data-id' => $arrLP[$i]['id']]
+                    );
+
+                    /*if ($isLast) {
+                        $orderIcons .= Display::url($disableDownIcon, '#', ['class' => 'btn btn-default']);
+                    } else {
+
+                    }*/
+                    $orderIcons .= Display::url(
+                        $downIcon,
+                        'javascript:void(0)',
+                        ['class' => 'btn btn-default order_items', 'data-dir' => 'down', 'data-id' => $arrLP[$i]['id']]
+                    );
+                }
+
                 $delete_icon .= ' <a 
                     href="'.$mainUrl.'&action=delete_item&id='.$arrLP[$i]['id'].'&lp_id='.$this->lp_id.'" 
                     onclick="return confirmation(\''.addslashes($title).'\');" 
@@ -6533,6 +6585,7 @@ class learnpath
                                     $prerequisities_icon 
                                     $move_item_icon 
                                     $audio_icon 
+                                    $orderIcons
                                     $delete_icon
                                 </div>",
                         ['class' => 'btn-toolbar button_actions']
@@ -6543,7 +6596,6 @@ class learnpath
                     Display::span($audio, ['class' => 'button_actions']);
             }
 
-            $parent_id = $arrLP[$i]['parent_item_id'];
             $default_data[$arrLP[$i]['id']] = $row;
             $default_content[$arrLP[$i]['id']] = $arrLP[$i];
 

+ 30 - 117
main/lp/learnpathItem.class.php

@@ -573,6 +573,10 @@ class learnpathItem
     public function get_interactions_count($checkdb = false)
     {
         $return = 0;
+        if (api_is_invitee()) {
+            // If the user is an invitee, we consider there's no interaction
+            return 0;
+        }
         $course_id = api_get_course_int_id();
 
         if ($checkdb) {
@@ -1511,62 +1515,22 @@ class learnpathItem
                             c_id = $course_id AND
                             iid = '".$this->db_item_view_id."' AND
                             view_count = '".$this->get_attempt_id()."'";
-
-                if ($debug > 2) {
-                    error_log(
-                        'learnpathItem::get_status() - Checking DB: '.$sql,
-                        0
-                    );
-                }
-
                 $res = Database::query($sql);
                 if (Database::num_rows($res) == 1) {
                     $row = Database::fetch_array($res);
                     if ($update_local) {
-                        if ($debug > 2) {
-                            error_log(
-                                'learnpathItem::set_status() :'.$row['status'],
-                                0
-                            );
-                        }
                         $this->set_status($row['status']);
                     }
-                    if ($debug > 2) {
-                        error_log(
-                            'learnpathItem::get_status() - Returning db value '.$row['status'],
-                            0
-                        );
-                    }
 
                     return $row['status'];
                 }
             }
         } else {
-            if ($debug > 2) {
-                error_log(
-                    'learnpathItem::get_status() - in get_status: using attrib',
-                    0
-                );
-            }
             if (!empty($this->status)) {
-                if ($debug > 2) {
-                    error_log(
-                        'learnpathItem::get_status() - Returning attrib: '.$this->status,
-                        0
-                    );
-                }
-
                 return $this->status;
             }
         }
 
-        if ($debug > 2) {
-            error_log(
-                'learnpathItem::get_status() - Returning default '.$this->possible_status[0],
-                0
-            );
-        }
-
         return $this->possible_status[0];
     }
 
@@ -1602,12 +1566,12 @@ class learnpathItem
         if (!isset($time)) {
             if ($origin == 'js') {
                 return '00 : 00: 00';
-            } else {
-                return '00 '.$h.' 00 \' 00"';
             }
-        } else {
-            return api_format_time($time, $origin);
+
+            return '00 '.$h.' 00 \' 00"';
         }
+
+        return api_format_time($time, $origin);
     }
 
     /**
@@ -2370,13 +2334,6 @@ class learnpathItem
                             } else {
                                 // Nothing found there either. Now return the
                                 // value of the corresponding resource completion status.
-                                if ($debug) {
-                                    error_log(
-                                        'New LP - Didnt find any group, returning value for '.$prereqs_string,
-                                        0
-                                    );
-                                }
-
                                 if (isset($refs_list[$prereqs_string]) &&
                                     isset($items[$refs_list[$prereqs_string]])
                                 ) {
@@ -2394,26 +2351,12 @@ class learnpathItem
                                                 $itemToCheck->get_title()
                                             );
                                             $this->prereq_alert = $explanation;
-                                            if ($debug) {
-                                                error_log(
-                                                    'New LP - Prerequisite '.$prereqs_string.' not complete',
-                                                    0
-                                                );
-                                            }
-                                        } else {
-                                            if ($debug) {
-                                                error_log(
-                                                    'New LP - Prerequisite '.$prereqs_string.' complete',
-                                                    0
-                                                );
-                                            }
                                         }
 
                                         // For one and first attempt.
                                         if ($this->prevent_reinit == 1) {
                                             // 2. If is completed we check the results in the DB of the quiz.
                                             if ($returnstatus) {
-                                                //AND origin_lp_item_id = '.$user_id.'
                                                 $sql = 'SELECT exe_result, exe_weighting
                                                         FROM '.Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES).'
                                                         WHERE
@@ -2432,14 +2375,6 @@ class learnpathItem
                                                     $minScore = $myItemToCheck->getPrerequisiteMinScore();
                                                     $maxScore = $myItemToCheck->getPrerequisiteMaxScore();
 
-                                                    /*if (empty($minScore)) {
-                                                        // Try with mastery_score
-                                                        $masteryScoreAsMin = $myItemToCheck->get_mastery_score();
-                                                        if (!empty($masteryScoreAsMin)) {
-                                                            $minScore = $masteryScoreAsMin;
-                                                        }
-                                                    }*/
-
                                                     if (isset($minScore) && isset($minScore)) {
                                                         // Taking min/max prerequisites values see BT#5776
                                                         if ($quiz['exe_result'] >= $minScore &&
@@ -2535,6 +2470,18 @@ class learnpathItem
                                             }
                                         }
 
+                                        if ($returnstatus === false) {
+                                            // Check results from another sessions.
+                                            $checkOtherSessions = api_get_configuration_value('validate_lp_prerequisite_from_other_session');
+                                            if ($checkOtherSessions) {
+                                                $returnstatus = $this->getStatusFromOtherSessions(
+                                                    $user_id,
+                                                    $prereqs_string,
+                                                    $refs_list
+                                                );
+                                            }
+                                        }
+
                                         return $returnstatus;
                                     } elseif ($itemToCheck->type === 'student_publication') {
                                         require_once api_get_path(SYS_CODE_PATH).'work/work.lib.php';
@@ -2545,12 +2492,6 @@ class learnpathItem
                                         } else {
                                             $returnstatus = false;
                                             $this->prereq_alert = get_lang('LearnpathPrereqNotCompleted');
-                                            if (self::DEBUG > 1) {
-                                                error_log(
-                                                    'Student pub, prereq'.$prereqs_string.' not completed',
-                                                    0
-                                                );
-                                            }
                                         }
 
                                         return $returnstatus;
@@ -2574,19 +2515,6 @@ class learnpathItem
                                                 $itemToCheck->get_title()
                                             );
                                             $this->prereq_alert = $explanation;
-                                            if (self::DEBUG > 1) {
-                                                error_log(
-                                                    'New LP - Prerequisite '.$prereqs_string.' not complete',
-                                                    0
-                                                );
-                                            }
-                                        } else {
-                                            if (self::DEBUG > 1) {
-                                                error_log(
-                                                    'New LP - Prerequisite '.$prereqs_string.' complete',
-                                                    0
-                                                );
-                                            }
                                         }
 
                                         $lp_item_view = Database::get_course_table(TABLE_LP_ITEM_VIEW);
@@ -2619,17 +2547,6 @@ class learnpathItem
                                                 if (!$returnstatus && empty($this->prereq_alert)) {
                                                     $this->prereq_alert = get_lang('LearnpathPrereqNotCompleted');
                                                 }
-                                                if (!$returnstatus) {
-                                                    if (self::DEBUG > 1) {
-                                                        error_log(
-                                                            'New LP - Prerequisite '.$prereqs_string.' not complete'
-                                                        );
-                                                    }
-                                                } else {
-                                                    if (self::DEBUG > 1) {
-                                                        error_log('New LP - Prerequisite '.$prereqs_string.' complete');
-                                                    }
-                                                }
                                             }
 
                                             if ($checkOtherSessions && $returnstatus === false) {
@@ -2639,21 +2556,9 @@ class learnpathItem
                                                     $refs_list
                                                 );
                                             }
-
-                                            return $returnstatus;
-                                        } else {
-                                            return $returnstatus;
                                         }
-                                    }
-                                } else {
-                                    if (self::DEBUG > 1) {
-                                        error_log(
-                                            'New LP - Could not find '.$prereqs_string.' in '.print_r(
-                                                $refs_list,
-                                                true
-                                            ),
-                                            0
-                                        );
+
+                                        return $returnstatus;
                                     }
                                 }
                             }
@@ -3614,6 +3519,10 @@ class learnpathItem
         if (self::DEBUG > 0) {
             error_log('learnpathItem::write_objectives_to_db()', 0);
         }
+        if (api_is_invitee()) {
+            // If the user is an invitee, we don't write anything to DB
+            return true;
+        }
         $course_id = api_get_course_int_id();
         if (is_array($this->objectives) && count($this->objectives) > 0) {
             // Save objectives.
@@ -3706,6 +3615,10 @@ class learnpathItem
 
             return false;
         }
+        if (api_is_invitee()) {
+            // If the user is an invitee, we don't write anything to DB
+            return true;
+        }
 
         $course_id = api_get_course_int_id();
         $mode = $this->get_lesson_mode();

+ 42 - 0
main/lp/lp_controller.php

@@ -95,6 +95,48 @@ $htmlHeadXtra[] = '
                 $(ui.item).css("width", "100%");
             }
         });
+        
+        
+        $(".li_container .order_items").click(function(e) {            
+            var dir = $(this).data("dir");
+            var itemId = $(this).data("id");             
+            var jItems = $("#lp_item_list li.li_container");            
+            var jItem = $("#"+ itemId);          
+            var index = jItems.index(jItem);
+            var total = jItems.length;
+                                    
+            switch (dir) {
+                case "up":
+                    if (index != 0 && jItems[index - 1]) {
+                        var item = jItem.detach().insertBefore(jItems[index - 1]);
+                    }
+                    break;
+                case "down":
+                     if (index != jItems.length - 1) {                        
+                        var subItems = jItem.find("li.li_container");                        
+                        if (subItems.length >= 0) { 
+                            index = subItems.length + index;
+                        }                                                
+                        if ((index + 1) < total) {
+                            var item = jItem.detach().insertAfter(jItems[index + 1]);
+                        }
+                     }
+                     break;
+            }   
+            
+            buildLPtree($("#lp_item_list"), 0);
+            
+            var order = "new_order="+ newOrderData + "&a=update_lp_item_order";
+            $.post(
+                "'.$ajax_url.'",
+                order,
+                function(reponse) {
+                    $("#message").html(reponse);
+                    order = "";
+                    newOrderData = "";
+                }
+            );            
+        });
 
         $("#lp_item_list").sortable({
             items: "li",

+ 11 - 3
main/lp/lp_view.php

@@ -33,7 +33,6 @@ if (isset($_REQUEST['origin']) && $_REQUEST['origin'] === 'learnpath') {
 }
 
 // To prevent the template class
-$show_learnpath = true;
 $lp_id = !empty($_GET['lp_id']) ? (int) $_GET['lp_id'] : 0;
 $sessionId = api_get_session_id();
 $course_code = api_get_course_id();
@@ -169,7 +168,7 @@ if ($allowLpItemTip) {
 }
 
 // Impress js
-if ($lp->mode == 'impress') {
+if ($lp->mode === 'impress') {
     $lp_id = $lp->get_id();
     $url = api_get_path(WEB_CODE_PATH)."lp/lp_impress.php?lp_id=$lp_id&".api_get_cidreq();
     header("Location: $url");
@@ -419,7 +418,7 @@ if (!api_is_invitee()) {
     $progress_bar = $lp->getProgressBar();
 }
 $navigation_bar = $lp->get_navigation_bar();
-$navigation_bar_bottom = $lp->get_navigation_bar('control-bottom', 'display:none');
+$navigation_bar_bottom = $lp->get_navigation_bar('control-bottom');
 $mediaplayer = $lp->get_mediaplayer($lp->current, $autostart);
 
 $tbl_lp_item = Database::get_course_table(TABLE_LP_ITEM);
@@ -546,6 +545,15 @@ $template->assign('iframe_src', $src);
 $template->assign('navigation_bar_bottom', $navigation_bar_bottom);
 $template->assign('show_left_column', $lp->getHideTableOfContents() == 0);
 
+$showMenu = 0;
+$settings = api_get_configuration_value('lp_view_settings');
+$display = isset($settings['display']) ? $settings['display'] : false;
+if (!empty($display)) {
+    $showMenu = isset($display['show_toolbar_by_default']) && $display['show_toolbar_by_default'] ? 1 : 0;
+}
+
+$template->assign('show_toolbar_by_default', $showMenu);
+
 if ($gamificationMode == 1) {
     $template->assign('gamification_stars', $lp->getCalculateStars($sessionId));
     $template->assign('gamification_points', $lp->getCalculateScore($sessionId));

+ 178 - 44
main/mySpace/access_details_session.php

@@ -5,7 +5,6 @@ require_once __DIR__.'/../inc/global.inc.php';
 
 api_block_anonymous_users();
 
-// Access restrictions.
 $is_allowedToTrack = api_is_platform_admin(true, true) ||
     api_is_teacher() || api_is_course_tutor();
 
@@ -24,14 +23,39 @@ if (empty($userInfo)) {
     api_not_allowed(true);
 }
 
-$sessions = SessionManager::getSessionsFollowedByUser($userId,
-    null,
+/**
+ * @param string $dateTime
+ * @param bool   $showTime
+ *
+ * @return string
+ */
+function customDate($dateTime, $showTime = false)
+{
+    $format = 'd/m/Y';
+    if ($showTime) {
+        $format = 'd/m/Y H:i:s';
+    }
+    $dateTime = api_get_local_time(
+        $dateTime,
         null,
         null,
+        true,
         false,
-        false,
-        false,
-        'ORDER BY s.access_end_date'
+        true,
+        $format
+    );
+
+    return $dateTime;
+}
+
+$sessions = SessionManager::getSessionsFollowedByUser($userId,
+    null,
+    null,
+    null,
+    false,
+    false,
+    false,
+    'ORDER BY s.access_end_date'
 );
 
 $startDate = '';
@@ -50,33 +74,35 @@ $form = new FormValidator(
     null,
     ['id' => 'myform']
 );
-$form->addElement('text', 'from', get_lang('From'), ['id' => 'date_from']);
-$form->addElement('text', 'to', get_lang('Until'), ['id' => 'date_to']);
+$form->addElement('text', 'from', get_lang('From'));
+$form->addElement('text', 'to', get_lang('Until'));
 $form->addElement('hidden', 'user_id', $userId);
 $form->addRule('from', get_lang('ThisFieldIsRequired'), 'required');
+$form->addRule('from', get_lang('ThisFieldIsRequired').' dd/mm/yyyy', 'callback', 'validateDate');
 $form->addRule('to', get_lang('ThisFieldIsRequired'), 'required');
+$form->addRule('to', get_lang('ThisFieldIsRequired').' dd/mm/yyyy', 'callback', 'validateDate');
 $form->addButtonSearch(get_lang('GenerateReport'));
 
-function customDate($dateTime)
+/**
+ * @param string $value
+ *
+ * @return bool
+ */
+function validateDate($value)
 {
-    $dateTime = api_get_local_time(
-        $dateTime,
-        null,
-        null,
-        true,
-        false,
-        true,
-        'd/m/Y'
-    );
+    $value = DateTime::createFromFormat('d/m/Y', $value);
 
-    return $dateTime;
+    if ($value === false) {
+        return false;
+    }
+
+    return true;
 }
 
 if ($form->validate()) {
     $values = $form->getSubmitValues();
     $from = $values['from'];
     $to = $values['to'];
-    $sessionCategories = UserManager::get_sessions_by_category($userId, false);
 
     $from = DateTime::createFromFormat('d/m/Y', $from);
     $to = DateTime::createFromFormat('d/m/Y', $to);
@@ -84,8 +110,12 @@ if ($form->validate()) {
     $from = api_get_utc_datetime($from->format('Y-m-d'));
     $to = api_get_utc_datetime($to->format('Y-m-d'));
 
-    $sessionCourseList = [];
+    $sessionCategories = UserManager::get_sessions_by_category($userId, false);
     $report = [];
+    $minLogin = 0;
+    $maxLogin = 0;
+    $totalDuration = 0;
+
     foreach ($sessionCategories as $category) {
         foreach ($category['sessions'] as $session) {
             $sessionId = $session['session_id'];
@@ -94,21 +124,59 @@ if ($form->validate()) {
                 $courseInfo = api_get_course_info_by_id($course['real_id']);
                 $result = MySpace::get_connections_to_course_by_date(
                     $userId,
-                    $course,
+                    $courseInfo,
                     $sessionId,
                     $from,
                     $to
                 );
 
+                $partialMinLogin = 0;
+                $partialMaxLogin = 0;
+                $partialDuration = 0;
+
                 foreach ($result as $item) {
                     $record = [
-                        $courseInfo['title'],
-                        $session['session_name'],
-                        customDate($item['login']),
-                        customDate($item['logout']),
+                        customDate($item['login'], true),
+                        customDate($item['logout'], true),
                         api_format_time($item['duration'], 'js'),
                     ];
-                    $report[] = $record;
+
+                    $totalDuration += $item['duration'];
+
+                    if (empty($minLogin)) {
+                        $minLogin = api_strtotime($item['login'], 'UTC');
+                    }
+                    if ($minLogin > api_strtotime($item['login'], 'UTC')) {
+                        $minLogin = api_strtotime($item['login'], 'UTC');
+                    }
+                    if (api_strtotime($item['logout']) > $maxLogin) {
+                        $maxLogin = api_strtotime($item['logout'], 'UTC');
+                    }
+
+                    // Partials
+                    $partialDuration += $item['duration'];
+                    if (empty($partialMinLogin)) {
+                        $partialMinLogin = api_strtotime($item['login'], 'UTC');
+                    }
+                    if ($partialMinLogin > api_strtotime($item['login'], 'UTC')) {
+                        $partialMinLogin = api_strtotime($item['login'], 'UTC');
+                    }
+                    if (api_strtotime($item['logout'], 'UTC') > $partialMaxLogin) {
+                        $partialMaxLogin = api_strtotime($item['logout'], 'UTC');
+                    }
+
+                    $report[$sessionId]['courses'][$course['real_id']][] = $record;
+                    $report[$sessionId]['name'][$course['real_id']] = $courseInfo['title'].'&nbsp; ('.$session['session_name'].')';
+                }
+
+                if (!empty($result)) {
+                    $record = [
+                        customDate($partialMinLogin, true),
+                        customDate($partialMaxLogin, true),
+                        api_format_time($partialDuration, 'js'),
+                    ];
+                    $report[$sessionId]['courses'][$course['real_id']][] = $record;
+                    $report[$sessionId]['name'][$course['real_id']] = $courseInfo['title'].'&nbsp; ('.$session['session_name'].')';
                 }
             }
         }
@@ -126,25 +194,61 @@ if ($form->validate()) {
             $to
         );
 
+        $partialMinLogin = 0;
+        $partialMaxLogin = 0;
+        $partialDuration = 0;
+
         foreach ($result as $item) {
             $record = [
-                $course['title'],
-                '',
-                customDate($item['login']),
-                customDate($item['logout']),
+                customDate($item['login'], true),
+                customDate($item['logout'], true),
                 api_format_time($item['duration'], 'js'),
             ];
-            $report[] = $record;
+            $report[0]['courses'][$course['course_id']][] = $record;
+            $report[0]['name'][$course['course_id']] = $course['title'];
+
+            $totalDuration += $item['duration'];
+
+            if (empty($minLogin)) {
+                $minLogin = api_strtotime($item['login'], 'UTC');
+            }
+            if ($minLogin > api_strtotime($item['login'], 'UTC')) {
+                $minLogin = api_strtotime($item['login'], 'UTC');
+            }
+            if (api_strtotime($item['logout'], 'UTC') > $maxLogin) {
+                $maxLogin = api_strtotime($item['logout'], 'UTC');
+            }
+
+            // Partials
+            $partialDuration += $item['duration'];
+            if (empty($partialMinLogin)) {
+                $partialMinLogin = api_strtotime($item['login'], 'UTC');
+            }
+            if ($partialMinLogin > api_strtotime($item['login'], 'UTC')) {
+                $partialMinLogin = api_strtotime($item['login'], 'UTC');
+            }
+            if (api_strtotime($item['logout'], 'UTC') > $partialMaxLogin) {
+                $partialMaxLogin = api_strtotime($item['logout'], 'UTC');
+            }
+        }
+
+        if (!empty($result)) {
+            $record = [
+                customDate($partialMinLogin, true),
+                customDate($partialMaxLogin, true),
+                api_format_time($partialDuration, 'js'),
+            ];
+
+            $report[0]['courses'][$course['course_id']][] = $record;
+            $report[0]['name'][$course['course_id']] = $course['title'];
         }
     }
 
     $table = new HTML_Table(['class' => 'data_table']);
     $headers = [
-        get_lang('Course'),
-        get_lang('Session'),
-        get_lang('StartDate'),
-        get_lang('EndDate'),
-        get_lang('Duration'),
+        get_lang('MinStartDate'),
+        get_lang('MaxEndDate'),
+        get_lang('TotalDuration'),
     ];
     $row = 0;
     $column = 0;
@@ -153,18 +257,48 @@ if ($form->validate()) {
         $column++;
     }
     $row++;
-    foreach ($report as $record) {
-        $column = 0;
-        foreach ($record as $item) {
-            $table->setCellContents($row, $column++, $item);
+    $column = 0;
+    $table->setCellContents($row, $column++, customDate($minLogin));
+    $table->setCellContents($row, $column++, customDate($maxLogin));
+    $table->setCellContents($row, $column++, api_format_time($totalDuration, 'js'));
+    $content = Display::page_subheader3(get_lang('Total')).$table->toHtml();
+
+    foreach ($report as $sessionId => $data) {
+        foreach ($data['courses'] as $courseId => $courseData) {
+            $content .= Display::page_subheader3($data['name'][$courseId]);
+            $table = new HTML_Table(['class' => 'data_table']);
+            $headers = [
+                get_lang('StartDate'),
+                get_lang('EndDate'),
+                get_lang('Duration'),
+            ];
+            $row = 0;
+            $column = 0;
+            foreach ($headers as $header) {
+                $table->setHeaderContents($row, $column, $header);
+                $column++;
+            }
+            $row++;
+            $countData = count($courseData);
+            foreach ($courseData as $record) {
+                $column = 0;
+                foreach ($record as $item) {
+                    $table->setCellContents($row, $column++, $item);
+                    if ($row == $countData) {
+                        $table->setRowAttributes($row, ['style' => 'font-weight:bold']);
+                    }
+                }
+                $row++;
+            }
+            $content .= $table->toHtml();
         }
-        $row++;
     }
 
     $tpl = new Template('', false, false, false, true, false, false);
     $tpl->assign('title', get_lang('AttestationOfAttendance'));
     $tpl->assign('student', $userInfo['complete_name']);
-    $tpl->assign('table_progress', $table->toHtml());
+    $tpl->assign('table_progress', $content);
+
     $content = $tpl->fetch($tpl->get_template('my_space/pdf_export_student.tpl'));
     $params = [
         'pdf_title' => get_lang('Resume'),
@@ -178,7 +312,7 @@ if ($form->validate()) {
         'orientation' => 'P',
     ];
 
-    $pdf = @new PDF('A4', $params['orientation'], $params);
+    @$pdf = new PDF('A4', $params['orientation'], $params);
 
     $pdf->setBackground($tpl->theme);
     @$pdf->content_to_pdf(

+ 3 - 5
main/session/session_edit.php

@@ -21,7 +21,7 @@ $htmlHeadXtra[] = api_get_asset('cropper/dist/cropper.min.js');
 $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
 $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
 
-$id = intval($_GET['id']);
+$id = (int) $_GET['id'];
 
 SessionManager::protectSession($id);
 
@@ -51,11 +51,10 @@ if (!empty($sessionInfo['coach_access_end_date'])) {
     $sessionInfo['coach_access_end_date'] = api_get_local_time($sessionInfo['coach_access_end_date']);
 }
 
-$id_coach = $sessionInfo['id_coach'];
 $tool_name = get_lang('EditSession');
 
-$interbreadcrumb[] = ['url' => "session_list.php", "name" => get_lang('SessionList')];
-$interbreadcrumb[] = ['url' => "resume_session.php?id_session=".$id, "name" => get_lang('SessionOverview')];
+$interbreadcrumb[] = ['url' => 'session_list.php', 'name' => get_lang('SessionList')];
+$interbreadcrumb[] = ['url' => 'resume_session.php?id_session='.$id, 'name' => get_lang('SessionOverview')];
 
 if (isset($_POST['formSent']) && $_POST['formSent']) {
     $formSent = 1;
@@ -206,7 +205,6 @@ $form->display();
 
 <script>
 $(function() {
-
 <?php
     if (!empty($sessionInfo['duration'])) {
         echo 'accessSwitcher(0);';

+ 0 - 12
main/social/view_promoted_message.php

@@ -17,17 +17,6 @@ $interbreadcrumb[] = ['url' => api_get_path(WEB_PATH).'main/social/home.php', 'n
 $interbreadcrumb[] = ['url' => 'promoted_messages.php', 'name' => get_lang('PromotedMessages')];
 
 $social_right_content = '';
-/*$social_right_content = '<div class="actions">';
-if (api_get_setting('allow_message_tool') === 'true') {
-    $social_right_content .= '<a href="'.api_get_path(WEB_PATH).'main/messages/new_message.php">'.
-        Display::return_icon('new-message.png', get_lang('ComposeMessage')).'</a>';
-    $social_right_content .= '<a href="'.api_get_path(WEB_PATH).'main/messages/inbox.php">'.
-        Display::return_icon('inbox.png', get_lang('Inbox')).'</a>';
-    $social_right_content .= '<a href="'.api_get_path(WEB_PATH).'main/messages/outbox.php">'.
-        Display::return_icon('outbox.png', get_lang('Outbox')).'</a>';
-}
-$social_right_content .= '</div>';*/
-
 if (empty($_GET['id'])) {
     $messageId = $_GET['id_send'];
     $source = 'outbox';
@@ -46,7 +35,6 @@ $logInfo = [
     'action_details' => 'view-message',
 ];
 Event::registerLog($logInfo);
-
 $social_menu_block = SocialManager::show_social_menu($show_menu);
 $message .= MessageManager::showMessageBox($messageId, 'promoted_messages');
 

+ 1 - 1
main/template/default/export/pdf_footer.tpl

@@ -4,7 +4,7 @@
             <strong>{{ _s.institution }}</strong>
         </td>
         <td class="text-right">
-            <strong> {PAGENO} / {nb} </strong>
+            <strong>{PAGENO} / {nb}</strong>
         </td>
     </tr>
 </table>

+ 1 - 8
main/template/default/learnpath/view.tpl

@@ -32,8 +32,6 @@
                             #timer .container{display:table;background:#777;color:#eee;font-weight:bold;width:100%;text-align:center;text-shadow:1px 1px 4px #999;}
                             #timer .container div{display:table-cell;font-size:24px;padding:0px;width:20px;}
                             #timer .container .divider{width:10px;color:#ddd;}
-                            #btn-comenzar{box-sizing:border-box;background:#eee;border:none;margin:0 auto;padding:20px;width:100%;font-size:30px;color:#777;}
-                            #btn-comenzar:hover{background:#fff;}
                         </style>
                         <script>
                             $(function() {
@@ -42,7 +40,6 @@
                                     minute: parseInt($("#minute").text()),
                                     second:  parseInt($("#second").text())
                                 };
-                                //window.timerInterval = null;
                                 clearInterval(window.timerInterval);
                                 window.timerInterval = setInterval(function(){
                                     // Seconds
@@ -76,7 +73,6 @@
                                 </div>
                             </div>
                         </div>
-
                         <div class="row">
                             <div class="col-xs-4">
                                 <b>
@@ -91,7 +87,6 @@
                                         <div id="minute">{{ minute }}</div>
                                         <div class="divider">:</div>
                                         <div id="second">{{ second }}</div>
-
                                         <div id="slash"> / </div>
                                         <div>{{ hour_min }}</div>
                                     </div>
@@ -175,7 +170,7 @@
                     </ul>
                 </div>
                 <nav id="btn-menu-float" class="circular-menu">
-                    <div class="circle">
+                    <div class="circle {{ show_toolbar_by_default == 1 ? 'open' : '' }}">
                         {% if show_left_column == 1 %}
                             <a href="#" title = "{{ 'Expand'|get_lang }}" id="lp-view-expand-toggle"
                                class="icon-toolbar expand" role="button">
@@ -262,7 +257,6 @@
         }
 
         {% if lp_mode == 'embedframe' %}
-            //$('#learning_path_main').addClass('lp-view-collapsed');
             $('#lp-view-expand-button, #lp-view-expand-toggle').on('click', function (e) {
                 e.preventDefault();
                 $('#learning_path_main').toggleClass('lp-view-collapsed');
@@ -383,7 +377,6 @@
         {% if disable_js_in_lp_view == 0 %}
             $(function() {
                 var arr = ['link', 'sco'];
-
                 if ($.inArray(olms.lms_item_type, arr) == -1) {
                     {{ frame_ready }}
                 }

+ 1 - 1
main/template/default/social/user_block.tpl

@@ -60,7 +60,7 @@
                                 {% endif %}
                             {% endfor %}
                         </div>
-                        <!-- End language cible ->
+                        <!-- End language cible -->
                         {% endif %}
                     </div>
                     {# Ofaj #}

+ 1 - 1
main/template/default/user_portal/grid_courses_with_category.tpl

@@ -1,5 +1,5 @@
 <div class="grid-courses">
-    {% for category in courses.in_category %}
+    {% for category in categories %}
         {% set nameCategory = category.title_category %}
         {% set idCategory = category.id_category %}
         <div id="category_{{ idCategory }}" class="panel panel-default">

+ 0 - 1
main/wiki/wiki.inc.php

@@ -4897,7 +4897,6 @@ class Wiki
 
             if (api_is_allowed_to_edit(false, true) || api_is_platform_admin()) {
                 // only by professors if page is hidden
-                //only by professors if page is hidden
                 $sql = "SELECT * FROM ".$tbl_wiki." s1
                         WHERE s1.c_id = $course_id AND linksto LIKE '%".Database::escape_string(
                         $page

+ 10 - 8
main/work/work.lib.php

@@ -2245,14 +2245,16 @@ function get_work_user_list(
                             $sizeFile = round(filesize($workDirectory.'/'.$work['url']) / 1000000);
                             $actionCompilatio = get_lang('CompilatioFileIsTooBig').': '.format_file_size($sizeFile).'<br />';
                         } else {
-                            $actionCompilatio = "<div id='id_avancement".$item_id."' class='compilation_block'>"
-                                ."<a href='javascript:void(0)' class=\"getSingleCompilatio\" onClick='getSingleCompilatio("
-                                .$item_id
-                                .");'>"
-                                .get_lang('CompilatioAnalysis')
-                                ." </a>"
-                                .get_lang('CompilatioWithCompilatio')
-                                ."</div>";
+                            $actionCompilatio = "<div id='id_avancement".$item_id."' class='compilation_block'>";
+                            $actionCompilatio .= Display::url(
+                                get_lang('CompilatioAnalysis'),
+                                'javascript:void(0)',
+                                [
+                                    'class' => 'getSingleCompilatio btn btn-primary btn-xs',
+                                    'onclick' => "getSingleCompilatio($item_id);",
+                                ]
+                            );
+                            $actionCompilatio .= get_lang('CompilatioWithCompilatio');
                         }
                     }
                     $work['compilatio'] = $actionCompilatio;

+ 1 - 0
plugin/customcertificate/src/index.php

@@ -950,6 +950,7 @@ function checkInstanceImage($certificateId, $imagePath, $field, $type = 'certifi
     $table = Database::get_main_table(CustomCertificatePlugin::TABLE_CUSTOMCERTIFICATE);
     $imagePath = Database::escape_string($imagePath);
     $field = Database::escape_string($field);
+    $certificateId = (int) $certificateId;
 
     $sql = "SELECT * FROM $table WHERE $field = '$imagePath'";
     $res = Database::query($sql);

+ 1 - 1
plugin/grading_electronic/generate.php

@@ -110,7 +110,7 @@ try {
 
     $fileData = [];
     $fileData[] = sprintf(
-        "1 %s %s%s",
+        '1 %s %s%s',
         $fieldProvider ? $fieldProvider['value'] : null,
         $values['course'],
         $dateStart->format('m/d/Y')