Răsfoiți Sursa

Merge with 1.9.x

Julio Montoya 12 ani în urmă
părinte
comite
26a1c88aa4
36 a modificat fișierele cu 2405 adăugiri și 1161 ștergeri
  1. 68 44
      main/admin/add_users_to_session.php
  2. 88 0
      main/admin/change_user_session.php
  3. 78 113
      main/admin/resume_session.php
  4. 3 1
      main/admin/session_course_user.php
  5. 61 73
      main/admin/session_course_user_list.php
  6. 1 1
      main/admin/user_move_stats.php
  7. 1 1
      main/course_info/legal.php
  8. 2 2
      main/css/base.css
  9. 482 261
      main/css/bootstrap-responsive.css
  10. 377 169
      main/css/bootstrap.css
  11. 34 4
      main/document/create_audio.php
  12. 16 0
      main/document/save_pixlr.php
  13. 51 22
      main/inc/lib/course.lib.php
  14. 8 12
      main/inc/lib/document.lib.php
  15. 368 166
      main/inc/lib/javascript/bootstrap/bootstrap.js
  16. 16 2
      main/inc/lib/jpegcam/webcam_receiver.php
  17. 6 0
      main/inc/lib/mail.lib.inc.php
  18. 12 7
      main/inc/lib/main_api.lib.php
  19. 15 33
      main/inc/lib/message.lib.php
  20. 5 0
      main/inc/lib/nanogong/receiver.php
  21. 47 20
      main/inc/lib/notification.lib.php
  22. 13 15
      main/inc/lib/online.inc.php
  23. 318 29
      main/inc/lib/sessionmanager.lib.php
  24. 13 0
      main/inc/lib/svg-edit/extensions/filesave.php
  25. 33 33
      main/inc/lib/usermanager.lib.php
  26. 6 2
      main/inc/lib/userportal.lib.php
  27. 13 0
      main/inc/lib/wami-recorder/record_document.php
  28. 12 11
      main/inc/local.inc.php
  29. 5 1
      main/install/db_main.sql
  30. 2 1
      main/install/db_stats.sql
  31. 2 1
      main/install/install_db.inc.php
  32. 47 0
      main/install/migrate-db-1.9.0-1.10.0-pre.sql
  33. 115 0
      main/install/update-db-1.9.0-1.10.0.inc.php
  34. 2 1
      main/messages/new_message.php
  35. 3 26
      main/user/subscribe_user.php
  36. 82 110
      main/user/user.php

+ 68 - 44
main/admin/add_users_to_session.php

@@ -30,8 +30,6 @@ $interbreadcrumb[] = array('url' => 'session_list.php','name' => get_lang('Sessi
 $interbreadcrumb[] = array('url' => "resume_session.php?id_session=".$id_session,"name" => get_lang('SessionOverview'));
 
 // Database Table Definitions
-$tbl_session						= Database::get_main_table(TABLE_MAIN_SESSION);
-$tbl_course							= Database::get_main_table(TABLE_MAIN_COURSE);
 $tbl_user							= Database::get_main_table(TABLE_MAIN_USER);
 $tbl_session_rel_user				= Database::get_main_table(TABLE_MAIN_SESSION_USER);
 
@@ -44,9 +42,9 @@ if(isset($_REQUEST['add_type']) && $_REQUEST['add_type']!=''){
 	$add_type = Security::remove_XSS($_REQUEST['add_type']);
 }
 
-//checking for extra field with filter on
+//Checking for extra field with filter on
 
-$extra_field_list= UserManager::get_extra_fields();
+$extra_field_list = UserManager::get_extra_fields();
 $new_field_list = array();
 if (is_array($extra_field_list)) {
 	foreach ($extra_field_list as $extra_field) {
@@ -101,7 +99,7 @@ function search_users($needle, $type) {
                 // search users where username or firstname or lastname begins likes $needle
                 $sql = 'SELECT user.user_id, username, lastname, firstname FROM '.$tbl_user.' user
                         WHERE (username LIKE "'.$needle.'%" OR firstname LIKE "'.$needle.'%"
-                            OR lastname LIKE "'.$needle.'%") AND user.status<>6 AND user.status<>'.DRH.''.
+                            OR lastname LIKE "'.$needle.'%") AND user.status <> 6 AND user.status<>'.DRH.' '.$cond_user_id.' '.
                             $order_clause.
                             ' LIMIT 11';
                 break;
@@ -165,7 +163,6 @@ function search_users($needle, $type) {
 	            	$return .= '...<br />';
 	            }
 			}
-
 			$xajax_response -> addAssign('ajax_list_users_single','innerHTML',api_utf8_encode($return));
 		} else {
 			global $nosessionUsersList;
@@ -181,11 +178,11 @@ function search_users($needle, $type) {
 	return $xajax_response;
 }
 
-$xajax -> processRequests();
+$xajax->processRequests();
 
 $htmlHeadXtra[] = $xajax->getJavascript('../inc/lib/xajax/');
 $htmlHeadXtra[] = '
-<script type="text/javascript">
+<script>
 function add_user_to_session (code, content) {
 	document.getElementById("user_to_add").value = "";
 	document.getElementById("ajax_list_users_single").innerHTML = "";
@@ -212,9 +209,9 @@ function remove_item(origin) {
 }
 
 function validate_filter() {
-		document.formulaire.add_type.value = \''.$add_type.'\';
-		document.formulaire.form_sent.value=0;
-		document.formulaire.submit();
+    document.formulaire.add_type.value = \''.$add_type.'\';
+    document.formulaire.form_sent.value=0;
+    document.formulaire.submit();
 }
 
 function checked_in_no_session(checked) {
@@ -235,17 +232,17 @@ function change_select(val) {
 $form_sent=0;
 $errorMsg=$firstLetterUser=$firstLetterSession='';
 $UserList=$SessionList=array();
-$sessions=array();
-$noPHP_SELF=true;
+$sessions = array();
+$noPHP_SELF = true;
 
-if($_POST['form_sent']) {
+if ($_POST['form_sent']) {
     $form_sent             = $_POST['form_sent'];
     $firstLetterUser       = $_POST['firstLetterUser'];
     $firstLetterSession    = $_POST['firstLetterSession'];
     $UserList              = $_POST['sessionUsersList'];
 
     if (!is_array($UserList)) {
-	$UserList=array();
+        $UserList=array();
     }
 
     if ($form_sent == 1) {
@@ -271,7 +268,11 @@ if ($ajax_search) {
             INNER JOIN $tbl_session_rel_user
                 ON $tbl_session_rel_user.id_user = u.user_id AND $tbl_session_rel_user.relation_type<>".SESSION_RELATION_TYPE_RRHH."
                 AND $tbl_session_rel_user.id_session = ".intval($id_session)."
-                WHERE u.status<>".DRH." AND u.status<>6 $order_clause";
+                WHERE u.status<>".DRH." AND 
+                    u.status<>6 AND
+                    $tbl_session_rel_user.moved_to = 0 AND
+                    $tbl_session_rel_user.moved_status <> ".SessionManager::SESSION_CHANGE_USER_REASON_ENROLLMENT_ANNULATION."                        
+                $order_clause";
 
     if ($_configuration['multiple_access_urls']) {
         $tbl_user_rel_access_url= Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
@@ -283,7 +284,11 @@ if ($ajax_search) {
                 ON $tbl_session_rel_user.id_user = u.user_id AND $tbl_session_rel_user.relation_type<>".SESSION_RELATION_TYPE_RRHH."
                 AND $tbl_session_rel_user.id_session = ".intval($id_session)."
                 INNER JOIN $tbl_user_rel_access_url url_user ON (url_user.user_id=u.user_id)
-                WHERE access_url_id = $access_url_id AND u.status<>".DRH." AND u.status<>6
+                WHERE   access_url_id = $access_url_id AND 
+                        u.status<>".DRH." AND 
+                        u.status<>6 AND 
+                        $tbl_session_rel_user.moved_to = 0 AND
+                        $tbl_session_rel_user.moved_status <> ".SessionManager::SESSION_CHANGE_USER_REASON_ENROLLMENT_ANNULATION."
                 $order_clause";
         }
     }
@@ -298,7 +303,7 @@ if ($ajax_search) {
     $use_extra_fields = false;
     if (is_array($extra_field_list)) {
         if (is_array($new_field_list) && count($new_field_list)>0 ) {
-            $result_list=array();
+            $result_list = array();
             foreach ($new_field_list as $new_field) {
                 $varname = 'field_'.$new_field['variable'];
                 if (UserManager::is_extra_field_available($new_field['variable'])) {
@@ -345,18 +350,26 @@ if ($ajax_search) {
         $sql = "SELECT  user_id, lastname, firstname, username, id_session
                FROM $tbl_user u
                     LEFT JOIN $tbl_session_rel_user
-                    ON $tbl_session_rel_user.id_user = u.user_id AND $tbl_session_rel_user.id_session = '$id_session' AND $tbl_session_rel_user.relation_type<>".SESSION_RELATION_TYPE_RRHH."
-                    $where_filter AND u.status<>".DRH." AND u.status<>6
+                    ON  $tbl_session_rel_user.id_user = u.user_id AND 
+                        $tbl_session_rel_user.id_session = '$id_session' AND 
+                        $tbl_session_rel_user.relation_type<>".SESSION_RELATION_TYPE_RRHH."
+                    $where_filter AND 
+                    u.status<>".DRH." AND 
+                    u.status<>6                    
                     $order_clause";
 
     } else {
         $sql = "SELECT  user_id, lastname, firstname, username, id_session
                 FROM $tbl_user u
                 LEFT JOIN $tbl_session_rel_user
-                ON $tbl_session_rel_user.id_user = u.user_id AND $tbl_session_rel_user.id_session = '$id_session' AND $tbl_session_rel_user.relation_type<>".SESSION_RELATION_TYPE_RRHH."
-                WHERE u.status<>".DRH." AND u.status<>6
+                ON  $tbl_session_rel_user.id_user = u.user_id AND 
+                    $tbl_session_rel_user.id_session = '$id_session' AND 
+                    $tbl_session_rel_user.relation_type<>".SESSION_RELATION_TYPE_RRHH."
+                WHERE   u.status<>".DRH." AND 
+                        u.status<>6                         
                 $order_clause";
     }
+    
     if ($_configuration['multiple_access_urls']) {
         $tbl_user_rel_access_url= Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
         $access_url_id = api_get_current_access_url_id();
@@ -364,30 +377,40 @@ if ($ajax_search) {
             $sql = "SELECT  u.user_id, lastname, firstname, username, id_session
                     FROM $tbl_user u
                     LEFT JOIN $tbl_session_rel_user
-                        ON $tbl_session_rel_user.id_user = u.user_id AND $tbl_session_rel_user.id_session = '$id_session' AND $tbl_session_rel_user.relation_type<>".SESSION_RELATION_TYPE_RRHH."
-                    INNER JOIN $tbl_user_rel_access_url url_user ON (url_user.user_id=u.user_id)
-                    WHERE access_url_id = $access_url_id  $where_filter AND u.status<>".DRH." AND u.status<>6 
+                        ON  $tbl_session_rel_user.id_user = u.user_id AND 
+                            $tbl_session_rel_user.id_session = '$id_session' AND 
+                            $tbl_session_rel_user.relation_type<>".SESSION_RELATION_TYPE_RRHH."
+                        INNER JOIN $tbl_user_rel_access_url url_user ON (url_user.user_id=u.user_id)
+                    WHERE   access_url_id = $access_url_id  $where_filter AND 
+                            u.status<>".DRH." AND 
+                            u.status<>6                            
                     $order_clause";
         }
     }
 
     $result   = Database::query($sql);
     $users    = Database::store_result($result,'ASSOC');
-
+    
     foreach ($users as $uid => $user) {
         if ($user['id_session'] != $id_session) {
             $nosessionUsersList[$user['user_id']] = array('fn'=>$user['firstname'],'ln'=>$user['lastname'],'un'=>$user['username']) ;
             unset($users[$uid]);
-	}
+        }
     }
     unset($users); //clean to free memory
 
-    //filling the correct users in list
-    $sql="SELECT  user_id, lastname, firstname, username, id_session
+    //Filling the correct users in list
+    $sql = "SELECT  user_id, lastname, firstname, username, id_session
           FROM $tbl_user u
           LEFT JOIN $tbl_session_rel_user
-          ON $tbl_session_rel_user.id_user = u.user_id AND $tbl_session_rel_user.id_session = '$id_session' AND $tbl_session_rel_user.relation_type<>".SESSION_RELATION_TYPE_RRHH."
-          WHERE u.status<>".DRH." AND u.status<>6 $order_clause";
+          ON    $tbl_session_rel_user.id_user = u.user_id AND 
+                $tbl_session_rel_user.id_session = '$id_session' AND 
+                $tbl_session_rel_user.relation_type<>".SESSION_RELATION_TYPE_RRHH."
+          WHERE u.status <> ".DRH." AND 
+                u.status <> 6 AND 
+                $tbl_session_rel_user.moved_to = 0 AND
+                $tbl_session_rel_user.moved_status <> ".SessionManager::SESSION_CHANGE_USER_REASON_ENROLLMENT_ANNULATION." 
+          $order_clause";
 
     if ($_configuration['multiple_access_urls']) {
         $tbl_user_rel_access_url= Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
@@ -398,12 +421,18 @@ if ($ajax_search) {
                 LEFT JOIN $tbl_session_rel_user
                     ON $tbl_session_rel_user.id_user = u.user_id AND $tbl_session_rel_user.id_session = '$id_session' AND $tbl_session_rel_user.relation_type<>".SESSION_RELATION_TYPE_RRHH."
                 INNER JOIN $tbl_user_rel_access_url url_user ON (url_user.user_id=u.user_id)
-                WHERE access_url_id = $access_url_id AND u.status<>".DRH." AND u.status<>6
+                WHERE   access_url_id = $access_url_id AND 
+                        u.status<>".DRH." AND 
+                        u.status<>6 AND 
+                        $tbl_session_rel_user.moved_to = 0 AND
+                        $tbl_session_rel_user.moved_status <> ".SessionManager::SESSION_CHANGE_USER_REASON_ENROLLMENT_ANNULATION." 
+                                                
                 $order_clause";
         }
     }
-    $result=Database::query($sql);
-    $users=Database::store_result($result,'ASSOC');
+    
+    $result = Database::query($sql);
+    $users = Database::store_result($result,'ASSOC');
     foreach ($users as $uid => $user) {
         if ($user['id_session'] == $id_session) {
             $sessionUsersList[$user['user_id']] = $user;
@@ -416,6 +445,7 @@ if ($ajax_search) {
     unset($users); //clean to free memory
 }
 
+
 if ($add_type == 'multiple') {
 	$link_add_type_unique = '<a href="'.api_get_self().'?id_session='.$id_session.'&add='.Security::remove_XSS($_GET['add']).'&add_type=unique">'.Display::return_icon('single.gif').get_lang('SessionAddTypeUnique').'</a>';
 	$link_add_type_multiple = Display::return_icon('multiple.gif').get_lang('SessionAddTypeMultiple');
@@ -428,6 +458,7 @@ if ($add_type == 'multiple') {
 <div class="actions">
 	<?php echo $link_add_type_unique ?>&nbsp;|&nbsp;<?php echo $link_add_type_multiple ?>&nbsp;|&nbsp;<?php echo $link_add_group; ?>
 </div>
+
 <form name="formulaire" method="post" action="<?php echo api_get_self(); ?>?page=<?php echo Security::remove_XSS($_GET['page']); ?>&id_session=<?php echo $id_session; ?><?php if(!empty($_GET['add'])) echo '&add=true' ; ?>" style="margin:0px;" <?php if($ajax_search){echo ' onsubmit="valide();"';}?>>
 <?php echo '<legend>'.$tool_name.' ('.$session_info['name'].') </legend>'; ?>
 <?php
@@ -562,7 +593,6 @@ unset($sessionUsersList);
         } else {
             //@todo see that the call to "valide()" doesn't duplicate the onsubmit of the form (necessary to avoid delete on "enter" key pressed)
 			echo '<button class="save" type="button" value="" onclick="valide()" >'.get_lang('SubscribeUsersToSession').'</button>';
-
         }
 		?>
 	</td>
@@ -570,11 +600,10 @@ unset($sessionUsersList);
 </table>
 </form>
 
-<script type="text/javascript">
+<script>
 <!--
 function moveItem(origin , destination){
-
-	for(var i = 0 ; i<origin.options.length ; i++) {
+	for (var i = 0 ; i<origin.options.length ; i++) {
 		if(origin.options[i].selected) {
 			destination.options[destination.length] = new Option(origin.options[i].text,origin.options[i].value);
 			origin.options[i]=null;
@@ -587,7 +616,6 @@ function moveItem(origin , destination){
 }
 
 function sortOptions(options) {
-
 	newOptions = new Array();
 	for (i = 0 ; i<options.length ; i++)
 		newOptions[i] = options[i];
@@ -618,9 +646,7 @@ function valide(){
 
 
 function loadUsersInSelect(select){
-
 	var xhr_object = null;
-
 	if(window.XMLHttpRequest) // Firefox
 		xhr_object = new XMLHttpRequest();
 	else if(window.ActiveXObject) // Internet Explorer
@@ -633,7 +659,6 @@ function loadUsersInSelect(select){
 
 	xhr_object.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
 
-
 	nosessionUsers = makepost(document.getElementById('origin_users'));
 	sessionUsers = makepost(document.getElementById('destination_users'));
 	nosessionClasses = makepost(document.getElementById('origin_classes'));
@@ -648,8 +673,7 @@ function loadUsersInSelect(select){
 	}
 }
 
-function makepost(select){
-
+function makepost(select) {
 	var options = select.options;
 	var ret = "";
 	for (i = 0 ; i<options.length ; i++)

+ 88 - 0
main/admin/change_user_session.php

@@ -0,0 +1,88 @@
+<?php
+
+/* For licensing terms, see /license.txt */
+$language_file = 'admin';
+$cidReset = true;
+require_once '../inc/global.inc.php';
+
+$user_id = intval($_REQUEST['user_id']);
+$session_id = intval($_REQUEST['id_session']);
+
+if (empty($user_id) && empty($session_id)) {
+    api_not_allowed(true);
+}
+
+SessionManager::protect_session_edit($session_id);
+
+if (api_is_platform_admin()) {
+    $sessions = SessionManager::get_sessions_admin();
+} else {
+    $sessions = SessionManager::get_sessions_by_coach(api_get_session_id());
+}
+
+$message = null;
+$session_to_select = array();
+foreach ($sessions as $session) {
+    if ($session_id != $session['id']) {
+        $session_to_select[$session['id']] = $session['name'];
+    }
+}
+
+$session_name = api_get_session_name($session_id);
+$user_info = api_get_user_info($user_id);
+
+//Check if user was already moved
+$user_status = SessionManager::get_user_status_in_session($session_id, $user_id);
+if (isset($user_status['moved_to']) && $user_status['moved_to'] != 0 || $user_status['moved_status'] == SessionManager::SESSION_CHANGE_USER_REASON_ENROLLMENT_ANNULATION) {
+    api_not_allowed(true);
+}
+
+$form = new FormValidator('change_user_session', 'post', api_get_self());
+$form->addElement('hidden', 'user_id', $user_id);
+$form->addElement('hidden', 'id_session', $session_id);
+$form->addElement('header', get_lang('ChangeUserSession'));
+$form->addElement('label', get_lang('User'), '<b>'.$user_info['complete_name'].'</b>');
+$form->addElement('label', get_lang('CurrentSession'), $session_name);
+
+$form->addElement('select', 'reason_id', get_lang('Action'), SessionManager::get_session_change_user_reasons(), array('id' => 'reason_id'));
+$form->addElement('select', 'new_session_id', get_lang('SessionDestination'), $session_to_select, array('id' => 'new_session_id'));
+
+$form->addElement('button', 'submit', get_lang('Change'));
+
+$content = $form->return_form();
+
+if ($form->validate()) {
+    $values = $form->getSubmitValues();
+    $result = SessionManager::change_user_session($values['user_id'], $values['id_session'], $values['new_session_id'], $values['reason_id']);
+    if ($result) {
+        $message = Display::return_message(get_lang('UserSessionWasChanged'));
+    }
+    header('Location: resume_session.php?id_session='.$values['id_session']);
+    exit;
+}
+
+$interbreadcrumb[] = array('url' => 'index.php', 'name' => get_lang('PlatformAdmin'));
+$interbreadcrumb[] = array('url' => 'session_list.php','name' => get_lang('SessionList'));
+$interbreadcrumb[] = array('url' => 'resume_session.php?id_session='.$session_id,'name' => get_lang('SessionOverview'));
+$interbreadcrumb[] = array('url' => '#','name' => get_lang('ChangeUserSession'));
+
+$htmlHeadXtra[] = '<script>
+
+$(document).ready(function() {
+    $("#reason_id").change(function() {
+        value = $(this).val();
+        if (value == "'.SessionManager::SESSION_CHANGE_USER_REASON_ENROLLMENT_ANNULATION.'") {
+            $("#new_session_id").parent().parent().hide();
+        } else {
+            $("#new_session_id").parent().parent().show();
+        }
+    });
+});
+
+</script>';
+
+$tpl = new Template();
+
+$tpl->assign('message', $message);
+$tpl->assign('content', $content);
+$tpl->display_one_col_template();

+ 78 - 113
main/admin/resume_session.php

@@ -23,42 +23,18 @@ $tool_name = get_lang('SessionOverview');
 $interbreadcrumb[] = array('url' => 'index.php','name' => get_lang('PlatformAdmin'));
 $interbreadcrumb[] = array('url' => 'session_list.php','name' => get_lang('SessionList'));
 
-// Database Table Definitions
-$tbl_session						= Database::get_main_table(TABLE_MAIN_SESSION);
-$tbl_session_rel_class				= Database::get_main_table(TABLE_MAIN_SESSION_CLASS);
-$tbl_session_rel_course				= Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
-$tbl_course							= Database::get_main_table(TABLE_MAIN_COURSE);
-$tbl_user							= Database::get_main_table(TABLE_MAIN_USER);
-$tbl_session_rel_user				= Database::get_main_table(TABLE_MAIN_SESSION_USER);
-$tbl_session_rel_course_rel_user	= Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
-$tbl_session_category				= Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
-
-$table_access_url_user              = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
-
-$sql = 'SELECT name, nbr_courses, nbr_users, nbr_classes, DATE_FORMAT(date_start,"%d-%m-%Y") as date_start, DATE_FORMAT(date_end,"%d-%m-%Y") as date_end, lastname, firstname, username, session_admin_id, nb_days_access_before_beginning, nb_days_access_after_end, session_category_id, visibility
-		FROM '.$tbl_session.' LEFT JOIN '.$tbl_user.' ON id_coach = user_id
-		WHERE '.$tbl_session.'.id='.$id_session;
-
-$rs      = Database::query($sql);
-$session = Database::store_result($rs);
-$session = $session[0];
-
-$sql = 'SELECT name FROM  '.$tbl_session_category.' WHERE id = "'.intval($session['session_category_id']).'"';
-$rs = Database::query($sql);
-$session_category = '';
-
-if (Database::num_rows($rs)>0) {
-	$rows_session_category = Database::store_result($rs);
-	$rows_session_category = $rows_session_category[0];
-	$session_category = $rows_session_category['name'];
+$session = SessionManager::get_session_info($id_session);
+$session_cat_info = SessionManager::get_session_category($session['session_category_id']);
+$session_category = null;
+if (!empty($session_cat_info)) {
+    $session_category = $session_cat_info['name'];
 }
 
 $action = $_GET['action'];
 
 $url_id = api_get_current_access_url_id();     
 
-
-switch($action) {
+switch ($action) {
     case 'add_user_to_url':        
         $user_id = $_REQUEST['user_id'];
         $result = UrlManager::add_user_to_url($user_id, $url_id);
@@ -68,39 +44,11 @@ switch($action) {
         }
         break;
     case 'delete':
-        $idChecked = $_GET['idChecked'];
-        if(is_array($idChecked)) {
-            $my_temp = array();
-            foreach ($idChecked as $id){
-                $my_temp[]= Database::escape_string($id);// forcing the escape_string
-            }
-            $idChecked = $my_temp;
-
-            $idChecked="'".implode("','",$idChecked)."'";
-
-            Database::query("DELETE FROM $tbl_session_rel_course WHERE id_session='$id_session' AND course_code IN($idChecked)");
-            $nbr_affected_rows=Database::affected_rows();
-
-            Database::query("DELETE FROM $tbl_session_rel_course_rel_user WHERE id_session='$id_session' AND course_code IN($idChecked)");
-            Database::query("UPDATE $tbl_session SET nbr_courses=nbr_courses-$nbr_affected_rows WHERE id='$id_session'");
+        if (isset($_GET['course_code_to_delete'])) {
+            SessionManager::delete_course_in_session($id_session, $_GET['course_code_to_delete']);
         }
-
-        if(!empty($_GET['class'])){
-            Database::query("DELETE FROM $tbl_session_rel_class WHERE session_id='$id_session' AND class_id=".Database::escape_string($_GET['class']));
-            $nbr_affected_rows=Database::affected_rows();
-            Database::query("UPDATE $tbl_session SET nbr_classes=nbr_classes-$nbr_affected_rows WHERE id='$id_session'");
-        }
-
         if (!empty($_GET['user'])) {
-            Database::query("DELETE FROM $tbl_session_rel_user WHERE relation_type<>".SESSION_RELATION_TYPE_RRHH." AND id_session='$id_session' AND id_user=".intval($_GET['user']));
-            $nbr_affected_rows=Database::affected_rows();
-
-            Database::query("UPDATE $tbl_session SET nbr_users=nbr_users-$nbr_affected_rows WHERE id='$id_session'");
-
-            Database::query("DELETE FROM $tbl_session_rel_course_rel_user WHERE id_session='$id_session' AND id_user=".intval($_GET['user']));
-            $nbr_affected_rows=Database::affected_rows();
-
-            Database::query("UPDATE $tbl_session_rel_course SET nbr_users=nbr_users-$nbr_affected_rows WHERE id_session='$id_session'");
+            SessionManager::unsubscribe_user_from_session($id_session, $_GET['user']);            
         }
         break;
 }
@@ -177,13 +125,25 @@ echo Display::page_subheader(get_lang('GeneralProperties').$url);
 		<?php echo api_ucfirst(get_lang('SessionVisibility')) ?> :
 	</td>
 	<td>
-		<?php if ($session['visibility']==1) echo get_lang('ReadOnly'); elseif($session['visibility']==2) echo get_lang('Visible');elseif($session['visibility']==3) echo api_ucfirst(get_lang('Invisible'))  ?>
+		<?php        
+        if (isset($session['date_end']) && $session['date_end'] != '00-00-0000') {
+            if ($session['visibility'] == 1) 
+                echo get_lang('ReadOnly'); 
+             elseif($session['visibility'] == 2) 
+                 echo get_lang('Visible');
+             elseif($session['visibility'] == 3) 
+                echo api_ucfirst(get_lang('Invisible'))  ;
+        } else {
+            //By default course sessions can be access normally see function api_get_session_visibility() when no date_end is proposed            
+            echo get_lang('Visible'); 
+        }
+        ?>
 	</td>
 </tr>
 
 <?php 
 
-$multiple_url_is_on = api_get_multiple_access_url();
+$multiple_url_is_on = api_is_multiple_url_enabled();
 
 if ($multiple_url_is_on) {
     echo '<tr><td>';   
@@ -220,60 +180,26 @@ if ($session['nbr_courses'] == 0){
 	echo '<tr>
 			<td colspan="4">'.get_lang('NoCoursesForThisSession').'</td>
 		</tr>';
-} else {
-	// select the courses
-	$sql = "SELECT code,title,visual_code, nbr_users
-			FROM $tbl_course,$tbl_session_rel_course
-			WHERE course_code = code
-			AND	id_session='$id_session'
-			ORDER BY title";
-	$result=Database::query($sql);
-	$courses=Database::store_result($result);
+} else {    
+    $courses = SessionManager::get_course_list_by_session_id($id_session);	
 	foreach ($courses as $course) {
-		//select the number of users
-
-		$sql = " SELECT count(*) FROM $tbl_session_rel_user sru, $tbl_session_rel_course_rel_user srcru
-				WHERE srcru.id_user = sru.id_user AND srcru.id_session = sru.id_session AND srcru.course_code = '".Database::escape_string($course['code'])."'
-				AND sru.relation_type<>".SESSION_RELATION_TYPE_RRHH." AND srcru.id_session = '".intval($id_session)."'";
-
-		$rs = Database::query($sql);
-		$course['nbr_users'] = Database::result($rs,0,0);
-
-		// Get coachs of the courses in session
-
-		$sql = "SELECT user.lastname,user.firstname,user.username FROM $tbl_session_rel_course_rel_user session_rcru, $tbl_user user
-				WHERE session_rcru.id_user = user.user_id AND session_rcru.id_session = '".intval($id_session)."' AND session_rcru.course_code ='".Database::escape_string($course['code'])."' AND session_rcru.status=2";
-		$rs = Database::query($sql);
-
-		$coachs = array();
-		if (Database::num_rows($rs) > 0) {
-			while($info_coach = Database::fetch_array($rs)) {
-				$coachs[] = api_get_person_name($info_coach['firstname'], $info_coach['lastname']).' ('.$info_coach['username'].')';
-			}
-		} else {
-			$coach = get_lang('None');
-		}
-
-		if (count($coachs) > 0) {
-			$coach = implode('<br />',$coachs);
-		} else {
-			$coach = get_lang('None');
-		}
+        $count_users = SessionManager::get_count_users_in_course_session($course['code'], $id_session);
+        $coaches = SessionManager::get_session_course_coaches_to_string($course['code'], $id_session);
 
 		$orig_param = '&origin=resume_session';
 		//hide_course_breadcrumb the parameter has been added to hide the name of the course, that appeared in the default $interbreadcrumb
 		echo '
 		<tr>
 			<td>'.Display::url($course['title'].' ('.$course['visual_code'].')', api_get_path(WEB_COURSE_PATH).$course['code'].'/?id_session='.$id_session),'</td>
-			<td>'.$coach.'</td>
-			<td>'.$course['nbr_users'].'</td>
+			<td>'.$coaches.'</td>
+			<td>'.$count_users.'</td>
 			<td>
                 <a href="'.api_get_path(WEB_COURSE_PATH).$course['code'].'/?id_session='.$id_session.'">'.Display::return_icon('course_home.gif', get_lang('Course')).'</a>   
                 <a href="session_course_user_list.php?id_session='.$id_session.'&course_code='.$course['code'].'">'.Display::return_icon('user.png', get_lang('Edit'), '', ICON_SIZE_SMALL).'</a>
                 <a href="'.api_get_path(WEB_CODE_PATH).'/user/user_import.php?action=import&cidReq='.$course['code'].'&id_session='.$id_session.'">'.Display::return_icon('import_csv.png', get_lang('ImportUsersToACourse'), null, ICON_SIZE_SMALL).'</a>   
 				<a href="../tracking/courseLog.php?id_session='.$id_session.'&cidReq='.$course['code'].$orig_param.'&hide_course_breadcrumb=1">'.Display::return_icon('statistics.gif', get_lang('Tracking')).'</a>&nbsp;                
 				<a href="session_course_edit.php?id_session='.$id_session.'&page=resume_session.php&course_code='.$course['code'].''.$orig_param.'">'.Display::return_icon('edit.png', get_lang('Edit'), '', ICON_SIZE_SMALL).'</a>
-				<a href="'.api_get_self().'?id_session='.$id_session.'&action=delete&idChecked[]='.$course['code'].'" onclick="javascript:if(!confirm(\''.get_lang('ConfirmYourChoice').'\')) return false;">'.Display::return_icon('delete.png', get_lang('Delete')).'</a>
+				<a href="'.api_get_self().'?id_session='.$id_session.'&action=delete&course_code_to_delete='.$course['code'].'" onclick="javascript:if(!confirm(\''.get_lang('ConfirmYourChoice').'\')) return false;">'.Display::return_icon('delete.png', get_lang('Delete')).'</a>
 			</td>
 		</tr>';
 	}
@@ -297,19 +223,28 @@ echo Display::page_subheader(get_lang('UserList').$url);
         <th>
             <?php echo get_lang('User'); ?>
         </th>
+        <th>
+            <?php echo get_lang('Information'); ?>
+        </th>
+        <th>
+            <?php echo get_lang('MovedAt'); ?>
+        </th>
+        <th>
+            <?php echo get_lang('Destination'); ?>
+        </th>
         <th>
             <?php echo get_lang('Actions'); ?>
         </th>
     </tr>
 <?php
 
-if ($session['nbr_users']==0) {
+if ($session['nbr_users'] == 0) {
 	echo '<tr>
 			<td colspan="2">'.get_lang('NoUsersForThisSession').'</td>
 		</tr>';
 } else {    
-	$order_clause = api_sort_by_first_name() ? ' ORDER BY firstname, lastname' : ' ORDER BY lastname, firstname';
-    
+	/*$order_clause = api_sort_by_first_name() ? ' ORDER BY firstname, lastname' : ' ORDER BY lastname, firstname';
+     *     
     if ($multiple_url_is_on) {           
         $sql = "SELECT u.user_id, lastname, firstname, username, access_url_id
                 FROM $tbl_user u
@@ -327,13 +262,40 @@ if ($session['nbr_users']==0) {
     }
 
 	$result = Database::query($sql);
-	$users  = Database::store_result($result);
+	$users  = Database::store_result($result);*/
 	$orig_param = '&origin=resume_session&id_session='.$id_session; // change breadcrumb in destination page
-	foreach ($users as $user){
+    
+    $users = SessionManager::get_users_by_session($id_session, 0);    
+    $reasons = SessionManager::get_session_change_user_reasons();
+    
+    if (!empty($users))
+	foreach ($users as $user) {        
         $user_link = '';
         if (!empty($user['user_id'])) {
             $user_link = '<a href="'.api_get_path(WEB_CODE_PATH).'admin/user_information.php?user_id='.intval($user['user_id']).'">'.api_htmlentities(api_get_person_name($user['firstname'], $user['lastname']),ENT_QUOTES,$charset).' ('.$user['username'].')</a>';
         }
+        $information = null;
+        $origin_destination = null;
+        
+        $row_class = null;
+        $moved_date = '-';
+        
+        $moved_link =  '<a href="change_user_session.php?user_id='.$user['user_id'].'&id_session='.$id_session.'">'.Display::return_icon('move.png', get_lang('ChangeUserSession')).'</a>&nbsp;';
+        
+        if (isset($user['moved_to']) && !empty($user['moved_to']) || $user['moved_status'] == SessionManager::SESSION_CHANGE_USER_REASON_ENROLLMENT_ANNULATION) {
+            $information = $reasons[$user['moved_status']];
+            
+            $moved_date = isset($user['moved_at']) && $user['moved_at'] != '0000-00-00 00:00:00' ? api_get_local_time($user['moved_at']) : '-';                        
+            $session_info = SessionManager::fetch($user['moved_to']);
+            
+            if ($session_info) {
+                $url = api_get_path(WEB_CODE_PATH).'admin/resume_session.php?id_session='.$session_info['id'];
+                $origin_destination = Display::url($session_info['name'], $url);
+            }
+            $row_class = 'row_odd';
+            
+            $moved_link =  Display::return_icon('move_na.png', get_lang('ChangeUserSession')).'&nbsp;';
+        }
         
         $link_to_add_user_in_url = '';
         
@@ -344,13 +306,17 @@ if ($session['nbr_users']==0) {
                 $link_to_add_user_in_url = '<a href="resume_session.php?action=add_user_to_url&id_session='.$id_session.'&user_id='.$user['user_id'].'">'.$add.'</a>';
             }                
         }
-		echo '<tr>
-                <td width="90%">
+		echo '<tr class="'.$row_class.'">
+                <td width="50%">
                     '.$user_link.'
                 </td>
-                <td>               
+                <td>'.$information.'</td>
+                <td>'.$moved_date.'</td>                    
+                <td>'.$origin_destination.'</td>
+                <td>
                     <a href="../mySpace/myStudents.php?student='.$user['user_id'].''.$orig_param.'">'.Display::return_icon('statistics.gif', get_lang('Reporting')).'</a>&nbsp;
                     <a href="session_course_user.php?id_user='.$user['user_id'].'&id_session='.$id_session.'">'.Display::return_icon('course.gif', get_lang('BlockCoursesForThisUser')).'</a>&nbsp;
+                    '.$moved_link.'
                     <a href="'.api_get_self().'?id_session='.$id_session.'&action=delete&user='.$user['user_id'].'" onclick="javascript:if(!confirm(\''.get_lang('ConfirmYourChoice').'\')) return false;">'.Display::return_icon('delete.png', get_lang('Delete')).'</a>
                     '.$link_to_add_user_in_url.'
                 </td>
@@ -360,5 +326,4 @@ if ($session['nbr_users']==0) {
 ?>
 </table>
 <?php
-// footer
 Display :: display_footer();

+ 3 - 1
main/admin/session_course_user.php

@@ -93,7 +93,8 @@ if ($_POST['formSent']) {
 			}
 		}
 	}
-	foreach($existingCourses as $existingCourse) {
+    
+	foreach ($existingCourses as $existingCourse) {
 		//$sql_insert_rel_course= "INSERT INTO $tbl_session_rel_course(id_session,course_code, id_coach) VALUES('$id_session','$enreg_course','$id_coach')";
 		if(!in_array($existingCourse['code'], $CourseList)){
 			$existingCourse = Database::escape_string($existingCourse['code']);
@@ -121,6 +122,7 @@ if (!empty($_GET['msg'])) {
 // the form header
 $session_info = SessionManager::fetch($id_session);
 $user_info = api_get_user_info($id_user);
+
 echo '<legend>'.$tool_name.': '.$session_info['name'].' - '.$user_info['complete_name'].'</legend>';
 
 $nosessionCourses = $sessionCourses = array();

+ 61 - 73
main/admin/session_course_user_list.php

@@ -11,24 +11,24 @@ $cidReset = true;
 
 require_once '../inc/global.inc.php';
 
-$tbl_user                           = Database::get_main_table(TABLE_MAIN_USER);
-$tbl_course                         = Database::get_main_table(TABLE_MAIN_COURSE);
-$tbl_session                        = Database::get_main_table(TABLE_MAIN_SESSION);
-$tbl_session_rel_course             = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
-$tbl_session_rel_user               = Database::get_main_table(TABLE_MAIN_SESSION_USER);
-$tbl_session_rel_course_rel_user    = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
-
 $id_session = intval($_GET['id_session']);
+
 SessionManager::protect_session_edit($id_session);
 
-if (empty($id_session )) {
-    api_not_allowed();
+if (empty($id_session)) {
+    api_not_allowed(true);
+}
+
+$course_info = api_get_course_info($_GET['course_code']);
+
+if (empty($course_info)) {
+    api_not_allowed(true);
 }
 
-$course_code    = Database::escape_string(trim($_GET['course_code']));
+$course_code    = $course_info['code'];
 $page           = intval($_GET['page']);
 $action         = $_REQUEST['action'];
-$default_sort = api_sort_by_first_name() ? 'firstname':'lastname';
+$default_sort   = api_sort_by_first_name() ? 'firstname':'lastname';
 $sort           = in_array($_GET['sort'], array('lastname','firstname','username')) ? $_GET['sort'] : $default_sort;
 $idChecked      = (is_array($_GET['idChecked']) ? $_GET['idChecked'] : (is_array($_POST['idChecked']) ? $_POST['idChecked'] : null));
 
@@ -42,32 +42,19 @@ if (is_array($idChecked)) {
 	$idChecked = $my_temp;
 }
 
-$sql = "SELECT s.name, c.title  FROM $tbl_session_rel_course src
-		INNER JOIN $tbl_session s ON s.id = src.id_session
-		INNER JOIN $tbl_course c ON c.code = src.course_code
-		WHERE src.id_session='$id_session' AND src.course_code='".Database::escape_string($course_code)."' ";
-
-$result = Database::query($sql);
+$session_info = SessionManager::fetch($id_session);
+$courses = SessionManager::get_course_list_by_session_id($id_session);
 
-if (!list($session_name,$course_title)=Database::fetch_row($result)) {
+if (!isset($courses[$course_info['real_id']])) {
 	header('Location: session_course_list.php?id_session='.$id_session);
 	exit();
 }
 
-
-switch($action) {
+switch ($action) {
     case 'delete':
-        if (is_array($idChecked) && count($idChecked)>0 ) {
-            array_map('intval', $idChecked);
-            $idChecked = implode(',',$idChecked);
-        }
-        if (!empty($idChecked)) {
-            Database::query("DELETE FROM $tbl_session_rel_course_rel_user WHERE id_session='$id_session' AND course_code='".$course_code."' AND id_user IN($idChecked)");
-            $nbr_affected_rows = Database::affected_rows();
-            Database::query("UPDATE $tbl_session_rel_course SET nbr_users=nbr_users-$nbr_affected_rows WHERE id_session='$id_session' AND course_code='".$course_code."'");
-        }
+        SessionManager::unsubscribe_user_from_course_session($id_session, $idChecked, $course_code);        
         header('Location: '.api_get_self().'?id_session='.$id_session.'&course_code='.urlencode($course_code).'&sort='.$sort);
-        exit();
+        exit;
         break;
     case 'add':
         SessionManager::subscribe_users_to_session_course($idChecked, $id_session, $course_code);
@@ -81,29 +68,30 @@ $limit  = 20;
 $from   = $page * $limit;
 $is_western_name_order = api_is_western_name_order();
 
-//scru.status<>2  scru.course_code='".$course_code."'
+$Users = SessionManager::get_users_in_course_session($course_code, $id_session, $sort, $direction, $from, $limit);
+        
+/*
+
 $sql = "SELECT DISTINCT u.user_id,".($is_western_name_order ? 'u.firstname, u.lastname' : 'u.lastname, u.firstname').", u.username, scru.id_user as is_subscribed
-             FROM $tbl_session_rel_user s INNER JOIN $tbl_user u ON (u.user_id=s.id_user) LEFT JOIN $tbl_session_rel_course_rel_user scru ON (u.user_id=scru.id_user AND  scru.course_code = '".$course_code."' )
-             WHERE s.id_session='$id_session'
+             FROM $tbl_session_rel_user s INNER JOIN $tbl_user u ON (u.user_id=s.id_user) 
+                    LEFT JOIN $tbl_session_rel_course_rel_user scru ON (u.user_id=scru.id_user AND  scru.course_code = '".$course_code."' )
+             WHERE s.id_session='$id_session' 
              ORDER BY $sort $direction LIMIT $from,".($limit+1);
-
+*/
 if ($direction == 'desc') {
     $direction = 'asc';
 } else {
     $direction = 'desc';
 }
 
-$result = Database::query($sql);
-$Users  = Database::store_result($result);
-
 $nbr_results = sizeof($Users);
 
-$tool_name = get_lang('Session').': '.$session_name.' - '.get_lang('Course').': '.$course_title;
+$tool_name = get_lang('Session').': '.$session_info['name'].' - '.get_lang('Course').': '.$course_info['title'];
 
 $interbreadcrumb[] = array("url" => "index.php","name" => get_lang('PlatformAdmin'));
 $interbreadcrumb[] = array("url" => "session_list.php","name" => get_lang('SessionList'));
 $interbreadcrumb[] = array('url' => "resume_session.php?id_session=".$id_session,"name" => get_lang('SessionOverview'));
-//$interbreadcrumb[]=array("url" => "session_course_list.php?id_session=$id_session","name" => get_lang('ListOfCoursesOfSession')." &quot;".api_htmlentities($session_name,ENT_QUOTES,$charset)."&quot;");
+
 
 Display::display_header($tool_name);
 
@@ -122,7 +110,7 @@ if($page) {
 ?>
 |
 <?php
-if($nbr_results > $limit) {
+if ($nbr_results > $limit) {
 ?>
 <a href="<?php echo api_get_self(); ?>?id_session=<?php echo $id_session; ?>&course_code=<?php echo urlencode($course_code); ?>&page=<?php echo $page+1; ?>&sort=<?php echo $sort; ?>"><?php echo get_lang('Next');?></a>
 <?php
@@ -149,38 +137,38 @@ if($nbr_results > $limit) {
 
 <?php
 $i=0;
-
-foreach ($Users as $key=>$enreg) {
-	if ($key == $limit) {
-		break;
-	}
-    ?>
-
-    <tr class="<?php echo $i?'row_odd':'row_even'; ?>">
-        <td><input type="checkbox" name="idChecked[]" value="<?php echo $enreg['user_id']; ?>"></td>
-        <?php if ($is_western_name_order) { ?>
-        <td><?php echo api_htmlentities($enreg['firstname'],ENT_QUOTES,$charset); ?></td>
-        <td><?php echo api_htmlentities($enreg['lastname'],ENT_QUOTES,$charset); ?></td>
-        <?php } else { ?>
-        <td><?php echo api_htmlentities($enreg['lastname'],ENT_QUOTES,$charset); ?></td>
-        <td><?php echo api_htmlentities($enreg['firstname'],ENT_QUOTES,$charset); ?></td>
-        <?php } ?>
-        <td><?php echo api_htmlentities($enreg['username'],ENT_QUOTES,$charset); ?></td>
-        <td>
-        <?php if ($enreg['is_subscribed']) { ?>
-            <a href="<?php echo api_get_self(); ?>?id_session=<?php echo $id_session; ?>&course_code=<?php echo urlencode($course_code); ?>&sort=<?php echo $sort; ?>&action=delete&idChecked[]=<?php echo $enreg['user_id']; ?>" onclick="javascript:if(!confirm('<?php echo get_lang('ConfirmYourChoice'); ?>')) return false;">
-                <?php Display::display_icon('delete.png', get_lang('Delete')); ?>
-            </a>
-        <?php } else  { ?>
-            <a href="<?php echo api_get_self(); ?>?id_session=<?php echo $id_session; ?>&course_code=<?php echo urlencode($course_code); ?>&sort=<?php echo $sort; ?>&action=add&idChecked[]=<?php echo $enreg['user_id']; ?>" onclick="javascript:if(!confirm('<?php echo get_lang('ConfirmYourChoice'); ?>')) return false;">
-                <?php Display::display_icon('add.png', get_lang('Add'), array(), ICON_SIZE_SMALL); ?>
-            </a>
-        <?php }  ?>
-
-        </td>
-    </tr>
-    <?php
-        $i=$i ? 0 : 1;
+if (!empty($Users)) {
+    foreach ($Users as $key=>$enreg) {
+        if ($key == $limit) {
+            break;
+        }
+        ?>
+        <tr class="<?php echo $i?'row_odd':'row_even'; ?>">
+            <td><input type="checkbox" name="idChecked[]" value="<?php echo $enreg['user_id']; ?>"></td>
+            <?php if ($is_western_name_order) { ?>
+            <td><?php echo api_htmlentities($enreg['firstname'],ENT_QUOTES,$charset); ?></td>
+            <td><?php echo api_htmlentities($enreg['lastname'],ENT_QUOTES,$charset); ?></td>
+            <?php } else { ?>
+            <td><?php echo api_htmlentities($enreg['lastname'],ENT_QUOTES,$charset); ?></td>
+            <td><?php echo api_htmlentities($enreg['firstname'],ENT_QUOTES,$charset); ?></td>
+            <?php } ?>
+            <td><?php echo api_htmlentities($enreg['username'],ENT_QUOTES,$charset); ?></td>
+            <td>
+            <?php if ($enreg['is_subscribed']) { ?>
+                <a href="<?php echo api_get_self(); ?>?id_session=<?php echo $id_session; ?>&course_code=<?php echo urlencode($course_code); ?>&sort=<?php echo $sort; ?>&action=delete&idChecked[]=<?php echo $enreg['user_id']; ?>" onclick="javascript:if(!confirm('<?php echo get_lang('ConfirmYourChoice'); ?>')) return false;">
+                    <?php Display::display_icon('delete.png', get_lang('Delete')); ?>
+                </a>
+            <?php } else  { ?>
+                <a href="<?php echo api_get_self(); ?>?id_session=<?php echo $id_session; ?>&course_code=<?php echo urlencode($course_code); ?>&sort=<?php echo $sort; ?>&action=add&idChecked[]=<?php echo $enreg['user_id']; ?>" onclick="javascript:if(!confirm('<?php echo get_lang('ConfirmYourChoice'); ?>')) return false;">
+                    <?php Display::display_icon('add.png', get_lang('Add'), array(), ICON_SIZE_SMALL); ?>
+                </a>
+            <?php }  ?>
+
+            </td>
+        </tr>
+        <?php
+            $i=$i ? 0 : 1;
+    }
 }
 unset($Users);
 ?>
@@ -216,4 +204,4 @@ unset($Users);
 <button class="save" type="submit"> <?php echo get_lang('Ok'); ?></button>
 </form>
 <?php
-Display::display_footer();
+Display::display_footer();

+ 1 - 1
main/admin/user_move_stats.php

@@ -105,7 +105,7 @@ if (isset($_REQUEST['load_ajax'])) {
                 if (empty($result) || !in_array($user_id, array_keys($result))) {
                     if ($debug) echo 'User added to the session'; 
                     //Registering user to the new session
-                    SessionManager::suscribe_users_to_session($new_session_id,array($user_id),false);                    
+                    SessionManager::suscribe_users_to_session($new_session_id, array($user_id), false);                    
                 }            
                            
                 //Begin with the import process

+ 1 - 1
main/course_info/legal.php

@@ -67,7 +67,7 @@ if (empty($session_id)) {
         header('Location: '.$url);
     }
     
-    $user_session_status = SessionManager::get_user_status_in_session($user_id, $course_code, $session_id);
+    $user_session_status = SessionManager::get_user_status_in_course_session($user_id, $course_code, $session_id);
     
     if (isset($user_session_status) || api_check_user_access_to_legal($course_info['visibility'])) {        
         $user_accepted_legal = CourseManager::is_user_accepted_legal($user_id, $course_code, $session_id);        

+ 2 - 2
main/css/base.css

@@ -48,8 +48,8 @@ legend {
 }
 
 .subnav {
-    font-size: 11px;
-    font-weight: bold;
+    /*font-size: 11px;
+    font-weight: bold;*/
 }
 
 .subnav .btn-navbar {

Fișier diff suprimat deoarece este prea mare
+ 482 - 261
main/css/bootstrap-responsive.css


Fișier diff suprimat deoarece este prea mare
+ 377 - 169
main/css/bootstrap.css


+ 34 - 4
main/document/create_audio.php

@@ -199,6 +199,7 @@ $(document).ready(function(){
 
     $options = $options_pedia = array();
     $selected_language = null;
+	$options_pedia['defaultmessage'] = get_lang('FirstSelectALanguage');//need read before platform languages
 	
     while ($row = Database::fetch_array($result_select)) {       
         if (api_get_setting('platformLanguage')==$row['english_name']) {        
@@ -238,8 +239,8 @@ $(document).ready(function(){
 	if(Security::remove_XSS($_GET['dt2a'])=='pediaphon'){
 		//lang default is a default message
 		$selected_language = "defaultmessage";
-		$options_pedia['defaultmessage'] =get_lang('FirstSelectALanguage');
-		$options['defaultmessage'] =get_lang('FirstSelectALanguage'); 
+		
+		$options['defaultmessage'] = get_lang('FirstSelectALanguage'); 
 		echo '<div>';
 		
 		$form = new FormValidator('form2', 'post', null, '', array('id' => 'form2'));
@@ -413,9 +414,25 @@ function downloadMP3_google($filepath, $dir) {
     // Replacing remaining dangerous non-letter characters.
     $clean_text = str_replace($search, $replace, $filename);
 	
+	$returntext2voice=file_get_contents("http://translate.google.com/translate_tts?tl=".$clean_lang."&q=".urlencode($clean_text)."");
+	
+	//make a temporal file for get the file size
+		$tmpfname = tempnam("/tmp", "CTF");
+		$handle = fopen($tmpfname, "w");
+		fwrite($handle, $returntext2voice);
+		fclose($handle);
+		// Check if there is enough space in the course to save the file
+		if (!DocumentManager::enough_space(filesize($tmpfname), DocumentManager::get_course_quota())) {
+			unlink($tmpfname);
+			die(get_lang('UplNotEnoughSpace'));
+		}
+		//erase temporal file
+		unlink($tmpfname);
+		
+	
 	//adding the file
 		//add new file to disk
-		file_put_contents($documentPath, file_get_contents("http://translate.google.com/translate_tts?tl=".$clean_lang."&q=".urlencode($clean_text).""));
+		file_put_contents($documentPath, $returntext2voice);
 		//add document to database
 		$current_session_id = api_get_session_id();
 		$groupId=$_SESSION['_gid'];
@@ -520,7 +537,20 @@ function downloadMP3_pediaphon($filepath, $dir){
 		$search_source=preg_match($find_t2v, $previous_returntext2voice, $hits);
 		$souce_end=substr($hits[0], 0,-1);
 		$returntext2voice = file_get_contents($souce_end);
-				
+		
+		//make a temporal file for get the file size
+			$tmpfname = tempnam("/tmp", "CTF");
+			$handle = fopen($tmpfname, "w");
+			fwrite($handle, $returntext2voice);
+			fclose($handle);
+			// Check if there is enough space in the course to save the file
+			if (!DocumentManager::enough_space(filesize($tmpfname), DocumentManager::get_course_quota())) {
+				unlink($tmpfname);
+				die(get_lang('UplNotEnoughSpace'));
+			}
+			//erase temporal file
+			unlink($tmpfname);
+		
 		//save file
 		file_put_contents($documentPath, $returntext2voice);
 		

+ 16 - 0
main/document/save_pixlr.php

@@ -110,6 +110,22 @@ if(strpos($current_mime, 'image')===false) {
 }
 
 
+//make a temporal file for get the file size
+$tmpfname = tempnam("/tmp", "CTF");
+$handle = fopen($tmpfname, "w");
+fwrite($handle, $contents);
+fclose($handle);
+
+// Check if there is enough space in the course to save the file
+if (!DocumentManager::enough_space(filesize($tmpfname), DocumentManager::get_course_quota())) {
+	unlink($tmpfname);
+	die(get_lang('UplNotEnoughSpace'));
+}
+
+//erase temporal file
+unlink($tmpfname);
+
+
 //path, file and title
 $paintFileName = $filename.'.'.$extension;
 $title = $title.'.'.$extension;

+ 51 - 22
main/inc/lib/course.lib.php

@@ -714,9 +714,10 @@ class CourseManager {
                     }
                 } else {
                     $students_in_course = SessionManager::get_users_by_session($session_id, '0');
-
-                    foreach($students_in_course as $user_item) {
-                        $students_in_courses[$user_item['user_id']] = $user_item['user_id'];
+                    foreach ($students_in_course as $user_item) {
+                        if ($user_item['moved_to'] == 0) {
+                            $students_in_courses[$user_item['user_id']] = $user_item['user_id'];
+                        }                        
                     }
                 }
             }
@@ -1120,11 +1121,11 @@ class CourseManager {
      * @param int       if using the session_id: 0 or 2 (student, coach), if using session_id = 0 STUDENT or COURSEMANAGER 
      * @return array
      */
-    public static function get_user_list_from_course_code($course_code, $session_id = 0, $limit = '', $order_by = '', $filter_by_status = null) {
-        // variable initialisation
+    public static function get_user_list_from_course_code($course_code, $session_id = 0, $limit = null, $order_by =null, $filter_by_status = null, $keyword = null) {
         $session_id     = intval($session_id);
         $course_code    = Database::escape_string($course_code);
-        $where          = array();
+        $keyword        = Database::escape_string($keyword);
+        $where          = array();        
 
         // if the $order_by does not contain 'ORDER BY' we have to check if it is a valid field that can be sorted on
         if (!strstr($order_by,'ORDER BY')) {
@@ -1140,22 +1141,27 @@ class CourseManager {
         if (!empty($session_id)) {
             $sql = 'SELECT DISTINCT user.user_id, session_course_user.status as status_session, user.*  ';
             $sql .= ' FROM '.Database::get_main_table(TABLE_MAIN_USER).' as user ';            
-            $sql .= ' LEFT JOIN '.Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER).' as session_course_user
+            $sql .= ' LEFT JOIN '.Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER).' as session_course_user                      
                       ON user.user_id = session_course_user.id_user
                       AND session_course_user.course_code="'.$course_code.'"
-                      AND session_course_user.id_session = '.$session_id;
-            $where[] = ' session_course_user.course_code IS NOT NULL ';
+                      AND session_course_user.id_session = '.$session_id.' 
+                      INNER JOIN '.Database::get_main_table(TABLE_MAIN_SESSION_USER).' as su 
+                      ON (  su.id_session = session_course_user.id_session AND 
+                            user.user_id = su.id_user AND 
+                            su.moved_to = 0 AND
+                            su.moved_status <> '.SessionManager::SESSION_CHANGE_USER_REASON_ENROLLMENT_ANNULATION.'
+                      ) ';
+            $where[] = ' AND session_course_user.course_code IS NOT NULL ';
             
             // 2 = coach
             // 0 = student            
             if (isset($filter_by_status)) {                
                 $filter_by_status = intval($filter_by_status);
-                $filter_by_status_condition = " session_course_user.status = $filter_by_status AND ";                
+                $filter_by_status_condition = " AND session_course_user.status = $filter_by_status AND ";                
             }
         } else {            
             $sql = 'SELECT DISTINCT course_rel_user.status as status_rel, user.user_id, course_rel_user.role, course_rel_user.tutor_id, user.*  ';
-            $sql .= ' FROM '.Database::get_main_table(TABLE_MAIN_USER).' as user ';
-            
+            $sql .= ' FROM '.Database::get_main_table(TABLE_MAIN_USER).' as user ';            
             $sql .= ' LEFT JOIN '.Database::get_main_table(TABLE_MAIN_COURSE_USER).' as course_rel_user
                         ON user.user_id = course_rel_user.user_id AND course_rel_user.relation_type<>'.COURSE_RELATION_TYPE_RRHH.'
                         AND course_rel_user.course_code="'.$course_code.'"';
@@ -1163,7 +1169,7 @@ class CourseManager {
             
             if (isset($filter_by_status) && $filter_by_status != '') {
                 $filter_by_status = intval($filter_by_status);
-                $filter_by_status_condition = " course_rel_user.status = $filter_by_status AND ";
+                $filter_by_status_condition = " AND course_rel_user.status = $filter_by_status AND ";
             }
         }
         
@@ -1171,15 +1177,35 @@ class CourseManager {
         if ($multiple_access_url) {
             $sql  .= ' LEFT JOIN '.Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER).'  au ON (au.user_id = user.user_id) ';
         }
+        
+        $keyword_condition = null;
+        if (!empty($keyword)) {
+            $where_keyword = array();
+            $where_keyword[] = "firstname LIKE '%$keyword%'";
+            $where_keyword[] = "lastname LIKE '%$keyword%'";
+            $where_keyword[] = "username LIKE '%$keyword%'";
+            $where_keyword[] = "official_code LIKE '%$keyword%'";    
+            $keyword_condition = ' AND ('.implode(' OR ', $where_keyword).') ';
+        }
+        
+        $where_condition = null;
+        if (!empty($where)) {
+            $where_condition = implode(' OR ', $where);
+        }
+
+        $sql .= " WHERE 1=1 $filter_by_status_condition $where_condition $keyword_condition";
 
-        $sql .= ' WHERE '.$filter_by_status_condition.' '.implode(' OR ', $where);
-                
         if ($multiple_access_url) {
             $current_access_url_id = api_get_current_access_url_id();
             $sql .= " AND (access_url_id =  $current_access_url_id ) ";
         }
-        $sql .= ' '.$order_by.' '.$limit;
-
+        
+        $sql .= ' '.$order_by;
+        
+        if (!empty($keyword)) {
+            $sql .= ' '.$limit;
+        }
+        
         $rs = Database::query($sql);
         $users = array();
 
@@ -1194,11 +1220,9 @@ class CourseManager {
                 if (isset($user['tutor_id'])) {
                     $user_info['tutor_id'] = $user['tutor_id'];
                 }
-
                 if (!empty($session_id)) {
                     $user_info['status_session'] = $user['status_session'];
                 }
-
                 $users[$user['user_id']] = $user_info;
             }
         }
@@ -1212,8 +1236,7 @@ class CourseManager {
      * @param   int       $session_id
      * @return  int
      */
-    public static function get_users_count_in_course($course_code, $session_id = 0) {
-        // variable initialisation
+    public static function get_users_count_in_course($course_code, $session_id = 0) {        
         $session_id     = intval($session_id);
         $course_code    = Database::escape_string($course_code);
 
@@ -1223,7 +1246,13 @@ class CourseManager {
             $sql .= ' LEFT JOIN '.Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER).' as session_course_user
                       ON user.user_id = session_course_user.id_user
                       AND session_course_user.course_code = "'.$course_code.'"
-                      AND session_course_user.id_session  = '.$session_id;
+                      AND session_course_user.id_session  = '.$session_id.'  
+                      INNER JOIN '.Database::get_main_table(TABLE_MAIN_SESSION_USER).' as su 
+                      ON ( su.id_session = session_course_user.id_session AND 
+                           user.user_id = su.id_user AND 
+                           su.moved_to = 0 AND
+                           su.moved_status <> '.SessionManager::SESSION_CHANGE_USER_REASON_ENROLLMENT_ANNULATION.'
+                         )';
 
             $where[] = ' session_course_user.course_code IS NOT NULL ';
         } else {

+ 8 - 12
main/inc/lib/document.lib.php

@@ -22,7 +22,7 @@ class DocumentManager {
      */
     public static function get_course_quota($course_code = null) {
         if (empty($course_code)) {
-            $course_info = api_get_course_info();
+        $course_info = api_get_course_info();
         } else {
             $course_info = api_get_course_info($course_code);
         }
@@ -1166,7 +1166,7 @@ class DocumentManager {
         //When using hotpotatoes files, new files are generated in the hotpotatoe folder, if user_id=1 does the exam a new html file will be generated: hotpotatoe.html.(user_id).t.html
         //so we remove that string in order to find correctly the origin file
         if (strpos($doc_path, 'HotPotatoes_files')) {
-//            $doc_path = substr($doc_path, 0, strlen($doc_path) - 8);
+            // $doc_path = substr($doc_path, 0, strlen($doc_path) - 8); // issue #5359
             $doc_path = substr($doc_path, 0, strlen($doc_path) - 7 - strlen(api_get_user_id()));
         }
 
@@ -1328,7 +1328,7 @@ class DocumentManager {
         if ($num == 0) {
             return null;
         }
-        $row = Database::fetch_array($rs);
+        $row    = Database::fetch_array($rs);
         return $row['document_id'];
     }
 
@@ -1337,7 +1337,7 @@ class DocumentManager {
      * @param string The course code
      * @return string The html content of the certificate
      */
-    static function replace_user_info_into_html($user_id, $course_code, $is_preview = false) {
+    function replace_user_info_into_html($user_id, $course_code, $is_preview = false) {
         $user_id 		= intval($user_id);
         $course_info 	= api_get_course_info($course_code);
         $tbl_document 	= Database::get_course_table(TABLE_DOCUMENT);
@@ -1350,7 +1350,7 @@ class DocumentManager {
             $new_content = '';
             $all_user_info = array();
             if (Database::num_rows($rs)) {
-                $row = Database::fetch_array($rs);
+                $row=Database::fetch_array($rs);
                 $filepath = api_get_path(SYS_COURSE_PATH).$course_info['path'].'/document'.$row['path'];
                 if (is_file($filepath)) {
                     $my_content_html = file_get_contents($filepath);
@@ -1406,9 +1406,7 @@ class DocumentManager {
             $date_long_certificate = api_convert_and_format_date(api_get_utc_datetime());
         }
 
-        $url = api_get_path(WEB_PATH).'certificates/index.php?id='.$info_grade_certificate['id'];
-
-        
+        $url = api_get_path(WEB_PATH).'certificates/?id='.$info_grade_certificate['id'];
         //replace content
         $info_to_replace_in_content_html     = array($first_name,
                                                      $last_name,
@@ -1425,7 +1423,6 @@ class DocumentManager {
                                                      '<a href="'.$url.'" target="_blank">'.get_lang('CertificateOnlineLink').'</a>',
                                                      '((certificate_barcode))',
                                                     );
-        
         $info_to_be_replaced_in_content_html = array('((user_firstname))',
         											 '((user_lastname))',
         											 '((gradebook_institution))',
@@ -1448,7 +1445,6 @@ class DocumentManager {
                 $info_to_replace_in_content_html[]=$value_extra;
             }
         }
-            
         $info_list[]=$info_to_be_replaced_in_content_html;
         $info_list[]=$info_to_replace_in_content_html;
         return $info_list;
@@ -1498,7 +1494,7 @@ class DocumentManager {
             
             if (!is_dir($base_work_dir_test)) {
                 $created_dir = create_unexisting_directory($course_info, api_get_user_id(), api_get_session_id(), $to_group_id,$to_user_id,$base_work_dir,$dir_name,$post_dir_name);                
-                $update_id = DocumentManager::get_document_id_of_directory_certificate();                
+                $update_id = self::get_document_id_of_directory_certificate();                
                 api_item_property_update($course_info, TOOL_DOCUMENT, $update_id, $visibility_command, api_get_user_id());
             }
         }
@@ -1509,7 +1505,7 @@ class DocumentManager {
      * @param string The course id
      * @return int The document id of the directory certificate
      */
-    function get_document_id_of_directory_certificate () {
+    static function get_document_id_of_directory_certificate () {
         $tbl_document=Database::get_course_table(TABLE_DOCUMENT);
         $course_id = api_get_course_int_id();
         $sql = "SELECT id FROM $tbl_document WHERE c_id = $course_id AND path='/certificates' ";

+ 368 - 166
main/inc/lib/javascript/bootstrap/bootstrap.js

@@ -1,5 +1,5 @@
 /* ===================================================
- * bootstrap-transition.js v2.0.4
+ * bootstrap-transition.js v2.1.0
  * http://twitter.github.com/bootstrap/javascript.html#transitions
  * ===================================================
  * Copyright 2012 Twitter, Inc.
@@ -36,8 +36,7 @@
           , transEndEventNames = {
                'WebkitTransition' : 'webkitTransitionEnd'
             ,  'MozTransition'    : 'transitionend'
-            ,  'OTransition'      : 'oTransitionEnd'
-            ,  'msTransition'     : 'MSTransitionEnd'
+            ,  'OTransition'      : 'oTransitionEnd otransitionend'
             ,  'transition'       : 'transitionend'
             }
           , name
@@ -59,7 +58,7 @@
   })
 
 }(window.jQuery);/* ==========================================================
- * bootstrap-alert.js v2.0.4
+ * bootstrap-alert.js v2.1.0
  * http://twitter.github.com/bootstrap/javascript.html#alerts
  * ==========================================================
  * Copyright 2012 Twitter, Inc.
@@ -148,7 +147,7 @@
   })
 
 }(window.jQuery);/* ============================================================
- * bootstrap-button.js v2.0.4
+ * bootstrap-button.js v2.1.0
  * http://twitter.github.com/bootstrap/javascript.html#buttons
  * ============================================================
  * Copyright 2012 Twitter, Inc.
@@ -243,7 +242,7 @@
   })
 
 }(window.jQuery);/* ==========================================================
- * bootstrap-carousel.js v2.0.4
+ * bootstrap-carousel.js v2.1.0
  * http://twitter.github.com/bootstrap/javascript.html#carousel
  * ==========================================================
  * Copyright 2012 Twitter, Inc.
@@ -290,7 +289,7 @@
     }
 
   , to: function (pos) {
-      var $active = this.$element.find('.active')
+      var $active = this.$element.find('.item.active')
         , children = $active.parent().children()
         , activePos = children.index($active)
         , that = this
@@ -312,6 +311,10 @@
 
   , pause: function (e) {
       if (!e) this.paused = true
+      if (this.$element.find('.next, .prev').length && $.support.transition.end) {
+        this.$element.trigger($.support.transition.end)
+        this.cycle()
+      }
       clearInterval(this.interval)
       this.interval = null
       return this
@@ -328,13 +331,15 @@
     }
 
   , slide: function (type, next) {
-      var $active = this.$element.find('.active')
+      var $active = this.$element.find('.item.active')
         , $next = next || $active[type]()
         , isCycling = this.interval
         , direction = type == 'next' ? 'left' : 'right'
         , fallback  = type == 'next' ? 'first' : 'last'
         , that = this
-        , e = $.Event('slide')
+        , e = $.Event('slide', {
+            relatedTarget: $next[0]
+          })
 
       this.sliding = true
 
@@ -382,9 +387,10 @@
       var $this = $(this)
         , data = $this.data('carousel')
         , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option)
+        , action = typeof option == 'string' ? option : options.slide
       if (!data) $this.data('carousel', (data = new Carousel(this, options)))
       if (typeof option == 'number') data.to(option)
-      else if (typeof option == 'string' || (option = options.slide)) data[option]()
+      else if (action) data[action]()
       else if (options.interval) data.cycle()
     })
   }
@@ -411,7 +417,7 @@
   })
 
 }(window.jQuery);/* =============================================================
- * bootstrap-collapse.js v2.0.4
+ * bootstrap-collapse.js v2.1.0
  * http://twitter.github.com/bootstrap/javascript.html#collapse
  * =============================================================
  * Copyright 2012 Twitter, Inc.
@@ -479,7 +485,7 @@
 
       this.$element[dimension](0)
       this.transition('addClass', $.Event('show'), 'shown')
-      this.$element[dimension](this.$element[0][scroll])
+      $.support.transition && this.$element[dimension](this.$element[0][scroll])
     }
 
   , hide: function () {
@@ -556,18 +562,19 @@
   * ==================== */
 
   $(function () {
-    $('body').on('click.collapse.data-api', '[data-toggle=collapse]', function ( e ) {
+    $('body').on('click.collapse.data-api', '[data-toggle=collapse]', function (e) {
       var $this = $(this), href
         , target = $this.attr('data-target')
           || e.preventDefault()
           || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
         , option = $(target).data('collapse') ? 'toggle' : $this.data()
+      $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
       $(target).collapse(option)
     })
   })
 
 }(window.jQuery);/* ============================================================
- * bootstrap-dropdown.js v2.0.4
+ * bootstrap-dropdown.js v2.1.0
  * http://twitter.github.com/bootstrap/javascript.html#dropdowns
  * ============================================================
  * Copyright 2012 Twitter, Inc.
@@ -594,7 +601,7 @@
  /* DROPDOWN CLASS DEFINITION
   * ========================= */
 
-  var toggle = '[data-toggle="dropdown"]'
+  var toggle = '[data-toggle=dropdown]'
     , Dropdown = function (element) {
         var $el = $(element).on('click.dropdown.data-api', this.toggle)
         $('html').on('click.dropdown.data-api', function () {
@@ -609,34 +616,82 @@
   , toggle: function (e) {
       var $this = $(this)
         , $parent
-        , selector
         , isActive
 
       if ($this.is('.disabled, :disabled')) return
 
-      selector = $this.attr('data-target')
+      $parent = getParent($this)
 
-      if (!selector) {
-        selector = $this.attr('href')
-        selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+      isActive = $parent.hasClass('open')
+
+      clearMenus()
+
+      if (!isActive) {
+        $parent.toggleClass('open')
+        $this.focus()
       }
 
-      $parent = $(selector)
-      $parent.length || ($parent = $this.parent())
+      return false
+    }
+
+  , keydown: function (e) {
+      var $this
+        , $items
+        , $active
+        , $parent
+        , isActive
+        , index
+
+      if (!/(38|40|27)/.test(e.keyCode)) return
+
+      $this = $(this)
+
+      e.preventDefault()
+      e.stopPropagation()
+
+      if ($this.is('.disabled, :disabled')) return
+
+      $parent = getParent($this)
 
       isActive = $parent.hasClass('open')
 
-      clearMenus()
+      if (!isActive || (isActive && e.keyCode == 27)) return $this.click()
 
-      if (!isActive) $parent.toggleClass('open')
+      $items = $('[role=menu] li:not(.divider) a', $parent)
 
-      return false
+      if (!$items.length) return
+
+      index = $items.index($items.filter(':focus'))
+
+      if (e.keyCode == 38 && index > 0) index--                                        // up
+      if (e.keyCode == 40 && index < $items.length - 1) index++                        // down
+      if (!~index) index = 0
+
+      $items
+        .eq(index)
+        .focus()
     }
 
   }
 
   function clearMenus() {
-    $(toggle).parent().removeClass('open')
+    getParent($(toggle))
+      .removeClass('open')
+  }
+
+  function getParent($this) {
+    var selector = $this.attr('data-target')
+      , $parent
+
+    if (!selector) {
+      selector = $this.attr('href')
+      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+    }
+
+    $parent = $(selector)
+    $parent.length || ($parent = $this.parent())
+
+    return $parent
   }
 
 
@@ -659,14 +714,16 @@
    * =================================== */
 
   $(function () {
-    $('html').on('click.dropdown.data-api', clearMenus)
+    $('html')
+      .on('click.dropdown.data-api touchstart.dropdown.data-api', clearMenus)
     $('body')
-      .on('click.dropdown', '.dropdown form', function (e) { e.stopPropagation() })
-      .on('click.dropdown.data-api', toggle, Dropdown.prototype.toggle)
+      .on('click.dropdown touchstart.dropdown.data-api', '.dropdown', function (e) { e.stopPropagation() })
+      .on('click.dropdown.data-api touchstart.dropdown.data-api'  , toggle, Dropdown.prototype.toggle)
+      .on('keydown.dropdown.data-api touchstart.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
   })
 
 }(window.jQuery);/* =========================================================
- * bootstrap-modal.js v2.0.4
+ * bootstrap-modal.js v2.1.0
  * http://twitter.github.com/bootstrap/javascript.html#modals
  * =========================================================
  * Copyright 2012 Twitter, Inc.
@@ -693,10 +750,11 @@
  /* MODAL CLASS DEFINITION
   * ====================== */
 
-  var Modal = function (content, options) {
+  var Modal = function (element, options) {
     this.options = options
-    this.$element = $(content)
+    this.$element = $(element)
       .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
+    this.options.remote && this.$element.find('.modal-body').load(this.options.remote)
   }
 
   Modal.prototype = {
@@ -719,8 +777,9 @@
 
         this.isShown = true
 
-        escape.call(this)
-        backdrop.call(this, function () {
+        this.escape()
+
+        this.backdrop(function () {
           var transition = $.support.transition && that.$element.hasClass('fade')
 
           if (!that.$element.parent().length) {
@@ -734,7 +793,12 @@
             that.$element[0].offsetWidth // force reflow
           }
 
-          that.$element.addClass('in')
+          that.$element
+            .addClass('in')
+            .attr('aria-hidden', false)
+            .focus()
+
+          that.enforceFocus()
 
           transition ?
             that.$element.one($.support.transition.end, function () { that.$element.trigger('shown') }) :
@@ -758,90 +822,98 @@
 
         $('body').removeClass('modal-open')
 
-        escape.call(this)
+        this.escape()
 
-        this.$element.removeClass('in')
+        $(document).off('focusin.modal')
+
+        this.$element
+          .removeClass('in')
+          .attr('aria-hidden', true)
 
         $.support.transition && this.$element.hasClass('fade') ?
-          hideWithTransition.call(this) :
-          hideModal.call(this)
+          this.hideWithTransition() :
+          this.hideModal()
       }
 
-  }
-
-
- /* MODAL PRIVATE METHODS
-  * ===================== */
+    , enforceFocus: function () {
+        var that = this
+        $(document).on('focusin.modal', function (e) {
+          if (that.$element[0] !== e.target && !that.$element.has(e.target).length) {
+            that.$element.focus()
+          }
+        })
+      }
 
-  function hideWithTransition() {
-    var that = this
-      , timeout = setTimeout(function () {
-          that.$element.off($.support.transition.end)
-          hideModal.call(that)
-        }, 500)
+    , escape: function () {
+        var that = this
+        if (this.isShown && this.options.keyboard) {
+          this.$element.on('keyup.dismiss.modal', function ( e ) {
+            e.which == 27 && that.hide()
+          })
+        } else if (!this.isShown) {
+          this.$element.off('keyup.dismiss.modal')
+        }
+      }
 
-    this.$element.one($.support.transition.end, function () {
-      clearTimeout(timeout)
-      hideModal.call(that)
-    })
-  }
+    , hideWithTransition: function () {
+        var that = this
+          , timeout = setTimeout(function () {
+              that.$element.off($.support.transition.end)
+              that.hideModal()
+            }, 500)
 
-  function hideModal(that) {
-    this.$element
-      .hide()
-      .trigger('hidden')
+        this.$element.one($.support.transition.end, function () {
+          clearTimeout(timeout)
+          that.hideModal()
+        })
+      }
 
-    backdrop.call(this)
-  }
+    , hideModal: function (that) {
+        this.$element
+          .hide()
+          .trigger('hidden')
 
-  function backdrop(callback) {
-    var that = this
-      , animate = this.$element.hasClass('fade') ? 'fade' : ''
+        this.backdrop()
+      }
 
-    if (this.isShown && this.options.backdrop) {
-      var doAnimate = $.support.transition && animate
+    , removeBackdrop: function () {
+        this.$backdrop.remove()
+        this.$backdrop = null
+      }
 
-      this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
-        .appendTo(document.body)
+    , backdrop: function (callback) {
+        var that = this
+          , animate = this.$element.hasClass('fade') ? 'fade' : ''
 
-      if (this.options.backdrop != 'static') {
-        this.$backdrop.click($.proxy(this.hide, this))
-      }
+        if (this.isShown && this.options.backdrop) {
+          var doAnimate = $.support.transition && animate
 
-      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
+          this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
+            .appendTo(document.body)
 
-      this.$backdrop.addClass('in')
+          if (this.options.backdrop != 'static') {
+            this.$backdrop.click($.proxy(this.hide, this))
+          }
 
-      doAnimate ?
-        this.$backdrop.one($.support.transition.end, callback) :
-        callback()
+          if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
 
-    } else if (!this.isShown && this.$backdrop) {
-      this.$backdrop.removeClass('in')
+          this.$backdrop.addClass('in')
 
-      $.support.transition && this.$element.hasClass('fade')?
-        this.$backdrop.one($.support.transition.end, $.proxy(removeBackdrop, this)) :
-        removeBackdrop.call(this)
+          doAnimate ?
+            this.$backdrop.one($.support.transition.end, callback) :
+            callback()
 
-    } else if (callback) {
-      callback()
-    }
-  }
+        } else if (!this.isShown && this.$backdrop) {
+          this.$backdrop.removeClass('in')
 
-  function removeBackdrop() {
-    this.$backdrop.remove()
-    this.$backdrop = null
-  }
+          $.support.transition && this.$element.hasClass('fade')?
+            this.$backdrop.one($.support.transition.end, $.proxy(this.removeBackdrop, this)) :
+            this.removeBackdrop()
 
-  function escape() {
-    var that = this
-    if (this.isShown && this.options.keyboard) {
-      $(document).on('keyup.dismiss.modal', function ( e ) {
-        e.which == 27 && that.hide()
-      })
-    } else if (!this.isShown) {
-      $(document).off('keyup.dismiss.modal')
-    }
+        } else if (callback) {
+          callback()
+        }
+      }
   }
 
 
@@ -873,17 +945,23 @@
 
   $(function () {
     $('body').on('click.modal.data-api', '[data-toggle="modal"]', function ( e ) {
-      var $this = $(this), href
-        , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
-        , option = $target.data('modal') ? 'toggle' : $.extend({}, $target.data(), $this.data())
+      var $this = $(this)
+        , href = $this.attr('href')
+        , $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
+        , option = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
 
       e.preventDefault()
-      $target.modal(option)
+
+      $target
+        .modal(option)
+        .one('hide', function () {
+          $this.focus()
+        })
     })
   })
 
 }(window.jQuery);/* ===========================================================
- * bootstrap-tooltip.js v2.0.4
+ * bootstrap-tooltip.js v2.1.0
  * http://twitter.github.com/bootstrap/javascript.html#tooltips
  * Inspired by the original jQuery.tipsy by Jason Frame
  * ===========================================================
@@ -928,11 +1006,13 @@
       this.options = this.getOptions(options)
       this.enabled = true
 
-      if (this.options.trigger != 'manual') {
-        eventIn  = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
+      if (this.options.trigger == 'click') {
+        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
+      } else if (this.options.trigger != 'manual') {
+        eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
         eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur'
-        this.$element.on(eventIn, this.options.selector, $.proxy(this.enter, this))
-        this.$element.on(eventOut, this.options.selector, $.proxy(this.leave, this))
+        this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
+        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
       }
 
       this.options.selector ?
@@ -1032,20 +1112,11 @@
       }
     }
 
-  , isHTML: function(text) {
-      // html string detection logic adapted from jQuery
-      return typeof text != 'string'
-        || ( text.charAt(0) === "<"
-          && text.charAt( text.length - 1 ) === ">"
-          && text.length >= 3
-        ) || /^(?:[^<]*<[\w\W]+>[^>]*$)/.exec(text)
-    }
-
   , setContent: function () {
       var $tip = this.tip()
         , title = this.getTitle()
 
-      $tip.find('.tooltip-inner')[this.isHTML(title) ? 'html' : 'text'](title)
+      $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
       $tip.removeClass('fade in top bottom left right')
     }
 
@@ -1069,6 +1140,8 @@
       $.support.transition && this.$tip.hasClass('fade') ?
         removeWithAnimation() :
         $tip.remove()
+
+      return this
     }
 
   , fixTitle: function () {
@@ -1128,6 +1201,10 @@
       this[this.tip().hasClass('in') ? 'hide' : 'show']()
     }
 
+  , destroy: function () {
+      this.hide().$element.off('.' + this.type).removeData(this.type)
+    }
+
   }
 
 
@@ -1154,11 +1231,12 @@
   , trigger: 'hover'
   , title: ''
   , delay: 0
+  , html: true
   }
 
 }(window.jQuery);
 /* ===========================================================
- * bootstrap-popover.js v2.0.4
+ * bootstrap-popover.js v2.1.0
  * http://twitter.github.com/bootstrap/javascript.html#popovers
  * ===========================================================
  * Copyright 2012 Twitter, Inc.
@@ -1185,7 +1263,7 @@
  /* POPOVER PUBLIC CLASS DEFINITION
   * =============================== */
 
-  var Popover = function ( element, options ) {
+  var Popover = function (element, options) {
     this.init('popover', element, options)
   }
 
@@ -1202,8 +1280,8 @@
         , title = this.getTitle()
         , content = this.getContent()
 
-      $tip.find('.popover-title')[this.isHTML(title) ? 'html' : 'text'](title)
-      $tip.find('.popover-content > *')[this.isHTML(content) ? 'html' : 'text'](content)
+      $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
+      $tip.find('.popover-content > *')[this.options.html ? 'html' : 'text'](content)
 
       $tip.removeClass('fade top bottom left right in')
     }
@@ -1230,6 +1308,10 @@
       return this.$tip
     }
 
+  , destroy: function () {
+      this.hide().$element.off('.' + this.type).removeData(this.type)
+    }
+
   })
 
 
@@ -1250,12 +1332,13 @@
 
   $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
     placement: 'right'
+  , trigger: 'click'
   , content: ''
   , template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'
   })
 
 }(window.jQuery);/* =============================================================
- * bootstrap-scrollspy.js v2.0.4
+ * bootstrap-scrollspy.js v2.1.0
  * http://twitter.github.com/bootstrap/javascript.html#scrollspy
  * =============================================================
  * Copyright 2012 Twitter, Inc.
@@ -1279,15 +1362,15 @@
   "use strict"; // jshint ;_;
 
 
-  /* SCROLLSPY CLASS DEFINITION
-   * ========================== */
+ /* SCROLLSPY CLASS DEFINITION
+  * ========================== */
 
-  function ScrollSpy( element, options) {
+  function ScrollSpy(element, options) {
     var process = $.proxy(this.process, this)
       , $element = $(element).is('body') ? $(window) : $(element)
       , href
     this.options = $.extend({}, $.fn.scrollspy.defaults, options)
-    this.$scrollElement = $element.on('scroll.scroll.data-api', process)
+    this.$scrollElement = $element.on('scroll.scroll-spy.data-api', process)
     this.selector = (this.options.target
       || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
       || '') + ' .nav li > a'
@@ -1314,7 +1397,7 @@
               , href = $el.data('target') || $el.attr('href')
               , $href = /^#\w/.test(href) && $(href)
             return ( $href
-              && href.length
+              && $href.length
               && [[ $href.position().top, href ]] ) || null
           })
           .sort(function (a, b) { return a[0] - b[0] })
@@ -1364,7 +1447,7 @@
           .parent('li')
           .addClass('active')
 
-        if (active.parent('.dropdown-menu'))  {
+        if (active.parent('.dropdown-menu').length)  {
           active = active.closest('li.dropdown').addClass('active')
         }
 
@@ -1377,7 +1460,7 @@
  /* SCROLLSPY PLUGIN DEFINITION
   * =========================== */
 
-  $.fn.scrollspy = function ( option ) {
+  $.fn.scrollspy = function (option) {
     return this.each(function () {
       var $this = $(this)
         , data = $this.data('scrollspy')
@@ -1397,7 +1480,7 @@
  /* SCROLLSPY DATA-API
   * ================== */
 
-  $(function () {
+  $(window).on('load', function () {
     $('[data-spy="scroll"]').each(function () {
       var $spy = $(this)
       $spy.scrollspy($spy.data())
@@ -1405,7 +1488,7 @@
   })
 
 }(window.jQuery);/* ========================================================
- * bootstrap-tab.js v2.0.4
+ * bootstrap-tab.js v2.1.0
  * http://twitter.github.com/bootstrap/javascript.html#tabs
  * ========================================================
  * Copyright 2012 Twitter, Inc.
@@ -1432,7 +1515,7 @@
  /* TAB CLASS DEFINITION
   * ==================== */
 
-  var Tab = function ( element ) {
+  var Tab = function (element) {
     this.element = $(element)
   }
 
@@ -1539,7 +1622,7 @@
   })
 
 }(window.jQuery);/* =============================================================
- * bootstrap-typeahead.js v2.0.4
+ * bootstrap-typeahead.js v2.1.0
  * http://twitter.github.com/bootstrap/javascript.html#typeahead
  * =============================================================
  * Copyright 2012 Twitter, Inc.
@@ -1617,17 +1700,23 @@
     }
 
   , lookup: function (event) {
-      var that = this
-        , items
-        , q
+      var items
 
       this.query = this.$element.val()
 
-      if (!this.query) {
+      if (!this.query || this.query.length < this.options.minLength) {
         return this.shown ? this.hide() : this
       }
 
-      items = $.grep(this.source, function (item) {
+      items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source
+
+      return items ? this.process(items) : this
+    }
+
+  , process: function (items) {
+      var that = this
+
+      items = $.grep(items, function (item) {
         return that.matcher(item)
       })
 
@@ -1709,7 +1798,7 @@
         .on('keyup',    $.proxy(this.keyup, this))
 
       if ($.browser.webkit || $.browser.msie) {
-        this.$element.on('keydown', $.proxy(this.keypress, this))
+        this.$element.on('keydown', $.proxy(this.keydown, this))
       }
 
       this.$menu
@@ -1717,6 +1806,40 @@
         .on('mouseenter', 'li', $.proxy(this.mouseenter, this))
     }
 
+  , move: function (e) {
+      if (!this.shown) return
+
+      switch(e.keyCode) {
+        case 9: // tab
+        case 13: // enter
+        case 27: // escape
+          e.preventDefault()
+          break
+
+        case 38: // up arrow
+          e.preventDefault()
+          this.prev()
+          break
+
+        case 40: // down arrow
+          e.preventDefault()
+          this.next()
+          break
+      }
+
+      e.stopPropagation()
+    }
+
+  , keydown: function (e) {
+      this.suppressKeyPressRepeat = !~$.inArray(e.keyCode, [40,38,9,13,27])
+      this.move(e)
+    }
+
+  , keypress: function (e) {
+      if (this.suppressKeyPressRepeat) return
+      this.move(e)
+    }
+
   , keyup: function (e) {
       switch(e.keyCode) {
         case 40: // down arrow
@@ -1742,32 +1865,6 @@
       e.preventDefault()
   }
 
-  , keypress: function (e) {
-      if (!this.shown) return
-
-      switch(e.keyCode) {
-        case 9: // tab
-        case 13: // enter
-        case 27: // escape
-          e.preventDefault()
-          break
-
-        case 38: // up arrow
-          if (e.type != 'keydown') break
-          e.preventDefault()
-          this.prev()
-          break
-
-        case 40: // down arrow
-          if (e.type != 'keydown') break
-          e.preventDefault()
-          this.next()
-          break
-      }
-
-      e.stopPropagation()
-    }
-
   , blur: function (e) {
       var that = this
       setTimeout(function () { that.hide() }, 150)
@@ -1805,12 +1902,13 @@
   , items: 8
   , menu: '<ul class="typeahead dropdown-menu"></ul>'
   , item: '<li><a href="#"></a></li>'
+  , minLength: 1
   }
 
   $.fn.typeahead.Constructor = Typeahead
 
 
- /* TYPEAHEAD DATA-API
+ /*   TYPEAHEAD DATA-API
   * ================== */
 
   $(function () {
@@ -1822,4 +1920,108 @@
     })
   })
 
+}(window.jQuery);
+/* ==========================================================
+ * bootstrap-affix.js v2.1.0
+ * http://twitter.github.com/bootstrap/javascript.html#affix
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function ($) {
+
+  "use strict"; // jshint ;_;
+
+
+ /* AFFIX CLASS DEFINITION
+  * ====================== */
+
+  var Affix = function (element, options) {
+    this.options = $.extend({}, $.fn.affix.defaults, options)
+    this.$window = $(window).on('scroll.affix.data-api', $.proxy(this.checkPosition, this))
+    this.$element = $(element)
+    this.checkPosition()
+  }
+
+  Affix.prototype.checkPosition = function () {
+    if (!this.$element.is(':visible')) return
+
+    var scrollHeight = $(document).height()
+      , scrollTop = this.$window.scrollTop()
+      , position = this.$element.offset()
+      , offset = this.options.offset
+      , offsetBottom = offset.bottom
+      , offsetTop = offset.top
+      , reset = 'affix affix-top affix-bottom'
+      , affix
+
+    if (typeof offset != 'object') offsetBottom = offsetTop = offset
+    if (typeof offsetTop == 'function') offsetTop = offset.top()
+    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()
+
+    affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ?
+      false    : offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ?
+      'bottom' : offsetTop != null && scrollTop <= offsetTop ?
+      'top'    : false
+
+    if (this.affixed === affix) return
+
+    this.affixed = affix
+    this.unpin = affix == 'bottom' ? position.top - scrollTop : null
+
+    this.$element.removeClass(reset).addClass('affix' + (affix ? '-' + affix : ''))
+  }
+
+
+ /* AFFIX PLUGIN DEFINITION
+  * ======================= */
+
+  $.fn.affix = function (option) {
+    return this.each(function () {
+      var $this = $(this)
+        , data = $this.data('affix')
+        , options = typeof option == 'object' && option
+      if (!data) $this.data('affix', (data = new Affix(this, options)))
+      if (typeof option == 'string') data[option]()
+    })
+  }
+
+  $.fn.affix.Constructor = Affix
+
+  $.fn.affix.defaults = {
+    offset: 0
+  }
+
+
+ /* AFFIX DATA-API
+  * ============== */
+
+  $(window).on('load', function () {
+    $('[data-spy="affix"]').each(function () {
+      var $spy = $(this)
+        , data = $spy.data()
+
+      data.offset = data.offset || {}
+
+      data.offsetBottom && (data.offset.bottom = data.offsetBottom)
+      data.offsetTop && (data.offset.top = data.offsetTop)
+
+      $spy.affix(data)
+    })
+  })
+
+
 }(window.jQuery);

+ 16 - 2
main/inc/lib/jpegcam/webcam_receiver.php

@@ -75,13 +75,27 @@ if (!$content) {
 	exit();
 }
 
+
+//make a temporal file for get the file size
+	$tmpfname = tempnam("/tmp", "CTF");
+	$handle = fopen($tmpfname, "w");
+	fwrite($handle, $content);
+	fclose($handle);
+	
+	// Check if there is enough space in the course to save the file
+	if (!DocumentManager::enough_space(filesize($tmpfname), DocumentManager::get_course_quota())) {
+		unlink($tmpfname);
+		die(get_lang('UplNotEnoughSpace'));
+	}
+	
+	//erase temporal file
+	unlink($tmpfname);
+
 //add to disk
 $fh = fopen($documentPath, 'w') or die("can't open file");
 fwrite($fh, $content);
 fclose($fh);
 
-
-//
 //add document to database
 	$doc_id = add_document($_course, $webcamdir.'/'.$webcamname_to_save, 'file', filesize($documentPath), $title_to_save);
 	api_item_property_update($_course, TOOL_DOCUMENT, $doc_id, 'DocumentAdded', $_user['user_id'], $groupId, null, null, null, $current_session_id);

+ 6 - 0
main/inc/lib/mail.lib.inc.php

@@ -163,6 +163,12 @@ function api_mail_html($recipient_name, $recipient_email, $subject, $message, $s
     if (is_array($extra_headers) && count($extra_headers) > 0) {
         foreach ($extra_headers as $key => $value) {
             switch (strtolower($key)) {
+                case 'reply-to':
+                    //the value here is the result of api_get_user_info()
+                    $sender_email = $value['email'];
+                    $sender_name  = $value['complete_name'];
+                    $mail->AddReplyTo($sender_email, $sender_name);
+                    break;
                 case 'encoding':
                 case 'content-transfer-encoding':
                     $mail->Encoding = $value;

+ 12 - 7
main/inc/lib/main_api.lib.php

@@ -810,9 +810,11 @@ function api_protect_course_script($print_headers = false, $allow_session_admins
     if (api_is_drh()) {
         return true;
     }
+    
     if (api_is_platform_admin($allow_session_admins)) {
     	return true;
     }
+    
     $course_info = api_get_course_info();
 
     if (isset($course_info) && isset($course_info['visibility'])) {
@@ -838,7 +840,7 @@ function api_protect_course_script($print_headers = false, $allow_session_admins
     			break;
     	}
     }
-        
+    
     //Check session visibility
     $session_id = api_get_session_id();
     
@@ -1836,7 +1838,7 @@ function api_get_session_visibility($session_id) {
 
         if (Database::num_rows($result) > 0 ) {
             $row = Database::fetch_array($result, 'ASSOC');
-            $visibility = $row['visibility'];
+            $visibility = $original_visibility = $row['visibility'];
 
             //I don't care the field visibility
             if ($row['date_start'] == '0000-00-00' && $row['date_end'] == '0000-00-00') {
@@ -1908,7 +1910,14 @@ function api_get_session_visibility($session_id) {
                         $visibility = SESSION_INVISIBLE;
                     }
                 }
+            } else {
+                //Student - check the moved_to variable
+                $user_status = SessionManager::get_user_status_in_session($session_id, api_get_user_id());
+                if (isset($user_status['moved_to']) && $user_status['moved_to'] != 0) {
+                    return $original_visibility;
+                }
             }
+            
         } else {
             $visibility = SESSION_INVISIBLE;
         }
@@ -2612,10 +2621,6 @@ function api_is_allowed_to_session_edit($tutor = false, $coach = false) {
             // Get the session visibility
             $session_visibility = api_get_session_visibility($session_id);  // if 5 the session is still available
             
-            //@todo We could load the session_rel_course_rel_user permission to increase the level of detail.
-            //echo api_get_user_id();
-            //echo api_get_course_id();
-
             switch ($session_visibility) {
                 case SESSION_VISIBLE_READ_ONLY: // 1
                     return false;
@@ -2623,7 +2628,7 @@ function api_is_allowed_to_session_edit($tutor = false, $coach = false) {
                     return true;
                 case SESSION_INVISIBLE:         // 3
                     return false;
-                case SESSION_AVAILABLE:         //5
+                case SESSION_AVAILABLE:         //4
                     return true;
             }
 

+ 15 - 33
main/inc/lib/message.lib.php

@@ -43,34 +43,7 @@ class MessageManager
 		}
 		return $online_user_list;
 	}
-
-	/**
-	* Displays info stating that the message is sent successfully.
-	*/
-	public static function display_success_message($uid) {
-			global $charset;
-		if ($_SESSION['social_exist']===true) {
-			$redirect="#remote-tab-2";
-			if (api_get_setting('allow_social_tool')=='true' && api_get_setting('allow_message_tool')=='true') {
-				$success=get_lang('MessageSentTo').
-				"&nbsp;<b>".
-				GetFullUserName($uid).
-				"</b>";
-			}else {
-				$success=get_lang('MessageSentTo').
-				"&nbsp;<b>".
-				GetFullUserName($uid).
-				"</b>";
-			}
-		} else {
-				$success=get_lang('MessageSentTo').
-				"&nbsp;<b>".
-				GetFullUserName($uid).
-				"</b>";
-		}
-		return Display::return_message(api_xml_http_response_encode($success), 'confirmation', false);
-	}
-
+    
 	/**
 	* Displays the wysiwyg html editor.
 	*/
@@ -207,7 +180,7 @@ class MessageManager
      * @param int    sender id (optional) the default value is the current user_id
 	 * @return bool
 	 */
-	public static function send_message($receiver_user_id, $subject, $content, $file_attachments = array(), $file_comments = array(), $group_id = 0, $parent_id = 0, $edit_message_id = 0, $topic_id = 0, $sender_id = null) {        
+	public static function send_message($receiver_user_id, $subject, $content, $file_attachments = array(), $file_comments = array(), $group_id = 0, $parent_id = 0, $edit_message_id = 0, $topic_id = 0, $sender_id = null) {
 		$table_message      = Database::get_main_table(TABLE_MESSAGE);
         $group_id           = intval($group_id);
         $receiver_user_id   = intval($receiver_user_id);
@@ -215,6 +188,10 @@ class MessageManager
         $edit_message_id    = intval($edit_message_id);
         $topic_id   		= intval($topic_id);
         
+        //Capturing the original sender id 
+        $original_sender_id = $user_sender_id;
+        
+        //Saving the user id for the chamilo inbox, if the sender is null we asume that the current user is the one that sent the message
         if (empty($sender_id)) {        
             $user_sender_id     = api_get_user_id();
         } else {
@@ -292,9 +269,14 @@ class MessageManager
 						
 			//Load user settings			
 			$notification = new Notification();
-			$sender_info = api_get_user_info($user_sender_id);
-			
-		    if (empty($group_id)) {	    	
+            
+		    if (empty($group_id)) {
+                
+                $sender_info = array();
+                if (!empty($original_sender_id)) {
+                    $sender_info = api_get_user_info($original_sender_id);
+                }
+
                 $notification->save_notification(NOTIFICATION_TYPE_MESSAGE, array($receiver_user_id), $subject, $content, $sender_info);                
 		    } else {
 		        $group_info = GroupPortalManager::get_group_data($group_id);
@@ -310,7 +292,7 @@ class MessageManager
                 foreach($user_list as $user_data) {
                     $new_user_list[] = $user_data['user_id'];
                 }
-                $group_info = array('group_info'=>$group_info, 'user_info' => $sender_info);
+                $group_info = array('group_info' => $group_info, 'user_info' => $sender_info);
                 $notification->save_notification(NOTIFICATION_TYPE_GROUP, $new_user_list, $subject, $content, $group_info);                     		
 		    }
 			return $inbox_last_id;

+ 5 - 0
main/inc/lib/nanogong/receiver.php

@@ -57,6 +57,11 @@ if ($nano_user_id!= api_get_user_id() || api_get_user_id()==0 || $nano_user_id==
 
 //Do not use here check Fileinfo method because return: text/plain
 
+// Check if there is enough space in the course to save the file
+if (!DocumentManager::enough_space(filesize($_FILES['voicefile']['tmp_name']), DocumentManager::get_course_quota())) {
+	die(get_lang('UplNotEnoughSpace'));
+}
+
 if (!file_exists($documentPath)){
 	//add document to disk
 	move_uploaded_file($_FILES['voicefile']['tmp_name'], $documentPath);

+ 47 - 20
main/inc/lib/notification.lib.php

@@ -41,26 +41,30 @@ define('NOTIFICATION_TYPE_GROUP',         3);
 class Notification extends Model {
     
     var $table;
-    var $columns             = array('id','dest_user_id','dest_mail','title','content','send_freq','created_at','sent_at');
+    var $columns             = array('id', 'dest_user_id', 'sender_id', 'dest_mail', 'title', 'content', 'send_freq', 'created_at', 'sent_at');
     var $max_content_length  = 254; //Max lenght of the notification.content field
     var $debug               = false;
     
     /* message, invitation, group messages */
     var $type;    
-    var $admin_name;
-    var $admin_email;
+    var $sender_name;
+    var $sender_email;
+    
+    var $extra_headers = array();
+    
+    var $send_email_as_user = false; //False, chamilo will sent an email as the user (not recommended)
     
 	public function __construct() {
         $this->table       = Database::get_main_table(TABLE_NOTIFICATION);
            
-        $this->admin_email  = api_get_setting('noreply_email_address');
-        $this->admin_name   = api_get_setting('siteName');
+        $this->sender_email  = api_get_setting('noreply_email_address');
+        $this->sender_name   = api_get_setting('siteName');
         
         // If no-reply  email doesn't exist use the admin email
-        if (empty($this->admin_email)) {            
-            $this->admin_email = api_get_setting('emailAdministrator');
-            $this->admin_name  = api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'), null, PERSON_NAME_EMAIL_ADDRESS);            
-        }
+        if (empty($this->sender_email)) {            
+            $this->sender_email = api_get_setting('emailAdministrator');
+            $this->sender_name  = api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'), null, PERSON_NAME_EMAIL_ADDRESS);            
+        }        
 	}  
 	  
     /**
@@ -68,19 +72,21 @@ class Notification extends Model {
      *  @param int notification frecuency 
      */	
     public function send($frec = NOTIFY_MESSAGE_DAILY) {
-        $notifications = $this->find('all',array('where'=>array('sent_at IS NULL AND send_freq = ?'=>$frec)));
-     
+        $notifications = $this->find('all', array('where'=> array('sent_at IS NULL AND send_freq = ?' => $frec)));     
         
         if (!empty($notifications)) {
             foreach ($notifications as $item_to_send) {
                 
+                $this->set_sender_info($item_to_send['sender_id']);
+                
                 //Sending email
                 api_mail_html($item_to_send['dest_mail'], 
                               $item_to_send['dest_mail'], 
                               Security::filter_terms($item_to_send['title']), 
                               Security::filter_terms($item_to_send['content']), 
-                              $this->admin_name, 
-                              $this->admin_email
+                              $this->sender_name, 
+                              $this->sender_email, 
+                              $this->extra_headers
                             );
                 if ($this->debug) { error_log('Sending message to: '.$item_to_send['dest_mail']); }
                 
@@ -92,6 +98,21 @@ class Notification extends Model {
         }                
     }
     
+    /**
+     * Sets the sender info in order to add the reply-to
+     */
+    function set_sender_info($user_id) {
+        if (!empty($user_id)) {
+            $sender_user_info = api_get_user_info($user_id);            
+            if ($this->send_email_as_user) {                
+                $this->sender_email = $sender_user_info['email'];
+                $this->sender_name  = $sender_user_info['complete_name'];          
+            } else {
+                $this->extra_headers = array('reply-to' => $sender_user_info);
+            }
+        }
+    }
+    
     /**
      * Save message notification
      * @param	array	message type NOTIFICATION_TYPE_MESSAGE, NOTIFICATION_TYPE_INVITATION, NOTIFICATION_TYPE_GROUP
@@ -103,11 +124,17 @@ class Notification extends Model {
     public function save_notification($type, $user_list, $title, $content, $sender_info = array()) {
         $this->type = intval($type);
         $content    = $this->format_content($content, $sender_info);
+        
+        $sender_id = 0;
+        if (!empty($sender_info) && isset($sender_info['user_id'])) {
+            $sender_id = $sender_info['user_id'];
+            $this->set_sender_info($sender_id);
+        }        
                 
         $setting_to_check = '';
         $avoid_my_self  = false;
         
-        switch($this->type) {
+        switch ($this->type) {
             case NOTIFICATION_TYPE_MESSAGE;
                 $setting_to_check = 'mail_notify_message';
                 break;
@@ -145,7 +172,7 @@ class Notification extends Model {
                     case NOTIFY_GROUP_AT_ONCE:                     
                         if (!empty($user_info['mail'])) {
                             $name = api_get_person_name($user_info['firstname'], $user_info['lastname']);                            
-                            api_mail_html($name, $user_info['mail'], Security::filter_terms($title), Security::filter_terms($content), $this->admin_name, $this->admin_email);
+                            api_mail_html($name, $user_info['mail'], Security::filter_terms($title), Security::filter_terms($content), $this->sender_name, $this->sender_email, $this->extra_headers);
                         }
                         $params['sent_at']       = api_get_utc_datetime();
                     //Saving the notification to be sent some day 
@@ -154,7 +181,8 @@ class Notification extends Model {
                 	    $params['dest_mail']     = $user_info['mail'];
                 	    $params['title']         = $title;
                 	    $params['content']       = cut($content, $this->max_content_length);
-                	    $params['send_freq']     = $user_setting;    			 
+                	    $params['send_freq']     = $user_setting;  			 
+                        $params['sender_id']     = $sender_id;
                 	    $this->save($params);
                 	    break;
                 }          
@@ -170,11 +198,10 @@ class Notification extends Model {
     public function format_content($content, $sender_info) {
         $new_message_text = $link_to_new_message = '';        
         
-        switch($this->type) {
+        switch ($this->type) {
             case NOTIFICATION_TYPE_MESSAGE:           
                 if (!empty($sender_info)) {
-                    $sender_name = api_get_person_name($sender_info['firstname'], $sender_info['lastname'], null, PERSON_NAME_EMAIL_ADDRESS);
-                    //$sender_mail = $sender_info['email'] ;            
+                    $sender_name = api_get_person_name($sender_info['firstname'], $sender_info['lastname'], null, PERSON_NAME_EMAIL_ADDRESS);                             
                     $new_message_text = sprintf(get_lang('YouHaveANewMessageFromX'), $sender_name);            
                 }
                 $link_to_new_message = Display::url(get_lang('SeeMessage'), api_get_path(WEB_CODE_PATH).'messages/inbox.php');
@@ -214,7 +241,7 @@ class Notification extends Model {
         }
               
         // You have received this message because you are subscribed text
-        $content        = $content.'<br /><hr><i>'.
+        $content = $content.'<br /><hr><i>'.
                           sprintf(get_lang('YouHaveReceivedThisNotificationBecauseYouAreSubscribedOrInvolvedInItToChangeYourNotificationPreferencesPleaseClickHereX'), Display::url($preference_url, $preference_url)).'</i>';
         return $content;        
     }

+ 13 - 15
main/inc/lib/online.inc.php

@@ -20,7 +20,7 @@
 use \ChamiloSession as Session;
 
 function LoginCheck($uid) {
-	global $_course, $_configuration;
+	global $_course;
 	$uid = (int) $uid;
 	$online_table = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_ONLINE);
 	if (!empty($uid)) {
@@ -52,7 +52,7 @@ function LoginCheck($uid) {
  * @author Fernando P. García <fernando@develcuy.com>
  */
 function online_logout($user_id = null, $logout_redirect = false) {
-    global $_configuration, $extAuthSource;
+    global $extAuthSource;
   
     // Database table definition
     $tbl_track_login = Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_LOGIN);
@@ -129,21 +129,19 @@ function user_is_online($user_id) {
 	$current_date		= api_get_utc_datetime();	
 	$access_url_id		= api_get_current_access_url_id();	
 	$time_limit			= api_get_setting('time_limit_whosonline');
-	//$time_limit = 1; changing this value there is no time limit 
-	
+		
 	$query = " SELECT login_user_id,login_date FROM ".$track_online_table ." track INNER JOIN ".$table_user ." u ON (u.user_id=track.login_user_id)
                WHERE track.access_url_id =  $access_url_id AND 
-                    DATE_ADD(login_date,INTERVAL $time_limit MINUTE) >= '".$current_date."'  AND 
+                    DATE_ADD(login_date, INTERVAL $time_limit MINUTE) >= '".$current_date."'  AND 
                     u.user_id =  $user_id 
-               LIMIT 1 ";
-	
+               LIMIT 1 ";	
 	$result = Database::query($query);
 	if (Database::num_rows($result)) {
 		return true;
 	}
-	return false;
-	
+	return false;	
 }
+
 /**
  * Gives a list of people online now (and in the last $valid minutes) 
  * @return  array       For each line, a list of user IDs and login dates, or FALSE on error or empty results
@@ -279,16 +277,16 @@ function who_is_online_count($time_limit = null, $friends = false) {
 				$query = "SELECT DISTINCT count(login_user_id) as count
 							FROM $track_online_table track
 							INNER JOIN $friend_user_table ON (friend_user_id = login_user_id)
-							WHERE track.access_url_id =  $access_url_id AND login_date >= '".$current_date."' AND friend_user_id <> '".api_get_user_id()."' AND relation_type='".USER_RELATION_TYPE_FRIEND."'  ";
+							WHERE track.access_url_id = $access_url_id AND login_date >= '".$current_date."' AND friend_user_id <> '".api_get_user_id()."' AND relation_type='".USER_RELATION_TYPE_FRIEND."'  ";
 			} else {
 				// all users online
-				$query = "SELECT count(login_id) as count FROM $track_online_table  track
-						  WHERE login_user_id <> 2 AND track.access_url_id =  $access_url_id AND login_date >= '$current_date' ";
+				$query = "SELECT count(login_id) as count FROM $track_online_table track
+						  WHERE login_user_id <> 2 AND track.access_url_id = $access_url_id AND login_date >= '$current_date' ";
 			}
 		}
 	}
     
-    //dev purposes show all users online
+    //Dev purposes show all users online
     
     /*$table_user = Database::get_main_table(TABLE_MAIN_USER);
     $query = "SELECT count(*)  as count FROM ".$table_user ."   ";*/
@@ -322,7 +320,7 @@ function who_is_online_in_this_course($from, $number_of_items, $uid, $time_limit
     $online_time 		= time() - $time_limit*60;
     $current_date		= api_get_utc_datetime($online_time);	
     $track_online_table = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_ONLINE);
-    $course_code         = Database::escape_string($course_code);
+    $course_code        = Database::escape_string($course_code);
     
     $from            = intval($from);
     $number_of_items = intval($number_of_items);
@@ -338,7 +336,7 @@ function who_is_online_in_this_course($from, $number_of_items, $uid, $time_limit
         $valid_date_time->sub(new DateInterval($diff));
 		$users_online = array();
 
-		while(list($login_user_id, $login_date) = Database::fetch_row($result)) {
+		while (list($login_user_id, $login_date) = Database::fetch_row($result)) {
             $user_login_date = new DateTime($login_date);            
 			if ($user_login_date > $valid_date_time) {
 				$users_online[] = $login_user_id;

+ 318 - 29
main/inc/lib/sessionmanager.lib.php

@@ -11,10 +11,35 @@
  * Code
  */
 
-class SessionManager {    
-	private function __construct() {
+class SessionManager {
+    
+    //See BT#4871
+    CONST SESSION_CHANGE_USER_REASON_SCHEDULE = 1;
+    CONST SESSION_CHANGE_USER_REASON_CLASSROOM = 2;
+    CONST SESSION_CHANGE_USER_REASON_LOCATION = 3;
+    CONST SESSION_CHANGE_USER_REASON_ENROLLMENT_ANNULATION = 4;    
+
+	private function __construct() {        
 	}
     
+    public static function get_session_info($session_id) {
+        $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
+        $tbl_user    = Database::get_main_table(TABLE_MAIN_USER);
+        
+        $sql = 'SELECT name, nbr_courses, nbr_users, nbr_classes, 
+                DATE_FORMAT(date_start,"%d-%m-%Y") as date_start, 
+                DATE_FORMAT(date_end,"%d-%m-%Y") as date_end, lastname, firstname, username, session_admin_id, 
+                nb_days_access_before_beginning, 
+                nb_days_access_after_end, 
+                session_category_id, 
+                visibility
+                FROM '.$tbl_session.' LEFT JOIN '.$tbl_user.' ON id_coach = user_id
+                WHERE '.$tbl_session.'.id='.$session_id;
+        $rs      = Database::query($sql);
+        $session = Database::store_result($rs);
+        return $session[0];
+    }
+    
     /**
      * Fetches a session from the database
      * @param   int     Session ID
@@ -218,12 +243,12 @@ class SessionManager {
      * Gets the admin session list callback of the admin/session_list.php page
      * @param array order and limit keys
      */
-	public static function get_sessions_admin($options) {
+	public static function get_sessions_admin($options = array()) {
 		$tbl_session            = Database::get_main_table(TABLE_MAIN_SESSION);
 		$tbl_session_category   = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);        
 		$tbl_user               = Database::get_main_table(TABLE_MAIN_USER);        
 
-		$where = 'WHERE 1=1 ';
+		$where = 'WHERE 1 = 1 ';
 		$user_id = api_get_user_id();
         
 		if (api_is_session_admin() && api_get_setting('allow_session_admins_to_manage_all_sessions') == 'false') {
@@ -273,9 +298,11 @@ class SessionManager {
 		if (!empty($options['where'])) {
 		   $query .= ' WHERE '.$options['where']; 
 		}
-
-		$query .= " ORDER BY ".$options['order']." LIMIT ".$options['limit'];
-
+        
+        if (!empty($options['order']) && !empty($options['limit'])) {
+            $query .= " ORDER BY ".$options['order']." LIMIT ".$options['limit'];
+        }
+        
 		$result = Database::query($query);
 		$formatted_sessions = array();
 		if (Database::num_rows($result)) {
@@ -648,6 +675,7 @@ class SessionManager {
 	                $enreg_user = Database::escape_string($enreg_user);
 					$insert_sql = "INSERT IGNORE INTO $tbl_session_rel_course_rel_user(id_session, course_code, id_user, visibility, status) VALUES('$id_session','$enreg_course','$enreg_user','$session_visibility', '0')";
 					Database::query($insert_sql);
+                    
 					if(Database::affected_rows()) {
 						$nbr_users++;
 					}
@@ -670,10 +698,14 @@ class SessionManager {
 		// Insert missing users into session
 		$nbr_users = 0;		
 		foreach ($user_list as $enreg_user) {
-	        $enreg_user = Database::escape_string($enreg_user);
-			$nbr_users++;
-			$insert_sql = "INSERT IGNORE INTO $tbl_session_rel_user (id_session, id_user) VALUES ('$id_session','$enreg_user')";
-			Database::query($insert_sql);
+	        $enreg_user = Database::escape_string($enreg_user);			
+			$insert_sql = "INSERT IGNORE INTO $tbl_session_rel_user (id_session, id_user) VALUES ('$id_session','$enreg_user')";			
+            Database::query($insert_sql);
+            
+            //Reset moved_to just in case
+            $update_sql = "UPDATE $tbl_session_rel_user SET moved_to = 0 , moved_status = 0, moved_at ='0000-00-00 00:00:00' WHERE  id_session = $id_session AND id_user = $enreg_user";                        
+            Database::query($update_sql);
+            $nbr_users++;
 		}
 
 		// update number of users in the session
@@ -686,6 +718,8 @@ class SessionManager {
             $update_sql = "UPDATE $tbl_session SET nbr_users= nbr_users + $nbr_users WHERE id='$id_session' ";
             Database::query($update_sql);           
         }
+
+
 	}
     
     function subscribe_users_to_session_course($user_list, $session_id, $course_code, $session_visibility = SESSION_VISIBLE_READ_ONLY ) {
@@ -724,13 +758,15 @@ class SessionManager {
 	/**
 	 * Unsubscribe user from session
 	 *
-	 * @param int Session id
-	 * @param int User id
-	 * @return bool True in case of success, false in case of error
+	 * @param int session id
+	 * @param int user id
+     * @param int reason of unsubscription see function get_session_change_user_reasons()
+	 * @return bool true in case of success, false in case of error
 	 */
 	public static function unsubscribe_user_from_session($session_id, $user_id) {
-		$session_id = (int)$session_id;
-		$user_id = (int)$user_id;
+		$session_id = intval($session_id);
+		$user_id = intval($user_id);
+        $reason_id = intval($reason_id);
 
 		$tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
 		$tbl_session_rel_course	= Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
@@ -742,26 +778,52 @@ class SessionManager {
 		$return = Database::affected_rows();
 
 		// Update number of users
-		$update_sql = "UPDATE $tbl_session SET nbr_users= nbr_users - $return WHERE id='$session_id' ";
+		$update_sql = "UPDATE $tbl_session SET nbr_users = nbr_users - $return WHERE id='$session_id' ";
 		Database::query($update_sql);
 
 		// Get the list of courses related to this session
 		$course_list = SessionManager::get_course_list_by_session_id($session_id);
-		if(!empty($course_list)) {
+        
+		if (!empty($course_list)) {
 			foreach($course_list as $course) {
 				$course_code = $course['code'];
 				// Delete user from course
 				Database::query("DELETE FROM $tbl_session_rel_course_rel_user WHERE id_session='$session_id' AND course_code='$course_code' AND id_user='$user_id'");
+                
 				if(Database::affected_rows()) {
 					// Update number of users in this relation
 					Database::query("UPDATE $tbl_session_rel_course SET nbr_users=nbr_users - 1 WHERE id_session='$session_id' AND course_code='$course_code'");
 				}
 			}
-		}
-
+		}  
 		return true;
-
 	}
+    
+    /**
+     * 
+     * @param int $session_id
+     * @param array user id list
+     * @param string $course_code
+     */
+    static function unsubscribe_user_from_course_session($session_id, $user_list, $course_code) {
+        $tbl_session_rel_course             = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
+        $tbl_session_rel_course_rel_user    = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
+
+        if (is_array($user_list) && count($user_list)>0 ) {
+            array_map('intval', $user_list);
+            $user_list = implode(',', $user_list);
+        }
+        $session_id = intval($session_id);
+        $course_code = Database::escape_string($course_code);
+        
+        if (!empty($user_list)) {
+            Database::query("DELETE FROM $tbl_session_rel_course_rel_user WHERE id_session='$session_id' AND course_code='".$course_code."' AND id_user IN($user_list)");
+            $nbr_affected_rows = Database::affected_rows();
+            Database::query("UPDATE $tbl_session_rel_course SET nbr_users=nbr_users-$nbr_affected_rows WHERE id_session='$session_id' AND course_code='".$course_code."'");
+        }        
+    }
+    
+    
 
 	 /** Subscribes courses to the given session and optionally (default) unsubscribes previous users
 	 * @author Carlos Vargas from existing code
@@ -1518,20 +1580,36 @@ class SessionManager {
     public static function get_users_by_session($id, $with_status = null) {
         if (empty($id)) {
             return array();
-        }
-        $id = intval($id);
+        }     
         $tbl_user               = Database::get_main_table(TABLE_MAIN_USER);
         $tbl_session_rel_user   = Database::get_main_table(TABLE_MAIN_SESSION_USER);
-
-        $sql = "SELECT $tbl_user.user_id, lastname, firstname, username
-                FROM $tbl_user INNER JOIN $tbl_session_rel_user
-                    ON $tbl_user.user_id = $tbl_session_rel_user.id_user 
-                    AND $tbl_session_rel_user.id_session = $id";
+        
+        $id = intval($id);
+        
+        if (api_is_multiple_url_enabled()) {
+            $url_id = api_get_current_access_url_id();   
+            $sql = "SELECT u.user_id, lastname, firstname, username, access_url_id, moved_to, moved_status, moved_at
+                FROM $tbl_user u
+                INNER JOIN $tbl_session_rel_user su
+                ON u.user_id = su.id_user AND su.relation_type<>".SESSION_RELATION_TYPE_RRHH."
+                LEFT OUTER JOIN $tbl_session_rel_user uu ON (uu.user_id = u.user_id)
+                WHERE su.id_session = $id AND (access_url_id = $url_id OR access_url_id is null )";
+        } else {
+            $sql = "SELECT u.user_id, lastname, firstname, username, moved_to, moved_status, moved_at
+                    FROM $tbl_user u INNER JOIN $tbl_session_rel_user su
+                    ON  u.user_id = su.id_user  AND 
+                        su.id_session = $id                                            
+                    ";
+        }
         
         if (isset($with_status) && $with_status != '') {
         	$with_status = intval($with_status);
         	$sql .= " WHERE relation_type = $with_status ";
         }
+        
+        $order_clause = api_sort_by_first_name() ? ' ORDER BY firstname, lastname' : ' ORDER BY lastname, firstname';
+    
+        $sql .= $order_clause;
                 
         $result = Database::query($sql);
         while ($row = Database::fetch_array($result,'ASSOC')) {
@@ -1570,7 +1648,7 @@ class SessionManager {
      * @param $session_id
      * @return unknown_type
      */
-    public static function get_user_status_in_session($user_id, $course_code, $session_id) {
+    public static function get_user_status_in_course_session($user_id, $course_code, $session_id) {
         $tbl_session_rel_course_rel_user    = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
         $tbl_user                           = Database::get_main_table(TABLE_MAIN_USER);        
         $sql = "SELECT session_rcru.status
@@ -1587,6 +1665,17 @@ class SessionManager {
         }
         return $status;
     }
+            
+    static function get_user_status_in_session($session_id, $user_id) {
+        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
+        $sql = "SELECT * FROM $tbl_session_rel_user WHERE id_user = $user_id AND id_session = $session_id";
+        $result = Database::query($sql);
+        if (Database::num_rows($result)) {
+            $result = Database::store_result($result, 'ASSOC');
+            return $result[0];
+        }
+        return array();
+    }
     
     function get_all_sessions_by_promotion($id) {
         $t = Database::get_main_table(TABLE_MAIN_SESSION);
@@ -1774,6 +1863,9 @@ class SessionManager {
     static function protect_session_edit($id) {
         api_protect_admin_script(true);
         $session_info = self::fetch($id);
+        if (empty($session_info)) {
+            api_not_allowed(true);
+        }
         if (!api_is_platform_admin() && api_get_setting('allow_session_admins_to_manage_all_sessions') != 'true') {
             if ($session_info['session_admin_id'] != api_get_user_id()) {
                 api_not_allowed(true);
@@ -1791,6 +1883,201 @@ class SessionManager {
         return Database::store_result($result);
     }
     
+    /**
+     *  @todo Add constatns in a DB table
+     */
+    static function get_session_change_user_reasons() {
+        return array (
+            self::SESSION_CHANGE_USER_REASON_SCHEDULE => get_lang('ScheduleChanged'),
+            self::SESSION_CHANGE_USER_REASON_CLASSROOM => get_lang('ClassRoomChanged'),
+            self::SESSION_CHANGE_USER_REASON_LOCATION => get_lang('LocationChanged'),
+            self::SESSION_CHANGE_USER_REASON_ENROLLMENT_ANNULATION => get_lang('EnrollmentAnnulation'),
+        );
+    }
+    
+    /** 
+     * Gets the reason name 
+     * @param int reason id
+     */
+    static function get_session_change_user_reason($id) {
+        $reasons = self::get_session_change_user_reasons();
+        return isset($reasons[$id]) ? $reasons[$id] : null;        
+    }
+    
+    /**
+     * Changes the user from one session to another due a reason
+     */
+    static function change_user_session($user_id, $old_session_id, $new_session_id, $reason_id) {
+        if (!empty($user_id) && !empty($old_session_id) && !empty($new_session_id)) {
+            $user_id = intval($user_id);
+            $old_session_id = intval($old_session_id);
+            $new_session_id = intval($new_session_id);
+            $reason_id = intval($reason_id);
+            
+            //self::unsubscribe_user_from_session($old_session_id, $user_id, $reason_id);             
+            
+            //$tbl_session_rel_course_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
+            $tbl_session_rel_course	= Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
+            $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
+            $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
+
+            // Update number of users
+            $update_sql = "UPDATE $tbl_session SET nbr_users = nbr_users - 1 WHERE id = '$old_session_id' ";
+            Database::query($update_sql);
+
+            // Get the list of courses related to this session
+            $course_list = SessionManager::get_course_list_by_session_id($old_session_id);
+            if (!empty($course_list)) {
+                foreach ($course_list as $course) {
+                    $course_code = $course['code'];
+                    // Delete user from course
+                    //Database::query("DELETE FROM $tbl_session_rel_course_rel_user WHERE id_session='$session_id' AND course_code='$course_code' AND id_user='$user_id'");
+                    //if (Database::affected_rows()) {
+                        // Update number of users in this relation
+                        $sql = "UPDATE $tbl_session_rel_course SET nbr_users = nbr_users - 1 WHERE id_session = '$old_session_id' AND course_code='$course_code'";                    
+                        Database::query($sql);
+                    //}
+                }
+            }
+            
+            //Deal with reasons
+            switch ($reason_id) {
+                case self::SESSION_CHANGE_USER_REASON_SCHEDULE:
+                case self::SESSION_CHANGE_USER_REASON_CLASSROOM:
+                case self::SESSION_CHANGE_USER_REASON_LOCATION:                       
+                    //Adding to the new session
+                    self::suscribe_users_to_session($new_session_id, array($user_id), null, false);
+                    
+                    //Setting move_to if session was provided
+                    $sql = "UPDATE $tbl_session_rel_user SET moved_to = '$new_session_id'
+                            WHERE id_session = '$old_session_id' AND id_user ='$user_id'";
+                    Database::query($sql);
+                    break;               
+                case self::SESSION_CHANGE_USER_REASON_ENROLLMENT_ANNULATION:
+                    UserManager::deactivate_users(array($user_id));
+                    break;
+            }
+            
+            $now = api_get_utc_datetime();            
+            //Setting the moved_status
+            $sql = "UPDATE $tbl_session_rel_user SET moved_status = $reason_id, moved_at = '$now'
+                    WHERE id_session = '$old_session_id' AND id_user ='$user_id'";            
+            Database::query($sql);
+            
+            return true;            
+        }
+        return;
+    }
+
+    
+    /**
+     * Get users inside a course session
+     */    
+    static function get_users_in_course_session($course_code, $id_session, $sort, $direction, $from = null, $limit = null) {
+        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
+        $tbl_session_rel_course_rel_user	= Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
+        $tbl_user                           = Database::get_main_table(TABLE_MAIN_USER);
+        
+        $course_code = Database::escape_string($course_code);
+        $id_session  = Database::escape_string($id_session);
+        $from = intval($from);
+        $limit = intval($limit);
+        
+        $is_western_name_order = api_is_western_name_order();
+                
+        //Select the number of users
+		$sql = " SELECT DISTINCT u.user_id,".($is_western_name_order ? 'u.firstname, u.lastname' : 'u.lastname, u.firstname').", u.username, scru.id_user as is_subscribed 
+                 FROM $tbl_session_rel_user sru INNER JOIN $tbl_user u ON (u.user_id=sru.id_user) 
+                      LEFT JOIN $tbl_session_rel_course_rel_user scru ON (u.user_id = scru.id_user AND  scru.course_code = '".$course_code."' )
+                 WHERE  sru.id_session = '$id_session' AND
+                        sru.moved_to = 0 AND sru.moved_status <> ".SessionManager::SESSION_CHANGE_USER_REASON_ENROLLMENT_ANNULATION." AND
+                        sru.relation_type<>".SESSION_RELATION_TYPE_RRHH;
+        $sql .= " ORDER BY $sort $direction ";
+        
+        if (!empty($from) && !empty($limit)) {
+            $sql .= " LIMIT $from, $limit";    
+        }        
+        
+		$result = Database::query($sql);
+        if (Database::num_rows($result)) {
+            return Database::store_result($result);
+        }
+        return false;
+    }
+    
+    static function get_count_users_in_course_session($course_code, $id_session) {
+        $tbl_session_rel_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
+        $tbl_session_rel_course_rel_user	= Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
+        
+        //Select the number of users
+		$sql = " SELECT count(*) FROM $tbl_session_rel_user sru, $tbl_session_rel_course_rel_user srcru
+				 WHERE  srcru.id_user = sru.id_user AND 
+                        srcru.id_session = sru.id_session AND 
+                        srcru.course_code = '".Database::escape_string($course_code)."' AND 
+                        srcru.id_session = '".intval($id_session)."'  AND
+                        (sru.moved_to = 0 AND sru.moved_status <> ".SessionManager::SESSION_CHANGE_USER_REASON_ENROLLMENT_ANNULATION.") AND
+                        sru.relation_type<>".SESSION_RELATION_TYPE_RRHH;
+
+		$result = Database::query($sql);
+        if (Database::num_rows($result)) {
+            return Database::result($result,0,0);
+        }
+        return 0;        
+    }
+    
+    /** 
+     * Get the list of coaches (only user ids)
+     * @param string course_code
+     * @param in session_id
+     * @return array
+     */
+    static function get_session_course_coaches($course_code, $session_id) {
+        $tbl_user							= Database::get_main_table(TABLE_MAIN_USER);
+        $tbl_session_rel_course_rel_user	= Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
+        
+        // Get coachs of the courses in session
+		$sql = "SELECT user.user_id FROM $tbl_session_rel_course_rel_user session_rcru, $tbl_user user
+				WHERE   session_rcru.id_user = user.user_id AND 
+                        session_rcru.id_session = '".intval($session_id)."' AND 
+                        session_rcru.course_code ='".Database::escape_string($course_code)."' AND 
+                        session_rcru.status=2";
+		$result = Database::query($sql);
+        return Database::store_result($result);        
+    }
+    
+    static function get_session_course_coaches_to_string($course_code, $session_id) {
+        $coaches = self::get_session_course_coaches($course_code, $session_id);
+        if (!empty($coaches)) {
+            $coach_list = array();            
+            foreach ($coaches as $coach_info) {
+                $user_info = api_get_user_info($coach_info['user_id']);
+                $coach_list[] = $user_info['complete_name'];
+            }            
+            if (!empty($coach_list)) {
+                return implode(', ', $coach_list);
+            }            
+        }        
+        return get_lang('None');
+    }
+    
+    static function delete_course_in_session($id_session, $course_code) {
+        $tbl_session_rel_course				= Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
+        $tbl_session_rel_course_rel_user	= Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
+        $tbl_session						= Database::get_main_table(TABLE_MAIN_SESSION);
+        
+        $id_session = intval($id_session);
+        $course_code = Database::escape_string($course_code);
+        
+        if (!empty($id_session) && !empty($course_code)) {
+
+            Database::query("DELETE FROM $tbl_session_rel_course WHERE id_session='$id_session' AND course_code = '$course_code'");
+            $nbr_affected_rows=Database::affected_rows();
+
+            Database::query("DELETE FROM $tbl_session_rel_course_rel_user WHERE id_session='$id_session' AND course_code = '$course_code'");
+            Database::query("UPDATE $tbl_session SET nbr_courses=nbr_courses-$nbr_affected_rows WHERE id='$id_session'");
+        }
+    }  
+
     static function get_sessions_by_user($user_id) {
        $session_categories = UserManager::get_sessions_by_category($user_id);
        $session_array = array();
@@ -1805,4 +2092,6 @@ class SessionManager {
        }
        return $session_array;
     }
+
+  
 }

+ 13 - 0
main/inc/lib/svg-edit/extensions/filesave.php

@@ -110,6 +110,19 @@ if (file_exists($saveDir.'/'.$filename.$i.'.'.$extension) && $currentTool=='docu
 }
 $documentPath = $saveDir.'/'.$drawFileName;
 
+//make a temporal file for get the file size
+	$tmpfname = tempnam("/tmp", "CTF");
+	$handle = fopen($tmpfname, "w");
+	fwrite($handle, $contents);
+	fclose($handle);
+	// Check if there is enough space in the course to save the file
+	if (!DocumentManager::enough_space(filesize($tmpfname), DocumentManager::get_course_quota())) {
+		unlink($tmpfname);
+		die(get_lang('UplNotEnoughSpace'));
+	}
+	//erase temporal file
+	unlink($tmpfname);
+
 //add new document to disk
 file_put_contents( $documentPath, $contents );
 

+ 33 - 33
main/inc/lib/usermanager.lib.php

@@ -390,14 +390,11 @@ class UserManager {
      * @return boolean 
      * @author Laurent Opprecht
      */
-    static function deactivate_users($ids = array())
-    {
+    static function deactivate_users($ids = array()) {
         if (empty($ids)) {
             return false;
         }
-
         $table_user = Database :: get_main_table(TABLE_MAIN_USER);
-
         $ids = is_array($ids) ? $ids : func_get_args();
         $ids = array_map('intval', $ids);
         $ids = implode(',', $ids);
@@ -1929,41 +1926,41 @@ class UserManager {
 	public static function get_sessions_by_category($user_id, $is_time_over = false) {
 		// Database Table Definitions		
 		$tbl_session				= Database :: get_main_table(TABLE_MAIN_SESSION);
-		$tbl_session_course_user	= Database :: get_main_table(TABLE_MAIN_SESSION_COURSE_USER);        
+		$tbl_session_course_user	= Database :: get_main_table(TABLE_MAIN_SESSION_COURSE_USER);      
+        $tbl_session_user           = Database :: get_main_table(TABLE_MAIN_SESSION_USER);
         $tbl_session_category       = Database :: get_main_table(TABLE_MAIN_SESSION_CATEGORY);
         
 		if ($user_id != strval(intval($user_id))) return array();
 
 		$categories = array();
         
-		// Get the list of sessions per user
         $now = api_get_utc_datetime();
         
+		// Get the list of sessions per user
 		$condition_date_end = "";
+        
 		if ($is_time_over) {
-			$condition_date_end = " AND (session.date_end < '$now' AND session.date_end != '0000-00-00')  ";
+			$condition_date_end = " AND ( (session.date_end < '$now' AND session.date_end != '0000-00-00') OR moved_to <> 0) ";
 		} else {
-			$condition_date_end = " AND (session.date_end >= '$now' OR session.date_end = '0000-00-00') ";
-		}
-        		
-        //ORDER BY session_category_id, date_start, date_end 
-        $sql = "SELECT DISTINCT session.id, 
-                                session.name, 
-                                session.date_start, 
-                                session.date_end, 
-                                session_category_id, 
+			$condition_date_end = " AND (session.date_end >= '$now' OR session.date_end = '0000-00-00') AND moved_to = 0 ";
+		}
+
+        $sql = "SELECT DISTINCT session.id, session.name, session.date_start, session.date_end, session_category_id, 
                                 session_category.name as session_category_name,
                                 session_category.date_start session_category_date_start,
                                 session_category.date_end session_category_date_end,
-                                nb_days_access_before_beginning
+                                nb_days_access_before_beginning,
+                                moved_to,
+                                moved_status
                                 
-                              FROM $tbl_session as session LEFT JOIN $tbl_session_category session_category ON (session_category_id = session_category.id) 
-                                    INNER JOIN $tbl_session_course_user as session_rel_course_user ON (session_rel_course_user.id_session = session.id)                             
-                              WHERE (
-                                        session_rel_course_user.id_user = $user_id OR session.id_coach = $user_id
-                                    )  $condition_date_end
-                              ORDER BY session_category_name, name";
-        
+                FROM $tbl_session as session LEFT JOIN $tbl_session_category session_category ON (session_category_id = session_category.id) 
+                      INNER JOIN $tbl_session_course_user as scu ON (scu.id_session = session.id)
+                      INNER JOIN $tbl_session_user su ON su.id_session = session.id AND su.id_user = scu.id_user
+                WHERE (
+                         scu.id_user = $user_id OR session.id_coach = $user_id
+                      )  $condition_date_end
+                ORDER BY session_category_name, name";
+        //var_dump($sql);
         $result = Database::query($sql);
         if (Database::num_rows($result) > 0) {
             while ($row = Database::fetch_array($result)) {
@@ -1979,6 +1976,9 @@ class UserManager {
                 $categories[$row['session_category_id']]['sessions'][$row['id']]['nb_days_access_before_beginning']     = $row['nb_days_access_before_beginning'];
                 $categories[$row['session_category_id']]['sessions'][$row['id']]['courses']         = UserManager::get_courses_list_by_session($user_id, $row['id']);
                 
+                $categories[$row['session_category_id']]['sessions'][$row['id']]['moved_to']         = $row['moved_to'];
+                $categories[$row['session_category_id']]['sessions'][$row['id']]['moved_status']     = $row['moved_status'];
+                
             }
         }
 		return $categories;
@@ -2017,10 +2017,10 @@ class UserManager {
 
 		$personal_course_list_sql = "SELECT course.code, course_rel_user.status course_rel_status, course_rel_user.sort sort, course_rel_user.user_course_cat user_course_cat		                                      
 			                         FROM ".$tbl_course_user." course_rel_user
-				                     LEFT JOIN ".$tbl_course." course
-					                 ON course.code = course_rel_user.course_code
-				                     LEFT JOIN ".$tbl_user_course_category." user_course_category
-					                 ON course_rel_user.user_course_cat = user_course_category.id
+                                            LEFT JOIN ".$tbl_course." course
+                                            ON course.code = course_rel_user.course_code
+                                            LEFT JOIN ".$tbl_user_course_category." user_course_category
+                                            ON course_rel_user.user_course_cat = user_course_category.id
 				                     $join_access_url
 			                         WHERE  course_rel_user.user_id = '".$user_id."' AND 
 			                                course_rel_user.relation_type <> ".COURSE_RELATION_TYPE_RRHH."  $where_access_url
@@ -2138,13 +2138,14 @@ class UserManager {
 				$where_access_url=" AND access_url_id = $access_url_id AND url_rel_session.session_id = $session_id ";
 			}
 		}
-		
+
+		// variable initialisation
+		$personal_course_list_sql = '';
 		$personal_course_list = array();
 		$courses = array();
 
 		// this query is very similar to the above query, but it will check the session_rel_course_user table if there are courses registered to our user or not
-		$personal_course_list_sql = "SELECT DISTINCT scu.course_code as code 
-                                    FROM $tbl_session_course_user as scu $join_access_url
+		$personal_course_list_sql = "SELECT DISTINCT scu.course_code as code FROM $tbl_session_course_user as scu $join_access_url
 									WHERE scu.id_user = $user_id AND scu.id_session = $session_id $where_access_url
 									ORDER BY code";
         
@@ -2161,8 +2162,7 @@ class UserManager {
 		}
 
 		if (api_is_allowed_to_create_course()) {
-			$personal_course_list_sql = "SELECT DISTINCT scu.course_code as code 
-                                        FROM $tbl_session_course_user as scu, $tbl_session as s $join_access_url
+			$personal_course_list_sql = "SELECT DISTINCT scu.course_code as code FROM $tbl_session_course_user as scu, $tbl_session as s $join_access_url
 										WHERE s.id = $session_id AND scu.id_session = s.id AND ((scu.id_user=$user_id AND scu.status=2) OR s.id_coach = $user_id)
 										$where_access_url
 										ORDER BY code";						            

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

@@ -857,7 +857,7 @@ class IndexManager {
 	 *  
 	 * */
 	function return_courses_and_sessions($user_id) {		       
-        $session_categories = array();        
+        $session_categories = array();     
         $load_history = (isset($_GET['history']) && intval($_GET['history']) == 1) ? true : false;
 		
 		if ($load_history) {
@@ -954,7 +954,11 @@ class IndexManager {
                             }
 
                             $params['title'] = $session_link;
-                            $params['subtitle'] = $extra_info;                            
+                            
+                            $moved_status = SessionManager::get_session_change_user_reason($session['moved_status']);
+                            $moved_status = isset($moved_status) && !empty($moved_status) ? ' ('.$moved_status.')' : null;
+                            
+                            $params['subtitle'] = $extra_info.$moved_status;
 
                             $params['right_actions'] = '';
                             if (api_is_platform_admin()) {

+ 13 - 0
main/inc/lib/wami-recorder/record_document.php

@@ -65,6 +65,19 @@ if (file_exists($saveDir.'/'.$waminame_noex.'.'.$ext)){
 
 $documentPath = $saveDir.'/'.$waminame_to_save;
 
+//make a temporal file for get the file size
+	$tmpfname = tempnam("/tmp", "CTF");
+	$handle = fopen($tmpfname, "w");
+	fwrite($handle, $content);
+	fclose($handle);
+	// Check if there is enough space in the course to save the file
+	if (!DocumentManager::enough_space(filesize($tmpfname), DocumentManager::get_course_quota())) {
+		unlink($tmpfname);
+		die(get_lang('UplNotEnoughSpace'));
+	}
+	//erase temporal file
+	unlink($tmpfname);
+
 
 //add to disk
 $fh = fopen($documentPath, 'w') or die("can't open file");

+ 12 - 11
main/inc/local.inc.php

@@ -883,7 +883,7 @@ if ((isset($uidReset) && $uidReset) || (isset($cidReset) && $cidReset)) {
                 // this user has no status related to this course
                 // The user is subscribed in a session? The user is a Session coach a Session admin ?
 
-                $tbl_session             = Database :: get_main_table(TABLE_MAIN_SESSION);
+                $tbl_session             = Database :: get_main_table(TABLE_MAIN_SESSION);                
                 $tbl_session_course      = Database :: get_main_table(TABLE_MAIN_SESSION_COURSE);
                 $tbl_session_course_user = Database :: get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
 
@@ -894,7 +894,8 @@ if ((isset($uidReset) && $uidReset) || (isset($cidReset) && $cidReset)) {
                                session_rcru.course_code = '$_cid' AND
                                session_rcru.id_user     = '$user_id' AND
                                session_rcru.id_session  = $session_id AND
-                               session_rcru.status      = 2";
+                               session_rcru.status      = 2                               
+                        ";
 
                 $result = Database::query($sql);
                 $row     = Database::store_result($result);
@@ -909,16 +910,16 @@ if ((isset($uidReset) && $uidReset) || (isset($cidReset) && $cidReset)) {
                     $is_sessionAdmin     = true;
                 } else {
                     //Im a coach or a student?
-                    $sql = "SELECT id_user, status FROM ".$tbl_session_course_user."
+                    $sql = "SELECT cu.id_user, cu.status FROM $tbl_session_course_user cu                             
                             WHERE   course_code = '$_cid' AND
-                                    id_user     = '".$user_id."' AND
-                                    id_session  = '".$session_id."'
+                                    cu.id_user     = '".$user_id."' AND
+                                    cu.id_session  = '".$session_id."'
                             LIMIT 1";
                     $result = Database::query($sql);
 
                     if (Database::num_rows($result)) {
                         $row = Database::fetch_array($result, 'ASSOC');
-
+                        
                         $session_course_status = $row['status'];
 
                         switch ($session_course_status) {
@@ -936,13 +937,14 @@ if ((isset($uidReset) && $uidReset) || (isset($cidReset) && $cidReset)) {
                                 }
                                 Session::write('_courseUser', $_courseUser);
                                 break;
-                            case '0': //student
+                            case '0': //Student
                                 $_courseUser['role'] = '';
                                 $is_courseMember     = true;
                                 $is_courseTutor      = false;
                                 $is_courseAdmin      = false;
                                 $is_courseCoach      = false;
                                 $is_sessionAdmin     = false;
+                      
                                 Session::write('_courseUser', $_courseUser);
                                 break;
                             default:
@@ -1016,8 +1018,8 @@ if ((isset($uidReset) && $uidReset) || (isset($cidReset) && $cidReset)) {
         if ($session_id != 0) {
             if (!$is_platformAdmin) {
                 // admin is not affected to the invisible session mode
-                $session_visibility = api_get_session_visibility($session_id);
-
+                $session_visibility = api_get_session_visibility($session_id);                
+                
                 switch ($session_visibility) {
                     case SESSION_INVISIBLE:
                         $is_allowed_in_course = false;
@@ -1104,5 +1106,4 @@ if (isset($_cid)) {
     Database::query($sql);
 }
 
-Redirect::session_request_uri($logging_in, $user_id);
-
+Redirect::session_request_uri($logging_in, $user_id);

+ 5 - 1
main/install/db_main.sql

@@ -514,8 +514,11 @@ CREATE TABLE IF NOT EXISTS session_rel_course_rel_user (
 DROP TABLE IF EXISTS session_rel_user;
 CREATE TABLE IF NOT EXISTS session_rel_user (
   id_session mediumint unsigned NOT NULL default '0',
-  id_user mediumint unsigned NOT NULL default '0',
+  id_user int unsigned NOT NULL default '0',
   relation_type int default 0,
+  moved_to int default 0,
+  moved_status int default 0,
+  moved_at datetime NOT NULL default '0000-00-00 00:00:00',
   PRIMARY KEY (id_session, id_user, relation_type)
 );
 
@@ -2826,6 +2829,7 @@ CREATE TABLE IF NOT EXISTS notification (
 	dest_user_id INT NOT NULL,
  	dest_mail 	CHAR(255),
  	title 		CHAR(255),
+    sender_id   INT NOT NULL DEFAULT 0,
  	content 	CHAR(255),
  	send_freq 	SMALLINT DEFAULT 1,
  	created_at 	DATETIME NOT NULL,

+ 2 - 1
main/install/db_stats.sql

@@ -287,6 +287,7 @@ ALTER TABLE track_e_access ADD INDEX (access_session_id);
 
 ALTER TABLE track_e_online ADD INDEX (course);
 ALTER TABLE track_e_online ADD INDEX (session_id);
+ALTER TABLE track_e_online ADD INDEX idx_trackonline_uat (login_user_id, access_url_id, login_date);
 
 ALTER TABLE track_e_item_property ADD INDEX (course_id, item_property_id, session_id);
 ALTER TABLE track_e_downloads ADD INDEX (down_session_id);  
@@ -326,4 +327,4 @@ CREATE TABLE track_e_attempt_coeff (
     id int unsigned not null auto_increment primary key,
     attempt_id INT NOT NULL, 
     marks_coeff float(6,2)
-);
+);

+ 2 - 1
main/install/install_db.inc.php

@@ -77,7 +77,8 @@ if (!defined('CLI_INSTALLATION')) {
     }	
 	//Create database
 	if ($create_database) {
-		$sql = "CREATE DATABASE IF NOT EXISTS `$mysqlMainDb`";
+        $charset_clause = ' DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci';
+		$sql = "CREATE DATABASE IF NOT EXISTS `$mysqlMainDb` $charset_clause";   
 		Database::query($sql) or die(Database::error());
 	}	
 }

+ 47 - 0
main/install/migrate-db-1.9.0-1.10.0-pre.sql

@@ -0,0 +1,47 @@
+-- This script updates the databases structure before migrating the data from
+-- version 1.9.0 (or version 1.9.2) to version 1.10.0
+-- it is intended as a standalone script, however, because of the multiple
+-- databases related difficulties, it should be parsed by a PHP script in
+-- order to connect to and update the right databases.
+-- There is one line per query, allowing the PHP function file() to read
+-- all lines separately into an array. The xxMAINxx-type markers are there
+-- to tell the PHP script which database we're talking about.
+-- By always using the keyword "TABLE" in the queries, we should be able
+-- to retrieve and modify the table name from the PHP script if needed, which
+-- will allow us to deal with the unique-database-type installations
+--
+-- This first part is for the main database
+
+-- xxMAINxx
+
+-- Optimize tracking query very often queried on busy campuses
+ALTER TABLE track_e_online ADD INDEX idx_trackonline_uat (login_user_id, access_url_id, login_date);
+
+-- Do not move this query
+
+-- Main changes
+
+-- Courses changes c_XXX
+
+ALTER TABLE c_lp_item ADD INDEX idx_c_lp_item_cid_lp_id (c_id, lp_id);
+ALTER TABLE c_lp_item_view ADD INDEX idx_c_lp_item_view_cid_lp_view_id_lp_item_id(c_id, lp_view_id, lp_item_id);
+ALTER TABLE c_tool_intro MODIFY COLUMN intro_text MEDIUMTEXT NOT NULL;
+ALTER TABLE notification ADD COLUMN sender_id INT NOT NULL DEFAULT 0;
+
+ALTER TABLE session_rel_user ADD COLUMN moved_to INT NOT NULL DEFAULT 0;
+ALTER TABLE session_rel_user ADD COLUMN moved_status INT NOT NULL DEFAULT 0;
+ALTER TABLE session_rel_user ADD COLUMN moved_at datetime NOT NULL default '0000-00-00 00:00:00';
+
+
+-- Normal tables
+
+UPDATE settings_current SET selected_value = '1.10.xx' WHERE variable = 'chamilo_database_version';
+
+-- xxSTATSxx
+-- All stats DB changes will be added in the "main zone"
+
+-- xxUSERxx
+-- All user DB changes will be added in the "main zone"
+
+-- xxCOURSExx
+-- All course DB changes will be added in the "main zone"

+ 115 - 0
main/install/update-db-1.9.0-1.10.0.inc.php

@@ -0,0 +1,115 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+/**
+ * Chamilo LMS
+ *
+ * Update the Chamilo database from an older Chamilo version
+ * Notice : This script has to be included by index.php
+ * or update_courses.php (deprecated).
+ *
+ * @package chamilo.install
+ * @todo
+ * - conditional changing of tables. Currently we execute for example
+ * ALTER TABLE $dbNameForm.cours
+ * instructions without checking wether this is necessary.
+ * - reorganise code into functions
+ * @todo use database library
+ */
+Log::notice('Entering file');
+
+$old_file_version = '1.9.0';
+$new_file_version = '1.10.0';
+
+// Check if we come from index.php or update_courses.php - otherwise display error msg
+if (defined('SYSTEM_INSTALLATION')) {
+
+    // Check if the current Chamilo install is eligible for update
+    if (!file_exists('../inc/conf/configuration.php')) {
+        echo '<strong>'.get_lang('Error').' !</strong> Chamilo '.implode('|', $updateFromVersion).' '.get_lang('HasNotBeenFound').'.<br /><br />
+                                '.get_lang('PleasGoBackToStep1').'.
+                                <p><button type="submit" class="back" name="step1" value="&lt; '.get_lang('Back').'">'.get_lang('Back').'</button></p>
+                                </td></tr></table></form></body></html>';
+        exit ();
+    }
+
+    $_configuration['db_glue'] = get_config_param('dbGlu');
+    
+    if ($singleDbForm) {
+        $_configuration['table_prefix'] 	= get_config_param('courseTablePrefix');
+        $_configuration['main_database'] 	= get_config_param('mainDbName');
+        $_configuration['db_prefix'] 		= get_config_param('dbNamePrefix');
+    }
+
+	$dbScormForm = preg_replace('/[^a-zA-Z0-9_\-]/', '', $dbScormForm);
+
+	if (!empty($dbPrefixForm) && strpos($dbScormForm, $dbPrefixForm) !== 0) {
+        $dbScormForm = $dbPrefixForm.$dbScormForm;
+    }
+
+    if (empty($dbScormForm) || $dbScormForm == 'mysql' || $dbScormForm == $dbPrefixForm) {
+        $dbScormForm = $dbPrefixForm.'scorm';
+    }
+
+    /*   Normal upgrade procedure: start by updating main, statistic, user databases */
+
+    // If this script has been included by index.php, not update_courses.php, so
+    // that we want to change the main databases as well...
+    $only_test = false;
+    if (defined('SYSTEM_INSTALLATION')) {
+        
+        if ($singleDbForm) {
+            $dbStatsForm = $dbNameForm;
+            $dbScormForm = $dbNameForm;
+            $dbUserForm  = $dbNameForm;
+        }        
+        /**
+         * Update the databases "pre" migration
+         */
+        include '../lang/english/create_course.inc.php';
+        
+        if ($languageForm != 'english') {
+            // languageForm has been escaped in index.php
+            include '../lang/'.$languageForm.'/create_course.inc.php';
+        }
+        
+        // Get the main queries list (m_q_list)
+        $m_q_list = get_sql_file_contents('migrate-db-'.$old_file_version.'-'.$new_file_version.'-pre.sql', 'main');
+        
+        if (count($m_q_list) > 0) {
+            // Now use the $m_q_list
+            /**
+             * We connect to the right DB first to make sure we can use the queries
+             * without a database name
+             */
+            if (strlen($dbNameForm) > 40) {
+                Log::error('Database name '.$dbNameForm.' is too long, skipping');
+            } elseif (!in_array($dbNameForm, $dblist)) {
+                Log::error('Database '.$dbNameForm.' was not found, skipping');
+            } else {
+                iDatabase::select_db($dbNameForm);
+                foreach ($m_q_list as $query){
+                    if ($only_test) {
+                        Log::notice("iDatabase::query($dbNameForm,$query)");
+                    } else {
+                        $res = iDatabase::query($query);
+                        if ($res === false) {
+                        	Log::error('Error in '.$query.': '.iDatabase::error());
+                        }
+                    }
+                }
+            }
+        }
+        
+        if (INSTALL_TYPE_UPDATE == 'update') {
+            
+            //Migrate classes to the new classes (usergroups)
+            
+        }
+        
+    }    
+    
+} else {
+    echo 'You are not allowed here !' . __FILE__;
+}
+

+ 2 - 1
main/messages/new_message.php

@@ -241,7 +241,8 @@ function manage_form($default, $select_from_user_list = null, $sent_to = null) {
 						if (is_string($res)) {
 							$html .= Display::return_message($res, 'error');
 						} else {
-							$html .= MessageManager::display_success_message($user);
+                            $user_info = api_get_user_info($user);
+							$html .= Display::return_message(get_lang('MessageSentTo')." &nbsp;<b>".$user_info['complete_name']."</b>", 'confirmation', false);
 						}
 					}
 				}       

+ 3 - 26
main/user/subscribe_user.php

@@ -16,7 +16,6 @@ $current_course_tool  = TOOL_USER;
 // the section (for the tabs)
 $this_section = SECTION_COURSES;
 
-
 // notice for unauthorized people.
 api_protect_course_script(true);
 
@@ -40,9 +39,6 @@ if ($_GET['keyword']) {
 
 Display :: display_header($tool_name, "User");
 
-// api_display_tool_title($tool_name);
-
-
 // Build search-form
 echo '<div class="actions">';
 
@@ -77,13 +73,11 @@ $list_not_register_user='';
 
 if (isset ($_REQUEST['register'])) {
 	if (isset($_REQUEST['type']) && $_REQUEST['type']=='teacher') {
-
 		if (!empty($current_session_id)) {
 			$result_simple_sub = SessionManager::set_coach_to_course_session(intval($_REQUEST['user_id']), $current_session_id, $_course['sysCode']);
 		} else {
 			$result_simple_sub = CourseManager :: subscribe_user(intval($_REQUEST['user_id']), $_course['sysCode'],COURSEMANAGER);
 		}
-
 	} else {
 		$result_simple_sub=CourseManager :: subscribe_user(intval($_REQUEST['user_id']), $_course['sysCode']);
 	}
@@ -180,12 +174,9 @@ if (!empty($_SESSION['session_user_name'])) {
 	unset($_SESSION['session_user_name']);
 }
 
-
-
 $is_western_name_order = api_is_western_name_order();
 $sort_by_first_name = api_sort_by_first_name();
 
-
 // Build table
 $table = new SortableTable('subscribe_users', 'get_number_of_users', 'get_user_data', ($is_western_name_order xor $sort_by_first_name) ? 3 : 2);
 $parameters['keyword'] = Security::remove_XSS($_REQUEST['keyword']);
@@ -359,20 +350,7 @@ function get_number_of_users() {
     if ($res) {	
 	   $row = Database::fetch_row($res);
 	   $count_user = $row[0];	   
-	}
-	
-	/* @todo seems not to be used
-	// we add 1 for every additional user (a user where the keyword matches one of the additional profile fields)
-	// that is not yet in the course and not yet in the search result
-	if (isset ($_REQUEST['keyword']) AND api_get_setting('ProfilingFilterAddingUsers') == 'true') {
-		foreach($additional_users as $additional_user_key=>$additional_user_value){
-			if (!in_array($additional_user_key,$users) AND !in_array($additional_user_key,$users_of_course)){
-				$result++;
-			}
-		}
-	}
-    */
-    
+	}   
 	return $count_user;
 }
 /**
@@ -413,8 +391,7 @@ function get_user_data($from, $number_of_items, $column, $direction) {
                 u.active               AS col4,
                 u.user_id              AS col5";
     }
-
-	
+    
 	if (isset($_REQUEST['type']) && $_REQUEST['type']=='teacher') {
 		// adding a teacher through a session
 		if (!empty($_SESSION["id_session"])) {
@@ -640,7 +617,7 @@ function active_filter($active, $url_params, $row) {
 		$image='error';
 	}
 	if ($row['0']<>$_user['user_id']) { // you cannot lock yourself out otherwise you could disable all the accounts including your own => everybody is locked out and nobody can change it anymore.
-		$result = '<center>'.Display::return_icon($image.'.png',  get_lang(ucfirst($action)), array('border'=>'0', 'style'=>'vertical-align: middle;') , 16).'</center>';
+		$result = Display::return_icon($image.'.png',  get_lang(ucfirst($action)), array('border'=>'0', 'style'=>'vertical-align: middle;') , 16);
 	}
 	return $result;
 }

+ 82 - 110
main/user/user.php

@@ -48,7 +48,7 @@ if (!api_is_platform_admin(true)) {
 /*
 	Constants and variables
 */
-$course_code            = Database::escape_string(api_get_course_id());
+$course_code            = api_get_course_id();
 $session_id             = api_get_session_id();
 $is_western_name_order 	= api_is_western_name_order();
 $sort_by_first_name 	= api_sort_by_first_name();
@@ -134,13 +134,17 @@ if (api_is_allowed_to_edit(null, true)) {
 				
                 if (api_get_session_id()) {	
                     $table_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
+                    $table_session_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
                     $sql_query = "SELECT DISTINCT user.user_id, ".($is_western_name_order ? "user.firstname, user.lastname" : "user.lastname, user.firstname").",  user.username, $select_email_condition phone, user.official_code, active $legal
-                                  FROM $table_session_course_user as session_course_user, $table_users as user ";
+                                  FROM $table_session_course_user as session_course_user, $table_users as user,  $table_session_user as su";
                     if ($_configuration['multiple_access_urls']) {
                         $sql_query .= ' , '.Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER).' au ';
                     }
-                    $sql_query .=" WHERE course_code = '$course_code' AND session_course_user.id_user = user.user_id ";
-                    $sql_query .= ' AND id_session = '.$session_id;							
+                    $sql_query .=" WHERE course_code = '$course_code' AND 
+                                        session_course_user.id_user = user.user_id AND 
+                                        su.id_user =  session_course_user.id_user AND session_course_user.id_session = su.id_session AND
+                                        su.moved_to = 0 AND su.moved_status <> ".SessionManager::SESSION_CHANGE_USER_REASON_ENROLLMENT_ANNULATION."  AND
+                                        session_course_user.id_session = $session_id";
 
                     if ($_configuration['multiple_access_urls']) {				
                         $sql_query .= " AND user.user_id = au.user_id AND access_url_id =  $current_access_url_id  ";
@@ -343,7 +347,6 @@ if (api_is_allowed_to_edit(null, true)) {
     }
 }
 
-
 /*		FUNCTIONS	*/
 
 function display_user_search_form() {
@@ -354,10 +357,6 @@ function display_user_search_form() {
 	echo '</form>';	
 }
 
-if (!$is_allowed_in_course) {
-	api_not_allowed(true);
-}
-
 /*	Header */
 if ($origin != 'learnpath') {
 	if (isset($_GET['keyword']) && !empty($_GET['keyword'])) {
@@ -416,31 +415,10 @@ if ( api_is_allowed_to_edit(null, true)) {
 /**
  *  * Get the users to display on the current page.
  */
-function get_number_of_users() {
-	$counter = 0;
-	if (!empty($_SESSION["id_session"])){
-		$a_course_users = CourseManager :: get_user_list_from_course_code($_SESSION['_course']['id'], $_SESSION['id_session']);
-
-	} else {
-		$a_course_users = CourseManager :: get_user_list_from_course_code($_SESSION['_course']['id'], 0);
-	}
-	foreach ($a_course_users as $user_id => $o_course_user) {
-		if ((isset($_GET['keyword']) && search_keyword($o_course_user['firstname'], $o_course_user['lastname'], $o_course_user['username'], $o_course_user['official_code'], $_GET['keyword'])) || !isset($_GET['keyword']) || empty($_GET['keyword'])) {
-			$counter++;
-		}
-	}
-	return $counter;
-}
-
-function search_keyword($firstname, $lastname, $username, $official_code, $keyword) {
-	if (api_strripos($firstname, $keyword) !== false || api_strripos($lastname, $keyword) !== false || api_strripos($username, $keyword) !== false || api_strripos($official_code, $keyword) !== false) {
-		return true;
-	} else {
-		return false;
-	}
+function get_number_of_users() {	    
+    return CourseManager::get_users_count_in_course(api_get_course_id(), api_get_session_id(), null, null, null, $_GET['keyword']);    
 }
 
-
 /**
  * Get the users to display on the current page.
  */
@@ -453,9 +431,7 @@ function get_user_data($from, $number_of_items, $column, $direction) {
 	$a_users = array();
 
 	// limit
-	if (!isset($_GET['keyword']) || empty($_GET['keyword'])) {
-		$limit = 'LIMIT '.intval($from).','.intval($number_of_items);
-	}
+	$limit = 'LIMIT '.intval($from).','.intval($number_of_items);	
 
 	if (!in_array($direction, array('ASC', 'DESC'))) {
 		$direction = 'ASC';
@@ -494,86 +470,83 @@ function get_user_data($from, $number_of_items, $column, $direction) {
     $session_id = api_get_session_id();
     $course_code = api_get_course_id();
     
-    $a_course_users = CourseManager :: get_user_list_from_course_code($course_code, $session_id, $limit, $order_by);
+    $a_course_users = CourseManager :: get_user_list_from_course_code($course_code, $session_id, $limit, $order_by, null, $_REQUEST['keyword']);
 
 	foreach ($a_course_users as $user_id => $o_course_user) {
-		if ((isset($_GET['keyword']) && search_keyword($o_course_user['firstname'], $o_course_user['lastname'], $o_course_user['username'], $o_course_user['official_code'], $_GET['keyword'])) || !isset($_GET['keyword']) || empty($_GET['keyword'])) {
-
-			$groups_name = GroupManager :: get_user_group_name($user_id);
-			$temp = array();
-			if (api_is_allowed_to_edit(null, true)) {
-				//if (api_get_setting('allow_user_course_subscription_by_course_admin') == 'true') {
-                	$temp[] = $user_id;
-                //}
-				$image_path = UserManager::get_user_picture_path_by_id($user_id, 'web', false, true);
-				$user_profile = UserManager::get_picture_user($user_id, $image_path['file'], 22, USER_IMAGE_SIZE_SMALL, ' width="22" height="22" ');
-				if (!api_is_anonymous()) {
-					$photo = '<a href="userInfo.php?'.api_get_cidreq().'&origin='.$origin.'&amp;uInfo='.$user_id.'" title="'.get_lang('Info').'"  ><img src="'.$user_profile['file'].'" '.$user_profile['style'].' alt="'.api_get_person_name($o_course_user['firstname'], $o_course_user['lastname']).'"  title="'.api_get_person_name($o_course_user['firstname'], $o_course_user['lastname']).'" /></a>';
-				} else {
-					$photo = '<img src="'.$user_profile['file'].'" '.$user_profile['style'].' alt="'.api_get_person_name($o_course_user['firstname'], $o_course_user['lastname']).'" title="'.api_get_person_name($o_course_user['firstname'], $o_course_user['lastname']).'" />';
-				}
-                
-				$temp[] = $photo;
-				$temp[] = $o_course_user['official_code'];
-				
-				if ($is_western_name_order) {
-					$temp[] = $o_course_user['firstname'];
-					$temp[] = $o_course_user['lastname'];
-				} else {
-					$temp[] = $o_course_user['lastname'];
-					$temp[] = $o_course_user['firstname'];
-				}
+        $groups_name = GroupManager :: get_user_group_name($user_id);
+        $temp = array();
+        if (api_is_allowed_to_edit(null, true)) {
+            //if (api_get_setting('allow_user_course_subscription_by_course_admin') == 'true') {
+                $temp[] = $user_id;
+            //}
+            $image_path = UserManager::get_user_picture_path_by_id($user_id, 'web', false, true);
+            $user_profile = UserManager::get_picture_user($user_id, $image_path['file'], 22, USER_IMAGE_SIZE_SMALL, ' width="22" height="22" ');
+            if (!api_is_anonymous()) {
+                $photo = '<a href="userInfo.php?'.api_get_cidreq().'&origin='.$origin.'&amp;uInfo='.$user_id.'" title="'.get_lang('Info').'"  ><img src="'.$user_profile['file'].'" '.$user_profile['style'].' alt="'.api_get_person_name($o_course_user['firstname'], $o_course_user['lastname']).'"  title="'.api_get_person_name($o_course_user['firstname'], $o_course_user['lastname']).'" /></a>';
+            } else {
+                $photo = '<img src="'.$user_profile['file'].'" '.$user_profile['style'].' alt="'.api_get_person_name($o_course_user['firstname'], $o_course_user['lastname']).'" title="'.api_get_person_name($o_course_user['firstname'], $o_course_user['lastname']).'" />';
+            }
 
-                $temp[] = $o_course_user['username'];                
-				$temp[] = isset($o_course_user['role']) ? $o_course_user['role'] : null; //Description
-				$temp[] = implode(', ', $groups_name); //Group				
+            $temp[] = $photo;
+            $temp[] = $o_course_user['official_code'];
 
-				// Status
-                $default_status = '-';
-				if ((isset($o_course_user['status_rel']) && $o_course_user['status_rel'] == 1) || (isset($o_course_user['status_session']) && $o_course_user['status_session'] == 2)) {
-					$default_status = get_lang('CourseManager');
-				} elseif (isset($o_course_user['tutor_id']) && $o_course_user['tutor_id'] == 1) {
-					$default_status = get_lang('Tutor');
-				}
-                $temp[] = $default_status;
-                
-                //Active
-				$temp[] = $o_course_user['active'];
-                
+            if ($is_western_name_order) {
+                $temp[] = $o_course_user['firstname'];
+                $temp[] = $o_course_user['lastname'];
+            } else {
+                $temp[] = $o_course_user['lastname'];
+                $temp[] = $o_course_user['firstname'];
+            }
+
+            $temp[] = $o_course_user['username'];                
+            $temp[] = isset($o_course_user['role']) ? $o_course_user['role'] : null; //Description
+            $temp[] = implode(', ', $groups_name); //Group				
+
+            // Status
+            $default_status = '-';
+            if ((isset($o_course_user['status_rel']) && $o_course_user['status_rel'] == 1) || (isset($o_course_user['status_session']) && $o_course_user['status_session'] == 2)) {
+                $default_status = get_lang('CourseManager');
+            } elseif (isset($o_course_user['tutor_id']) && $o_course_user['tutor_id'] == 1) {
+                $default_status = get_lang('Tutor');
+            }
+            $temp[] = $default_status;
+
+            //Active
+            $temp[] = $o_course_user['active'];
+
+            //User id for actions
+            $temp[] = $user_id;
+        } else {
+            $image_path = UserManager::get_user_picture_path_by_id($user_id, 'web', false, true);
+            $image_repository = $image_path['dir'];
+            $existing_image = $image_path['file'];
+            if (!api_is_anonymous()) {
+                $photo= '<a href="userInfo.php?'.api_get_cidreq().'&origin='.$origin.'&amp;uInfo='.$user_id.'" title="'.get_lang('Info').'"  ><img src="'.$image_repository.$existing_image.'" alt="'.api_get_person_name($o_course_user['firstname'], $o_course_user['lastname']).'"  width="22" height="22" title="'.api_get_person_name($o_course_user['firstname'], $o_course_user['lastname']).'" /></a>';
+            } else {
+                $photo= '<img src="'.$image_repository.$existing_image.'" alt="'.api_get_person_name($o_course_user['firstname'], $o_course_user['lastname']).'"  width="22" height="22" title="'.api_get_person_name($o_course_user['firstname'], $o_course_user['lastname']).'" />';
+            }
+            $temp[] = $user_id;
+            $temp[] = $photo;
+            $temp[] = $o_course_user['official_code'];
+
+            if ($is_western_name_order) {
+                $temp[] = $o_course_user['firstname'];
+                $temp[] = $o_course_user['lastname'];
+            } else {
+                $temp[] = $o_course_user['lastname'];
+                $temp[] = $o_course_user['firstname'];
+            }				
+            $temp[] = $o_course_user['username'];
+            $temp[] = $o_course_user['role'];
+            $temp[] = implode(', ', $groups_name);//Group
+
+            if ($course_info['unsubscribe'] == 1) {
                 //User id for actions
-				$temp[] = $user_id;
-			} else {
-				$image_path = UserManager::get_user_picture_path_by_id($user_id, 'web', false, true);
-				$image_repository = $image_path['dir'];
-				$existing_image = $image_path['file'];
-				if (!api_is_anonymous()) {
-					$photo= '<a href="userInfo.php?'.api_get_cidreq().'&origin='.$origin.'&amp;uInfo='.$user_id.'" title="'.get_lang('Info').'"  ><img src="'.$image_repository.$existing_image.'" alt="'.api_get_person_name($o_course_user['firstname'], $o_course_user['lastname']).'"  width="22" height="22" title="'.api_get_person_name($o_course_user['firstname'], $o_course_user['lastname']).'" /></a>';
-				} else {
-					$photo= '<img src="'.$image_repository.$existing_image.'" alt="'.api_get_person_name($o_course_user['firstname'], $o_course_user['lastname']).'"  width="22" height="22" title="'.api_get_person_name($o_course_user['firstname'], $o_course_user['lastname']).'" />';
-				}
                 $temp[] = $user_id;
-				$temp[] = $photo;
-                $temp[] = $o_course_user['official_code'];
-
-				if ($is_western_name_order) {
-					$temp[] = $o_course_user['firstname'];
-					$temp[] = $o_course_user['lastname'];
-				} else {
-					$temp[] = $o_course_user['lastname'];
-					$temp[] = $o_course_user['firstname'];
-				}				
-				$temp[] = $o_course_user['username'];
-				$temp[] = $o_course_user['role'];
-				$temp[] = implode(', ', $groups_name);//Group
-                
-                if ($course_info['unsubscribe'] == 1) {
-                    //User id for actions
-                    $temp[] = $user_id;
-                }
-				//$temp[] = $o_course_user['official_code'];				
-			}
-			$a_users[$user_id] = $temp;
-		}
+            }
+            //$temp[] = $o_course_user['official_code'];				
+        }
+        $a_users[$user_id] = $temp;
 	}
 	return $a_users;
 }
@@ -605,7 +578,6 @@ function active_filter($active, $url_params, $row) {
 	return $result;
 }
 
-
 /**
  * Build the modify-column of the table
  * @param int $user_id The user id

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff