Bläddra i källkod

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

jmontoyaa 7 år sedan
förälder
incheckning
1102ece3bd
80 ändrade filer med 602 tillägg och 512 borttagningar
  1. 11 1
      app/Resources/public/css/base.css
  2. 24 8
      documentation/security.html
  3. 5 1
      main/admin/configure_plugin.php
  4. 2 2
      main/announcements/announcements.php
  5. 1 1
      main/auth/shibboleth/lib/shibboleth_session.class.php
  6. 57 0
      main/auth/sso/SsoServer.php
  7. 1 1
      main/calendar/agenda.php
  8. 2 2
      main/exercise/exercise_report.php
  9. 2 2
      main/exercise/hotpotatoes_exercise_report.php
  10. 1 1
      main/forum/editthread.php
  11. 1 1
      main/forum/forumfunction.inc.php
  12. 1 1
      main/forum/viewforum.php
  13. 1 1
      main/forum/viewthread.php
  14. 4 4
      main/forum/viewthread_flat.inc.php
  15. 4 4
      main/forum/viewthread_nested.inc.php
  16. 3 3
      main/forum/viewthread_threaded.inc.php
  17. 1 1
      main/gradebook/gradebook_flatview.php
  18. 1 1
      main/inc/ajax/announcement.ajax.php
  19. 1 0
      main/inc/ajax/course_home.ajax.php
  20. 1 1
      main/inc/lib/AnnouncementManager.php
  21. 1 1
      main/inc/lib/CourseChatUtils.php
  22. 67 119
      main/inc/lib/api.lib.php
  23. 11 1
      main/inc/lib/banner.lib.php
  24. 2 1
      main/inc/lib/course_home.lib.php
  25. 3 3
      main/inc/lib/display.lib.php
  26. 2 2
      main/inc/lib/groupmanager.lib.php
  27. 7 7
      main/inc/lib/login.lib.php
  28. 100 44
      main/inc/lib/plugin.class.php
  29. 5 18
      main/inc/lib/sessionmanager.lib.php
  30. 4 1
      main/inc/lib/usermanager.lib.php
  31. 13 13
      main/inc/local.inc.php
  32. 0 1
      main/lang/arabic/trad4all.inc.php
  33. 0 1
      main/lang/asturian/trad4all.inc.php
  34. 0 1
      main/lang/basque/trad4all.inc.php
  35. 0 1
      main/lang/brazilian/trad4all.inc.php
  36. 0 1
      main/lang/bulgarian/trad4all.inc.php
  37. 0 1
      main/lang/catalan/trad4all.inc.php
  38. 0 1
      main/lang/croatian/trad4all.inc.php
  39. 0 1
      main/lang/danish/trad4all.inc.php
  40. 0 1
      main/lang/dutch/trad4all.inc.php
  41. 1 1
      main/lang/english/trad4all.inc.php
  42. 0 1
      main/lang/finnish/trad4all.inc.php
  43. 4 4
      main/lang/french/trad4all.inc.php
  44. 0 1
      main/lang/galician/trad4all.inc.php
  45. 4 5
      main/lang/german/trad4all.inc.php
  46. 0 1
      main/lang/greek/trad4all.inc.php
  47. 0 1
      main/lang/hungarian/trad4all.inc.php
  48. 0 1
      main/lang/italian/trad4all.inc.php
  49. 0 1
      main/lang/latvian/trad4all.inc.php
  50. 0 1
      main/lang/lithuanian/trad4all.inc.php
  51. 0 1
      main/lang/persian/trad4all.inc.php
  52. 0 1
      main/lang/polish/trad4all.inc.php
  53. 0 1
      main/lang/portuguese/trad4all.inc.php
  54. 0 1
      main/lang/quechua_cusco/trad4all.inc.php
  55. 0 1
      main/lang/romanian/trad4all.inc.php
  56. 0 1
      main/lang/russian/trad4all.inc.php
  57. 0 1
      main/lang/serbian/trad4all.inc.php
  58. 0 1
      main/lang/slovak/trad4all.inc.php
  59. 0 1
      main/lang/slovenian/trad4all.inc.php
  60. 2 3
      main/lang/spanish/trad4all.inc.php
  61. 0 1
      main/lang/swedish/trad4all.inc.php
  62. 0 1
      main/lang/trad_chinese/trad4all.inc.php
  63. 79 87
      main/lp/learnpath.class.php
  64. 1 1
      main/survey/create_new_survey.php
  65. 1 1
      main/survey/survey.php
  66. 4 4
      main/survey/survey_list.php
  67. 81 78
      main/template/default/layout/layout_2_col.tpl
  68. 2 2
      main/template/default/user_portal/classic_session.tpl
  69. 1 1
      main/template/default/user_portal/grid_session.tpl
  70. 12 10
      main/template/default/work/comments.tpl
  71. 18 14
      main/tracking/courseLog.php
  72. 1 1
      main/tracking/course_session_report.php
  73. 1 1
      main/tracking/exams.php
  74. 1 1
      main/tracking/lp_results_by_user.php
  75. 1 1
      main/tracking/question_course_report.php
  76. 1 1
      src/Chamilo/CoreBundle/Entity/SettingsCurrent.php
  77. 39 20
      tests/behat/features/session.feature
  78. 4 1
      tests/xhprof/footer.php
  79. 4 1
      tests/xhprof/header.php
  80. 1 1
      user_portal.php

+ 11 - 1
app/Resources/public/css/base.css

@@ -163,7 +163,6 @@ header {
     color: #666;
 }
 #carousel-announcement img{
-    display: block;
     max-width: 100%;
     height: auto;
 }
@@ -6791,6 +6790,10 @@ input.form-control[type="color"] {
     margin-top: 20px;
 }
 
+.col-xs-6.course-tool:nth-child(2n+1) {
+    clear: left;
+}
+
 /* Extra small devices (phones, less than 768px) */
 /* No media query since this is the default in Bootstrap */
 
@@ -6811,6 +6814,13 @@ input.form-control[type="color"] {
 
 /* Medium devices (desktops, 992px and up) */
 @media (min-width: 992px) {
+    .col-xs-6.course-tool:nth-child(2n+1) {
+        clear: none;
+    }
+    .col-md-3.course-tool:nth-child(4n+1) {
+        clear: left;
+    }
+
     div.navbar-collapse {
         padding-left: 0;
     }

+ 24 - 8
documentation/security.html

@@ -23,19 +23,20 @@
   <li><a href="#3.Using-safe-browsers">Using safe browsers</a></li>
   <li><a href="#4.Moving-config-file">Moving your configuration file out of the web directory</a></li>
   <li><a href="#5.Files-permissions">Restricting files permissions</a></li>
+  <li><a href="#6.HSTS">HTTP Headers Security</a></li>
 </ol>
 
 <h2><a name="1.Disclosing-server-info"></a>1. Disclosing server info</h2>
 <p>
 It is considered a safer behaviour not to disclose server information from your Chamilo page. In order to avoid
     both web server and PHP information disclosure, you might want to take the following actions:
+</p>
 <ul>
 <li>Locate the <i>ServerTokens</i> setting inside your Apache configuration and set it to "Prod"</li>
 <li>Locate the <i>ServerSignature</i> setting inside your Apache configuration and set it to "Off"</li>
 <li>Locate the <i>expose_php</i> setting inside your PHP configuration and set it to "Off"</li>
 <li>Reload Apache</li>
 </ul>
-</p>
 
 <h2><a name="2.Keeping-up-to-date"></a>2. Keeping up to date</h2>
 <p>
@@ -62,31 +63,46 @@ access to your database if that one isn't well protected and many other stuff we
     move the configuration file out of your web directory. If your Chamilo installation is in /var/www/, move your
     configuration to /etc/chamilo/configuration.php, for example. Then create a new app/config/configuration.php
     file, open it, and write the following:</p>
-<p>
 <pre>
 &lt;?php
 require '/etc/chamilo/configuration.php';
 </pre>
-</p>
 <p>
 This will prevent direct access to your settings and make it seem totally the same to Chamilo.
 </p>
 
 <h2><a name="5.Files-permissions"></a>5. Restricting files permissions</h2>
-        Making all the Chamilo files world-writable will help you install quickly, and it solves many
+        <p>Making all the Chamilo files world-writable will help you install quickly, and it solves many
         issues for people without much admin experience. However, it's more
         secure to make a distinct user owner of all the chamilo files and folders,
         and only give read access to the web server to all files, and write access
-        only to the directories previously mentioned. This way, these files need
+            only to the directories previously mentioned.</p>
+    <p>This way, these files need
         only be readable and writable by the Apache process owner, not by the
         entire world. It would also be advisable to make all writable directory
         refuse the interpretation of PHP files (except for the root of the courses
-        directories). Don't hesitate to hire an experienced administrator to do that,
+        directories).</p>
+    <p>Don't hesitate to hire an experienced administrator to do that,
         it might be a bit more expensive now, but you'll be happy not to have to loose
-        all of your data to a hacker who attacked your site.</li>
+        all of your data to a hacker who attacked your site.</p>
 
 
-    <hr />
+<hr />
+<h2><a name="6.HSTS">HTTP Headers Security</a></h2>
+    <p>A relatively recent development in web security, HTTP headers can be modified either
+    from the web server or from the application (like Chamilo) to increase the security
+        of your visitors.</p>
+    <p>These implies several aspects, from simple to complex, to deal with, from stuff like
+    indicating which websites you say media or libraries can be loaded from, to adding
+    extra info about your SSL certificate to make sure a hacked certification authority
+        will not immediately make your certificate useless.</p>
+    <p>In Chamilo 1.11.6, we have added several parameters, together with recommendations,
+    to main/install/configuration.dist.php, that you are free to use or ignore,
+        depending on the level of security you want to achieve.</p>>
+    <p>To check your portal for possible improvements in terms of headers security,
+        we highly recommend the <a href="https://securityheaders.io/">securityheaders.io</a>
+        website. If you want to read more about CSP and all related headers
+        security techniques, check <a href="https://scotthelme.co.uk/">Scott Helme's blog</a>.
 <h2>Authors</h2>
 <ul>
 <li>Yannick Warnier, Zend Certified PHP Engineer, BeezNest Belgium SPRL,

+ 5 - 1
main/admin/configure_plugin.php

@@ -80,8 +80,12 @@ if (isset($form)) {
             );
         }
 
+        /** @var \Plugin $objPlugin */
+        $objPlugin = $pluginInfo['plugin_class']::create();
+        $objPlugin->get_settings(true);
+        $objPlugin->performActionsAfterConfigure();
+
         if (isset($values['show_main_menu_tab'])) {
-            $objPlugin = $pluginInfo['plugin_class']::create();
             $objPlugin->manageTab($values['show_main_menu_tab']);
         }
 

+ 2 - 2
main/announcements/announcements.php

@@ -297,7 +297,7 @@ switch ($action) {
             api_not_allowed();
         }
 
-        if (!api_is_course_coach() || api_is_element_in_the_session(TOOL_ANNOUNCEMENT, $id)) {
+        if (!api_is_session_general_coach() || api_is_element_in_the_session(TOOL_ANNOUNCEMENT, $id)) {
             AnnouncementManager::delete_announcement($_course, $id);
             Display::addFlash(Display::return_message(get_lang('AnnouncementDeleted')));
         }
@@ -331,7 +331,7 @@ switch ($action) {
                     api_not_allowed();
                 }
 
-                if (!api_is_course_coach() ||
+                if (!api_is_session_general_coach() ||
                     api_is_element_in_the_session(TOOL_ANNOUNCEMENT, $_GET['id'])
                 ) {
                     AnnouncementManager::change_visibility_announcement(

+ 1 - 1
main/auth/shibboleth/lib/shibboleth_session.class.php

@@ -56,7 +56,7 @@ class ShibbolethSession
          * This is BAD. Logic should be migrated into a function and stop relying on global variables.
          */
         global $_uid, $is_allowedCreateCourse, $is_platformAdmin, $_real_cid, $is_courseAdmin;
-        global $is_courseMember, $is_courseTutor, $is_courseCoach, $is_allowed_in_course, $is_sessionAdmin, $_gid;
+        global $is_courseMember, $is_courseTutor, $is_session_general_coach, $is_allowed_in_course, $is_sessionAdmin, $_gid;
         $_uid = $uid;
 
         //is_allowedCreateCourse

+ 57 - 0
main/auth/sso/SsoServer.php

@@ -0,0 +1,57 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+/**
+ * This file contains the necessary elements to implement a Single Sign On
+ * using chamilo as a SSO server
+ * @package chamilo.auth.sso
+ */
+class SsoServer
+{
+    /**
+     * This is used to get the url with the SSO params
+     * @param string $refererSso
+     * @param array $additionalParams
+     * @return string
+     */
+    public function getUrl($refererSso, $additionalParams = array())
+    {
+        if (empty($refererSso)) {
+            return null;
+        }
+
+        $getParams = parse_url($refererSso, PHP_URL_QUERY);
+        $userInfo = api_get_user_info(api_get_user_id(), false, true);
+        $chamiloUrl = api_get_path(WEB_PATH);
+        $sso = [
+            'username' => $userInfo['username'],
+            'secret' => sha1($userInfo['password']),
+            'master_domain' => $chamiloUrl,
+            'master_auth_uri' => $chamiloUrl.'?submitAuth=true',
+            'lifetime' => time() + 3600,
+            'target' => $refererSso,
+        ];
+
+        if (!empty($additionalParams)) {
+            foreach ($additionalParams as $key => $value) {
+                if (!empty($key)) {
+                    $sso[$key] = $value;
+
+                    continue;
+                }
+
+                $sso[] = $value;
+            }
+        }
+
+        $cookie = base64_encode(serialize($sso));
+
+        return $refererSso
+            .($getParams ? '&' : '?')
+            .http_build_query([
+                'loginFailed' => 0,
+                'sso_referer' => $refererSso,
+                'sso_cookie' => $cookie
+            ]);
+    }
+}

+ 1 - 1
main/calendar/agenda.php

@@ -285,7 +285,7 @@ if ($allowToEdit) {
             $content = $form->returnForm();
             break;
         case "delete":
-            if (!(api_is_course_coach() && !api_is_element_in_the_session(TOOL_AGENDA, $eventId))) {
+            if (!(api_is_session_general_coach() && !api_is_element_in_the_session(TOOL_AGENDA, $eventId))) {
                 // a coach can only delete an element belonging to his session
                 $content = $agenda->deleteEvent($eventId);
             }

+ 2 - 2
main/exercise/exercise_report.php

@@ -74,7 +74,7 @@ if (!empty($_GET['path'])) {
 
 if (!empty($_REQUEST['export_report']) && $_REQUEST['export_report'] == '1') {
     if (api_is_platform_admin() || api_is_course_admin() ||
-        api_is_course_tutor() || api_is_course_coach()
+        api_is_course_tutor() || api_is_session_general_coach()
     ) {
         $loadExtraData = false;
         if (isset($_REQUEST['extra_data']) && $_REQUEST['extra_data'] == 1) {
@@ -262,7 +262,7 @@ $actions = null;
 if ($is_allowedToEdit && $origin != 'learnpath') {
     // the form
     if (api_is_platform_admin() || api_is_course_admin() ||
-        api_is_course_tutor() || api_is_course_coach()
+        api_is_course_tutor() || api_is_session_general_coach()
     ) {
         $actions .= '<a href="admin.php?exerciseId='.intval($_GET['exerciseId']).'">'.Display::return_icon('back.png', get_lang('GoBackToQuestionList'), '', ICON_SIZE_MEDIUM).'</a>';
         $actions .= '<a href="live_stats.php?'.api_get_cidreq().'&exerciseId='.$exercise_id.'">'.Display::return_icon('activity_monitor.png', get_lang('LiveResults'), '', ICON_SIZE_MEDIUM).'</a>';

+ 2 - 2
main/exercise/hotpotatoes_exercise_report.php

@@ -54,7 +54,7 @@ if (!empty($_REQUEST['path'])) {
 $origin = isset($origin) ? $origin : null;
 
 if (!empty($_REQUEST['export_report']) && $_REQUEST['export_report'] == '1') {
-    if (api_is_platform_admin() || api_is_course_admin() || api_is_course_tutor() || api_is_course_coach()) {
+    if (api_is_platform_admin() || api_is_course_admin() || api_is_course_tutor() || api_is_session_general_coach()) {
         $load_extra_data = false;
         if (isset($_REQUEST['extra_data']) && $_REQUEST['extra_data'] == 1) {
             $load_extra_data = true;
@@ -71,7 +71,7 @@ if (!empty($_REQUEST['export_report']) && $_REQUEST['export_report'] == '1') {
 $actions = null;
 if ($is_allowedToEdit && $origin != 'learnpath') {
     // the form
-    if (api_is_platform_admin() || api_is_course_admin() || api_is_course_tutor() || api_is_course_coach()) {
+    if (api_is_platform_admin() || api_is_course_admin() || api_is_course_tutor() || api_is_session_general_coach()) {
         $actions .= '<a id="export_opener" href="'.api_get_self().'?export_report=1&path='.$hotpotatoes_path.' ">'.
             Display::return_icon('save.png', get_lang('Export'), '', ICON_SIZE_MEDIUM).'</a>';
     }

+ 1 - 1
main/forum/editthread.php

@@ -168,7 +168,7 @@ $form->addElement('text', 'thread_title', get_lang('Title'));
 $form->addElement('advanced_settings', 'advanced_params', get_lang('AdvancedParameters'));
 $form->addElement('html', '<div id="advanced_params_options" style="display:none">');
 
-if ((api_is_course_admin() || api_is_course_coach() || api_is_course_tutor()) && ($threadId)) {
+if ((api_is_course_admin() || api_is_session_general_coach() || api_is_course_tutor()) && ($threadId)) {
     // Thread qualify
     if (Gradebook::is_active()) {
         //Loading gradebook select

+ 1 - 1
main/forum/forumfunction.inc.php

@@ -2879,7 +2879,7 @@ function show_add_post_form($current_forum, $forum_setting, $action, $id = '', $
     }
 
     if (Gradebook::is_active() &&
-        (api_is_course_admin() || api_is_course_coach() || api_is_course_tutor()) && !($myThread)
+        (api_is_course_admin() || api_is_session_general_coach() || api_is_course_tutor()) && !($myThread)
     ) {
         $form->addElement('advanced_settings', 'advanced_params', get_lang('AdvancedParameters'));
         $form->addElement('html', '<div id="advanced_params_options" style="display:none">');

+ 1 - 1
main/forum/viewforum.php

@@ -574,7 +574,7 @@ if (is_array($threads)) {
             $iconsEdit = '';
             if ($origin != 'learnpath') {
                 if (api_is_allowed_to_edit(false, true) &&
-                    !(api_is_course_coach() && $current_forum['session_id'] != $sessionId)
+                    !(api_is_session_general_coach() && $current_forum['session_id'] != $sessionId)
                 ) {
                     $iconsEdit .= '<a href="'.$forumUrl.'editthread.php?'.$cidreq
                         . '&forum='.$my_forum.'&thread='

+ 1 - 1
main/forum/viewthread.php

@@ -198,7 +198,7 @@ if ($my_message != 'PostDeletedSpecial') {
             // new thread link
             if ((
                     api_is_allowed_to_edit(false, true) &&
-                    !(api_is_course_coach() && $current_forum['session_id'] != $sessionId)
+                    !(api_is_session_general_coach() && $current_forum['session_id'] != $sessionId)
                 ) ||
                 ($current_forum['allow_new_threads'] == 1 && isset($_user['user_id'])) ||
                 ($current_forum['allow_new_threads'] == 1 && !isset($_user['user_id']) && $current_forum['allow_anonymous'] == 1)

+ 4 - 4
main/forum/viewthread_flat.inc.php

@@ -162,7 +162,7 @@ if (isset($current_thread['thread_id'])) {
                 ($current_forum['allow_edit'] == 1 && $row['user_id'] == $_user['user_id']) ||
                 (
                 api_is_allowed_to_edit(false, true) &&
-                !(api_is_course_coach() && $current_forum['session_id'] != $sessionId)
+                !(api_is_session_general_coach() && $current_forum['session_id'] != $sessionId)
                 )
             ) {
                 if (api_is_allowed_to_session_edit(false, true)) {
@@ -178,7 +178,7 @@ if (isset($current_thread['thread_id'])) {
             if ($origin != 'learnpath') {
                 if (GroupManager::is_tutor_of_group($userId, $groupInfo) ||
                     api_is_allowed_to_edit(false, true) &&
-                    !(api_is_course_coach() && $current_forum['session_id'] != $sessionId)
+                    !(api_is_session_general_coach() && $current_forum['session_id'] != $sessionId)
                 ) {
                     if ($locked === false) {
                         $deleteUrl = api_get_self().'?'.api_get_cidreq().'&'.http_build_query([
@@ -205,7 +205,7 @@ if (isset($current_thread['thread_id'])) {
 
                 if (GroupManager::is_tutor_of_group($userId, $groupInfo) ||
                     (api_is_allowed_to_edit(false, true) &&
-                    !(api_is_course_coach() && $current_forum['session_id'] != $sessionId)
+                    !(api_is_session_general_coach() && $current_forum['session_id'] != $sessionId)
                     )
                 ) {
                     $iconEdit .= return_visible_invisible_icon(
@@ -318,7 +318,7 @@ if (isset($current_thread['thread_id'])) {
                     $html .= '<a href="download.php?file='.$realname.'"> '.$user_filename.' </a>';
 
                     if (($current_forum['allow_edit'] == 1 && $row['user_id'] == $_user['user_id']) ||
-                        (api_is_allowed_to_edit(false, true) && !(api_is_course_coach() && $current_forum['session_id'] != $sessionId))
+                        (api_is_allowed_to_edit(false, true) && !(api_is_session_general_coach() && $current_forum['session_id'] != $sessionId))
                     ) {
                         $html .= '&nbsp;&nbsp;<a href="'.api_get_self().'?'.api_get_cidreq().'&action=delete_attach&id_attach='
                             . $attachment['iid'].'&forum='.$clean_forum_id.'&thread='.$clean_thread_id

+ 4 - 4
main/forum/viewthread_nested.inc.php

@@ -118,7 +118,7 @@ foreach ($posts as $post) {
     if ((isset($groupInfo['iid']) && $tutorGroup) ||
         ($current_forum['allow_edit'] == 1 && $post['user_id'] == $userId) ||
         (api_is_allowed_to_edit(false, true) &&
-        !(api_is_course_coach() && $current_forum['session_id'] != $sessionId))
+        !(api_is_session_general_coach() && $current_forum['session_id'] != $sessionId))
     ) {
         if ($locked == false && postIsEditableByStudent($current_forum, $post)) {
             $editUrl = api_get_path(WEB_CODE_PATH).'forum/editpost.php?'.api_get_cidreq();
@@ -139,7 +139,7 @@ foreach ($posts as $post) {
 
     if ((isset($groupInfo['iid']) && $tutorGroup) ||
         api_is_allowed_to_edit(false, true) &&
-        !(api_is_course_coach() && $current_forum['session_id'] != $sessionId)
+        !(api_is_session_general_coach() && $current_forum['session_id'] != $sessionId)
     ) {
         if ($locked == false) {
             $deleteUrl = api_get_self().'?'.api_get_cidreq().'&'.http_build_query([
@@ -164,7 +164,7 @@ foreach ($posts as $post) {
 
     if (api_is_allowed_to_edit(false, true) &&
         !(
-            api_is_course_coach() &&
+            api_is_session_general_coach() &&
             $current_forum['session_id'] != $sessionId
         )
     ) {
@@ -333,7 +333,7 @@ foreach ($posts as $post) {
             $html .= ' "> '.$user_filename.' </a>';
             $html .= '<span class="forum_attach_comment" >'.$attachment['comment'].'</span>';
             if (($current_forum['allow_edit'] == 1 && $post['user_id'] == $userId) ||
-                (api_is_allowed_to_edit(false, true) && !(api_is_course_coach() && $current_forum['session_id'] != $sessionId))
+                (api_is_allowed_to_edit(false, true) && !(api_is_session_general_coach() && $current_forum['session_id'] != $sessionId))
             ) {
                 $html .= '&nbsp;&nbsp;<a href="'.api_get_self().'?'.api_get_cidreq().'&action=delete_attach&id_attach='
                     . $attachment['iid'].'&forum='.$clean_forum_id.'&thread='.$clean_thread_id

+ 3 - 3
main/forum/viewthread_threaded.inc.php

@@ -242,7 +242,7 @@ if (
         $row['user_id'] == $_user['user_id']
     ) || (
         api_is_allowed_to_edit(false, true) && !(
-            api_is_course_coach() &&
+            api_is_session_general_coach() &&
             $current_forum['session_id'] != $sessionId
         )
     )
@@ -279,7 +279,7 @@ if (!empty($my_post) && is_array($my_post)) {
 if (
     (isset($groupInfo['iid']) && GroupManager::is_tutor_of_group(api_get_user_id(), $groupInfo)) ||
     api_is_allowed_to_edit(false, true) &&
-    !(api_is_course_coach() && $current_forum['session_id'] != $sessionId)
+    !(api_is_session_general_coach() && $current_forum['session_id'] != $sessionId)
 ) {
     if ($locked == false) {
         echo "<a href=\"".api_get_self()."?".api_get_cidreq().
@@ -434,7 +434,7 @@ if (!empty($attachment_list) && is_array($attachment_list)) {
 
         if (
             ($current_forum['allow_edit'] == 1 && $rows[$display_post_id]['user_id'] == $_user['user_id']) ||
-            (api_is_allowed_to_edit(false, true) && !(api_is_course_coach() && $current_forum['session_id'] != $sessionId))
+            (api_is_allowed_to_edit(false, true) && !(api_is_session_general_coach() && $current_forum['session_id'] != $sessionId))
         ) {
             echo '&nbsp;&nbsp;<a href="'.api_get_self().'?'.
                 api_get_cidreq().'&action=delete_attach&id_attach='.$attachment['id'].'&forum='.$forumId.

+ 1 - 1
main/gradebook/gradebook_flatview.php

@@ -210,7 +210,7 @@ if (isset($_GET['print'])) {
 if (!empty($_GET['export_report']) &&
     $_GET['export_report'] == 'export_report'
 ) {
-    if (api_is_platform_admin() || api_is_course_admin() || api_is_course_coach() || $isDrhOfCourse) {
+    if (api_is_platform_admin() || api_is_course_admin() || api_is_session_general_coach() || $isDrhOfCourse) {
         $user_id = null;
 
         if (empty($_SESSION['export_user_fields'])) {

+ 1 - 1
main/inc/ajax/announcement.ajax.php

@@ -24,7 +24,7 @@ switch ($action) {
 
             $list = explode(',', $_REQUEST['id']);
             foreach ($list as $itemId) {
-                if (!api_is_course_coach() || api_is_element_in_the_session(TOOL_ANNOUNCEMENT, $itemId)) {
+                if (!api_is_session_general_coach() || api_is_element_in_the_session(TOOL_ANNOUNCEMENT, $itemId)) {
                     AnnouncementManager::delete_announcement($courseInfo, $itemId);
                 }
             }

+ 1 - 0
main/inc/ajax/course_home.ajax.php

@@ -474,6 +474,7 @@ switch ($action) {
         $start = $limit * $page - $limit;
         $course_list = SessionManager::get_course_list_by_session_id($session_id);
         $count = 0;
+        $temp = [];
 
         foreach ($course_list as $item) {
             if (isset($course_id) && !empty($course_id)) {

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

@@ -1620,7 +1620,7 @@ class AnnouncementManager
                 // we can edit if : we are the teacher OR the element belongs to
                 // the session we are coaching OR the option to allow users to edit is on
                 if (api_is_allowed_to_edit(false, true) ||
-                    (api_is_course_coach() && api_is_element_in_the_session(TOOL_ANNOUNCEMENT, $myrow['id']))
+                    (api_is_session_general_coach() && api_is_element_in_the_session(TOOL_ANNOUNCEMENT, $myrow['id']))
                     || (api_get_course_setting('allow_user_edit_announcement') && !api_is_anonymous())
                 ) {
                     $modify_icons = "<a href=\"".$actionUrl."&action=modify&id=".$myrow['id']."\">".

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

@@ -1678,7 +1678,7 @@ class CourseChatUtils
         }
         $history .= '</div>';
 
-        if ($isMaster || $GLOBALS['is_courseCoach']) {
+        if ($isMaster || $GLOBALS['is_session_general_coach']) {
             $history .= '
                 <div id="clear-chat">
                     <button type="button" id="chat-reset" class="btn btn-danger btn-sm">

+ 67 - 119
main/inc/lib/api.lib.php

@@ -5,6 +5,7 @@ use ChamiloSession as Session;
 use Chamilo\CourseBundle\Entity\CItemProperty;
 use Chamilo\UserBundle\Entity\User;
 use Symfony\Component\Finder\Finder;
+use Chamilo\CoreBundle\Entity\SettingsCurrent;
 
 /**
  * This is a code library for Chamilo.
@@ -2624,15 +2625,17 @@ function api_is_course_admin()
 
 /**
  * Checks whether the current user is a course coach
- * @return bool     True if current user is a course coach
+ * Based on the presence of user in session.id_coach (session general coach)
+ * @return bool True if current user is a course coach
  */
-function api_is_course_coach()
+function api_is_session_general_coach()
 {
-    return Session::read('is_courseCoach');
+    return Session::read('is_session_general_coach');
 }
 
 /**
  * Checks whether the current user is a course tutor
+ * Based on the presence of user in session_rel_course_rel_user.user_id with status = 2
  * @return bool     True if current user is a course tutor
  */
 function api_is_course_tutor()
@@ -5353,119 +5356,76 @@ function &api_get_settings($cat = null, $ordering = 'list', $access_url = 1, $ur
 }
 
 /**
- * Sets a platform configuration setting to a given value
- * @param string    The value we want to record
- * @param string    The variable name we want to insert
- * @param string    The subkey for the variable we want to insert
- * @param string    The type for the variable we want to insert
- * @param string    The category for the variable we want to insert
- * @param string    The title
- * @param string    The comment
- * @param string    The scope
- * @param string    The subkey text
- * @param int       The access_url for which this parameter is valid
- * @param int       The changeability of this setting for non-master urls
- * @param string $val
- * @param string $var
- * @param string $sk
- * @param string $c
- * @return boolean  true on success, false on failure
+ * @param string $value The value we want to record
+ * @param string $variable The variable name we want to insert
+ * @param string $subKey The subkey for the variable we want to insert
+ * @param string $type The type for the variable we want to insert
+ * @param string $category The category for the variable we want to insert
+ * @param string $title The title
+ * @param string $comment The comment
+ * @param string $scope The scope
+ * @param string $subKeyText The subkey text
+ * @param int $accessUrlId The access_url for which this parameter is valid
+ * @param int $visiblity The changeability of this setting for non-master urls
+ * @return int The setting ID
  */
 function api_add_setting(
-    $val,
-    $var,
-    $sk = null,
+    $value,
+    $variable,
+    $subKey = null,
     $type = 'textfield',
-    $c = null,
-    $title = '',
-    $com = '',
-    $sc = null,
-    $skt = null,
-    $a = 1,
-    $v = 0
+    $category = null,
+    $title = null,
+    $comment = null,
+    $scope = null,
+    $subKeyText = null,
+    $accessUrlId = 1,
+    $visiblity = 0
 ) {
-    if (empty($var) || !isset($val)) { return false; }
-    $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
-    $var = Database::escape_string($var);
-    $val = Database::escape_string($val);
-    $a = (int) $a;
-    if (empty($a)) { $a = 1; }
-    // Check if this variable doesn't exist already
-    $select = "SELECT id FROM $t_settings WHERE variable = '$var' ";
-    if (!empty($sk)) {
-        $sk = Database::escape_string($sk);
-        $select .= " AND subkey = '$sk'";
-    }
-    if ($a > 1) {
-        $select .= " AND access_url = $a";
-    } else {
-        $select .= " AND access_url = 1 ";
+    $em = Database::getManager();
+    $settingRepo = $em->getRepository('ChamiloCoreBundle:SettingsCurrent');
+
+    $accessUrlId = (int) $accessUrlId ?: 1;
+
+    $criteria = ['variable' => $variable, 'accessUrl' => $accessUrlId];
+
+    if (!empty($subKey)) {
+        $criteria['subkey'] = $subKey;
     }
-    $res = Database::query($select);
-    if (Database::num_rows($res) > 0) { // Found item for this access_url.
-        $row = Database::fetch_array($res);
-        Database::update(
-            $t_settings,
-            array('selected_value' => $val),
-            array('id = ?' => array($row['id']))
-        );
-        return $row['id'];
+
+    // Check if this variable doesn't exist already
+    /** @var SettingsCurrent $setting */
+    $setting = $settingRepo->findOneBy($criteria);
+
+    if ($setting) {
+        $setting->setSelectedValue($value);
+
+        $em->persist($setting);
+        $em->flush();
+
+        return $setting->getId();
     }
 
     // Item not found for this access_url, we have to check if the whole thing is missing
     // (in which case we ignore the insert) or if there *is* a record but just for access_url = 1
-    $insert = "INSERT INTO $t_settings ".
-                "(variable,selected_value,".
-                "type,category,".
-                "subkey,title,".
-                "comment,scope,".
-                "subkeytext,access_url,access_url_changeable)".
-                " VALUES ('$var','$val',";
-    if (isset($type)) {
-        $type = Database::escape_string($type);
-        $insert .= "'$type',";
-    } else {
-        $insert .= "NULL,";
-    }
-    if (isset($c)) { // Category
-        $c = Database::escape_string($c);
-        $insert .= "'$c',";
-    } else {
-        $insert .= "NULL,";
-    }
-    if (isset($sk)) { // Subkey
-        $sk = Database::escape_string($sk);
-        $insert .= "'$sk',";
-    } else {
-        $insert .= "NULL,";
-    }
-    if (isset($title)) { // Title
-        $title = Database::escape_string($title);
-        $insert .= "'$title',";
-    } else {
-        $insert .= "NULL,";
-    }
-    if (isset($com)) { // Comment
-        $com = Database::escape_string($com);
-        $insert .= "'$com',";
-    } else {
-        $insert .= "NULL,";
-    }
-    if (isset($sc)) { // Scope
-        $sc = Database::escape_string($sc);
-        $insert .= "'$sc',";
-    } else {
-        $insert .= "NULL,";
-    }
-    if (isset($skt)) { // Subkey text
-        $skt = Database::escape_string($skt);
-        $insert .= "'$skt',";
-    } else {
-        $insert .= "NULL,";
-    }
-    $insert .= "$a,$v)";
-    $res = Database::query($insert);
-    return $res;
+    $setting = new SettingsCurrent();
+    $setting
+        ->setVariable($variable)
+        ->setSelectedValue($value)
+        ->setType($type)
+        ->setCategory($category)
+        ->setSubkey($subKey)
+        ->setTitle($title)
+        ->setComment($comment)
+        ->setScope($scope)
+        ->setSubkeytext($subKeyText)
+        ->setAccessUrl($accessUrlId)
+        ->setAccessUrlChangeable($visiblity);
+
+    $em->persist($setting);
+    $em->flush();
+
+    return $setting->getId();
 }
 
 /**
@@ -5537,7 +5497,6 @@ function api_is_course_visible_for_user($userid = null, $cid = null) {
         // This user has got a recorded state for this course.
         $cuData = Database::fetch_array($result);
         $is_courseMember = true;
-        $is_courseTutor = ($cuData['is_tutor'] == 1);
         $is_courseAdmin = ($cuData['status'] == 1);
     }
 
@@ -5562,17 +5521,11 @@ function api_is_course_visible_for_user($userid = null, $cid = null) {
 
         if ($row[0]['id_coach'] == $userid) {
             $is_courseMember = true;
-            $is_courseTutor = true;
             $is_courseAdmin = false;
-            $is_courseCoach = true;
-            $is_sessionAdmin = false;
         }
         elseif ($row[0]['session_admin_id'] == $userid) {
             $is_courseMember = false;
-            $is_courseTutor = false;
             $is_courseAdmin = false;
-            $is_courseCoach = false;
-            $is_sessionAdmin = true;
         } else {
             // Check if the current user is the course coach.
             $sql = "SELECT 1
@@ -5586,9 +5539,6 @@ function api_is_course_visible_for_user($userid = null, $cid = null) {
             //if ($row = Database::fetch_array($result)) {
             if (Database::num_rows($result) > 0) {
                 $is_courseMember = true;
-                $is_courseTutor = true;
-                $is_courseCoach = true;
-                $is_sessionAdmin = false;
 
                 $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
 
@@ -5616,9 +5566,7 @@ function api_is_course_visible_for_user($userid = null, $cid = null) {
                     // This user haa got a recorded state for this course.
                     while ($row = Database::fetch_array($result)) {
                         $is_courseMember = true;
-                        $is_courseTutor = false;
                         $is_courseAdmin = false;
-                        $is_sessionAdmin = false;
                     }
                 }
             }

+ 11 - 1
main/inc/lib/banner.lib.php

@@ -167,7 +167,17 @@ function getCustomTabs()
     $result = Database::query($sql);
     $customTabs = array();
     while ($row = Database::fetch_assoc($result)) {
-        $customTabs[] = $row;
+        $shouldAdd = true;
+
+        if (strpos($row['subkey'], Plugin::TAB_FILTER_NO_STUDENT) !== false && api_is_student()) {
+            $shouldAdd = false;
+        } elseif (strpos($row['subkey'], Plugin::TAB_FILTER_ONLY_STUDENT) !== false && !api_is_student()) {
+            $shouldAdd = false;
+        }
+
+        if ($shouldAdd) {
+            $customTabs[] = $row;
+        }
     }
 
     return $customTabs;

+ 2 - 1
main/inc/lib/course_home.lib.php

@@ -951,7 +951,8 @@ class CourseHome
                         !file_exists(api_get_path(SYS_CODE_PATH).'img/icons/64/'.$tool['image'])) {
                         $tool['image'] = 'plugins.png';
                     }
-                    $tool_link_params['href'] = api_get_path(WEB_PLUGIN_PATH).$tool['original_link'].'?'.api_get_cidreq();
+                    $tool_link_params['href'] = api_get_path(WEB_PLUGIN_PATH)
+                        .$tool['original_link'].$qm_or_amp.api_get_cidreq();
                 }
 
                 $icon = Display::return_icon(

+ 3 - 3
main/inc/lib/display.lib.php

@@ -739,14 +739,14 @@ class Display
         }
 
         $size_extra = $size.'/';
-
-        // Checking the img/ folder
         $icon = $w_code_path.'img/'.$image;
-
         $theme = 'themes/chamilo/icons/';
 
         if ($loadThemeIcon) {
             $theme = 'themes/'.api_get_visual_theme().'/icons/';
+            if (is_file($alternateCssPath.$theme.$image)) {
+                $icon = $alternateWebCssPath.$theme.$image;
+            }
             // Checking the theme icons folder example: app/Resources/public/css/themes/chamilo/icons/XXX
             if (is_file($alternateCssPath.$theme.$size_extra.$image)) {
                 $icon = $alternateWebCssPath.$theme.$size_extra.$image;

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

@@ -2027,7 +2027,7 @@ class GroupManager
             return true;
         }
 
-        if (api_is_course_coach() && $groupInfo['session_id'] == $sessionId) {
+        if (api_is_session_general_coach() && $groupInfo['session_id'] == $sessionId) {
             return true;
         }
 
@@ -2267,7 +2267,7 @@ class GroupManager
             $url = api_get_path(WEB_CODE_PATH).'group/';
             // Edit-links
             if (api_is_allowed_to_edit(false, true) &&
-                !(api_is_course_coach() && intval($this_group['session_id']) != $session_id)
+                !(api_is_session_general_coach() && intval($this_group['session_id']) != $session_id)
             ) {
                 $edit_actions = '<a href="'.$url.'settings.php?'.api_get_cidreq(true, false).'&gidReq='.$this_group['id'].'"  title="'.get_lang('Edit').'">'.
                     Display::return_icon('edit.png', get_lang('EditGroup'), '', ICON_SIZE_SMALL).'</a>&nbsp;';

+ 7 - 7
main/inc/lib/login.lib.php

@@ -361,7 +361,7 @@ class Login
      * @global type $_courseUser
      * @global type $is_courseAdmin
      * @global type $is_courseTutor
-     * @global type $is_courseCoach
+     * @global type $is_session_general_coach
      * @global type $is_courseMember
      * @global type $is_sessionAdmin
      * @global type $is_allowed_in_course
@@ -380,7 +380,7 @@ class Login
 
         global $is_courseAdmin; //course teacher
         global $is_courseTutor; //course teacher - some rights
-        global $is_courseCoach; //course coach
+        global $is_session_general_coach; //course coach
         global $is_courseMember; //course student
         global $is_sessionAdmin;
         global $is_allowed_in_course;
@@ -635,7 +635,7 @@ class Login
                             $is_courseMember = false;
                             $is_courseTutor = false;
                             $is_courseAdmin = false;
-                            $is_courseCoach = false;
+                            $is_session_general_coach = false;
                             $is_sessionAdmin = true;
                         } else {
                             //Im a coach or a student?
@@ -656,7 +656,7 @@ class Login
                                     case '2': // coach - teacher
                                         $is_courseMember = true;
                                         $is_courseTutor = true;
-                                        $is_courseCoach = true;
+                                        $is_session_general_coach = true;
                                         $is_sessionAdmin = false;
 
                                         if (api_get_setting('extend_rights_for_coach') == 'true') {
@@ -699,7 +699,7 @@ class Login
                 $is_courseMember = false;
                 $is_courseAdmin = false;
                 $is_courseTutor = false;
-                $is_courseCoach = false;
+                $is_session_general_coach = false;
                 $is_sessionAdmin = false;
             }
 
@@ -758,14 +758,14 @@ class Login
             Session::write('is_courseAdmin', $is_courseAdmin);
             Session::write('is_courseMember', $is_courseMember);
             Session::write('is_courseTutor', $is_courseTutor);
-            Session::write('is_courseCoach', $is_courseCoach);
+            Session::write('is_session_general_coach', $is_session_general_coach);
             Session::write('is_allowed_in_course', $is_allowed_in_course);
             Session::write('is_sessionAdmin', $is_sessionAdmin);
         } else {
             // continue with the previous values
             $is_courseAdmin = Session::read('is_courseAdmin');
             $is_courseTutor = Session::read('is_courseTutor');
-            $is_courseCoach = Session::read('is_courseCoach');
+            $is_session_general_coach = Session::read('is_session_general_coach');
             $is_courseMember = Session::read('is_courseMember');
             $is_allowed_in_course = Session::read('is_allowed_in_course');
         }

+ 100 - 44
main/inc/lib/plugin.class.php

@@ -1,6 +1,8 @@
 <?php
 /* For licensing terms, see /license.txt */
 
+use Chamilo\CourseBundle\Entity\CTool;
+
 /**
  * Class Plugin
  * Base class for plugins
@@ -38,9 +40,9 @@ class Plugin
      * main/img/icons/64/plugin_name_na.png
      * @example
      * $course_settings = array(
-          array('name' => 'big_blue_button_welcome_message',  'type' => 'text'),
-          array('name' => 'big_blue_button_record_and_store', 'type' => 'checkbox')
-       );
+    array('name' => 'big_blue_button_welcome_message',  'type' => 'text'),
+    array('name' => 'big_blue_button_record_and_store', 'type' => 'checkbox')
+    );
      */
     public $course_settings = array();
     /**
@@ -49,6 +51,9 @@ class Plugin
      */
     public $course_settings_callback = false;
 
+    const TAB_FILTER_NO_STUDENT = '::no-student';
+    const TAB_FILTER_ONLY_STUDENT = '::only-student';
+
     /**
      * Default constructor for the plugin class. By default, it only sets
      * a few attributes of the object
@@ -291,11 +296,12 @@ class Plugin
 
     /**
      * Returns an array with the global settings for this plugin
+     * @param bool $forceFromDB Optional. Force get settings from the database
      * @return array Plugin settings as an array
      */
-    public function get_settings()
+    public function get_settings($forceFromDB = false)
     {
-        if (empty($this->settings)) {
+        if (empty($this->settings) || $forceFromDB) {
             $settings = api_get_settings_params(
                 array(
                     "subkey = ? AND category = ? AND type = ? " => array($this->get_name(), 'Plugins', 'setting')
@@ -468,41 +474,62 @@ class Plugin
         }
 
         // Stop here if we don't want a tool link on the course homepage
-        if (!$add_tool_link) {
+        if (!$add_tool_link || $this->addCourseTool == false) {
             return true;
         }
 
-        if ($this->addCourseTool == false) {
-            return true;
+        //Add an icon in the table tool list
+        $this->createLinkToCourseTool($plugin_name, $courseId);
+    }
+
+    /**
+     * Add an link for a course tool
+     * @param string $name The tool name
+     * @param int $courseId The course ID
+     * @param string $iconName Optional. Icon file name
+     * @param string $link Optional. Link URL
+     * @return \Chamilo\CourseBundle\Entity\CTool|null
+     */
+    protected function createLinkToCourseTool($name, $courseId, $iconName = null, $link = null)
+    {
+        if (!$this->addCourseTool) {
+            return null;
         }
 
-        //Add an icon in the table tool list
-        $table = Database::get_course_table(TABLE_TOOL_LIST);
-        $sql = "SELECT name FROM $table
-                WHERE c_id = $courseId AND name = '$plugin_name' ";
-        $result = Database::query($sql);
-        if (!Database::num_rows($result)) {
-            $tool_link = "$plugin_name/start.php";
-            $cToolId = AddCourse::generateToolId($courseId);
+        $em = Database::getManager();
 
-            Database::insert(
-                $table,
-                [
-                    'id' => $cToolId,
-                    'c_id' => $courseId,
-                    'name' => $plugin_name,
-                    'link' => $tool_link,
-                    'image' => "$plugin_name.png",
-                    'visibility' => 1,
-                    'admin' => 0,
-                    'address' => 'squaregrey.gif',
-                    'added_tool' => 0,
-                    'target' => '_self',
-                    'category' => 'plugin',
-                    'session_id' => 0
-                ]
-            );
+        /** @var CTool $tool */
+        $tool = $em
+            ->getRepository('ChamiloCourseBundle:CTool')
+            ->findOneBy([
+                'name' => $name,
+                'cId' => $courseId
+            ]);
+
+        if (!$tool) {
+            $cToolId = AddCourse::generateToolId($courseId);
+            $pluginName = $this->get_name();
+
+            $tool = new CTool();
+            $tool
+                ->setId($cToolId)
+                ->setCId($courseId)
+                ->setName($name)
+                ->setLink($link ?: "$pluginName/start.php")
+                ->setImage($iconName ?: "$pluginName.png")
+                ->setVisibility(true)
+                ->setAdmin(0)
+                ->setAddress('squaregrey.gif')
+                ->setAddedTool(false)
+                ->setTarget('_self')
+                ->setCategory('plugin')
+                ->setSessionId(0);
+
+            $em->persist($tool);
+            $em->flush();
         }
+
+        return $tool;
     }
 
     /**
@@ -611,14 +638,14 @@ class Plugin
 
     }
 
-   /**
-    * Add a tab to platform
-    * @param string   $tabName
-    * @param string   $url
-    *
-    * @return false|string
-    */
-    public function addTab($tabName, $url)
+    /**
+     * Add a tab to platform
+     * @param string $tabName
+     * @param string $url
+     * @param string $userFilter Optional. Filter tab type
+     * @return false|string
+     */
+    public function addTab($tabName, $url, $userFilter = null)
     {
         $sql = "SELECT * FROM settings_current
                 WHERE
@@ -650,6 +677,17 @@ class Plugin
 
         // End Check
         $subkey = 'custom_tab_'.$tabNum;
+
+        if (!empty($userFilter)) {
+            switch ($userFilter) {
+                case self::TAB_FILTER_NO_STUDENT:
+                    //no break
+                case self::TAB_FILTER_ONLY_STUDENT:
+                    $subkey .= $userFilter;
+                    break;
+            }
+        }
+
         $attributes = array(
             'variable' => 'show_tabs',
             'subkey' => $subkey,
@@ -707,9 +745,16 @@ class Plugin
                 $tabs = Database::store_result($result, 'ASSOC');
                 $i = 1;
                 foreach ($tabs as $row) {
-                    $attributes = array(
-                        'subkey' => 'custom_tab_'.$i
-                    );
+                    $newSubKey = "custom_tab_$i";
+
+                    if (strpos($row['subkey'], self::TAB_FILTER_NO_STUDENT) !== false) {
+                        $newSubKey .= self::TAB_FILTER_NO_STUDENT;
+                    } elseif (strpos($row['subkey'], self::TAB_FILTER_ONLY_STUDENT) !== false) {
+                        $newSubKey .= self::TAB_FILTER_ONLY_STUDENT;
+                    }
+
+                    $attributes = ['subkey' => $newSubKey];
+
                     $this->updateTab($row['subkey'], $attributes);
                     $i++;
                 }
@@ -803,4 +848,15 @@ class Plugin
         }
         return false;
     }
+
+    /**
+     * Allow make some actions after configure the plugin parameters
+     * This function is called from main/admin/configure_plugin.php page
+     * when saving the plugin parameters
+     * @return \Plugin
+     */
+    public function performActionsAfterConfigure()
+    {
+        return $this;
+    }
 }

+ 5 - 18
main/inc/lib/sessionmanager.lib.php

@@ -3497,29 +3497,16 @@ class SessionManager
             $imgPath = Display::return_icon(
                 'session_default_small.png',
                 null,
-                null,
-                null,
-                null,
+                [],
+                ICON_SIZE_SMALL,
+                false,
                 true
             );
 
-            $tableExtraFields = Database::get_main_table(TABLE_EXTRA_FIELD);
-            $sql = "SELECT id FROM ".$tableExtraFields."
-                    WHERE extra_field_type = 3 AND variable='image'";
-            $resultField = Database::query($sql);
-            $imageFieldId = Database::fetch_assoc($resultField);
-
             while ($row = Database::fetch_array($result)) {
+                $imageFilename = \ExtraField::FIELD_TYPE_FILE_IMAGE.'_'.$row['id'].'.png';
 
-                $row['image'] = null;
-                $sessionImage = $sysUploadPath.$imageFieldId['id'].'_'.$row['id'].'.png';
-
-                if (is_file($sessionImage)) {
-                    $sessionImage = $webUploadPath.$imageFieldId['id'].'_'.$row['id'].'.png';
-                    $row['image'] = $sessionImage;
-                } else {
-                    $row['image'] = $imgPath;
-                }
+                $row['image'] = is_file($sysUploadPath.$imageFilename) ? $webUploadPath.$imageFilename : $imgPath;
 
                 if ($row['display_start_date'] == '0000-00-00 00:00:00' || $row['display_start_date'] == '0000-00-00') {
                     $row['display_start_date'] = null;

+ 4 - 1
main/inc/lib/usermanager.lib.php

@@ -2653,6 +2653,9 @@ class UserManager
         // Get the list of sessions per user
         $now = new DateTime('now', new DateTimeZone('UTC'));
 
+        // LEFT JOIN is used for session_rel_course_rel_user because an inner
+        // join would not catch session-courses where the user is general
+        // session coach but which do not have students nor coaches registered
         $dql = "SELECT DISTINCT
                     s.id,
                     s.name,
@@ -2665,7 +2668,7 @@ class UserManager
                     s.coachAccessStartDate AS coach_access_start_date,
                     s.coachAccessEndDate AS coach_access_end_date
                 FROM ChamiloCoreBundle:Session AS s
-                INNER JOIN ChamiloCoreBundle:SessionRelCourseRelUser AS scu WITH scu.session = s
+                LEFT JOIN ChamiloCoreBundle:SessionRelCourseRelUser AS scu WITH scu.session = s
                 INNER JOIN ChamiloCoreBundle:AccessUrlRelSession AS url WITH url.sessionId = s.id
                 LEFT JOIN ChamiloCoreBundle:SessionCategory AS sc WITH s.category = sc
                 WHERE (scu.user = :user OR s.generalCoach = :user) AND url.accessUrlId = :url

+ 13 - 13
main/inc/local.inc.php

@@ -1079,11 +1079,11 @@ $user_id = isset($_user['user_id']) ? $_user['user_id'] : null;
 /*$is_courseAdmin     = false; //course teacher
 $is_courseTutor     = false; //course teacher - some rights
 $is_courseMember    = false; //course student
-$is_courseCoach     = false; //course coach
+$is_session_general_coach     = false; //course coach
 */
 // Course - User permissions
 $is_sessionAdmin = false;
-$is_courseCoach = false; //course coach
+$is_session_general_coach = false; //course coach
 $is_courseAdmin = false;
 $is_courseTutor = false;
 $is_courseMember = false;
@@ -1223,7 +1223,7 @@ if ((isset($uidReset) && $uidReset) || (isset($cidReset) && $cidReset)) {
                     $is_courseMember     = false;
                     $is_courseTutor      = false;
                     $is_courseAdmin      = false;
-                    $is_courseCoach      = false;
+                    $is_session_general_coach      = false;
                     $is_sessionAdmin     = true;
                 } else {
                     // Am I a session coach for this session?
@@ -1239,7 +1239,7 @@ if ((isset($uidReset) && $uidReset) || (isset($cidReset) && $cidReset)) {
                     if (Database::num_rows($result)) {
                         $is_courseMember = true;
                         $is_courseTutor = false;
-                        $is_courseCoach = true;
+                        $is_session_general_coach = true;
                         $is_sessionAdmin = false;
                     } else {
                         // Am I a course coach or a student?
@@ -1261,7 +1261,7 @@ if ((isset($uidReset) && $uidReset) || (isset($cidReset) && $cidReset)) {
                                 case '2': // coach - teacher
                                     $is_courseMember = true;
                                     $is_courseTutor = true;
-                                    $is_courseCoach = true;
+                                    $is_session_general_coach = false;
                                     $is_sessionAdmin = false;
 
                                     if (api_get_setting('extend_rights_for_coach') == 'true') {
@@ -1274,7 +1274,7 @@ if ((isset($uidReset) && $uidReset) || (isset($cidReset) && $cidReset)) {
                                     $is_courseMember = true;
                                     $is_courseTutor = false;
                                     $is_courseAdmin = false;
-                                    $is_courseCoach = false;
+                                    $is_session_general_coach = false;
                                     $is_sessionAdmin = false;
 
                                     break;
@@ -1284,7 +1284,7 @@ if ((isset($uidReset) && $uidReset) || (isset($cidReset) && $cidReset)) {
                                     $is_courseTutor = false;
                                     $is_courseAdmin = false;
                                     $is_sessionAdmin = false;
-                                    $is_courseCoach = false;
+                                    $is_session_general_coach = false;
                                     break;
                             }
                         } else {
@@ -1293,7 +1293,7 @@ if ((isset($uidReset) && $uidReset) || (isset($cidReset) && $cidReset)) {
                             $is_courseTutor = false;
                             $is_courseAdmin = false;
                             $is_sessionAdmin = false;
-                            $is_courseCoach = false;
+                            $is_session_general_coach = false;
                         }
                     }
                 }
@@ -1305,7 +1305,7 @@ if ((isset($uidReset) && $uidReset) || (isset($cidReset) && $cidReset)) {
                         if (isset($sessionInfo['course_list'][$_course['real_id']])) {
                             $is_courseMember = true;
                             $is_courseTutor = false;
-                            $is_courseCoach = false;
+                            $is_session_general_coach = false;
                             $is_sessionAdmin = false;
                         }
                     }
@@ -1348,7 +1348,7 @@ if ((isset($uidReset) && $uidReset) || (isset($cidReset) && $cidReset)) {
         $is_courseMember = false;
         $is_courseAdmin = false;
         $is_courseTutor = false;
-        $is_courseCoach = false;
+        $is_session_general_coach = false;
         $is_sessionAdmin = false;
     }
 
@@ -1417,7 +1417,7 @@ if ((isset($uidReset) && $uidReset) || (isset($cidReset) && $cidReset)) {
                 $is_courseMember = false;
                 $is_courseAdmin = false;
                 $is_courseTutor = false;
-                $is_courseCoach = false;
+                $is_session_general_coach = false;
                 $is_sessionAdmin = false;
                 $is_allowed_in_course = false;
             }
@@ -1456,14 +1456,14 @@ if ((isset($uidReset) && $uidReset) || (isset($cidReset) && $cidReset)) {
             $is_allowed_in_course = true;
         }
     }
-    Session::write('is_courseCoach', $is_courseCoach);
+    Session::write('is_session_general_coach', $is_session_general_coach);
     Session::write('is_allowed_in_course', $is_allowed_in_course);
     Session::write('is_sessionAdmin', $is_sessionAdmin);
 } else {
     // Continue with the previous values
     $is_courseAdmin = isset($_SESSION['is_courseAdmin']) ? $_SESSION['is_courseAdmin'] : false;
     $is_courseTutor = isset($_SESSION['is_courseTutor']) ? $_SESSION['is_courseTutor'] : false;
-    $is_courseCoach = isset($_SESSION['is_courseCoach']) ? $_SESSION['is_courseCoach'] : false;
+    $is_session_general_coach = isset($_SESSION['is_session_general_coach']) ? $_SESSION['is_session_general_coach'] : false;
     $is_courseMember = isset($_SESSION['is_courseMember']) ? $_SESSION['is_courseMember'] : false;
     $is_allowed_in_course = isset($_SESSION ['is_allowed_in_course']) ? $_SESSION ['is_allowed_in_course'] : false;
 }

+ 0 - 1
main/lang/arabic/trad4all.inc.php

@@ -2490,7 +2490,6 @@ $ApprovalForNewAccount = "إعتماد الحسابات الجديدة";
 $ManageUser = "Manage user";
 $SubscribeUserToCourseAsTeacher = "سجل المستخدمين كمدرسين في هذا المقرر";
 $PasswordEncryptedForSecurity = "كلمة السر مشفره لأسباب أمنية. لذا وبعد الضغط على الوصلة التي ستصلك عن طريق البريد الالكتروني سترسل إليكم مرة أخرى مع كلمة السر الخاصة بك";
-$SystemUnableToSendEmailContact = "النظام غير قادر على إرسال البريد الإلكتروني للاتصال";
 $OpenIDCouldNotBeFoundPleaseRegister = "عفواً ، هذه الهوية المفتوحة ، لا يمكن العثور عليها في قاعدة بياناتنا . من فضلك قم بتسجيل حساب جديد . أما إذا كان لديك بالفعل حساب معنا ، يرجى تعديل ملفك الشخصي من داخل حسابك لإضافة هذه الهوية .";
 $UsernameMaxXCharacters = "يحتاج اسم المستخدم إلى أحرف طويلة ليكن بأقصى حد";
 $PictureUploaded = "تم أرسال  الصورة";

+ 0 - 1
main/lang/asturian/trad4all.inc.php

@@ -3449,7 +3449,6 @@ $ApprovalForNewAccount = "Aprobar una cuenta nueva";
 $ManageUser = "Xestión d'usuarios";
 $SubscribeUserToCourseAsTeacher = "Matricular usuarios como profesores nesti cursu";
 $PasswordEncryptedForSecurity = "La so seña ta encriptada pola so seguridá. Poro, si calcó nel enllaz que rexenera la seña, va unviase-y un corréu nuevu cola so seña.";
-$SystemUnableToSendEmailContact = "El sistema nun pudo unvia-y el corréu electrónicu";
 $OpenIDCouldNotBeFoundPleaseRegister = "Esti OpenID nun s'atopa na base datos. Por favor, rexístrese pa tener una cuenta. Si yá la tien, edite'l so perfil y ameste esti OpenID.";
 $UsernameMaxXCharacters = "El nome d'usuariu pue tener, como muncho, %s carauteres";
 $PictureUploaded = "La so imaxe unvióse";

+ 0 - 1
main/lang/basque/trad4all.inc.php

@@ -3554,7 +3554,6 @@ $ApprovalForNewAccount = "Kontu berria onartu da";
 $ManageUser = "Kudeatu erabiltzailea";
 $SubscribeUserToCourseAsTeacher = "Inskribatu irakasleak";
 $PasswordEncryptedForSecurity = "Segurtasuna dela eta, pasahitza enkriptatuta dago. Horrexegatik, pasahitza berrezartzeko lotura sakatu ondoren, zure pasahitza jasotzen duen mezu elektronikoa bidaliko zaizu.";
-$SystemUnableToSendEmailContact = "Plataforma honek ezin izan dizu mezu elektronikoa bidali";
 $OpenIDCouldNotBeFoundPleaseRegister = "OpenID hau ezin izan da gure datu basean aurkitu. Mesedez, kontu berria eskuratzeko, erregistratu. Jadanik baduzu kontu bat gurekin, editatu kontuaren barruan duzun profila, OpenID hau gehitzeko.";
 $UsernameMaxXCharacters = "Erabiltzailearen izenak, gehienez, %s karaktere eduki ditzake.";
 $PictureUploaded = "Zure irudia kargatu da";

+ 0 - 1
main/lang/brazilian/trad4all.inc.php

@@ -3971,7 +3971,6 @@ $ApprovalForNewAccount = "Aprovação para um novo registro";
 $ManageUser = "Administrar usuário";
 $SubscribeUserToCourseAsTeacher = "Registra usuários neste curso como professor";
 $PasswordEncryptedForSecurity = "A sua senha está encriptada por razões de segurança. Assim, depois de clicar no link será enviado um e-mail para você com sua senha.";
-$SystemUnableToSendEmailContact = "Não foi possível enviar a senha perdida/esquecida. Entre em contato com o administrador da plataforma clicando no seguinte link:";
 $OpenIDCouldNotBeFoundPleaseRegister = "Este OpenID não foi encontrado na nossa base de dados. Por favor, registe-se novamente. Se já está registado, conecte-se, edite o seu perfil no interior da sua conta e acrescente este OpenID.";
 $UsernameMaxXCharacters = "O Nome de usuário pode ter no máximo %s caracteres";
 $PictureUploaded = "A foto foi enviada com sucesso";

+ 0 - 1
main/lang/bulgarian/trad4all.inc.php

@@ -3422,7 +3422,6 @@ $ApprovalForNewAccount = "Одобряване на нова регистрац
 $ManageUser = "Администриране на потребител";
 $SubscribeUserToCourseAsTeacher = "Записване на потребители в курса като преподаватели";
 $PasswordEncryptedForSecurity = "Вашата парола е закодирана поради изисквания за сигурност. Щракнете връзката и ще получите e-mail с нова парола.";
-$SystemUnableToSendEmailContact = "Системата не може да изпрати e-mail по дадения адрес за контакт";
 $OpenIDCouldNotBeFoundPleaseRegister = "Предоставеният OpenID не може да бъде намерен в нашата база от данни. Ако вече имате акаунт при нас, моля, редактирайте потребителския си профил като добавите този OpenID.";
 $UsernameMaxXCharacters = "Потребителското име трябва да е с максимум %s букви.";
 $PictureUploaded = "Вашата снимка е качена.";

+ 0 - 1
main/lang/catalan/trad4all.inc.php

@@ -3900,7 +3900,6 @@ $ApprovalForNewAccount = "Validació d'un nou compte";
 $ManageUser = "Gestió d'usuari";
 $SubscribeUserToCourseAsTeacher = "Inscriure professors";
 $PasswordEncryptedForSecurity = "La seva contrasenya està encriptada per a la seva seguretat. Per això, quan hagi premut en l'enllaç per a regenerar la seva clau se li remetrà un nou correu que contindrà la seva contrasenya.";
-$SystemUnableToSendEmailContact = "El sistema no ha pogut enviar-li el correu electrònic";
 $OpenIDCouldNotBeFoundPleaseRegister = "Aquest OpenID no es troba en la nostra base de dades. Per favor, registri's per a obtenir un compte. Si ja té un compte amb nosaltres, editi el seu perfil en la mateixa per a afegir aquest OpenID";
 $UsernameMaxXCharacters = "El nom d'usuari pot tenir com a màxim una longitud de %s caràcters";
 $PictureUploaded = "La seva imatge ha estat enviada";

+ 0 - 1
main/lang/croatian/trad4all.inc.php

@@ -2404,7 +2404,6 @@ $ApprovalForNewAccount = "Odobravanje novog računa";
 $ManageUser = "Upravljanje korisnikom";
 $SubscribeUserToCourseAsTeacher = "Upiši polaznike na ovaj kolegij nastavnika";
 $PasswordEncryptedForSecurity = "Vaša zaporka je šifrirana radi sigurnosnih razloga. Nakon odabira poveznice biti će vam poslana zaporka na vašu e-poštu.";
-$SystemUnableToSendEmailContact = "Sustav ne može naslovljenom poslati e-poštu";
 $OpenIDCouldNotBeFoundPleaseRegister = "Ovaj OpenID nije pronađen u našoj bazi podataka. Molim prijavite se za novi korisnički račun. Ukoliko već imate otvoreni korisnički račun, tada dodajte ovaj OpenID u vašim korisničkim postavkama.";
 $UsernameMaxXCharacters = "Korisničko ime može sadržavati najviše %s znakova";
 $PictureUploaded = "Vaša slika je učitana";

+ 0 - 1
main/lang/danish/trad4all.inc.php

@@ -2247,7 +2247,6 @@ $ApprovalForNewAccount = "Godkendelse af ny profil";
 $ManageUser = "Administrer deltagere";
 $SubscribeUserToCourseAsTeacher = "Tilmeld undervisere/kursusadministratorer";
 $PasswordEncryptedForSecurity = "Din adgangskode er krypteret af sikkerhedsmæssige årsager. Hvis du klikker på linket, vil du modtage en ny e-mail med din adgangskode.";
-$SystemUnableToSendEmailContact = "Systemet kunne ikke sende e-mailen";
 $UsernameMaxXCharacters = "Brugernavnet skal maks. være %s karakterer langt";
 $InLnk = "Ikke aktive funktioner og links";
 $DelLk = "Er du sikkert på, at du vil slettet dette link?";

+ 0 - 1
main/lang/dutch/trad4all.inc.php

@@ -3950,7 +3950,6 @@ $ApprovalForNewAccount = "Goedkeuring voor een nieuw account";
 $ManageUser = "Beheer gebruiker";
 $SubscribeUserToCourseAsTeacher = "Schrijf de gebruikers in deze cursus in als leerkracht";
 $PasswordEncryptedForSecurity = "Uw paswoord is geëncrypteerd omwile van beveiligingsredenen. Na het klikken op de link wordt opnieuw een e-mail verstuurd met uw paswoord.";
-$SystemUnableToSendEmailContact = "Het systeem kon het email contact niet verzenden";
 $OpenIDCouldNotBeFoundPleaseRegister = "Deze OpenID bestaat niet in onze database. Gelieve u te registreren voor een nieuwe account. Bent u bij ons reeds geregistreerd, gelieve dan uw profiel aan te passen, en deze OpenID toe te voegen";
 $UsernameMaxXCharacters = "De gebruikersnaam mag slechts maximum %s tekens lang zijn";
 $PictureUploaded = "Uw afbeelding werd geüploaded";

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
main/lang/english/trad4all.inc.php


+ 0 - 1
main/lang/finnish/trad4all.inc.php

@@ -2447,7 +2447,6 @@ $ApprovalForNewAccount = "Uuden tunnuksen hyväksyminen";
 $ManageUser = "Hallitse käyttäjää";
 $SubscribeUserToCourseAsTeacher = "Rekisteröi kouluttajia";
 $PasswordEncryptedForSecurity = "Salasanasi on salattu tietoturvan takaamiseksi. Painamalla linkkiä saat sähköpostiin uuden salasanan.";
-$SystemUnableToSendEmailContact = "Sähköpostin lähettäminen ei onnistunut";
 $UsernameMaxXCharacters = "Tunnuksen pitää olla korkeintaan %s merkkiä pitkä";
 $PictureUploaded = "Kuvasi on ladattu";
 $UsersRegistered = "Käyttäjät on rekisteröity kurssille";

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 4 - 4
main/lang/french/trad4all.inc.php


+ 0 - 1
main/lang/galician/trad4all.inc.php

@@ -3977,7 +3977,6 @@ $ApprovalForNewAccount = "Aprobación dunha conta nova";
 $ManageUser = "Xestionar usuario";
 $SubscribeUserToCourseAsTeacher = "Rexistrar usuarios neste curso como profesor";
 $PasswordEncryptedForSecurity = "O seu contrasinal está encriptado para a súa seguridade. Por iso, cando pulse no enlace para rexenerar a súa clave remitiráselle un novo correo que conterá o seu contrasinal.";
-$SystemUnableToSendEmailContact = "O sistema non puido enviar o correo electrónico";
 $OpenIDCouldNotBeFoundPleaseRegister = "Este OpenID non se encontra na nosa base de datos. Por favor, rexístrese para obter unha conta. Se xa ten unha conta con nós, edite o seu perfil na mesma para engadir este OpenID";
 $UsernameMaxXCharacters = "O nome de usuario pode ter como máximo unha lonxitude de %s caracteres";
 $PictureUploaded = "A súa imaxe foi enviada";

+ 4 - 5
main/lang/german/trad4all.inc.php

@@ -2046,7 +2046,7 @@ $UsersWereEdited = "Benutzer-Zugänge wurden aktualisiert";
 $AtLeastOneUserAndOneURL = "Mindestens ein Benutzer und eine URL müssen ausgewählt sein";
 $UsersBelongURL = "Die Benutzer-Zugänge wurden der URL zugefügt";
 $LPTestScore = "Kurs-Bewertung";
-$ScormAndLPTestTotalAverage = "Durchschnittliches Ergebnisse der Tests in den Lernpfaden";
+$ScormAndLPTestTotalAverage = "Durchschnittliches Ergebnis der Tests in den Lernpfaden";
 $ImportUsersToACourse = "Importiere Benutzer-Liste";
 $ImportCourses = "Importiere Kurs-Liste";
 $ManageUsers = "Benutzer verwalten";
@@ -3969,7 +3969,6 @@ $ApprovalForNewAccount = "Genehmigung für neuen Zugang";
 $ManageUser = "Benutzer verwalten";
 $SubscribeUserToCourseAsTeacher = "Als Kursleiter in diesen Kurs einschreiben";
 $PasswordEncryptedForSecurity = "Ihr Passwort wurde zur Sicherheit verschlüsselt. Daher wird nach dem Klick auf den Link eine E-Mail mit Ihrem Passwort an Ihre E-Mail Adresse verschickt.";
-$SystemUnableToSendEmailContact = "System konnte E-Mail Kontakt nicht versenden";
 $OpenIDCouldNotBeFoundPleaseRegister = "Diese OpenID konnte in unserer Datenbank nicht gefunden werden. Registrieren Sie sich bitte für einen neuen Zugang. Sollten Sie bereits einen Zugang bei uns haben, bearbeiten Sie bitte Ihr Profil in Ihrem Zugang, und fügen Sie diese OpenID hinzu.";
 $UsernameMaxXCharacters = "Der Benutzername darf höchstens %s Zeichen lang sein";
 $PictureUploaded = "Ihr Bild wurde hochgeladen";
@@ -6621,10 +6620,10 @@ $CertificateOnlineLink = "Link zum Zertifikat";
 $NewExercises = "Neue Tests";
 $MyAverage = "Mein Durchschnitt";
 $AllAttempts = "Alle Versuche";
-$QuestionsToReview = "Fragen die überprüft werden müssen";
+$QuestionsToReview = "Zu wiederholende Fragen";
 $QuestionWithNoAnswer = "Fragen ohne Antworten";
 $ValidateAnswers = "Antworten bestätigen";
-$ReviewQuestions = "Ausgewählte Fragen bewerten";
+$ReviewQuestions = "Ausgewählte Fragen wiederholen";
 $YouTriedToResolveThisExerciseEarlier = "Sie haben bereits früher versucht den Test zu lösen";
 $NoCookies = "Der Browser unterstützt keine Cookies. Chamilo benötigt \"Cookies\", um gewisse Dinge (wie z.B. Lernfortschritt oder Login-Status) temporär zu speichern. Dies bedeutet: ohne Cookies kein Login. Bitte im Browser daher Cookies erlauben, und danach diese Seite neu laden.";
 $NoJavascript = "Der Browser unterstützt kein JavaScript. Chamilo benötigt JavaScript, um ein möglichst angenehmes Lernerlebnis zu gewährleisten. Das bedeutet: viele Features werden funktionieren, aber der ein oder andere Effekt in Sachen Benutzerfreundlichkeit könnte ausbleiben. Daher ist es ratsam, JavaScript im Browser zu aktivieren, und diese Seite neu zu laden.";
@@ -6794,7 +6793,7 @@ $TextWhenFinished = "Text, der am Ende des Tests erscheint";
 $Validated = "Bestätigt";
 $NotValidated = "Nicht bestätigt";
 $Revised = "Korrigiert";
-$SelectAQuestionToReview = "Wählen Sie eine Frage zur Korrektur";
+$SelectAQuestionToReview = "Wählen Sie eine Frage zur Wiederholung";
 $ReviewQuestionLater = "Korrigiere Frage später";
 $NumberStudentWhoSelectedIt = "Anzahl Teilnehmer die ausgewählt haben";
 $QuestionsAlreadyAnswered = "Betreits beantwortete Fragen";

+ 0 - 1
main/lang/greek/trad4all.inc.php

@@ -3980,7 +3980,6 @@ $ApprovalForNewAccount = "Έγκριση νέου λογαριασμού";
 $ManageUser = "Διαχείριση χρήστη";
 $SubscribeUserToCourseAsTeacher = "Εισαγωγή εκπαιδευτών";
 $PasswordEncryptedForSecurity = "Your password is encrypted for security reasons. Thus, after pressing the link an e-mail will be sent to you again with your password.";
-$SystemUnableToSendEmailContact = "This platform was unable to send the email. Please contact";
 $OpenIDCouldNotBeFoundPleaseRegister = "This OpenID could not be found in our database. Please register for a new account. If you have already an account with us, please edit your profile inside your account to add this OpenID";
 $UsernameMaxXCharacters = "The login needs to be maximum %s characters long";
 $PictureUploaded = "Your picture has been uploaded";

+ 0 - 1
main/lang/hungarian/trad4all.inc.php

@@ -2666,7 +2666,6 @@ $ApprovalForNewAccount = "Új felhasználó jóváhagyása";
 $ManageUser = "Felhasználók kezelése";
 $SubscribeUserToCourseAsTeacher = "Felhasználók tanárként beíratása a kurzusba";
 $PasswordEncryptedForSecurity = "A jelszavát a rendszer titkosítva tárolja biztonsági okokból. A hivatkozásra kattintva egy újabb emailt fog kapni jelszavával.";
-$SystemUnableToSendEmailContact = "A rendszer nem tudott email üzenetet küldeni";
 $OpenIDCouldNotBeFoundPleaseRegister = "Ez az OpenID nem található az adatbázisban. Kérem, regisztrálja magát egy új azonosítóért. Ha már van azonosítója nálunk, kérjük, belépés után módosítsa profilját OpenID hozzáadásához";
 $UsernameMaxXCharacters = "A felhasználónév maximum %s karakter hosszú lehet.";
 $PictureUploaded = "A képet sikeresen feltöltötte";

+ 0 - 1
main/lang/italian/trad4all.inc.php

@@ -3986,7 +3986,6 @@ $ApprovalForNewAccount = "Approvazione della nuova iscrizione";
 $ManageUser = "Gestione utenti";
 $SubscribeUserToCourseAsTeacher = "Iscrivi un docente";
 $PasswordEncryptedForSecurity = "La tua password è criptata per motivi di sicurezza e di privacy, per cui cliccando sul collegamento la password ti verrà all'indirizzo e-mail da te fornito.";
-$SystemUnableToSendEmailContact = "Il sistema non è in grado di inviare il messaggio e-mail: contatta l'";
 $OpenIDCouldNotBeFoundPleaseRegister = "L'OpenID non è stato trovato nel database. Ti preghiamo di registrarti nuovamente. Se sei già registrata/o modifica il tuo profilo e aggiungi l'OpenID corretto.";
 $UsernameMaxXCharacters = "Il Nome Utente può avere una lunghezza massima di %s caratteri";
 $PictureUploaded = "L'immagine è stata caricata";

+ 0 - 1
main/lang/latvian/trad4all.inc.php

@@ -3342,7 +3342,6 @@ $ApprovalForNewAccount = "Jauna konta apstiprinājums";
 $ManageUser = "Organizēt lietotāju";
 $SubscribeUserToCourseAsTeacher = "Reģistrēt Lektorus";
 $PasswordEncryptedForSecurity = "Drošības apsvērumu dēļ, Jūsu parole tiek šifrēta. Tādējādi, nospiežot uz e-pasta saites, Jums tiks nosūtīta atkārtota parole.";
-$SystemUnableToSendEmailContact = "Portāls nevar nosūtīt e-pastu";
 $OpenIDCouldNotBeFoundPleaseRegister = "Šis OpenID nav atrodams mūsu datu bāzē. Lūdzu reģistrēties jauna konta izveidei. Ja Jums jau ir konts mūsu sistēmā, lūdzu, rediģējiet savu profilu konta iekšienē, lai pievienotu šo OpenID";
 $UsernameMaxXCharacters = "Lietotājvārdam jābūt %s burtu garam";
 $PictureUploaded = "Jūsu attēli ir augšupielādēti";

+ 0 - 1
main/lang/lithuanian/trad4all.inc.php

@@ -2103,7 +2103,6 @@ $ApprovalForNewAccount = "Naujos sąskaitos patvirtinimas";
 $ManageUser = "Valdyti vartotoją";
 $SubscribeUserToCourseAsTeacher = "Užregistruoti vartotojus šiame kurse kaip dėstytojus";
 $PasswordEncryptedForSecurity = "Your password is encrypted for security reasons. Thus, after pressing the link an e-mail will be sent to you again with your password.";
-$SystemUnableToSendEmailContact = "System unable to send email contact";
 $InLnk = "Paslėpti įrankiai ir nuorodos";
 $DelLk = "Ar tikrai norite ištrinti šią nuorodą?";
 $NameOfTheLink = "Nuorodos pavadinimas";

+ 0 - 1
main/lang/persian/trad4all.inc.php

@@ -2655,7 +2655,6 @@ $ApprovalForNewAccount = "تاییدیه برای حساب کاربری جدید
 $ManageUser = "مدیریت کاربر";
 $SubscribeUserToCourseAsTeacher = "ثبت نام اساتید";
 $PasswordEncryptedForSecurity = "کلمه عبور شما جهت امنیت بیشتر کد گذاری شد. البته پس از فشردن پیوند یک نامه الکترونیک بهمراه کلمه عبور برای شما مجددا ارسال می شود.";
-$SystemUnableToSendEmailContact = "این سیستم قادر به ارسال نامه الکترونیک نبود. لطفا تماس بگیرید";
 $OpenIDCouldNotBeFoundPleaseRegister = "این OpenID  در پایگاه داده وجود ندارد. لطفا یک حساب کاربری جدید ثبت کنید. اگر هم اکنون یک حساب کاربری در سایت دارید، لطفا مشخصات خود در حساب کاربری را ویرایش نموده و این OpenID  را اضافه نمایید.";
 $UsernameMaxXCharacters = "نام کاربری باید حداکثر %s کاراکتر طول داشته باشد";
 $PictureUploaded = "تصویر شما آپلود شد";

+ 0 - 1
main/lang/polish/trad4all.inc.php

@@ -3538,7 +3538,6 @@ $ApprovalForNewAccount = "Zatwierdzenie nowego konta";
 $ManageUser = "Zarządzaj użytkownikami";
 $SubscribeUserToCourseAsTeacher = "Zapisz (Nauczyciel) użytkowników na kurs.";
 $PasswordEncryptedForSecurity = "Twoje hasło jest szyfrowane ze względów bezpieczeństwa. Po naciśnięciu przycisku, hasło zostanie wysłane do Ciebie ponownie.";
-$SystemUnableToSendEmailContact = "System nie był w stanie wysłać e-mail'a. Prosimy o kontakt";
 $OpenIDCouldNotBeFoundPleaseRegister = "Nie można znaleźć tego ID w naszej bazie danych. Zarejestruj nowe konto. Jeśli masz już u nas konto, edytuj swój profil wewnątrz swojego konta, aby dodać ID";
 $UsernameMaxXCharacters = "Nazwa użytkownika może mieć do %s znaków.";
 $PictureUploaded = "Twój obraz został wgrany";

+ 0 - 1
main/lang/portuguese/trad4all.inc.php

@@ -3976,7 +3976,6 @@ $ApprovalForNewAccount = "Aprovação de nova conta";
 $ManageUser = "Gerir utilizador";
 $SubscribeUserToCourseAsTeacher = "Inscrever instrutores";
 $PasswordEncryptedForSecurity = "A sua senha/password encontra-se encriptada por razões de segurança. Assim, após clicar na ligação/link ser-lhe-á enviado um e-mail com a sua password.";
-$SystemUnableToSendEmailContact = "Não foi possível ao Portal enviar o e-mail de contacto";
 $OpenIDCouldNotBeFoundPleaseRegister = "Este OpenID não foi encontrado na nossa base-de-dados. Por favor, registe-se com uma nova conta. Se já possui uma conta, por favor edite o seu perfil na área da sua conta para adicionar este OpenID";
 $UsernameMaxXCharacters = "O login/acesso só pode conter um máximo de %s caracteres";
 $PictureUploaded = "A sua imagem foi enviada";

+ 0 - 1
main/lang/quechua_cusco/trad4all.inc.php

@@ -3168,7 +3168,6 @@ $ApprovalForNewAccount = "Musuq qelqachanaq chaninchaynin";
 $ManageUser = "Haykuqmasi kamachina";
 $SubscribeUserToCourseAsTeacher = "Qelqachay yachachiqkunata";
 $PasswordEncryptedForSecurity = "Qelqa pakaykiqa encriptada nisqa kashan tajyaykipaq. Chayrayku hoqmanta mañakunki chayqa, musuq e-chaskita apachimusaykiku qelqa-pakaykiwan.";
-$SystemUnableToSendEmailContact = "Kay k'itiqa manaraqmi apachisunkichu e-chaskita";
 $OpenIDCouldNotBeFoundPleaseRegister = "Kay OpenId manan kashanchu base de datos nisqapiqa. Ama hina kaychu, qelqachakuy cuenta nisqata hap'ipanaykipaq. Sichus cuenta nisqawan ña kashanki, chayqa ruwapay runaykimanta OpenId nisqa yapanapaq";
 $UsernameMaxXCharacters = "Haykuqmasi sutiqa kay yupasqa seq'ellawan kanqa %s";
 $PictureUploaded = "Wankiykiqa apachikunña";

+ 0 - 1
main/lang/romanian/trad4all.inc.php

@@ -3858,7 +3858,6 @@ $ApprovalForNewAccount = "Aprobare pentru cont nou";
 $ManageUser = "Gestioneaza utilizatorul";
 $SubscribeUserToCourseAsTeacher = "Inscrieti utilizatorii acestui curs ca si profesori";
 $PasswordEncryptedForSecurity = "Parola dvs. este criptata din motive de securitate. Dupa ce faceti clic pe link-ul va fi trimis un alt e-mail cu parola.";
-$SystemUnableToSendEmailContact = "Sistemul nu poate trimite emailul";
 $OpenIDCouldNotBeFoundPleaseRegister = "Aceste OpenID nu exista in baza noastra de date. Va rugam sa va inregistrati pentru un nou cont. Sunteti deja inregistrat in baza noastra de date. Va rugam sa  adaptati profilul dvs. si sa adaugati OpenID.";
 $UsernameMaxXCharacters = "Numele de utilizator poate fi de maximum %s caractere";
 $PictureUploaded = "Fotografia a fost actualizata";

+ 0 - 1
main/lang/russian/trad4all.inc.php

@@ -2397,7 +2397,6 @@ $ApprovalForNewAccount = "Одобрение новой учетной запи
 $ManageUser = "Управление пользователем";
 $SubscribeUserToCourseAsTeacher = "Подписать преподавателя пользователей на этот курс";
 $PasswordEncryptedForSecurity = "Ваш пароль зашифрован в целях безопасности. Поэтому, после нажатия на ссылку Вы получите письмо по эл. почте со своим паролем снова.";
-$SystemUnableToSendEmailContact = "Система не может послать эл. адрес для контакта";
 $OpenIDCouldNotBeFoundPleaseRegister = "Этот ID_Открытия не найден в нашей базе данных. Пожалуйста, зарегистрируйтесь для создания новой учетной записи. Если у нас уже есть Ваша учетная запись, пожалуйста, отредактируйте свой профиль внутри вашей учетной записи так, чтобы добавить этот ID_Открытия";
 $UsernameMaxXCharacters = "Имя пользователя должно содержать максимум % символов";
 $InLnk = "Сделать неактивными инструменты и ссылки";

+ 0 - 1
main/lang/serbian/trad4all.inc.php

@@ -1948,7 +1948,6 @@ $ApprovalForNewAccount = "Odobrenje za novi nalog";
 $ManageUser = "Upravljanje korisnika";
 $SubscribeUserToCourseAsTeacher = "Upisati trenera";
 $PasswordEncryptedForSecurity = "Vaša lozinka je šifrovana iz bezbednosnih razloga. Nakon što pritisnete link e-mail će vam poslati ponovo lozinku.";
-$SystemUnableToSendEmailContact = "Portal nije u mogućnosti da pošalje e-mail kontakt";
 $OpenIDCouldNotBeFoundPleaseRegister = "Ovaj otvoreni ID nije bilo moguće pronaći u našoj bazi. Molimo Vas da se prijavite za novi nalog. Ako već imate nalog kod nas, molimo vas uredite svoj profil na svom računu dodavanjem ovog otvorenog ID";
 $UsernameMaxXCharacters = "Korisničko ime treba da bude dugačko najviše %s znakova";
 $PictureUploaded = "Vaša slika je bila učitana";

+ 0 - 1
main/lang/slovak/trad4all.inc.php

@@ -4033,7 +4033,6 @@ $ApprovalForNewAccount = "Schválenie nového konta";
 $ManageUser = "Spravovať používateľov";
 $SubscribeUserToCourseAsTeacher = "Prihlásiť lektorov";
 $PasswordEncryptedForSecurity = "Vaše heslo je z bezpečnostných dôvodov zakódované. Preto po kliknutí na odkaz Vám bude znova zaslaný e-mail s Vašim heslom.";
-$SystemUnableToSendEmailContact = "Systém nie je schopný poslať e-mailový kontakt";
 $OpenIDCouldNotBeFoundPleaseRegister = "Tento OpenID nebol nájdený v databáze. Prosím zaregistrujte si nový účet. Ak ste máte u nás účet, upravte svoj ​​profil v účte pridaním tohto OpenID";
 $UsernameMaxXCharacters = "Meno používateľa môže byť dlhé maximálne # znakov";
 $PictureUploaded = "Váš obrázok bol načítaný";

+ 0 - 1
main/lang/slovenian/trad4all.inc.php

@@ -3966,7 +3966,6 @@ $ApprovalForNewAccount = "Odobritev za nov račun";
 $ManageUser = "Upravljaj uporabnika";
 $SubscribeUserToCourseAsTeacher = "Vpiši uporabnike v ta tečaj kot učitelje";
 $PasswordEncryptedForSecurity = "Vaše geslo je bilo kriptirano iz varnostnih razlogov. Zato vam bo geslo po kliku na dano povezavo poslano na vaš e-poštni naslov.";
-$SystemUnableToSendEmailContact = "System ne more poslati e-pošte naslovniku";
 $OpenIDCouldNotBeFoundPleaseRegister = "Ta OpenID ne obstaja v naši podatkovni bazi. Prosimo, da se registrirajte za dodelitev novega uporabniškega računa. V primeru, da uporabniški račun na tem portalu že imate, ustrezno spremenite vaš profil, tako da dodate ta OpenID.";
 $UsernameMaxXCharacters = "Uporabniško ime je lahko dolgo največ %s znakov";
 $PictureUploaded = "Vaša slika je bila naložena";

+ 2 - 3
main/lang/spanish/trad4all.inc.php

@@ -4008,7 +4008,6 @@ $ApprovalForNewAccount = "Validación de una nueva cuenta";
 $ManageUser = "Gestión de usuario";
 $SubscribeUserToCourseAsTeacher = "Inscribir profesores";
 $PasswordEncryptedForSecurity = "Su contraseña está encriptada para su seguridad. Por ello, cuando haya pulsado en el enlace para regenerar su clave se le remitirá un nuevo correo que contendrá su contraseña.";
-$SystemUnableToSendEmailContact = "El sistema no ha podido enviarle el correo electrónico";
 $OpenIDCouldNotBeFoundPleaseRegister = "Este OpenID no se encuentra en nuestra base de datos. Por favor, regístrese para obtener una cuenta. Si ya tiene una cuenta con nosotros,  edite su perfil en la misma para añadir este OpenID";
 $UsernameMaxXCharacters = "El nombre de usuario puede tener como máximo una longitud de %s caracteres";
 $PictureUploaded = "Su imagen ha sido enviada";
@@ -5345,8 +5344,8 @@ $AddTimeLimit = "Añadir límite de tiempo";
 $EditTimeLimit = "Editar límite de tiempo";
 $TheTimeLimitsAreReferential = "El plazo de una categoría es referencial, no afectará a los límites de una sesión de formación";
 $FieldTypeTag = "User tag";
-$SendEmailToAdminTitle = "Aviso por correo electrónico, de la creación de un nuevo curso";
-$SendEmailToAdminComment = "Enviar un correo electrónico al administrador de la plataforma, cada vez que un profesor cree un nuevo curso";
+$SendEmailToAdminTitle = "Aviso e-mail a la creación de nuevos cursos";
+$SendEmailToAdminComment = "Enviar un correo electrónico al administrador de la plataforma cada vez que un profesor cree un nuevo curso";
 $UserTag = "Etiqueta de usuario";
 $SelectSession = "Seleccionar sesión";
 $SpecialCourse = "Curso especial";

+ 0 - 1
main/lang/swedish/trad4all.inc.php

@@ -2415,7 +2415,6 @@ $ApprovalForNewAccount = "Godkännande av nytt konto";
 $ManageUser = "Hantera användare";
 $SubscribeUserToCourseAsTeacher = "Lägg till lärare till kursen";
 $PasswordEncryptedForSecurity = "Ditt lösenord blir krypterat av säkerhetsskäl. När du klickar på länken skickas e-post till dig med ditt lösenord.";
-$SystemUnableToSendEmailContact = "Systemet kunde inte skicka e-posten";
 $OpenIDCouldNotBeFoundPleaseRegister = "Angivet OpenID kunde inte hittas i vår databas. Om du redan finns registrerad hos oss kan du ändra i din profil för att lägga till inloggning med OpenID, annars behöver du registrera ett nytt konto.";
 $UsernameMaxXCharacters = "Användarnamnet kan vara max %s tecken långt";
 $PictureUploaded = "Din bild blev uppladdad";

+ 0 - 1
main/lang/trad_chinese/trad4all.inc.php

@@ -2175,7 +2175,6 @@ $ApprovalForNewAccount = "批核新戶口";
 $ManageUser = "管理使用者";
 $SubscribeUserToCourseAsTeacher = "於本課程加入教師用戶";
 $PasswordEncryptedForSecurity = "因應安全理由,你的密碼已被加密。按下連結,你的密碼便會通過電郵傳送給你。";
-$SystemUnableToSendEmailContact = "系統未能發送電郵給聯絡人";
 $UsernameMaxXCharacters = "使用者名稱最長為 %s 字母";
 $InLnk = "隱藏的工具";
 $DelLk = "確定要移除這連結嗎?";

+ 79 - 87
main/lp/learnpath.class.php

@@ -11,6 +11,8 @@ use Symfony\Component\Finder\Finder;
 use Chamilo\CourseBundle\Entity\CLp;
 use Chamilo\CourseBundle\Entity\CTool;
 use Chamilo\UserBundle\Entity\User;
+use Chamilo\CourseBundle\Entity\CLpItem,
+    Chamilo\CourseBundle\Entity\CLpItemView;
 
 /**
  * Class learnpath
@@ -4282,7 +4284,7 @@ class learnpath
         $courseId = api_get_course_int_id();
         $sessionId = api_get_session_id();
         $sessionCondition = api_get_session_condition($sessionId, true, false, 't.sessionId');
-        
+
         $em = Database::getManager();
 
         /** @var CLpCategory $category */
@@ -11735,105 +11737,103 @@ EOD;
         $lpViewId,
         $origin = 'learnpath'
     ) {
-        $tbl_lp_item = Database::get_course_table(TABLE_LP_ITEM);
         $course_info = api_get_course_info_by_id($course_id);
-        $course_id = $course_info['real_id'];
         $course_code = $course_info['code'];
         $session_id = api_get_session_id();
         $learningPathId = intval($learningPathId);
         $id_in_path = intval($id_in_path);
         $lpViewId = intval($lpViewId);
         $em = Database::getManager();
-        $sql = "SELECT * FROM $tbl_lp_item
-                 WHERE
-                    c_id = $course_id AND
-                    lp_id = $learningPathId AND
-                    id = $id_in_path
-                ";
-        $res_item = Database::query($sql);
-        if (Database::num_rows($res_item) < 1) {
-            return -1;
-        }
-        $row_item = Database::fetch_array($res_item, 'ASSOC');
+        $lpItemRepo = $em->getRepository('ChamiloCourseBundle:CLpItem');
+        /** @var CLpItem $rowItem */
+        $rowItem = $lpItemRepo->findOneBy([
+            'cId' => $course_id,
+            'lpId' => $learningPathId,
+            'id' => $id_in_path
+        ]);
 
-        $item_view_table = Database::get_course_table(TABLE_LP_ITEM_VIEW);
-        // Get the lp_item_view with the highest view_count.
-        $sql = "SELECT * FROM $item_view_table
-                WHERE
-                    c_id = $course_id AND
-                    lp_item_id = ".$row_item['id']." AND
-                    lp_view_id = $lpViewId
-                ORDER BY view_count DESC";
-        $learnpathItemViewResult = Database::query($sql);
-        $learnpathItemViewData = Database::fetch_array($learnpathItemViewResult, 'ASSOC');
-        $learnpathItemViewId = 0;
-        if (isset($learnpathItemViewData)) {
-            $learnpathItemViewId = $learnpathItemViewData['id'];
+        if (!$rowItem) {
+            return -1;
         }
 
-        $type = strtolower($row_item['item_type']);
-        $id = (strcmp($row_item['path'], '') == 0) ? '0' : $row_item['path'];
+        $type = $rowItem->getItemType();
+        $id = empty($rowItem->getPath()) ? '0' : $rowItem->getPath();
         $main_dir_path = api_get_path(WEB_CODE_PATH);
         $main_course_path = api_get_path(WEB_COURSE_PATH).$course_info['directory'].'/';
         $link = '';
-        $extraParams = "origin=$origin&cidReq=$course_code&session_id=$session_id&id_session=$session_id";
+        $extraParams = api_get_cidreq().'&session_id='.$session_id;
         switch ($type) {
             case 'dir':
-                $link .= $main_dir_path.'lp/blank.php';
-                break;
+                return $main_dir_path.'lp/blank.php';
             case TOOL_CALENDAR_EVENT:
-                $link .= $main_dir_path.'calendar/agenda.php?agenda_id='.$id.'&'.$extraParams;
-                break;
+                return $main_dir_path.'calendar/agenda.php?agenda_id='.$id.'&'.$extraParams;
             case TOOL_ANNOUNCEMENT:
-                $link .= $main_dir_path.'announcements/announcements.php?ann_id='.$id.'&'.$extraParams;
-                break;
+                return $main_dir_path.'announcements/announcements.php?ann_id='.$id.'&'.$extraParams;
             case TOOL_LINK:
-                $link .= $main_dir_path.'link/link_goto.php?link_id='.$id.'&'.$extraParams;
-                break;
+                $linkInfo = Link::get_link_info($id);
+
+                return $linkInfo['url'];
             case TOOL_QUIZ:
-                if (!empty($id)) {
-                    $TBL_EXERCICES = Database::get_course_table(TABLE_QUIZ_TEST);
-                    $sql = "SELECT * FROM $TBL_EXERCICES WHERE c_id = $course_id AND id=$id";
-                    $result = Database::query($sql);
-                    $myrow = Database::fetch_array($result);
-                    if ($row_item['title'] != '') {
-                        $myrow['title'] = $row_item['title'];
-                    }
-                    $link .= $main_dir_path.'exercise/overview.php?lp_init=1&learnpath_item_view_id='.$learnpathItemViewId.'&learnpath_id='.$learningPathId.'&learnpath_item_id='.$id_in_path.'&exerciseId='.$id.'&'.$extraParams;
+                if (empty($id)) {
+                    return '';
                 }
-                break;
+
+                // Get the lp_item_view with the highest view_count.
+                $learnpathItemViewResult = $em
+                    ->getRepository('ChamiloCourseBundle:CLpItemView')
+                    ->findBy(
+                        ['cId' => $course_id, 'lpItemId' => $rowItem->getId(), 'lpViewId' => $lpViewId],
+                        ['viewCount' => 'DESC'],
+                        1
+                    );
+                /** @var CLpItemView $learnpathItemViewData */
+                $learnpathItemViewData = current($learnpathItemViewResult);
+                $learnpathItemViewId = $learnpathItemViewData ? $learnpathItemViewData->getId() : 0;
+
+                return $main_dir_path.'exercise/overview.php?'.$extraParams.'&'
+                    .http_build_query([
+                        'lp_init' => 1,
+                        'learnpath_item_view_id' => $learnpathItemViewId,
+                        'learnpath_id' => $learningPathId,
+                        'learnpath_item_id' => $id_in_path,
+                        'exerciseId' => $id
+                    ]);
             case TOOL_HOTPOTATOES: //lowercase because of strtolower above
                 $TBL_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
                 $result = Database::query("SELECT * FROM ".$TBL_DOCUMENT." WHERE c_id = $course_id AND id=$id");
                 $myrow = Database::fetch_array($result);
                 $path = $myrow['path'];
-                $link .= $main_dir_path.'exercise/showinframes.php?file='.$path.'&cid='.$course_code.'&uid='.api_get_user_id().'&learnpath_id='.$learningPathId.'&learnpath_item_id='.$id_in_path.'&lp_view_id='.$lpViewId.'&'.$extraParams;
-                break;
+
+                return $main_dir_path.'exercise/showinframes.php?file='.$path.'&cid='.$course_code.'&uid='
+                    .api_get_user_id().'&learnpath_id='.$learningPathId.'&learnpath_item_id='.$id_in_path
+                    .'&lp_view_id='.$lpViewId.'&'.$extraParams;
             case TOOL_FORUM:
-                $link .= $main_dir_path.'forum/viewforum.php?forum='.$id.'&lp=true&'.$extraParams;
-                break;
+                return $main_dir_path.'forum/viewforum.php?forum='.$id.'&lp=true&'.$extraParams;
             case TOOL_THREAD:  //forum post
                 $tbl_topics = Database::get_course_table(TABLE_FORUM_THREAD);
-                if (!empty($id)) {
-                    $sql = "SELECT * FROM $tbl_topics WHERE c_id = $course_id AND thread_id=$id";
-                    $result = Database::query($sql);
-                    $myrow = Database::fetch_array($result);
-                    $link .= $main_dir_path.'forum/viewthread.php?thread='.$id.'&forum='.$myrow['forum_id'].'&lp=true&'.$extraParams;
+                if (empty($id)) {
+                    return '';
                 }
-                break;
+                $sql = "SELECT * FROM $tbl_topics WHERE c_id = $course_id AND thread_id=$id";
+                $result = Database::query($sql);
+                $myrow = Database::fetch_array($result);
+
+                return $main_dir_path.'forum/viewthread.php?thread='.$id.'&forum='.$myrow['forum_id'].'&lp=true&'
+                    .$extraParams;
             case TOOL_POST:
                 $tbl_post = Database::get_course_table(TABLE_FORUM_POST);
                 $result = Database::query("SELECT * FROM $tbl_post WHERE c_id = $course_id AND post_id=$id");
                 $myrow = Database::fetch_array($result);
-                $link .= $main_dir_path.'forum/viewthread.php?post='.$id.'&thread='.$myrow['thread_id'].'&forum='.$myrow['forum_id'].'&lp=true&'.$extraParams;
-                break;
+
+                return $main_dir_path.'forum/viewthread.php?post='.$id.'&thread='.$myrow['thread_id'].'&forum='
+                    .$myrow['forum_id'].'&lp=true&'.$extraParams;
             case TOOL_DOCUMENT:
                 $document = $em
                     ->getRepository('ChamiloCourseBundle:CDocument')
                     ->findOneBy(['cId' => $course_id, 'id' => $id]);
 
                 if (!$document) {
-                    break;
+                    return '';
                 }
 
                 $documentPathInfo = pathinfo($document->getPath());
@@ -11841,45 +11841,37 @@ EOD;
                 $extension = isset($documentPathInfo['extension']) ? $documentPathInfo['extension'] : '';
                 $showDirectUrl = !in_array($extension, $jplayer_supported_files);
 
-                if ($showDirectUrl) {
-                    $link = $main_course_path.'document'.$document->getPath().'?'.$extraParams;
-                } else {
-                    $link = api_get_path(WEB_CODE_PATH).'document/showinframes.php?id='.$id.'&'.$extraParams;
-                }
-
                 $openmethod = 2;
                 $officedoc = false;
                 Session::write('openmethod', $openmethod);
                 Session::write('officedoc', $officedoc);
-                break;
+
+                if ($showDirectUrl) {
+                    return $main_course_path.'document'.$document->getPath().'?'.$extraParams;
+                }
+
+                return api_get_path(WEB_CODE_PATH).'document/showinframes.php?id='.$id.'&'.$extraParams;
             case TOOL_LP_FINAL_ITEM:
-                $link .= api_get_path(WEB_CODE_PATH).'lp/lp_final_item.php?&id='.$id.'&lp_id='.$learningPathId.'&'.$extraParams;
-                break;
+                return api_get_path(WEB_CODE_PATH).'lp/lp_final_item.php?&id='.$id.'&lp_id='.$learningPathId.'&'
+                    .$extraParams;
             case 'assignments':
-                $link .= $main_dir_path.'work/work.php?'.$extraParams;
-                break;
+                return $main_dir_path.'work/work.php?'.$extraParams;
             case TOOL_DROPBOX:
-                $link .= $main_dir_path.'dropbox/index.php?'.$extraParams;
-                break;
+                return $main_dir_path.'dropbox/index.php?'.$extraParams;
             case 'introduction_text': //DEPRECATED
-                $link .= '';
-                break;
+                return '';
             case TOOL_COURSE_DESCRIPTION:
-                $link .= $main_dir_path.'course_description?'.$extraParams;
-                break;
+                return $main_dir_path.'course_description?'.$extraParams;
             case TOOL_GROUP:
-                $link .= $main_dir_path.'group/group.php?'.$extraParams;
-                break;
+                return $main_dir_path.'group/group.php?'.$extraParams;
             case TOOL_USER:
-                $link .= $main_dir_path.'user/user.php?'.$extraParams;
-                break;
+                return $main_dir_path.'user/user.php?'.$extraParams;
             case TOOL_STUDENTPUBLICATION:
-                if (!empty($row_item['path'])) {
-                    $link .= $main_dir_path.'work/work_list.php?id='.$row_item['path'].'&'.$extraParams;
-                    break;
+                if (!empty($rowItem->getPath())) {
+                    return $main_dir_path.'work/work_list.php?id='.$rowItem->getPath().'&'.$extraParams;
                 }
-                $link .= $main_dir_path.'work/work.php?'.api_get_cidreq().'&id='.$row_item['path'].'&'.$extraParams;
-                break;
+
+                return $main_dir_path.'work/work.php?'.api_get_cidreq().'&id='.$rowItem->getPath().'&'.$extraParams;
         } //end switch
 
         return $link;

+ 1 - 1
main/survey/create_new_survey.php

@@ -26,7 +26,7 @@ $table_gradebook_link = Database::get_main_table(TABLE_MAIN_GRADEBOOK_LINK);
 /** @todo this has to be moved to a more appropriate place (after the display_header of the code) */
 // If user is not teacher or if he's a coach trying to access an element out of his session
 if (!api_is_allowed_to_edit()) {
-    if (!api_is_course_coach() ||
+    if (!api_is_session_general_coach() ||
         (!empty($_GET['survey_id']) &&
         !api_is_element_in_the_session(TOOL_SURVEY, $_GET['survey_id']))
     ) {

+ 1 - 1
main/survey/survey.php

@@ -30,7 +30,7 @@ if ($isDrhOfCourse) {
     exit;
 }
 if (!api_is_allowed_to_edit(false, true) ||
-    (api_is_course_coach() && $extend_rights_for_coachs == 'false')
+    (api_is_session_general_coach() && $extend_rights_for_coachs == 'false')
 ) {
     api_not_allowed(true);
     exit;

+ 4 - 4
main/survey/survey_list.php

@@ -94,7 +94,7 @@ $sessionId = api_get_session_id();
 if ($action === 'delete' && isset($_GET['survey_id'])) {
     // Getting the information of the survey (used for when the survey is shared)
     $survey_data = SurveyManager::get_survey($_GET['survey_id']);
-    if (api_is_course_coach() && $sessionId != $survey_data['session_id']) {
+    if (api_is_session_general_coach() && $sessionId != $survey_data['session_id']) {
         // The coach can't delete a survey not belonging to his session
         api_not_allowed();
         exit;
@@ -118,7 +118,7 @@ if ($action === 'delete' && isset($_GET['survey_id'])) {
 if ($action == 'empty') {
     $mysession = api_get_session_id();
     if ($mysession != 0) {
-        if (!((api_is_course_coach() || api_is_platform_admin()) &&
+        if (!((api_is_session_general_coach() || api_is_platform_admin()) &&
             api_is_element_in_the_session(TOOL_SURVEY, $_GET['survey_id']))) {
             // The coach can't empty a survey not belonging to his session
             api_not_allowed();
@@ -158,7 +158,7 @@ if (isset($_POST['action']) && $_POST['action']) {
 }
 
 echo '<div class="actions">';
-if (!api_is_course_coach() || $extend_rights_for_coachs == 'true') {
+if (!api_is_session_general_coach() || $extend_rights_for_coachs == 'true') {
     // Action links
     echo '<a href="'.api_get_path(WEB_CODE_PATH).'survey/create_new_survey.php?'.api_get_cidreq().'&amp;action=add">'.
         Display::return_icon('new_survey.png', get_lang('CreateNewSurvey'), '', ICON_SIZE_MEDIUM).'</a> ';
@@ -168,7 +168,7 @@ echo '<a href="'.api_get_self().'?'.api_get_cidreq().'&amp;search=advanced">'.
 echo '</div>';
 
 // Load main content
-if (api_is_course_coach() && $extend_rights_for_coachs == 'false') {
+if (api_is_session_general_coach() && $extend_rights_for_coachs == 'false') {
     SurveyUtil::display_survey_list_for_coach();
 } else {
     SurveyUtil::display_survey_list();

+ 81 - 78
main/template/default/layout/layout_2_col.tpl

@@ -1,104 +1,107 @@
 {% extends template ~ "/layout/page.tpl" %}
 
 {% block body %}
-<div class="row">
     {% if plugin_main_top %}
-        <div class="page-main-top" class="col-md-12">
-            {{ plugin_main_top }}
+        <div class="row">
+            <div class="page-main-top" class="col-md-12">
+                {{ plugin_main_top }}
+            </div>
         </div>
     {% endif %}
-    <div class="col-md-3">
-        <div class="sidebar">
-            {% if plugin_menu_top %}
-                <div class="siderbar-menu-top">
-                    {{ plugin_menu_top }}
-                </div>
-            {% endif %}
-
-            {% include template ~ "/layout/login_form.tpl" %}
+    <div class="row">
+        <div class="col-md-9 col-md-push-3">
+            <div class="page-content">
+                {% if plugin_content_top %}
+                    <div class="page-content-top">
+                        {{ plugin_content_top }}
+                    </div>
+                {% endif %}
 
-            {% if _u.logged  == 1 %}
-                {{ user_image_block }}
-            {% endif %}
+                {{ sniff_notification }}
 
-            {{ profile_block }}
-            {{ course_block }}
-            {{ teacher_block }}
-            {{ skills_block }}
-            {{ certificates_search_block }}
-            {{ notice_block }}
-            {{ help_block }}
-            {{ navigation_course_links }}
-            {{ search_block }}
-            {{ classes_block }}
+                {% if home_page_block %}
+                    <article id="homepage-home">
+                        {{ home_page_block }}
+                    </article>
+                {% endif %}
 
-            {% if plugin_menu_bottom %}
-                <div class="sidebar-menu-bottom">
-                    {{ plugin_menu_bottom }}
-                </div>
-            {% endif %}
-        </div>
-    </div>
-    <div class="col-md-9">
-        <div class="page-content">
+                {% block page_body %}
+                    {% include template ~ "/layout/page_body.tpl" %}
+                {% endblock %}
 
-            {% if plugin_content_top %}
-                <div class="page-content-top">
-                    {{ plugin_content_top }}
-                </div>
-            {% endif %}
+                {% if welcome_to_course_block %}
+                    <article id="homepage-course">
+                        {{ welcome_to_course_block }}
+                    </article>
+                {% endif %}
 
-            {{ sniff_notification }}
+                {% block content %}
+                    {% if content is not null %}
+                        <section id="page" class="{{ course_history_page }}">
+                            {{ content }}
+                        </section>
+                    {% endif %}
+                {% endblock %}
 
-            {% if home_page_block %}
-                <article id="homepage-home">
-                    {{ home_page_block }}
-                </article>
-            {% endif %}
+                {% if announcements_block %}
+                    <article id="homepage-announcements">
+                        {{ announcements_block }}
+                    </article>
+                {% endif %}
 
-            {% block page_body %}
-                {% include template ~ "/layout/page_body.tpl" %}
-            {% endblock %}
+                {% if course_category_block %}
+                    <article id="homepage-course-category">
+                        {{ course_category_block }}
+                    </article>
+                {% endif %}
 
-            {% if welcome_to_course_block %}
-                <article id="homepage-course">
-                {{ welcome_to_course_block }}
-                </article>
-            {% endif %}
+                {% include template ~ "/layout/hot_courses.tpl" %}
 
-            {% block content %}
-                {% if content is not null %}
-                    <section id="page" class="{{ course_history_page }}">
-                        {{ content }}
-                    </section>
+                {% if plugin_content_bottom %}
+                    <div id="plugin_content_bottom">
+                        {{ plugin_content_bottom }}
+                    </div>
+                {% endif %}
+            </div>
+        </div>
+        <div class="col-md-3 col-md-pull-9">
+            <div class="sidebar">
+                {% if plugin_menu_top %}
+                    <div class="siderbar-menu-top">
+                        {{ plugin_menu_top }}
+                    </div>
                 {% endif %}
-            {% endblock %}
 
-            {% if announcements_block %}
-                <article id="homepage-announcements">
-                {{ announcements_block }}
-                </article>
-            {% endif %}
+                {% include template ~ "/layout/login_form.tpl" %}
 
-            {% if course_category_block %}
-                <article id="homepage-course-category">
-                    {{ course_category_block }}
-                </article>
-            {% endif %}
+                {% if _u.logged  == 1 %}
+                    {{ user_image_block }}
+                {% endif %}
 
-            {% include template ~ "/layout/hot_courses.tpl" %}
+                {{ profile_block }}
+                {{ course_block }}
+                {{ teacher_block }}
+                {{ skills_block }}
+                {{ certificates_search_block }}
+                {{ notice_block }}
+                {{ help_block }}
+                {{ navigation_course_links }}
+                {{ search_block }}
+                {{ classes_block }}
 
-            {% if plugin_content_bottom %}
-                <div id="plugin_content_bottom">
-                    {{plugin_content_bottom}}
-                </div>
-            {% endif %}
+                {% if plugin_menu_bottom %}
+                    <div class="sidebar-menu-bottom">
+                        {{ plugin_menu_bottom }}
+                    </div>
+                {% endif %}
+            </div>
         </div>
     </div>
     {% if plugin_main_bottom %}
-        <div class="page-main-bottom" class="col-md-12">
-            {{ plugin_main_bottom }}
+        <div class="row">
+            <div class="page-main-bottom" class="col-md-12">
+                {{ plugin_main_bottom }}
+            </div>
         </div>
     {% endif %}
-</div>
 {% endblock %}

+ 2 - 2
main/template/default/user_portal/classic_session.tpl

@@ -41,7 +41,7 @@
             <div class="session panel-body {{ collapsable }}" id="collapse_{{ row.id }}">
                 <div class="row">
                     <div class="col-md-12">
-                        {% if row.description != '' %}
+                        {% if row.show_description %}
                             {{ row.description }}
                         {% endif %}
                         <ul class="info-session list-inline">
@@ -132,7 +132,7 @@
                     <div class="col-md-10">
                         <div class="info-session">
                             <p>{{ row.subtitle }}</p>
-                            {% if row.description != '' %}
+                            {% if row.show_description %}
                                 <div class="description">
                                     {{ row.description }}
                                 </div>

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

@@ -103,7 +103,7 @@
             {% endif %}
         </div>
         <div class="panel-body">
-            {% if row.description != '' %}
+            {% if row.show_description %}
                 {{ row.description }}
             {% endif %}
 

+ 12 - 10
main/template/default/work/comments.tpl

@@ -19,17 +19,19 @@
             {% endif %}
         </p>
         {% if comment.file_url is not empty %}
-            <p>
-                <a href="{{ comment.file_url }}">
-                    <img src="{{ "attachment.gif"|icon(32) }}" width="32" height="32">
-                    {{ comment.file_name_to_show }}
-                </a>
-                {% if is_allowed_to_edit %}
-                    <a href="{{ comment.delete_file_url }}">
-                        <img src="{{ "delete.png"|icon(22) }}" width="22" height="22">
+            <ul class="fa-ul">
+                <li>
+                    <span class="fa-li fa fa-paperclip"></span>
+                    <a href="{{ comment.file_url }}">
+                        {{ comment.file_name_to_show }}
                     </a>
-                {% endif %}
-            </p>
+                    {% if is_allowed_to_edit %}
+                        <a href="{{ comment.delete_file_url }}">
+                            {{ 'delete.png'|img(22, 'Delete'|get_lang) }}
+                        </a>
+                    {% endif %}
+                </li>
+            </ul>
         {% endif %}
     </li>
 {% endfor %}

+ 18 - 14
main/tracking/courseLog.php

@@ -312,22 +312,26 @@ if (!empty($coaches)) {
     $html .= $coaches;
 }
 
-$sessionList = SessionManager::get_session_by_course($courseInfo['real_id']);
-if (!empty($sessionList)) {
-    $html .= Display::page_subheader2(get_lang('SessionList'));
-    $icon = Display::return_icon(
-        'session.png',
-        null,
-        null,
-        ICON_SIZE_TINY
-    );
+if (api_is_platform_admin(true) || api_is_session_general_coach()) {
+    $sessionList = SessionManager::get_session_by_course($courseInfo['real_id']);
+
+    if (!empty($sessionList)) {
+        $html .= Display::page_subheader2(get_lang('SessionList'));
+        $icon = Display::return_icon(
+            'session.png',
+            null,
+            null,
+            ICON_SIZE_TINY
+        );
 
-    $html .= '<ul class="session-list">';
-    foreach ($sessionList as $session) {
-        $url = api_get_path(WEB_CODE_PATH).'mySpace/course.php?session_id='.$session['id'].'&cidReq='.$courseInfo['code'];
-        $html .= Display::tag('li', $icon.' '.Display::url($session['name'], $url));
+        $html .= '<ul class="session-list">';
+        foreach ($sessionList as $session) {
+            $url = api_get_path(WEB_CODE_PATH).'mySpace/course.php?session_id='
+                .$session['id'].'&cidReq='.$courseInfo['code'];
+            $html .= Display::tag('li', $icon.' '.Display::url($session['name'], $url));
+        }
+        $html .= '</ul>';
     }
-    $html .= '</ul>';
 }
 
 $html .= Display::page_subheader2(get_lang('StudentList'));

+ 1 - 1
main/tracking/course_session_report.php

@@ -11,7 +11,7 @@ require_once __DIR__.'/../inc/global.inc.php';
 
 $this_section = "session_my_space";
 
-$is_allowedToTrack = $is_courseAdmin || $is_platformAdmin || $is_courseCoach || $is_sessionAdmin;
+$is_allowedToTrack = $is_courseAdmin || $is_platformAdmin || $is_session_general_coach || $is_sessionAdmin;
 
 if (!$is_allowedToTrack) {
     api_not_allowed(true);

+ 1 - 1
main/tracking/exams.php

@@ -12,7 +12,7 @@ $toolTable = Database::get_course_table(TABLE_TOOL_LIST);
 $quizTable = Database::get_course_table(TABLE_QUIZ_TEST);
 
 $this_section = SECTION_TRACKING;
-$is_allowedToTrack = $is_courseAdmin || $is_platformAdmin || $is_courseCoach || $is_sessionAdmin;
+$is_allowedToTrack = $is_courseAdmin || $is_platformAdmin || $is_session_general_coach || $is_sessionAdmin;
 
 if (!$is_allowedToTrack) {
     api_not_allowed();

+ 1 - 1
main/tracking/lp_results_by_user.php

@@ -13,7 +13,7 @@ require_once __DIR__.'/../inc/global.inc.php';
 
 $this_section = SECTION_TRACKING;
 
-$is_allowedToTrack = $is_courseAdmin || $is_platformAdmin || $is_courseCoach || $is_sessionAdmin;
+$is_allowedToTrack = $is_courseAdmin || $is_platformAdmin || $is_session_general_coach || $is_sessionAdmin;
 
 if (!$is_allowedToTrack) {
 	Display :: display_header(null);

+ 1 - 1
main/tracking/question_course_report.php

@@ -11,7 +11,7 @@ require_once __DIR__.'/../inc/global.inc.php';
 
 $this_section = "session_my_space";
 
-$is_allowedToTrack = $is_courseAdmin || $is_platformAdmin || $is_courseCoach || $is_sessionAdmin;
+$is_allowedToTrack = $is_courseAdmin || $is_platformAdmin || $is_session_general_coach || $is_sessionAdmin;
 
 if (!$is_allowedToTrack) {
 	Display::display_header(null);

+ 1 - 1
src/Chamilo/CoreBundle/Entity/SettingsCurrent.php

@@ -104,7 +104,7 @@ class SettingsCurrent
      *
      * @ORM\Column(name="access_url_locked", type="integer", nullable=false, options={"default": 0 } )
      */
-    private $accessUrlLocked;
+    private $accessUrlLocked = 0;
 
     /**
      * Set variable

+ 39 - 20
tests/behat/features/session.feature

@@ -12,26 +12,45 @@ Feature: Session tool
     And I press "Add category"
     Then I should see "The category has been added"
 
-#  @javascript
-#  Scenario: Create a session
-#    Given I am on "/main/session/session_add.php"
-#    When I fill in the following:
-#      | name | Session 1 |
-#    And I fill in select2 input "#coach_username" with id "1" and value "admin"
-#    And I press "submit"
-#    Then I should see "Add courses to this session (Session 1)"
-#    Then I select "TEMP (TEMP)" from "NoSessionCoursesList[]"
-#    And I press "add_course"
-#    And I press "next"
-#    Then I should see "Update successful"
-#
-#  Scenario: Delete session
-#    Given I am on "/main/session/session_list.php?keyword=Session+1"
-#    And wait for the page to be loaded
-#    And I follow "Delete"
-#    And I confirm the popup
-#    Then I should see "Deleted"
-#
+  Scenario: Create a session with hidden description
+    Given I am on "/main/session/session_add.php"
+    When I fill in the following:
+      | name | Temp Session |
+    And I press "advanced_params"
+    And I fill in ckeditor field "description" with "Description for Temp Session"
+    And I press "submit"
+    Then I should see "Add courses to this session (Temp Session)"
+    Then I select "TEMP (TEMP)" from "NoSessionCoursesList[]"
+    And I press "add_course"
+    And I press "next"
+    Then I should see "Update successful"
+
+  Scenario: Check hidden session description
+    Given I am on "/user_portal.php?nosession=true"
+    Then I should see "Temp Session"
+    And I should not see "Description for Temp Session"
+
+  Scenario: Show session description
+    Given I am on "/main/session/session_list.php?keyword=Temp+session"
+    And wait for the page to be loaded
+    And I follow "Edit"
+    When I press "advanced_params"
+    And I check "Show description"
+    And I press "submit"
+    Then I should see "Update successful"
+
+  Scenario: Check shown session description
+    Given I am on "/user_portal.php?nosession=true"
+    Then I should see "Temp Session"
+    And I should see "Description for Temp Session"
+
+  Scenario: Delete session
+    Given I am on "/main/session/session_list.php?keyword=Temp+session"
+    And wait for the page to be loaded
+    And I follow "Delete"
+    And I confirm the popup
+    Then I should see "Deleted"
+
   Scenario: Delete session category
     Given I am on "/main/session/session_category_list.php"
     And I follow "Delete"

+ 4 - 1
tests/xhprof/footer.php

@@ -5,7 +5,10 @@
 /**
  * Init
  */
-if (extension_loaded('tideways')) {
+
+$isAjaxRequest = isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest';
+
+if (extension_loaded('tideways') && !$isAjaxRequest) {
     $profiler_namespace = 'chamilolms';  // namespace for your application
     $xhprof_data = tideways_disable();
     //$xhprof_runs = new XHProfRuns_Default();

+ 4 - 1
tests/xhprof/header.php

@@ -11,7 +11,10 @@
  * in your php config also disable the .htaccess line about the tests/
  * directory.
  */
-if (extension_loaded('tideways')) {
+
+$isAjaxRequest = isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest';
+
+if (extension_loaded('tideways') && !$isAjaxRequest) {
     //include_once __DIR__.'/xhprof_lib/utils/xhprof_lib.php';
     //include_once __DIR__.'/xhprof_lib/utils/xhprof_runs.php';
     tideways_enable(TIDEWAYS_FLAGS_NO_SPANS);

+ 1 - 1
user_portal.php

@@ -142,7 +142,7 @@ if (isset($_COOKIE['defaultMyCourseView'.$userId]) &&
 // if teacher, session coach or admin, display the button to change te course view
 
 if ($displayMyCourseViewBySessionLink &&
-    (api_is_drh() || api_is_course_coach() || api_is_platform_admin() || api_is_session_admin() || api_is_teacher())
+    (api_is_drh() || api_is_session_general_coach() || api_is_platform_admin() || api_is_session_admin() || api_is_teacher())
 ) {
     $courseAndSessions['html'] = "<div class='view-by-session-link'>
 		<div class='btn-group pull-right'>

Vissa filer visades inte eftersom för många filer har ändrats