Browse Source

Merge with 1.11.x

jmontoyaa 8 years ago
parent
commit
9c477ce3b7
71 changed files with 1314 additions and 579 deletions
  1. 39 3
      app/Resources/public/css/base.css
  2. 1 1
      bower.json
  3. 34 30
      main/admin/add_users_to_usergroup.php
  4. 2 2
      main/admin/settings.lib.php
  5. 4 4
      main/admin/settings.php
  6. 31 1
      main/admin/user_export.php
  7. 5 1
      main/auth/courses.php
  8. 51 34
      main/auth/courses_controller.php
  9. 28 0
      main/auth/inscription.php
  10. 17 29
      main/cron/import_csv.php
  11. 9 7
      main/exercise/exercise.class.php
  12. 1 0
      main/exercise/exercise.php
  13. 13 14
      main/exercise/exercise_submit.php
  14. 15 24
      main/forum/editpost.php
  15. 99 14
      main/forum/forumfunction.inc.php
  16. 2 5
      main/forum/iframe_thread.php
  17. 15 0
      main/forum/index.php
  18. 18 4
      main/forum/viewforum.php
  19. 17 1
      main/forum/viewforumcategory.php
  20. 1 4
      main/forum/viewpost.php
  21. 20 5
      main/forum/viewthread.php
  22. 45 24
      main/forum/viewthread_nested.inc.php
  23. 63 16
      main/inc/ajax/forum.ajax.php
  24. 1 0
      main/inc/lib/CoursesAndSessionsCatalog.class.php
  25. 10 10
      main/inc/lib/api.lib.php
  26. 13 3
      main/inc/lib/auth.lib.php
  27. 1 3
      main/inc/lib/banner.lib.php
  28. 7 1
      main/inc/lib/course_description.lib.php
  29. 2 0
      main/inc/lib/diagnoser.lib.php
  30. 63 5
      main/inc/lib/display.lib.php
  31. 9 5
      main/inc/lib/extra_field.lib.php
  32. 27 32
      main/inc/lib/extra_field_value.lib.php
  33. 89 5
      main/inc/lib/sessionmanager.lib.php
  34. 1 0
      main/inc/lib/social.lib.php
  35. 17 10
      main/inc/lib/usermanager.lib.php
  36. 4 1
      main/install/configuration.dist.php
  37. 4 0
      main/lang/brazilian/trad4all.inc.php
  38. 7 1
      main/lang/english/trad4all.inc.php
  39. 114 14
      main/lang/faroese/trad4all.inc.php
  40. 7 1
      main/lang/french/trad4all.inc.php
  41. 1 0
      main/lang/german/trad4all.inc.php
  42. 6 0
      main/lang/spanish/trad4all.inc.php
  43. 16 9
      main/lp/learnpath.class.php
  44. 3 3
      main/lp/lp_build.php
  45. 61 22
      main/session/about.php
  46. 9 22
      main/social/friends.php
  47. 47 17
      main/social/groups.php
  48. 10 7
      main/social/home.php
  49. 24 24
      main/social/search.php
  50. 9 6
      main/template/default/auth/courses_categories.php
  51. 0 1
      main/template/default/layout/head.tpl
  52. 2 0
      main/template/default/layout/layout_1_col.tpl
  53. 2 0
      main/template/default/layout/layout_2_col.tpl
  54. 49 50
      main/template/default/layout/menu.tpl
  55. 3 1
      main/template/default/layout/page.tpl
  56. 34 40
      main/template/default/layout/page_header.tpl
  57. 3 1
      main/template/default/layout/show_header.tpl
  58. 3 1
      main/template/default/mail/mail.tpl
  59. 61 14
      main/template/default/session/about.tpl
  60. 1 1
      main/template/default/social/user_block.tpl
  61. 4 0
      main/work/work.lib.php
  62. 1 1
      plugin/google_maps/lang/english.php
  63. 1 1
      plugin/google_maps/lang/french.php
  64. 1 1
      plugin/google_maps/lang/spanish.php
  65. 2 2
      plugin/google_maps/view/map_coordinates.tpl
  66. 31 21
      plugin/vchamilo/install.php
  67. 5 0
      plugin/vchamilo/lang/english.php
  68. 11 2
      plugin/vchamilo/lib/Virtual.php
  69. 5 0
      plugin/vchamilo/views/editinstance_form.php
  70. 2 2
      src/Chamilo/CoreBundle/Entity/ExtraField.php
  71. 1 16
      tests/main/forum/forumfunction.inc.test.php

+ 39 - 3
app/Resources/public/css/base.css

@@ -21,10 +21,11 @@ body{
     position: absolute;
     bottom: 0;
     width: 100%;
-
+    padding-top: 20px;
+    padding-bottom: 20px;
 }
 #content-section, #page-wrap{
-    margin-bottom: 100px;
+    margin-bottom: 230px;
 }
 /* End Sticky footer style */
 select {
@@ -1234,7 +1235,10 @@ a.unread {
 #course_tools .content a {
   font-size: 12px;
 }
-
+.course-tool .make_visible_and_invisible img{
+    margin-top: -3px;
+    margin-right: 5px;
+}
 .big_icon img {
   padding:5px;
   -moz-border-radius:10px;
@@ -6444,3 +6448,35 @@ ul#toolnavbox-two li a.btn{
     height: 14.22222px;
 }
 
+input.form-control[type="color"] {
+    padding: 2px;
+}
+
+.form-separator {
+    font-weight: bold;
+    border-bottom: 2px solid #CCC;
+    padding-bottom: 12px;
+    color: #666;
+    margin-bottom: 20px;
+    margin-top: 20px;
+}
+
+/* Extra small devices (phones, less than 768px) */
+/* No media query since this is the default in Bootstrap */
+
+/* Small devices (tablets, 768px and up) */
+@media (min-width: 768px) {
+
+}
+
+/* Medium devices (desktops, 992px and up) */
+@media (min-width: 992px) {
+    div.navbar-collapse {
+        padding-left: 0;
+    }
+}
+
+/* Large devices (large desktops, 1200px and up) */
+@media (min-width: 1200px) {
+
+}

+ 1 - 1
bower.json

@@ -19,7 +19,7 @@
     "modernizr": "2.8.*",
     "jqueryui-timepicker-addon": "1.5.*",
     "image-map-resizer": "0.5.*",
-    "fullcalendar": "3.1.*",
+    "fullcalendar": "3.1.0",
     "simpleWebRTC": "1.15.*",
     "select2": "4.*",
     "MathJax": "2.5.*",

+ 34 - 30
main/admin/add_users_to_usergroup.php

@@ -27,7 +27,6 @@ $interbreadcrumb[]= array('url' => 'usergroups.php','name' => get_lang('Classes'
 $tool_name = get_lang('SubscribeUsersToClass');
 
 $id = intval($_GET['id']);
-
 $relation = isset($_REQUEST['relation']) ? intval($_REQUEST['relation']) : '';
 
 $htmlHeadXtra[] = '
@@ -98,7 +97,7 @@ $new_field_list = array();
 if (is_array($extra_field_list)) {
     foreach ($extra_field_list as $extra_field) {
         //if is enabled to filter and is a "<select>" field type
-        if ($extra_field[8]==1 && $extra_field[2]==4 ) {
+        if ($extra_field[8] == 1 && $extra_field[2] == 4) {
             $new_field_list[] = array(
                 'name'=> $extra_field[3],
                 'variable' => $extra_field[1], 'data'=> $extra_field[9]
@@ -139,7 +138,6 @@ if (isset($_GET['action']) && $_GET['action'] == 'export') {
     $groupInfo = $usergroup->get($id);
     $users = $usergroup->getUserListByUserGroup($id);
     if (!empty($users)) {
-
         $data = array(
             array('UserName', 'ClassName')
         );
@@ -152,11 +150,10 @@ if (isset($_GET['action']) && $_GET['action'] == 'export') {
     }
 }
 
-
 // Filter by Extra Fields
 $use_extra_fields = false;
 if (is_array($extra_field_list)) {
-    if (is_array($new_field_list) && count($new_field_list)>0 ) {
+    if (is_array($new_field_list) && count($new_field_list) > 0) {
         foreach ($new_field_list as $new_field) {
             $varname = 'field_'.$new_field['variable'];
             if (UserManager::is_extra_field_available($new_field['variable'])) {
@@ -250,6 +247,7 @@ if (!empty($complete_user_list)) {
                 continue;
             }
         }
+
         // Avoid anonymous users
         if ($item['status'] == 6) {
             continue;
@@ -347,38 +345,36 @@ echo '</div>';
 <?php
 echo '<legend>'.$tool_name.': '.$data['name'].'</legend>';
 
-
-    if (is_array($extra_field_list)) {
-        if (is_array($new_field_list) && count($new_field_list)>0) {
-            echo '<h3>'.get_lang('FilterByUser').'</h3>';
-            foreach ($new_field_list as $new_field) {
-                echo $new_field['name'];
-                $varname = 'field_'.$new_field['variable'];
-                echo '&nbsp;<select name="'.$varname.'">';
-                echo '<option value="0">--'.get_lang('Select').'--</option>';
-                foreach ($new_field['data'] as $option) {
-                    $checked='';
-                    if (isset($_POST[$varname])) {
-                        if ($_POST[$varname] == $option[1]) {
-                            $checked = 'selected="true"';
-                        }
+if (is_array($extra_field_list)) {
+    if (is_array($new_field_list) && count($new_field_list)>0) {
+        echo '<h3>'.get_lang('FilterByUser').'</h3>';
+        foreach ($new_field_list as $new_field) {
+            echo $new_field['name'];
+            $varname = 'field_'.$new_field['variable'];
+            echo '&nbsp;<select name="'.$varname.'">';
+            echo '<option value="0">--'.get_lang('Select').'--</option>';
+            foreach ($new_field['data'] as $option) {
+                $checked='';
+                if (isset($_POST[$varname])) {
+                    if ($_POST[$varname] == $option[1]) {
+                        $checked = 'selected="true"';
                     }
-                    echo '<option value="'.$option[1].'" '.$checked.'>'.$option[1].'</option>';
                 }
-                echo '</select>';
-                echo '&nbsp;&nbsp;';
+                echo '<option value="'.$option[1].'" '.$checked.'>'.$option[1].'</option>';
             }
-            echo '<input type="button" value="'.get_lang('Filter').'" onclick="validate_filter()" />';
-            echo '<br /><br />';
+            echo '</select>';
+            echo '&nbsp;&nbsp;';
         }
+        echo '<input type="button" value="'.get_lang('Filter').'" onclick="validate_filter()" />';
+        echo '<br /><br />';
     }
+}
 
 echo Display::input('hidden', 'id', $id);
 echo Display::input('hidden', 'form_sent', '1');
 echo Display::input('hidden', 'add_type', null);
 
 ?>
-
 <div class="row">
     <div class="col-md-5">
         <?php if ($data['group_type'] == UserGroup::SOCIAL_CLASS) { ?>
@@ -412,7 +408,12 @@ echo Display::input('hidden', 'add_type', null);
         'elements_not_in_name',
         $elements_not_in,
         '',
-        array('class'=>'col-md-7', 'multiple'=>'multiple','id'=>'elements_not_in','size'=>'15px'),
+        array(
+            'class' => 'form-control',
+            'multiple' => 'multiple',
+            'id' => 'elements_not_in',
+            'size' => '15px',
+        ),
         false
     );
     ?>
@@ -442,14 +443,18 @@ echo Display::input('hidden', 'add_type', null);
             'elements_in_name[]',
             $elements_in,
             '',
-            array('class'=>'col-md-7', 'multiple'=>'multiple','id'=>'elements_in','size'=>'15px'),
+            array(
+                'class' => 'form-control',
+                'multiple' => 'multiple',
+                'id' => 'elements_in',
+                'size' => '15px'
+            ),
             false
         );
         unset($sessionUsersList);
     ?>
     </div>
 </div>
-
 <?php
     echo '<button class="btn btn-primary" type="button" value="" onclick="valide()" ><em class="fa fa-check"></em>'.
         get_lang('SubscribeUsersToClass').'</button>';
@@ -469,7 +474,6 @@ function moveItem(origin , destination) {
 }
 
 function sortOptions(options) {
-
     newOptions = new Array();
     for (i = 0 ; i<options.length ; i++)
         newOptions[i] = options[i];

+ 2 - 2
main/admin/settings.lib.php

@@ -1364,7 +1364,7 @@ function generateSettingsForm($settings, $settings_by_access_list)
                 break;
             case 'textarea':
                 if ($row['variable'] == 'header_extra_content') {
-                    $file = api_get_path(SYS_PATH).api_get_home_path().'header_extra_content.txt';
+                    $file = api_get_home_path().'header_extra_content.txt';
                     $value = '';
                     if (file_exists($file)) {
                         $value = file_get_contents($file);
@@ -1372,7 +1372,7 @@ function generateSettingsForm($settings, $settings_by_access_list)
                     $form->addElement('textarea', $row['variable'], array(get_lang($row['title']), get_lang($row['comment'])) , array('rows'=>'10'), $hideme);
                     $default_values[$row['variable']] = $value;
                 } elseif ($row['variable'] == 'footer_extra_content') {
-                    $file = api_get_path(SYS_PATH).api_get_home_path().'footer_extra_content.txt';
+                    $file = api_get_home_path().'footer_extra_content.txt';
                     $value = '';
                     if (file_exists($file)) {
                         $value = file_get_contents($file);

+ 4 - 4
main/admin/settings.php

@@ -278,12 +278,12 @@ if (!empty($_GET['category']) &&
                 $old_value = api_get_setting($key);
                 switch ($key) {
                     case 'header_extra_content':
-                        file_put_contents(api_get_path(SYS_PATH).api_get_home_path().'/header_extra_content.txt', $value);
-                        $value = api_get_home_path().'/header_extra_content.txt';
+                        file_put_contents(api_get_home_path().'header_extra_content.txt', $value);
+                        $value = api_get_home_path().'header_extra_content.txt';
                         break;
                     case 'footer_extra_content':
-                        file_put_contents(api_get_path(SYS_PATH).api_get_home_path().'/footer_extra_content.txt', $value);
-                        $value = api_get_home_path().'/footer_extra_content.txt';
+                        file_put_contents(api_get_home_path().'footer_extra_content.txt', $value);
+                        $value = api_get_home_path().'footer_extra_content.txt';
                         break;
                     case 'InstitutionUrl':
                     case 'course_validation_terms_and_conditions_url':

+ 31 - 1
main/admin/user_export.php

@@ -15,12 +15,19 @@ api_protect_admin_script();
 $course_table = Database:: get_main_table(TABLE_MAIN_COURSE);
 $user_table = Database:: get_main_table(TABLE_MAIN_USER);
 $course_user_table = Database:: get_main_table(TABLE_MAIN_COURSE_USER);
+$session_course_user_table = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
 
 $tool_name = get_lang('ExportUserListXMLCSV');
 
 $interbreadcrumb[] = array("url" => 'index.php', "name" => get_lang('PlatformAdmin'));
 
 set_time_limit(0);
+$coursesSessions = [];
+$coursesSessions[''] = '--';
+
+$allCoursesFromSessions = SessionManager::getAllCoursesFromAllSessions();
+
+$coursesSessions = array_merge($coursesSessions, $allCoursesFromSessions);
 
 $courses = array ();
 $courses[''] = '--';
@@ -52,6 +59,7 @@ $form->addElement('radio', 'file_type', null, 'XLS', 'xls');
 
 $form->addElement('checkbox', 'addcsvheader', get_lang('AddCSVHeader'), get_lang('YesAddCSVHeader'),'1');
 $form->addElement('select', 'course_code', get_lang('OnlyUsersFromCourse'), $courses);
+$form->addElement('select', 'course_session', get_lang('OnlyUsersFromCourseSession'), $coursesSessions);
 $form->addButtonExport(get_lang('Export'));
 $form->setDefaults(array('file_type' => 'csv'));
 
@@ -62,6 +70,20 @@ if ($form->validate()) {
 	$courseInfo = api_get_course_info($course_code);
 	$courseId = $courseInfo['real_id'];
 
+	$courseSessionValue = explode(':', $export['course_session']);
+	$courseSessionCode = '';
+	$sessionId = 0;
+	$courseSessionId = 0;
+	$sessionInfo = [];
+
+	if (is_array($courseSessionValue) && isset($courseSessionValue[1])) {
+        $courseSessionCode = $courseSessionValue[0];
+        $sessionId = $courseSessionValue[1];
+        $courseSessionInfo= api_get_course_info($courseSessionCode);
+        $courseSessionId = $courseSessionInfo['real_id'];
+        $sessionInfo = api_get_session_info($sessionId);
+    }
+
 	$sql = "SELECT
 				u.user_id 	AS UserId,
 				u.lastname 	AS LastName,
@@ -81,7 +103,15 @@ if ($form->validate()) {
 						cu.relation_type<>".COURSE_RELATION_TYPE_RRHH."
 					ORDER BY lastname,firstname";
 		$filename = 'export_users_'.$course_code.'_'.api_get_local_time();
-	} else {
+	} else if (strlen($courseSessionCode) > 0) {
+        $sql .= " FROM $user_table u, $session_course_user_table scu
+					WHERE
+						u.user_id = scu.user_id AND
+						scu.c_id = $courseSessionId AND
+						scu.session_id = $sessionId 
+					ORDER BY lastname,firstname";
+        $filename = 'export_users_'.$courseSessionCode.'_'.$sessionInfo['name'].'_'.api_get_local_time();
+    } else {
 		if (api_is_multiple_url_enabled()) {
 			$tbl_user_rel_access_url= Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
 			$access_url_id = api_get_current_access_url_id();

+ 5 - 1
main/auth/courses.php

@@ -151,7 +151,11 @@ if (isset($_REQUEST['search_course'])) {
 // Subscribe user to course
 if (isset($_REQUEST['subscribe_course'])) {
     if ($ctok == $_GET['sec_token']) {
-        $courses_controller->subscribe_user($_GET['subscribe_course'], $_GET['search_term'], $categoryCode);
+        $courses_controller->subscribe_user(
+            $_GET['subscribe_course'],
+            $_GET['search_term'],
+            $categoryCode
+        );
     }
 }
 

+ 51 - 34
main/auth/courses_controller.php

@@ -217,35 +217,37 @@ class CoursesController
             return false;
         }
 
-        $message = '';
-        $error = '';
-        $content = '';
-        $result = [];
-
         // The course must be open in order to access the auto subscription
         if (in_array(
             $courseInfo['visibility'],
             array(COURSE_VISIBILITY_CLOSED, COURSE_VISIBILITY_REGISTERED, COURSE_VISIBILITY_HIDDEN))
         ) {
-            $error = get_lang('SubscribingNotAllowed');
+            Display::addFlash(
+                Display::return_message(
+                    get_lang('SubscribingNotAllowed'),
+                    'warning'
+                )
+            );
         } else {
+            // Redirect to subscription
+            if (api_is_anonymous()) {
+                header('Location: '.api_get_path(WEB_CODE_PATH).'auth/inscription.php&c='.$course_code);
+                exit;
+            }
             $result = $this->model->subscribe_user($course_code);
             if (!$result) {
-                $error = get_lang('CourseRegistrationCodeIncorrect');
+                Display::addFlash(
+                    Display::return_message(
+                        get_lang('CourseRegistrationCodeIncorrect'),
+                        'warning'
+                    )
+                );
             } else {
-                // Redirect directly to the course after subscription
-                $message = isset($result['message']) ? $result['message'] : '';
-                $content = isset($result['content']) ? $result['content'] : '';
+                Display::addFlash(
+                    Display::return_message($result['message'])
+                );
             }
         }
-
-        if (!empty($search_term)) {
-            $this->search_courses($search_term, $message, $error, $content);
-        } else {
-            $this->courses_categories('subscribe', $category_code, $message, $error, $content);
-        }
-
-        return $result;
     }
 
     /**
@@ -509,13 +511,21 @@ class CoursesController
      * @param string $sessionName The session name
      * @param boolean $checkRequirements Optional.
      *        Whether the session has requirement. Default is false
+     * @param bool $includeText Optional. Whether show the text in button
      * @return string The button HTML
      */
     public function getRegisteredInSessionButton(
         $sessionId,
         $sessionName,
-        $checkRequirements = false
+        $checkRequirements = false,
+        $includeText = false,
+        $btnBing = false
     ) {
+        if($btnBing){
+            $btnBing = 'btn-lg'; 
+        }else{
+            $btnBing = 'btn-sm';
+        }
         if ($checkRequirements) {
             $url = api_get_path(WEB_AJAX_PATH);
             $url .= 'sequence.ajax.php?';
@@ -526,16 +536,17 @@ class CoursesController
             ]);
 
             return Display::toolbarButton(
-                null,
+                get_lang('CheckRequirements'),
                 $url,
                 'shield',
                 'default',
                 [
-                    'class' => 'btn-sm ajax',
+                    'class' => $btnBing . ' ajax',
                     'data-title' => get_lang('CheckRequirements'),
                     'data-size' => 'md',
                     'title' => get_lang('CheckRequirements')
-                ]
+                ],
+                $includeText
             );
         }
 
@@ -555,16 +566,17 @@ class CoursesController
             ]);
 
             $result = Display::toolbarButton(
-                null,
+                get_lang('Subscribe'),
                 $url,
-                'sign-in',
-                'success',
+                'pencil',
+                'primary',
                 [
-                    'class' => 'btn-sm ajax',
+                    'class' => $btnBing .' ajax',
                     'data-title' => get_lang('AreYouSureToSubscribe'),
                     'data-size' => 'md',
                     'title' => get_lang('Subscribe')
-                ]
+                ],
+                $includeText
             );
         } else {
             $url .= 'inc/email_editor.php?';
@@ -574,11 +586,12 @@ class CoursesController
             ]);
 
             $result = Display::toolbarButton(
-                null,
+                get_lang('SubscribeToSessionRequest'),
                 $url,
-                'sign-in',
-                'success',
-                ['class' => 'btn-sm']
+                'pencil',
+                'primary',
+                ['class' => $btnBing],
+                $includeText
             );
         }
 
@@ -643,10 +656,14 @@ class CoursesController
             '';
         $sessionsBlocks = $this->getFormatedSessionsBlock($sessions);
 
-        // Get session list catalogue URL
-        //$sessionUrl = CourseCategory::getCourseCategoryUrl(1, $limit['length'], null, 0, 'display_sessions');
         // Get session search catalogue URL
-        $courseUrl = CourseCategory::getCourseCategoryUrl(1, $limit['length'], null, 0, 'subscribe');
+        $courseUrl = CourseCategory::getCourseCategoryUrl(
+            1,
+            $limit['length'],
+            null,
+            0,
+            'subscribe'
+        );
 
         $tpl = new Template();
         $tpl->assign('show_courses', CoursesAndSessionsCatalog::showCourses());

+ 28 - 0
main/auth/inscription.php

@@ -131,6 +131,17 @@ $user_already_registered_show_terms = false;
 if (api_get_setting('allow_terms_conditions') == 'true') {
     $user_already_registered_show_terms = isset($_SESSION['term_and_condition']['user_id']);
 }
+// Direct Link Session Subscription feature #12220
+$sessionRedirect = isset($_REQUEST['s']) && !empty($_REQUEST['s']) ? $_REQUEST['s'] : null;
+$onlyOneCourseSessionRedirect = isset($_REQUEST['cr']) && !empty($_REQUEST['cr']) ? $_REQUEST['cr'] : null;
+
+if (api_get_configuration_value('allow_redirect_to_session_after_inscription_about')) {
+
+    if (!empty($sessionRedirect)) {
+        Session::write('session_redirect', $sessionRedirect);
+        Session::write('only_one_course_session_redirect', $onlyOneCourseSessionRedirect);
+    }
+}
 
 // Direct Link Subscription feature #5299
 $course_code_redirect = isset($_REQUEST['c']) && !empty($_REQUEST['c']) ? $_REQUEST['c'] : null;
@@ -658,6 +669,7 @@ if ($blockButton) {
 }
 
 $course_code_redirect = Session::read('course_redirect');
+$sessionToRedirect = Session::read('session_redirect');
 
 if ($form->validate()) {
     $values = $form->getSubmitValues(1);
@@ -804,6 +816,19 @@ if ($form->validate()) {
                 Database::query($sql);
             }
 
+            // Saving user to Session if it was set
+            if (!empty($sessionToRedirect)) {
+                $sessionInfo = api_get_session_info($sessionToRedirect);
+                if (!empty($sessionInfo)) {
+                    SessionManager::subscribe_users_to_session(
+                        $sessionToRedirect,
+                        [$user_id],
+                        SESSION_VISIBLE_READ_ONLY,
+                        false
+                    );
+                }
+            }
+
             // Saving user to course if it was set.
             if (!empty($course_code_redirect)) {
                 $course_info = api_get_course_info($course_code_redirect);
@@ -1011,6 +1036,7 @@ if ($form->validate()) {
         }
     }
 
+    SessionManager::redirectToSession();
     $form_data = CourseManager::redirectToCourse($form_data);
 
     $form_register = new FormValidator('form_register', 'post', $form_data['action']);
@@ -1029,6 +1055,8 @@ if ($form->validate()) {
     // Just in case
     Session::erase('course_redirect');
     Session::erase('exercise_redirect');
+    Session::erase('session_redirect');
+    Session::erase('only_one_course_session_redirect');
 
     if (CustomPages::enabled()) {
         CustomPages::display(

+ 17 - 29
main/cron/import_csv.php

@@ -348,14 +348,14 @@ class ImportCsv
 
         $row['teachers'] = array();
         if (isset($row['Teacher']) && !empty($row['Teacher'])) {
-            //$this->logger->addInfo("Teacher list found: ".$row['Teacher']);
+            $this->logger->addInfo("Teacher list found: ".$row['Teacher']);
             $teachers = explode(',', $row['Teacher']);
             if (!empty($teachers)) {
                 foreach ($teachers as $teacherUserName) {
                     $teacherUserName = trim($teacherUserName);
                     $userInfo = api_get_user_info_from_username($teacherUserName);
                     if (!empty($userInfo)) {
-                        //$this->logger->addInfo("Username found: $teacherUserName");
+                        $this->logger->addInfo("Username found: $teacherUserName");
                         $row['teachers'][] = $userInfo['user_id'];
                     }
                 }
@@ -830,7 +830,6 @@ class ImportCsv
 
                 if (empty($teacherId)) {
                     $errorFound = true;
-
                     $this->logger->addInfo(
                         "No teacher found in course code : '$courseCode' and session: '$sessionId'"
                     );
@@ -857,11 +856,6 @@ class ImportCsv
                     $errorFound = true;
                 }
 
-                // If old events do nothing.
-                /*if (api_strtotime($startDate) < time()) {
-                    continue;
-                }*/
-
                 if ($errorFound == false) {
                     $eventsToCreate[] = array(
                         'start' => $startDate,
@@ -919,6 +913,7 @@ class ImportCsv
             ];
 
             $eventsToCreateFinal = [];
+
             foreach ($eventsToCreate as $event) {
                 $update = false;
                 $item = null;
@@ -945,15 +940,7 @@ class ImportCsv
                     );
 
                     if (!empty($item)) {
-                        $this->logger->addInfo(
-                            "Event #$externalEventId was already added. Updating ..."
-                        );
                         $update = true;
-                        //continue;
-                    } else {
-                        $this->logger->addInfo(
-                            "Event #$externalEventId was not added. Preparing to be created ..."
-                        );
                     }
                 }
 
@@ -987,6 +974,8 @@ class ImportCsv
                 $update = $event['update'];
                 $externalEventId = $event['external_event_id'];
 
+                $info = 'Course: '.$courseInfo['real_id'].' ('.$courseInfo['code'].') - Session: '.$event['session_id'];
+
                 $agenda = new Agenda(
                     'course',
                     $event['sender_id'],
@@ -1004,17 +993,16 @@ class ImportCsv
                 // To use the event comment you need
                 // ALTER TABLE c_calendar_event ADD COLUMN comment TEXT;
                 // add in configuration.php allow_agenda_event_comment = true
-
                 if (empty($courseInfo)) {
                     $this->logger->addInfo(
-                        "No course found for added: #".$event['course_id']." Skipping ..."
+                        "No course found for event #$externalEventId Course #".$event['course_id']." Skipping ..."
                     );
                     continue;
                 }
 
                 if (empty($event['sender_id'])) {
                     $this->logger->addInfo(
-                        "No sender found: #".$event['sender_id']." Skipping ..."
+                        "No sender found for event #$externalEventId Send #".$event['sender_id']." Skipping ..."
                     );
                     continue;
                 }
@@ -1037,7 +1025,7 @@ class ImportCsv
                 $startDatePlusDays = api_strtotime("$days weekdays");
 
                 $this->logger->addInfo(
-                    "startDatePlusDays: ".$startDatePlusDays.' - First date: '.$firstDate
+                    "startDatePlusDays: ".api_get_utc_datetime($startDatePlusDays).' - First date: '.$firstDate
                 );
 
                 // Send
@@ -1098,7 +1086,7 @@ class ImportCsv
 
                     if (count($announcementsWithTitleList) == 0) {
                         $this->logger->addInfo(
-                            "Mail to be sent because start date: ".$event['start']
+                            "Mail to be sent because start date: ".$event['start']." and no announcement found."
                         );
                         $announcementId = AnnouncementManager::add_announcement(
                             $courseInfo,
@@ -1118,7 +1106,7 @@ class ImportCsv
 
                         if ($announcementId) {
                             $this->logger->addInfo(
-                                "Announcement added: ".(int)($announcementId)
+                                "Announcement added: ".(int)($announcementId)." in $info"
                             );
                             $this->logger->addInfo(
                                 "<<--SENDING MAIL-->>"
@@ -1135,7 +1123,7 @@ class ImportCsv
                     } else {
                         $report['mail_not_sent_announcement_exists']++;
                         $this->logger->addInfo(
-                            "Mail NOT sent an announcement seems to be already saved in this course-session"
+                            "Mail NOT sent. An announcement seems to be already saved in $info"
                         );
                     }
                 } else {
@@ -1165,11 +1153,11 @@ class ImportCsv
 
                     if ($eventResult !== false) {
                         $this->logger->addInfo(
-                            "Event updated: #".$item['item_id']
+                            "Event updated #".$item['item_id']." External cal Id: (".$externalEventId.") $info"
                         );
                     } else {
                         $this->logger->addInfo(
-                            "Error while updating event."
+                            "Error while updating event with external id: $externalEventId"
                         );
                     }
                 } else {
@@ -1199,11 +1187,11 @@ class ImportCsv
                             )
                         );
                         $this->logger->addInfo(
-                            "Event added: #$eventId"
+                            "Event added: #$eventId External cal id: (".$externalEventId.") $info"
                         );
                     } else {
                         $this->logger->addInfo(
-                            "Error while creating event."
+                            "Error while creating event external id: $externalEventId"
                         );
                     }
                 }
@@ -1314,7 +1302,7 @@ class ImportCsv
                         CourseManager::updateTeachers(
                             $courseInfo,
                             $row['teachers'],
-                            true,
+                            false,
                             false,
                             false,
                             $teacherBackup
@@ -1886,7 +1874,7 @@ class ImportCsv
             false, // updateCourseCoaches
             true, // sessionWithCoursesModifier
             true, //$addOriginalCourseTeachersAsCourseSessionCoaches
-            true, //$removeAllTeachersFromCourse
+            false, //$removeAllTeachersFromCourse
             1, // $showDescription,
             $teacherBackup,
             $groupBackup

+ 9 - 7
main/exercise/exercise.class.php

@@ -3044,21 +3044,20 @@ class Exercise
                 }).bind('timer', function () {
                     send_form();
                 });
-
             }
 
             function send_form() {
                 if ($('#exercise_form').length) {
                     $('#exercise_form').submit();
                 } else {
-                    //In reminder
+                    // In exercise_reminder.php
                     final_submit();
                 }
             }
 
             function onExpiredTimeExercise() {
                 $('#wrapper-clock').hide();
-                $('#exercise_form').hide();
+                //$('#exercise_form').hide();
                 $('#expired-message-id').show();
 
                 //Fixes bug #5263
@@ -3067,7 +3066,6 @@ class Exercise
             }
 
 			$(document).ready(function() {
-
 				var current_time = new Date().getTime();
                 var time_left    = parseInt(".$time_left."); // time in seconds when using minutes there are some seconds lost
 				var expired_time = current_time + (time_left*1000);
@@ -6382,7 +6380,7 @@ class Exercise
         return $result;
     }
 
-    function return_time_left_div()
+    public function return_time_left_div()
     {
         $html = '<div id="clock_warning" style="display:none">';
         $html .= Display::return_message(
@@ -8227,8 +8225,12 @@ class Exercise
             $numberRandomQuestions = $this->random;
             $questionScoreList = array();
             for ($i = 1; $i <= count($questionList); $i++) {
-                $tmpobj_question = Question::read($questionList[$i]);
-                $questionScoreList[] = $tmpobj_question->weighting;
+                if (isset($questionList[$i])) {
+                    $tmpobj_question = Question::read($questionList[$i]);
+                    if (is_object($tmpobj_question)) {
+                        $questionScoreList[] = $tmpobj_question->weighting;
+                    }
+                }
             }
             rsort($questionScoreList);
             // add the first $numberRandomQuestions value of score array to get max_score

+ 1 - 0
main/exercise/exercise.php

@@ -69,6 +69,7 @@ Session::erase('objQuestion');
 Session::erase('objAnswer');
 Session::erase('questionList');
 Session::erase('exerciseResult');
+Session::erase('firstTime');
 
 //General POST/GET/SESSION/COOKIES parameters recovery
 $origin = isset($_REQUEST['origin']) ? Security::remove_XSS($_REQUEST['origin']) : null;

+ 13 - 14
main/exercise/exercise_submit.php

@@ -298,10 +298,6 @@ if ($objExercise->selectAttempts() > 0) {
     }
 }
 
-if ($debug) {
-    error_log("4. Setting the exe_id: $exe_id");
-}
-
 /* 5. Getting user exercise info (if the user took the exam before)
    generating exe_id */
 $exercise_stat_info = $objExercise->get_stat_track_exercise_info(
@@ -316,9 +312,8 @@ $questionListUncompressed = $objExercise->getQuestionListWithMediasUncompressed(
 Session::write('question_list_uncompressed', $questionListUncompressed);
 
 $clock_expired_time = null;
-
 if (empty($exercise_stat_info)) {
-    if ($debug)  error_log('5  $exercise_stat_info is empty ');
+    if ($debug) error_log('5  $exercise_stat_info is empty ');
 	$total_weight = 0;
 	$questionList = $objExercise->get_validated_question_list();
 	foreach ($questionListUncompressed as $question_id) {
@@ -358,6 +353,7 @@ if (empty($exercise_stat_info)) {
 	$exe_id = $exercise_stat_info['exe_id'];
     // Remember last question id position.
     $isFirstTime = Session::read('firstTime');
+
     if ($isFirstTime && $objExercise->type == ONE_PER_PAGE) {
         $resolvedQuestions = Event::getAllExerciseEventByExeId($exe_id);
         if (!empty($resolvedQuestions) &&
@@ -485,7 +481,7 @@ if ($time_control) {
 	        if ($debug) {error_log('7.11. Setting the $_SESSION[expired_time]: '.$_SESSION['expired_time'][$current_expired_time_key] ); };
         }
     } else {
-        $clock_expired_time =  $_SESSION['expired_time'][$current_expired_time_key];
+        $clock_expired_time = $_SESSION['expired_time'][$current_expired_time_key];
     }
 } else {
     if ($debug) { error_log("7 No time control"); };
@@ -503,7 +499,6 @@ if ($time_control) { //Sends the exercise form when the expired time is finished
 }
 
 //in LP's is enabled the "remember question" feature?
-
 if (!isset($_SESSION['questionList'])) {
     // selects the list of question ID
     $questionList = $objExercise->get_validated_question_list();
@@ -527,7 +522,11 @@ if (!empty($questionList)) {
 }
 
 if ($current_question > $question_count) {
-    $current_question = 0;
+    // If time control then don't change the current question, otherwise there will be a loop.
+    // @todo
+    if ($time_control == false) {
+        $current_question = 0;
+    }
 }
 
 if ($formSent && isset($_POST)) {
@@ -600,7 +599,7 @@ if ($formSent && isset($_POST)) {
 
     // the script "exercise_result.php" will take the variable $exerciseResult from the session
     Session::write('exerciseResult', $exerciseResult);
-    Session::write('remind_list', $remind_list);
+//    Session::write('remind_list', $remind_list);
     Session::write('exerciseResultCoordinates',$exerciseResultCoordinates);
 
     // if all questions on one page OR if it is the last question (only for an exercise with one question per page)
@@ -766,6 +765,7 @@ $is_visible_return = $objExercise->is_visible(
     $learnpath_item_id,
     $learnpath_item_view_id
 );
+
 if ($is_visible_return['value'] == false) {
     echo $is_visible_return['message'];
     if ($origin != 'learnpath') {
@@ -774,6 +774,7 @@ if ($is_visible_return['value'] == false) {
     exit;
 }
 
+$exercise_timeover = false;
 $limit_time_exists = (!empty($objExercise->start_time) || !empty($objExercise->end_time)) ? true : false;
 
 if ($limit_time_exists) {
@@ -789,8 +790,6 @@ if ($limit_time_exists) {
     if ($_SERVER['REQUEST_METHOD'] != 'POST') {
         if (!empty($objExercise->end_time)) {
             $exercise_timeover = (($time_now - $exercise_end_time) > 0) ? true : false;
-        } else {
-            $exercise_timeover = false;
         }
     }
 
@@ -1135,12 +1134,12 @@ if (!empty($error)) {
 
 	// Show list of questions
     $i = 1;
-    $attempt_list = array();
+    $attempt_list = [];
     if (isset($exe_id)) {
         $attempt_list = Event::getAllExerciseEventByExeId($exe_id);
     }
 
-    $remind_list  = array();
+    $remind_list = [];
     if (isset($exercise_stat_info['questions_to_check']) && !empty($exercise_stat_info['questions_to_check'])) {
         $remind_list = explode(',', $exercise_stat_info['questions_to_check']);
     }

+ 15 - 24
main/forum/editpost.php

@@ -125,11 +125,6 @@ $htmlHeadXtra[] = <<<JS
     </script>
 JS;
 
-if ($origin == 'learnpath') {
-    Display::display_reduced_header();
-} else {
-    Display::display_header();
-}
 /* Is the user allowed here? */
 
 // The user is not allowed here if
@@ -139,15 +134,13 @@ if ($origin == 'learnpath') {
 // 4. if editing of replies is not allowed
 // The only exception is the course manager
 // I have split this is several pieces for clarity.
-//if (!api_is_allowed_to_edit() AND (($current_forum_category['visibility'] == 0 OR $current_forum['visibility'] == 0) OR ($current_forum_category['locked'] <> 0 OR $current_forum['locked'] <> 0 OR $current_thread['locked'] <> 0))) {
 if (!api_is_allowed_to_edit(null, true) &&
-    (($current_forum_category && $current_forum_category['visibility'] == 0) ||
-        $current_forum['visibility'] == 0)
+    (
+        ($current_forum_category && $current_forum_category['visibility'] == 0) ||
+        $current_forum['visibility'] == 0
+    )
 ) {
-    $forum_allow = forum_not_allowed_here();
-    if ($forum_allow === false) {
-        exit;
-    }
+    api_not_allowed(true);
 }
 
 if (!api_is_allowed_to_edit(null, true) &&
@@ -157,28 +150,26 @@ if (!api_is_allowed_to_edit(null, true) &&
         $current_thread['locked'] <> 0
     )
 ) {
-    $forum_allow = forum_not_allowed_here();
-    if ($forum_allow === false) {
-        exit;
-    }
+    api_not_allowed(true);
 }
 
 if (!$_user['user_id'] && $current_forum['allow_anonymous'] == 0) {
-    $forum_allow = forum_not_allowed_here();
-    if ($forum_allow === false) {
-        exit;
-    }
+    api_not_allowed(true);
 }
+
 $group_id = api_get_group_id();
 
 if (!api_is_allowed_to_edit(null, true) &&
     $current_forum['allow_edit'] == 0 &&
     !GroupManager::is_tutor_of_group(api_get_user_id(), $group_properties['iid'])
 ) {
-    $forum_allow = forum_not_allowed_here();
-    if ($forum_allow === false) {
-        exit;
-    }
+    api_not_allowed(true);
+}
+
+if ($origin == 'learnpath') {
+    Display::display_reduced_header();
+} else {
+    Display::display_header();
 }
 
 // Action links

+ 99 - 14
main/forum/forumfunction.inc.php

@@ -25,6 +25,7 @@ use Chamilo\CourseBundle\Entity\CForumThread;
  * @todo several functions have to be moved to the itemmanager library
  * @todo displaying icons => display library
  * @todo complete the missing phpdoc the correct order should be
+ * @todo convert into a class
  */
 
 define('FORUM_NEW_POST', 0);
@@ -1931,8 +1932,14 @@ function getThreadInfo($threadId, $cId)
  *
  * @return array containing all the information about the posts of a given thread
  */
-function getPosts($forumInfo, $threadId, $orderDirection = 'ASC', $recursive = false, $postId = null, $depth = -1)
-{
+function getPosts(
+    $forumInfo,
+    $threadId,
+    $orderDirection = 'ASC',
+    $recursive = false,
+    $postId = null,
+    $depth = -1
+) {
     $em = Database::getManager();
 
     if (api_is_allowed_to_edit(false, true)) {
@@ -1957,15 +1964,11 @@ function getPosts($forumInfo, $threadId, $orderDirection = 'ASC', $recursive = f
             $filterModerated = false;
         }
     } else {
-        if (GroupManager::is_tutor_of_group(api_get_user_id(), $groupInfo['iid']) || api_is_allowed_to_edit()) {
+        if (GroupManager::is_tutor_of_group(api_get_user_id(), $groupInfo['iid']) || api_is_allowed_to_edit(false, true)) {
             $filterModerated = false;
         }
     }
 
-    if ($filterModerated && $forumInfo['moderated'] == 1) {
-        $criteria->andWhere(Criteria::expr()->eq('status', 1));
-    }
-
     if ($recursive) {
         $criteria->andWhere(Criteria::expr()->eq('postParentId', $postId));
     }
@@ -1975,8 +1978,20 @@ function getPosts($forumInfo, $threadId, $orderDirection = 'ASC', $recursive = f
         ->addCriteria($criteria)
         ->addOrderBy('p.postId', $orderDirection);
 
-    $posts = $qb->getQuery()->getResult();
 
+    if ($filterModerated && $forumInfo['moderated'] == 1) {
+        if (!api_is_allowed_to_edit(false, true)) {
+            $userId = api_get_user_id();
+            $qb->andWhere(
+                "p.status = 1 OR 
+                    (p.status = ".CForumPost::STATUS_WAITING_MODERATION." AND p.posterId = $userId) OR
+                    (p.status IS NULL AND p.posterId = $userId) 
+                    "
+            );
+        }
+    }
+
+    $posts = $qb->getQuery()->getResult();
     $depth++;
 
     $list = [];
@@ -2018,7 +2033,6 @@ function getPosts($forumInfo, $threadId, $orderDirection = 'ASC', $recursive = f
         if (!$recursive) {
             continue;
         }
-
         $list = array_merge(
             $list,
             getPosts(
@@ -3939,6 +3953,8 @@ function updateThreadInfo($thread_id, $last_post_id, $post_date)
  * This function is called when the user is not allowed in this forum/thread/...
  * @return bool display message of "not allowed"
  *
+ * @deprecated use api_not_allowed()
+ *
  * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  * @version february 2006, dokeos 1.8
  */
@@ -6055,24 +6071,93 @@ function getForumCategoryByTitle($title, $courseId, $sessionId = 0)
     return $resultData;
 }
 
-function getPostStatus($current_forum, $row)
+/**
+ * @param array $current_forum
+ * @param array $row
+ *
+ * @return string
+ */
+function getPostStatus($current_forum, $row, $addWrapper = true)
 {
     $statusIcon = '';
     if ($current_forum['moderated']) {
-        $statusIcon = '<br /><br />';
+        if ($addWrapper) {
+            $statusIcon = '<br /><br /><span id="status_post_'.$row['iid'].'">';
+        }
         $row['status'] = empty($row['status']) ? 2 : $row['status'];
+
+        $addUrl = false;
+        if (api_is_allowed_to_edit(false, true)) {
+            $addUrl = true;
+        }
+
+        $label = '';
+        $icon = '';
+        $buttonType = '';
         switch ($row['status']) {
             case CForumPost::STATUS_VALIDATED:
-                $statusIcon .= Display::label(get_lang('Validated'), 'success');
+                $label = get_lang('Validated');
+                $icon = 'check-circle';
+                $buttonType = 'success';
                 break;
             case CForumPost::STATUS_WAITING_MODERATION:
-                $statusIcon .= Display::label(get_lang('WaitingModeration'), 'warning');
+                $label = get_lang('WaitingModeration');
+                $icon = 'warning';
+                $buttonType = 'warning';
                 break;
             case CForumPost::STATUS_REJECTED:
-                $statusIcon .= Display::label(get_lang('Rejected'), 'danger');
+                $label = get_lang('Rejected');
+                $icon = 'minus-circle';
+                $buttonType = 'danger';
                 break;
         }
+
+        if ($addUrl) {
+            $statusIcon .= Display::toolbarButton(
+                $label.'&nbsp;',
+                'javascript:void(0)',
+                $icon,
+                $buttonType,
+                ['class' => 'change_post_status']
+            );
+        } else {
+            $statusIcon .= Display::label(
+                Display::returnFontAwesomeIcon($icon).$label,
+                $buttonType
+            );
+        }
+
+        if ($addWrapper) {
+            $statusIcon .= '</span>';
+        }
     }
 
     return $statusIcon;
 }
+
+/**
+ * @param array $forumInfo
+ * @param int $threadId
+ * @param int $status
+ * @return mixed
+ */
+function getCountPostsWithStatus($status, $forumInfo, $threadId = null)
+{
+    $em = Database::getManager();
+    $criteria = Criteria::create();
+    $criteria
+        ->where(Criteria::expr()->eq('status', $status))
+        ->andWhere(Criteria::expr()->eq('cId', $forumInfo['c_id']))
+        ->andWhere(Criteria::expr()->eq('visible', 1))
+    ;
+
+    if (!empty($threadId)) {
+        $criteria->andWhere(Criteria::expr()->eq('threadId', $threadId));
+    }
+
+    $qb = $em->getRepository('ChamiloCourseBundle:CForumPost')->createQueryBuilder('p');
+    $qb->select('count(p.iid)')
+        ->addCriteria($criteria);
+
+    return $qb->getQuery()->getSingleScalarResult();
+}

+ 2 - 5
main/forum/iframe_thread.php

@@ -51,11 +51,8 @@ $current_forum_category = get_forumcategory_information(
 
 // if the user is not a course administrator and the forum is hidden
 // then the user is not allowed here.
-if (!api_is_allowed_to_edit(false, true) AND ($current_forum['visibility'] == 0 OR $current_thread['visibility'] == 0)) {
-    $forum_allow = forum_not_allowed_here();
-    if ($forum_allow === false) {
-        exit;
-    }
+if (!api_is_allowed_to_edit(false, true) && ($current_forum['visibility'] == 0 || $current_thread['visibility'] == 0)) {
+    api_not_allowed(false);
 }
 
 $course_id = api_get_course_int_id();

+ 15 - 0
main/forum/index.php

@@ -2,6 +2,7 @@
 /* For licensing terms, see /license.txt */
 
 use ChamiloSession as Session;
+use Chamilo\CourseBundle\Entity\CForumPost;
 
 /**
  * These files are a complete rework of the forum. The database structure is
@@ -509,6 +510,20 @@ if (is_array($forumCategories)) {
                                 'class'=>'description'
                             ]
                         );
+
+                        if ($forum['moderated'] == 1 && api_is_allowed_to_edit(false, true)) {
+                            $waitingCount = getCountPostsWithStatus(
+                                CForumPost::STATUS_WAITING_MODERATION,
+                                $forum
+                            );
+                            if (!empty($waitingCount)) {
+                                $html .= Display::label(
+                                    get_lang('PostsPendingModeration'). ': '.$waitingCount,
+                                    'warning'
+                                );
+                            }
+                        }
+
                         $html .= '</div>';
                         $html .= '</div>';
 

+ 18 - 4
main/forum/viewforum.php

@@ -1,6 +1,8 @@
 <?php
 /* For licensing terms, see /license.txt */
 
+use Chamilo\CourseBundle\Entity\CForumPost;
+
 /**
  * These files are a complete rework of the forum. The database structure is
  * based on phpBB but all the code is rewritten. A lot of new functionalities
@@ -460,11 +462,8 @@ if (is_array($threads)) {
                 $newPost = '';
             }
 
-            if ($row['thread_sticky'] == 1) {
-                //$sticky = Display::return_icon('exclamation.gif');
-            }
-
             $name = api_get_person_name($row['firstname'], $row['lastname']);
+
             $linkPostForum = '<a href="viewthread.php?' . api_get_cidreq() . '&forum=' . Security::remove_XSS($my_forum)
                 . "&origin=$origin&thread={$row['thread_id']}&search="
                 . Security::remove_XSS(urlencode($my_search)) . '">'
@@ -514,6 +513,21 @@ if (is_array($threads)) {
             );
             $html .= '<p>'. get_lang('By') .' ' .$authorName.'</p>';
             $html .= '<p>' . api_convert_and_format_date($row['insert_date']) . '</p>';
+
+            if ($current_forum['moderated'] == 1 && api_is_allowed_to_edit(false, true)) {
+                $waitingCount = getCountPostsWithStatus(
+                    CForumPost::STATUS_WAITING_MODERATION,
+                    $current_forum,
+                    $row['thread_id']
+                );
+                if (!empty($waitingCount)) {
+                    $html .= Display::label(
+                        get_lang('PostsPendingModeration'). ': '.$waitingCount,
+                        'warning'
+                    );
+                }
+            }
+
             $html .= '</div>';
             $html .= '</div>';
 

+ 17 - 1
main/forum/viewforumcategory.php

@@ -1,6 +1,8 @@
 <?php
 /* For licensing terms, see /license.txt */
 
+use Chamilo\CourseBundle\Entity\CForumPost;
+
 /**
  * These files are a complete rework of the forum. The database structure is
  * based on phpBB but all the code is rewritten. A lot of new functionalities
@@ -268,7 +270,7 @@ if ($action_forums != 'add') {
             // SHOULD WE SHOW THIS PARTICULAR FORUM
             // you are teacher => show forum
 
-            if (api_is_allowed_to_edit(false,true)) {
+            if (api_is_allowed_to_edit(false, true)) {
                 //echo 'teacher';
                 $show_forum = true;
             } else {
@@ -390,6 +392,20 @@ if ($action_forums != 'add') {
                         'class' => 'description'
                     )
                 );
+
+                if ($forum['moderated'] == 1 && api_is_allowed_to_edit(false, true)) {
+                    $waitingCount = getCountPostsWithStatus(
+                        CForumPost::STATUS_WAITING_MODERATION,
+                        $forum
+                    );
+                    if (!empty($waitingCount)) {
+                        $html .= Display::label(
+                            get_lang('PostsPendingModeration'). ': '.$waitingCount,
+                            'warning'
+                        );
+                    }
+                }
+
                 $html .= '</div>';
                 $html .= '</div>';
                 $html .= '<div class="col-md-6">';

+ 1 - 4
main/forum/viewpost.php

@@ -85,10 +85,7 @@ if ($origin == 'learnpath') {
 if (!api_is_allowed_to_edit(false, true) &&
     ($current_forum['visibility'] == 0 || $current_thread['visibility'] == 0)
 ) {
-    $forum_allow = forum_not_allowed_here();
-    if ($forum_allow === false) {
-        exit;
-    }
+    api_not_allowed(false);
 }
 
 /* Actions */

+ 20 - 5
main/forum/viewthread.php

@@ -59,6 +59,25 @@ $groupId = api_get_group_id();
 $group_properties = GroupManager::get_group_properties($groupId);
 $sessionId = api_get_session_id();
 
+$ajaxURL = api_get_path(WEB_AJAX_PATH).'forum.ajax.php?'.api_get_cidreq().'&a=change_post_status';
+$htmlHeadXtra[] = '<script>
+$(function() {
+    $("span").on("click", ".change_post_status", function() {
+        var updateDiv = $(this).parent();
+        var postId = updateDiv.attr("id");
+                
+        $.ajax({
+            url: "'.$ajaxURL.'&post_id="+postId,
+            type: "GET",
+            success: function(data) {
+                updateDiv.html(data);
+            }                
+        });
+    });  
+});
+    
+</script>';
+
 if ($origin == 'group') {
     $interbreadcrumb[] = array(
         'url' => api_get_path(WEB_CODE_PATH).'group/group.php?'.api_get_cidreq(),
@@ -113,10 +132,7 @@ if (
     !api_is_allowed_to_edit(false, true) &&
     ($current_forum['visibility'] == 0 || $current_thread['visibility'] == 0)
 ) {
-    $forum_allow = forum_not_allowed_here();
-    if ($forum_allow === false) {
-        exit;
-    }
+    api_not_allowed(false);
 }
 
 /* Actions */
@@ -220,7 +236,6 @@ if ($my_message != 'PostDeletedSpecial') {
     echo '</div>&nbsp;';
 
     /* Display Forum Category and the Forum information */
-
     if (!isset($_SESSION['view'])) {
         $viewMode = $current_forum['default_view'];
     } else {

+ 45 - 24
main/forum/viewthread_nested.inc.php

@@ -1,6 +1,8 @@
 <?php
 /* For licensing terms, see /license.txt */
 
+use Chamilo\CourseBundle\Entity\CForumPost;
+
 /**
  * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  * @author Julio Montoya <gugli100@gmail.com> UI Improvements + lots of bugfixes
@@ -37,6 +39,8 @@ $userId = api_get_user_id();
 $groupInfo = GroupManager::get_group_properties($group_id);
 $postCount = 1;
 
+$allowUserImageForum = api_get_course_setting('allow_user_image_forum');
+
 foreach ($rows as $post) {
     // The style depends on the status of the message: approved or not.
     if ($post['visible'] == '0') {
@@ -55,11 +59,9 @@ foreach ($rows as $post) {
     $html .= '<div class="col-md-offset-' . $indent . '" >';
     $html .= '<div class="panel panel-default forum-post">';
     $html .= '<div class="panel-body">';
-
     $html .= '<div class="row">';
     $html .= '<div class="col-md-2">';
 
-
     $username = sprintf(get_lang('LoginX'), $post['username']);
     if ($post['user_id'] == '0') {
         $name = $post['poster_name'];
@@ -68,7 +70,7 @@ foreach ($rows as $post) {
     }
 
     if ($origin != 'learnpath') {
-        if (api_get_course_setting('allow_user_image_forum')) {
+        if ($allowUserImageForum) {
             $html .= '<div class="thumbnail">' . display_user_image($post['user_id'], $name, $origin) . '</div>';
         }
 
@@ -78,7 +80,7 @@ foreach ($rows as $post) {
             array('class' => 'title-username')
         );
     } else {
-        if (api_get_course_setting('allow_user_image_forum')) {
+        if ($allowUserImageForum) {
             $html .= '<div class="thumbnail">' . display_user_image($post['user_id'], $name, $origin) . '</div>';
         }
 
@@ -95,13 +97,13 @@ foreach ($rows as $post) {
     if ($origin != 'learnpath') {
         $html .= Display::tag(
             'p',
-            api_convert_and_format_date($post['post_date']),
+            Display::dateToStringAgoAndLongDate($post['post_date']),
             array('class' => 'post-date')
         );
     } else {
         $html .= Display::tag(
             'p',
-            api_convert_and_format_date($post['post_date'], DATE_TIME_FORMAT_SHORT),
+            Display::dateToStringAgoAndLongDate($post['post_date']),
             array('class' => 'text-muted')
         );
     }
@@ -111,25 +113,34 @@ foreach ($rows as $post) {
     $id_attach = !empty($attachment_list) ? $attachment_list['iid'] : '';
 
     $iconEdit = '';
+    $editButton = '';
     // The user who posted it can edit his thread only if the course admin allowed this in the properties of the forum
     // The course admin him/herself can do this off course always
 
-    if (
-    (isset($groupInfo['iid']) &&GroupManager::is_tutor_of_group(api_get_user_id(), $groupInfo['iid'])) ||
+    $tutorGroup = GroupManager::is_tutor_of_group(api_get_user_id(), $groupInfo['iid']);
+
+    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))
     ) {
         if ($locked == false) {
-            $iconEdit .= "<a href=\"editpost.php?" . api_get_cidreq()
-                . "&forum=$clean_forum_id&thread=$clean_thread_id&post={$post['post_id']}&id_attach=$id_attach"
-                . "\">"
+            $editUrl = api_get_path(WEB_CODE_PATH).'forum/editpost.php?'.api_get_cidreq();
+            $editUrl .= "&forum=$clean_forum_id&thread=$clean_thread_id&post={$post['post_id']}&id_attach=$id_attach";
+
+            $iconEdit .= "<a href='".$editUrl."'>"
                 . Display::return_icon('edit.png', get_lang('Edit'), array(), ICON_SIZE_SMALL)
                 . "</a>";
+
+            $editButton = Display::toolbarButton(
+                get_lang('Edit'),
+                $editUrl,
+                'pencil',
+                'default'
+            );
         }
     }
 
-    if (
-        (isset($groupInfo['iid']) && GroupManager::is_tutor_of_group(api_get_user_id(), $groupInfo['iid'])) ||
+    if ((isset($groupInfo['iid']) && $tutorGroup) ||
         api_is_allowed_to_edit(false, true) &&
         !(api_is_course_coach() && $current_forum['session_id'] != $sessionId)
     ) {
@@ -190,7 +201,9 @@ foreach ($rows as $post) {
     if ($userCanQualify) {
         if ($count > 0) {
             $current_qualify_thread = showQualify(
-                '1', $post['user_id'], $_GET['thread']
+                '1',
+                $post['user_id'],
+                $_GET['thread']
             );
             if ($locked == false) {
                 $iconEdit .= "<a href=\"forumqualify.php?" . api_get_cidreq()
@@ -208,6 +221,10 @@ foreach ($rows as $post) {
         $html .= '<div class="tools-icons">' . $iconEdit . ' '.$statusIcon.'</div>';
     }
 
+    $buttonReply = '';
+    $buttonQuote = '';
+    $waitingValidation = '';
+
     if (($current_forum_category && $current_forum_category['locked'] == 0) &&
         $current_forum['locked'] == 0 && $current_thread['locked'] == 0 || api_is_allowed_to_edit(false, true)
     ) {
@@ -238,9 +255,17 @@ foreach ($rows as $post) {
                     'success',
                     ['id' => "quote-post-{$post['post_id']}"]
                 );
+
+                if ($current_forum['moderated'] && !api_is_allowed_to_edit(false, true)) {
+                    if (empty($post['status']) || $post['status'] == CForumPost::STATUS_WAITING_MODERATION) {
+                        $buttonReply = '';
+                        $buttonQuote = '';
+                    }
+                }
             }
         }
     } else {
+        $closedPost = '';
         if ($current_forum_category && $current_forum_category['locked'] == 1) {
             $closedPost = Display::tag(
                 'div',
@@ -265,10 +290,8 @@ foreach ($rows as $post) {
 
         $html .= $closedPost;
     }
-
     $html .= '</div>';
 
-
     // note: this can be removed here because it will be displayed in the tree
     if (
         isset($whatsnew_post_info[$current_forum['forum_id']][$current_thread['thread_id']][$post['post_id']]) &&
@@ -282,7 +305,8 @@ foreach ($rows as $post) {
 
     if ($post['post_notification'] == '1' && $post['poster_id'] == $userId) {
         $post_image .= Display::return_icon(
-                'forumnotification.gif', get_lang('YouWillBeNotified')
+            'forumnotification.gif',
+            get_lang('YouWillBeNotified')
         );
     }
 
@@ -293,10 +317,8 @@ foreach ($rows as $post) {
     $html .= Display::tag('div', $titlePost, array('class' => 'post-header'));
 
     // the post body
-
     $html .= Display::tag('div', $post['post_text'], array('class' => 'post-body'));
     $html .= '</div>';
-
     $html .= '</div>';
 
     $html .= '<div class="row">';
@@ -305,11 +327,10 @@ foreach ($rows as $post) {
     $attachment_list = getAllAttachment($post['post_id']);
     if (!empty($attachment_list) && is_array($attachment_list)) {
         foreach ($attachment_list as $attachment) {
-            $realname = $attachment['path'];
             $user_filename = $attachment['filename'];
             $html .= Display::return_icon('attachment.gif', get_lang('Attachment'));
             $html .= '<a href="download.php?file=';
-            $html .= $realname;
+            $html .= $attachment['path'];
             $html .= ' "> ' . $user_filename . ' </a>';
             $html .= '<span class="forum_attach_comment" >' . $attachment['comment'] . '</span>';
             if (($current_forum['allow_edit'] == 1 && $post['user_id'] == $userId) ||
@@ -326,18 +347,18 @@ foreach ($rows as $post) {
 
     $html .= '</div>';
     $html .= '<div class="col-md-6 text-right">';
-    $html .= $buttonReply . ' ' . $buttonQuote;
+    $html .= "$editButton $buttonReply $buttonQuote $waitingValidation";
     $html .= '</div>';
     $html .= '</div>';
+
     // The post has been displayed => it can be removed from the what's new array
     unset($whatsnew_post_info[$current_forum['forum_id']][$current_thread['thread_id']][$post['post_id']]);
     unset($_SESSION['whatsnew_post_info'][$current_forum['forum_id']][$current_thread['thread_id']][$post['post_id']]);
 
-
     $html .= '</div>';
     $html .= '</div>';
     $html .= '</div>';
-    echo $html;
 
+    echo $html;
     $count++;
 }

+ 63 - 16
main/inc/ajax/forum.ajax.php

@@ -1,6 +1,8 @@
 <?php
 /* For licensing terms, see /license.txt */
 
+use Chamilo\CourseBundle\Entity\CForumPost;
+
 /**
  * Responses to AJAX calls for forum attachments
  * @package chamilo/forum
@@ -13,24 +15,21 @@ require_once api_get_path(SYS_CODE_PATH) . 'forum/forumfunction.inc.php';
 // First, protect this script
 api_protect_course_script(false);
 
-/**
- * Main code
- */
+$action = isset($_REQUEST['a']) ? $_REQUEST['a'] : null;
 // Create a default error response
 $json = array(
     'error' => true,
     'errorMessage' => 'ERROR',
 );
-$action = isset($_REQUEST['a']) ? $_REQUEST['a'] : null;
-
-$current_forum = get_forum_information($_REQUEST['forum']);
-$current_forum_category = get_forumcategory_information($current_forum['forum_category']);
-$current_thread = get_thread_information($_REQUEST['forum'], $_REQUEST['thread']);
 
 // Check if exist action
 if (!empty($action)) {
     switch ($action) {
         case 'upload_file':
+            $current_forum = get_forum_information($_REQUEST['forum']);
+            $current_forum_category = get_forumcategory_information($current_forum['forum_category']);
+            $current_thread = get_thread_information($_REQUEST['forum'], $_REQUEST['thread']);
+
             if (!empty($_FILES) && !empty($_REQUEST['forum'])) {
                 // The user is not allowed here if
                 // 1. the forum category, forum or thread is invisible (visibility==0)
@@ -95,8 +94,13 @@ if (!empty($action)) {
                     }
                 }
             }
+            echo json_encode($json);
             break;
         case 'delete_file':
+            $current_forum = get_forum_information($_REQUEST['forum']);
+            $current_forum_category = get_forumcategory_information($current_forum['forum_category']);
+            $current_thread = get_thread_information($_REQUEST['forum'], $_REQUEST['thread']);
+
             // Check if set attachment ID and thread ID
             if (isset($_REQUEST['attachId']) && isset($_REQUEST['thread'])) {
                 api_block_course_item_locked_by_gradebook($_REQUEST['thread'], LINK_FORUM_THREAD);
@@ -107,24 +111,24 @@ if (!empty($action)) {
                 // 4. if editing of replies is not allowed
                 // The only exception is the course manager
                 // They are several pieces for clarity.
-                if (!api_is_allowed_to_edit(null, true) AND
+                if (!api_is_allowed_to_edit(null, true) &&
                     (
-                        ($current_forum_category && $current_forum_category['visibility'] == 0) OR
+                        ($current_forum_category && $current_forum_category['visibility'] == 0) ||
                         $current_forum['visibility'] == 0)
                 ) {
                     $json['errorMessage'] = '1. the forum category, forum or thread is invisible (visibility==0)';
                     break;
                 }
-                if (!api_is_allowed_to_edit(null, true) AND
+                if (!api_is_allowed_to_edit(null, true) &&
                     (
-                        ($current_forum_category && $current_forum_category['locked'] <> 0) OR
-                        $current_forum['locked'] <> 0 OR $current_thread['locked'] <> 0
+                        ($current_forum_category && $current_forum_category['locked'] <> 0) ||
+                        $current_forum['locked'] <> 0 || $current_thread['locked'] <> 0
                     )
                 ) {
                     $json['errorMessage'] = '2. the forum category, forum or thread is locked (locked <>0)';
                     break;
                 }
-                if (api_is_anonymous() AND $current_forum['allow_anonymous'] == 0) {
+                if (api_is_anonymous() && $current_forum['allow_anonymous'] == 0) {
                     $json['errorMessage'] = '3. if anonymous posts are not allowed';
                     break;
                 }
@@ -147,9 +151,52 @@ if (!empty($action)) {
                     $json['errorMessage'] = 'Success';
                 }
             }
+            echo json_encode($json);
+            break;
+        case 'change_post_status':
+            if (api_is_allowed_to_edit(false, true)) {
+                $postId = isset($_GET['post_id']) ? $_GET['post_id'] : '';
+                if (empty($postId)) {
+                    exit;
+                }
+
+                $postId = str_replace('status_post_', '', $postId);
+                $em = Database::getManager();
+                /** @var CForumPost $post */
+                $post = $em->find('ChamiloCourseBundle:CForumPost', $postId);
+                if ($post) {
+                    $forum = get_forums($post->getForumId(), api_get_course_id());
+                    $status = $post->getStatus();
+                    if (empty($status)) {
+                        $status = CForumPost::STATUS_WAITING_MODERATION;
+                    }
+
+                    switch ($status) {
+                        case CForumPost::STATUS_VALIDATED:
+                            $changeTo = CForumPost::STATUS_REJECTED;
+                            break;
+                        case CForumPost::STATUS_WAITING_MODERATION:
+                            $changeTo = CForumPost::STATUS_VALIDATED;
+                            break;
+                        case CForumPost::STATUS_REJECTED:
+                            $changeTo = CForumPost::STATUS_WAITING_MODERATION;
+                            break;
+                    }
+                    $post->setStatus($changeTo);
+                    $em->persist($post);
+                    $em->flush();
+
+                    echo getPostStatus(
+                        $forum,
+                        [
+                            'iid' => $post->getIid(),
+                            'status' => $post->getStatus(),
+                        ],
+                        false
+                    );
+                }
+            }
             break;
     }
 }
-
-echo json_encode($json);
 exit;

+ 1 - 0
main/inc/lib/CoursesAndSessionsCatalog.class.php

@@ -2,6 +2,7 @@
 /* For licensing terms, see /license.txt */
 
 /**
+ * @todo change class name
  * Class CoursesAndSessionsCatalog
  */
 class CoursesAndSessionsCatalog

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

@@ -855,10 +855,14 @@ function api_get_path($path = '', $configuration = [])
         if (!empty($virtualChamilo)) {
             $paths[$root_web][SYS_ARCHIVE_PATH] = api_add_trailing_slash($virtualChamilo[SYS_ARCHIVE_PATH]);
             $paths[$root_web][SYS_HOME_PATH] = api_add_trailing_slash($virtualChamilo[SYS_HOME_PATH]);
-            $paths[$root_web][WEB_HOME_PATH] = api_add_trailing_slash($virtualChamilo[WEB_HOME_PATH]);
             $paths[$root_web][SYS_COURSE_PATH] = api_add_trailing_slash($virtualChamilo[SYS_COURSE_PATH]);
             $paths[$root_web][SYS_UPLOAD_PATH] = api_add_trailing_slash($virtualChamilo[SYS_UPLOAD_PATH]);
 
+            $paths[$root_web][WEB_HOME_PATH] = api_add_trailing_slash($virtualChamilo[WEB_HOME_PATH]);
+            $paths[$root_web][WEB_UPLOAD_PATH] = api_add_trailing_slash($virtualChamilo[WEB_UPLOAD_PATH]);
+            $paths[$root_web][WEB_ARCHIVE_PATH] = api_add_trailing_slash($virtualChamilo[WEB_ARCHIVE_PATH]);
+            //$paths[$root_web][WEB_COURSE_PATH] = api_add_trailing_slash($virtualChamilo[WEB_COURSE_PATH]);
+
             // WEB_UPLOAD_PATH should be handle by apache htaccess in the vhost
 
             // RewriteEngine On
@@ -2353,7 +2357,7 @@ function api_get_setting($variable, $key = null)
 {
     global $_setting;
     if ($variable == 'header_extra_content') {
-        $filename = api_get_path(SYS_PATH).api_get_home_path().'header_extra_content.txt';
+        $filename = api_get_home_path().'header_extra_content.txt';
         if (file_exists($filename)) {
             $value = file_get_contents($filename);
             return $value;
@@ -2362,7 +2366,7 @@ function api_get_setting($variable, $key = null)
         }
     }
     if ($variable == 'footer_extra_content') {
-        $filename = api_get_path(SYS_PATH).api_get_home_path().'footer_extra_content.txt';
+        $filename = api_get_home_path().'footer_extra_content.txt';
         if (file_exists($filename)) {
             $value = file_get_contents($filename);
             return $value;
@@ -3194,16 +3198,14 @@ function api_not_allowed($print_headers = false, $message = null)
     global $this_section;
 
     if (CustomPages::enabled() && !isset($user_id)) {
-
         if (empty($user_id)) {
             // Why the CustomPages::enabled() need to be to set the request_uri
             $_SESSION['request_uri'] = $_SERVER['REQUEST_URI'];
         }
-
         CustomPages::display(CustomPages::INDEX_UNLOGGED);
     }
 
-    $origin = isset($_GET['origin']) ? $_GET['origin'] : '';
+    $origin = api_get_origin();
 
     $msg = null;
     if (isset($message)) {
@@ -7852,10 +7854,8 @@ function api_mail_html(
     if (isset($additionalParameters['link'])) {
         $mailView->assign('link', $additionalParameters['link']);
     }
-    $mailView->assign(
-        'mail_header_style',
-        api_get_configuration_value('mail_header_style')
-    );
+    $mailView->assign('mail_header_style',api_get_configuration_value('mail_header_style'));
+    $mailView->assign('mail_content_style',api_get_configuration_value('mail_content_style'));
     $layout = $mailView->get_template('mail/mail.tpl');
     $mail->Body = $mailView->fetch($layout);
 

+ 13 - 3
main/inc/lib/auth.lib.php

@@ -638,9 +638,17 @@ class Auth
             if (CourseManager::add_user_to_course($user_id, $course_code, $status_user_in_new_course)) {
                 $send = api_get_course_setting('email_alert_to_teacher_on_new_user_in_course', $course_code);
                 if ($send == 1) {
-                    CourseManager::email_to_tutor($user_id, $all_course_information['real_id'], $send_to_tutor_also = false);
+                    CourseManager::email_to_tutor(
+                        $user_id,
+                        $all_course_information['real_id'],
+                        $send_to_tutor_also = false
+                    );
                 } else if ($send == 2) {
-                    CourseManager::email_to_tutor($user_id, $all_course_information['real_id'], $send_to_tutor_also = true);
+                    CourseManager::email_to_tutor(
+                        $user_id,
+                        $all_course_information['real_id'],
+                        $send_to_tutor_also = true
+                    );
                 }
                 $url = Display::url($all_course_information['title'], api_get_course_url($course_code));
                 $message = sprintf(get_lang('EnrollToCourseXSuccessful'), $url);
@@ -649,7 +657,9 @@ class Auth
             }
             return array('message' => $message);
         } else {
-            if (isset($_POST['course_registration_code']) && $_POST['course_registration_code'] != $all_course_information['registration_code']) {
+            if (isset($_POST['course_registration_code']) &&
+                $_POST['course_registration_code'] != $all_course_information['registration_code']
+            ) {
                 return false;
             }
             $message = get_lang('CourseRequiresPassword') . '<br />';

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

@@ -703,9 +703,8 @@ function return_breadcrumb($interbreadcrumb, $language_file, $nameTools)
         }
 
         // View as student/teacher link
-        $view = null;
         if (!empty($view_as_student_link)) {
-            $view .= Display::tag('div', $view_as_student_link, array('id' => 'view_as_link','class' => 'pull-right'));
+            $html .= Display::tag('div', $view_as_student_link, array('id' => 'view_as_link','class' => 'pull-right'));
         }
 
         if (!empty($navigation_right)) {
@@ -716,7 +715,6 @@ function return_breadcrumb($interbreadcrumb, $language_file, $nameTools)
         }
 
         if (!empty($lis)) {
-            $html .= $view;
             $html .= Display::tag('ul', $lis, array('class'=>'breadcrumb'));
         }
 

+ 7 - 1
main/inc/lib/course_description.lib.php

@@ -178,7 +178,13 @@ class CourseDescription
 		        WHERE c_id = $course_id AND session_id='" . $this->session_id . "'";
         $rs = Database::query($sql);
         $max = Database::fetch_array($rs);
-        $description_type = $max['MAX'] + 1;
+
+        if ($max['MAX'] >= 8) {
+            $description_type = 8;
+        } else {
+            $description_type = $max['MAX'] + 1;
+        }
+
         if ($description_type < ADD_BLOCK) {
             $description_type = ADD_BLOCK;
         }

+ 2 - 0
main/inc/lib/diagnoser.lib.php

@@ -430,6 +430,8 @@ class Diagnoser
 
         $array[] = $this->build_setting(self :: STATUS_INFORMATION, '[SERVER]', 'php_uname()', 'http://be2.php.net/php_uname', php_uname(), null, null, get_lang('UnameInfo'));
 
+        $array[] = $this->build_setting(self :: STATUS_INFORMATION, '[SERVER]', '$_SERVER["HTTP_X_FORWARDED_FOR"]', 'http://be.php.net/reserved.variables.server', (!empty($_SERVER["HTTP_X_FORWARDED_FOR"]) ? $_SERVER["HTTP_X_FORWARDED_FOR"] : ''), null, null, get_lang('ServerXForwardedForInfo'));
+
         return $array;
     }
 

+ 63 - 5
main/inc/lib/display.lib.php

@@ -2006,10 +2006,25 @@ class Display
         return $html;
     }
 
+    /**
+     * @param array $buttons
+     * @return string
+     */
+    public static function groupButton($buttons)
+    {
+        $html = '<div class="btn-group" role="group">';
+        foreach ($buttons as $button) {
+            $html .= $button;
+        }
+        $html .= '</div>';
+
+        return $html;
+    }
+
     /**
      * @todo use twig
      */
-    public static function group_button($title, $elements)
+    public static function groupButtonWithDropDown($title, $elements)
     {
         $html = '<div class="btn-group">
                 <button class="btn btn-default dropdown-toggle" data-toggle="dropdown">
@@ -2321,15 +2336,15 @@ class Display
      *
      * @return string
      */
-    public static function panel($content, $title = '', $footer = '', $style = '', $extra = '', $id = '')
+    public static function panel($content, $title = '', $footer = '', $style = '', $extra = '')
     {
         $title = !empty($title) ? '<div class="panel-heading"><h3 class="panel-title">'.$title.'</h3>'.$extra.'</div>' : '';
         $footer = !empty($footer) ? '<div class="panel-footer ">'.$footer.'</div>' : '';
-        $styles = ['primary','success','info','warning','danger'];
+        $styles = ['primary', 'success', 'info', 'warning', 'danger'];
         $style = !in_array($style, $styles) ? 'default' : $style;
 
         return '
-            <div id = '.$id.' class="panel panel-'.$style.'">
+            <div class="panel panel-'.$style.'">
                 '.$title.'
                 '.self::contentPanel($content).'
                 '.$footer.'
@@ -2355,6 +2370,8 @@ class Display
      * @param string $icon The Awesome Font class for icon
      * @param string $type Optional. The button Bootstrap class. Default 'default' class
      * @param array $attributes The additional attributes
+     * @param bool $includeText
+     *
      * @return string The button HTML
      */
     public static function toolbarButton(
@@ -2522,7 +2539,7 @@ HTML;
 
     /**
      * Returns the string "1 day ago" with a link showing the exact date time.
-     * @param string $dateTime in UTC
+     * @param string $dateTime in UTC or a DateTime in UTC
      *
      * @return string
      */
@@ -2532,12 +2549,53 @@ HTML;
             return '';
         }
 
+        if ($dateTime instanceof \DateTime) {
+            $dateTime = $dateTime->format('Y-m-d H:i:s');
+        }
+
         return self::tip(
             date_to_str_ago($dateTime),
             api_get_local_time($dateTime)
         );
     }
 
+    /**
+     * @param $userInfo
+     * @param string $status
+     * @param string $toolbar
+     * @return string
+     */
+    public static function getUserCard($userInfo, $status= '', $toolbar = '')
+    {
+        if (!empty($status)) {
+            $status = '<div class="items-user-status">'.$status.'</div>';
+        }
+
+        if (!empty($toolbar)) {
+            $toolbar = '<div class="btn-group pull-right">'.$toolbar.'</div>';
+        }
+
+        return '<div class="col-md-12">                    
+                    <div class="row">
+                        <div class="col-md-2">                            
+                            <img src="'.$userInfo['avatar'].'" class="img-responsive img-circle">
+                        </div>
+                        <div class="col-md-10">
+                           <p>'.$userInfo['complete_name'].'</p>
+                           <div class="row">
+                           <div class="col-md-2">
+                           '.$status.'
+                           </div>
+                           <div class="col-md-10">                           
+                           '.$toolbar.'
+                           </div>
+                           </div>
+                        </div>
+                    </div>
+                    <hr />
+              </div>';
+    }
+
     public static function iconAnswer($typeAnswer){
         $valor = null;
         switch ($typeAnswer){

+ 9 - 5
main/inc/lib/extra_field.lib.php

@@ -1352,11 +1352,15 @@ class ExtraField extends Model
                         }
                         break;
                     case ExtraField::FIELD_TYPE_DIVIDER:
-                        $form->addElement(
-                            'static',
-                            $field_details['variable'],
-                            '<br /><strong>'.$field_details['display_text'].'</strong>'
-                        );
+                        $form->addHtml('
+                            <div class="form-group ">
+                                <div class="col-sm-12">
+                                    <div class="panel-separator">
+                                       <h4 id="' . $field_details['variable'] . '" class="form-separator">' . $field_details['display_text'] . '</h4>
+                                    </div>
+                                </div>
+                            </div>    
+                        ');
                         break;
                     case ExtraField::FIELD_TYPE_TAG:
                         $variable = $field_details['variable'];

+ 27 - 32
main/inc/lib/extra_field_value.lib.php

@@ -5,6 +5,7 @@ use Chamilo\CoreBundle\Entity\ExtraField as EntityExtraField;
 use Chamilo\CoreBundle\Entity\ExtraFieldRelTag;
 use Chamilo\CoreBundle\Entity\Tag;
 use ChamiloSession as Session;
+use Chamilo\CoreBundle\Entity\ExtraFieldValues;
 
 /**
  * Class ExtraFieldValue
@@ -62,7 +63,8 @@ class ExtraFieldValue extends Model
      */
     public function get_count()
     {
-        $query = Database::getManager()->getRepository('ChamiloCoreBundle:ExtraFieldValues')->createQueryBuilder('e');
+        $em = Database::getManager();
+        $query = $em->getRepository('ChamiloCoreBundle:ExtraFieldValues')->createQueryBuilder('e');
         $query->select('count(e.id)');
         $query->where('e.extraFieldType = :type');
         $query->setParameter('type', $this->getExtraField()->getExtraFieldType());
@@ -250,7 +252,6 @@ class ExtraFieldValue extends Model
                     }
 
                     if ($value['error'] == 0) {
-
                         //Crop the image to adjust 16:9 ratio
                         $crop = new Image($value['tmp_name']);
                         $crop->crop($params['extra_' . $field_variable . '_crop_result']);
@@ -264,7 +265,6 @@ class ExtraFieldValue extends Model
                             'value' => $fileDirStored . $fileName,
                             'comment' => $comment
                         );
-
                         self::save($newParams);
                     }
                     break;
@@ -461,7 +461,7 @@ class ExtraFieldValue extends Model
                 */
                 if (false) {
                     global $app;
-                    switch($this->type) {
+                    switch ($this->type) {
                         case 'question':
                             $extraFieldValue = new ChamiloLMS\Entity\QuestionFieldValues();
                             $extraFieldValue->setUserId(api_get_user_id());
@@ -495,7 +495,6 @@ class ExtraFieldValue extends Model
                     }
                 } else {
                     if ($extraFieldInfo['field_type'] == ExtraField::FIELD_TYPE_TAG) {
-
                         $option = new ExtraFieldOption($this->type);
                         $optionExists = $option->get($params['value']);
                         if (empty($optionExists)) {
@@ -548,7 +547,6 @@ class ExtraFieldValue extends Model
 
                     if (isset($extraFieldValue)) {
                         if (!empty($params['value'])) {
-
                             /*
                              *  If the field value is similar to the previous value then the comment will be the same
                                 in order to no save in the log an empty record
@@ -801,7 +799,6 @@ class ExtraFieldValue extends Model
         $result = Database::query($sql);
 
         if (Database::num_rows($result)) {
-
             return Database::store_result($result, 'ASSOC');
         }
 
@@ -934,7 +931,6 @@ class ExtraFieldValue extends Model
 
         $result = Database::query($sql);
         if (Database::num_rows($result)) {
-
             return Database::store_result($result, 'ASSOC');
         }
 
@@ -1035,49 +1031,48 @@ class ExtraFieldValue extends Model
     /**
      * Get all values for an item
      * @param int $itemId The item ID
-     * @param boolean $onlyVisibleFields Get the visible extra field only
+     * @param boolean $visibleToSelf Get the visible extra field only
+     * @param boolean $visibleToOthers
+     *
      * @return array
      */
-    public function getAllValuesForAnItem($itemId, $onlyVisibleFields = false)
+    public function getAllValuesForAnItem($itemId, $visibleToSelf = null, $visibleToOthers = null)
     {
         $em = Database::getManager();
-        $queryBuilder = $em->createQueryBuilder();
-        $fieldOptionsRepo = $em->getRepository('ChamiloCoreBundle:ExtraFieldOptions');
-
-        $queryBuilder = $queryBuilder->select('fv')
+        /** @var \Doctrine\DBAL\Query\QueryBuilder $qb */
+        $qb = $em->createQueryBuilder();
+        $qb = $qb->select('fv')
             ->from('ChamiloCoreBundle:ExtraFieldValues', 'fv')
-            ->innerJoin(
-                'ChamiloCoreBundle:ExtraField',
-                'f',
-                Doctrine\ORM\Query\Expr\Join::WITH,
-                'fv.field = f'
-            )
+            ->join('fv.field', 'f')
             ->where(
-                $queryBuilder->expr()->andX(
-                    $queryBuilder->expr()->eq('fv.itemId', ':item'),
-                    $queryBuilder->expr()->eq('f.extraFieldType', ':field_type')
-                )
+                $qb->expr()->eq('fv.itemId', ':item')
             );
 
-        if ($onlyVisibleFields) {
-            $queryBuilder->andWhere(
-                $queryBuilder->expr()->eq('f.visibleToSelf', true)
-            );
+        if (is_bool($visibleToSelf)) {
+            $qb
+                ->andWhere($qb->expr()->eq('f.visibleToSelf', ':visibleToSelf'))
+                ->setParameter('visibleToSelf', $visibleToSelf);
+        }
+
+        if (is_bool($visibleToOthers)) {
+            $qb
+                ->andWhere($qb->expr()->eq('f.visibleToOthers', ':visibleToOthers'))
+                ->setParameter('visibleToOthers', $visibleToOthers);
         }
 
-        $fieldValues = $queryBuilder
+        $fieldValues = $qb
             ->setParameter('item', $itemId)
-            ->setParameter('field_type', $this->getExtraField()->getExtraFieldType())
             ->getQuery()
             ->getResult();
 
-        $valueList = [];
+        $fieldOptionsRepo = $em->getRepository('ChamiloCoreBundle:ExtraFieldOptions');
 
+        $valueList = [];
+        /** @var ExtraFieldValues $fieldValue */
         foreach ($fieldValues as $fieldValue) {
             $item = [
                 'value' => $fieldValue
             ];
-
             switch ($fieldValue->getField()->getFieldType()) {
                 case ExtraField::FIELD_TYPE_SELECT:
                     $item['option'] = $fieldOptionsRepo->findOneBy([

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

@@ -2021,7 +2021,7 @@ class SessionManager
         is_array($courseInfo) ? $courseId = $courseInfo['real_id'] : $courseId = $courseInfo;
 
         $statusCondition = null;
-        if (isset($status) && !is_null($status))  {
+        if (isset($status) && !is_null($status)) {
             $status = intval($status);
             $statusCondition  = " AND status = $status";
         }
@@ -4794,7 +4794,12 @@ class SessionManager
                                     $coach_id = UserManager::get_user_id_from_username($course_coach);
                                     if ($coach_id !== false) {
                                         // Just insert new coaches
-                                        SessionManager::updateCoaches($session_id, $courseId, array($coach_id), false);
+                                        SessionManager::updateCoaches(
+                                            $session_id,
+                                            $courseId,
+                                            array($coach_id),
+                                            false
+                                        );
 
                                         if ($debug) {
                                             $logger->addInfo("Sessions - Adding course coach: user #$coach_id ($course_coach) to course: '$course_code' and session #$session_id");
@@ -4810,6 +4815,9 @@ class SessionManager
                             $teacherToAdd = null;
                             // Only one coach is added.
                             if ($onlyAddFirstCoachOrTeacher == true) {
+                                if ($debug) {
+                                    $logger->addInfo("onlyAddFirstCoachOrTeacher : true");
+                                }
 
                                 foreach ($course_coaches as $course_coach) {
                                     $coach_id = UserManager::get_user_id_from_username($course_coach);
@@ -4824,7 +4832,6 @@ class SessionManager
                                 if (!empty($teacherList)) {
                                     foreach ($teacherList as $teacher) {
                                         if ($teacherToAdd != $teacher['user_id']) {
-
                                             $sql = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)."
                                                     WHERE
                                                         user_id = ".$teacher['user_id']." AND
@@ -4861,12 +4868,25 @@ class SessionManager
                                                 $teacher['user_id'],
                                                 $course_code
                                             );
+
+                                            if ($debug) {
+                                                $logger->addInfo("Delete user #".$teacher['user_id']." from base course: $course_code");
+                                            }
                                         }
                                     }
                                 }
 
                                 if (!empty($teacherToAdd)) {
-                                    SessionManager::updateCoaches($session_id, $courseId, array($teacherToAdd), true);
+                                    SessionManager::updateCoaches(
+                                        $session_id,
+                                        $courseId,
+                                        array($teacherToAdd),
+                                        true
+                                    );
+
+                                    if ($debug) {
+                                        $logger->addInfo("Add coach #$teacherToAdd to course $courseId and session $session_id");
+                                    }
 
                                     $userCourseCategory = '';
                                     if (isset($teacherBackupList[$teacherToAdd]) &&
@@ -4884,6 +4904,10 @@ class SessionManager
                                         $userCourseCategory
                                     );
 
+                                    if ($debug) {
+                                        $logger->addInfo("Subscribe user #$teacherToAdd as teacher in course $course_code ");
+                                    }
+
                                     if (isset($groupBackup['user'][$teacherToAdd]) &&
                                         isset($groupBackup['user'][$teacherToAdd][$course_code]) &&
                                         !empty($groupBackup['user'][$teacherToAdd][$course_code])
@@ -4915,6 +4939,9 @@ class SessionManager
                             // See BT#6449#note-195
                             // All coaches are added.
                             if ($removeAllTeachersFromCourse) {
+                                if ($debug) {
+                                    $logger->addInfo("removeAllTeachersFromCourse true");
+                                }
                                 $teacherToAdd = null;
                                 foreach ($course_coaches as $course_coach) {
                                     $coach_id = UserManager::get_user_id_from_username(
@@ -4969,6 +4996,10 @@ class SessionManager
                                                     $teacher['user_id'],
                                                     $course_code
                                                 );
+
+                                                if ($debug) {
+                                                    $logger->addInfo("Delete user #".$teacher['user_id']." from base course: $course_code");
+                                                }
                                             }
                                         }
                                     }
@@ -4990,6 +5021,10 @@ class SessionManager
                                             $userCourseCategory
                                         );
 
+                                        if ($debug) {
+                                            $logger->addInfo("Add user as teacher #".$teacherId." in base course: $course_code");
+                                        }
+
                                         if (isset($groupBackup['user'][$teacherId]) &&
                                             isset($groupBackup['user'][$teacherId][$course_code]) &&
                                             !empty($groupBackup['user'][$teacherId][$course_code])
@@ -5184,6 +5219,26 @@ class SessionManager
         return $coursesFromSession;
     }
 
+    /**
+     * getAllCoursesFromAllSessions
+     *
+     * @return array
+     */
+    public static function getAllCoursesFromAllSessions()
+    {
+        $sessions = SessionManager::get_sessions_list();
+        $coursesFromSession = array();
+        if (!empty($sessions)) {
+            foreach ($sessions as $session) {
+                $courseList = SessionManager::get_course_list_by_session_id($session['id']);
+                foreach ($courseList as $course) {
+                    $coursesFromSession[$course['code'].':'.$session['id']] = $course['visual_code'] . ' - ' . $course['title'] . ' (' . $session['name'] . ')';
+                }
+            }
+        }
+        return $coursesFromSession;
+    }
+
     /**
      * @param string $status
      * @param int $userId
@@ -7010,7 +7065,7 @@ class SessionManager
         $tbl_user = Database::get_main_table(TABLE_MAIN_USER);
 
         $form->addElement('text', 'name', get_lang('SessionName'), array(
-            'maxlength' => 50,
+            'maxlength' => 150,
         ));
         $form->addRule('name', get_lang('ThisFieldIsRequired'), 'required');
         $form->addRule('name', get_lang('SessionNameAlreadyExists'), 'callback', 'check_session_name');
@@ -8198,4 +8253,33 @@ class SessionManager
 
         return Database::store_result($result, 'ASSOC');
     }
+
+    /**
+     * subsscribe and redirect to session after inscription
+     */
+    public static function redirectToSession()
+    {
+        $sessionId = isset($_SESSION['session_redirect']) ? $_SESSION['session_redirect'] : null;
+        $onlyOneCourseSessionToRedirect = isset($_SESSION['only_one_course_session_redirect']) ? $_SESSION['only_one_course_session_redirect'] : null;
+        $userId = api_get_user_id();
+        $sessionInfo = api_get_session_info($sessionId);
+
+        if (!empty($sessionInfo)) {
+
+            $response = self::isUserSubscribedAsStudent($sessionId, $userId);
+
+            if ($response) {
+
+                $urlToRedirect = api_get_path(WEB_CODE_PATH) . 'session/index.php?session_id=' . $sessionId;
+
+                if (!empty($onlyOneCourseSessionToRedirect)) {
+
+                        $urlToRedirect = api_get_path(WEB_PATH) . 'courses/' . $onlyOneCourseSessionToRedirect . '/index.php?id_session=' . $sessionId;
+                }
+
+                header('Location: ' . $urlToRedirect);
+                exit;
+            }
+        }
+    }
 }

+ 1 - 0
main/inc/lib/social.lib.php

@@ -137,6 +137,7 @@ class SocialManager extends UserManager
                     'lastName' => $my_user_info['lastName'],
                     'username' => $my_user_info['username'],
                     'image' => $my_user_info['avatar'],
+                    'user_info' => $my_user_info,
                 );
             } else {
                 $list_ids_friends[] = $row;

+ 17 - 10
main/inc/lib/usermanager.lib.php

@@ -409,7 +409,14 @@ class UserManager
                     null,
                     PERSON_NAME_EMAIL_ADDRESS
                 );
-                $tplSubject = new Template(null, false, false, false, false, false);
+                $tplSubject = new Template(
+                    null,
+                    false,
+                    false,
+                    false,
+                    false,
+                    false
+                );
                 $layoutSubject = $tplSubject->get_template(
                     'mail/subject_registration_platform.tpl'
                 );
@@ -574,7 +581,6 @@ class UserManager
                     WHERE status=1 AND c_id = " . intval($course->c_id);
             $res2 = Database::query($sql);
             if (Database::num_rows($res2) == 1) {
-
                 return false;
             }
         }
@@ -618,11 +624,14 @@ class UserManager
         $table_work = Database :: get_course_table(TABLE_STUDENT_PUBLICATION);
 
         // Unsubscribe the user from all groups in all his courses
-        $sql = "SELECT c.id FROM $table_course c, $table_course_user cu
+        $sql = "SELECT c.id 
+                FROM $table_course c 
+                INNER JOIN $table_course_user cu
+                ON (c.id = cu.c_id)
                 WHERE
                     cu.user_id = '".$user_id."' AND
-                    relation_type<>".COURSE_RELATION_TYPE_RRHH." AND
-                    c.id = cu.c_id";
+                    relation_type<>".COURSE_RELATION_TYPE_RRHH."
+                ";
 
         $res = Database::query($sql);
         while ($course = Database::fetch_object($res)) {
@@ -851,7 +860,6 @@ class UserManager
     public static function activate_users($ids = array())
     {
         if (empty($ids)) {
-
             return false;
         }
 
@@ -1226,7 +1234,6 @@ class UserManager
     public static function create_username($firstname, $lastname)
     {
         if (empty($firstname) && empty($lastname)) {
-
             return false;
         }
 
@@ -1501,9 +1508,9 @@ class UserManager
         if (count($order_by) > 0) {
             $sql_query .= ' ORDER BY '.Database::escape_string(implode(',', $order_by), null, false);
         }
+
         $sql_result = Database::query($sql_query);
         while ($result = Database::fetch_array($sql_result)) {
-
             $result['complete_name'] = api_get_person_name(
                 $result['firstname'],
                 $result['lastname']
@@ -1593,7 +1600,7 @@ class UserManager
      *
      * @return    array     Array of 2 elements: 'dir' and 'file' which contain
      * the dir and file as the name implies if image does not exist it will
-     * return the unknow image if anonymous parameter is true if not it returns an empty array
+     * return the unknown image if anonymous parameter is true if not it returns an empty array
      */
     public static function getUserPicturePathById($id, $type = 'web', $userInfo = [])
     {
@@ -5394,7 +5401,7 @@ EOF;
     }
 
     /**
-     * Get the boss user list from a followed user id
+     * Get the boss user ID from a followed user id
      * @param $userId
      * @return bool
      */

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

@@ -267,6 +267,9 @@ $_configuration['system_stable'] = NEW_VERSION_STABLE;
 //$_configuration['show_prerequisite_as_blocked'] = false;
 // Mail header extra HTML attributes
 //$_configuration['mail_header_style'] = '';
+// Mail body extra HTML attributes
+//$_configuration['mail_content_style'] = '';
 // Show all agenda events in personal agenda from all session no matter the visibility.
 //$_configuration['personal_agenda_show_all_session_events'] = false;
-
+// Allows to redirect to the session after the inscription in session about
+// $_configuration['allow_redirect_to_session_after_inscription_about'] = false;

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

@@ -7838,4 +7838,8 @@ $DeleteCorrections = "Excluir correções";
 $AllowMyFilesTitle = "Permitir Minha página Arquivos";
 $AllowMyFilesComment = "Permitir que os usuários fazer upload de arquivos em um espaço pessoal na plataforma.";
 $InstallMultiURLDetectedNotMainURL = "Você está usando o recurso multi-URL e está tentando atualizar seu portal usando um URL secundário. Por favor, conecte-se ao URL principal para continuar com a atualização: %s";
+$OnlyXQuestionsPickedRandomly = "Apenas %s perguntas serão escolhidas aleatoriamente após a configuração do quiz.";
+$AllowDownloadDocumentsByApiKeyTitle = "Permitir download de documentos do curso por chave da API";
+$AllowDownloadDocumentsByApiKeyComment = "Fazer download de documentos que verificam a chave REST API para um usuário";
+$UploadCorrectionsExplanationWithDownloadLinkX = "Primeiro você tem que baixar as correções aqui . Depois que você tem que descompactar esse arquivo e editar os arquivos como você queria sem alterar os nomes dos arquivos. Em seguida, crie um arquivo zip com esses arquivos modificados e faça o upload desse formulário.";
 ?>

+ 7 - 1
main/lang/english/trad4all.inc.php

@@ -7947,11 +7947,17 @@ $Unassigned = "Unassigned";
 $SelectWeeksSpan = "Select the timespan in weeks";
 $CourseXAdded = "Course %s added";
 $CurrentPassword = "Current password";
-$DeleteCorrections = "Delete corrections";
+$DeleteCorrections = "Delete all corrections";
 $AllowMyFilesTitle = "Enable 'My Files' section";
 $AllowMyFilesComment = "Allow users to upload files to a personal space on the platform.";
 $InstallMultiURLDetectedNotMainURL = "You are currently using the multi-URL feature and are trying to upgrade your portal using a secondary URL. Please connect to the main URL to proceed with the upgrade: %s";
 $OnlyXQuestionsPickedRandomly = "Only %s questions will be picked randomly following the quiz configuration.";
+$AllowDownloadDocumentsByApiKeyTitle = "Allow download course documents by API Key";
+$AllowDownloadDocumentsByApiKeyComment = "Download documents verifying the REST API key for a user";
 $UploadCorrectionsExplanationWithDownloadLinkX = "First you have to download the corrections <a href='%s'> here </a>.
 After that you have to unzip that file and edit the files as you wanted without changing the file names.
 Then create a zip file with those modified files and upload it in this form.";
+$PostsPendingModeration = "Posts pending moderation";
+$OnlyUsersFromCourseSession = "Only users from one course in a session";
+$ServerXForwardedForInfo = "If the server is behind a proxy or firewall (and only in those cases), it might be using the X_FORWARDED_FOR HTTP header to show the remote user IP (yours, in this case).";
+?>

+ 114 - 14
main/lang/faroese/trad4all.inc.php

@@ -4,9 +4,16 @@ for more information: see languages.txt in the lang folder.
 */
 $MobilePhoneNumberWrong = "Fartelefonnummarið væntar tøl ella nýtir stavir";
 $FieldTypeMobilePhoneNumber = "Fartelefonnummar";
+$AgendaList = "Skrá";
+$Calendar = "Kalendari";
 $Username = "Brúkaranavn";
-$Month = "Máni";
+$SelectAnOption = "Vel ein kalendara";
+$Month = "Mánaður";
+$Day = "Dagur";
+$Detail = "Smálutir";
 $Week = "Vika";
+$ICalFileImport = "Flyt inn úr Outlook";
+$ScormStatus = "Støða";
 $MessageEmptyMessageOrSubject = "Evnis regla og boð mugu bæði vera nýtt";
 $Messages = "Boð";
 $DeleteSelectedMessages = "Strika valdu boðini";
@@ -15,9 +22,17 @@ $ReplyToMessage = "Svara hesum boðunum";
 $BackToInbox = "Aftur til boðkliva";
 $ErrorSendingMessage = "Nú kom villa í tá boðini skuldu sendast.";
 $DeleteMessage = "Strika hesi boðini";
+$Professors = "Undirvísarar";
+$Tests = "Royndir";
 $Learnpaths = "Skeið";
 $Scormtool = "Skeið";
 $CreateCourse = "Stovna eitt skeið";
+$TitleNotification = "Síðani tú inni seinast";
+$QuizQuestionAdded = "Spurningar eru lagdir afturat í venjing";
+$QuizQuestionUpdated = "Spurningar eru dagførdir í venjing";
+$QuizQuestionDeleted = "Spurningar eru strikaðir í venjing";
+$AddImage = "Vel mynd";
+$SortMyCourses = "Skipa skeið";
 $EditDocument = "Broyt";
 $MailMarkSelectedAsUnread = "Marka sum ólisin boð";
 $MailMarkSelectedAsRead = "Marka sum lisin boð";
@@ -26,34 +41,64 @@ $AdminUsers = "Brúkarar";
 $AdminCourses = "Skeið";
 $AddCourse = "Stovna eitt skeið";
 $ProfileChangesTitle = "Vangamynd";
+$Exercises = "Royndir";
+$Classes = "Brúkaraflokkar";
 $NbCourses = "Skeið";
+$DateStart = "Byrjanardagur";
 $NbUsers = "Brúkarar";
 $NumberOfCourses = "Skeið";
-$FieldTypeDate = "Dato";
+$FieldTypeDate = "Dagfesting";
 $Msg = "Boð";
+$InC = "í hesi lærugrein";
 $Friends = "Vinfólk";
 $PersonalData = "Vangamynd";
 $Invites = "Innbjóðingar";
 $TryAndFindSomeFriends = "Finn vinfólk";
-$DateExo = "Dato";
+$MyCertificates = "Prógv";
+$LearnpathStatus = "Støða";
+$Questions = "Spurningar";
+$Answer = "Svar";
+$ExerciseName = "Navn á roynd";
+$ElementList = "Lutur";
+$CorrespondsTo = "Svarar til";
+$ExpectedChoice = "Rætt svar";
+$YourTotalScore = "Stig fyri royndina";
+$Correct = "Rætt";
+$DateExo = "Dagfesting";
+$NotAttempted = "Ikki gjørd";
+$ExeStartTime = "Byrjanardagur";
+$QuantityQuestions = "Spurningar";
+$Title = "Heiti";
+$UsersOnline = "Innritaðir brúkarar";
 $Description = "Lýsing";
 $Links = "Leinkjur";
 $Name = "Navn";
+$Comment = "Viðmerking";
 $Edit = "Broyt";
 $Language = "Mál";
-$CourseCreate = "Stovna eitt skeið";
-$CourseCode = "Stytting";
-$OfficialCode = "Stytting";
+$DelImage = "Strika mynd";
+$Code = "Koda fyri lærugrein";
+$CourseCreate = "Stovna eina lærugrein";
+$CourseCode = "Koda fyri lærugrein";
+$OfficialCode = "FSG flokkur";
 $FirstName = "Fornavn";
 $LastName = "Eftirnavn";
+$Status = "Støða";
 $Email = "Teldupostur";
+$AvailableTill = "Tøk til";
 $Search = "Leita";
+$Import = "Flyt inn";
 $Modify = "Broyt";
 $Help = "Hjálp";
+$Add = "Goym";
+$Choice = "Tú valdi";
 $Manager = "Umsitari";
-$Date = "Dato";
+$Notice = "Vegleiðing";
+$Date = "Dagfesting";
+$Show = "Vís";
 $MyCourses = "Míni skeið";
 $ModifyProfile = "Vangamynd";
+$Logout = "Rita út";
 $MyAgenda = "Kalendari";
 $SwitchToTeacherView = "Vís sum undirvísari";
 $SwitchToStudentView = "Vís sum næmingur";
@@ -61,6 +106,7 @@ $Courses = "Skeið";
 $Home = "Heim";
 $SelectAll = "Vel alt";
 $UnSelectAll = "Frável alt";
+$OnLine = "Á";
 $Users = "Brúkarar";
 $Today = "Í dag";
 $WednesdayInit = "M";
@@ -94,25 +140,45 @@ $DecemberLong = "Desember";
 $Agenda = "Kalendari";
 $Average = "Miðal";
 $Learnpath = "Skeið";
+$Quiz = "Royndir";
 $Chat = "Prát";
 $Tracking = "Frásagnir";
+$StartDate = "Byrjanardagur";
 $Student = "Næmingur";
 $Teacher = "Undirvísari";
-$ThisFieldIsRequired = "kassi sum skal fyllast út";
+$InThisCourse = "í hesi lærugrein";
+$ThisFieldIsRequired = "Skal fyllast út";
 $EditRight = "Broyt";
+$DeleteRight = "Strika";
+$Delete = "Strika";
 $Actions = "Smálutir";
-$Inbox = "Boðklivin";
+$Inbox = "Boðklivi";
+$AddRight = "Goym";
 $CampusHomepage = "Heim";
 $MySpace = "Frásagnir";
+$Progress = "Úrslit";
+$Progression = "Úrslit";
+$Teachers = "Undirvísarar";
+$MyProgress = "Úrslit";
+$UserOnlineListSession = "Innritaðir brúkarar - Í mínum skúlaflokki";
+$AvailableUntil = "Tøk til";
+$MainNavigation = "Yvirlit";
 $HomeDirectory = "Heim";
 $Exercise = "Venjing";
 $Result = "Úrslit";
+$Words = "Orð";
+$Details = "Smálutir";
 $Phone = "Telefon";
 $SaveSettings = "Goym stillingar";
+$Duration = "Nýtt tíð";
 $SocialNetwork = "Sosialt";
+$HistoryTrainingSessions = "Eldri skeið";
+$HistoryTrainingSession = "Eldri skeið";
+$Until = "Tøk til";
 $QuestionPlan = "Hjálp";
 $Helptwo = "Hjálp";
 $MenuGeneral = "Hjálp";
+$UsersOnLineList = "Innritaðir brúkarar";
 $HelpMaj = "Hjálp";
 $Enter2passToChange = "Ynskir tú at broyta loyniorð, skriva so núverandi loyniorðið inn omanfyri, og skriva nýggja loyniorðið í báðar kassarnar niðanfyri. Letur tú allar tríggjar kassarnar vera blankar, varðveitir tú verandi loyniorðið.";
 $NewPass = "Nýtt loyniorð";
@@ -121,16 +187,27 @@ $Confirmation = "Endurtak nýggja loyniorðið";
 $SearchButton = "Leita";
 $SearchPages = "Leita";
 $EditPage = "Broyt";
+$FProgress = "Úrslit";
 $ScormAccess = "Skeið";
-$LoginsTitleMonthColumn = "Máni";
-$LoginTitleDateColumn = "Dato";
+$LoginsTitleMonthColumn = "Mánaður";
+$ScormStatusColumn = "Støða";
+$ExercicesResults = "Stig fyri gjørdar royndir";
+$LoginTitleDateColumn = "Dagfesting";
 $PeriodDay = "Dagur";
 $PeriodWeek = "Vika";
-$PeriodMonth = "Máni";
+$PeriodMonth = "Mánaður";
 $BredCrumpUsers = "Brúkarar";
-$SelectTargetDate = "Dato";
-$TargetDate = "Dato";
+$AvgStudentsProgress = "Úrslit";
+$CourseProgress = "Úrslit";
+$NumberOfQuestions = "Spurningar";
+$NextQuestion = "Næsti spurningur";
+$PreviousQuestion = "Undanfarni spurningur";
+$Score = "Úrslit";
+$SelectTargetDate = "Dagfesting";
+$TargetDate = "Dagfesting";
+$AgendaAdd = "Skriva í kalendaran";
 $Detail = "Smálutir";
+$WorkDelete = "Strika";
 $WorkModify = "Broyt";
 $Compose = "Skriva boð";
 $Invitations = "Innbjóðingar";
@@ -152,15 +229,32 @@ $ToolChat = "Prát";
 $ToolTracking = "Frásagnir";
 $ContactInformation = "Samskiftis upplýsingar";
 $MyFiles = "Fílur";
+$UpdateImage = "Dagfør mynd";
 $LoginOrEmailAddress = "Brúkaranavn ella teldupost adressa";
 $Profile = "Vangamynd";
 $LearningPaths = "Undirvísingargongd";
+$LatestAttempt = "Úrslit seinast";
 $MySocialGroups = "Mínir bólkar";
 $SocialGroups = "Bólkar";
 $MailNotifyInvitation = "Send teldupost um inbjóðingar";
 $MailNotifyMessage = "Send teldupost um persónlig boð";
 $MailNotifyGroupMessage = "Send teldupost um boð í bólkum";
 $ToolSearch = "Leita";
+$Reset = "Nullstilla";
+$DecreaseFontSize = "Minka um skriftstødd";
+$ResetFontSize = "Nullstilla skriftstødd";
+$IncreaseFontSize = "Veks um skriftstødd";
+$StartTest = "Byrja royndina";
+$Wrong = "Ikki rætt";
+$ReviewQuestions = "Endurskoða spurningar";
+$YouTriedToResolveThisExerciseEarlier = "Tú hevur gjørt hesa royndina áður";
+$Attempt = "Umfar";
+$SaveForNow = "Goym";
+$ContinueTest = "Halt áfram við royndini";
+$PersonalCalendar = "Mín kalendari";
+$Skills = "Førleikar";
+$NotValidated = "Ikki váttað";
+$ReviewQuestionLater = "Endurskoða spurning seinni";
 $Me = "Eg";
 $Vote = "Atkvøða";
 $Votes = "Atkvøður";
@@ -168,9 +262,15 @@ $XStarsOutOf5 = "%s av 5 stjørnum";
 $Visits = "Vitjanir";
 $YourVote = "Tín atkvøða";
 $HottestCourses = "Best umtóktu skeiðini";
+$EndTest = "Enda royndina";
 $GoToCourse = "Far til hetta skeiðið";
 $CourseCatalog = "Yvirlit yvir skeið";
 $MarkAll = "Vel alt";
 $UnmarkAll = "Frável alt";
+$Offline = "Av";
 $DataTableSearch = "Leita";
+$YouNotYetAchievedCertificates = "Tú hevur ikki fingið prógv enn. Halt áfram undirvísingargongdini fyri at fáa eitt!";
+$UntilDateX = "Tøk til %s";
+$PoweredByX = "Próvstovan";
+$CalendarStartDate = "Byrjanardagur";
 ?>

+ 7 - 1
main/lang/french/trad4all.inc.php

@@ -7626,7 +7626,7 @@ $NowDownloadYourCertificateClickHere = "Télécharge ton certificat en cliquant
 $AdditionallyYouHaveObtainedTheFollowingSkills = "En plus, tu as acquis les compétences suivantes";
 $IHaveObtainedSkillXOnY = "J'ai acquis la compétence %s sur %s";
 $AnotherAttempt = "Nouvelle tentative";
-$RemainingXAttempts = "%s tentatives restantes";
+$RemainingXAttempts = "Nombre de tentatives restantes: %s";
 $Map = "Carte";
 $MyLocation = "Ma position";
 $ShowCourseInUserLanguage = "Afficher les îlots dans la langue de l'utilisateur";
@@ -7899,6 +7899,12 @@ $AllowMyFilesTitle = "Activer la page 'Mes fichiers'";
 $AllowMyFilesComment = "Permettre aux utilisateurs de télécharger des fichiers vers un espace personnel sur la plate-forme.";
 $InstallMultiURLDetectedNotMainURL = "Vous utilisez actuellement la fonctionnalité de multi-URL et êtes sur le point de mettre à jour votre portail en utilisant une URL secondaire. Merci de vous connecter à l'URL principale pour continuer le processus de mise à jour: %s";
 $OnlyXQuestionsPickedRandomly = "Seules %s questions seront tirées au hasard selon les règles établies dans la configuration de l'exercice.";
+$AllowDownloadDocumentsByApiKeyTitle = "Permettre le téléchargement de documents par API";
+$AllowDownloadDocumentsByApiKeyComment = "Permettre le téléchargement de documents du cours via une authentification sur base de la clef API d'un utilisateur. Cette option est utile pour l'application mobile et ne devrait être utilisée que si votre portail est en HTTPS.";
+$UploadCorrectionsExplanationWithDownloadLinkX = "Veuillez d'abord télécharger les corrections <a href=\"%s\">ici</a> puis les décompresser et éditer les fichiers sans changer leurs noms. Ensuite, créez un fichier zip avec les fichiers modifiés et téléchargez-le vers le serveur sous cette forme.";
+$PostsPendingModeration = "Participations en attente de modération";
+$OnlyUsersFromCourseSession = "Seulement les utilisateurs d'un cours dans une session";
+$ServerXForwardedForInfo = "Si le serveur est derrière un proxy ou un firewall (et uniquement dans ces cas), il pourrait utiliser le header HTTP X_FORWARDED_FOR pour montrer l'adresse IP de l'utilisateur distant (la vôtre, dans ce cas précis).";
 
 // Ofaj
 

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

@@ -6897,6 +6897,7 @@ $HideColumn = "Spalte verstecken";
 $DisplayColumn = "Spalte anzeigen";
 $LegalAgreementAccepted = "Nutzungsbedingungen akzeptiert";
 $DateFormatLongNoDayJS = "dd MM yy";
+$RemainingXAttempts = "Anzahl der verbleibenden Versuche: %s";
 $Contact = "Kontakt";
 $YourPasswordCannotBeTheSameAsYourEmail = "Ihr Passwort kann nicht die gleiche sein wie Ihre E-Mail";
 $YourPasswordCannotContainYourUsername = "Ihr Passwort kann nicht enthalten Ihren Benutzernamen";

+ 6 - 0
main/lang/spanish/trad4all.inc.php

@@ -7969,4 +7969,10 @@ $AllowMyFilesTitle = "Permitir uso de página 'Mis documentos'";
 $AllowMyFilesComment = "Permitir a los usuarios subir archivos en un espacio personal en la plataforma.";
 $InstallMultiURLDetectedNotMainURL = "Usted actualmente está usando la funcionalidad de multi-url y está intentando actualizar su portal usando una URL secundaria. Por favor, conéctese a la URL principal para proceder con la actualización: %s";
 $OnlyXQuestionsPickedRandomly = "Solo %s preguntas serán seleccionadas aleatoriamente según la configuración del ejercicio.";
+$AllowDownloadDocumentsByApiKeyTitle = "Permitir descargar documentos del curso a través de la clave de API";
+$AllowDownloadDocumentsByApiKeyComment = "Descargar documentos con la llave API";
+$UploadCorrectionsExplanationWithDownloadLinkX = "Primero necesita descargar las correcciones <a href=\"%s\">aquí</a>. Luego descomprima el archivo y edita los documentos sin cambiar sus nombres. Finalmente, crea un archivo zip con estos documentos y vuelva a subir el archivo en esta forma a través de este formulario.";
+$PostsPendingModeration = "Contribuciones a la espera de moderación";
+$OnlyUsersFromCourseSession = "Solo usuarios de un curso en una sesión";
+$ServerXForwardedForInfo = "Si su servidor está detrás de un reverse proxy o un firewall (y únicamente en estos casos), podría usar la cabecera HTTP X_FORWARDED_FOR para mostrar la dirección IP del usuario distante (usted, en este caso).";
 ?>

+ 16 - 9
main/lp/learnpath.class.php

@@ -2651,6 +2651,7 @@ class learnpath
             if (isset($size)) {
                 $info = pathinfo($preview_image);
                 $image_custom_size = $info['filename'].'.'.$size.'.'.$info['extension'];
+
                 if (file_exists($image_sys_path.$image_custom_size)) {
                     if ($path_type == 'web') {
                         return $image_path.$image_custom_size;
@@ -5915,7 +5916,7 @@ class learnpath
                     ])
                 ),
             );
-            $actionsRight = Display::group_button(get_lang('PrerequisitesOptions'), $buttons);
+            $actionsRight = Display::groupButtonWithDropDown(get_lang('PrerequisitesOptions'), $buttons);
         }
 
         $toolbar = Display::toolbarAction('actions-lp-controller', array($actionsLeft, $actionsRight));
@@ -8714,7 +8715,7 @@ class learnpath
         $row = Database :: fetch_array($result);
         $prerequisiteId = $row['prerequisite'];
         $session_id = api_get_session_id();
-        $session_condition = api_get_session_condition($session_id);
+        $session_condition = api_get_session_condition($session_id, true, true);
         $sql = "SELECT * FROM $tbl_lp
                 WHERE c_id = $course_id $session_condition
                 ORDER BY display_order ";
@@ -8822,7 +8823,7 @@ class learnpath
         $tbl_quiz = Database :: get_course_table(TABLE_QUIZ_TEST);
 
         $session_id = api_get_session_id();
-        $condition_session = api_get_session_condition($session_id);
+        $condition_session = api_get_session_condition($session_id, true, true);
 
         $setting = api_get_configuration_value('show_invisible_exercise_in_lp_list');
 
@@ -8868,7 +8869,7 @@ class learnpath
             $return .= Display::return_icon('move_everywhere.png', get_lang('Move'), array(), ICON_SIZE_TINY);
             $return .= '</a> ';
             $return .= Display::return_icon('quizz_small.gif', '', array(), ICON_SIZE_TINY);
-            $return .= '<a href="' . api_get_self() . '?'.api_get_cidreq().'&action=add_item&type=' . TOOL_QUIZ . '&file=' . $row_quiz['id'] . '&lp_id=' . $this->lp_id . '">' .
+            $return .= '<a class="moved" href="' . api_get_self() . '?'.api_get_cidreq().'&action=add_item&type=' . TOOL_QUIZ . '&file=' . $row_quiz['id'] . '&lp_id=' . $this->lp_id . '">' .
                 Security :: remove_XSS(cut($row_quiz['title'], 80)).
                 '</a>';
 
@@ -8894,9 +8895,15 @@ class learnpath
         $moveEverywhereIcon = Display::return_icon('move_everywhere.png', get_lang('Move'), array(), ICON_SIZE_TINY);
 
         $session_id = api_get_session_id();
-        $condition_session = api_get_session_condition($session_id, true, null, "link.session_id");
+        $condition_session = api_get_session_condition(
+            $session_id,
+            true,
+            true,
+            "link.session_id"
+        );
 
-        $sql = "SELECT link.id as link_id,
+        $sql = "SELECT 
+                    link.id as link_id,
                     link.title as link_title,
                     link.category_id as category_id,
                     link_category.category_title as category_title
@@ -8956,7 +8963,7 @@ class learnpath
                             $moveEverywhereIcon.
                         '</a>
                         '.Display::return_icon('lp_link.png').'
-                        <a href="'.$selfUrl.'?'.$courseIdReq.'&action=add_item&type='.
+                        <a class="moved" href="'.$selfUrl.'?'.$courseIdReq.'&action=add_item&type='.
                         TOOL_LINK.'&file='.$key.'&lp_id='.$this->lp_id.'">'.
                         Security::remove_XSS($title).
                         '</a>
@@ -9104,10 +9111,10 @@ class learnpath
                 $return .= Display::return_icon('move_everywhere.png', get_lang('Move'), array(), ICON_SIZE_TINY);
                 $return .= ' </a>';
                 $return .= Display::return_icon('lp_forum.png', '', array(), ICON_SIZE_TINY);
-                $return .= '<a style="cursor:hand" onclick="javascript: toggle_forum(' . $forum['forum_id'] . ')" style="vertical-align:middle">
+                $return .= '<a onclick="toggle_forum(' . $forum['forum_id'] . ');" style="cursor:hand; vertical-align:middle">
                                 <img src="' . Display::returnIconPath('add.gif').'" id="forum_' . $forum['forum_id'] . '_opener" align="absbottom" />
                             </a>
-                            <a href="' . api_get_self() . '?'.api_get_cidreq().'&action=add_item&type=' . TOOL_FORUM . '&forum_id=' . $forum['forum_id'] . '&lp_id=' . $this->lp_id . '" style="vertical-align:middle">' .
+                            <a class="moved" href="' . api_get_self() . '?'.api_get_cidreq().'&action=add_item&type=' . TOOL_FORUM . '&forum_id=' . $forum['forum_id'] . '&lp_id=' . $this->lp_id . '" style="vertical-align:middle">' .
                     Security :: remove_XSS($forum['forum_title']) . '</a>';
 
                 $return .= '</li>';

+ 3 - 3
main/lp/lp_build.php

@@ -24,9 +24,9 @@ $tbl_lp = Database::get_course_table(TABLE_LP_MAIN);
 $tbl_lp_item = Database::get_course_table(TABLE_LP_ITEM);
 $tbl_lp_view = Database::get_course_table(TABLE_LP_VIEW);
 
-$isStudentView  = (int) $_REQUEST['isStudentView'];
-$learnpath_id   = (int) $_REQUEST['lp_id'];
-$submit			= $_POST['submit_button'];
+$isStudentView = (int)$_REQUEST['isStudentView'];
+$learnpath_id = (int)$_REQUEST['lp_id'];
+$submit = $_POST['submit_button'];
 
 /* MAIN CODE */
 if ((!$is_allowed_to_edit) || ($isStudentView)) {

+ 61 - 22
main/session/about.php

@@ -3,12 +3,16 @@
 
 use Chamilo\CoreBundle\Entity\ExtraField;
 use Chamilo\CourseBundle\Entity\CCourseDescription;
-use \Chamilo\CoreBundle\Entity\SequenceResource;
+use Chamilo\CoreBundle\Entity\SequenceResource;
+use Chamilo\UserBundle\Entity\Repository\UserRepository;
+use Chamilo\UserBundle\Entity\User;
 
 /**
  * Session about page
  * Show information about a session and its courses
  * @author Angel Fernando Quiroz Campos <angel.quiroz@beeznest.com>
+ * @author Julio Montoya
+ *
  * @package chamilo.session
  */
 
@@ -18,20 +22,21 @@ require_once __DIR__.'/../inc/global.inc.php';
 
 $sessionId = isset($_GET['session_id']) ? intval($_GET['session_id']) : 0;
 
-$entityManager = Database::getManager();
+$em = Database::getManager();
 
-$session = $entityManager->find('ChamiloCoreBundle:Session', $sessionId);
+$session = $em->find('ChamiloCoreBundle:Session', $sessionId);
 
 if (!$session) {
     api_not_allowed(true);
 }
 
 $courses = [];
-$sessionCourses = $entityManager->getRepository('ChamiloCoreBundle:Session')->getCoursesOrderedByPosition($session);
-$fieldsRepo = $entityManager->getRepository('ChamiloCoreBundle:ExtraField');
-$fieldTagsRepo = $entityManager->getRepository('ChamiloCoreBundle:ExtraFieldRelTag');
-$userRepo = $entityManager->getRepository('ChamiloUserBundle:User');
-$sequenceResourceRepo = $entityManager->getRepository('ChamiloCoreBundle:SequenceResource');
+$sessionCourses = $em->getRepository('ChamiloCoreBundle:Session')->getCoursesOrderedByPosition($session);
+$fieldsRepo = $em->getRepository('ChamiloCoreBundle:ExtraField');
+$fieldTagsRepo = $em->getRepository('ChamiloCoreBundle:ExtraFieldRelTag');
+/** @var UserRepository $userRepo */
+$userRepo = $em->getRepository('ChamiloUserBundle:User');
+$sequenceResourceRepo = $em->getRepository('ChamiloCoreBundle:SequenceResource');
 
 $tagField = $fieldsRepo->findOneBy([
     'extraFieldType' => ExtraField::COURSE_FIELD_TYPE,
@@ -51,18 +56,25 @@ foreach ($sessionCourses as $sessionCourse) {
 
     $courseCoaches = $userRepo->getCoachesForSessionCourse($session, $sessionCourse);
     $coachesData = [];
-
+    /** @var User $courseCoach */
     foreach ($courseCoaches as $courseCoach) {
         $coachData = [
             'complete_name' => $courseCoach->getCompleteName(),
-            'image' => UserManager::getUserPicture($courseCoach->getId(), USER_IMAGE_SIZE_ORIGINAL),
-            'extra_fields' => $userValues->getAllValuesForAnItem($courseCoach->getId(), true)
+            'image' => UserManager::getUserPicture(
+                $courseCoach->getId(),
+                USER_IMAGE_SIZE_ORIGINAL
+            ),
+            'extra_fields' => $userValues->getAllValuesForAnItem(
+                $courseCoach->getId(),
+                null,
+                true
+            ),
         ];
 
         $coachesData[] = $coachData;
     }
 
-    $courseDescriptionTools = $entityManager->getRepository('ChamiloCourseBundle:CCourseDescription')
+    $courseDescriptionTools = $em->getRepository('ChamiloCourseBundle:CCourseDescription')
         ->findBy(
             [
                 'cId' => $sessionCourse->getId(),
@@ -74,7 +86,8 @@ foreach ($sessionCourses as $sessionCourse) {
             ]
         );
 
-    $courseDescription = $courseObjectives = $courseTopics = null;
+    $courseDescription = $courseObjectives = $courseTopics = $courseMethodology = $courseMaterial = $courseResources = $courseAssesment = null;
+    $courseCustom = [];
 
     foreach ($courseDescriptionTools as $descriptionTool) {
         switch ($descriptionTool->getDescriptionType()) {
@@ -87,6 +100,21 @@ foreach ($sessionCourses as $sessionCourse) {
             case CCourseDescription::TYPE_TOPICS:
                 $courseTopics = $descriptionTool;
                 break;
+            case CCourseDescription::TYPE_METHODOLOGY:
+                $courseMethodology = $descriptionTool;
+                break;
+            case CCourseDescription::TYPE_COURSE_MATERIAL:
+                $courseMaterial = $descriptionTool;
+                break;
+            case CCourseDescription::TYPE_RESOURCES:
+                $courseResources = $descriptionTool;
+                break;
+            case CCourseDescription::TYPE_ASSESMENT:
+                $courseAssesment = $descriptionTool;
+                break;
+            case CCourseDescription::TYPE_CUSTOM:
+                $courseCustom[] = $descriptionTool;
+                break;
         }
     }
 
@@ -96,8 +124,13 @@ foreach ($sessionCourses as $sessionCourse) {
         'tags' => $courseTags,
         'objectives' => $courseObjectives,
         'topics' => $courseTopics,
+        'methodology' => $courseMethodology,
+        'material' => $courseMaterial,
+        'resources' => $courseResources,
+        'assesment' => $courseAssesment,
+        'custom' => array_reverse($courseCustom),
         'coaches' => $coachesData,
-        'extra_fields' => $courseValues->getAllValuesForAnItem($sessionCourse->getId())
+        'extra_fields' => $courseValues->getAllValuesForAnItem($sessionCourse->getId(), null, true)
     ];
 }
 
@@ -116,7 +149,6 @@ $sessionRequirements = $sequenceResourceRepo->getRequirements(
 );
 
 $hasRequirements = false;
-
 foreach ($sessionRequirements as $sequence) {
     if (!empty($sequence['requirements'])) {
         $hasRequirements = true;
@@ -129,7 +161,7 @@ $courseController = new CoursesController();
 /* View */
 $template = new Template($session->getName(), true, true, false, true, false);
 $template->assign('show_tutor', (api_get_setting('show_session_coach')==='true' ? true : false));
-$template->assign('pageUrl', api_get_path(WEB_PATH) . "session/{$session->getId()}/about/");
+$template->assign('page_url', api_get_path(WEB_PATH) . "session/{$session->getId()}/about/");
 $template->assign('session', $session);
 $template->assign('session_date', $sessionDates);
 $template->assign(
@@ -144,17 +176,26 @@ $template->assign(
     $courseController->getRegisteredInSessionButton(
         $session->getId(),
         $session->getName(),
-        $hasRequirements
+        $hasRequirements,
+        true,
+        true
     )
 );
 
+$redirectToSession = api_get_configuration_value('allow_redirect_to_session_after_inscription_about');
+$redirectToSession = $redirectToSession ? '?s=' . $sessionId : false;
+
+$coursesInThisSession = SessionManager::get_course_list_by_session_id($sessionId);
+$coursesCount = count($coursesInThisSession);
+$redirectToSession = $coursesCount == 1 ? $redirectToSession . '&cr=' . array_values($coursesInThisSession)[0]['directory'] : $redirectToSession;
+
+$template->assign('redirect_to_session', $redirectToSession);
 $template->assign('courses', $courses);
-//$essence = new Essence\Essence();
-$essence =  Essence\Essence::instance( );
+$essence =  Essence\Essence::instance();
 $template->assign('essence', $essence);
 $template->assign(
     'session_extra_fields',
-    $sessionValues->getAllValuesForAnItem($session->getId(), true)
+    $sessionValues->getAllValuesForAnItem($session->getId(), null, true)
 );
 $template->assign('has_requirements', $hasRequirements);
 $template->assign('sequences', $sessionRequirements);
@@ -162,9 +203,7 @@ $template->assign('sequences', $sessionRequirements);
 $templateFolder = api_get_configuration_value('default_template');
 
 $layout = $template->get_template('session/about.tpl');
-
 $content = $template->fetch($layout);
-
 $template->assign('header', $session->getName());
 $template->assign('content', $content);
 $template->display_one_col_template();

+ 9 - 22
main/social/friends.php

@@ -117,8 +117,8 @@ if (count($friends) == 0) {
 
     $social_right_content .= $filterForm->returnForm();
 
-    $friend_html = '<div id="friends" class="row">';
-
+    $friend_html = '<div id="whoisonline">';
+    $friend_html .= '<div class="row">';
     $number_friends = count($friends);
     $j = 0;
 
@@ -126,31 +126,18 @@ if (count($friends) == 0) {
         while ($j < $number_friends) {
             if (isset($friends[$j])) {
                 $friend = $friends[$j];
-                $user_name = api_xml_http_response_encode($friend['firstName'].' '.$friend['lastName']);
-				$userPicture = UserManager::getUserPicture($friend['friend_user_id']);
-
-                $friend_html .= '
-                    <div class="col-md-3">
-                        <div class="thumbnail text-center" id="div_' . $friends[$j]['friend_user_id'] . '">
-                            <img src="' . $userPicture . '" class="img-responsive" id="imgfriend_' . $friend['friend_user_id'] . '" title="'.$user_name.'">
-                            <div class="caption">
-                                <h3>
-                                    <a href="profile.php?u=' . $friend['friend_user_id'] . '">' . $user_name . '</a>
-                                </h3>
-                                <p>
-                                    <button class="btn btn-danger" onclick="delete_friend(this)" id=img_' . $friend['friend_user_id'] . '>
-                                        ' . get_lang('Delete') . '
-                                    </button>
-                                </p>
-                            </div>
-                        </div>
-                    </div>
-                ';
+                 $toolBar = '<button class="btn btn-danger" onclick="delete_friend(this)" id=img_' . $friend['friend_user_id'] . '>
+                    ' . get_lang('Delete') . '
+                </button>';
+                $url = api_get_path(WEB_PATH).'main/social/profile.php?u='.$friend['friend_user_id'];
+                $friend['user_info']['complete_name'] = Display::url($friend['user_info']['complete_name'], $url);
+                $friend_html .= Display::getUserCard($friend['user_info'], '', $toolBar);
             }
             $j++;
         }
     }
     $friend_html .= '</div>';
+    $friend_html .= '</div>';
     $social_right_content .= $friend_html;
 }
 $social_right_content .= '</div>';

+ 47 - 17
main/social/groups.php

@@ -73,14 +73,30 @@ if (is_array($results) && count($results) > 0) {
         }
         $url  = '<a href="group_view.php?id='.$id.'">' . $name . '</a>';
 
-        $count_users_group = count($usergroup->get_users_by_group($id, false, array(GROUP_USER_PERMISSION_ADMIN, GROUP_USER_PERMISSION_READER, GROUP_USER_PERMISSION_MODERATOR), 0 , 1000));
-        if ($count_users_group == 1 ) {
+        $count_users_group = count(
+            $usergroup->get_users_by_group(
+                $id,
+                false,
+                array(
+                    GROUP_USER_PERMISSION_ADMIN,
+                    GROUP_USER_PERMISSION_READER,
+                    GROUP_USER_PERMISSION_MODERATOR,
+                ),
+                0,
+                1000
+            )
+        );
+        if ($count_users_group == 1) {
             $count_users_group = $count_users_group.' '.get_lang('Member');
         } else {
             $count_users_group = $count_users_group.' '.get_lang('Members');
         }
 
-        $picture = $usergroup->get_picture_group($result['id'], $result['picture'],80);
+        $picture = $usergroup->get_picture_group(
+            $result['id'],
+            $result['picture'],
+            80
+        );
         $result['picture'] = '<img class="social-groups-image" src="'.$picture['file'].'" />';
 
         $members = Display::returnFontAwesomeIcon('user').$count_users_group;
@@ -146,21 +162,18 @@ foreach ($results as $result) {
     //Avoiding my groups
 
     if (!in_array($id,$my_group_list)) {
-        $html .= '<a class="btn" href="group_view.php?id='.$id.'&action=join&u='.api_get_user_id().'">'.get_lang('JoinGroup').'</a> ';
+        $html .= '<a class="btn btn-primary" href="group_view.php?id='.$id.'&action=join&u='.api_get_user_id().'">'.get_lang('JoinGroup').'</a> ';
     }
 
     $html .= '<div class="group-actions" >'.$join_url.'</div>';
     $html .= '</div>';
     $html .= '</div>';
-
-
     $grid_item_2 = $html;
-
-    $grid_newest_groups[]= array($grid_item_2);
+    $grid_newest_groups[] = array($grid_item_2);
 }
 
 // Pop groups
-$results = $usergroup->get_groups_by_popularity(4,false);
+$results = $usergroup->get_groups_by_popularity(4, false);
 $grid_pop_groups = array();
 
 if (is_array($results) && count($results) > 0) {
@@ -168,10 +181,22 @@ if (is_array($results) && count($results) > 0) {
         $result['name'] = Security::remove_XSS($result['name'], STUDENT, true);
         $result['description'] = Security::remove_XSS($result['description'], STUDENT, true);
         $id = $result['id'];
-        $name = cut($result['name'],GROUP_TITLE_LENGTH,true);
+        $name = cut($result['name'], GROUP_TITLE_LENGTH, true);
 
-        $count_users_group = count($usergroup->get_users_by_group($id, false, array(GROUP_USER_PERMISSION_ADMIN, GROUP_USER_PERMISSION_READER, GROUP_USER_PERMISSION_MODERATOR), 0 , 1000));
-        if ($count_users_group == 1 ) {
+        $count_users_group = count(
+            $usergroup->get_users_by_group(
+                $id,
+                false,
+                array(
+                    GROUP_USER_PERMISSION_ADMIN,
+                    GROUP_USER_PERMISSION_READER,
+                    GROUP_USER_PERMISSION_MODERATOR,
+                ),
+                0,
+                1000
+            )
+        );
+        if ($count_users_group == 1) {
             $count_users_group = $count_users_group.' '.get_lang('Member');
         } else {
             $count_users_group = $count_users_group.' '.get_lang('Members');
@@ -197,9 +222,8 @@ if (is_array($results) && count($results) > 0) {
             $html .= '';
         }
         //Avoiding my groups
-
         if (!in_array($id,$my_group_list)) {
-            $html .= '<a class="btn" href="group_view.php?id='.$id.'&action=join&u='.api_get_user_id().'">'.get_lang('JoinGroup').'</a> ';
+            $html .= '<a class="btn btn-primary" href="group_view.php?id='.$id.'&action=join&u='.api_get_user_id().'">'.get_lang('JoinGroup').'</a> ';
         }
 
         $html .= '<div class="group-actions" >'.$join_url.'</div>';
@@ -213,15 +237,21 @@ if (is_array($results) && count($results) > 0) {
 
 // Display groups (newest, mygroups, pop)
 $query_vars = array();
-
 $newest_content = $popular_content = $my_group_content = null;
-
 if (isset($_GET['view']) && in_array($_GET['view'], $allowed_views)) {
     $view_group = $_GET['view'];
     switch ($view_group) {
         case 'mygroups':
             if (count($grid_my_groups) > 0) {
-                $my_group_content = Display::return_sortable_grid('mygroups', array(), $grid_my_groups, array('hide_navigation'=>true, 'per_page' => 2), $query_vars, false, array(true, true, true,false));
+                $my_group_content = Display::return_sortable_grid(
+                    'mygroups',
+                    array(),
+                    $grid_my_groups,
+                    array('hide_navigation' => true, 'per_page' => 2),
+                    $query_vars,
+                    false,
+                    array(true, true, true, false)
+                );
             }
             if (api_get_setting('allow_students_to_create_groups_in_social') == 'true') {
                 $create_group_item =  '<a class="btn btn-default" href="'.api_get_path(WEB_PATH).'main/social/group_add.php">'.

+ 10 - 7
main/social/home.php

@@ -102,9 +102,12 @@ if (!empty($results)) {
 
         $group_url = "group_view.php?id=$id";
 
-        $result['name'] = '<div class="group-name">'.Display::url(
-                          api_ucwords(cut($result['name'], 40, true)), $group_url)
-                          .'</div><div class="count-username">'.
+        $link = Display::url(
+            api_ucwords(cut($result['name'], 40, true)),
+            $group_url
+        );
+
+        $result['name'] = '<div class="group-name">'.$link.'</div><div class="count-username">'.
                             Display::returnFontAwesomeIcon('user').$result['count'].'</div>';
 
         $picture = $userGroup->get_picture_group(
@@ -115,7 +118,7 @@ if (!empty($results)) {
         );
 
         $result['picture'] = '<img class="img-responsive" src="' . $picture['file'] . '" />';
-        $group_actions = '<div class="group-more"><a href="groups.php?#tab_browse-2">' . get_lang('SeeMore') . '</a></div>';
+        $group_actions = '<div class="group-more"><a class="btn btn-default" href="groups.php?#tab_browse-2">' . get_lang('SeeMore') . '</a></div>';
         $group_info= '<div class="description"><p>' . cut($result['description'], 120, true) . "</p></div>";
         $groups_newest[] = array(
             Display::url(
@@ -158,7 +161,7 @@ foreach ($results as $result) {
         GROUP_IMAGE_SIZE_BIG
     );
     $result['picture_uri'] = '<img class="img-responsive" src="' . $picture['file'] . '" />';
-    $group_actions = '<div class="group-more" ><a href="groups.php?#tab_browse-3">' . get_lang('SeeMore') . '</a></div>';
+    $group_actions = '<div class="group-more"><a class="btn btn-default" href="groups.php?#tab_browse-3">' . get_lang('SeeMore') . '</a></div>';
     $group_info= '<div class="description"><p>' . cut($result['description'], 120, true) . "</p></div>";
     $groups_pop[] = array(
         Display::url($result['picture_uri'], $group_url),
@@ -171,7 +174,7 @@ $social_group_block = null;
 if ($list > 0) {
     $social_group_block .= '<div class="list-group-newest">';
     $social_group_block .= '<div class="group-title">' . get_lang('Newest') . '</div>';
-    for ($i = 0;$i < $list; $i++) {
+    for ($i = 0; $i < $list; $i++) {
         $social_group_block.='<div class="row">';
         $social_group_block.='<div class="col-md-3">' . $groups_newest[$i][0] . '</div>';
         $social_group_block.='<div class="col-md-9">' . $groups_newest[$i][1];
@@ -185,7 +188,7 @@ if ($list > 0) {
     $social_group_block .= '<div class="list-group-newest">';
     $social_group_block .= '<div class="group-title">' . get_lang('Popular') . '</div>';
 
-    for ($i = 0;$i < $list; $i++) {
+    for ($i = 0; $i < $list; $i++) {
         $social_group_block.='<div class="row">';
         $social_group_block.='<div class="col-md-3">' . $groups_pop[$i][0] . '</div>';
         $social_group_block.='<div class="col-md-9">' . $groups_pop[$i][1];

+ 24 - 24
main/social/search.php

@@ -17,7 +17,10 @@ if (api_get_setting('allow_social_tool') != 'true') {
 
 $this_section = SECTION_SOCIAL;
 $tool_name = get_lang('Search');
-$interbreadcrumb[] = array('url' => 'profile.php', 'name' => get_lang('SocialNetwork'));
+$interbreadcrumb[] = array(
+    'url' => api_get_path(WEB_CODE_PATH).'social/profile.php',
+    'name' => get_lang('SocialNetwork'),
+);
 
 $query = isset($_GET['q']) ? Security::remove_XSS($_GET['q']): null;
 $query_search_type = isset($_GET['search_type']) && in_array($_GET['search_type'], array('0','1','2')) ? $_GET['search_type'] : null;
@@ -41,16 +44,21 @@ $groups = array();
 $totalGroups = array();
 $users = array();
 $totalUsers = array();
-
 $usergroup = new UserGroup();
 
 // I'm searching something
-if ($query != '' || ($query_vars['search_type']=='1' && count($query_vars)>2) ) {
-    $itemPerPage = 8;
+if ($query != '' || ($query_vars['search_type']=='1' && count($query_vars)>2)) {
+    $itemPerPage = 6;
 
     if ($_GET['search_type']=='0' || $_GET['search_type']=='1') {
         $page = isset($_GET['users_page_nr']) ? intval($_GET['users_page_nr']) : 1;
-        $totalUsers = UserManager::get_all_user_tags($_GET['q'], 0, 0, $itemPerPage, true);
+        $totalUsers = UserManager::get_all_user_tags(
+            $_GET['q'],
+            0,
+            0,
+            $itemPerPage,
+            true
+        );
 
         $from = intval(($page - 1) * $itemPerPage);
         // Get users from tags
@@ -72,7 +80,6 @@ if ($query != '' || ($query_vars['search_type']=='1' && count($query_vars)>2) )
 
     $results = '<div id="whoisonline">';
     if (is_array($users) && count($users) > 0) {
-
         $results .= '<div class="row">';
         $buttonClass = 'btn btn-default btn-sm';
         foreach ($users as $user) {
@@ -104,8 +111,6 @@ if ($query != '' || ($query_vars['search_type']=='1' && count($query_vars)>2) )
                 ]
             );
 
-            $img = '<img src="'.$user_info['avatar'].'" class="img-responsive img-circle" width="100" height="100">';
-
             if ($user_info['user_is_online']) {
                 $status_icon = Display::return_icon('online.png', get_lang('OnLine'), null, ICON_SIZE_TINY);
             } else {
@@ -122,20 +127,11 @@ if ($query != '' || ($query_vars['search_type']=='1' && count($query_vars)>2) )
             $user_info['complete_name'] = Display::url($user_info['complete_name'], $url);
             $invitations = $user['tag'].$sendInvitation.$sendMessage;
 
-            $results .= '<div class="col-md-3">
-                            <div class="items-user">
-                                <div class="items-user-avatar">
-                                '.$img.'
-                                </div>
-                                <div class="user-info">
-                                   <p>'.$user_info['complete_name'].'</p>
-                                   <div class="items-user-status">' . $status_icon . $user_icon . '</div>
-                                   <div class="toolbar">
-                                    '.$invitations.'
-                                   </div>
-                                </div>
-                            </div>
-                      </div>';
+            $results .= Display::getUserCard(
+                $user_info,
+                $status_icon.$user_icon,
+                $invitations
+            );
         }
         $results .= '</div>';
     }
@@ -181,8 +177,12 @@ if ($query != '' || ($query_vars['search_type']=='1' && count($query_vars)>2) )
             } else {
                 $count_users_group = $count_users_group;
             }
-            $picture = $usergroup->get_picture_group($group['id'], $group['picture'], GROUP_IMAGE_SIZE_ORIGINAL);
-            //$tags = $usergroup->get_group_tags($group['id']);
+            $picture = $usergroup->get_picture_group(
+                $group['id'],
+                $group['picture'],
+                GROUP_IMAGE_SIZE_ORIGINAL
+            );
+
             $tags = null;
             $group['picture'] = '<img class="img-responsive img-circle" src="'.$picture['file'].'" />';
 

+ 9 - 6
main/template/default/auth/courses_categories.php

@@ -61,7 +61,6 @@ $code = isset($code) ? $code : null;
         <?php } ?>
     });
 </script>
-
 <div class="row">
     <div class="col-md-4">
         <h5><?php echo get_lang('Search'); ?></h5>
@@ -131,7 +130,6 @@ $code = isset($code) ? $code : null;
 <div class="row">
 <?php
 if ($showCourses && $action != 'display_sessions') {
-
     if (!empty($message)) {
         Display::display_confirmation_message($message, false);
     }
@@ -150,6 +148,8 @@ if ($showCourses && $action != 'display_sessions') {
     $ajax_url = api_get_path(WEB_AJAX_PATH).'course.ajax.php?a=add_course_vote';
     $user_id = api_get_user_id();
 
+    $categoryList = CourseManager::getCategoriesList();
+
     if (!empty($browse_courses_in_category)) {
         foreach ($browse_courses_in_category as $course) {
             $course_hidden = $course['visibility'] == COURSE_VISIBILITY_HIDDEN;
@@ -175,6 +175,11 @@ if ($showCourses && $action != 'display_sessions') {
             // display the course bloc
             $html .= '<div class="col-xs-6 col-sm-6 col-md-3"><div class="items items-courses">';
 
+            $course['category_title'] = '';
+            if (isset($course['category'])) {
+                $course['category_title'] = isset($categoryList[$course['category']]) ? $categoryList[$course['category']] : '';
+            }
+
             // display thumbnail
             $html .= returnThumbnail($course);
 
@@ -267,6 +272,7 @@ echo $cataloguePagination;
 /**
  * Display the course catalog image of a course
  * @param array $course
+ *
  * @return string HTML string
  */
 function returnThumbnail($course)
@@ -285,10 +291,8 @@ function returnThumbnail($course)
 
     $html .= '<div class="image">';
     $html .= '<img class="img-responsive" src="'.$course_medium_image.'" alt="'.api_htmlentities($title).'"/>';
-    $categoryTitle = isset($course['category']) ? $course['category'] : '';
+    $categoryTitle = isset($course['category_title']) ? $course['category_title'] : '';
     if (!empty($categoryTitle)) {
-        $listCategory = CourseManager::getCategoriesList();
-        $categoryTitle = $listCategory[$categoryTitle];
         $html .= '<span class="category">'. $categoryTitle.'</span>';
         $html .= '<div class="cribbon"></div>';
     }
@@ -317,7 +321,6 @@ function returnThumbnail($course)
     return $html;
 }
 
-
 /**
  * Display the title of a course in course catalog
  * @param $course

+ 0 - 1
main/template/default/layout/head.tpl

@@ -33,4 +33,3 @@ var disconnect_lang = '{{ "ChatDisconnected"|get_lang }}';
 
 {{ css_custom_file_to_string }}
 {{ css_style_print }}
-{{ header_extra_content }}

+ 2 - 0
main/template/default/layout/layout_1_col.tpl

@@ -1,6 +1,7 @@
 {% extends template ~ "/layout/page.tpl" %}
 
 {% block body %}
+    <div class="row">
     {% if plugin_main_top %}
         <div id="plugin_main_top" class="col-md-12">
             {{ plugin_main_top }}
@@ -35,4 +36,5 @@
             {{ plugin_main_bottom }}
         </div>
     {% endif %}
+    </div>
 {% endblock %}

+ 2 - 0
main/template/default/layout/layout_2_col.tpl

@@ -1,6 +1,7 @@
 {% extends template ~ "/layout/page.tpl" %}
 
 {% block body %}
+    <div class="row">
 {% if plugin_main_top %}
     <div id="plugin_main_top" class="col-md-12">
         {{ plugin_main_top }}
@@ -93,4 +94,5 @@
         {{ plugin_main_bottom }}
     </div>
 {% endif %}
+    </div>
 {% endblock %}

+ 49 - 50
main/template/default/layout/menu.tpl

@@ -2,7 +2,8 @@
     <div class="container">
         <!-- Brand and toggle get grouped for better mobile display -->
         <div class="navbar-header">
-            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#menuone" aria-expanded="false">
+            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#menuone"
+                    aria-expanded="false">
                 <span class="sr-only">Toggle navigation</span>
                 <span class="icon-bar"></span>
                 <span class="icon-bar"></span>
@@ -18,59 +19,57 @@
                     </li>
                 {% endfor %}
             </ul>
-           {% if _u.logged == 1 %}
-               <script>
-               $(document).ready(function() {
-                    $.ajax({
-                        type: "GET",
-                        url: "{{ _p.web_main }}inc/ajax/message.ajax.php?a=get_count_message",
-                        success: function(data) {
-                            if (data != '') {
-                                $("#count_message_li").show();
-                                $("#count_message").html(data);
-                            }
-                        }
+            {% if _u.logged == 1 %}
+                <script>
+                    $(document).ready(function () {
+                        $("#count_message")
+                            .load('{{ _p.web_main }}inc/ajax/message.ajax.php?a=get_count_message', function () {
+                                $("#count_message_li").removeClass('hidden');
+                            });
                     });
-                });
-               </script>
-            <ul class="nav navbar-nav navbar-right">
-               <li id="count_message_li" style="display: none">
-                   <a href="{{ message_url }}">
-                       <span id="count_message"></span>
-                   </a>
-               </li>
-               {% if _u.status != 6 %}
-                <li class="dropdown avatar-user">
-                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
-                        <img class="img-circle" src="{{ _u.avatar_small }}" alt="{{ _u.complete_name }}" />  <span class="caret"></span>
-                    </a>
-                    <ul class="dropdown-menu" role="menu">
-                        <li class="user-header">
-                            <div class="text-center">
-                            <img class="img-circle" src="{{ _u.avatar_medium }}" alt="{{ _u.complete_name }}" />
-                            <p class="name"><a href="{{ profile_url }}">{{ _u.complete_name }}</a></p>
-                            <p><i class="fa fa-envelope-o" aria-hidden="true"></i> {{ _u.email }}</p>
-                            </div>
-                        </li>
-                        <li role="separator" class="divider"></li>
-                        <li class="user-body">
-                            <a title="{{ "Inbox"|get_lang }}" href="{{ message_url }}">
-                                <em class="fa fa-envelope" aria-hidden="true"></em> {{ "Inbox"|get_lang }}
-                            </a>
-                            {% if certificate_url %}
-                            <a title="{{ "MyCertificates"|get_lang }}" href="{{ certificate_url }}">
-                                <em class="fa fa-graduation-cap" aria-hidden="true"></em> {{ "MyCertificates"|get_lang }}
+                </script>
+                <ul class="nav navbar-nav navbar-right">
+                    <li id="count_message_li" class="hidden">
+                        <a href="{{ message_url }}">
+                            <span id="count_message"></span>
+                        </a>
+                    </li>
+                    {% if _u.status != 6 %}
+                        <li class="dropdown avatar-user">
+                            <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button"
+                               aria-expanded="false">
+                                <img class="img-circle" src="{{ _u.avatar_small }}" alt="{{ _u.complete_name }}"/> <span
+                                        class="caret"></span>
                             </a>
-                            {% endif %}
+                            <ul class="dropdown-menu" role="menu">
+                                <li class="user-header">
+                                    <div class="text-center">
+                                        <img class="img-circle" src="{{ _u.avatar_medium }}"
+                                             alt="{{ _u.complete_name }}"/>
+                                        <p class="name"><a href="{{ profile_url }}">{{ _u.complete_name }}</a></p>
+                                        <p><i class="fa fa-envelope-o" aria-hidden="true"></i> {{ _u.email }}</p>
+                                    </div>
+                                </li>
+                                <li role="separator" class="divider"></li>
+                                <li class="user-body">
+                                    <a title="{{ "Inbox"|get_lang }}" href="{{ message_url }}">
+                                        <em class="fa fa-envelope" aria-hidden="true"></em> {{ "Inbox"|get_lang }}
+                                    </a>
+                                    {% if certificate_url %}
+                                        <a title="{{ "MyCertificates"|get_lang }}" href="{{ certificate_url }}">
+                                            <em class="fa fa-graduation-cap"
+                                                aria-hidden="true"></em> {{ "MyCertificates"|get_lang }}
+                                        </a>
+                                    {% endif %}
 
-                            <a id="logout_button" title="{{ "Logout"|get_lang }}" href="{{ logout_link }}" >
-                                <em class="fa fa-sign-out"></em> {{ "Logout"|get_lang }}
-                            </a>
+                                    <a id="logout_button" title="{{ "Logout"|get_lang }}" href="{{ logout_link }}">
+                                        <em class="fa fa-sign-out"></em> {{ "Logout"|get_lang }}
+                                    </a>
+                                </li>
+                            </ul>
                         </li>
-                    </ul>
-                </li>
-               {% endif %}
-            </ul>
+                    {% endif %}
+                </ul>
             {% endif %}
         </div>
     </div>

+ 3 - 1
main/template/default/layout/page.tpl

@@ -44,7 +44,9 @@
 	<section id="content-section">
         <div class="container">
             {% block breadcrumb %}
-                {{ breadcrumb }}
+                <div id="page-breadcrumb">
+                    {{ breadcrumb }}
+                </div>
             {% endblock %}
 
             {% block body %}

+ 34 - 40
main/template/default/layout/page_header.tpl

@@ -7,58 +7,52 @@
 {% endblock %}
 <div class="extra-header">{{ header_extra_content }}</div>
 <header id="header-section">
-<section>
     <div class="container">
-	<div class="row">
-	    <div class="col-md-3">
-	    	<div class="logo">
-                {{ logo }}
+        <div class="row">
+            <div class="col-md-3">
+                <div class="logo">
+                    {{ logo }}
+                </div>
             </div>
-	    </div>
             <div class="col-md-9">
-                <div class="col-sm-4">
-                    {% if plugin_header_left is not null %}
-                    <div id="plugin_header_left">
-                        {{ plugin_header_left }}
-                    </div>
-                    {% endif %}
-                </div>
-                <div class="col-sm-4">
-                    {% if plugin_header_center is not null %}
-                    <div id="plugin_header_center">
-                        {{ plugin_header_center }}
+                <div class="row">
+                    <div class="col-sm-4">
+                        {% if plugin_header_left is not null %}
+                            <div id="plugin_header_left">
+                                {{ plugin_header_left }}
+                            </div>
+                        {% endif %}
                     </div>
-                    {% endif %}
-                </div>
-                <div class="col-sm-4">
-                    {% if plugin_header_right is not null %}
-                    <div id="plugin_header_right">
-                        {{ plugin_header_right }}
+                    <div class="col-sm-4">
+                        {% if plugin_header_center is not null %}
+                            <div id="plugin_header_center">
+                                {{ plugin_header_center }}
+                            </div>
+                        {% endif %}
                     </div>
-                    {% endif %}
-                     <script>
-                       $(document).ready(function() {
-                            $.ajax({
-                                type: "GET",
-                                url: "{{ _p.web_main }}inc/ajax/online.ajax.php?a=get_users_online",
-                                success: function(data) {
-                                    $("#notifications").append(data);
-                                }
+                    <div class="col-sm-4">
+                        {% if plugin_header_right is not null %}
+                            <div id="plugin_header_right">
+                                {{ plugin_header_right }}
+                            </div>
+                        {% endif %}
+                        <script>
+                            $(document).on('ready', function () {
+                                $("#notifications").load("{{ _p.web_main }}inc/ajax/online.ajax.php?a=get_users_online");
                             });
-                        });
-                       </script>
-                    <div class="section-notifications">
-                        <ul id="notifications" class="nav nav-pills pull-right">
-                        </ul>
+                        </script>
+                        <div class="section-notifications">
+                            <ul id="notifications" class="nav nav-pills pull-right">
+                            </ul>
+                        </div>
+                        {{ accessibility }}
                     </div>
-                    {{ accessibility }}
                 </div>
             </div>
         </div>
     </div>
-</section>
+</header>
 {% block menu %}
     {% include template ~ "/layout/menu.tpl" %}
 {% endblock %}
-</header>
 {% include template ~ "/layout/course_navigation.tpl" %}

+ 3 - 1
main/template/default/layout/show_header.tpl

@@ -37,7 +37,9 @@
 <section id="content-section">
     <div class="container">
         {% block breadcrumb %}
-            {{ breadcrumb }}
+            <div id="page-breadcrumb">
+                {{ breadcrumb }}
+            </div>
         {% endblock %}
         {{ flash_messages }}
 {% endif %}

+ 3 - 1
main/template/default/mail/mail.tpl

@@ -16,7 +16,7 @@
         }
     </script>
 </head>
-<body style="margin: 0; padding: 0;">
+<body style="margin: 0; padding: 0; ">
     <table border="0" cellpadding="0" cellspacing="0" width="100%">
         <tr>
             <td>
@@ -28,7 +28,9 @@
                     </tr>
                     <tr>
                         <td cellpadding="0" cellspacing="0" style="padding: 40px 10px">
+                            <span {{ mail_content_style }}>
                             {{ content }}
+                            </span>
                         </td>
                     </tr>
                     <tr>

+ 61 - 14
main/template/default/session/about.tpl

@@ -28,10 +28,11 @@
                                     <dl class="dl-horizontal">
                                         {% if sequence.requirements %}
                                             <dt>{{ sequence.name }}</dt>
-
                                             {% for requirement in sequence.requirements %}
                                                 <dd>
-                                                    <a href="{{ _p.web ~ 'session/' ~ requirement.getId ~ '/about/' }}">{{ requirement.getName }}</a>
+                                                    <a href="{{ _p.web ~ 'session/' ~ requirement.getId ~ '/about/' }}">
+                                                        {{ requirement.getName }}
+                                                    </a>
                                                 </dd>
                                             {% endfor %}
                                         {% endif %}
@@ -91,7 +92,7 @@
                     <div class="panel-body">
                         {% if course_data.objectives %}
                             <div class="objective-course">
-                                <h4 class="title-info"><em class="fa fa-book"></em> {{ "Objectives"|get_lang }}</h4>
+                                <h4 class="title-info"><em class="fa fa-book"></em> {{ course_data.objectives.getTitle }}</h4>
                                 <div class="content-info">
                                     {{ course_data.objectives.getContent }}
                                 </div>
@@ -100,12 +101,59 @@
 
                         {% if course_data.topics %}
                             <div class="topics">
-                                <h4 class="title-info"><em class="fa fa-book"></em> {{ "Topics"|get_lang }}</h4>
+                                <h4 class="title-info"><em class="fa fa-book"></em> {{ course_data.topics.getTitle }}</h4>
                                 <div class="content-info">
                                     {{ course_data.topics.getContent }}
                                 </div>
                             </div>
                         {% endif %}
+
+                        {% if course_data.methodology %}
+                            <div class="topics">
+                                <h4 class="title-info"><em class="fa fa-book"></em> {{ course_data.methodology.getTitle }}</h4>
+                                <div class="content-info">
+                                    {{ course_data.methodology.getContent }}
+                                </div>
+                            </div>
+                        {% endif %}
+
+                        {% if course_data.material %}
+                            <div class="topics">
+                                <h4 class="title-info"><em class="fa fa-book"></em> {{ course_data.material.getTitle }}</h4>
+                                <div class="content-info">
+                                    {{ course_data.material.getContent }}
+                                </div>
+                            </div>
+                        {% endif %}
+
+                        {% if course_data.resources %}
+                            <div class="topics">
+                                <h4 class="title-info"><em class="fa fa-book"></em> {{ course_data.resources.getTitle }}</h4>
+                                <div class="content-info">
+                                    {{ course_data.resources.getContent }}
+                                </div>
+                            </div>
+                        {% endif %}
+
+                        {% if course_data.assesment %}
+                            <div class="topics">
+                                <h4 class="title-info"><em class="fa fa-book"></em> {{ course_data.assesment.getTitle }}</h4>
+                                <div class="content-info">
+                                    {{ course_data.assesment.getContent }}
+                                </div>
+                            </div>
+                        {% endif %}
+
+                        {% if course_data.custom %}
+                            {% for custom in course_data.custom %}
+                                <div class="topics">
+                                    <h4 class="title-info"><em class="fa fa-book"></em> {{ custom.getTitle }}</h4>
+                                    <div class="content-info">
+                                        {{ custom.getContent }}
+                                    </div>
+                                </div>
+                            {% endfor %}
+                        {% endif %}
                     </div>
                 </div>
             </div>
@@ -121,7 +169,6 @@
                                 <div class="row">
                                     <div class="col-xs-7 col-md-7">
                                         <h4>{{ coach.complete_name }}</h4>
-
                                         {% for extra_field in coach.extra_fields %}
                                             <dl>
                                                 <dt>{{ extra_field.value.getField().getDisplayText() }}</dt>
@@ -159,13 +206,13 @@
                     <div class="panel-heading">{{ "ShareWithYourFriends"|get_lang }}</div>
                     <div class="panel-body">
                         <div class="icons-social text-center">
-                            <a href="https://www.facebook.com/sharer/sharer.php?{{ {'u': pageUrl}|url_encode }}" target="_blank" class="btn bnt-link btn-lg">
+                            <a href="https://www.facebook.com/sharer/sharer.php?{{ {'u': page_url }|url_encode }}" target="_blank" class="btn bnt-link btn-lg">
                                 <em class="fa fa-facebook fa-2x"></em>
                             </a>
-                            <a href="https://twitter.com/home?{{ {'status': session.getName() ~ ' ' ~ pageUrl}|url_encode }}" target="_blank" class="btn bnt-link btn-lg">
+                            <a href="https://twitter.com/home?{{ {'status': session.getName() ~ ' ' ~ page_url }|url_encode }}" target="_blank" class="btn bnt-link btn-lg">
                                 <em class="fa fa-twitter fa-2x"></em>
                             </a>
-                            <a href="https://www.linkedin.com/shareArticle?{{ {'mini': 'true', 'url': pageUrl, 'title': session.getName() }|url_encode }}" target="_blank" class="btn bnt-link btn-lg">
+                            <a href="https://www.linkedin.com/shareArticle?{{ {'mini': 'true', 'url': page_url , 'title': session.getName() }|url_encode }}" target="_blank" class="btn bnt-link btn-lg">
                                 <em class="fa fa-linkedin fa-2x"></em>
                             </a>
                         </div>
@@ -176,18 +223,18 @@
     {% endfor %}
 
     <div class="row">
-        <div class="col-md-4 col-md-offset-4">
+        <div class="col-md-12">
+            <div class="text-center">
             {% if _u.logged and not is_subscribed %}
-                <div class="text-center">
-                    {{ subscribe_button }}
-                </div>
+                {{ subscribe_button }}
             {% elseif not _u.logged %}
                 {% if 'allow_registration'|get_setting == 'true' %}
-                    <a href="{{ _p.web_main ~ 'auth/inscription.php' }}" class="btn btn-info btn-lg">
-                        <em class="fa fa-sign-in fa-fw"></em> {{ 'SignUp'|get_lang }}
+                    <a href="{{ _p.web_main ~ 'auth/inscription.php' ~ redirect_to_session }}" class="btn btn-info btn-lg">
+                        <i class="fa fa-pencil" aria-hidden="true"></i> {{ 'SignUp'|get_lang }}
                     </a>
                 {% endif %}
             {% endif %}
+            </div>
         </div>
     </div>
 </div>

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

@@ -4,7 +4,7 @@
             <div class="panel-heading" role="tab" id="heading-sn">
                 <h4 class="panel-title">
                     <a role="button" data-toggle="collapse" data-parent="#sn-avatar" href="#sn-avatar-one" aria-expanded="true" aria-controls="sn-avatar-one">
-                    {{ "Role" | get_lang }}
+                    {{ "Profile" | get_lang }}
                     </a>
                 </h4>
             </div>

+ 4 - 0
main/work/work.lib.php

@@ -5128,6 +5128,10 @@ function protectWork($courseInfo, $workId)
     }
 }
 
+/**
+ * @param array $courseInfo
+ * @param array $work
+ */
 function deleteCorrection($courseInfo, $work)
 {
     if (isset($work['url_correction']) && !empty($work['url_correction']) && isset($work['iid'])) {

+ 1 - 1
plugin/google_maps/lang/english.php

@@ -4,7 +4,7 @@ $strings['plugin_title'] = "Google Maps";
 $strings['plugin_comment'] = "Enable the functionality to show google maps";
 $strings['extra_field_name_help'] = "Enter one or many extra user fields name separated by a comma (,) from which you want to obtain the locations, you can get up to 5 geolocation fields (the rest will be ignored) which will be marked with the following icons respectively:
 <br><br>
-<img src='//maps.google.com/mapfiles/ms/icons/red-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/green-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/blue-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/yellow-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/purple-dot.png'>
+<img src='//maps.google.com/mapfiles/ms/icons/red-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/blue-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/green-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/yellow-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/purple-dot.png'>
 <br><br>
 Follow the link below to see the map : <a href='". api_get_path(WEB_PLUGIN_PATH) . "google_maps/src/map_coordinates.php'>" . api_get_path(WEB_PLUGIN_PATH) . "google_maps/src/map_coordinates.php</a>";
 $strings['enable_api'] = "Enable API";

+ 1 - 1
plugin/google_maps/lang/french.php

@@ -4,7 +4,7 @@ $strings['plugin_title'] = "Google Maps";
 $strings['plugin_comment'] = "Active la fonctionnalité pour afficher Google Maps";
 $strings['extra_field_name_help'] = "Entrez ici le ou les nom(s) des champs extra d'utilisateur séparés par une virgule (,) desquels on souhaite obtenir la géolocalisation, vous pouvez définir jusqu'à 5 champs pour la géolocalisation (le reste est ignoré). Ils seront associés dans l'ordre avec les icônes suivantes :
 <br><br>
-<img src='//maps.google.com/mapfiles/ms/icons/red-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/green-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/blue-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/yellow-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/purple-dot.png'>
+<img src='//maps.google.com/mapfiles/ms/icons/red-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/blue-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/green-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/yellow-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/purple-dot.png'>
 <br><br>
 Suivez le lien pour voir la carte : <a href='". api_get_path(WEB_PLUGIN_PATH) . "google_maps/src/map_coordinates.php'>" . api_get_path(WEB_PLUGIN_PATH) . "google_maps/src/map_coordinates.php</a>";
 $strings['enable_api'] = "Enable API";

+ 1 - 1
plugin/google_maps/lang/spanish.php

@@ -4,7 +4,7 @@ $strings['plugin_title'] = "Google Maps";
 $strings['plugin_comment'] = "Enable the functionality to show google maps";
 $strings['extra_field_name_help'] = "Ingrese aquí el nombre del campo o los campos extra de usuario separados por una coma (,) del cual quiere obtener las localizaciones, puede obtener hasta 5 campos de geolocalización (el resto serán ignorados) los cuales se marcarán con los siguientes iconos respectivamente:
 <br><br>
-<img src='//maps.google.com/mapfiles/ms/icons/red-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/green-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/blue-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/yellow-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/purple-dot.png'>
+<img src='//maps.google.com/mapfiles/ms/icons/red-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/blue-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/green-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/yellow-dot.png'> <img src='//maps.google.com/mapfiles/ms/icons/purple-dot.png'>
 <br><br>
 siga el siguiente link para ver el mapa : <a href='". api_get_path(WEB_PLUGIN_PATH) . "google_maps/src/map_coordinates.php'>" . api_get_path(WEB_PLUGIN_PATH) . "google_maps/src/map_coordinates.php</a>";
 $strings['enable_api'] = "Activar API";

+ 2 - 2
plugin/google_maps/view/map_coordinates.tpl

@@ -72,10 +72,10 @@
                         marker.setIcon('//maps.google.com/mapfiles/ms/icons/red-dot.png');
                         break;
                     case 2:
-                        marker.setIcon('//maps.google.com/mapfiles/ms/icons/green-dot.png');
+                        marker.setIcon('//maps.google.com/mapfiles/ms/icons/blue-dot.png');
                         break;
                     case 3:
-                        marker.setIcon('//maps.google.com/mapfiles/ms/icons/blue-dot.png');
+                        marker.setIcon('//maps.google.com/mapfiles/ms/icons/green-dot.png');
                         break;
                     case 4:
                         marker.setIcon('//maps.google.com/mapfiles/ms/icons/yellow-dot.png');

+ 31 - 21
plugin/vchamilo/install.php

@@ -17,29 +17,39 @@ api_protect_admin_script();
 
 $table = 'vchamilo';
 $tablename = Database::get_main_table($table);
-$sql = "CREATE TABLE IF NOT EXISTS $tablename (
-  id int NOT NULL AUTO_INCREMENT,
-  sitename varchar(80) NOT NULL,
-  slug varchar(255) NOT NULL,
-  institution varchar(80) NOT NULL,
-  root_web varchar(120),
-  db_host varchar(80) NOT NULL,
-  db_user varchar(16) DEFAULT 'root',
-  db_password varchar(32),  
-  table_prefix varchar(16),
-  db_prefix varchar(16),
-  main_database varchar(60) DEFAULT 'chamilo',
-  url_append varchar(32),
-  course_folder varchar(80),
-  visible int,
-  lastcrongap int,
-  lastcron int,
-  croncount int,
-  template varchar(255),
-  password_encryption varchar(255),  
-  PRIMARY KEY (id)
+$sql = "
+    CREATE TABLE IF NOT EXISTS $tablename (
+    id int NOT NULL AUTO_INCREMENT,
+    sitename varchar(80) NOT NULL,
+    slug varchar(255) NOT NULL,
+    institution varchar(80) NOT NULL,
+    root_web varchar(120),
+    db_host varchar(80) NOT NULL,
+    db_user varchar(16) DEFAULT 'root',
+    db_password varchar(32),  
+    table_prefix varchar(16),
+    db_prefix varchar(16),
+    main_database varchar(60) DEFAULT 'chamilo',
+    url_append varchar(32),
+    course_folder varchar(80),
+    visible int,
+    lastcrongap int,
+    lastcron int,
+    croncount int,
+    template varchar(255),
+    password_encryption varchar(255),
+    archive_url varchar(255),
+    home_url varchar(255),
+    upload_url varchar(255),
+    course_url varchar(255),
+    PRIMARY KEY (id)
 ) DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
 ";
+
+/*ALTER TABLE vchamilo ADD COLUMN archive_url varchar(255);
+ALTER TABLE vchamilo ADD COLUMN home_url varchar(255);
+ALTER TABLE vchamilo ADD COLUMN upload_url varchar(255);
+ALTER TABLE vchamilo ADD COLUMN course_url varchar(255);*/
 Database::query($sql);
 
 $table = 'vchamilo_config';

+ 5 - 0
plugin/vchamilo/lang/english.php

@@ -117,3 +117,8 @@ $strings['CoursePath'] = 'Path to courses directory';
 $strings['HomePath'] = 'Path to home directory';
 $strings['UploadPath'] = 'Path to upload directory';
 
+$strings['ArchiveUrl'] = 'Archive URL';
+$strings['HomeUrl'] = 'Home URL';
+$strings['UploadUrl'] = 'Upload URL';
+$strings['CourseUrl'] = 'Course URL';
+

+ 11 - 2
plugin/vchamilo/lib/Virtual.php

@@ -96,10 +96,13 @@ class Virtual
 
                 $data['SYS_ARCHIVE_PATH'] = self::addTrailingSlash($archivePath).$data['slug'];
                 $data['SYS_HOME_PATH'] = self::addTrailingSlash($homePath).$data['slug'];
-                $data['WEB_HOME_PATH'] = $_configuration['vchamilo_web_root'] . '/var/home/' . $data['slug'];
                 $data['SYS_COURSE_PATH'] = self::addTrailingSlash($coursePath).$data['slug'];
                 $data['SYS_UPLOAD_PATH'] = self::addTrailingSlash($uploadPath).$data['slug'];
-                //$data['WEB_UPLOAD_PATH'] = $_configuration['vchamilo_web_root'] . '/var/upload/' . $data['slug'];
+
+                $data['WEB_HOME_PATH'] = self::addTrailingSlash($data['home_url']);
+                $data['WEB_UPLOAD_PATH'] = self::addTrailingSlash($data['upload_url']);
+                $data['WEB_ARCHIVE_PATH'] = self::addTrailingSlash($data['archive_url']);
+                //$data['WEB_COURSE_PATH'] = self::addTrailingSlash($data['course_url']);
 
                 if (!empty($passwordEncryption)) {
                     $_configuration['password_encryption'] = $passwordEncryption;
@@ -962,6 +965,12 @@ class Virtual
         }
 
         $data->root_web = api_add_trailing_slash($data->root_web);
+
+        $data->archive_url = api_add_trailing_slash($data->archive_url);
+        $data->home_url = api_add_trailing_slash($data->home_url);
+        $data->upload_url = api_add_trailing_slash($data->upload_url);
+        $data->course_url = api_add_trailing_slash($data->course_url);
+
         if (substr($data->root_web, 0, 4) != 'http') {
             $data->root_web = api_get_protocol().'://'.$data->root_web;
         }

+ 5 - 0
plugin/vchamilo/views/editinstance_form.php

@@ -415,6 +415,11 @@ class InstanceForm extends ChamiloForm
             'onclick="opencnxpopup(\''.$_configuration['root_web'].'\'); return false;"'
         );
 
+        $form->addText('archive_url', $this->_plugin->get_lang('ArchiveUrl'));
+        $form->addText('home_url', $this->_plugin->get_lang('HomeUrl'));
+        $form->addText('upload_url', $this->_plugin->get_lang('UploadUrl'));
+        //$form->addText('course_url', $this->_plugin->get_lang('CourseUrl'));
+
         /**
          * Template selection.
          */

+ 2 - 2
src/Chamilo/CoreBundle/Entity/ExtraField.php

@@ -124,8 +124,8 @@ class ExtraField extends BaseAttribute
     public function __construct()
     {
         parent::__construct();
-        $this->visibleToOthers = 0;
-        $this->visibleToSelf = 0;
+        $this->visibleToOthers = false;
+        $this->visibleToSelf = false;
     }
 
     /**

+ 1 - 16
tests/main/forum/forumfunction.inc.test.php

@@ -487,7 +487,7 @@ class TestForumFunction extends UnitTestCase {
 		}
 		//var_dump($res);
 	 }
-	
+
 	 /**
 	* Retrieve all posts of a given thread
 	* @param int $thread_id integer that indicates the forum
@@ -1172,21 +1172,6 @@ class TestForumFunction extends UnitTestCase {
 		$this->assertTrue(is_null($res));
 		//var_dump($res);
 	}
-
-
- 	 /**
-	* This public function is called when the user is not allowed in this forum/thread/...
-	* @return bool display message of "not allowed"
-	*/
-
-	public function testforum_not_allowed_here() {
-		 ob_start();
-		 $res = forum_not_allowed_here();
-		 ob_end_clean();
-		 $this->assertTrue(is_bool($res));
-		 //var_dump($res);
-	 }
-
 	  /**
 	 * Delete the all the attachments from the DB and the file according to the post's id or attach id(optional)
 	 * @param post id