Jelajahi Sumber

Merge with 1.9

Julio Montoya 12 tahun lalu
induk
melakukan
9a5790045c
100 mengubah file dengan 6901 tambahan dan 3347 penghapusan
  1. 1 1
      .hgignore
  2. 6 2
      documentation/changelog.html
  3. 68 44
      main/admin/add_users_to_session.php
  4. 88 0
      main/admin/change_user_session.php
  5. 1 1
      main/admin/configure_inscription.php
  6. 2 2
      main/admin/example_session.csv
  7. 2 2
      main/admin/example_session.xml
  8. 164 0
      main/admin/extra_field_options.php
  9. 1 0
      main/admin/index.php
  10. 4 12
      main/admin/ldap_import_students_to_session.php
  11. 213 198
      main/admin/resume_session.php
  12. 264 405
      main/admin/session_add.php
  13. 12 12
      main/admin/session_course_edit.php
  14. 3 1
      main/admin/session_course_user.php
  15. 61 73
      main/admin/session_course_user_list.php
  16. 0 397
      main/admin/session_edit.php
  17. 185 205
      main/admin/session_export.php
  18. 200 0
      main/admin/session_fields.php
  19. 69 100
      main/admin/session_import.php
  20. 178 72
      main/admin/session_list.php
  21. 3 6
      main/admin/statistics/index.php
  22. 12 5
      main/admin/statistics/statistics.lib.php
  23. 1 1
      main/admin/user_add.php
  24. 1 1
      main/admin/user_edit.php
  25. 266 280
      main/admin/user_fields.php
  26. 108 144
      main/admin/user_fields_options.php
  27. 14 7
      main/admin/user_information.php
  28. 1 1
      main/admin/user_move_stats.php
  29. 1 1
      main/auth/inscription.php
  30. 2 2
      main/auth/profile.php
  31. 17 15
      main/auth/sso/sso.class.php
  32. 1 1
      main/calendar/agenda_js.php
  33. 1 1
      main/course_info/legal.php
  34. 1 1
      main/coursecopy/classes/CourseBuilder.class.php
  35. 0 9
      main/css/academica/default.css
  36. 1 13
      main/css/baby_orange/default.css
  37. 36 31
      main/css/base.css
  38. 6 35
      main/css/blue_lagoon/default.css
  39. 491 261
      main/css/bootstrap-responsive.css
  40. 408 171
      main/css/bootstrap.css
  41. 2 28
      main/css/cool_blue/default.css
  42. 1 11
      main/css/corporate/default.css
  43. 0 13
      main/css/cosmic_campus/default.css
  44. 1 28
      main/css/delicious_bordeaux/default.css
  45. 0 36
      main/css/dokeos_blue/default.css
  46. 1 41
      main/css/dokeos_classic/default.css
  47. 2 36
      main/css/dokeos_classic_2D/default.css
  48. 34 4
      main/document/create_audio.php
  49. 16 0
      main/document/save_pixlr.php
  50. 12 9
      main/document/showinframes.php
  51. 10 4
      main/exercice/exercise_show.php
  52. 1 1
      main/exercice/question_pool.php
  53. 61 67
      main/gradebook/gradebook_display_certificate.php
  54. 2 2
      main/gradebook/lib/gradebook_data_generator.class.php
  55. 20 3
      main/inc/ajax/admin.ajax.php
  56. 21 0
      main/inc/ajax/extra_field.ajax.php
  57. 128 29
      main/inc/ajax/model.ajax.php
  58. 5 26
      main/inc/ajax/user_manager.ajax.php
  59. 0 18
      main/inc/global.inc.php
  60. 11 1
      main/inc/lib/autoload.class.php
  61. 3 1
      main/inc/lib/banner.lib.php
  62. 2 2
      main/inc/lib/career.lib.php
  63. 86 141
      main/inc/lib/course.lib.php
  64. 20 31
      main/inc/lib/course_home.lib.php
  65. 1 0
      main/inc/lib/database.constants.inc.php
  66. 4 7
      main/inc/lib/database.lib.php
  67. 25 76
      main/inc/lib/display.lib.php
  68. 8 12
      main/inc/lib/document.lib.php
  69. 33 3
      main/inc/lib/events.lib.inc.php
  70. 551 0
      main/inc/lib/extra_field.lib.php
  71. 330 0
      main/inc/lib/extra_field_option.lib.php
  72. 192 0
      main/inc/lib/extra_field_value.lib.php
  73. 1 1
      main/inc/lib/formvalidator/Element/style_submit_button.php
  74. 3 1
      main/inc/lib/formvalidator/FormValidator.class.php
  75. 27 0
      main/inc/lib/formvalidator/Rule/CompareDateTimeText.php
  76. 1 1
      main/inc/lib/formvalidator/Rule/CompareFields.php
  77. 22 11
      main/inc/lib/grade_model.lib.php
  78. 33 22
      main/inc/lib/internationalization.lib.php
  79. 370 168
      main/inc/lib/javascript/bootstrap/bootstrap.js
  80. 7 0
      main/inc/lib/javascript/date/date.js
  81. 85 0
      main/inc/lib/javascript/datetimepicker/jquery-ui-sliderAccess.js
  82. 6 0
      main/inc/lib/javascript/datetimepicker/jquery-ui-timepicker-addon.css
  83. 1530 0
      main/inc/lib/javascript/datetimepicker/jquery-ui-timepicker-addon.js
  84. 20 0
      main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-af.js
  85. 20 0
      main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-ca.js
  86. 20 0
      main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-cs.js
  87. 20 0
      main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-de.js
  88. 20 0
      main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-el.js
  89. 20 0
      main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-es.js
  90. 20 0
      main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-et.js
  91. 20 0
      main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-fi.js
  92. 20 0
      main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-fr.js
  93. 20 0
      main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-gl.js
  94. 20 0
      main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-he.js
  95. 20 0
      main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-hu.js
  96. 20 0
      main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-id.js
  97. 20 0
      main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-it.js
  98. 20 0
      main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-ja.js
  99. 20 0
      main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-ko.js
  100. 20 0
      main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-lt.js

+ 1 - 1
.hgignore

@@ -14,7 +14,7 @@ courses/*
 main/garbage/*
 !main/garbage/index.html
 !main/garbage/Serializer
-
+vendor/*
 #Home
 home/*
 #!home/default_platform_document

+ 6 - 2
documentation/changelog.html

@@ -55,7 +55,11 @@
 <h3>New Features</h3>
 <h3>Improvements</h3>
 <h3>Debugging</h3>
-
+<h3>Important changes</h3>
+<ul>
+  <li>Users and sessions extra fields of "double select" type have a modified syntax. If you used this field type in a previous version of Chamilo, you will probably need to update it manually from the database.</li>
+  <li></li>
+</ul>
 
 <h1>Chamilo 1.9.0 - Vogüé, 31st of July, 2012</h1>
 
@@ -2177,4 +2181,4 @@ a simple videoconferencing interface.</p>
         <img src="http://jigsaw.w3.org/css-validator/images/vcss-blue" style="margin: 1em; float: right;" alt="Valid CSS" />
     </a>
 </body>
-</html>
+</html>

+ 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(array('order' => 'name'));
+} else {
+    $sessions = SessionManager::get_sessions_by_general_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();

+ 1 - 1
main/admin/configure_inscription.php

@@ -277,7 +277,7 @@ if ($display_all_form) {
         }
     }
     $extra_data = UserManager::get_extra_user_data(api_get_user_id(), true);
-    UserManager::set_extra_fields_in_form($form, $extra_data, 'registration');
+    ExtraField::set_extra_fields_in_form($form, $extra_data, 'registration', false, null, 'user');
 }
 
 // Terms and conditions

+ 2 - 2
main/admin/example_session.csv

@@ -1,3 +1,3 @@
 SessionName;Coach;DateStart;DateEnd;Users;Courses
-Session1;jmontoya;2008/08/08;2012/12/12;username1|username2;course1[coach1][username1,username2]|course2[coach1][username1,username2]
-Session2;jmontoya;2008/08/08;2012/12/12;username1|username2;course1[coach1][username1,username2]|course2[coach1][username1,username2]
+Session1;jmontoya;2012-06-30 11:00:00;2016-06-30 11:00:00;username1|username2;course1[coach1][username1,username2]|course2[coach1][username1,username2]
+Session2;jmontoya;2012-06-30 11:00:00;2016-06-30 11:00:00;username1|username2;course1[coach1][username1,username2]|course2[coach1][username1,username2]

+ 2 - 2
main/admin/example_session.xml

@@ -24,8 +24,8 @@
     <Session>
         <SessionName>The Universe</SessionName>
         <Coach>Coach</Coach>
-        <DateStart>2008/08/01</DateStart>
-        <DateEnd>2020/12/12</DateEnd>
+        <DateStart>2012-06-30 11:00:00</DateStart>
+        <DateEnd>2016-06-30 11:00:00</DateEnd>
         <User>jmontoya</User>
         <User>jmontoya2</User>
     	<Course>

+ 164 - 0
main/admin/extra_field_options.php

@@ -0,0 +1,164 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+/**
+ *  @package chamilo.admin
+ */
+
+// Language files that need to be included.
+$language_file = array('admin');
+
+$cidReset = true;
+require_once '../inc/global.inc.php';
+
+$this_section = SECTION_PLATFORM_ADMIN;
+
+api_protect_admin_script();
+
+//Add the JS needed to use the jqgrid
+$htmlHeadXtra[] = api_get_jqgrid_js();
+
+// setting breadcrumbs
+$interbreadcrumb[]=array('url' => 'index.php','name' => get_lang('PlatformAdmin'));
+
+$tool_name = null;
+
+$action = isset($_GET['action']) ? $_GET['action'] : null;
+$field_id = isset($_GET['field_id']) ? $_GET['field_id'] : null;
+$type = 'session';
+
+if (empty($field_id)) {
+    api_not_allowed();
+}
+
+$extra_field = new ExtraField($type);
+$extra_field_info = $extra_field->get($field_id);
+
+
+$check = Security::check_token('request');
+$token = Security::get_token();    
+
+if ($action == 'add') {
+    $interbreadcrumb[]=array('url' => 'session_fields.php','name' => get_lang('ExtraFields'));
+    $interbreadcrumb[]=array('url' => 'session_fields.php?action=edit&id='.$extra_field_info['id'],'name' => $extra_field_info['field_display_text']);
+    $interbreadcrumb[]=array('url' => 'extra_field_options.php?type='.$type.'&field_id='.$extra_field_info['id'], 'name' => get_lang('EditExtraFieldOptions'));
+    $interbreadcrumb[]=array('url' => '#','name' => get_lang('Add'));
+} elseif ($action == 'edit') {
+    $interbreadcrumb[]=array('url' => 'session_fields.php','name' => get_lang('ExtraFields'));
+    $interbreadcrumb[]=array('url' => 'session_fields.php?action=edit&id='.$extra_field_info['id'],'name' => $extra_field_info['field_display_text']);
+    $interbreadcrumb[]=array('url' => 'extra_field_options.php?type='.$type.'&field_id='.$extra_field_info['id'], 'name' => get_lang('EditExtraFieldOptions'));
+    
+    $interbreadcrumb[]=array('url' => '#','name' => get_lang('Edit'));
+} else {
+    $interbreadcrumb[]=array('url' => 'session_fields.php','name' => get_lang('ExtraFields'));
+    $interbreadcrumb[]=array('url' => 'session_fields.php?action=edit&id='.$extra_field_info['id'],'name' => $extra_field_info['field_display_text']);
+    $interbreadcrumb[]=array('url' => '#','name' => get_lang('EditExtraFieldOptions'));
+}
+
+//jqgrid will use this URL to do the selects
+$params = 'field_id='.$field_id.'&type='.$type;
+$url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_extra_field_options&'.$params;
+
+//The order is important you need to check the the $column variable in the model.ajax.php file 
+$columns        = array(get_lang('Name'), get_lang('Value'),  get_lang('Order'), get_lang('Actions'));
+  
+//Column config
+$column_model   = array(
+                        array('name'=>'option_display_text', 'index'=>'option_display_text',      'width'=>'180',   'align'=>'left'),
+                        array('name'=>'option_value',       'index'=>'option_value',          'width'=>'',  'align'=>'left','sortable'=>'false'),
+                        array('name'=>'option_order',         'index'=>'option_order',              'width'=>'',  'align'=>'left','sortable'=>'false'),
+                        array('name'=>'actions',            'index'=>'actions',                 'width'=>'100',  'align'=>'left','formatter'=>'action_formatter','sortable'=>'false')
+                       );            
+//Autowidth             
+$extra_params['autowidth'] = 'true';
+//height auto 
+$extra_params['height'] = 'auto'; 
+
+//With this function we can add actions to the jgrid (edit, delete, etc)
+$action_links = 'function action_formatter(cellvalue, options, rowObject) {
+                         return \'<a href="?action=edit&'.$params.'&id=\'+options.rowId+\'">'.Display::return_icon('edit.png',get_lang('Edit'),'',ICON_SIZE_SMALL).'</a>'.
+                         '&nbsp;<a onclick="javascript:if(!confirm('."\'".addslashes(api_htmlentities(get_lang("ConfirmYourChoice"),ENT_QUOTES))."\'".')) return false;"  href="?sec_token='.$token.'&action=delete&'.$params.'&id=\'+options.rowId+\'">'.Display::return_icon('delete.png',get_lang('Delete'),'',ICON_SIZE_SMALL).'</a>'.
+                         '\'; 
+                 }';
+$htmlHeadXtra[]='
+<script>
+$(function() {
+    // grid definition see the $obj->display() function
+    '.Display::grid_js('extra_field_options',  $url, $columns, $column_model, $extra_params, array(), $action_links, true).'
+    
+});
+</script>';
+
+// The header.
+Display::display_header($tool_name);
+
+echo Display::page_header($extra_field_info['field_display_text']);
+
+$obj = new ExtraFieldOption($type);
+$obj->field_id = $field_id;
+
+// Action handling: Add
+switch ($action) {
+    case 'add':
+        if (api_get_session_id() != 0 && !api_is_allowed_to_session_edit(false, true)) {
+            api_not_allowed();
+        }        
+        $url  = api_get_self().'?action='.Security::remove_XSS($_GET['action']).'&'.$params;
+        $form = $obj->return_form($url, 'add');
+
+        // The validation or display
+        if ($form->validate()) {
+            if ($check) {
+                $values = $form->exportValues();
+                $res    = $obj->save_one_item($values);            
+                if ($res) {
+                    Display::display_confirmation_message(get_lang('ItemAdded'));
+                }
+            }        
+            $obj->display();
+        } else {
+            /*echo '<div class="actions">';
+            echo '<a href="'.api_get_self().'">'.Display::return_icon('back.png',get_lang('Back'),'',ICON_SIZE_MEDIUM).'</a>';
+            echo '</div>';            */
+            $form->addElement('hidden', 'sec_token');
+            $form->setConstants(array('sec_token' => $token));
+            $form->display();
+        }
+        break;
+    case 'edit':
+        // Action handling: Editing 
+        $url  = api_get_self().'?action='.Security::remove_XSS($_GET['action']).'&id='.intval($_GET['id']).'&'.$params;
+        $form = $obj->return_form($url, 'edit');    
+
+        // The validation or display
+        if ($form->validate()) {            
+            if ($check) {
+                $values = $form->exportValues();                
+                $res    = $obj->update($values);                
+                Display::display_confirmation_message(sprintf(get_lang('ItemUpdated'), $values['name']), false);                
+            }            
+            $obj->display();
+        } else {
+            /*echo '<div class="actions">';
+            echo '<a href="'.api_get_self().'">'.Display::return_icon('back.png',get_lang('Back'),'',ICON_SIZE_MEDIUM).'</a>';
+            echo '</div>';*/
+            $form->addElement('hidden', 'sec_token');
+            $form->setConstants(array('sec_token' => $token));
+            $form->display();
+        }
+        break;
+    case 'delete':
+        // Action handling: delete
+        if ($check) {
+            $res = $obj->delete($_GET['id']);
+            if ($res) {
+                Display::display_confirmation_message(get_lang('ItemDeleted'));
+            }
+        }
+        $obj->display();
+        break;
+    default:
+        $obj->display();   
+        break;
+}
+Display :: display_footer();

+ 1 - 0
main/admin/index.php

@@ -202,6 +202,7 @@ if (api_is_platform_admin()) {
 }
 
 $items[] = array('url'=>'usergroups.php', 	'label' => get_lang('Classes'));
+$items[] = array('url'=>'session_fields.php', 	'label' => get_lang('ManageSessionFields'));
 
 $blocks['sessions']['items'] = $items;
 $blocks['sessions']['extra'] = null;

+ 4 - 12
main/admin/ldap_import_students_to_session.php

@@ -87,18 +87,10 @@ elseif(!empty($annee) && empty($id_session))
 	echo Display::return_icon('course.gif', get_lang('SelectSessionToImportUsersTo')).' '.get_lang('SelectSessionToImportUsersTo').'<br />';
 	echo '<form method="post" action="'.api_get_self().'?annee='.Security::remove_XSS($annee).'"><br />';
 	echo '<select name="id_session">';
-
-	$tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
-	$sql = "SELECT id,name,nbr_courses,date_start,date_end " .
-		" FROM $tbl_session ".
-		" ORDER BY name";
-	$result = Database::query($sql);
-
-	$sessions=Database::store_result($result);
-	$nbr_results=count($sessions);
-	foreach($sessions as $row)
-	{
-		echo '<option value="'.$row['id'].'">'.api_htmlentities($row['name'], ENT_COMPAT, api_get_system_encoding()).' ('.$row['date_start'].' - '.$row['date_end'].')</option>';
+    
+    $sessions = SessionManager::get_sessions_list();	
+	foreach ($sessions as $row) {
+		echo '<option value="'.$row['id'].'">'.api_htmlentities($row['name'], ENT_COMPAT, api_get_system_encoding()).' ('.api_get_local_time($row['access_start_date']).' - '.api_get_local_time($row['access_end_date']).')</option>';
 	}
 	echo '</select>';
 	echo '<input type="submit" value="'.get_lang('Submit').'">';

+ 213 - 198
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 = api_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,42 +44,15 @@ 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;
 }
+
 Display::display_header($tool_name);
 
 if (!empty($_GET['warn'])) {
@@ -113,18 +62,20 @@ if (!empty($_GET['warn'])) {
 if (!empty($message)) {
     echo $message;
 }
+$dates = SessionManager::parse_session_dates($session);
+echo Display::page_header(Display::return_icon('session.png', get_lang('Session')).' '.$session['name']." <small>$dates</small>");
 
-echo Display::page_header(Display::return_icon('session.png', get_lang('Session')).' '.$session['name']);
-
-$url = Display::url(Display::return_icon('edit.png', get_lang('Edit'), array(), ICON_SIZE_SMALL), "session_edit.php?page=resume_session.php&id=$id_session");
+$url = Display::url(Display::return_icon('edit.png', get_lang('Edit'), array(), ICON_SIZE_SMALL), "session_add.php?page=resume_session.php&id=$id_session");
 echo Display::page_subheader(get_lang('GeneralProperties').$url);
 
+$coach_info = api_get_user_info($session['id_coach']);
+
 ?>
 <!-- General properties -->
 <table class="data_table">
 <tr>
 	<td><?php echo get_lang('GeneralCoach'); ?> :</td>
-	<td><?php echo api_get_person_name($session['firstname'], $session['lastname']).' ('.$session['username'].')' ?></td>
+	<td><?php echo $coach_info['complete_name'].' ('.$coach_info['username'].')' ?></td>
 </tr>
 <?php if(!empty($session_category)) { ?>
 <tr>
@@ -133,57 +84,73 @@ echo Display::page_subheader(get_lang('GeneralProperties').$url);
 </tr>
 <?php } ?>
 <tr>
-	<td><?php echo get_lang('Date'); ?> :</td>
-	<td>
-	<?php
-		if ($session['date_start'] == '00-00-0000' && $session['date_end']== '00-00-0000' )
-			echo get_lang('NoTimeLimits');
-		else {
-            if ($session['date_start'] != '00-00-0000') {
-            	//$session['date_start'] = Display::tag('i', get_lang('NoTimeLimits'));
-                $session['date_start'] =  get_lang('From').' '.$session['date_start'];
-            } else {
-            	$session['date_start'] = '';
-            }
-            if ($session['date_end'] == '00-00-0000') {
-                $session['date_end'] ='';
-            } else {
-            	$session['date_end'] = get_lang('Until').' '.$session['date_end'];
-            }
-			echo $session['date_start'].' '.$session['date_end'];
-        }
-        ?>
-	</td>
+	<td><?php echo get_lang('SessionDisplayStartDate'); ?> :</td>
+	<td><?php echo api_get_local_time($session['display_start_date'], null, null, true); ?></td>    
 </tr>
-<!-- show nb_days_before and nb_days_after only if they are different from 0 -->
 <tr>
-	<td>
-		<?php echo api_ucfirst(get_lang('DaysBefore')) ?> :
-	</td>
-	<td>
-		<?php echo intval($session['nb_days_access_before_beginning']) ?>
-	</td>
+    <td><?php echo get_lang('SessionDisplayEndDate'); ?> :</td>
+	<td><?php echo api_get_local_time($session['display_end_date'], null, null, true); ?></td>
 </tr>
-<tr>
-	<td>
-		<?php echo api_ucfirst(get_lang('DaysAfter')) ?> :
-	</td>
-	<td>
-		<?php echo intval($session['nb_days_access_after_end']) ?>
-	</td>
+<tr>    
+    <td><?php echo get_lang('SessionStartDate'); ?> :</td>
+	<td><?php echo api_get_local_time($session['access_start_date'], null, null, true); ?></td>
+</tr>
+<tr>    
+    <td><?php echo get_lang('SessionEndDate'); ?> :</td>
+	<td><?php echo api_get_local_time($session['access_end_date'], null, null, true); ?></td>
+</tr>
+<tr>    
+    <td><?php echo get_lang('SessionCoachStartDate'); ?> :</td>
+	<td><?php echo api_get_local_time($session['coach_access_start_date'], null, null, true); ?></td>
+</tr>
+<tr>    
+    <td><?php echo get_lang('SessionCoachEndDate'); ?> :</td>
+	<td><?php echo api_get_local_time($session['coach_access_end_date'], null, null, true); ?></td>
 </tr>
 <tr>
 	<td>
 		<?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['access_end_date']) && $session['access_end_date'] != '0000-00-00 00:00:00') {            
+            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 
+<?php
+
+$session_field = new SessionField();
+$session_fields = $session_field->get_all();
+foreach ($session_fields as $session_field) {
+    if ($session_field['field_visible'] != '1') {
+        continue;        
+    }
+    $obj = new SessionFieldValue();
+    $result = $obj->get_values_by_handler_and_field_id($id_session, $session_field['id'], true);
+    
+    $session_value = null;
+    if ($result) {
+        $session_value = $result['field_value'];
+    }    
+    echo "<tr>";
+    echo "<td> {$session_field['field_display_text']} </td>";
+    echo "<td> $session_value </td>";
+    echo "</tr>";    
+}
 
-$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>';   
@@ -191,7 +158,7 @@ if ($multiple_url_is_on) {
     echo '</td>';
     echo '<td>';
     $url_list = UrlManager::get_access_url_from_session($id_session);
-    foreach($url_list as $url_data) {
+    foreach ($url_list as $url_data) {
         echo $url_data['url'].'<br />';
     }        
     echo '</td></tr>';
@@ -220,60 +187,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>';
 	}
@@ -286,7 +219,7 @@ if ($session['nbr_courses'] == 0){
 
 $url = Display::url(Display::return_icon('edit.png', get_lang('Edit'), array(), ICON_SIZE_SMALL), "add_users_to_session.php?page=resume_session.php&id_session=$id_session");
 $url .= Display::url(Display::return_icon('import_csv.png', get_lang('ImportUsers'), array(), ICON_SIZE_SMALL), "session_user_import.php?id_session=$id_session");
-echo Display::page_subheader(get_lang('UserList').$url);
+echo Display::page_subheader(get_lang('StudentList').$url);
 
 ?>
 
@@ -297,68 +230,150 @@ echo Display::page_subheader(get_lang('UserList').$url);
         <th>
             <?php echo get_lang('User'); ?>
         </th>
+        <th>
+            <?php echo get_lang('Status'); ?>
+        </th>
+        <th>
+            <?php echo get_lang('Information'); ?>
+        </th>
+        <th>
+            <?php echo get_lang('Destination'); ?>
+        </th>
+        <th>
+            <?php echo get_lang('MovedAt'); ?>
+        </th>
         <th>
             <?php echo get_lang('Actions'); ?>
         </th>
     </tr>
 <?php
-
-if ($session['nbr_users']==0) {
-	echo '<tr>
-			<td colspan="2">'.get_lang('NoUsersForThisSession').'</td>
-		</tr>';
+/*
+if ($session['nbr_users'] == 0) {
+	
 } else {    
-	$order_clause = api_sort_by_first_name() ? ' ORDER BY firstname, lastname' : ' ORDER BY lastname, firstname';
+*/
+	$orig_param = '&origin=resume_session&id_session='.$id_session; // change breadcrumb in destination page
+    
+    $users = SessionManager::get_users_by_session($id_session, 0);        
+    //$reasons = SessionManager::get_session_change_user_reasons();
     
-    if ($multiple_url_is_on) {           
-        $sql = "SELECT u.user_id, lastname, firstname, username, access_url_id
-                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 $table_access_url_user uu ON (uu.user_id = u.user_id)
-                WHERE su.id_session = $id_session AND (access_url_id = $url_id OR access_url_id is null )
-                $order_clause";
+    if (!empty($users)) {
+        foreach ($users as $user) {
+            $user_info = api_get_user_info($user['user_id']);
+            //$link_class = 'class="item_disabled"';
+            $link_class = null;
+            $user_status_in_platform = Display::return_icon('error.png', get_lang('Inactive'));
+            $information = '';
+            $moved_date = '-';
+            
+            if ($user_info['active'] == 1 ) {
+                $user_status_in_platform = Display::return_icon('accept.png', get_lang('Active'));                
+                //$link_class = null;
+            } else {
+                $status_info = get_latest_event_by_user_and_type($user['user_id'], LOG_USER_DEACTIVATED);
+                //var_dump($status_info);
+                if (!empty($status_info)) {
+                    $information .= sprintf(get_lang('UserInactivedSinceX'), api_convert_and_format_date($status_info['default_date'], DATE_TIME_FORMAT_LONG));
+                    $moved_date = api_get_local_time($status_info['default_date']);
+                }
+                $user_info['complete_name_with_username'] = Display::tag('del', $user_info['complete_name_with_username']);
+            }
+            
+            $user_link = '';            
+            if (!empty($user['user_id'])) {
+                $user_link = '<a '.$link_class.' href="'.api_get_path(WEB_CODE_PATH).'admin/user_information.php?user_id='.intval($user['user_id']).'">'.$user_info['complete_name_with_username'].'</a>';
+            }
+            $origin = null;
+            $destination = null;
+            $row_style = null;
+
+            $course_link = '<a href="session_course_user.php?id_user='.$user['user_id'].'&id_session='.$id_session.'">'.Display::return_icon('course.gif', get_lang('BlockCoursesForThisUser')).'&nbsp;</a>';
+            $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;';
+
+            //User in this session is subscribed but was moved to another session
+            if (isset($user['moved_to']) && !empty($user['moved_to']) || $user['moved_status'] == SessionManager::SESSION_CHANGE_USER_REASON_ENROLLMENT_ANNULATION) {
+                
+                $variation = SessionManager::get_session_change_user_reasons_variations_by_id($user['moved_status'], 'to');
+                //$information = $reasons[$user['moved_status']].$variation;
+                $information .= $variation;
+
+                $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 ($user['moved_status'] != SessionManager::SESSION_CHANGE_USER_REASON_ENROLLMENT_ANNULATION) {
+                    $url = api_get_path(WEB_CODE_PATH).'admin/resume_session.php?id_session='.$id_session;                
+                    //$origin = Display::url($session['name'], $url);                
+
+                    if ($session_info) {
+                        $url = api_get_path(WEB_CODE_PATH).'admin/resume_session.php?id_session='.$session_info['id'];
+                        $destination = Display::url($session_info['name'], $url);
+                        //$destination = $destination;
+                    }            
+                }
+                $row_style = 'style = " background-color: #ddd;"';
+                $course_link=  Display::return_icon('course_na.gif', get_lang('BlockCoursesForThisUser')).'&nbsp;';
+                $moved_link =  Display::return_icon('move_na.png', get_lang('ChangeUserSession')).'&nbsp;';
+                $delete_link = Display::return_icon('delete_na.png', get_lang('Delete')).'&nbsp;';
+            } else {          
+                $session_origin_info = SessionManager::get_session_rel_user_by_moved_to($id_session, $user['user_id']);
+
+                if (!empty($session_origin_info)) {
+                   $moved_date = api_get_local_time($session_origin_info['moved_at']);
+                }            
+                $session_info = SessionManager::fetch($session_origin_info['id_session']);
+                
+                $variation = SessionManager::get_session_change_user_reasons_variations_by_id($session_origin_info['moved_status'], 'from');
+                
+                //$information = $reasons[$session_origin_info['moved_status']].$variation;
+                $information .= $variation;
+
+                if ($session_info) {
+                    $url = api_get_path(WEB_CODE_PATH).'admin/resume_session.php?id_session='.$session_info['id'];
+                    $origin = Display::url($session_info['name'], $url);
+
+                    $url = api_get_path(WEB_CODE_PATH).'admin/resume_session.php?id_session='.$id_session;                
+                    //$destination = Display::url($session['name'], $url);
+                    //$destination = ' / '.$destination;
+                }
+
+                $delete_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 = '';
+
+            if ($multiple_url_is_on) {
+                if ($user['access_url_id'] != $url_id) {            
+                    $user_link .= ' '.Display::return_icon('warning.png', get_lang('UserNotAddedInURL'), array(), ICON_SIZE_SMALL);
+                    $add = Display::return_icon('add.png', get_lang('AddUsersToURL'), array(), ICON_SIZE_SMALL);
+                    $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 '.$row_style.'>
+                    <td width="30%">
+                        '.$user_link.'
+                    </td>
+                    <td>'.$user_status_in_platform.'</td>
+                    <td>'.$information.'</td>
+                    <td>'.$origin.' '.$destination.'</td>
+                    <td>'.$moved_date.'</td>
+                    <td>
+                        <a href="../mySpace/myStudents.php?student='.$user['user_id'].''.$orig_param.'">'.Display::return_icon('statistics.gif', get_lang('Reporting')).'</a>&nbsp;
+                        '.$course_link.'
+                        '.$moved_link.'
+                        '.$delete_link.'
+                        '.$link_to_add_user_in_url.'
+                    </td>
+                    </tr>';
+        }
     } else {
-        $sql = "SELECT u.user_id, lastname, firstname, username
-                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."
-                AND su.id_session = ".$id_session.$order_clause;
+        echo '<tr>
+			<td colspan="2">'.get_lang('NoUsersForThisSession').'</td>
+		</tr>';
     }
 
-	$result = Database::query($sql);
-	$users  = Database::store_result($result);
-	$orig_param = '&origin=resume_session&id_session='.$id_session; // change breadcrumb in destination page
-	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>';
-        }
-        
-        $link_to_add_user_in_url = '';
-        
-        if ($multiple_url_is_on) {
-            if ($user['access_url_id'] != $url_id) {            
-                $user_link .= ' '.Display::return_icon('warning.png', get_lang('UserNotAddedInURL'), array(), ICON_SIZE_SMALL);
-                $add = Display::return_icon('add.png', get_lang('AddUsersToURL'), array(), ICON_SIZE_SMALL);
-                $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%">
-                    '.$user_link.'
-                </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;
-                    <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>
-                </tr>';
-	}
-}
 ?>
 </table>
 <?php
-// footer
-Display :: display_footer();
+Display :: display_footer();

+ 264 - 405
main/admin/session_add.php

@@ -7,443 +7,302 @@
 */
 
 // name of the language file that needs to be included
-$language_file='admin';
+$language_file = 'admin';
 
-$cidReset=true;
+$cidReset = true;
 
 // including the global Chamilo file
 require_once '../inc/global.inc.php';
 
-// including additional libraries
-require_once '../inc/lib/xajax/xajax.inc.php';
-
-$xajax = new xajax();
-//$xajax->debugOn();
-$xajax -> registerFunction ('search_coachs');
-
 // setting the section (for the tabs)
-$this_section=SECTION_PLATFORM_ADMIN;
+$this_section = SECTION_PLATFORM_ADMIN;
 
 api_protect_admin_script(true);
 
 $formSent=0;
 $errorMsg='';
 
-$interbreadcrumb[]=array('url' => 'index.php',       'name' => get_lang('PlatformAdmin'));
-$interbreadcrumb[]=array('url' => 'session_list.php','name' => get_lang('SessionList'));
-
-// Database Table Definitions
-$tbl_user		= Database::get_main_table(TABLE_MAIN_USER);
-
-function search_coachs($needle) {
-	global $tbl_user;
-
-	$xajax_response = new XajaxResponse();
-	$return = '';
-
-	if(!empty($needle)) {
-		// xajax send utf8 datas... datas in db can be non-utf8 datas
-		$charset = api_get_system_encoding();
-		$needle = api_convert_encoding($needle, $charset, 'utf-8');
-
-		$order_clause = api_sort_by_first_name() ? ' ORDER BY firstname, lastname, username' : ' ORDER BY lastname, firstname, username';
-
-		// search users where username or firstname or lastname begins likes $needle
-		$sql = 'SELECT username, lastname, firstname FROM '.$tbl_user.' user
-				WHERE (username LIKE "'.$needle.'%"
-				OR firstname LIKE "'.$needle.'%"
-				OR lastname LIKE "'.$needle.'%")
-				AND status=1'.
-				$order_clause.
-				' LIMIT 10';
-
-		global $_configuration;
-		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();
-			if ($access_url_id != -1){
-
-				$sql = 'SELECT username, lastname, firstname FROM '.$tbl_user.' user
-				INNER JOIN '.$tbl_user_rel_access_url.' url_user ON (url_user.user_id=user.user_id)
-				WHERE access_url_id = '.$access_url_id.'  AND (username LIKE "'.$needle.'%"
-				OR firstname LIKE "'.$needle.'%"
-				OR lastname LIKE "'.$needle.'%")
-				AND status=1'.
-				$order_clause.
-				' LIMIT 10';
-
-			}
-		}
-
-		$rs = Database::query($sql);
-		while ($user = Database :: fetch_array($rs)) {
-			$return .= '<a href="javascript: void(0);" onclick="javascript: fill_coach_field(\''.$user['username'].'\')">'.api_get_person_name($user['firstname'], $user['lastname']).' ('.$user['username'].')</a><br />';
-		}
-	}
-	$xajax_response -> addAssign('ajax_list_coachs','innerHTML', api_utf8_encode($return));
-	return $xajax_response;
-}
-$xajax -> processRequests();
+$interbreadcrumb[] = array('url' => 'index.php',       'name' => get_lang('PlatformAdmin'));
+$interbreadcrumb[] = array('url' => 'session_list.php','name' => get_lang('SessionList'));
+
+$htmlHeadXtra[] = '<script src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/tag/jquery.fcbkcomplete.js" type="text/javascript" language="javascript"></script>';
+$htmlHeadXtra[] = '<link  href="'.api_get_path(WEB_LIBRARY_PATH).'javascript/tag/style.css" rel="stylesheet" type="text/css" />';
+$htmlHeadXtra[] = api_get_jquery_libraries_js(array('jquery-ui-i18n'));
 
-$htmlHeadXtra[] = $xajax->getJavascript('../inc/lib/xajax/');
+$htmlHeadXtra = api_get_datetime_picker_js($htmlHeadXtra);
 
-$htmlHeadXtra[] = '
-<script type="text/javascript">
-function fill_coach_field (username) {
-	document.getElementById("coach_username").value = username;
-	document.getElementById("ajax_list_coachs").innerHTML = "";
+$id = null;
+$url_action = api_get_self();
+if (isset($_GET['id'])) {
+   $id = intval($_GET['id']);
+   $url_action = '?id='.$id;
+}
+
+$add_coach = null;
+
+if ($id) {
+    $tool_name = get_lang('EditSession');    
+    SessionManager::protect_session_edit($id);    
+    $session_info = api_get_session_info($id);    
+    if (!empty($session_info['id_coach'])) {
+        $user_info = api_get_user_info($session_info['id_coach']);        
+        $add_coach = '$("#coach_id").trigger("addItem", [{"title": "'.$user_info['complete_name'].'", "value": "'.$session_info['id_coach'].'"}]);';
+    }
+    $button = get_lang('Update');    
+} else {
+    $tool_name = get_lang('AddSession');
+    $button = get_lang('Add');
 }
-</script>';
 
+$url = api_get_path(WEB_AJAX_PATH).'admin.ajax.php?1=1';
+
+$htmlHeadXtra[] ='
+<script>
+function check() {
+    $("#coach_id option:selected").each(function() {
+        var id = $(this).val();
+        var name = $(this).text();        
+        if (id != "" ) {
+            $.ajax({ 
+                async: false,
+                url: "'.$url.'&a=user_exists", 
+                data: "id="+id,
+                success: function(return_value) {                    
+                    if (return_value == 0 ) {                        
+                        alert("'.get_lang('UserDoesNotExist').'");                        
+                        //Deleting select option tag
+                        $("#coach_id").find("option").remove();
+                        
+                        $(".holder li").each(function () {
+                            if ($(this).attr("rel") == id) {
+                                $(this).remove();
+                            }
+                        });
+                    }
+                },            
+            });                
+        }
+    });
+}
 
-if ($_POST['formSent']) {
-	$formSent = 1;
-	$name                  = $_POST['name'];
-	$year_start            = $_POST['year_start'];
-	$month_start           = $_POST['month_start'];
-	$day_start             = $_POST['day_start'];
-	$year_end              = $_POST['year_end'];
-	$month_end             = $_POST['month_end'];
-	$day_end               = $_POST['day_end'];
-	$nb_days_acess_before  = $_POST['nb_days_acess_before'];
-	$nb_days_acess_after   = $_POST['nb_days_acess_after'];
-	//$nolimit               = $_POST['nolimit'];
-	$coach_username        = $_POST['coach_username'];
-	$id_session_category   = $_POST['session_category'];
-	$id_visibility         = $_POST['session_visibility'];
+$(function() {
+
+    $("#coach_id").fcbkcomplete({
+        json_url: "'.$url.'&a=find_coaches",
+        maxitems: 1,
+        addontab: false,
+        input_min_size: 1,
+        cache: false,
+        complete_text:"'.get_lang('StartToType').'",
+        firstselected: false,        
+        onselect: check,
+        filter_selected: true,
+        newel: true           
+    });
+    
+    '.$add_coach.'        
+
+    $("#display_end_date").datetimepicker({
+        dateFormat: "yy-mm-dd",
+        hour: 9,        
+        onSelect: function(selectedDateTime) {
+            var start = $(this).datetimepicker("getDate");
+            
+            if (!$("#access_end_date").val()) {
+                $("#access_end_date").val(selectedDateTime);
+            }
+            
+            if (!$("#coach_access_end_date").val()) {
+                $("#coach_access_end_date").val(selectedDateTime);
+            }
+        }
+    });
+    
+    $("#display_start_date").datetimepicker({
+        dateFormat: "yy-mm-dd",
+        hour: 9,        
+        onSelect: function(selectedDateTime) {
+            var start = $(this).datetimepicker("getDate");
+            
+            if (!$("#access_start_date").val()) {
+                $("#access_start_date").val(selectedDateTime);
+            }
+            
+            if (!$("#coach_access_start_date").val()) {
+                $("#coach_access_start_date").val(selectedDateTime);
+            }
+        }
+    });
+    
+    $("#access_start_date").datetimepicker({
+        dateFormat: "yy-mm-dd",
+        hour: 9,
+        onSelect: function(selectedDateTime) {
+            var start = $(this).datetimepicker("getDate");        
+            //$("#access_end_date").val(selectedDateTime);                    
+        }
+    });
     
-    $end_limit             = $_POST['end_limit'];
-    $start_limit           = $_POST['start_limit'];  
+    access_start_date_content = $("#access_end_date").val();
     
-    if (empty($end_limit) && empty($start_limit)) {
-        $nolimit = 1;
+    if (access_start_date_content.length > 0) {
+        $("#visibility_container").show();
     } else {
-    	$nolimit = null;
-    }    
-	$return = SessionManager::create_session($name,$year_start,$month_start,$day_start,$year_end,$month_end,$day_end,$nb_days_acess_before,$nb_days_acess_after,$nolimit,$coach_username, $id_session_category,$id_visibility, $start_limit, $end_limit);
-
-	if ($return == strval(intval($return))) {
-		// integer => no error on session creation
-		header('Location: add_courses_to_session.php?id_session='.$return.'&add=true&msg=');
-		exit();
-	}
-}
-
-$nb_days_acess_before = 0;
-$nb_days_acess_after = 0;
-
-$thisYear=date('Y');
-$thisMonth=date('m');
-$thisDay=date('d');
+        $("#visibility_container").hide();
+    }
+    
+    $("#access_end_date").datetimepicker({
+        dateFormat: "yy-mm-dd",
+        onSelect: function(selectedDateTime) {            
+            $("#visibility_container").show();
+        }
+    });
+    
+    $("#access_end_date").on("change", function() {        
+        content = $(this).val();
+        if (content.length > 0) {
+            $("#visibility_container").show();
+        } else {
+            $("#visibility_container").hide();
+        }
+        
+    });
+    
+    $("#coach_access_start_date").datetimepicker({
+        dateFormat: "yy-mm-dd",
+        hour: 9,
+        onSelect: function(selectedDateTime) {
+            var start = $(this).datetimepicker("getDate");        
+            //$("#coach_access_end_date").val(selectedDateTime);
+        }
+    });
+    
+    $("#coach_access_end_date").datetimepicker({
+        dateFormat: "yy-mm-dd"
+    });
+
+    var value = 1;
+    $("#advanced_parameters").on("click", function() {    
+        $("#options").toggle(function() {        
+            if (value == 1) {
+                $("#advanced_parameters").addClass("btn-hide");        
+                value = 0;
+            } else {
+                $("#advanced_parameters").removeClass("btn-hide");      
+                value = 1;
+            }
+        });
+    });
+    
+});
+</script>';
 
-$tool_name = get_lang('AddSession');
+$form = new FormValidator('add_session', 'post', $url_action);
+$form->addElement('header', $tool_name);
 
-Display::display_header($tool_name);
+//Name
+$form->addElement('text', 'name', get_lang('SessionName'), array('class' => 'span6'));
+$form->addRule('name', get_lang('ThisFieldIsRequired'), 'required');
 
-if (!empty($return)) {
-	Display::display_error_message($return,false);
-}
-echo '<div class="actions">';
-echo '<a href="../admin/index.php">'.Display::return_icon('back.png', get_lang('BackTo').' '.get_lang('PlatformAdmin'),'',ICON_SIZE_MEDIUM).'</a>';
-echo '</div>';
-
-?>
-<form class="form-horizontal" method="post" name="form" action="<?php echo api_get_self(); ?>" style="margin:0px;">
-    <input type="hidden" name="formSent" value="1">
-    <div class="control-group">
-        <label class="control-label">
-            <?php echo get_lang('SessionName') ?>
-        </label>
-        <div class="controls">
-            <input type="text" name="name" class="span4" maxlength="50" value="<?php if($formSent) echo api_htmlentities($name,ENT_QUOTES,$charset); ?>">
-        </div>        
-    </div>   
-  
-    <div class="control-group">
-        <label class="control-label">
-            <?php echo get_lang('CoachName') ?>
-        </label>
-        <div class="controls">
-  
-<?php
-
-$sql = 'SELECT COUNT(1) FROM '.$tbl_user.' WHERE status=1';
-$rs = Database::query($sql);
-$count_users = Database::result($rs, 0, 0);
-
-if (intval($count_users)<50) {
-	$order_clause = api_sort_by_first_name() ? ' ORDER BY firstname, lastname, username' : ' ORDER BY lastname, firstname, username';
-	$sql="SELECT user_id, lastname,firstname,username FROM $tbl_user WHERE status='1'".$order_clause;
-	
-	global $_configuration;
-	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();
-		if ($access_url_id != -1){
-			$sql = 'SELECT user.user_id, username, lastname, firstname FROM '.$tbl_user.' user
-			INNER JOIN '.$tbl_user_rel_access_url.' url_user ON (url_user.user_id=user.user_id)
-			WHERE access_url_id = '.$access_url_id.'  AND status=1'.$order_clause;
-		}
-	}
-	$result = Database::query($sql);
-	$Coaches = Database::store_result($result);
-	
-	?>
-	<select id="coach_username" class="chzn-select" name="coach_username" style="width:350px;" title="<?php echo get_lang('Select'); ?>" >
-		<option value="0"><?php get_lang('None'); ?></option>
-		<?php foreach($Coaches as $enreg): ?>
-		<option value="<?php echo $enreg['username']; ?>"> <?php echo api_get_person_name($enreg['firstname'], $enreg['lastname']).' ('.$enreg['username'].')'; ?></option>
-		<?php endforeach; ?>
-	</select>
-	<?php
-	echo Display::return_icon('synthese_view.gif',get_lang('ActivityCoach'));
+if (empty($id)) {    
+    $form->addRule('name', get_lang('SessionNameAlreadyExists'), 'callback', 'check_session_name');
 } else {
-	?>
-	<input type="text" name="coach_username" id="coach_username" onkeyup="xajax_search_coachs(document.getElementById('coach_username').value)" /><div id="ajax_list_coachs"></div>
-	<?php
+    $form->addElement('hidden', 'id', $id);
 }
-$Categories = SessionManager::get_all_session_category();
-?>	
-        </div>        
-    </div>
-  
-
-
-    <div class="control-group">
-        <label class="control-label">
-            <?php echo get_lang('SessionCategory') ?>
-        </label>
-        <div class="controls">
-            <select id="session_category" class="chzn-select" name="session_category" style="width:350px;" title="<?php echo get_lang('Select'); ?>">
-                <option value="0"><?php get_lang('None'); ?></option>       
-            <?php 
-            if (!empty($Categories)) {
-                foreach($Categories as $Rows) { ?>
-                    <option value="<?php echo $Rows['id']; ?>" <?php if($Rows['id'] == $id_session_category) echo 'selected="selected"'; ?>><?php echo $Rows['name']; ?></option>
-                <?php }
-            }
-            ?>
-        </select>
-        </div>        
-    </div>   
-    
- <div class="control-group">
-        <div class="controls">
-            <a href="javascript://" onclick="if(document.getElementById('options').style.display == 'none'){document.getElementById('options').style.display = 'block';}else{document.getElementById('options').style.display = 'none';}"><?php echo get_lang('DefineSessionOptions') ?></a>
-        <div style="display: <?php if($formSent && ($nb_days_acess_before!=0 || $nb_days_acess_after!=0)) echo 'block'; else echo 'none'; ?>;" id="options">
-            <br />
-            <input type="text" name="nb_days_acess_before" value="<?php echo $nb_days_acess_before; ?>" style="width: 30px;">&nbsp;<?php echo get_lang('DaysBefore') ?><br /><br />
-            <input type="text" name="nb_days_acess_after" value="<?php echo $nb_days_acess_after; ?>" style="width: 30px;">&nbsp;<?php echo get_lang('DaysAfter') ?>
-            <br />
-        </div>
-        </div>        
-</div>   
-    
- <div class="control-group">        
-        <div class="controls">                
-    <label for="start_limit">
-        <input id="start_limit" type="checkbox" name="start_limit" onchange="disable_starttime(this)" />
-    <?php echo get_lang('DateStartSession');?>
-    </label> 
- 
-    <div id="start_date" style="display:none">
-       <br />
-    
-  <select name="day_start">
-	<option value="1">01</option>
-	<option value="2" <?php if((!$formSent && $thisDay == 2) || ($formSent && $day_start == 2)) echo 'selected="selected"'; ?> >02</option>
-	<option value="3" <?php if((!$formSent && $thisDay == 3) || ($formSent && $day_start == 3)) echo 'selected="selected"'; ?> >03</option>
-	<option value="4" <?php if((!$formSent && $thisDay == 4) || ($formSent && $day_start == 4)) echo 'selected="selected"'; ?> >04</option>
-	<option value="5" <?php if((!$formSent && $thisDay == 5) || ($formSent && $day_start == 5)) echo 'selected="selected"'; ?> >05</option>
-	<option value="6" <?php if((!$formSent && $thisDay == 6) || ($formSent && $day_start == 6)) echo 'selected="selected"'; ?> >06</option>
-	<option value="7" <?php if((!$formSent && $thisDay == 7) || ($formSent && $day_start == 7)) echo 'selected="selected"'; ?> >07</option>
-	<option value="8" <?php if((!$formSent && $thisDay == 8) || ($formSent && $day_start == 8)) echo 'selected="selected"'; ?> >08</option>
-	<option value="9" <?php if((!$formSent && $thisDay == 9) || ($formSent && $day_start == 9)) echo 'selected="selected"'; ?> >09</option>
-	<option value="10" <?php if((!$formSent && $thisDay == 10) || ($formSent && $day_start == 10)) echo 'selected="selected"'; ?> >10</option>
-	<option value="11" <?php if((!$formSent && $thisDay == 11) || ($formSent && $day_start == 11)) echo 'selected="selected"'; ?> >11</option>
-	<option value="12" <?php if((!$formSent && $thisDay == 12) || ($formSent && $day_start == 12)) echo 'selected="selected"'; ?> >12</option>
-	<option value="13" <?php if((!$formSent && $thisDay == 13) || ($formSent && $day_start == 13)) echo 'selected="selected"'; ?> >13</option>
-	<option value="14" <?php if((!$formSent && $thisDay == 14) || ($formSent && $day_start == 14)) echo 'selected="selected"'; ?> >14</option>
-	<option value="15" <?php if((!$formSent && $thisDay == 15) || ($formSent && $day_start == 15)) echo 'selected="selected"'; ?> >15</option>
-	<option value="16" <?php if((!$formSent && $thisDay == 16) || ($formSent && $day_start == 16)) echo 'selected="selected"'; ?> >16</option>
-	<option value="17" <?php if((!$formSent && $thisDay == 17) || ($formSent && $day_start == 17)) echo 'selected="selected"'; ?> >17</option>
-	<option value="18" <?php if((!$formSent && $thisDay == 18) || ($formSent && $day_start == 18)) echo 'selected="selected"'; ?> >18</option>
-	<option value="19" <?php if((!$formSent && $thisDay == 19) || ($formSent && $day_start == 19)) echo 'selected="selected"'; ?> >19</option>
-	<option value="20" <?php if((!$formSent && $thisDay == 20) || ($formSent && $day_start == 20)) echo 'selected="selected"'; ?> >20</option>
-	<option value="21" <?php if((!$formSent && $thisDay == 21) || ($formSent && $day_start == 21)) echo 'selected="selected"'; ?> >21</option>
-	<option value="22" <?php if((!$formSent && $thisDay == 22) || ($formSent && $day_start == 22)) echo 'selected="selected"'; ?> >22</option>
-	<option value="23" <?php if((!$formSent && $thisDay == 23) || ($formSent && $day_start == 23)) echo 'selected="selected"'; ?> >23</option>
-	<option value="24" <?php if((!$formSent && $thisDay == 24) || ($formSent && $day_start == 24)) echo 'selected="selected"'; ?> >24</option>
-	<option value="25" <?php if((!$formSent && $thisDay == 25) || ($formSent && $day_start == 25)) echo 'selected="selected"'; ?> >25</option>
-	<option value="26" <?php if((!$formSent && $thisDay == 26) || ($formSent && $day_start == 26)) echo 'selected="selected"'; ?> >26</option>
-	<option value="27" <?php if((!$formSent && $thisDay == 27) || ($formSent && $day_start == 27)) echo 'selected="selected"'; ?> >27</option>
-	<option value="28" <?php if((!$formSent && $thisDay == 28) || ($formSent && $day_start == 28)) echo 'selected="selected"'; ?> >28</option>
-	<option value="29" <?php if((!$formSent && $thisDay == 29) || ($formSent && $day_start == 29)) echo 'selected="selected"'; ?> >29</option>
-	<option value="30" <?php if((!$formSent && $thisDay == 30) || ($formSent && $day_start == 30)) echo 'selected="selected"'; ?> >30</option>
-	<option value="31" <?php if((!$formSent && $thisDay == 31) || ($formSent && $day_start == 31)) echo 'selected="selected"'; ?> >31</option>
-  </select>
-  /
-  <select name="month_start">
-	<option value="1">01</option>
-	<option value="2" <?php if((!$formSent && $thisMonth == 2) || ($formSent && $month_start == 2)) echo 'selected="selected"'; ?> >02</option>
-	<option value="3" <?php if((!$formSent && $thisMonth == 3) || ($formSent && $month_start == 3)) echo 'selected="selected"'; ?> >03</option>
-	<option value="4" <?php if((!$formSent && $thisMonth == 4) || ($formSent && $month_start == 4)) echo 'selected="selected"'; ?> >04</option>
-	<option value="5" <?php if((!$formSent && $thisMonth == 5) || ($formSent && $month_start == 5)) echo 'selected="selected"'; ?> >05</option>
-	<option value="6" <?php if((!$formSent && $thisMonth == 6) || ($formSent && $month_start == 6)) echo 'selected="selected"'; ?> >06</option>
-	<option value="7" <?php if((!$formSent && $thisMonth == 7) || ($formSent && $month_start == 7)) echo 'selected="selected"'; ?> >07</option>
-	<option value="8" <?php if((!$formSent && $thisMonth == 8) || ($formSent && $month_start == 8)) echo 'selected="selected"'; ?> >08</option>
-	<option value="9" <?php if((!$formSent && $thisMonth == 9) || ($formSent && $month_start == 9)) echo 'selected="selected"'; ?> >09</option>
-	<option value="10" <?php if((!$formSent && $thisMonth == 10) || ($formSent && $month_start == 10)) echo 'selected="selected"'; ?> >10</option>
-	<option value="11" <?php if((!$formSent && $thisMonth == 11) || ($formSent && $month_start == 11)) echo 'selected="selected"'; ?> >11</option>
-	<option value="12" <?php if((!$formSent && $thisMonth == 12) || ($formSent && $month_start == 12)) echo 'selected="selected"'; ?> >12</option>
-  </select>
-  /
-  <select name="year_start">
-<?php
-for ($i=$thisYear-5;$i <= ($thisYear+5);$i++) {
-?>
-	<option value="<?php echo $i; ?>" <?php if((!$formSent && $thisYear == $i) || ($formSent && $year_start == $i)) echo 'selected="selected"'; ?> ><?php echo $i; ?></option>
-<?php
+//Coaches
+//$coaches = SessionManager::get_user_list();
+$form->addElement('select', 'id_coach', get_lang('CoachName'), array(),array('id' => 'coach_id'));
+$form->addRule('id_coach', get_lang('ThisFieldIsRequired'), 'required');
+
+$form->addElement('advanced_settings','<a class="btn btn-show" id="advanced_parameters" href="javascript://">'.get_lang('AdvancedParameters').'</a>');
+$form->addElement('html','<div id="options" style="display:none">');
+
+//Dates
+$form->addElement('text', 'display_start_date', array(get_lang('SessionDisplayStartDate'), get_lang('SessionDisplayStartDateComment')), array('id' => 'display_start_date'));
+$form->addElement('text', 'display_end_date', array(get_lang('SessionDisplayEndDate'), get_lang('SessionDisplayEndDateComment')), array('id' => 'display_end_date'));
+$form->addRule(array('display_start_date', 'display_end_date'), get_lang('StartDateMustBeBeforeTheEndDate'), 'compare_datetime_text', '< allow_empty');
+     
+$form->addElement('text', 'access_start_date', array(get_lang('SessionStartDate'), get_lang('SessionStartDateComment')), array('id' => 'access_start_date'));
+$form->addElement('text', 'access_end_date', array(get_lang('SessionEndDate'), get_lang('SessionEndDateComment')), array('id' => 'access_end_date'));
+$form->addRule(array('access_start_date', 'access_end_date'), get_lang('StartDateMustBeBeforeTheEndDate'), 'compare_datetime_text', '< allow_empty');
+
+//Visibility
+$visibility_list = array(SESSION_VISIBLE_READ_ONLY=>get_lang('SessionReadOnly'), SESSION_VISIBLE=>get_lang('SessionAccessible'), SESSION_INVISIBLE=>api_ucfirst(get_lang('SessionNotAccessible')));
+
+$form->addElement('html','<div id="visibility_container">');
+$form->addElement('select', 'visibility', get_lang('SessionVisibility'), $visibility_list, array('id' => 'visibility'));
+$form->addElement('html','</div>');
+
+$form->addElement('text', 'coach_access_start_date', array(get_lang('SessionCoachStartDate'), get_lang('SessionCoachStartDateComment')), array('id' => 'coach_access_start_date'));
+$form->addElement('text', 'coach_access_end_date', array(get_lang('SessionCoachEndDate'), get_lang('SessionCoachEndDateComment')), array('id' => 'coach_access_end_date'));
+$form->addRule(array('coach_access_start_date', 'coach_access_end_date'), get_lang('StartDateMustBeBeforeTheEndDate'), 'compare_datetime_text', '< allow_empty');
+
+//Session categories
+
+$categories = SessionManager::get_all_session_category();
+
+$select_categories = array();
+if (!empty($categories)) {
+    $select_categories = array('0' => get_lang('None'));
+    foreach ($categories as $row) {
+        $select_categories[$row['id']] = $row['name'];
+    }
 }
-?>
-    </select>  
-    </div>
-       
-        </div>        
-    </div>   
+$form->addElement('select', 'session_category_id', get_lang('SessionCategory'), $select_categories, array('id' => 'session_category_id_name', 'class' => null));
 
+//Extra session fields
+$session_field = new SessionField();
+$extra = $session_field->add_elements($form, $id);
 
-    
- <div class="control-group">
-        <div class="controls">            
-            <label for="end_limit">
-                <input id="end_limit" type="checkbox" name="end_limit" onchange="disable_endtime(this)" />
-                <?php echo get_lang('DateEndSession') ?>
-            </label>
-  <div id="end_date" style="display:none">
-  <br />
-  
-  <select name="day_end">
-	<option value="1">01</option>
-	<option value="2" <?php if((!$formSent && $thisDay == 2) || ($formSent && $day_end == 2)) echo 'selected="selected"'; ?> >02</option>
-	<option value="3" <?php if((!$formSent && $thisDay == 3) || ($formSent && $day_end == 3)) echo 'selected="selected"'; ?> >03</option>
-	<option value="4" <?php if((!$formSent && $thisDay == 4) || ($formSent && $day_end == 4)) echo 'selected="selected"'; ?> >04</option>
-	<option value="5" <?php if((!$formSent && $thisDay == 5) || ($formSent && $day_end == 5)) echo 'selected="selected"'; ?> >05</option>
-	<option value="6" <?php if((!$formSent && $thisDay == 6) || ($formSent && $day_end == 6)) echo 'selected="selected"'; ?> >06</option>
-	<option value="7" <?php if((!$formSent && $thisDay == 7) || ($formSent && $day_end == 7)) echo 'selected="selected"'; ?> >07</option>
-	<option value="8" <?php if((!$formSent && $thisDay == 8) || ($formSent && $day_end == 8)) echo 'selected="selected"'; ?> >08</option>
-	<option value="9" <?php if((!$formSent && $thisDay == 9) || ($formSent && $day_end == 9)) echo 'selected="selected"'; ?> >09</option>
-	<option value="10" <?php if((!$formSent && $thisDay == 10) || ($formSent && $day_end == 10)) echo 'selected="selected"'; ?> >10</option>
-	<option value="11" <?php if((!$formSent && $thisDay == 11) || ($formSent && $day_end == 11)) echo 'selected="selected"'; ?> >11</option>
-	<option value="12" <?php if((!$formSent && $thisDay == 12) || ($formSent && $day_end == 12)) echo 'selected="selected"'; ?> >12</option>
-	<option value="13" <?php if((!$formSent && $thisDay == 13) || ($formSent && $day_end == 13)) echo 'selected="selected"'; ?> >13</option>
-	<option value="14" <?php if((!$formSent && $thisDay == 14) || ($formSent && $day_end == 14)) echo 'selected="selected"'; ?> >14</option>
-	<option value="15" <?php if((!$formSent && $thisDay == 15) || ($formSent && $day_end == 15)) echo 'selected="selected"'; ?> >15</option>
-	<option value="16" <?php if((!$formSent && $thisDay == 16) || ($formSent && $day_end == 16)) echo 'selected="selected"'; ?> >16</option>
-	<option value="17" <?php if((!$formSent && $thisDay == 17) || ($formSent && $day_end == 17)) echo 'selected="selected"'; ?> >17</option>
-	<option value="18" <?php if((!$formSent && $thisDay == 18) || ($formSent && $day_end == 18)) echo 'selected="selected"'; ?> >18</option>
-	<option value="19" <?php if((!$formSent && $thisDay == 19) || ($formSent && $day_end == 19)) echo 'selected="selected"'; ?> >19</option>
-	<option value="20" <?php if((!$formSent && $thisDay == 20) || ($formSent && $day_end == 20)) echo 'selected="selected"'; ?> >20</option>
-	<option value="21" <?php if((!$formSent && $thisDay == 21) || ($formSent && $day_end == 21)) echo 'selected="selected"'; ?> >21</option>
-	<option value="22" <?php if((!$formSent && $thisDay == 22) || ($formSent && $day_end == 22)) echo 'selected="selected"'; ?> >22</option>
-	<option value="23" <?php if((!$formSent && $thisDay == 23) || ($formSent && $day_end == 23)) echo 'selected="selected"'; ?> >23</option>
-	<option value="24" <?php if((!$formSent && $thisDay == 24) || ($formSent && $day_end == 24)) echo 'selected="selected"'; ?> >24</option>
-	<option value="25" <?php if((!$formSent && $thisDay == 25) || ($formSent && $day_end == 25)) echo 'selected="selected"'; ?> >25</option>
-	<option value="26" <?php if((!$formSent && $thisDay == 26) || ($formSent && $day_end == 26)) echo 'selected="selected"'; ?> >26</option>
-	<option value="27" <?php if((!$formSent && $thisDay == 27) || ($formSent && $day_end == 27)) echo 'selected="selected"'; ?> >27</option>
-	<option value="28" <?php if((!$formSent && $thisDay == 28) || ($formSent && $day_end == 28)) echo 'selected="selected"'; ?> >28</option>
-	<option value="29" <?php if((!$formSent && $thisDay == 29) || ($formSent && $day_end == 29)) echo 'selected="selected"'; ?> >29</option>
-	<option value="30" <?php if((!$formSent && $thisDay == 30) || ($formSent && $day_end == 30)) echo 'selected="selected"'; ?> >30</option>
-	<option value="31" <?php if((!$formSent && $thisDay == 31) || ($formSent && $day_end == 31)) echo 'selected="selected"'; ?> >31</option>
-  </select>
-  /
-  <select name="month_end">
-	<option value="1">01</option>
-	<option value="2" <?php if((!$formSent && $thisMonth == 2) || ($formSent && $month_end == 2)) echo 'selected="selected"'; ?> >02</option>
-	<option value="3" <?php if((!$formSent && $thisMonth == 3) || ($formSent && $month_end == 3)) echo 'selected="selected"'; ?> >03</option>
-	<option value="4" <?php if((!$formSent && $thisMonth == 4) || ($formSent && $month_end == 4)) echo 'selected="selected"'; ?> >04</option>
-	<option value="5" <?php if((!$formSent && $thisMonth == 5) || ($formSent && $month_end == 5)) echo 'selected="selected"'; ?> >05</option>
-	<option value="6" <?php if((!$formSent && $thisMonth == 6) || ($formSent && $month_end == 6)) echo 'selected="selected"'; ?> >06</option>
-	<option value="7" <?php if((!$formSent && $thisMonth == 7) || ($formSent && $month_end == 7)) echo 'selected="selected"'; ?> >07</option>
-	<option value="8" <?php if((!$formSent && $thisMonth == 8) || ($formSent && $month_end == 8)) echo 'selected="selected"'; ?> >08</option>
-	<option value="9" <?php if((!$formSent && $thisMonth == 9) || ($formSent && $month_end == 9)) echo 'selected="selected"'; ?> >09</option>
-	<option value="10" <?php if((!$formSent && $thisMonth == 10) || ($formSent && $month_end == 10)) echo 'selected="selected"'; ?> >10</option>
-	<option value="11" <?php if((!$formSent && $thisMonth == 11) || ($formSent && $month_end == 11)) echo 'selected="selected"'; ?> >11</option>
-	<option value="12" <?php if((!$formSent && $thisMonth == 12) || ($formSent && $month_end == 12)) echo 'selected="selected"'; ?> >12</option>
-  </select>
-  /
-  <select name="year_end">
 
-<?php
-for ($i=$thisYear-5;$i <= ($thisYear+5);$i++) {
-?>
-	<option value="<?php echo $i; ?>" <?php if((!$formSent && ($thisYear+1) == $i) || ($formSent && $year_end == $i)) echo 'selected="selected"'; ?> ><?php echo $i; ?></option>
-<?php
-}
-?>
-    </select>
-    <br />    <br />
-    <?php echo get_lang('SessionVisibility') ?>
-    <select name="session_visibility" style="width:250px;">
-        <?php
-        $visibility_list = array(SESSION_VISIBLE_READ_ONLY=>get_lang('SessionReadOnly'), SESSION_VISIBLE=>get_lang('SessionAccessible'), SESSION_INVISIBLE=>api_ucfirst(get_lang('SessionNotAccessible')));
-        foreach($visibility_list as $key=>$item): ?>
-        <option value="<?php echo $key; ?>" <?php if($item == $visibility_id) echo 'selected="selected"'; ?>><?php echo $item; ?></option>
-        <?php endforeach; ?>
-    </select>    
-     </div>  
-       
-        </div>        
-    </div>   
-    
-    
- <div class="control-group">        
-    <div class="controls">
-        <button class="save" type="submit" value="<?php echo get_lang('NextStep') ?>"><?php echo get_lang('NextStep') ?></button>
-    </div>
-</div>
-</form>
-<script type="text/javascript">
-
-function setDisable(select){
-	document.form.day_start.disabled = (select.checked) ? true : false;
-	document.form.month_start.disabled = (select.checked) ? true : false;
-	document.form.year_start.disabled = (select.checked) ? true : false;
-
-	document.form.day_end.disabled = (select.checked) ? true : false;
-	document.form.month_end.disabled = (select.checked) ? true : false;
-	document.form.year_end.disabled = (select.checked) ? true : false;
-
-	document.form.session_visibility.disabled = (select.checked) ? true : false;
-	document.form.session_visibility.selectedIndex = 0;
-    
-    document.form.start_limit.disabled = (select.checked) ? true : false;
-    document.form.start_limit.checked = false;
-    document.form.end_limit.disabled = (select.checked) ? true : false;
-    document.form.end_limit.checked = false;
-       
-    var end_div = document.getElementById('end_date');
-    end_div.style.display = 'none';
-        
-    var start_div = document.getElementById('start_date');
-    start_div.style.display = 'none';        
+$htmlHeadXtra[] ='
+<script>
+
+$(function() {
+    '.$extra['jquery_ready_content'].'
+});
+</script>';
+
+$form->addElement('html','</div>');
+      
+$form->addElement('button', 'submit', $button);
+
+if (!empty($session_info)) {
+    $session_info['display_start_date'] = api_get_local_time($session_info['display_start_date'], null, null, true);
+    $session_info['display_end_date'] = api_get_local_time($session_info['display_end_date'], null, null, true);
+    $session_info['access_start_date'] = api_get_local_time($session_info['access_start_date'], null, null, true);
+    $session_info['access_end_date'] = api_get_local_time($session_info['access_end_date'], null, null, true);
+    $session_info['coach_access_start_date'] = api_get_local_time($session_info['coach_access_start_date'], null, null, true);
+    $session_info['coach_access_end_date'] = api_get_local_time($session_info['coach_access_end_date'], null, null, true);    
+    $form->setDefaults($session_info);
 }
 
-function disable_endtime(select) {
-    var end_div = document.getElementById('end_date');
-    if (end_div.style.display == 'none')
-        end_div.style.display = 'block';
-     else 
-        end_div.style.display = 'none';
+if ($form->validate()) {
+    $params = $form->getSubmitValues();
+    if (isset($params['id'])) {
+        SessionManager::update($params);
+        header('Location: resume_session.php?id_session='.$params['id']);
+		exit;
+    } else {
+        $session_id = SessionManager::add($params);        
+        if ($session_id) {
+            // integer => no error on session creation
+            header('Location: add_courses_to_session.php?id_session='.$session_id.'&add=true&msg=');
+            exit;
+        }
+    }
 }
 
-function disable_starttime(select) {
-    var start_div = document.getElementById('start_date');
-    if (start_div.style.display == 'none')
-        start_div.style.display = 'block';
-     else 
-        start_div.style.display = 'none';
+function check_session_name($name) {    
+    $session = SessionManager::get_session_by_name($name);    
+    return empty($session) ? true : false;
 }
-</script>
-<?php
+
+Display::display_header($tool_name);
+
+echo '<div class="actions">';
+echo '<a href="../admin/index.php">'.Display::return_icon('back.png', get_lang('BackTo').' '.get_lang('PlatformAdmin'),'',ICON_SIZE_MEDIUM).'</a>';
+echo '</div>';
+
+$form->display();
 Display::display_footer();

+ 12 - 12
main/admin/session_course_edit.php

@@ -13,10 +13,10 @@ require_once '../inc/global.inc.php';
 $id_session = intval($_GET['id_session']);
 SessionManager::protect_session_edit($id_session);
 
-$course_code=trim(stripslashes($_GET['course_code']));
+$course_code = Database::escape_string($_GET['course_code']);
 
-$formSent=0;
-$errorMsg='';
+$formSent = 0;
+$errorMsg = '';
 
 // Database Table Definitions
 $tbl_user			= Database::get_main_table(TABLE_MAIN_USER);
@@ -26,14 +26,15 @@ $tbl_session_course	= Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
 $tbl_session_rel_course_rel_user	= Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
 
 $course_info=api_get_course_info($_REQUEST['course_code']);
-$tool_name=$course_info['name'];
+$tool_name = $course_info['name'];
 
 $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" =>api_htmlentities($session_name,ENT_QUOTES,$charset));
 
-$result = Database::query("SELECT s.name, c.title FROM $tbl_session_course sc,$tbl_session s,$tbl_course c WHERE sc.id_session=s.id AND sc.course_code=c.code AND sc.id_session='$id_session' AND sc.course_code='".addslashes($course_code)."'");
+$result = Database::query("SELECT s.name, c.title FROM $tbl_session_course sc,$tbl_session s,$tbl_course c 
+                           WHERE sc.id_session=s.id AND sc.course_code=c.code AND sc.id_session='$id_session' AND sc.course_code='".$course_code."'");
 
 if (!list($session_name,$course_title)=Database::fetch_row($result)) {
 	header('Location: session_course_list.php?id_session='.$id_session);
@@ -68,7 +69,7 @@ if ($_POST['formSent']) {
 		$array_intersect = array_diff($coachs_course_session,$id_coachs);
 
 		foreach ($array_intersect as $nocoach_user_id) {
-			$rs2 = SessionManager::set_coach_to_course_session($nocoach_user_id, $id_session, $course_code,true);
+			$rs2 = SessionManager::set_coach_to_course_session($nocoach_user_id, $id_session, $course_code, true);
 		}
 
 		header('Location: '.Security::remove_XSS($_GET['page']).'?id_session='.$id_session);
@@ -96,19 +97,18 @@ if ($_configuration['multiple_access_urls']) {
     $sql="SELECT user_id,lastname,firstname,username FROM $tbl_user WHERE status='1'".$order_clause;
 }
 
-$result=Database::query($sql);
+$result = Database::query($sql);
 
-$coaches=Database::store_result($result);
+$coaches = Database::store_result($result);
 
 Display::display_header($tool_name);
 
-$tool_name=get_lang('ModifySessionCourse');
-api_display_tool_title($tool_name);
+$tool_name = get_lang('ModifySessionCourse');
+echo Display::page_header($tool_name);
 ?>
 <form method="post" action="<?php echo api_get_self(); ?>?id_session=<?php echo $id_session; ?>&course_code=<?php echo urlencode($course_code); ?>&page=<?php echo Security::remove_XSS($_GET['page']) ?>" style="margin:0px;">
 <input type="hidden" name="formSent" value="1">
-
-<table border="0" cellpadding="5" cellspacing="0" width="600px">
+<table>
 
 <?php
 if(!empty($errorMsg)) {

+ 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();

+ 0 - 397
main/admin/session_edit.php

@@ -1,397 +0,0 @@
-<?php
-/* For licensing terms, see /license.txt */
-
-// name of the language file that needs to be included
-$language_file ='admin';
-$cidReset = true;
-require_once '../inc/global.inc.php';
-
-// setting the section (for the tabs)
-$this_section = SECTION_PLATFORM_ADMIN;
-
-
-
-$formSent = 0;
-
-// Database Table Definitions
-$tbl_user		= Database::get_main_table(TABLE_MAIN_USER);
-$tbl_session	= Database::get_main_table(TABLE_MAIN_SESSION);
-
-$id = intval($_GET['id']);
-
-SessionManager::protect_session_edit($id);
-
-$sql = "SELECT name,date_start,date_end,id_coach, session_admin_id, nb_days_access_before_beginning, nb_days_access_after_end, session_category_id, visibility
-        FROM $tbl_session WHERE id = $id";
-$result = Database::query($sql);
-
-if (!$infos = Database::fetch_array($result)) {
-    header('Location: session_list.php');
-    exit();
-}
-
-$id_coach   = $infos['id_coach'];
-
-
-
-$tool_name = get_lang('EditSession');
-
-$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,"name" => get_lang('SessionOverview'));
-
-list($year_start,$month_start,$day_start)   = explode('-',$infos['date_start']);
-list($year_end,$month_end,$day_end)         = explode('-',$infos['date_end']);
-
-$end_year_disabled = $end_month_disabled = $end_day_disabled = '';
-
-if ($_POST['formSent']) {
-	$formSent = 1;
-
-	$name                  = $_POST['name'];
-	$year_start            = $_POST['year_start'];
-	$month_start           = $_POST['month_start'];
-	$day_start             = $_POST['day_start'];
-	$year_end              = $_POST['year_end'];
-	$month_end             = $_POST['month_end'];
-	$day_end               = $_POST['day_end'];
-	$nb_days_acess_before  = $_POST['nb_days_access_before'];
-	$nb_days_acess_after   = $_POST['nb_days_access_after'];
-	//$nolimit               = $_POST['nolimit'];
-	$id_coach              = $_POST['id_coach'];
-	$id_session_category   = $_POST['session_category'];
-	$id_visibility         = $_POST['session_visibility'];
-
-    $end_limit              = $_POST['end_limit'];
-    $start_limit            = $_POST['start_limit'];
-
-    if (empty($end_limit) && empty($start_limit)) {
-        $nolimit = 1;
-    } else {
-        $nolimit = null;
-    }
-
-	$return = SessionManager::edit_session($id,$name,$year_start,$month_start,$day_start,$year_end,$month_end,$day_end,$nb_days_acess_before,$nb_days_acess_after,$nolimit, $id_coach, $id_session_category,$id_visibility,$start_limit,$end_limit);
-	if ($return == strval(intval($return))) {
-		header('Location: resume_session.php?id_session='.$return);
-		exit();
-	}
-}
-
-$order_clause = api_sort_by_first_name() ? ' ORDER BY firstname, lastname, username' : ' ORDER BY lastname, firstname, username';
-$sql="SELECT user_id,lastname,firstname,username FROM $tbl_user WHERE status='1'".$order_clause;
-
-if ($_configuration['multiple_access_urls']) {
-	$table_access_url_rel_user= Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
-	$access_url_id = api_get_current_access_url_id();
-	if ($access_url_id != -1) {
-		$sql="SELECT DISTINCT u.user_id,lastname,firstname,username FROM $tbl_user u INNER JOIN $table_access_url_rel_user url_rel_user ON (url_rel_user.user_id = u.user_id)
-			  WHERE status='1' AND access_url_id = '$access_url_id' $order_clause";
-	}
-}
-
-$result     = Database::query($sql);
-$Coaches    = Database::store_result($result);
-$thisYear   = date('Y');
-
-// display the header
-Display::display_header($tool_name);
-
-// display the tool title
-// api_display_tool_title($tool_name);
-
-if (!empty($return)) {
-	Display::display_error_message($return,false);
-}
-?>
-
-<form class="form-horizontal" method="post" name="form" action="<?php echo api_get_self(); ?>?page=<?php echo Security::remove_XSS($_GET['page']) ?>&id=<?php echo $id; ?>" style="margin:0px;">
-<fieldset>
-    <legend><?php echo $tool_name; ?></legend>
-    <input type="hidden" name="formSent" value="1">
-
-    <div class="control-group">
-        <label class="control-label">
-            <?php echo get_lang('SessionName') ?>
-        </label>
-        <div class="controls">
-            <input type="text" name="name" class="span4" maxlength="50" value="<?php if($formSent) echo api_htmlentities($name,ENT_QUOTES,$charset); else echo api_htmlentities($infos['name'],ENT_QUOTES,$charset); ?>">
-        </div>
-    </div>
-    <div class="control-group">
-        <label class="control-label">
-            <?php echo get_lang('CoachName') ?>
-        </label>
-        <div class="controls">
-            <select class="chzn-select" name="id_coach" style="width:380px;" title="<?php echo get_lang('Choose'); ?>" >
-                <option value="">----- <?php echo get_lang('None') ?> -----</option>
-                <?php foreach($Coaches as $enreg) { ?>
-                <option value="<?php echo $enreg['user_id']; ?>" <?php if(($enreg['user_id'] == $infos['id_coach']) || ($enreg['user_id'] == $id_coach)) echo 'selected="selected"'; ?>><?php echo api_get_person_name($enreg['firstname'], $enreg['lastname']).' ('.$enreg['username'].')'; ?></option>
-                <?php
-                }
-                unset($Coaches);
-                $Categories = SessionManager::get_all_session_category();
-            ?>
-        </select>
-        </div>
-    </div>
-    <div class="control-group">
-        <label class="control-label">
-            <?php echo get_lang('SessionCategory') ?>
-        </label>
-        <div class="controls">
-                <select class="chzn-select" id="session_category" name="session_category" style="width:380px;" title="<?php echo get_lang('Select'); ?>">
-        <option value="0"><?php get_lang('None'); ?></option>
-        <?php
-          if (!empty($Categories)) {
-              foreach($Categories as $Rows)  { ?>
-                <option value="<?php echo $Rows['id']; ?>" <?php if($Rows['id'] == $infos['session_category_id']) echo 'selected="selected"'; ?>><?php echo $Rows['name']; ?></option>
-        <?php }
-          }
-         ?>
-    </select>
-        </div>
-    </div>
-    <div class="control-group">
-        <div class="controls">
-            <a href="javascript://" onclick="if(document.getElementById('options').style.display == 'none'){document.getElementById('options').style.display = 'block';}else{document.getElementById('options').style.display = 'none';}"><?php echo get_lang('DefineSessionOptions') ?></a>
-        </div>
-    </div>
-    <div class="control-group">
-        <div class="controls">
-            <div style="display:
-            <?php
-                if($formSent){
-                    if($nb_days_access_before!=0 || $nb_days_access_after!=0)
-                        echo 'block';
-                    else echo 'none';
-                }
-                else{
-                    if($infos['nb_days_access_before_beginning']!=0 || $infos['nb_days_access_after_end']!=0)
-                        echo 'block';
-                    else
-                        echo 'none';
-                }
-            ?>
-                ;" id="options">
-
-            <input type="text" name="nb_days_access_before" value="<?php if($formSent) echo api_htmlentities($nb_days_access_before,ENT_QUOTES,$charset); else echo api_htmlentities($infos['nb_days_access_before_beginning'],ENT_QUOTES,$charset); ?>" style="width: 30px;">&nbsp;<?php echo get_lang('DaysBefore') ?>
-                <br />
-                <br />
-            <input type="text" name="nb_days_access_after" value="<?php if($formSent) echo api_htmlentities($nb_days_access_after,ENT_QUOTES,$charset); else echo api_htmlentities($infos['nb_days_access_after_end'],ENT_QUOTES,$charset); ?>" style="width: 30px;">&nbsp;<?php echo get_lang('DaysAfter') ?>
-
-            </div>
-        </div>
-    </div>
-
-    <div class="clear"></div>
-    <div class="control-group">
-        <div class="controls">
-            <label for="start_limit">
-                <input id="start_limit" type="checkbox" name="start_limit" onchange="disable_starttime(this)" <?php if ($year_start!="0000") echo "checked"; ?>/>
-            <?php echo get_lang('DateStartSession');?>
-            </label>
-            <div id="start_date" style="<?php echo ($year_start=="0000") ? "display:none" : "display:block" ; ?>">
-            <br />
-              <select name="day_start">
-                <option value="1">01</option>
-                <option value="2" <?php if($day_start == 2) echo 'selected="selected"'; ?> >02</option>
-                <option value="3" <?php if($day_start == 3) echo 'selected="selected"'; ?> >03</option>
-                <option value="4" <?php if($day_start == 4) echo 'selected="selected"'; ?> >04</option>
-                <option value="5" <?php if($day_start == 5) echo 'selected="selected"'; ?> >05</option>
-                <option value="6" <?php if($day_start == 6) echo 'selected="selected"'; ?> >06</option>
-                <option value="7" <?php if($day_start == 7) echo 'selected="selected"'; ?> >07</option>
-                <option value="8" <?php if($day_start == 8) echo 'selected="selected"'; ?> >08</option>
-                <option value="9" <?php if($day_start == 9) echo 'selected="selected"'; ?> >09</option>
-                <option value="10" <?php if($day_start == 10) echo 'selected="selected"'; ?> >10</option>
-                <option value="11" <?php if($day_start == 11) echo 'selected="selected"'; ?> >11</option>
-                <option value="12" <?php if($day_start == 12) echo 'selected="selected"'; ?> >12</option>
-                <option value="13" <?php if($day_start == 13) echo 'selected="selected"'; ?> >13</option>
-                <option value="14" <?php if($day_start == 14) echo 'selected="selected"'; ?> >14</option>
-                <option value="15" <?php if($day_start == 15) echo 'selected="selected"'; ?> >15</option>
-                <option value="16" <?php if($day_start == 16) echo 'selected="selected"'; ?> >16</option>
-                <option value="17" <?php if($day_start == 17) echo 'selected="selected"'; ?> >17</option>
-                <option value="18" <?php if($day_start == 18) echo 'selected="selected"'; ?> >18</option>
-                <option value="19" <?php if($day_start == 19) echo 'selected="selected"'; ?> >19</option>
-                <option value="20" <?php if($day_start == 20) echo 'selected="selected"'; ?> >20</option>
-                <option value="21" <?php if($day_start == 21) echo 'selected="selected"'; ?> >21</option>
-                <option value="22" <?php if($day_start == 22) echo 'selected="selected"'; ?> >22</option>
-                <option value="23" <?php if($day_start == 23) echo 'selected="selected"'; ?> >23</option>
-                <option value="24" <?php if($day_start == 24) echo 'selected="selected"'; ?> >24</option>
-                <option value="25" <?php if($day_start == 25) echo 'selected="selected"'; ?> >25</option>
-                <option value="26" <?php if($day_start == 26) echo 'selected="selected"'; ?> >26</option>
-                <option value="27" <?php if($day_start == 27) echo 'selected="selected"'; ?> >27</option>
-                <option value="28" <?php if($day_start == 28) echo 'selected="selected"'; ?> >28</option>
-                <option value="29" <?php if($day_start == 29) echo 'selected="selected"'; ?> >29</option>
-                <option value="30" <?php if($day_start == 30) echo 'selected="selected"'; ?> >30</option>
-                <option value="31" <?php if($day_start == 31) echo 'selected="selected"'; ?> >31</option>
-              </select>
-              /
-              <select name="month_start">
-                <option value="1">01</option>
-                <option value="2" <?php if($month_start == 2) echo 'selected="selected"'; ?> >02</option>
-                <option value="3" <?php if($month_start == 3) echo 'selected="selected"'; ?> >03</option>
-                <option value="4" <?php if($month_start == 4) echo 'selected="selected"'; ?> >04</option>
-                <option value="5" <?php if($month_start == 5) echo 'selected="selected"'; ?> >05</option>
-                <option value="6" <?php if($month_start == 6) echo 'selected="selected"'; ?> >06</option>
-                <option value="7" <?php if($month_start == 7) echo 'selected="selected"'; ?> >07</option>
-                <option value="8" <?php if($month_start == 8) echo 'selected="selected"'; ?> >08</option>
-                <option value="9" <?php if($month_start == 9) echo 'selected="selected"'; ?> >09</option>
-                <option value="10" <?php if($month_start == 10) echo 'selected="selected"'; ?> >10</option>
-                <option value="11" <?php if($month_start == 11) echo 'selected="selected"'; ?> >11</option>
-                <option value="12" <?php if($month_start == 12) echo 'selected="selected"'; ?> >12</option>
-              </select>
-              /
-              <select name="year_start">
-
-            <?php
-            for($i=$thisYear-5;$i <= ($thisYear+5);$i++) { ?>
-                <option value="<?php echo $i; ?>" <?php if($year_start == $i) echo 'selected="selected"'; ?> ><?php echo $i; ?></option>
-            <?php
-            }
-            ?>
-              </select>
-          </div>
-        </div>
-    </div>
-
-    <div class="control-group">
-        <div class="controls">
-            <label for="end_limit">
-                <input id="end_limit" type="checkbox" name="end_limit" onchange="disable_endtime(this)" <?php if ($year_end!="0000") echo "checked"; ?>/>
-            <?php echo get_lang('DateEndSession') ?>
-            </label>
-          <div id="end_date" style="<?php echo ($year_end=="0000") ? "display:none" : "display:block" ; ?>">
-          <br />
-
-          <select name="day_end" <?php echo $end_day_disabled; ?> >
-        	<option value="1">01</option>
-        	<option value="2" <?php if($day_end == 2) echo 'selected="selected"'; ?> >02</option>
-        	<option value="3" <?php if($day_end == 3) echo 'selected="selected"'; ?> >03</option>
-        	<option value="4" <?php if($day_end == 4) echo 'selected="selected"'; ?> >04</option>
-        	<option value="5" <?php if($day_end == 5) echo 'selected="selected"'; ?> >05</option>
-        	<option value="6" <?php if($day_end == 6) echo 'selected="selected"'; ?> >06</option>
-        	<option value="7" <?php if($day_end == 7) echo 'selected="selected"'; ?> >07</option>
-        	<option value="8" <?php if($day_end == 8) echo 'selected="selected"'; ?> >08</option>
-        	<option value="9" <?php if($day_end == 9) echo 'selected="selected"'; ?> >09</option>
-        	<option value="10" <?php if($day_end == 10) echo 'selected="selected"'; ?> >10</option>
-        	<option value="11" <?php if($day_end == 11) echo 'selected="selected"'; ?> >11</option>
-        	<option value="12" <?php if($day_end == 12) echo 'selected="selected"'; ?> >12</option>
-        	<option value="13" <?php if($day_end == 13) echo 'selected="selected"'; ?> >13</option>
-        	<option value="14" <?php if($day_end == 14) echo 'selected="selected"'; ?> >14</option>
-        	<option value="15" <?php if($day_end == 15) echo 'selected="selected"'; ?> >15</option>
-        	<option value="16" <?php if($day_end == 16) echo 'selected="selected"'; ?> >16</option>
-        	<option value="17" <?php if($day_end == 17) echo 'selected="selected"'; ?> >17</option>
-        	<option value="18" <?php if($day_end == 18) echo 'selected="selected"'; ?> >18</option>
-        	<option value="19" <?php if($day_end == 19) echo 'selected="selected"'; ?> >19</option>
-        	<option value="20" <?php if($day_end == 20) echo 'selected="selected"'; ?> >20</option>
-        	<option value="21" <?php if($day_end == 21) echo 'selected="selected"'; ?> >21</option>
-        	<option value="22" <?php if($day_end == 22) echo 'selected="selected"'; ?> >22</option>
-        	<option value="23" <?php if($day_end == 23) echo 'selected="selected"'; ?> >23</option>
-        	<option value="24" <?php if($day_end == 24) echo 'selected="selected"'; ?> >24</option>
-        	<option value="25" <?php if($day_end == 25) echo 'selected="selected"'; ?> >25</option>
-        	<option value="26" <?php if($day_end == 26) echo 'selected="selected"'; ?> >26</option>
-        	<option value="27" <?php if($day_end == 27) echo 'selected="selected"'; ?> >27</option>
-        	<option value="28" <?php if($day_end == 28) echo 'selected="selected"'; ?> >28</option>
-        	<option value="29" <?php if($day_end == 29) echo 'selected="selected"'; ?> >29</option>
-        	<option value="30" <?php if($day_end == 30) echo 'selected="selected"'; ?> >30</option>
-        	<option value="31" <?php if($day_end == 31) echo 'selected="selected"'; ?> >31</option>
-          </select>
-          /
-          <select name="month_end" <?php echo $end_month_disabled; ?> >
-        	<option value="1">01</option>
-        	<option value="2" <?php if($month_end == 2) echo 'selected="selected"'; ?> >02</option>
-        	<option value="3" <?php if($month_end == 3) echo 'selected="selected"'; ?> >03</option>
-        	<option value="4" <?php if($month_end == 4) echo 'selected="selected"'; ?> >04</option>
-        	<option value="5" <?php if($month_end == 5) echo 'selected="selected"'; ?> >05</option>
-        	<option value="6" <?php if($month_end == 6) echo 'selected="selected"'; ?> >06</option>
-        	<option value="7" <?php if($month_end == 7) echo 'selected="selected"'; ?> >07</option>
-        	<option value="8" <?php if($month_end == 8) echo 'selected="selected"'; ?> >08</option>
-        	<option value="9" <?php if($month_end == 9) echo 'selected="selected"'; ?> >09</option>
-        	<option value="10" <?php if($month_end == 10) echo 'selected="selected"'; ?> >10</option>
-        	<option value="11" <?php if($month_end == 11) echo 'selected="selected"'; ?> >11</option>
-        	<option value="12" <?php if($month_end == 12) echo 'selected="selected"'; ?> >12</option>
-          </select>
-          /
-          <select name="year_end" <?php echo $end_year_disabled; ?>>
-
-        <?php
-        for($i=$thisYear-5;$i <= ($thisYear+5);$i++) {
-        ?>
-        	<option value="<?php echo $i; ?>" <?php if($year_end == $i) echo 'selected="selected"'; ?> ><?php echo $i; ?></option>
-        <?php
-        }
-        ?>
-          </select>
-           <br />      <br />
-
-            <?php echo get_lang('SessionVisibility') ?> <br />
-            <select name="session_visibility" style="width:250px;">
-                <?php
-                $visibility_list = array(SESSION_VISIBLE_READ_ONLY=>get_lang('SessionReadOnly'), SESSION_VISIBLE=>get_lang('SessionAccessible'), SESSION_INVISIBLE=>api_ucfirst(get_lang('SessionNotAccessible')));
-                foreach($visibility_list as $key=>$item): ?>
-                <option value="<?php echo $key; ?>" <?php if($key == $infos['visibility']) echo 'selected="selected"'; ?>><?php echo $item; ?></option>
-                <?php endforeach; ?>
-            </select>
-    </div>
-    </div>
-  </div>
-
-    <div class="control-group">
-        <div class="controls">
-            <button class="save" type="submit" value="<?php echo get_lang('ModifyThisSession') ?>"><?php echo get_lang('ModifyThisSession') ?></button>
-        </div>
-    </div>
-</fieldset>
-</form>
-
-<script type="text/javascript">
-
-<?php if($year_start=="0000") echo "setDisable(document.form.nolimit);\r\n"; ?>
-
-function setDisable(select){
-
-	document.form.day_start.disabled = (select.checked) ? true : false;
-	document.form.month_start.disabled = (select.checked) ? true : false;
-	document.form.year_start.disabled = (select.checked) ? true : false;
-
-	document.form.day_end.disabled = (select.checked) ? true : false;
-	document.form.month_end.disabled = (select.checked) ? true : false;
-	document.form.year_end.disabled = (select.checked) ? true : false;
-
-	document.form.session_visibility.disabled = (select.checked) ? true : false;
-	document.form.session_visibility.selectedIndex = 0;
-
-    document.form.start_limit.disabled = (select.checked) ? true : false;
-    document.form.start_limit.checked = false;
-    document.form.end_limit.disabled = (select.checked) ? true : false;
-    document.form.end_limit.checked = false;
-
-    var end_div = document.getElementById('end_date');
-    end_div.style.display = 'none';
-
-    var start_div = document.getElementById('start_date');
-    start_div.style.display = 'none';
-
-
-}
-
-function disable_endtime(select) {
-    var end_div = document.getElementById('end_date');
-    if (end_div.style.display == 'none')
-        end_div.style.display = 'block';
-     else
-        end_div.style.display = 'none';
-}
-
-function disable_starttime(select) {
-    var start_div = document.getElementById('start_date');
-    if (start_div.style.display == 'none')
-        start_div.style.display = 'block';
-     else
-        start_div.style.display = 'none';
-}
-
-</script>
-<?php
-Display::display_footer();

+ 185 - 205
main/admin/session_export.php

@@ -1,7 +1,8 @@
 <?php
+
 /**
-*	@package chamilo.admin
-*/
+ * 	@package chamilo.admin
+ */
 // name of the language file that needs to be included
 $language_file = 'admin';
 
@@ -13,237 +14,216 @@ include '../inc/global.inc.php';
 $this_section = SECTION_PLATFORM_ADMIN;
 
 api_protect_admin_script(true);
-include api_get_path(LIBRARY_PATH).'fileManage.lib.php';
+include api_get_path(LIBRARY_PATH) . 'fileManage.lib.php';
 
 $session_id = intval($_GET['session_id']);
 $formSent = 0;
 $errorMsg = '';
 
 // Database Table Definitions
-$tbl_user					= Database::get_main_table(TABLE_MAIN_USER);
-$tbl_course      			= Database::get_main_table(TABLE_MAIN_COURSE);
-$tbl_course_user 			= Database::get_main_table(TABLE_MAIN_COURSE_USER);
-$tbl_session      			= Database::get_main_table(TABLE_MAIN_SESSION);
-$tbl_session_user      		= Database::get_main_table(TABLE_MAIN_SESSION_USER);
-$tbl_session_course      	= Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
-$tbl_session_course_user 	= Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
-
+$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_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
+$tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
 
 $archivePath = api_get_path(SYS_ARCHIVE_PATH);
-$archiveURL  = api_get_path(WEB_CODE_PATH).'course_info/download.php?archive=';
+$archiveURL = api_get_path(WEB_CODE_PATH) . 'course_info/download.php?archive=';
 
-$tool_name   = get_lang('ExportSessionListXMLCSV');
+$tool_name = get_lang('ExportSessionListXMLCSV');
 
 global $_configuration;
 
-
-$interbreadcrumb[] = array('url' => 'index.php',"name" => get_lang('PlatformAdmin'));
+$interbreadcrumb[] = array('url' => 'index.php', "name" => get_lang('PlatformAdmin'));
 
 set_time_limit(0);
 
 if ($_POST['formSent']) {
-	$formSent = $_POST['formSent'];
-	$file_type = ($_POST['file_type'] == 'csv')?'csv':'xml';
-	$session_id = $_POST['session_id'];
-	if (empty($session_id)) {
-		$sql = "SELECT id,name,id_coach,username,date_start,date_end,visibility,session_category_id FROM $tbl_session INNER JOIN $tbl_user
-					ON $tbl_user.user_id = $tbl_session.id_coach ORDER BY id";
-
-		
-		if ($_configuration['multiple_access_urls']) {
-			$tbl_session_rel_access_url= Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
-			$access_url_id = api_get_current_access_url_id();
-			if ($access_url_id != -1){
-			$sql = "SELECT id, name,id_coach,username,date_start,date_end,visibility,session_category_id FROM $tbl_session s INNER JOIN $tbl_session_rel_access_url as session_rel_url
+    $formSent = $_POST['formSent'];
+    $file_type = ($_POST['file_type'] == 'csv') ? 'csv' : 'xml';
+    $session_id = $_POST['session_id'];
+    if (empty($session_id)) {
+        $sql = "SELECT id,name,id_coach,username,access_start_date,access_end_date,visibility,session_category_id 
+                FROM $tbl_session INNER JOIN $tbl_user
+				ON $tbl_user.user_id = $tbl_session.id_coach ORDER BY id";
+        if ($_configuration['multiple_access_urls']) {
+            $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
+            $access_url_id = api_get_current_access_url_id();
+            if ($access_url_id != -1) {
+                $sql = "SELECT id, name,id_coach,username,access_start_date,access_end_date,visibility,session_category_id 
+                FROM $tbl_session s INNER JOIN $tbl_session_rel_access_url as session_rel_url
 				ON (s.id= session_rel_url.session_id) INNER JOIN $tbl_user u ON (u.user_id = s.id_coach)
 				WHERE access_url_id = $access_url_id
 				ORDER BY id";
-
-			}
-		}
-		$result=Database::query($sql);
-	}
-	else
-	{
-		$sql = "SELECT id,name,username,date_start,date_end,visibility,session_category_id
+            }
+        }
+        $result = Database::query($sql);
+    } else {
+        $sql = "SELECT id,name,username,access_start_date,access_end_date,visibility,session_category_id
 				FROM $tbl_session
 				INNER JOIN $tbl_user
 					ON $tbl_user.user_id = $tbl_session.id_coach
 				WHERE id='$session_id'";
 
-		$result = Database::query($sql);
-
-	}
-
-	if(Database::num_rows($result))
-	{
-		if(!file_exists($archivePath))
-		{
-			mkdir($archivePath, api_get_permissions_for_new_directories(), true);
-		}
-
-		if(!file_exists($archivePath.'index.html'))
-		{
-			$fp=fopen($archivePath.'index.html','w');
-
-			fputs($fp,'<html><head></head><body></body></html>');
-
-			fclose($fp);
-		}
-
-		$archiveFile='export_sessions_'.$session_id.'_'.date('Y-m-d_H-i-s').'.'.$file_type;
-
-		while( file_exists($archivePath.$archiveFile))
-		{
-			$archiveFile='export_users_'.$session_id.'_'.date('Y-m-d_H-i-s').'_'.uniqid('').'.'.$file_type;
-		}
-		$fp=fopen($archivePath.$archiveFile,'w');
-
-		if($file_type == 'csv')
-		{
-			$cvs = true;
-			fputs($fp,"SessionName;Coach;DateStart;DateEnd;Visibility;SessionCategory;Users;Courses;\n");
-		}
-		else
-		{
-			$cvs = false;
-			fputs($fp, "<?xml version=\"1.0\" encoding=\"".api_get_system_encoding()."\"?>\n<Sessions>\n");
-		}
-
-		while($row=Database::fetch_array($result))
-		{
-			$add = '';
-			$row['name'] = str_replace(';',',',$row['name']);
-			$row['username'] = str_replace(';',',',$row['username']);
-			$row['date_start'] = str_replace(';',',',$row['date_start']);
-			$row['date_end'] = str_replace(';',',',$row['date_end']);
-			$row['visibility'] = str_replace(';',',',$row['visibility']);
-			$row['session_category'] = str_replace(';',',',$row['session_category_id']);
-			if($cvs){
-				$add.= $row['name'].';'.$row['username'].';'.$row['date_start'].';'.$row['date_end'].';'.$row['visibility'].';'.$row['session_category'].';';
-			}
-			else {
-				$add = "\t<Session>\n"
-						 ."\t\t<SessionName>$row[name]</SessionName>\n"
-						 ."\t\t<Coach>$row[username]</Coach>\n"
-						 ."\t\t<DateStart>$row[date_start]</DateStart>\n"
-						 ."\t\t<DateEnd>$row[date_end]</DateEnd>\n"
-						 ."\t\t<Visibility>$row[visibility]</Visibility>\n"
-						 ."\t\t<SessionCategory>$row[session_category]</SessionCategory>\n";
-			}
-
-			//users
-			$sql = "SELECT DISTINCT $tbl_user.username FROM $tbl_user
+        $result = Database::query($sql);
+    }
+
+    if (Database::num_rows($result)) {
+        if (!file_exists($archivePath)) {
+            mkdir($archivePath, api_get_permissions_for_new_directories(), true);
+        }
+
+        if (!file_exists($archivePath . 'index.html')) {
+            $fp = fopen($archivePath . 'index.html', 'w');
+
+            fputs($fp, '<html><head></head><body></body></html>');
+
+            fclose($fp);
+        }
+
+        $archiveFile = 'export_sessions_' . $session_id . '_' . date('Y-m-d_H-i-s') . '.' . $file_type;
+
+        while (file_exists($archivePath . $archiveFile)) {
+            $archiveFile = 'export_users_' . $session_id . '_' . date('Y-m-d_H-i-s') . '_' . uniqid('') . '.' . $file_type;
+        }
+        $fp = fopen($archivePath . $archiveFile, 'w');
+
+        if ($file_type == 'csv') {
+            $cvs = true;
+            fputs($fp, "SessionName;Coach;DateStart;DateEnd;Visibility;SessionCategory;Users;Courses;\n");
+        } else {
+            $cvs = false;
+            fputs($fp, "<?xml version=\"1.0\" encoding=\"" . api_get_system_encoding() . "\"?>\n<Sessions>\n");
+        }
+
+        while ($row = Database::fetch_array($result)) {
+            $add = '';
+            $row['name'] = str_replace(';', ',', $row['name']);
+            $row['username'] = str_replace(';', ',', $row['username']);
+            $row['access_start_date'] = str_replace(';', ',', api_get_local_time($row['access_start_date'], null, null, true));
+            $row['access_end_date'] = str_replace(';', ',', api_get_local_time($row['access_end_date'], null, null, true));
+            $row['visibility'] = str_replace(';', ',', $row['visibility']);
+            $row['session_category'] = str_replace(';', ',', $row['session_category_id']);
+            if ($cvs) {
+                $add.= $row['name'] . ';' . $row['username'] . ';' . $row['access_start_date'] . ';' . $row['access_end_date'] . ';' . $row['visibility'] . ';' . $row['session_category'] . ';';
+            } else {
+                $add = "\t<Session>\n"
+                        . "\t\t<SessionName>$row[name]</SessionName>\n"
+                        . "\t\t<Coach>$row[username]</Coach>\n"
+                        . "\t\t<DateStart>$row[access_start_date]</DateStart>\n"
+                        . "\t\t<DateEnd>$row[access_end_date]</DateEnd>\n"
+                        . "\t\t<Visibility>$row[visibility]</Visibility>\n"
+                        . "\t\t<SessionCategory>$row[session_category]</SessionCategory>\n";
+            }
+
+            //users
+            $sql = "SELECT DISTINCT $tbl_user.username FROM $tbl_user
 					INNER JOIN $tbl_session_user
-						ON $tbl_user.user_id = $tbl_session_user.id_user AND $tbl_session_user.relation_type<>".SESSION_RELATION_TYPE_RRHH."
-						AND $tbl_session_user.id_session = '".$row['id']."'";
-
-			$rsUsers = Database::query($sql);
-			$users = '';
-			while($rowUsers = Database::fetch_array($rsUsers)){
-				if($cvs){
-					$users .= str_replace(';',',',$rowUsers['username']).'|';
-				}
-				else {
-					$users .= "\t\t<User>$rowUsers[username]</User>\n";
-				}
-			}
-			if(!empty($users) && $cvs)
-				$users = api_substr($users , 0, api_strlen($users)-1);
-
-			if($cvs)
-				$users .= ';';
-
-			$add .= $users;
-
-			//courses
-			$sql = "SELECT DISTINCT $tbl_course.code
+						ON $tbl_user.user_id = $tbl_session_user.id_user AND $tbl_session_user.relation_type<>" . SESSION_RELATION_TYPE_RRHH . "
+						AND $tbl_session_user.id_session = '" . $row['id'] . "'";
+
+            $rsUsers = Database::query($sql);
+            $users = '';
+            while ($rowUsers = Database::fetch_array($rsUsers)) {
+                if ($cvs) {
+                    $users .= str_replace(';', ',', $rowUsers['username']) . '|';
+                } else {
+                    $users .= "\t\t<User>$rowUsers[username]</User>\n";
+                }
+            }
+            if (!empty($users) && $cvs)
+                $users = api_substr($users, 0, api_strlen($users) - 1);
+
+            if ($cvs)
+                $users .= ';';
+
+            $add .= $users;
+
+            //courses
+            $sql = "SELECT DISTINCT $tbl_course.code
 					FROM $tbl_course
 					INNER JOIN $tbl_session_course_user
 						ON $tbl_course.code = $tbl_session_course_user.course_code
-						AND $tbl_session_course_user.id_session = '".$row['id']."'";
+						AND $tbl_session_course_user.id_session = '" . $row['id'] . "'";
 
-			$rsCourses = Database::query($sql);
+            $rsCourses = Database::query($sql);
 
-			$courses = '';
-			while($rowCourses = Database::fetch_array($rsCourses)){
+            $courses = '';
+            while ($rowCourses = Database::fetch_array($rsCourses)) {
 
-				// get coachs from a course
-				$sql = "SELECT u.username
+                // get coachs from a course
+                $sql = "SELECT u.username
 					FROM $tbl_session_course_user scu
 					INNER JOIN $tbl_user u ON u.user_id = scu.id_user
 					WHERE scu.course_code = '{$rowCourses['code']}'
-						AND scu.id_session = '".$row['id']."' AND scu.status = 2 ";
-
-				$rs_coachs = Database::query($sql);
-				$coachs = array();
-				while ($row_coachs = Database::fetch_array($rs_coachs)) {
-					$coachs[] = $row_coachs['username'];
-				}
-
-				$coachs = implode(",",$coachs);
-
-				if($cvs){
-					$courses .= str_replace(';',',',$rowCourses['code']);
-					$courses .= '['.str_replace(';',',',$coachs).'][';
-				}
-				else {
-					$courses .= "\t\t<Course>\n";
-					$courses .= "\t\t\t<CourseCode>$rowCourses[code]</CourseCode>\n";
-					$courses .= "\t\t\t<Coach>$coachs</Coach>\n";
-				}
-
-				// rel user courses
-				$sql = "SELECT DISTINCT u.username
+						AND scu.id_session = '" . $row['id'] . "' AND scu.status = 2 ";
+
+                $rs_coachs = Database::query($sql);
+                $coachs = array();
+                while ($row_coachs = Database::fetch_array($rs_coachs)) {
+                    $coachs[] = $row_coachs['username'];
+                }
+
+                $coachs = implode(",", $coachs);
+                if ($cvs) {
+                    $courses .= str_replace(';', ',', $rowCourses['code']);
+                    $courses .= '[' . str_replace(';', ',', $coachs) . '][';
+                } else {
+                    $courses .= "\t\t<Course>\n";
+                    $courses .= "\t\t\t<CourseCode>$rowCourses[code]</CourseCode>\n";
+                    $courses .= "\t\t\t<Coach>$coachs</Coach>\n";
+                }
+
+                // rel user courses
+                $sql = "SELECT DISTINCT u.username
 						FROM $tbl_session_course_user scu
-						INNER JOIN $tbl_session_user su ON scu.id_user = su.id_user AND scu.id_session = su.id_session AND su.relation_type<>".SESSION_RELATION_TYPE_RRHH."
+						INNER JOIN $tbl_session_user su ON scu.id_user = su.id_user AND scu.id_session = su.id_session AND su.relation_type<>" . SESSION_RELATION_TYPE_RRHH . "
 						INNER JOIN $tbl_user u
 						ON scu.id_user = u.user_id
-						AND scu.course_code='".$rowCourses['code']."'
-						AND scu.id_session='".$row['id']."'";
-
-				$rsUsersCourse = Database::query($sql);
-				$userscourse = '';
-				while($rowUsersCourse = Database::fetch_array($rsUsersCourse)){
-
-					if($cvs){
-						$userscourse .= str_replace(';',',',$rowUsersCourse['username']).',';
-					}
-					else {
-						$courses .= "\t\t\t<User>$rowUsersCourse[username]</User>\n";
-					}
-				}
-				if($cvs){
-					if(!empty($userscourse))
-						$userscourse = api_substr($userscourse , 0, api_strlen($userscourse)-1);
-
-					$courses .= $userscourse.']|';
-				}
-				else {
-					$courses .= "\t\t</Course>\n";
-				}
-			}
-
-			if(!empty($courses) && $cvs)
-				$courses = api_substr($courses , 0, api_strlen($courses)-1);
-			$add .= $courses;
-
-			if($cvs) {
-				$breakline = api_is_windows_os()?"\r\n":"\n";
-				$add .= ";$breakline";
-			} else {
-				$add .= "\t</Session>\n";
-			}
-
-			fputs($fp, $add);
-		}
-
-		if(!$cvs)
-			fputs($fp,"</Sessions>\n");
-		fclose($fp);
-
-		$errorMsg=get_lang('UserListHasBeenExported').'<br/><a class="btn" href="'.$archiveURL.$archiveFile.'">'.get_lang('ClickHereToDownloadTheFile').'</a>';
-	}
+						AND scu.course_code='" . $rowCourses['code'] . "'
+						AND scu.id_session='" . $row['id'] . "'";
+
+                $rsUsersCourse = Database::query($sql);
+                $userscourse = '';
+                while ($rowUsersCourse = Database::fetch_array($rsUsersCourse)) {
+
+                    if ($cvs) {
+                        $userscourse .= str_replace(';', ',', $rowUsersCourse['username']) . ',';
+                    } else {
+                        $courses .= "\t\t\t<User>$rowUsersCourse[username]</User>\n";
+                    }
+                }
+                if ($cvs) {
+                    if (!empty($userscourse))
+                        $userscourse = api_substr($userscourse, 0, api_strlen($userscourse) - 1);
+
+                    $courses .= $userscourse . ']|';
+                }
+                else {
+                    $courses .= "\t\t</Course>\n";
+                }
+            }
+
+            if (!empty($courses) && $cvs)
+                $courses = api_substr($courses, 0, api_strlen($courses) - 1);
+            $add .= $courses;
+
+            if ($cvs) {
+                $breakline = api_is_windows_os() ? "\r\n" : "\n";
+                $add .= ";$breakline";
+            } else {
+                $add .= "\t</Session>\n";
+            }
+
+            fputs($fp, $add);
+        }
+
+        if (!$cvs)
+            fputs($fp, "</Sessions>\n");
+        fclose($fp);
+
+        $errorMsg = get_lang('UserListHasBeenExported') . '<br/><a class="btn" href="' . $archiveURL . $archiveFile . '">' . get_lang('ClickHereToDownloadTheFile') . '</a>';
+    }
 }
 
 // display the header
@@ -253,29 +233,29 @@ Display::display_header($tool_name);
 $sql = "SELECT id, name FROM $tbl_session ORDER BY name";
 
 if ($_configuration['multiple_access_urls']) {
-	$tbl_session_rel_access_url= Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
-	$access_url_id = api_get_current_access_url_id();
-	if ($access_url_id != -1){
-	$sql = "SELECT id, name FROM $tbl_session s INNER JOIN $tbl_session_rel_access_url as session_rel_url
+    $tbl_session_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_SESSION);
+    $access_url_id = api_get_current_access_url_id();
+    if ($access_url_id != -1) {
+        $sql = "SELECT id, name FROM $tbl_session s INNER JOIN $tbl_session_rel_access_url as session_rel_url
 		ON (s.id= session_rel_url.session_id)
 		WHERE access_url_id = $access_url_id
 		ORDER BY name";
-	}
+    }
 }
 $result = Database::query($sql);
 $Sessions = Database::store_result($result);
 
 echo '<div class="actions">';
-echo '<a href="../admin/index.php">'.Display::return_icon('back.png', get_lang('BackTo').' '.get_lang('PlatformAdmin'),'',ICON_SIZE_MEDIUM).'</a>';
+echo '<a href="../admin/index.php">' . Display::return_icon('back.png', get_lang('BackTo') . ' ' . get_lang('PlatformAdmin'), '', ICON_SIZE_MEDIUM) . '</a>';
 echo '</div>';
 
 if (!empty($errorMsg)) {
-	Display::display_normal_message($errorMsg, false); //main API
+    Display::display_normal_message($errorMsg, false); //main API
 }
 
 $form = new FormValidator('session_export', 'post', api_get_self());
 $form->addElement('hidden', 'formSent', 1);
-$form->addElement('radio', 'file_type', get_lang('OutputFileType'), 'CSV' , 'csv', null, array('id' => 'file_type_csv'));
+$form->addElement('radio', 'file_type', get_lang('OutputFileType'), 'CSV', 'csv', null, array('id' => 'file_type_csv'));
 $form->addElement('radio', 'file_type', null, 'XML', 'xml', null, array('id' => 'file_type_xml'));
 
 $options = array();
@@ -284,7 +264,7 @@ foreach ($Sessions as $enreg) {
     $options[$enreg['id']] = $enreg['name'];
 }
 
-$form->addElement('select', 'session_id', get_lang('WhichSessionToExport'),  $options);
+$form->addElement('select', 'session_id', get_lang('WhichSessionToExport'), $options);
 $form->addElement('button', 'submit', get_lang('ExportSession'));
 
 $defaults = array();

+ 200 - 0
main/admin/session_fields.php

@@ -0,0 +1,200 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+/**
+ *  @package chamilo.admin
+ */
+
+// Language files that need to be included.
+$language_file = array('admin');
+
+$cidReset = true;
+require_once '../inc/global.inc.php';
+
+$this_section = SECTION_PLATFORM_ADMIN;
+
+api_protect_admin_script();
+
+//Add the JS needed to use the jqgrid
+$htmlHeadXtra[] = api_get_jqgrid_js();
+
+// setting breadcrumbs
+$interbreadcrumb[]=array('url' => 'index.php','name' => get_lang('PlatformAdmin'));
+
+$tool_name = null;
+
+$action = isset($_GET['action']) ? $_GET['action'] : null;
+
+$check = Security::check_token('request');
+$token = Security::get_token();    
+
+if ($action == 'add') {
+    $interbreadcrumb[]=array('url' => 'session_fields.php','name' => get_lang('SessionFields'));
+    $interbreadcrumb[]=array('url' => '#','name' => get_lang('Add'));
+} elseif ($action == 'edit') {
+    $interbreadcrumb[]=array('url' => 'session_fields.php','name' => get_lang('SessionFields'));    
+    $interbreadcrumb[]=array('url' => '#','name' => get_lang('Edit'));
+} else {
+    $interbreadcrumb[]=array('url' => '#','name' => get_lang('SessionFields'));
+}
+
+//jqgrid will use this URL to do the selects
+$url            = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_extra_fields&type=session';
+
+//The order is important you need to check the the $column variable in the model.ajax.php file 
+$columns        = array(get_lang('Name'), get_lang('FieldLabel'),  get_lang('Type'), get_lang('FieldChangeability'), get_lang('Visibility'), get_lang('Filter'), get_lang('FieldOrder'), get_lang('Actions'));
+
+//Column config
+$column_model   = array(
+                        array('name'=>'field_display_text', 'index'=>'field_display_text',      'width'=>'180',   'align'=>'left'),
+                        array('name'=>'field_variable',     'index'=>'field_variable',          'width'=>'',  'align'=>'left','sortable'=>'true'),
+                        array('name'=>'field_type',         'index'=>'field_type',              'width'=>'',  'align'=>'left','sortable'=>'true'),    
+                        array('name'=>'field_changeable',   'index'=>'field_changeable',        'width'=>'50',  'align'=>'left','sortable'=>'true'),    
+                        array('name'=>'field_visible',      'index'=>'field_visible',           'width'=>'40',  'align'=>'left','sortable'=>'true'),                            
+                        array('name'=>'field_filter',       'index'=>'field_filter',            'width'=>'30',  'align'=>'left','sortable'=>'true'),
+                        array('name'=>'field_order',        'index'=>'field_order',             'width'=>'40',  'align'=>'left','sortable'=>'true'),    
+                        array('name'=>'actions',            'index'=>'actions',                 'width'=>'100',  'align'=>'left','formatter'=>'action_formatter','sortable'=>'false')
+);
+
+//Autowidth             
+$extra_params['autowidth'] = 'true';
+//height auto 
+$extra_params['height'] = 'auto';
+$extra_params['sortname'] = 'field_order';
+
+//With this function we can add actions to the jgrid (edit, delete, etc)
+$action_links = 'function action_formatter(cellvalue, options, rowObject) {
+                         return \'<a href="?action=edit&id=\'+options.rowId+\'">'.Display::return_icon('edit.png',get_lang('Edit'),'',ICON_SIZE_SMALL).'</a>'.
+                         '&nbsp;<a onclick="javascript:if(!confirm('."\'".addslashes(api_htmlentities(get_lang("ConfirmYourChoice"),ENT_QUOTES))."\'".')) return false;"  href="?sec_token='.$token.'&action=delete&id=\'+options.rowId+\'">'.Display::return_icon('delete.png',get_lang('Delete'),'',ICON_SIZE_SMALL).'</a>'.
+                         '\'; 
+                 }';
+$htmlHeadXtra[]='
+<script>
+$(function() {
+    // grid definition see the $obj->display() function
+    '.Display::grid_js('session_fields',  $url, $columns, $column_model, $extra_params, array(), $action_links,true).'
+            
+    $("#field_type").on("change", function() {      
+        id = $(this).val();        
+        switch(id) {
+            case "1":
+                $("#example").html("'.addslashes(Display::return_icon('userfield_text.png')).'"); 
+                break;
+            case "2":        
+                $("#example").html("'.addslashes(Display::return_icon('userfield_text_area.png')).'"); 
+                break;
+            case "3":     
+                $("#example").html("'.addslashes(Display::return_icon('add_user_field_howto.png')).'");            
+                break;
+            case "4":
+                $("#example").html("'.addslashes(Display::return_icon('userfield_drop_down.png')).'");
+                break;
+            case "5":
+                $("#example").html("'.addslashes(Display::return_icon('userfield_multidropdown.png')).'");
+                break;
+            case "6":
+                $("#example").html("'.addslashes(Display::return_icon('userfield_data.png')).'");
+                break;
+            case "7":
+                $("#example").html("'.addslashes(Display::return_icon('userfield_date_time.png')).'");
+                break;
+            case "8":
+                $("#example").html("'.addslashes(Display::return_icon('userfield_doubleselect.png')).'");
+                break;
+            case "9":
+                $("#example").html("'.addslashes(Display::return_icon('userfield_divider.png')).'");
+                break;
+            case "10":
+                $("#example").html("'.addslashes(Display::return_icon('userfield_user_tag.png')).'");
+                break;
+            case "11":
+                $("#example").html("'.addslashes(Display::return_icon('userfield_data.png')).'");                                            
+                break;
+        }
+    });
+
+    var value = 1;
+    $("#advanced_parameters").on("click", function() {
+        $("#options").toggle(function() {        
+            if (value == 1) {
+                $("#advanced_parameters").addClass("btn-hide");        
+                value = 0;
+            } else {
+                $("#advanced_parameters").removeClass("btn-hide");      
+                value = 1;
+            }
+        });
+    });
+});
+</script>';
+
+// The header.
+Display::display_header($tool_name);
+
+$obj = new SessionField();
+
+// Action handling: Add
+switch ($action) {
+    case 'add':
+        if (api_get_session_id() != 0 && !api_is_allowed_to_session_edit(false, true)) {
+            api_not_allowed();
+        }        
+        $url  = api_get_self().'?action='.Security::remove_XSS($_GET['action']);
+        $form = $obj->return_form($url, 'add');
+
+        // The validation or display
+        if ($form->validate()) {          
+            if ($check) {
+                $values = $form->exportValues();       
+                $res    = $obj->save($values);            
+                if ($res) {
+                    Display::display_confirmation_message(get_lang('ItemAdded'));
+                }
+            }        
+            $obj->display();
+        } else {
+            echo '<div class="actions">';
+            echo '<a href="'.api_get_self().'">'.Display::return_icon('back.png',get_lang('Back'),'',ICON_SIZE_MEDIUM).'</a>';
+            echo '</div>';            
+            $form->addElement('hidden', 'sec_token');
+            $form->setConstants(array('sec_token' => $token));
+            $form->display();
+        }
+        break;
+    case 'edit':
+        // Action handling: Editing 
+        $url  = api_get_self().'?action='.Security::remove_XSS($_GET['action']).'&id='.intval($_GET['id']);
+        $form = $obj->return_form($url, 'edit');    
+
+        // The validation or display
+        if ($form->validate()) {            
+            if ($check) {
+                $values = $form->exportValues();                
+                $res    = $obj->update($values);                
+                Display::display_confirmation_message(sprintf(get_lang('ItemUpdated'), $values['name']), false);                
+            }            
+            $obj->display();
+        } else {
+            echo '<div class="actions">';
+            echo '<a href="'.api_get_self().'">'.Display::return_icon('back.png',get_lang('Back'),'',ICON_SIZE_MEDIUM).'</a>';
+            echo '</div>';
+            $form->addElement('hidden', 'sec_token');
+            $form->setConstants(array('sec_token' => $token));
+            $form->display();
+        }
+        break;
+    case 'delete':
+        // Action handling: delete
+        if ($check) {
+            $res = $obj->delete($_GET['id']);
+            if ($res) {
+                Display::display_confirmation_message(get_lang('ItemDeleted'));
+            }
+        }
+        $obj->display();
+        break;
+    default:
+        $obj->display();   
+        break;
+}
+Display :: display_footer();

+ 69 - 100
main/admin/session_import.php

@@ -22,10 +22,7 @@ if (isset($_GET['action']) && $_GET['action'] == 'show_message') {
     $error_message = Security::remove_XSS($_GET['message']);
 }
 
-
 $tbl_user                   = Database::get_main_table(TABLE_MAIN_USER);
-$tbl_course                 = Database::get_main_table(TABLE_MAIN_COURSE);
-$tbl_course_user            = Database::get_main_table(TABLE_MAIN_COURSE_USER);
 $tbl_session                = Database::get_main_table(TABLE_MAIN_SESSION);
 $tbl_session_user           = Database::get_main_table(TABLE_MAIN_SESSION_USER);
 $tbl_session_course         = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
@@ -56,9 +53,7 @@ if ($_POST['formSent']) {
         $session_counter = 0;
 
         if ($file_type == 'xml') {
-
             // XML
-
             // SimpleXML for PHP5 deals with various encodings, but how many they are, what are version issues, do we need to waste time with configuration options?
             // For avoiding complications we go some sort of "PHP4 way" - we convert the input xml-file into UTF-8 before passing it to the parser.
             // Instead of:
@@ -161,7 +156,7 @@ if ($_POST['formSent']) {
                         $params['user_id']          = api_get_user_id();
                         
                         // Looking up for the teacher.
-                        $username       = trim(api_utf8_decode($courseNode->CourseTeacher));
+                        $username = trim(api_utf8_decode($courseNode->CourseTeacher));
                         $sql = "SELECT user_id, lastname, firstname FROM $tbl_user WHERE username='$username'";
                         $rs = Database::query($sql);
                         list($user_id, $lastname, $firstname) = Database::fetch_array($rs);
@@ -193,30 +188,7 @@ if ($_POST['formSent']) {
                         }
 
                         $date_start = trim(api_utf8_decode($node_session->DateStart)); // Just in case - encoding conversion.
-
-                        if (!empty($date_start)) {
-                            list($year_start, $month_start, $day_start) = explode('/', $date_start);
-                            if(empty($year_start) || empty($month_start) || empty($day_start)) {
-                                $error_message .= get_lang('WrongDate').' : '.$date_start.'<br />';
-                                break;
-                            } else {
-                                $time_start = mktime(0, 0, 0, $month_start, $day_start, $year_start);
-                            }
-
-                            $date_end = trim(api_utf8_decode($node_session->DateEnd));
-                            if (!empty($date_start)) {
-                                list($year_end, $month_end, $day_end) = explode('/', $date_end);
-                                if (empty($year_end) || empty($month_end) || empty($day_end)) {
-                                    $error_message .= get_lang('Error').' : '.$date_end.'<br />';
-                                    break;
-                                } else {
-                                    $time_end = mktime(0, 0, 0, $month_end, $day_end, $year_end);
-                                }
-                            }
-                            if ($time_end - $time_start < 0) {
-                                $error_message .= get_lang('StartDateShouldBeBeforeEndDate').' : '.$date_end.'<br />';
-                            }
-                        }
+                        $date_end = trim(api_utf8_decode($node_session->DateEnd));                                                
 
                         $visibility = trim(api_utf8_decode($node_session->Visibility));
                         $session_category_id = trim(api_utf8_decode($node_session->SessionCategory));
@@ -239,45 +211,48 @@ if ($_POST['formSent']) {
                                     $session_name .= $suffix;
                                 }
                             }
-                            // Creating the session.
-                            $sql_session = "INSERT IGNORE INTO $tbl_session SET
-                                    name = '".Database::escape_string($session_name)."',
-                                    id_coach = '$coach_id',
-                                    date_start = '$date_start',
-                                    date_end = '$date_end',
-                                    visibility = '$visibility',
-                                    session_category_id = '$session_category_id',
-                                    session_admin_id=".intval($_user['user_id']);
-                            $rs_session = Database::query($sql_session);
-                            $session_id = Database::insert_id();
+                            
+                            $params = array (
+                                'id_coach' => $coach_id,
+                                'visibility' => $visibility,
+                                'name' => $session_name,
+                                'access_start_date' => $date_start,
+                                'access_end_date' => $date_end,
+                                'session_category_id' => $session_category_id,
+                                'session_admin_id' => api_get_user_id(),
+                            );
+                            $session_id = SessionManager::add($params);                            
                             $session_counter++;
 
                         } else {
                             // Update the session if it is needed.
                             $my_session_result = SessionManager::get_session_by_name($session_name);
+                            
                             if ($my_session_result === false) {
-                                // Creating the session.
-                                $sql_session = "INSERT IGNORE INTO $tbl_session SET
-                                        name = '".Database::escape_string($session_name)."',
-                                        id_coach = '$coach_id',
-                                        date_start = '$date_start',
-                                        date_end = '$date_end',
-                                        visibility = '$visibility',
-                                        session_category_id = '$session_category_id',
-                                        session_admin_id=".intval($_user['user_id']);
-                                $rs_session = Database::query($sql_session);
-                                $session_id = Database::insert_id();
+                                $params = array (
+                                    'id_coach' => $coach_id,
+                                    'visibility' => $visibility,
+                                    'name' => $session_name,
+                                    'access_start_date' => $date_start,
+                                    'access_end_date' => $date_end,
+                                    'session_category_id' => $session_category_id,
+                                    'session_admin_id' => api_get_user_id(),
+                                );
+                                $session_id = SessionManager::add($params);                                      
                                 $session_counter++;
                             } else {
-                                // if the session already exists - update it.
-                                $sql_session = "UPDATE $tbl_session SET
-                                        id_coach = '$coach_id',
-                                        date_start = '$date_start',
-                                        date_end = '$date_end',
-                                        visibility = '$visibility',
-                                        session_category_id = '$session_category_id'
-                                    WHERE name = '$session_name'";
-                                $rs_session = Database::query($sql_session);
+                                
+                                $params = array (
+                                    'id' => $my_session_result['id'],
+                                    'id_coach' => $coach_id,
+                                    'visibility' => $visibility,
+                                    'name' => $session_name,
+                                    'access_start_date' => $date_start,
+                                    'access_end_date' => $date_end,
+                                    'session_category_id' => $session_category_id,
+                                    'session_admin_id' => api_get_user_id(),
+                                );
+                                SessionManager::update($params);                                
                                 $session_id = Database::query("SELECT id FROM $tbl_session WHERE name='$session_name'");
                                 list($session_id) = Database::fetch_array($session_id);
                                 Database::query("DELETE FROM $tbl_session_user WHERE id_session='$session_id'");
@@ -296,7 +271,6 @@ if ($_POST['formSent']) {
                             UrlManager::add_session_to_url($session_id, 1);
                         }
 
-
                         // Adding users to the new session.
                         foreach ($node_session->User as $node_user) {
                             $username = UserManager::purify_username(api_utf8_decode($node_user), $purification_option_for_usernames);
@@ -522,49 +496,44 @@ if ($_POST['formSent']) {
                                 $session_name .= $suffix;
                             }
                         }
-
-                        // Creating the session.
-                        $sql_session = "INSERT IGNORE INTO $tbl_session SET
-                                name = '".Database::escape_string($session_name)."',
-                                id_coach = '$coach_id',
-                                date_start = '$date_start',
-                                date_end = '$date_end',
-                                visibility = '$visibility',
-                                session_category_id = '$session_category_id',
-                                session_admin_id=".intval($_user['user_id']);
-                        $rs_session = Database::query($sql_session);
-                        $session_id = Database::insert_id();
+                        
+                        $params = array (
+                            'id_coach' => $coach_id,
+                            'visibility' => $visibility,
+                            'name' => $session_name,
+                            'access_start_date' => $date_start,
+                            'access_end_date' => $date_end,
+                            'session_category_id' => $session_category_id,
+                            'session_admin_id' => api_get_user_id(),
+                        );
+                        $session_id = SessionManager::add($params); 
                         $session_counter++;
                     } else {
                         $my_session_result = SessionManager::get_session_by_name($session_name);
                         if ($my_session_result === false) {
-
-                            // Creating a session.
-                            $sql_session = "INSERT IGNORE INTO $tbl_session SET
-                                    name = '$session_name',
-                                    id_coach = '$coach_id',
-                                    date_start = '$date_start',
-                                    date_end = '$date_end',
-                                    visibility = '$visibility',
-                                    session_category_id = '$session_category_id'";
-
-                            $rs_session = Database::query($sql_session);
-                            // We get the last insert id.
-                            $my_session_result = SessionManager::get_session_by_name($session_name);
-                            $session_id = $my_session_result['id'];
-                            //echo '<br>';
+                            $params = array (
+                                'id_coach' => $coach_id,
+                                'visibility' => $visibility,
+                                'name' => $session_name,
+                                'access_start_date' => $date_start,
+                                'access_end_date' => $date_end,
+                                'session_category_id' => $session_category_id,
+                                'session_admin_id' => api_get_user_id(),
+                            );
+                            $session_id = SessionManager::add($params); 
                         } else {
-                            // The session already exists, update it then.
-                            $sql_session = "UPDATE $tbl_session SET
-                                    id_coach = '$coach_id',
-                                    date_start = '$date_start',
-                                    date_end = '$date_end',
-                                    visibility = '$visibility',
-                                    session_category_id = '$session_category_id'
-                                WHERE name = '$session_name'";
-                            $rs_session = Database::query($sql_session);
-                            $session_id = Database::query("SELECT id FROM $tbl_session WHERE name='$session_name'");
-                            list($session_id) = Database::fetch_array($session_id);
+                            $session_id = $my_session_result['id'];
+                            $params = array (
+                                'id' => $session_id,
+                                'id_coach' => $coach_id,
+                                'visibility' => $visibility,
+                                'name' => $session_name,
+                                'access_start_date' => $date_start,
+                                'access_end_date' => $date_end,
+                                'session_category_id' => $session_category_id,
+                                'session_admin_id' => api_get_user_id(),
+                            );
+                            SessionManager::update($params);
                             Database::query("DELETE FROM $tbl_session_user WHERE id_session='$session_id'");
                             Database::query("DELETE FROM $tbl_session_course WHERE id_session='$session_id'");
                             Database::query("DELETE FROM $tbl_session_course_user WHERE id_session='$session_id'");

+ 178 - 72
main/admin/session_list.php

@@ -11,6 +11,10 @@ api_protect_admin_script(true);
 
 //Add the JS needed to use the jqgrid
 $htmlHeadXtra[] = api_get_jqgrid_js();
+$htmlHeadXtra[] = api_get_js('json-js/json2.js');
+$htmlHeadXtra[] = api_get_js('date/date.js');
+
+$htmlHeadXtra = api_get_datetime_picker_js($htmlHeadXtra);
 
 $action = $_REQUEST['action'];
 $idChecked = $_REQUEST['idChecked'];
@@ -20,12 +24,12 @@ if ($action == 'delete') {
 	header('Location: session_list.php');
 	exit();
 } elseif ($action == 'copy') {
-	SessionManager::copy_session($idChecked);
+	SessionManager::copy_session($idChecked, true, false);
     header('Location: session_list.php');
     exit();
 }
 
-$interbreadcrumb[]=array("url" => "index.php","name" => get_lang('PlatformAdmin'));
+$interbreadcrumb[] = array("url" => "index.php","name" => get_lang('PlatformAdmin'));
 
 $tool_name = get_lang('SessionList');
 Display::display_header($tool_name);
@@ -46,114 +50,186 @@ if (isset($_REQUEST['keyword'])) {
     $url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_sessions&_search=true&rows=20&page=1&sidx=&sord=asc&filters=&searchField=name&searchString='.Security::remove_XSS($_REQUEST['keyword']).'&searchOper=bw';    
 }
 
-//The order is important you need to check the the $column variable in the model.ajax.php file 
-$columns        = array(get_lang('Name'), get_lang('NumberOfCourses'), get_lang('NumberOfUsers'), get_lang('SessionCategoryName'), 
-                        get_lang('StartDate'), get_lang('EndDate'), get_lang('Coach'),  get_lang('Status'), get_lang('Visibility'), get_lang('Actions'));
-
-//$activeurl = '?sidx=session_active';
-//Column config
-$column_model   = array(
-                        array('name'=>'name',           'index'=>'name',          'width'=>'120',  'align'=>'left', 'search' => 'true'),                        
-                        array('name'=>'nbr_courses',    'index'=>'nbr_courses',   'width'=>'30',   'align'=>'left', 'search' => 'true'),
-                        array('name'=>'nbr_users',      'index'=>'nbr_users',     'width'=>'30',   'align'=>'left', 'search' => 'true'),
-                        array('name'=>'category_name',  'index'=>'category_name', 'width'=>'70',   'align'=>'left', 'search' => 'true'),
-                        array('name'=>'date_start',     'index'=>'date_start',    'width'=>'40',   'align'=>'left', 'search' => 'true'),
-                        array('name'=>'date_end',       'index'=>'date_end',      'width'=>'40',   'align'=>'left', 'search' => 'true'),
-                        array('name'=>'coach_name',     'index'=>'coach_name',    'width'=>'80',   'align'=>'left', 'search' => 'false'),                        
-                        array('name'=>'status',         'index'=>'session_active','width'=>'40',   'align'=>'left', 'search' => 'true', 'stype'=>'select',
-                                 
-                              //for the bottom bar
-                              'searchoptions' => array(                                                
-                                                'defaultValue'  => '1', 
-                                                'value'         => '1:'.get_lang('Active').';0:'.get_lang('Inactive')),
-                             
-                              //for the top bar                              
-                              'editoptions' => array('value' => ':'.get_lang('All').';1:'.get_lang('Active').';0:'.get_lang('Inactive'))),
-                                          
-                                   
-                        array('name'=>'visibility',     'index'=>'visibility',      'width'=>'40',   'align'=>'left', 'search' => 'false'),                        
-                        array('name'=>'actions',        'index'=>'actions',         'width'=>'100',  'align'=>'left','formatter'=>'action_formatter','sortable'=>'false', 'search' => 'false')
-                       );            
 //Autowidth             
 $extra_params['autowidth'] = 'true';
-
-//height auto 
+//Height auto 
 $extra_params['height'] = 'auto';
-//$extra_params['excel'] = 'excel';
 
 $extra_params['rowList'] = array(10, 20 ,30);
 
+$result = SessionManager::get_session_columns();
+$columns = $result['columns'];
+$column_model = $result['column_model'];
+
+$extra_params['postData'] =array (
+                    'filters' => array(                                        
+                                        "groupOp" => "AND",                                         
+                                        "rules" => $result['rules'], 
+                                        /*array(
+                                            array( "field" => "display_start_date", "op" => "gt", "data" => ""),
+                                            array( "field" => "display_end_date", "op" => "gt", "data" => "")
+                                        ),*/ 
+                                        //'groups' => $groups
+                                )                                
+);
+/*
+     $filters = array('filters' => array( "groupOp" => "AND", 
+                                        "rules" => $rules));
+    
+     $filters = json_encode($filters);
+ var_dump($filters);*/
 
 //With this function we can add actions to the jgrid (edit, delete, etc)
 $action_links = 'function action_formatter(cellvalue, options, rowObject) {
-                         return \'<a href="session_edit.php?page=resume_session.php&id=\'+options.rowId+\'">'.Display::return_icon('edit.png',get_lang('Edit'),'',ICON_SIZE_SMALL).'</a>'.
+                         return \'<a href="session_add.php?page=resume_session.php&id=\'+options.rowId+\'">'.Display::return_icon('edit.png',get_lang('Edit'),'',ICON_SIZE_SMALL).'</a>'.
                          '&nbsp;<a href="add_users_to_session.php?page=session_list.php&id_session=\'+options.rowId+\'">'.Display::return_icon('user_subscribe_session.png',get_lang('SubscribeUsersToSession'),'',ICON_SIZE_SMALL).'</a>'.
                          '&nbsp;<a href="add_courses_to_session.php?page=session_list.php&id_session=\'+options.rowId+\'">'.Display::return_icon('courses_to_session.png',get_lang('SubscribeCoursesToSession'),'',ICON_SIZE_SMALL).'</a>'.
                          '&nbsp;<a onclick="javascript:if(!confirm('."\'".addslashes(api_htmlentities(get_lang("ConfirmYourChoice"),ENT_QUOTES))."\'".')) return false;"  href="session_list.php?action=copy&idChecked=\'+options.rowId+\'">'.Display::return_icon('copy.png',get_lang('Copy'),'',ICON_SIZE_SMALL).'</a>'.
                          '&nbsp;<a onclick="javascript:if(!confirm('."\'".addslashes(api_htmlentities(get_lang("ConfirmYourChoice"),ENT_QUOTES))."\'".')) return false;"  href="session_list.php?action=delete&idChecked=\'+options.rowId+\'">'.Display::return_icon('delete.png',get_lang('Delete'),'',ICON_SIZE_SMALL).'</a>'.
                          '\'; 
                  }';
+$url_select = api_get_path(WEB_AJAX_PATH).'extra_field.ajax.php?1=1';
 ?>
 <script>
 
-
 function setSearchSelect(columnName) {    
-    $("#sessions").jqGrid('setColProp', columnName,
-    {                   
-       searchoptions:{
+    $("#sessions").jqGrid('setColProp', columnName, {                   
+       /*searchoptions:{
             dataInit:function(el){                            
                 $("option[value='1']",el).attr("selected", "selected");
                 setTimeout(function(){
                     $(el).trigger('change');
-                },1000);
+                }, 1000);
             }
-        }
+        }*/
     });
 }
+var added_cols = [];
+var original_cols = [];
+
+function clean_cols(grid, added_cols) {
+    //Cleaning 
+    for (key in added_cols) {
+        //console.log('hide: ' + key);                    
+        grid.hideCol(key);
+    };
+    grid.showCol('name');
+    grid.showCol('display_start_date');
+    grid.showCol('display_end_date');    
+    grid.showCol('course_title');
+}
+
+function show_cols(grid, added_cols) {
+    grid.showCol('name').trigger('reloadGrid');
+    for (key in added_cols) {
+        //console.log('show: ' + key);
+        grid.showCol(key);
+    };    
+}
 
+var second_filters = [];
 
 $(function() {
+    date_pick_today = function(elem) {
+        $(elem).datetimepicker({dateFormat: "yy-mm-dd"});
+        $(elem).datetimepicker('setDate', (new Date()));
+    }
+    date_pick_one_month = function(elem) {
+        $(elem).datetimepicker({dateFormat: "yy-mm-dd"});
+        next_month = Date.today().next().month();
+        $(elem).datetimepicker('setDate', next_month);
+    }
+    
+    //Great hack
+    register_second_select = function(elem) {
+        second_filters[$(elem).val()] = $(elem);        
+    }
+    
+    fill_second_select = function(elem) {
+        $(elem).on("change", function() {
+            composed_id = $(this).val();
+            field_id = composed_id.split("#")[0];
+            id = composed_id.split("#")[1];
+            
+            $.ajax({
+                url: "<?php echo $url_select ?>&a=get_second_select_options", 
+                dataType: "json",
+                data: "type=session&field_id="+field_id+"&option_value_id="+id,
+                success: function(data) {
+                    my_select = second_filters[field_id];
+                    my_select.empty();
+                    $.each(data, function(index, value) {
+                        my_select.append($("<option/>", {
+                            value: index,
+                            text: value
+                        }));
+                    });            
+                }
+            }); 
+        });        
+    }
+
     <?php 
-        echo Display::grid_js('sessions', $url,$columns,$column_model,$extra_params, array(), $action_links,true);      
+        echo Display::grid_js('sessions', $url, $columns, $column_model, $extra_params, array(), $action_links, true);      
     ?>
     
-    setSearchSelect("status");    
+    setSearchSelect("status");
     
-    $("#sessions").jqGrid('navGrid','#sessions_pager', {edit:false,add:false,del:false},
+    var grid = $("#sessions"),
+    prmSearch = {
+        multipleSearch : true, 
+        overlay : false, 
+        width: 600,
+        caption: '<?php echo addslashes(get_lang('Search')); ?>',
+        formclass:'data_table',
+        onSearch : function() {
+            var postdata = grid.jqGrid('getGridParam', 'postData');
+                        
+            if (postdata && postdata.filters) {
+                filters = jQuery.parseJSON(postdata.filters);
+                clean_cols(grid, added_cols);
+                added_cols = [];                
+                $.each(filters, function(key, value){
+                    if (key == 'rules') {
+                        $.each(value, function(key, value) {
+                            //if (added_cols[value.field] == undefined) {
+                                added_cols[value.field] = value.field;
+                            //}
+                            //grid.showCol(value.field);                            
+                        });
+                    }                    
+                });
+                show_cols(grid, added_cols);                
+            }
+       },
+       onReset: function() {      
+            clean_cols(grid, added_cols);
+       }
+    };
+    
+    original_cols = grid.jqGrid('getGridParam', 'colModel');    
+    
+    grid.jqGrid('navGrid','#sessions_pager', 
+        {edit:false,add:false,del:false},
         {height:280,reloadAfterSubmit:false}, // edit options 
         {height:280,reloadAfterSubmit:false}, // add options 
-        {reloadAfterSubmit:false}, // del options 
-        {width:500} // search options
+        {reloadAfterSubmit:false},// del options 
+        prmSearch
     );
-    /*
-    // add custom button to export the data to excel
-    jQuery("#sessions").jqGrid('navButtonAdd','#sessions_pager',{
-           caption:"", 
-           onClickButton : function () { 
-               jQuery("#sessions").excelExport();
-           } 
-    });
+                  
+    // create the searching dialog
+    grid.searchGrid(prmSearch);
     
-    jQuery('#sessions').jqGrid('navButtonAdd','#sessions_pager',{id:'pager_csv',caption:'',title:'Export To CSV',onClickButton : function(e)
-    {
-        try {
-            jQuery("#sessions").jqGrid('excelExport',{tag:'csv', url:'grid.php'});
-        } catch (e) {
-            window.location= 'grid.php?oper=csv';
-        }
-    },buttonicon:'ui-icon-document'})
-    */
-   
+    //Fixes search table
+    var searchDialogAll = $("#fbox_"+grid[0].id);
+    searchDialogAll.addClass("table");
     
-    //Adding search options
-    var options = {
-        'stringResult': true,
-        'autosearch' : true,
-        'searchOnEnter':false      
-    }
-    jQuery("#sessions").jqGrid('filterToolbar',options);    
-    var sgrid = $("#sessions")[0];
-    sgrid.triggerToolbar();
+    var searchDialog = $("#searchmodfbox_"+grid[0].id);    
+    searchDialog.addClass("ui-jqgrid ui-widget ui-widget-content ui-corner-all");
+    searchDialog.css({position:"relative", "z-index":"auto", "float":"left"})    
+    var gbox = $("#gbox_"+grid[0].id);
+    gbox.before(searchDialog);
+    gbox.css({clear:"left"});
 });
 </script>
 <div class="actions">
@@ -162,5 +238,35 @@ echo '<a href="'.api_get_path(WEB_CODE_PATH).'admin/session_add.php">'.Display::
 echo '<a href="'.api_get_path(WEB_CODE_PATH).'admin/add_many_session_to_category.php">'.Display::return_icon('session_to_category.png',get_lang('AddSessionsInCategories'),'',ICON_SIZE_MEDIUM).'</a>';
 echo '<a href="'.api_get_path(WEB_CODE_PATH).'admin/session_category_list.php">'.Display::return_icon('folder.png',get_lang('ListSessionCategory'),'',ICON_SIZE_MEDIUM).'</a>';
 echo '</div>';
+
+$form = new FormValidator('search');
+
+$form->addElement('header', get_lang('Filter'));
+
+$form->addElement('text', 'start_date_start', get_lang('Between'), array('id' =>'start_date_start'));
+$form->addElement('text', 'start_date_end', get_lang('And'), array('id' =>'start_date_end'));
+$renderer = $form->defaultRenderer();
+
+$renderer->setElementTemplate(get_lang('StartDate').' {label} {element}', 'start_date_start');  
+$renderer->setElementTemplate('{label} {element}', 'start_date_end');  
+
+$form->addElement('html', '<div class="clear"></div>');
+
+$form->addElement('text', 'end_date_start', get_lang('Between'), array('id' =>'end_date_start'));
+$form->addElement('text', 'end_date_end', get_lang('And'), array('id' =>'end_date_end'));
+
+$renderer->setElementTemplate(get_lang('EndDate').' {label} {element}', 'end_date_start');  
+$renderer->setElementTemplate('{label} {element}', 'end_date_end');  
+           
+$options = CourseManager::get_course_list_of_user_as_course_admin(api_get_user_id());
+$form->addElement('select', 'course', get_lang('Course'), $options);
+
+
+//$session_field->add_elements($form);
+
+$form->addElement('button', 'submit', get_lang('Search'), array('id' => 'search_button'));
+
+//$form->display();
+
 echo Display::grid_html('sessions');
 Display::display_footer();

+ 3 - 6
main/admin/statistics/index.php

@@ -83,8 +83,7 @@ switch ($_GET['report']) {
         break;
     case 'courselastvisit':
         Statistics::print_course_last_visit();
-        break;
-    //---
+        break;    
     case 'users':
         // total amount of users
         Statistics::print_stats(
@@ -118,12 +117,10 @@ switch ($_GET['report']) {
         break;
     case 'zombies':
         ZombieReport::create(array('report' => 'zombies'))->display();
-        break;
-    //---
+        break;    
     case 'activities':
         Statistics::print_activities_stats();
-        break;
-    //---
+        break;    
     case 'messagesent':
         $messages_sent = Statistics::get_messages('sent');
         Statistics::print_stats(get_lang('MessagesSent'), $messages_sent);

+ 12 - 5
main/admin/statistics/statistics.lib.php

@@ -185,10 +185,10 @@ class Statistics {
         } else {
             $sql .= " ORDER BY col4 DESC ";
         }
-        $sql .=    " LIMIT $from,$number_of_items ";
+        $sql .=    " LIMIT $from, $number_of_items ";
 
         $res = Database::query($sql);
-        $activities = array ();
+        $activities = array();
         while ($row = Database::fetch_row($res)) {            
             if (strpos($row[1], '_object') === false) {
                 $row[2] = $row[2];
@@ -200,13 +200,21 @@ class Statistics {
                     }
                 }
             }
-        	if (!empty($row['default_date']) && $row['default_date'] != '0000-00-00 00:00:00') {        	
+        	/*if (!empty($row['default_date']) && $row['default_date'] != '0000-00-00 00:00:00') {        	
             	$row['default_date'] = api_get_local_time($row['default_date']);
         	} else {
         		$row['default_date'] = '-';
+        	}*/
+            
+            if (!empty($row[4]) && $row[4] != '0000-00-00 00:00:00') {        	
+            	$row[4] = api_get_local_time($row[4]);
+        	} else {
+        		$row[4] = '-';
         	}
+            
             $activities[] = $row;
         }
+        
         return $activities;
     }
 
@@ -482,7 +490,6 @@ class Statistics {
     }
 
     static function print_activities_stats() {
-
         echo '<h4>'.get_lang('ImportantActivities').'</h4>';
 
         // Create a search-box
@@ -495,7 +502,7 @@ class Statistics {
         $form->addElement('text','keyword',get_lang('keyword'));
         $form->addElement('style_submit_button', 'submit', get_lang('Search'),'class="search"');
         echo '<div class="actions">';
-            $form->display();
+        $form->display();
         echo '</div>';
         
         $table = new SortableTable('activities', array('Statistics','get_number_of_activities'), array('Statistics','get_activities_data'),4,50,'DESC');

+ 1 - 1
main/admin/user_add.php

@@ -207,7 +207,7 @@ $form->addElement('radio', 'active', '', get_lang('Inactive'), 0);
 
 $extra_data = UserManager::get_extra_user_data(0, true);
 
-$return_params = UserManager::set_extra_fields_in_form($form, $extra_data, 'user_add');
+$return_params = ExtraField::set_extra_fields_in_form($form, $extra_data, 'user_add', false, null, 'user');
 $jquery_ready_content = $return_params['jquery_ready_content'];
 
 // the $jquery_ready_content variable collects all functions that will be load in the $(document).ready javascript function

+ 1 - 1
main/admin/user_edit.php

@@ -266,7 +266,7 @@ if (!$user_data['platform_admin']) {
 
 
 // EXTRA FIELDS
-$return_params = UserManager::set_extra_fields_in_form($form, $extra_data, 'user_edit', true, $user_id);
+$return_params = ExtraField::set_extra_fields_in_form($form, $extra_data, 'user_edit', true, $user_id, 'user');
 $jquery_ready_content = $return_params['jquery_ready_content'];
 
 // the $jquery_ready_content variable collects all functions that will be load in the $(document).ready javascript function

+ 266 - 280
main/admin/user_fields.php

@@ -1,8 +1,9 @@
 <?php
+
 /* For licensing terms, see /license.txt */
 /**
-*	@package chamilo.admin
-*/
+ * 	@package chamilo.admin
+ */
 // name of the language file that needs to be included
 $language_file = array('admin', 'registration');
 $cidReset = true;
@@ -11,170 +12,167 @@ $cidReset = true;
 require '../inc/global.inc.php';
 
 // section for the tabs
-$this_section=SECTION_PLATFORM_ADMIN;
+$this_section = SECTION_PLATFORM_ADMIN;
 
 // user permissions
 api_protect_admin_script();
 
 // Database table definitions
-$table_admin	= Database :: get_main_table(TABLE_MAIN_ADMIN);
-$table_user 	= Database :: get_main_table(TABLE_MAIN_USER);
-$table_uf	 	= Database :: get_main_table(TABLE_MAIN_USER_FIELD);
-$table_uf_opt 	= Database :: get_main_table(TABLE_MAIN_USER_FIELD_OPTIONS);
-$table_uf_val 	= Database :: get_main_table(TABLE_MAIN_USER_FIELD_VALUES);
+$table_admin = Database :: get_main_table(TABLE_MAIN_ADMIN);
+$table_user = Database :: get_main_table(TABLE_MAIN_USER);
+$table_uf = Database :: get_main_table(TABLE_MAIN_USER_FIELD);
+$table_uf_opt = Database :: get_main_table(TABLE_MAIN_USER_FIELD_OPTIONS);
+$table_uf_val = Database :: get_main_table(TABLE_MAIN_USER_FIELD_VALUES);
 
-$interbreadcrumb[] = array ("url" => 'index.php', "name" => get_lang('PlatformAdmin'));
+$interbreadcrumb[] = array("url" => 'index.php', "name" => get_lang('PlatformAdmin'));
 
 // Display form
-if(1)
-{
-	$tool_name = get_lang('UserFields');
-	Display :: display_header($tool_name, "");
-	//api_display_tool_title($tool_name);
-	if (isset ($_GET['action']))
-	{
-		$check = Security::check_token('get');
-		if($check) {
-			switch ($_GET['action']) {
-				case 'show_message' :
-					Display :: display_normal_message($_GET['message']);
-					break;
-				case 'show_field' :
-					if (api_is_platform_admin() && !empty($_GET['field_id']) && UserManager :: update_extra_field($_GET['field_id'],array('field_visible'=>'1'))) {
-						Display :: display_confirmation_message(get_lang('FieldShown'));
-					} else {
-						Display :: display_error_message(get_lang('CannotShowField'));
-					}
-					break;
-				case 'hide_field' :
-					if (api_is_platform_admin() && !empty($_GET['field_id']) && UserManager :: update_extra_field($_GET['field_id'],array('field_visible'=>'0'))) {
-						Display :: display_confirmation_message(get_lang('FieldHidden'));
-					} else {
-						Display :: display_error_message(get_lang('CannotHideField'));
-					}
-					break;
-				case 'thaw_field' :
-					if (api_is_platform_admin() && !empty($_GET['field_id']) && UserManager :: update_extra_field($_GET['field_id'],array('field_changeable'=>'1'))) {
-						Display :: display_confirmation_message(get_lang('FieldMadeChangeable'));
-					} else {
-						Display :: display_error_message(get_lang('CannotMakeFieldChangeable'));
-					}
-					break;
-				case 'freeze_field' :
-					if (api_is_platform_admin() && !empty($_GET['field_id']) && UserManager :: update_extra_field($_GET['field_id'],array('field_changeable'=>'0'))) {
-						Display :: display_confirmation_message(get_lang('FieldMadeUnchangeable'));
-					} else {
-						Display :: display_error_message(get_lang('CannotMakeFieldUnchangeable'));
-					}
-					break;
-				case 'moveup' :
-					if (api_is_platform_admin() && !empty($_GET['field_id'])) {
-						if (move_user_field('moveup', $_GET['field_id'])) {
-							Display :: display_confirmation_message(get_lang('FieldMovedUp'));
-						} else {
-							Display :: display_error_message(get_lang('CannotMoveField'));
-						}
-					}
-					break;
-				case 'movedown' :
-					if (api_is_platform_admin() && !empty($_GET['field_id'])) {
-						if (move_user_field('movedown', $_GET['field_id'])) {
-							Display :: display_confirmation_message(get_lang('FieldMovedDown'));
-						} else {
-							Display :: display_error_message(get_lang('CannotMoveField'));
-						}
-					}
-					break;
-				case 'filter_on' :
-					if (api_is_platform_admin() && !empty($_GET['field_id']) && UserManager :: update_extra_field($_GET['field_id'],array('field_filter'=>'1'))) {
-						Display :: display_confirmation_message(get_lang('FieldFilterSetOn'));
-					} else {
-						Display :: display_error_message(get_lang('CannotShowField'));
-					}
-					break;
-				case 'filter_off' :
-					if (api_is_platform_admin() && !empty($_GET['field_id']) && UserManager :: update_extra_field($_GET['field_id'],array('field_filter'=>'0'))) {
-						Display :: display_confirmation_message(get_lang('FieldFilterSetOff'));
-					} else {
-						Display :: display_error_message(get_lang('CannotShowField'));
-					}
-					break;
-
-				case 'delete':
-					if (api_is_platform_admin() && !empty($_GET['field_id'])) {
-						if (delete_user_fields($_GET['field_id'])) {
-							Display :: display_confirmation_message(get_lang('FieldDeleted'));
-						} else {
-							Display :: display_error_message(get_lang('CannotDeleteField'));
-						}
-					}
-					break;
-			}
-			Security::clear_token();
-		}
-	}
-	if (isset ($_POST['action'])) {
-		$check = Security::check_token('get');
-		if($check) {
-			switch ($_POST['action']) {
-				default:
-					break;
-			}
-			Security::clear_token();
-		}
-	}
-
-	// Create an add-field box
-	$form = new FormValidator('add_field','post','','',null,false);
-	$renderer =& $form->defaultRenderer();
-	$renderer->setElementTemplate('<span>{element}</span> ');
-	//$form->addElement('text','label',get_lang('FieldLabel'));
-	//$form->addElement('text','type',get_lang('FieldType'));
-	//$form->addElement('text','title',get_lang('FieldTitle'));
-	//$form->addElement('text','default',get_lang('FieldDefaultValue'));
-	//$form->addElement('submit','submit',get_lang('Search'));
-	$form->addElement('static','search_advanced_link',null,'<a href="user_fields_add.php?action=fill">'.Display::return_icon('add_user_fields.png', get_lang('AddUserField'),'',ICON_SIZE_MEDIUM).'</a>');
-	echo '<div class="actions">';
-	$form->display();
-	echo '</div>';
-
-	// Create a sortable table with user-data
-	$parameters['sec_token'] = Security::get_token();
-	//$column_show  = array(1,1,1,1,1,1,1,1,1,0,0);
-	//$column_order = array(1,2,3,4,5,6,7,8,9,10,11);
-	$extra_fields = UserManager::get_extra_fields();
-	$number_of_extra_fields = count($extra_fields);
-
-    $table = new SortableTable('user_field', array('UserManager','get_number_of_extra_fields'), array('UserManager','get_extra_fields'),5);
-	$table->set_additional_parameters($parameters);
-	$table->set_header(0, '', false);
-	$table->set_header(1, get_lang('FieldLabel'), false);
-	$table->set_header(2, get_lang('FieldType'), false);
-	$table->set_header(3, get_lang('FieldTitle'),false);
-	$table->set_header(4, get_lang('FieldDefaultValue'),false);
-	$table->set_header(5, get_lang('FieldOrder'), false);
-	$table->set_header(6, get_lang('FieldVisibility'), false);
-	$table->set_header(7, get_lang('FieldChangeability'), false);
-	$table->set_header(8, get_lang('FieldFilter'), false);
-	$table->set_header(9, get_lang('Modify'), false);
-	$table->set_column_filter(5, 'order_filter');
-	$table->set_column_filter(6, 'modify_visibility');
-	$table->set_column_filter(7, 'modify_changeability');
-	$table->set_column_filter(8, 'modify_field_filter');
-	$table->set_column_filter(9, 'edit_filter');
-	$table->set_column_filter(2, 'type_filter');
-	$table->display();
+$tool_name = get_lang('UserFields');
+Display :: display_header($tool_name);
+
+if (isset($_GET['action'])) {
+    $check = Security::check_token('get');
+    if ($check) {
+        switch ($_GET['action']) {
+            case 'show_message' :
+                Display :: display_normal_message($_GET['message']);
+                break;
+            case 'show_field' :
+                if (api_is_platform_admin() && !empty($_GET['field_id']) && UserManager :: update_extra_field($_GET['field_id'], array('field_visible' => '1'))) {
+                    Display :: display_confirmation_message(get_lang('FieldShown'));
+                } else {
+                    Display :: display_error_message(get_lang('CannotShowField'));
+                }
+                break;
+            case 'hide_field' :
+                if (api_is_platform_admin() && !empty($_GET['field_id']) && UserManager :: update_extra_field($_GET['field_id'], array('field_visible' => '0'))) {
+                    Display :: display_confirmation_message(get_lang('FieldHidden'));
+                } else {
+                    Display :: display_error_message(get_lang('CannotHideField'));
+                }
+                break;
+            case 'thaw_field' :
+                if (api_is_platform_admin() && !empty($_GET['field_id']) && UserManager :: update_extra_field($_GET['field_id'], array('field_changeable' => '1'))) {
+                    Display :: display_confirmation_message(get_lang('FieldMadeChangeable'));
+                } else {
+                    Display :: display_error_message(get_lang('CannotMakeFieldChangeable'));
+                }
+                break;
+            case 'freeze_field' :
+                if (api_is_platform_admin() && !empty($_GET['field_id']) && UserManager :: update_extra_field($_GET['field_id'], array('field_changeable' => '0'))) {
+                    Display :: display_confirmation_message(get_lang('FieldMadeUnchangeable'));
+                } else {
+                    Display :: display_error_message(get_lang('CannotMakeFieldUnchangeable'));
+                }
+                break;
+            case 'moveup' :
+                if (api_is_platform_admin() && !empty($_GET['field_id'])) {
+                    if (move_user_field('moveup', $_GET['field_id'])) {
+                        Display :: display_confirmation_message(get_lang('FieldMovedUp'));
+                    } else {
+                        Display :: display_error_message(get_lang('CannotMoveField'));
+                    }
+                }
+                break;
+            case 'movedown' :
+                if (api_is_platform_admin() && !empty($_GET['field_id'])) {
+                    if (move_user_field('movedown', $_GET['field_id'])) {
+                        Display :: display_confirmation_message(get_lang('FieldMovedDown'));
+                    } else {
+                        Display :: display_error_message(get_lang('CannotMoveField'));
+                    }
+                }
+                break;
+            case 'filter_on' :
+                if (api_is_platform_admin() && !empty($_GET['field_id']) && UserManager :: update_extra_field($_GET['field_id'], array('field_filter' => '1'))) {
+                    Display :: display_confirmation_message(get_lang('FieldFilterSetOn'));
+                } else {
+                    Display :: display_error_message(get_lang('CannotShowField'));
+                }
+                break;
+            case 'filter_off' :
+                if (api_is_platform_admin() && !empty($_GET['field_id']) && UserManager :: update_extra_field($_GET['field_id'], array('field_filter' => '0'))) {
+                    Display :: display_confirmation_message(get_lang('FieldFilterSetOff'));
+                } else {
+                    Display :: display_error_message(get_lang('CannotShowField'));
+                }
+                break;
+
+            case 'delete':
+                if (api_is_platform_admin() && !empty($_GET['field_id'])) {
+                    if (delete_user_fields($_GET['field_id'])) {
+                        Display :: display_confirmation_message(get_lang('FieldDeleted'));
+                    } else {
+                        Display :: display_error_message(get_lang('CannotDeleteField'));
+                    }
+                }
+                break;
+        }
+        Security::clear_token();
+    }
+}
+if (isset($_POST['action'])) {
+    $check = Security::check_token('get');
+    if ($check) {
+        switch ($_POST['action']) {
+            default:
+                break;
+        }
+        Security::clear_token();
+    }
 }
 
+// Create an add-field box
+$form = new FormValidator('add_field', 'post', '', '', null, false);
+$renderer = & $form->defaultRenderer();
+$renderer->setElementTemplate('<span>{element}</span> ');
+//$form->addElement('text','label',get_lang('FieldLabel'));
+//$form->addElement('text','type',get_lang('FieldType'));
+//$form->addElement('text','title',get_lang('FieldTitle'));
+//$form->addElement('text','default',get_lang('FieldDefaultValue'));
+//$form->addElement('submit','submit',get_lang('Search'));
+$form->addElement('static', 'search_advanced_link', null, '<a href="user_fields_add.php?action=fill">' . Display::return_icon('add_user_fields.png', get_lang('AddUserField'), '', ICON_SIZE_MEDIUM) . '</a>');
+echo '<div class="actions">';
+$form->display();
+echo '</div>';
+
+// Create a sortable table with user-data
+$parameters['sec_token'] = Security::get_token();
+//$column_show  = array(1,1,1,1,1,1,1,1,1,0,0);
+//$column_order = array(1,2,3,4,5,6,7,8,9,10,11);
+$extra_fields = UserManager::get_extra_fields();
+$number_of_extra_fields = count($extra_fields);
+
+$table = new SortableTable('user_field', array('UserManager', 'get_number_of_extra_fields'), array('UserManager', 'get_extra_fields'), 5);
+$table->set_additional_parameters($parameters);
+$table->set_header(0, '', false);
+$table->set_header(1, get_lang('FieldLabel'), false);
+$table->set_header(2, get_lang('FieldType'), false);
+$table->set_header(3, get_lang('FieldTitle'), false);
+$table->set_header(4, get_lang('FieldDefaultValue'), false);
+$table->set_header(5, get_lang('FieldOrder'), false);
+$table->set_header(6, get_lang('FieldVisibility'), false);
+$table->set_header(7, get_lang('FieldChangeability'), false);
+$table->set_header(8, get_lang('FieldFilter'), false);
+$table->set_header(9, get_lang('Modify'), false);
+$table->set_column_filter(5, 'order_filter');
+$table->set_column_filter(6, 'modify_visibility');
+$table->set_column_filter(7, 'modify_changeability');
+$table->set_column_filter(8, 'modify_field_filter');
+$table->set_column_filter(9, 'edit_filter');
+$table->set_column_filter(2, 'type_filter');
+$table->display();
+
+
 Display::display_footer();
+
 //gateway functions to the UserManager methods (provided for SorteableTable callback mechanism)
-function get_number_of_extra_fields()
-{
-	return UserManager::get_number_of_extra_fields();
+function get_number_of_extra_fields() {
+    return UserManager::get_number_of_extra_fields();
 }
-function get_extra_fields($f,$n,$o,$d)
-{
-	return UserManager::get_extra_fields($f,$n,$o,$d);
+
+function get_extra_fields($f, $n, $o, $d) {
+    return UserManager::get_extra_fields($f, $n, $o, $d);
 }
 
 /**
@@ -189,7 +187,7 @@ function get_extra_fields($f,$n,$o,$d)
  */
 function type_filter($type) {
     $types = UserManager::get_user_field_types();
-	return $types[$type];
+    return $types[$type];
 }
 
 /**
@@ -204,23 +202,23 @@ function type_filter($type) {
  * @version July 2008
  * @since Dokeos 1.8.6
  */
-function order_filter($field_order,$url_params,$row)
-{
-	global $number_of_extra_fields;
-	$return = '';
-	// the up icon only has to appear when the row can be moved up (all but the first row)
-	if ($row[5]<>1) {
-		$return .= '<a href="'.api_get_self().'?action=moveup&field_id='.$row[0].'&sec_token='.$_SESSION['sec_token'].'">'.Display::return_icon('up.gif', get_lang('Up')).'</a>';
-	} else {
-		$return .= Display::return_icon('blank.gif','',array('width'=>'21px'));
-	}
-
-	// the down icon only has to appear when the row can be moved down (all but the last row)
-	if ($row[5]<>$number_of_extra_fields) {
-		$return .= '<a href="'.api_get_self().'?action=movedown&field_id='.$row[0].'&sec_token='.$_SESSION['sec_token'].'">'.Display::return_icon('down.gif', get_lang('Down')).'</a>';
-	}
-	return $return;
+function order_filter($field_order, $url_params, $row) {
+    global $number_of_extra_fields;
+    $return = '';
+    // the up icon only has to appear when the row can be moved up (all but the first row)
+    if ($row[5] <> 1) {
+        $return .= '<a href="' . api_get_self() . '?action=moveup&field_id=' . $row[0] . '&sec_token=' . $_SESSION['sec_token'] . '">' . Display::return_icon('up.gif', get_lang('Up')) . '</a>';
+    } else {
+        $return .= Display::return_icon('blank.gif', '', array('width' => '21px'));
+    }
+
+    // the down icon only has to appear when the row can be moved down (all but the last row)
+    if ($row[5] <> $number_of_extra_fields) {
+        $return .= '<a href="' . api_get_self() . '?action=movedown&field_id=' . $row[0] . '&sec_token=' . $_SESSION['sec_token'] . '">' . Display::return_icon('down.gif', get_lang('Down')) . '</a>';
+    }
+    return $return;
 }
+
 /**
  * Modify the visible field to show links and icons
  * @param	int 	The current visibility
@@ -228,10 +226,10 @@ function order_filter($field_order,$url_params,$row)
  * @param	array	The results row
  * @return	string	The link
  */
-function modify_visibility($visibility,$url_params,$row)
-{
-	return ($visibility?'<a href="'.api_get_self().'?action=hide_field&field_id='.$row[0].'&sec_token='.$_SESSION['sec_token'].'">'.Display::return_icon('visible.gif', get_lang('Hide')).'</a>':'<a href="'.api_get_self().'?action=show_field&field_id='.$row[0].'&sec_token='.$_SESSION['sec_token'].'">'.Display::return_icon('invisible.gif', get_lang('Show')).'</a>');
+function modify_visibility($visibility, $url_params, $row) {
+    return ($visibility ? '<a href="' . api_get_self() . '?action=hide_field&field_id=' . $row[0] . '&sec_token=' . $_SESSION['sec_token'] . '">' . Display::return_icon('visible.gif', get_lang('Hide')) . '</a>' : '<a href="' . api_get_self() . '?action=show_field&field_id=' . $row[0] . '&sec_token=' . $_SESSION['sec_token'] . '">' . Display::return_icon('invisible.gif', get_lang('Show')) . '</a>');
 }
+
 /**
  * Modify the changeability field to show links and icons
  * @param	int 	The current changeability
@@ -239,23 +237,21 @@ function modify_visibility($visibility,$url_params,$row)
  * @param	array	The results row
  * @return	string	The link
  */
-function modify_changeability($changeability,$url_params,$row)
-{
-	return ($changeability?'<a href="'.api_get_self().'?action=freeze_field&field_id='.$row[0].'&sec_token='.$_SESSION['sec_token'].'">'.Display::return_icon('right.gif', get_lang('MakeUnchangeable')).'</a>':'<a href="'.api_get_self().'?action=thaw_field&field_id='.$row[0].'&sec_token='.$_SESSION['sec_token'].'">'.Display::return_icon('wrong.gif', get_lang('MakeChangeable')).'</a>');
+function modify_changeability($changeability, $url_params, $row) {
+    return ($changeability ? '<a href="' . api_get_self() . '?action=freeze_field&field_id=' . $row[0] . '&sec_token=' . $_SESSION['sec_token'] . '">' . Display::return_icon('right.gif', get_lang('MakeUnchangeable')) . '</a>' : '<a href="' . api_get_self() . '?action=thaw_field&field_id=' . $row[0] . '&sec_token=' . $_SESSION['sec_token'] . '">' . Display::return_icon('wrong.gif', get_lang('MakeChangeable')) . '</a>');
 }
 
-function modify_field_filter ($changeability,$url_params,$row)
-{
-	return ($changeability?'<a href="'.api_get_self().'?action=filter_off&field_id='.$row[0].'&sec_token='.$_SESSION['sec_token'].'">'.Display::return_icon('right.gif', get_lang('FilterOff')).'</a>':'' .
-						   '<a href="'.api_get_self().'?action=filter_on&field_id='.$row[0].'&sec_token='.$_SESSION['sec_token'].'">'.Display::return_icon('wrong.gif', get_lang('FilterOn')).'</a>');
+function modify_field_filter($changeability, $url_params, $row) {
+    return ($changeability ? '<a href="' . api_get_self() . '?action=filter_off&field_id=' . $row[0] . '&sec_token=' . $_SESSION['sec_token'] . '">' . Display::return_icon('right.gif', get_lang('FilterOff')) . '</a>' : '' .
+                    '<a href="' . api_get_self() . '?action=filter_on&field_id=' . $row[0] . '&sec_token=' . $_SESSION['sec_token'] . '">' . Display::return_icon('wrong.gif', get_lang('FilterOn')) . '</a>');
 }
 
 function edit_filter($id, $url_params, $row) {
-	global $charset;
-	$return = '<a href="user_fields_add.php?action=edit&field_id='.$row[0].'&field_type='.$row[2].'&sec_token='.$_SESSION['sec_token'].'">'.Display::return_icon('edit.png',get_lang('Edit')).'</a>';
-	$return .= ' <a href="'.api_get_self().'?action=delete&field_id='.$row[0].'&sec_token='.$_SESSION['sec_token'].'" onclick="javascript:if(!confirm('."'".addslashes(api_htmlentities(get_lang("ConfirmYourChoice"),ENT_QUOTES,$charset))."'".')) return false;">'.
-            Display::return_icon('delete.png',get_lang('Delete')).'</a>';
-	return $return;
+    global $charset;
+    $return = '<a href="user_fields_add.php?action=edit&field_id=' . $row[0] . '&field_type=' . $row[2] . '&sec_token=' . $_SESSION['sec_token'] . '">' . Display::return_icon('edit.png', get_lang('Edit')) . '</a>';
+    $return .= ' <a href="' . api_get_self() . '?action=delete&field_id=' . $row[0] . '&sec_token=' . $_SESSION['sec_token'] . '" onclick="javascript:if(!confirm(' . "'" . addslashes(api_htmlentities(get_lang("ConfirmYourChoice"), ENT_QUOTES, $charset)) . "'" . ')) return false;">' .
+            Display::return_icon('delete.png', get_lang('Delete')) . '</a>';
+    return $return;
 }
 
 /**
@@ -268,71 +264,64 @@ function edit_filter($id, $url_params, $row) {
  * @version July 2008
  * @since Dokeos 1.8.6
  */
-function move_user_field($direction,$field_id) {
-	// Databse table definitions
-	$table_user_field = Database::get_main_table(TABLE_MAIN_USER_FIELD);
-
-	// check the parameters
-	if (!in_array($direction,array('moveup','movedown')) OR !is_numeric($field_id))
-	{
-		return false;
-	}
-
-	// determine the SQL sort direction
-	if ($direction == 'moveup')
-	{
-		$sortdirection = 'DESC';
-	}
-	else
-	{
-		$sortdirection = 'ASC';
-	}
+function move_user_field($direction, $field_id) {
+    // Databse table definitions
+    $table_user_field = Database::get_main_table(TABLE_MAIN_USER_FIELD);
+
+    // check the parameters
+    if (!in_array($direction, array('moveup', 'movedown')) OR !is_numeric($field_id)) {
+        return false;
+    }
+
+    // determine the SQL sort direction
+    if ($direction == 'moveup') {
+        $sortdirection = 'DESC';
+    } else {
+        $sortdirection = 'ASC';
+    }
 
     // first reorder user_fields
     reorder_user_fields();
 
-	$found = false;
-	$sql = "SELECT id, field_order FROM $table_user_field ORDER BY field_order $sortdirection";
-	$result = Database::query($sql);
-	while($row = Database::fetch_array($result))
-	{
-		if ($found)
-		{
-			$next_id = $row['id'];
-			$next_order = $row['field_order'];
-			break;
-		}
-
-		if ($field_id == $row['id'])
-		{
-			$this_id = $row['id'];
-			$this_order = $row['field_order'];
-			$found = true;
-		}
-	}
-
-	$sql1 = "UPDATE ".$table_user_field." SET field_order = '".intval($next_order)."' WHERE id =  '".intval($this_id)."'";
-	$sql2 = "UPDATE ".$table_user_field." SET field_order = '".intval($this_order)."' WHERE id =  '".intval($next_id)."'";
-	Database::query($sql1);
-	Database::query($sql2);
-
-	return true;
+    $found = false;
+    $sql = "SELECT id, field_order FROM $table_user_field ORDER BY field_order $sortdirection";
+    $result = Database::query($sql);
+    while ($row = Database::fetch_array($result)) {
+        if ($found) {
+            $next_id = $row['id'];
+            $next_order = $row['field_order'];
+            break;
+        }
+
+        if ($field_id == $row['id']) {
+            $this_id = $row['id'];
+            $this_order = $row['field_order'];
+            $found = true;
+        }
+    }
+
+    $sql1 = "UPDATE " . $table_user_field . " SET field_order = '" . intval($next_order) . "' WHERE id =  '" . intval($this_id) . "'";
+    $sql2 = "UPDATE " . $table_user_field . " SET field_order = '" . intval($this_order) . "' WHERE id =  '" . intval($next_id) . "'";
+    Database::query($sql1);
+    Database::query($sql2);
+
+    return true;
 }
 
 /**
-* Re-order user fields
-*/
+ * Re-order user fields
+ */
 function reorder_user_fields() {
-      // Database table definition
-      $t_user_field = Database::get_main_table(TABLE_MAIN_USER_FIELD);
-      $sql = "SELECT * FROM $t_user_field ORDER by field_order ASC";
-      $res = Database::query($sql);
-      $i = 1;
-      while ($row = Database::fetch_array($res)) {
-              $sql_reorder = "UPDATE $t_user_field SET field_order = $i WHERE id = '".$row['id']."'";
-              Database::query($sql_reorder);
-              $i++;
-      }
+    // Database table definition
+    $t_user_field = Database::get_main_table(TABLE_MAIN_USER_FIELD);
+    $sql = "SELECT * FROM $t_user_field ORDER by field_order ASC";
+    $res = Database::query($sql);
+    $i = 1;
+    while ($row = Database::fetch_array($res)) {
+        $sql_reorder = "UPDATE $t_user_field SET field_order = $i WHERE id = '" . $row['id'] . "'";
+        Database::query($sql_reorder);
+        $i++;
+    }
 }
 
 /**
@@ -345,42 +334,39 @@ function reorder_user_fields() {
  * @version July 2008
  * @since Dokeos 1.8.6
  */
-function delete_user_fields($field_id)
-{
-	// Database table definitions
-	$table_user_field 			= Database::get_main_table(TABLE_MAIN_USER_FIELD);
-	$table_user_field_options	= Database::get_main_table(TABLE_MAIN_USER_FIELD_OPTIONS);
-	$table_user_field_values 	= Database::get_main_table(TABLE_MAIN_USER_FIELD_VALUES);
-
-	// delete the fields
-	$sql = "DELETE FROM $table_user_field WHERE id = '".Database::escape_string($field_id)."'";
-	$result = Database::query($sql);
-	if (Database::affected_rows() == 1)
-	{
-		// delete the field options
-		$sql = "DELETE FROM $table_user_field_options WHERE field_id = '".Database::escape_string($field_id)."'";
-		$result = Database::query($sql);
-
-		// delete the field values
-		$sql = "DELETE FROM $table_user_field_values WHERE field_id = '".Database::escape_string($field_id)."'";
-		$result = Database::query($sql);
-
-		// recalculate the field_order because the value is used to show/hide the up/down icon
-		// and the field_order value cannot be bigger than the number of fields
-		$sql = "SELECT * FROM $table_user_field ORDER BY field_order ASC";
-		$result = Database::query($sql);
-		$i = 1;
-		while($row = Database::fetch_array($result))
-		{
-			$sql_reorder = "UPDATE $table_user_field SET field_order = '".Database::escape_string($i)."' WHERE id = '".Database::escape_string($row['id'])."'";
-			$result_reorder = Database::query($sql_reorder);
-			$i++;
-		}
-
-		// field was deleted so we return true
-		return true;
-	} else {
-		// the field was not deleted so we return false
-		return false;
-	}
+function delete_user_fields($field_id) {
+    // Database table definitions
+    $table_user_field = Database::get_main_table(TABLE_MAIN_USER_FIELD);
+    $table_user_field_options = Database::get_main_table(TABLE_MAIN_USER_FIELD_OPTIONS);
+    $table_user_field_values = Database::get_main_table(TABLE_MAIN_USER_FIELD_VALUES);
+
+    // delete the fields
+    $sql = "DELETE FROM $table_user_field WHERE id = '" . Database::escape_string($field_id) . "'";
+    $result = Database::query($sql);
+    if (Database::affected_rows() == 1) {
+        // delete the field options
+        $sql = "DELETE FROM $table_user_field_options WHERE field_id = '" . Database::escape_string($field_id) . "'";
+        $result = Database::query($sql);
+
+        // delete the field values
+        $sql = "DELETE FROM $table_user_field_values WHERE field_id = '" . Database::escape_string($field_id) . "'";
+        $result = Database::query($sql);
+
+        // recalculate the field_order because the value is used to show/hide the up/down icon
+        // and the field_order value cannot be bigger than the number of fields
+        $sql = "SELECT * FROM $table_user_field ORDER BY field_order ASC";
+        $result = Database::query($sql);
+        $i = 1;
+        while ($row = Database::fetch_array($result)) {
+            $sql_reorder = "UPDATE $table_user_field SET field_order = '" . Database::escape_string($i) . "' WHERE id = '" . Database::escape_string($row['id']) . "'";
+            $result_reorder = Database::query($sql_reorder);
+            $i++;
+        }
+
+        // field was deleted so we return true
+        return true;
+    } else {
+        // the field was not deleted so we return false
+        return false;
+    }
 }

+ 108 - 144
main/admin/user_fields_options.php

@@ -1,8 +1,9 @@
 <?php
+
 /* For licensing terms, see /license.txt */
 /**
-*	@package chamilo.admin
-*/
+ * 	@package chamilo.admin
+ */
 // name of the language file that needs to be included
 $language_file = array('admin', 'registration');
 
@@ -13,22 +14,15 @@ $cidReset = true;
 require '../inc/global.inc.php';
 
 // section for the tabs
-$this_section=SECTION_PLATFORM_ADMIN;
+$this_section = SECTION_PLATFORM_ADMIN;
 
 // user permissions
 api_protect_admin_script();
 
-// Database table definitions
-$table_admin				= Database :: get_main_table(TABLE_MAIN_ADMIN);
-$table_user 				= Database :: get_main_table(TABLE_MAIN_USER);
-$table_userfields	 		= Database :: get_main_table(TABLE_MAIN_USER_FIELD);
-$table_userfields_options 	= Database :: get_main_table(TABLE_MAIN_USER_FIELD_OPTIONS);
-$table_userfields_values 	= Database :: get_main_table(TABLE_MAIN_USER_FIELD_VALUES);
-
 // breadcrumbs
-$interbreadcrumb[] = array ('url' => 'index.php', 'name' => get_lang('PlatformAdmin'));
-$interbreadcrumb[] = array ('url' => 'user_fields.php', 'name' => get_lang('UserFields'));
-$interbreadcrumb[] = array ('url' => 'user_fields_add.php?action=edit&field_id='.Security::remove_XSS($_GET['field_id']).'&amp;sec_token='.$_SESSION['sec_token'], 'name' => get_lang('EditUserFields'));
+$interbreadcrumb[] = array('url' => 'index.php', 'name' => get_lang('PlatformAdmin'));
+$interbreadcrumb[] = array('url' => 'user_fields.php', 'name' => get_lang('UserFields'));
+$interbreadcrumb[] = array('url' => 'user_fields_add.php?action=edit&field_id=' . Security::remove_XSS($_GET['field_id']) . '&amp;sec_token=' . $_SESSION['sec_token'], 'name' => get_lang('EditUserFields'));
 
 // name of the tools
 $tool_name = get_lang('UserFieldsSortOptions');
@@ -36,46 +30,35 @@ $tool_name = get_lang('UserFieldsSortOptions');
 // display header
 Display::display_header($tool_name);
 
-if (isset ($_GET['action']))
-{
-	$check = Security::check_token('get');
-	if($check)
-	{
-		switch ($_GET['action'])
-		{
-			case 'moveup' :
-				if (api_is_platform_admin() && !empty($_GET['option_id']))
-				{
-					if (move_user_field_option('moveup', $_GET['option_id']))
-					{
-						Display :: display_confirmation_message(get_lang('FieldOptionMovedUp'));
-					}
-					else
-					{
-						Display :: display_error_message(get_lang('CannotMoveFieldOption'));
-					}
-				}
-				break;
-			case 'movedown' :
-				if (api_is_platform_admin() && !empty($_GET['option_id']))
-				{
-					if (move_user_field_option('movedown', $_GET['option_id']))
-					{
-						Display :: display_confirmation_message(get_lang('FieldOptionMovedDown'));
-					}
-					else
-					{
-						Display :: display_error_message(get_lang('CannotMoveFieldOption'));
-					}
-				}
-				break;
-		}
-	}
+if (isset($_GET['action'])) {
+    $check = Security::check_token('get');
+    if ($check) {
+        switch ($_GET['action']) {
+            case 'moveup' :
+                if (api_is_platform_admin() && !empty($_GET['option_id'])) {
+                    if (move_user_field_option('moveup', $_GET['option_id'])) {
+                        Display :: display_confirmation_message(get_lang('FieldOptionMovedUp'));
+                    } else {
+                        Display :: display_error_message(get_lang('CannotMoveFieldOption'));
+                    }
+                }
+                break;
+            case 'movedown' :
+                if (api_is_platform_admin() && !empty($_GET['option_id'])) {
+                    if (move_user_field_option('movedown', $_GET['option_id'])) {
+                        Display :: display_confirmation_message(get_lang('FieldOptionMovedDown'));
+                    } else {
+                        Display :: display_error_message(get_lang('CannotMoveFieldOption'));
+                    }
+                }
+                break;
+        }
+    }
 }
 
 // getting all the information of the field
 $field_info = UserManager::get_extra_field_information($_GET['field_id']);
-echo '<strong>'.$field_info['3'].'</strong><br />';
+echo Display::page_header($field_info['3']);
 
 // the total number of options (used in the actions_filter function but declared here for performance reasons)
 $number_of_options = get_number_of_options();
@@ -83,7 +66,7 @@ $number_of_options = get_number_of_options();
 // displaying the sortable table
 $parameters['sec_token'] = Security::get_token();
 $parameters['field_id'] = Security::remove_XSS($_GET['field_id']);
-$table = new SortableTable('options', 'get_number_of_options', 'get_options_data',2);
+$table = new SortableTable('options', 'get_number_of_options', 'get_options_data', 2);
 $table->set_additional_parameters($parameters);
 $table->set_header(0, get_lang('DisplayOrder'), false);
 $table->set_header(1, get_lang('OptionText'), false);
@@ -94,59 +77,50 @@ $table->display();
 // display footer
 Display::display_footer();
 
+function get_options_data($from, $number_of_items, $column, $direction) {
+    // Database table definition
+    $table_userfields_options = Database :: get_main_table(TABLE_MAIN_USER_FIELD_OPTIONS);
 
-function get_options_data($from, $number_of_items, $column, $direction)
-{
-	// Database table definition
-	$table_userfields_options 	= Database :: get_main_table(TABLE_MAIN_USER_FIELD_OPTIONS);
-
-	// The sql statement
-	$sql = "SELECT
+    // The sql statement
+    $sql = "SELECT
 				option_order 		AS col0,
 				option_display_text	AS col1,
 				id 					AS col2
-			FROM $table_userfields_options WHERE field_id='".Database::escape_string($_GET['field_id'])."' ORDER BY option_order ASC";
-	$sql .= " LIMIT $from,$number_of_items";
-	$res = Database::query($sql);
-	$return = array ();
-	while ($option = Database::fetch_row($res))
-	{
-		$return[] = $option;
-	}
-	return $return;
+			FROM $table_userfields_options WHERE field_id='" . Database::escape_string($_GET['field_id']) . "' ORDER BY option_order ASC";
+    $sql .= " LIMIT $from,$number_of_items";
+    $res = Database::query($sql);
+    $return = array();
+    while ($option = Database::fetch_row($res)) {
+        $return[] = $option;
+    }
+    return $return;
 }
 
-function get_number_of_options($from=null, $number_of_items=null, $column=null, $direction=null)
-{
-	// Database table definition
-	$table_userfields_options 	= Database :: get_main_table(TABLE_MAIN_USER_FIELD_OPTIONS);
+function get_number_of_options($from = null, $number_of_items = null, $column = null, $direction = null) {
+    // Database table definition
+    $table_userfields_options = Database :: get_main_table(TABLE_MAIN_USER_FIELD_OPTIONS);
 
-	// The sql statement
-	$sql = "SELECT count(id) as total FROM $table_userfields_options WHERE field_id='".Database::escape_string($_GET['field_id'])."' ";
-	$res = Database::query($sql);
-	$row = Database::fetch_row($res);
-	return $row[0];
+    // The sql statement
+    $sql = "SELECT count(id) as total FROM $table_userfields_options WHERE field_id='" . Database::escape_string($_GET['field_id']) . "' ";
+    $res = Database::query($sql);
+    $row = Database::fetch_row($res);
+    return $row[0];
 }
 
-function actions_filter($option_id,$url_params,$row)
-{
-	global $number_of_options;
-
-	if ($row[0]<>1)
-	{
-		$return .= '<a href="'.api_get_self().'?action=moveup&amp;option_id='.$option_id.'&amp;field_id='.Security::remove_XSS($_GET['field_id']).'&amp;sec_token='.$_SESSION['sec_token'].'">'.Display::return_icon('up.gif', get_lang('Up')).'</a>';
-	}
-	else
-	{
-		$return .= Display::return_icon('blank.gif','',array('width'=>'21px'));
-	}
-
-	// the down icon only has to appear when the row can be moved down (all but the last row)
-	if ($row[0]<>$number_of_options)
-	{
-		$return .= '<a href="'.api_get_self().'?action=movedown&amp;option_id='.$option_id.'&amp;field_id='.Security::remove_XSS($_GET['field_id']).'&amp;sec_token='.$_SESSION['sec_token'].'">'.Display::return_icon('down.gif', get_lang('Down')).'</a>';
-	}
-	return $return;
+function actions_filter($option_id, $url_params, $row) {
+    global $number_of_options;
+
+    if ($row[0] <> 1) {
+        $return .= '<a href="' . api_get_self() . '?action=moveup&amp;option_id=' . $option_id . '&amp;field_id=' . Security::remove_XSS($_GET['field_id']) . '&amp;sec_token=' . $_SESSION['sec_token'] . '">' . Display::return_icon('up.gif', get_lang('Up')) . '</a>';
+    } else {
+        $return .= Display::return_icon('blank.gif', '', array('width' => '21px'));
+    }
+
+    // the down icon only has to appear when the row can be moved down (all but the last row)
+    if ($row[0] <> $number_of_options) {
+        $return .= '<a href="' . api_get_self() . '?action=movedown&amp;option_id=' . $option_id . '&amp;field_id=' . Security::remove_XSS($_GET['field_id']) . '&amp;sec_token=' . $_SESSION['sec_token'] . '">' . Display::return_icon('down.gif', get_lang('Down')) . '</a>';
+    }
+    return $return;
 }
 
 /**
@@ -159,53 +133,43 @@ function actions_filter($option_id,$url_params,$row)
  * @version July 2008
  * @since Dokeos 1.8.6
  */
-function move_user_field_option($direction,$option_id)
-{
-	// Database table definition
-	$table_userfields_options 	= Database :: get_main_table(TABLE_MAIN_USER_FIELD_OPTIONS);
-
-	// check the parameters
-	if (!in_array($direction,array('moveup','movedown')) OR !is_numeric($option_id))
-	{
-		return false;
-	}
-
-	// determine the SQL sort direction
-	if ($direction == 'moveup')
-	{
-		$sortdirection = 'DESC';
-	}
-	else
-	{
-		$sortdirection = 'ASC';
-	}
-
-	$found = false;
-
-	$sql = "SELECT id, option_order FROM $table_userfields_options  WHERE field_id='".Database::escape_string($_GET['field_id'])."' ORDER BY option_order $sortdirection";
-	$result = Database::query($sql);
-	while($row = Database::fetch_array($result))
-	{
-		if ($found)
-		{
-			$next_id = $row['id'];
-			$next_order = $row['option_order'];
-			break;
-		}
-
-		if ($option_id == $row['id'])
-		{
-			$this_id = $row['id'];
-			$this_order = $row['option_order'];
-			$found = true;
-		}
-	}
-
-	$sql1 = "UPDATE ".$table_userfields_options." SET option_order = '".Database::escape_string($next_order)."' WHERE id =  '".Database::escape_string($this_id)."'";
-	$sql2 = "UPDATE ".$table_userfields_options." SET option_order = '".Database::escape_string($this_order)."' WHERE id =  '".Database::escape_string($next_id)."'";
-	Database::query($sql1);
-	Database::query($sql2);
-
-	return true;
-}
-?>
+function move_user_field_option($direction, $option_id) {
+    // Database table definition
+    $table_userfields_options = Database :: get_main_table(TABLE_MAIN_USER_FIELD_OPTIONS);
+
+    // check the parameters
+    if (!in_array($direction, array('moveup', 'movedown')) OR !is_numeric($option_id)) {
+        return false;
+    }
+
+    // determine the SQL sort direction
+    if ($direction == 'moveup') {
+        $sortdirection = 'DESC';
+    } else {
+        $sortdirection = 'ASC';
+    }
+
+    $found = false;
+
+    $sql = "SELECT id, option_order FROM $table_userfields_options  WHERE field_id='" . Database::escape_string($_GET['field_id']) . "' ORDER BY option_order $sortdirection";
+    $result = Database::query($sql);
+    while ($row = Database::fetch_array($result)) {
+        if ($found) {
+            $next_id = $row['id'];
+            $next_order = $row['option_order'];
+            break;
+        }
+
+        if ($option_id == $row['id']) {
+            $this_id = $row['id'];
+            $this_order = $row['option_order'];
+            $found = true;
+        }
+    }
+
+    $sql1 = "UPDATE " . $table_userfields_options . " SET option_order = '" . Database::escape_string($next_order) . "' WHERE id =  '" . Database::escape_string($this_id) . "'";
+    $sql2 = "UPDATE " . $table_userfields_options . " SET option_order = '" . Database::escape_string($this_order) . "' WHERE id =  '" . Database::escape_string($next_id) . "'";
+    Database::query($sql1);
+    Database::query($sql2);
+    return true;
+}

+ 14 - 7
main/admin/user_information.php

@@ -97,7 +97,11 @@ if (count($sessions) > 0) {
             $row = array ();
             $row[] = $my_course['code'];
             $row[] = $course_info['title'];
-            $row[] = $my_course['status'] == STUDENT ? get_lang('Student') : get_lang('Teacher');
+            //$row[] = $my_course['status'] == STUDENT ? get_lang('Student') : get_lang('Teacher');
+            
+            $roles = api_detect_user_roles($user['user_id'], $my_course['code'], $id_session);
+            $row[] = api_get_roles_to_string($roles);
+        
             
             $tools = '<a href="course_information.php?code='.$course_info['code'].'&id_session='.$id_session.'">'.Display::return_icon('synthese_view.gif', get_lang('Overview')).'</a>'.
                     '<a href="'.api_get_path(WEB_COURSE_PATH).$course_info['path'].'?id_session='.$id_session.'">'.Display::return_icon('course_home.gif', get_lang('CourseHomepage')).'</a>';
@@ -112,7 +116,7 @@ if (count($sessions) > 0) {
         Display :: display_sortable_table($header, $data, array (), array(), array ('user_id' => intval($_GET['user_id'])));
     }
 } else {
-    echo '<p>'.get_lang('NoSessionsForThisUser').'</p>';
+    Display::display_warning_message(get_lang('NoSessionsForThisUser'));
 }
 
 
@@ -129,12 +133,15 @@ if (Database::num_rows($res) > 0) {
     $header[] = array (get_lang('Title'), true);
     $header[] = array (get_lang('Status'), true);
     $header[] = array ('', false);
-    $data = array ();
+    $data = array();
     while ($course = Database::fetch_object($res)) {
         $row = array ();
         $row[] = $course->code;
         $row[] = $course->title;
-        $row[] = $course->status == STUDENT ? get_lang('Student') : get_lang('Teacher');
+        
+        //$row[] = $course->status == STUDENT ? get_lang('Student') : get_lang('Teacher');
+        $roles = api_detect_user_roles($user['user_id'], $course->code);
+        $row[] = api_get_roles_to_string($roles);
         $tools = '<a href="course_information.php?code='.$course->code.'">'.Display::return_icon('synthese_view.gif', get_lang('Overview')).'</a>'.
                 '<a href="'.api_get_path(WEB_COURSE_PATH).$course->directory.'">'.Display::return_icon('course_home.gif', get_lang('CourseHomepage')).'</a>' .
                 '<a href="course_edit.php?course_code='.$course->code.'">'.Display::return_icon('edit.gif', get_lang('Edit')).'</a>';
@@ -148,7 +155,7 @@ if (Database::num_rows($res) > 0) {
     echo Display::page_subheader(get_lang('Courses'));
     Display :: display_sortable_table($header, $data, array (), array (), array ('user_id' => intval($_GET['user_id'])));    
 } else {
-    echo '<p>'.get_lang('NoCoursesForThisUser').'</p>';
+    Display::display_warning_message(get_lang('NoCoursesForThisUser'));
 }
 
 /**
@@ -174,8 +181,8 @@ if (Database::num_rows($res) > 0) {
     echo '<blockquote>';
     Display :: display_sortable_table($header, $data, array (), array (), array ('user_id' => intval($_GET['user_id'])));
     echo '</blockquote>';
-} else {
-    echo '<p>'.get_lang('NoClassesForThisUser').'</p>';
+} else {    
+    Display::display_warning_message(get_lang('NoClassesForThisUser'));
 }
 
 /**

+ 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/auth/inscription.php

@@ -155,7 +155,7 @@ if ($user_already_registered_show_terms == false) {
     }
     // EXTRA FIELDS
     $extra_data = UserManager::get_extra_user_data(api_get_user_id(), true);
-    UserManager::set_extra_fields_in_form($form, $extra_data, 'registration');
+    ExtraField::set_extra_fields_in_form($form, $extra_data, 'registration', false, null, 'user');
 }
 
 if (isset($_SESSION['user_language_choice']) && $_SESSION['user_language_choice'] != '') {

+ 2 - 2
main/auth/profile.php

@@ -280,7 +280,7 @@ if (is_platform_authentication() && is_profile_editable() && api_get_setting('pr
 
 // EXTRA FIELDS
 $extra_data = UserManager::get_extra_user_data(api_get_user_id(), true);
-$return_params = UserManager::set_extra_fields_in_form($form, $extra_data, 'profile', api_get_user_id());
+$return_params = ExtraField::set_extra_fields_in_form($form, $extra_data, 'profile', api_get_user_id(), 'user');
 $jquery_ready_content = $return_params['jquery_ready_content'];
 
 // the $jquery_ready_content variable collects all functions that will be load in the $(document).ready javascript function
@@ -612,7 +612,7 @@ if ($form->validate()) {
 
 	// User tag process
 	//1. Deleting all user tags
-	$list_extra_field_type_tag = UserManager::get_all_extra_field_by_type(UserManager::USER_FIELD_TYPE_TAG);
+	$list_extra_field_type_tag = UserManager::get_all_extra_field_by_type(ExtraField::FIELD_TYPE_TAG);
     
 	if (is_array($list_extra_field_type_tag) && count($list_extra_field_type_tag)>0) {
 		foreach ($list_extra_field_type_tag as $id) {

+ 17 - 15
main/auth/sso/sso.class.php

@@ -53,6 +53,17 @@ class sso {
         header('Location: '.$this->master_url.'&sso_referer='.urlencode($this->referer).'&sso_target='.urlencode($this->target));
         exit;
     }
+    
+    function redirect_to($sso, $user_id, $logged_in) {           
+        if (isset($sso['target']) && !empty($sso['target'])) {
+            header('Location: '. $sso['target']);    
+        } else {
+            //Use this handy function to deal with platform settings
+            Redirect::session_request_uri($logged_in, $user_id);                                            
+        }                                            
+        exit;
+    }
+    
     /**
      * Validates the received active connection data with the database
      * @return	bool	Return the loginFailed variable value to local.inc.php
@@ -121,13 +132,10 @@ class sso {
                                     if (is_array($my_url_list) && count($my_url_list)>0 ) {
                                         if (in_array($current_access_url_id, $my_url_list)) {
                                             // the user has permission to enter at this site
-                                            $_user['user_id'] = $uData['user_id'];
+                                            $_user['user_id'] = $uData['user_id'];                                            
                                             Session::write('_user',$_user);
-                                            event_login();
-                                            // Redirect to homepage
-                                            $sso_target = isset($sso['target']) ? $sso['target'] : api_get_path(WEB_PATH) .'.index.php';
-                                            header('Location: '. $sso_target);
-                                            exit;
+                                            event_login();                                            
+                                            self::redirect_to($sso, $_user['user_id'], true);                                        
                                         } else {
                                             // user does not have permission for this site
                                             $loginFailed = true;
@@ -152,6 +160,7 @@ class sso {
                                         $_user['user_id'] = $uData['user_id'];
                                         Session::write('_user',$_user);
                                         event_login();
+                                        self::redirect_to($sso, $_user['user_id'], true);
                                     } else {
                                         //Secondary URL admin wants to login 
                                         // so we check as a normal user
@@ -159,6 +168,7 @@ class sso {
                                             $_user['user_id'] = $uData['user_id'];
                                             Session::write('_user',$_user);
                                             event_login();
+                                            self::redirect_to($sso, $_user['user_id'], true);
                                         } else {
                                             $loginFailed = true;
                                             Session::erase('_uid');
@@ -172,15 +182,7 @@ class sso {
                                 $_user['user_id'] = $uData['user_id'];
                                 Session::write('_user',$_user);
                                 event_login();
-                                // Redirect to homepage
-                                /* Login was successfull, stay on Chamilo 
-                                $protocol = api_get_setting('sso_authentication_protocol');
-                                $master_url = api_get_setting('sso_authentication_domain');
-                                $target = $protocol.$master_url;
-                                $sso_target = isset($target) ? $target : api_get_path(WEB_PATH) .'.index.php';
-                                header('Location: '. $sso_target);
-                                exit;
-                                */
+                                self::redirect_to($sso, $_user['user_id'], true);                               
                             }
                         } else {
                             // user account expired

+ 1 - 1
main/calendar/agenda_js.php

@@ -28,7 +28,7 @@ $current_course_tool  = TOOL_CALENDAR_EVENT;
 
 $this_section = SECTION_MYAGENDA;
 
-$htmlHeadXtra[] = api_get_jquery_libraries_js(array('jquery-ui','jquery-ui-i18n'));
+$htmlHeadXtra[] = api_get_jquery_libraries_js(array('jquery-ui-i18n'));
 $htmlHeadXtra[] = api_get_js('qtip2/jquery.qtip.min.js');
 $htmlHeadXtra[] = api_get_js('fullcalendar/fullcalendar.min.js');
 $htmlHeadXtra[] = api_get_js('fullcalendar/gcal.js');

+ 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);        

+ 1 - 1
main/coursecopy/classes/CourseBuilder.class.php

@@ -493,7 +493,7 @@ class CourseBuilder {
 		// Building a fictional test for collecting orphan questions.
 		$build_orphan_questions = !empty($_POST['recycle_option']); // When a course is emptied this option should be activated (true).
         
-		$sql = "SELECT questions.* FROM $table_que as questions
+		$sql = "SELECT * FROM $table_que as questions 
                 LEFT JOIN $table_rel as quizz_questions 
                     ON (questions.id = quizz_questions.question_id AND questions.c_id = $course_id AND quizz_questions.c_id = $course_id)
                 LEFT JOIN $table_qui as exercices 

+ 0 - 9
main/css/academica/default.css

@@ -229,15 +229,6 @@ ul#navigation .student-connect a {
 	list-style-type: none;
 	margin-bottom: 5px;
 }
-/* user_portal session list */
-.session_course_item .courses {
-	margin-bottom: 5px;
-	height:35px;
-}
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-}
 
 .courses a {
 	text-decoration:underline;

+ 1 - 13
main/css/baby_orange/default.css

@@ -1067,20 +1067,8 @@ div.system_announcement {
 	margin-bottom: 10px;
 	background-color:#F9F9F9;
 }
-.session_course_item {
-	margin: 0px;
-	margin-bottom:20px;
-	font-size:135%;
-}
-.session_course_item .item_closed, .userportal-course-item-title .item_closed {
-     font-size:80%; 
-}
-.session_course_item .courses {
-	margin-bottom: 5px;
-	height:35px;
-}
-/*NAVIGATION MENU BAR*/
 
+/*NAVIGATION MENU BAR*/
 
 .menucaption {
 	font-size: 12px;

+ 36 - 31
main/css/base.css

@@ -52,8 +52,8 @@ header #logo {
 }
 
 .subnav {
-    font-size: 11px;
-    font-weight: bold;
+    /*font-size: 11px;
+    font-weight: bold;*/
 }
 
 .subnav .btn-navbar {
@@ -379,7 +379,7 @@ footer .container .row {
     border:1px solid #ccc;
     margin-bottom: 11px;
     height:32px;
-    padding: 2px 2px 2px 14px;
+    padding: 2px 2px 2px 8px;
     vertical-align:middle;    
 }
 
@@ -482,16 +482,11 @@ a.tag {
     margin-bottom: 5px;
     height: 30px;
 }
-/* user_portal session list */
-.session_course_item .courses {
-    margin-bottom: 5px;
-    height:35px;
-}
-.session_course_item {
-    /* padding: 0px; */
-    margin: 0px;
-    margin-bottom:15px;
-    font-size:135%;
+
+/* Fixes course items with bootstrap 2.1.1*/
+.course_item h3{
+    margin:0px 0px 5px 0px;
+    line-height: 28px;
 }
 
 .userportal-course-item {
@@ -507,9 +502,6 @@ a.tag {
     margin-bottom: 7px;
 }
 
-.session_course_item .item_closed, .userportal-course-item-title .item_closed {
-    font-size:80%;
-}
 #maincontent .courseslist li {
     margin-bottom:8px;
 }
@@ -1971,7 +1963,7 @@ div.image-social-content center.friend {
     margin-right:4px;
 }
 
-
+/*
 textarea {
     border:1px solid #CCCCCC;
     padding:5px;
@@ -1980,7 +1972,8 @@ textarea {
     border-radius:5px;
     color:#666666;
 }
-
+*/
+/*
 select {
     color:#555;
     border: 1px solid #CCC;
@@ -1991,7 +1984,7 @@ select {
     -moz-border-radius:5px;
     -webkit-border-radius:5px;
     border-radius:5px;
-}
+}*/
 
 /* Fixes the FB input*/
 input.maininput:focus {
@@ -2010,6 +2003,17 @@ input.maininput:focus {
     margin-bottom: 20px;
 }
 
+/* session.php */
+#session_course_list .big_icon {
+    padding:10px;
+    text-align:center;
+}
+
+#session_course_list .content {
+    text-align:center;
+    margin-bottom: 20px;
+}
+
 .big_icon img {
     padding:5px;
     -moz-border-radius:10px;
@@ -2059,18 +2063,7 @@ input.maininput:focus {
     padding: 18px;
 }
 
-/* Makes the course elements more readable */
-.userportal-course-item {
-
-}
-
-.session_course_item {
-    padding: 6px 0px 6px 5px ;
-}
-
 /* LP tool*/
-
-
 #lp_overview .thumbnail {
     text-align: center;
 }
@@ -2715,6 +2708,11 @@ div.admin_section h4 {
     color: green;
 }
 
+.ribbon h3 {
+    font-size: 18px;
+    line-height: 9px;
+}
+
 .exercise_save_now_button img {
     position: relative;
     top: 4px;
@@ -2896,9 +2894,11 @@ form .formw .freeze {
 .label_tag.admin_event {
     background:red;
 }
+
 .label_tag.course_event {
     background:#458B00;
 }
+
 .label_tag.group_event {
     background:#A0522D;
 }
@@ -3811,7 +3811,7 @@ a.forum_group_link {
 }
 
 #main_content .course_item {
-    padding: 5px 0px 5px 0px;
+    padding: 0px 0px 16px 0px;
 }
 
 /* actions */
@@ -4670,4 +4670,9 @@ i.size-32.icon-new-work{
 
 #filepaths input{
     margin-bottom:5px;    
+}
+
+/* Fixing z-index */
+#ui-datepicker-div {
+    z-index: 1005 !important;
 }

+ 6 - 35
main/css/blue_lagoon/default.css

@@ -7,7 +7,7 @@
 /* Redefining html styles */
 body {
 	/* hack ignored by non-IE to enable ie to support :hover on button */
-     behavior:url("/main/css/csshover3.htc");
+    behavior:url("/main/css/csshover3.htc");
 	font-family: arial, verdana, helvetica, sans-serif;
 	font-size: 12px;
 	color: #000;
@@ -20,7 +20,7 @@ body {
 #main {
 	float: left;
 	margin: 0px auto;
-	margin-top: 5x;
+	margin-top: 5px;
 	width: 96%;
 	padding: 0px 10px 10px 10px;
 	min-height: 320px;
@@ -56,7 +56,7 @@ ul#navigation li a {
     border:1px solid #AFAFAF;
     -moz-border-radius:10px 0px 0px 10px;
     -webkit-border-bottom-right-radius: 10px;
-    -webkit-border-top-right-radius: 10x;
+    -webkit-border-top-right-radius: 10px;
     -khtml-border-bottom-right-radius: 10px;
     -khtml-border-top-right-radius: 10px;
     -moz-box-shadow: 0px 4px 3px #000;
@@ -217,7 +217,7 @@ ul#navigation li a {
 	border:1px solid #AFAFAF;
 	-moz-border-radius:10px 0px 0px 10px;
 	-webkit-border-bottom-right-radius: 10px;
-	-webkit-border-top-right-radius: 10x;
+	-webkit-border-top-right-radius: 10px;
 	-khtml-border-bottom-right-radius: 10px;
 	-khtml-border-top-right-radius: 10px;
 	-moz-box-shadow: 0px 4px 3px #000;
@@ -310,49 +310,20 @@ input[type="text"]:focus, input[type="password"]:focus, textarea:focus {
 	padding-right: 5px;
 	width: auto;
 }
+
 /* user_portal course list */
 .courses {
 	list-style-type: none;
 	margin-bottom: 5px;
 	height: 30px;
 }
-/* user_portal session list */
-.session_course_item .courses {
-	margin-bottom: 5px;
-	height:35px;
-}
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-	font-size:135%;
-}
-
-.session_course_item .item_closed, .userportal-course-item-title .item_closed {
-     font-size:80%; 
-}
 
-/*****************************************************
- *  HEADER STYLES                                    *
- *****************************************************/
 #header {
 	width: 100%;
 	padding: 0;
 	margin: 0;
 }
-/********************************************************
- *  HEADER 1: Title, portal, organisation, course title	*
- ********************************************************/
-#header1 {
-	padding: 4px;
-	color: #8e975b;
-}
-#header1 a {
-	color: #636363;
-	text-decoration: none;
-}
-#header1 a:hover {
-	text-decoration: underline;
-}
+
 #sitename {
 	margin: 0;
 	font-weight: bold;

File diff ditekan karena terlalu besar
+ 491 - 261
main/css/bootstrap-responsive.css


File diff ditekan karena terlalu besar
+ 408 - 171
main/css/bootstrap.css


+ 2 - 28
main/css/cool_blue/default.css

@@ -45,7 +45,7 @@ ul#navigation li a {
     border:1px solid #AFAFAF;
     -moz-border-radius:10px 0px 0px 10px;
     -webkit-border-bottom-right-radius: 10px;
-    -webkit-border-top-right-radius: 10x;
+    -webkit-border-top-right-radius: 10px;
     -khtml-border-bottom-right-radius: 10px;
     -khtml-border-top-right-radius: 10px;
     -moz-box-shadow: 0px 4px 3px #000;
@@ -276,19 +276,6 @@ a:active {
 	margin-bottom: 5px;
 	height: 30px;
 }
-/* user_portal session list */
-.session_course_item .courses {
-	margin-bottom: 5px;
-	height:35px;
-}
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-	font-size:135%;
-}
-.session_course_item .item_closed, .userportal-course-item-title .item_closed {
-     font-size:80%; 
-}
 
 /*****************************************************
  *  HEADER STYLES                                    *
@@ -298,20 +285,7 @@ a:active {
 	padding: 0;
 	margin: 0;
 }
-/********************************************************
- *  HEADER 1: Title, portal, organisation, course title	*
- ********************************************************/
-#header1 {
-	padding: 4px;
-	color: #2ea2c5;
-}
-#header1 a {
-	color: #636363;
-	text-decoration: none;
-}
-#header1 a:hover {
-	text-decoration: underline;
-}
+
 #sitename {
 	margin: 0;
 	font-weight: bold;

+ 1 - 11
main/css/corporate/default.css

@@ -140,7 +140,7 @@ ul#navigation li a {
     border:1px solid #AFAFAF;
     -moz-border-radius:10px 0px 0px 10px;
     -webkit-border-bottom-right-radius: 10px;
-    -webkit-border-top-right-radius: 10x;
+    -webkit-border-top-right-radius: 10px;
     -khtml-border-bottom-right-radius: 10px;
     -khtml-border-top-right-radius: 10px;
     -moz-box-shadow: 0px 4px 3px #000;
@@ -277,16 +277,6 @@ ul#navigation .student-connect a {
 	padding: 5px;
 }
 
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-	font-size:135%;
-}
-.session_course_item .courses {
-	margin-bottom: 5px;
-	height:35px;
-}
-
 .menu {
 	float: right;
 	width: 200px;

+ 0 - 13
main/css/cosmic_campus/default.css

@@ -274,19 +274,6 @@ ul#navigation .student-connect a {
 	margin-bottom: 5px;
 	height: 30px;
 }
-/* user_portal session list */
-.session_course_item .courses {
-	margin-bottom: 5px;
-	height:35px;
-}
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-	font-size:135%;
-}
-.session_course_item .item_closed, .userportal-course-item-title .item_closed {
-     font-size:80%; 
-}
 .user_course_category {
 	background-color: #efefef;
 	border: 1px solid #666;

+ 1 - 28
main/css/delicious_bordeaux/default.css

@@ -304,20 +304,6 @@ input[type="text"]:focus, input[type="password"]:focus, textarea:focus {
 	margin-bottom: 5px;
 	height: 30px;
 }
-/* user_portal session list */
-.session_course_item .courses {
-	margin-bottom: 5px;
-	height:35px;
-}
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-	font-size:135%;
-}
-.session_course_item .item_closed, .userportal-course-item-title .item_closed {
-     font-size:80%; 
-}
-
 /*****************************************************
  *  HEADER STYLES                                    *
  *****************************************************/
@@ -326,20 +312,7 @@ input[type="text"]:focus, input[type="password"]:focus, textarea:focus {
 	padding: 0;
 	margin: 0;
 }
-/********************************************************
- *  HEADER 1: Title, portal, organisation, course title	*
- ********************************************************/
-#header1 {
-	padding: 4px;
-	color: #975b5b;
-}
-#header1 a {
-	color: #636363;
-	text-decoration: none;
-}
-#header1 a:hover {
-	text-decoration: underline;
-}
+
 #sitename {
 	margin: 0;
 	font-weight: bold;

+ 0 - 36
main/css/dokeos_blue/default.css

@@ -303,42 +303,6 @@ input[type="text"]:focus, input[type="password"]:focus, textarea:focus {
 	margin-bottom: 5px;
 	height: 30px;
 }
-/* user_portal session list */
-.session_course_item .courses {
-	margin-bottom: 5px;
-	height:35px;
-}
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-	font-size:135%;
-}
-.session_course_item .item_closed, .userportal-course-item-title .item_closed {
-     font-size:80%; 
-}
-
-/*****************************************************
- *  HEADER STYLES                                    *
- *****************************************************/
-#header {
-	width: 100%;
-	padding: 0;
-	margin: 0;
-}
-/********************************************************
- *  HEADER 1: Title, portal, organisation, course title	*
- ********************************************************/
-#header1 {
-	padding: 4px;
-	color: #8e975b;
-}
-#header1 a {
-	color: #636363;
-	text-decoration: none;
-}
-#header1 a:hover {
-	text-decoration: underline;
-}
 #sitename {
 	margin: 0;
 	font-weight: bold;

+ 1 - 41
main/css/dokeos_classic/default.css

@@ -223,7 +223,7 @@ ul#navigation li a {
 	border:1px solid #AFAFAF;
 	-moz-border-radius:10px 0px 0px 10px;
 	-webkit-border-bottom-right-radius: 10px;
-	-webkit-border-top-right-radius: 10x;
+	-webkit-border-top-right-radius: 10px;
 	-khtml-border-bottom-right-radius: 10px;
 	-khtml-border-top-right-radius: 10px;
 	-moz-box-shadow: 0px 4px 3px #000;
@@ -309,46 +309,6 @@ input[text] {
 	margin-bottom: 5px;
 	height: 30px;
 }
-/* user_portal session list */
-.session_course_item .courses {
-	margin-bottom: 5px;
-	height:35px;
-}
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-	font-size:135%;
-}
-.session_course_item .item_closed, .userportal-course-item-title .item_closed {
-     font-size:80%; 
-}
-
-/*****************************************************
- *  HEADER STYLES                                    *
- *****************************************************/
-#header {
-	width: 100%;
-	padding: 0;
-	margin: 0;
-}
-/********************************************************
- *  HEADER 1: Title, portal, organisation, course title	*
- ********************************************************/
-#header1 {
-	font-size: 12px;
-	padding: 4px;
-	background-color: #264269;
-	color: #fff;
-	border-bottom: 1px solid white;
-}
-#header1 a {
-	color: #fff;
-	text-decoration: none;
-}
-#header1 a:hover {
-	background-color: #264269;
-	text-decoration: underline;
-}
 #sitename {
 	margin: 0;
 	font-weight: bold;

+ 2 - 36
main/css/dokeos_classic_2D/default.css

@@ -103,7 +103,7 @@ ul#navigation li a {
 	border:1px solid #AFAFAF;
 	-moz-border-radius:10px 0px 0px 10px;
 	-webkit-border-bottom-right-radius: 10px;
-	-webkit-border-top-right-radius: 10x;
+	-webkit-border-top-right-radius: 10px;
 	-khtml-border-bottom-right-radius: 10px;
 	-khtml-border-top-right-radius: 10px;
 	-moz-box-shadow: 0px 4px 3px #000;
@@ -162,7 +162,7 @@ ul#navigation li a {
     border:1px solid #AFAFAF;
     -moz-border-radius:10px 0px 0px 10px;
     -webkit-border-bottom-right-radius: 10px;
-    -webkit-border-top-right-radius: 10x;
+    -webkit-border-top-right-radius: 10px;
     -khtml-border-bottom-right-radius: 10px;
     -khtml-border-top-right-radius: 10px;
     -moz-box-shadow: 0px 4px 3px #000;
@@ -298,47 +298,13 @@ ul#navigation .student-connect a {
 	margin-bottom: 5px;
 	height: 30px;
 }
-/* user_portal session list */
-.session_course_item .courses {
-	margin-bottom: 5px;
-	height:35px;
-}
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-	font-size:135%;
-}
-
-/*
-	HEADER STYLES
-*/
 
 #header {
 	margin: 0;
 	padding: 0;
 	width: 100%;
 }
-/*
-------------------------------------------------------------------------------
-	HEADER 1: Title, portal, organisation, course title
-------------------------------------------------------------------------------
-*/
 
-#header1 {
-	background-color: #264269;
-	border-bottom: 1px solid white;
-	color: #fff;
-	font-size: 12px;
-	padding: 4px;
-}
-#header1 a {
-	color: #fff;
-	text-decoration: none;
-}
-#header1 a:hover {
-	background-color: #264269;
-	text-decoration: underline;
-}
 #sitename {
 	font-weight: bold;
 	margin: 0;

+ 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;

+ 12 - 9
main/document/showinframes.php

@@ -143,6 +143,7 @@ $frameheight = 135;
 if ($is_courseAdmin) {
     $frameheight = 165;
 }
+
 $js_glossary_in_documents = '';
 if (api_get_setting('show_glossary_in_documents') == 'ismanual') {
     $js_glossary_in_documents = '	//	    $(document).ready(function() {
@@ -151,8 +152,6 @@ if (api_get_setting('show_glossary_in_documents') == 'ismanual') {
                                       }, "top.mainFrame",
                                       { load: [
                                                 {type:"script", id:"_fr1", src:"'.api_get_path(WEB_LIBRARY_PATH).'javascript/jquery.min.js"},
-                                                {type:"script", id:"_fr4", src:"'.api_get_path(WEB_LIBRARY_PATH).'javascript/jquery-ui/smoothness/jquery-ui-1.8.21.custom.min.js"},
-                                                {type:"stylesheet", id:"_fr5", src:"'.api_get_path(WEB_LIBRARY_PATH).'javascript/jquery-ui/smoothness/jquery-ui-1.8.21.custom.css"}, 
                                                 {type:"script", id:"_fr2", src:"'.api_get_path(WEB_LIBRARY_PATH).'javascript/jquery.highlight.js"},
                                                 {type:"script", id:"_fr3", src:"'.api_get_path(WEB_LIBRARY_PATH).'fckeditor/editor/plugins/glossary/fck_glossary_manual.js"}
                                            ]
@@ -177,7 +176,6 @@ if (api_get_setting('show_glossary_in_documents') == 'ismanual') {
                                 //   });';
 }
 
-
 $web_odf_supported_files = DocumentManager::get_web_odf_extension_list();
 if (in_array(strtolower($pathinfo['extension']), $web_odf_supported_files)) {
     $show_web_odf  = true;    
@@ -235,6 +233,7 @@ if ($show_web_odf) {
     $execute_iframe = false;
 }
 
+
 $is_freemind_available = $pathinfo['extension']=='mm' && api_get_setting('enable_freemind') == 'true';
 if ($is_freemind_available){
     $execute_iframe = false;
@@ -298,7 +297,8 @@ if ($jplayer_supported) {
     echo '</div>';     
 }
 
-if ($is_freemind_available) { 
+
+if ($is_freemind_available) {
 	?>	
 	<script type="text/javascript" src="<?php echo api_get_path(WEB_LIBRARY_PATH) ?>swfobject/swfobject.js"></script>
 	<style type="text/css">
@@ -306,12 +306,12 @@ if ($is_freemind_available) {
 			height: 500px;
 			padding-top:10px;
 		}
-	</style>		
+	</style>
 	<div id="flashcontent" onmouseover="giveFocus();">
 		 Flash plugin or Javascript are turned off.
 		 Activate both  and reload to view the mindmap
 	</div>		
-	<script>
+	<script>        
         function giveFocus() { 
 		  document.visorFreeMind.focus();  
 		}
@@ -363,7 +363,6 @@ if ($is_freemind_available) {
 	<?php
 }
 
-
 if ($is_nanogong_available) {
 
 		//make temp audio
@@ -416,8 +415,12 @@ if ($is_nanogong_available) {
 		$_SESSION['temp_audio_nanogong']=$to_sys;      
     echo '</div>';    
 }
-
 if ($execute_iframe) {
     echo '<iframe id="mainFrame" name="mainFrame" border="0" frameborder="0" scrolling="no" style="width:100%;" height="600" src="'.$file_url_web.'&amp;rand='.mt_rand(1, 10000).'" height="500"></iframe>';
 }
-Display::display_footer();
+
+if (api_get_setting('show_glossary_in_documents') == 'isautomatic') {
+    echo '<div id="glossary_popup"></div>';
+}
+
+Display::display_footer();

+ 10 - 4
main/exercice/exercise_show.php

@@ -62,18 +62,24 @@ if ( empty ( $action ) ) {              $action         = $_REQUEST['action']; }
 $id = intval($_REQUEST['id']); //exe id
 
 if (empty($id)) {
-	api_not_allowed();
+	api_not_allowed(true);
 }
-
 $is_allowedToEdit    = api_is_allowed_to_edit(null,true) || $is_courseTutor || api_is_session_admin() || api_is_drh();
 
+//if (api_is_coach(api_get_session_id(), api_get_course_id())) {    
+if (api_is_course_session_coach(api_get_user_id(), api_get_course_id(), api_get_session_id())) {    
+    if (!api_coach_can_edit_view_results(api_get_course_id(), api_get_session_id())) {
+        api_not_allowed(true);
+    }
+}
+
 //Getting results from the exe_id. This variable also contain all the information about the exercise
 $track_exercise_info = get_exercise_track_exercise_info($id);
 
 
 //No track info
 if (empty($track_exercise_info)) {
-    api_not_allowed();
+    api_not_allowed(true);
 }
 
 $exercise_id        = $track_exercise_info['id'];
@@ -102,7 +108,7 @@ if (isset($session_control_key) && !exercise_time_control_is_valid($exercise_id,
 //Only users can see their own results 
 if (!$is_allowedToEdit) {
     if ($student_id != $current_user_id) {
-    	api_not_allowed();
+    	api_not_allowed(true);
     }
 }
 

+ 1 - 1
main/exercice/question_pool.php

@@ -285,7 +285,7 @@ if (isset($type)) {
 echo '<input type="hidden" name="fromExercise" value="'.$fromExercise.'">';
 
 // Session list, if sessions are used.
-$session_list = SessionManager::get_sessions_by_coach(api_get_user_id());
+$session_list = SessionManager::get_sessions_by_general_coach(api_get_user_id());
 $tabAttrParam = array('class'=>'chzn-select', 'onchange'=>'submit_form(this)');	// when sessions are used
 $labelFormRow = get_lang('Session');
 $session_select_list = array();

+ 61 - 67
main/gradebook/gradebook_display_certificate.php

@@ -19,6 +19,7 @@ require_once 'lib/gradebook_functions.inc.php';
 require_once 'lib/be.inc.php';
 require_once 'lib/gradebook_data_generator.class.php';
 
+
 //extra javascript functions for in html head:
 $htmlHeadXtra[] =
 "<script>
@@ -29,16 +30,14 @@ function confirmation() {
 		{return false;} 
 }
 </script>";
+
 api_block_anonymous_users();
 
 if (!api_is_allowed_to_edit()) {
 	api_not_allowed(true);
 }
 
-
-    
 $course_code = api_get_course_id();
-
 $interbreadcrumb[] = array ('url' => Security::remove_XSS($_SESSION['gradebook_dest']).'?',	'name' => get_lang('Gradebook'));
 $interbreadcrumb[] = array ('url' => '#','name' => get_lang('GradebookListOfStudentsCertificates'));
 $this_section = SECTION_COURSES;
@@ -47,90 +46,85 @@ Display::display_header('');
 if ($_GET['action'] == 'delete') {
     $check = Security::check_token('get');
     if ($check) {
-        $certificate = new Certificate($_GET['certificate_id']);
-        $result = $certificate->delete();
+    $certificate = new Certificate($_GET['certificate_id']);
+    $result = $certificate->delete();
         Security::clear_token();
-        if ($result ==true) {
-            Display::display_confirmation_message(get_lang('CertificateRemoved'));
-        } else  {
-            Display::display_error_message(get_lang('CertificateNotRemoved'));		
-        }
-    }
+	if ($result ==true) {
+		Display::display_confirmation_message(get_lang('CertificateRemoved'));
+	} else  {
+		Display::display_error_message(get_lang('CertificateNotRemoved'));		
+	}
+}
 }
 
 $token = Security::get_token();
 
 echo Display::page_header(get_lang('GradebookListOfStudentsCertificates'));
-$cat_id = isset($_GET['cat_id']) ? (int)$_GET['cat_id'] : null;
-
-//@todo replace all this code with something like get_total_weight()
-$cats = Category :: load ($cat_id, null, null, null, null, null, false);
-
-if (!empty($cats)) {
-
-    //with this fix the teacher only can view 1 gradebook
-    if (api_is_platform_admin()) {
-        $stud_id= (api_is_allowed_to_edit() ? null : api_get_user_id());
-    } else {
-        $stud_id= api_get_user_id();
-    }
-
-    $total_weight = $cats[0]->get_weight();
-
-    $allcat  = $cats[0]->get_subcategories($stud_id, api_get_course_id(), api_get_session_id());
-    $alleval = $cats[0]->get_evaluations($stud_id);
-    $alllink = $cats[0]->get_links($stud_id);
-
-    $datagen = new GradebookDataGenerator ($allcat,$alleval, $alllink);
-
-    $total_resource_weight = 0;
-    if (!empty($datagen)) {    
-        $data_array = $datagen->get_data(GradebookDataGenerator :: GDG_SORT_NAME,0,null,true);
+	$cat_id = isset($_GET['cat_id']) ? (int)$_GET['cat_id'] : null;
 
-        if (!empty($data_array)) {
-            $newarray = array();
-            foreach ($data_array as $data) {
-                $newarray[] = array_slice($data, 1);
+	//@todo replace all this code with something like get_total_weight()
+    $cats = Category :: load ($cat_id, null, null, null, null, null, false);
+    
+    if (!empty($cats)) {
+        
+        //with this fix the teacher only can view 1 gradebook
+        if (api_is_platform_admin()) {
+            $stud_id= (api_is_allowed_to_edit() ? null : api_get_user_id());
+        } else {
+            $stud_id= api_get_user_id();
+        }
+        
+        $total_weight = $cats[0]->get_weight();
+        
+        $allcat  = $cats[0]->get_subcategories($stud_id, api_get_course_id(), api_get_session_id());
+        $alleval = $cats[0]->get_evaluations($stud_id);
+        $alllink = $cats[0]->get_links($stud_id);
+        
+        $datagen = new GradebookDataGenerator ($allcat,$alleval, $alllink);
+        
+        $total_resource_weight = 0;
+        if (!empty($datagen)) {    
+            $data_array = $datagen->get_data(GradebookDataGenerator :: GDG_SORT_NAME,0,null,true);
+            
+            if (!empty($data_array)) {
+                $newarray = array();
+                foreach ($data_array as $data) {
+                    $newarray[] = array_slice($data, 1);
+                }
+                
+                foreach($newarray as $item) {
+                    $total_resource_weight = $total_resource_weight + $item['2'];
+                }            
             }
-
-            foreach($newarray as $item) {
-                $total_resource_weight = $total_resource_weight + $item['2'];
-            }            
+        }    
+    
+        if ($total_resource_weight != $total_weight) {
+            Display::display_warning_message(get_lang('SumOfActivitiesWeightMustBeEqualToTotalWeight'));
         }
-    }    
-
-    if ($total_resource_weight != $total_weight) {
-        Display::display_warning_message(get_lang('SumOfActivitiesWeightMustBeEqualToTotalWeight'));
     }
-}
-
-$certificate_list = get_list_users_certificates($cat_id);	
-
-if (count($certificate_list)==0) {
-    echo Display::display_warning_message(get_lang('NoResultsAvailable'));
-} else {
-    echo '<table class="data_table">';
     
-    foreach ($certificate_list as $index=>$value) {
+	$certificate_list = get_list_users_certificates($cat_id);	
+	
+	if (count($certificate_list)==0) {
+		echo Display::display_warning_message(get_lang('NoResultsAvailable'));
+	} else {
+    echo '<table class="data_table">';
+		foreach ($certificate_list as $index=>$value) {
         echo '<tr>
                     <td width="100%" class="actions">'.get_lang('Student').' : '.api_get_person_name($value['firstname'], $value['lastname']).' ( '.$value['username'].')</td>';
 		echo '</tr>';
         echo '<tr><td>
             <table class="data_table">';
-		
 		$list_certificate = get_list_gradebook_certificates_by_user_id ($value['user_id'], $cat_id);		
 		foreach ($list_certificate as $value_certificate) {
 			echo '<tr>';
 			echo '<td width="50%">'.get_lang('Score').' : '.$value_certificate['score_certificate'].'</td>';
 			echo '<td width="30%">'.get_lang('Date').' : '.api_convert_and_format_date($value_certificate['created_at']).'</td>';
 			echo '<td width="20%">';
-			
-            //$url = "index.php?export_certificate=yes&cat_id=".$cat_id."&user=".$value['user_id'];
-            $url = api_get_path(WEB_PATH).'certificates/index.php?id='.$value_certificate['id'];
-            $certificates = Display::url(get_lang('Certificate'), $url, array('target'=>'_blank', 'class' => 'btn'));
-            
-            echo $certificates;
-            
+                //$url = "index.php?export_certificate=yes&cat_id=".$cat_id."&user=".$value['user_id'];
+                $url = api_get_path(WEB_PATH).'certificates/index.php?id='.$value_certificate['id'];
+    			$certificates = Display::url(get_lang('Certificate'), $url, array('target'=>'_blank', 'class' => 'btn'));
+    			echo $certificates;
 			echo '<a onclick="return confirmation();" href="gradebook_display_certificate.php?sec_token='.$token.'&cidReq='.$course_code.'&action=delete&cat_id='.$cat_id.'&certificate_id='.$value_certificate['id'].'">
                     '.Display::return_icon('delete.png',get_lang('Delete')).'
                   </a>';
@@ -138,7 +132,7 @@ if (count($certificate_list)==0) {
 		}
 		echo '</table>';
         echo '</td></tr>';    
-    }
+		}
     echo '</table>';
-}
+	}
 Display::display_footer();

+ 2 - 2
main/gradebook/lib/gradebook_data_generator.class.php

@@ -189,8 +189,8 @@ class GradebookDataGenerator
 
     //  Other functions
 	private function build_result_column($item, $ignore_score_color) {
-		$scoredisplay = ScoreDisplay :: instance();        
-		$score 	     = $item->calc_score(api_get_user_id());
+		$scoredisplay = ScoreDisplay::instance();        
+		$score 	      = $item->calc_score(api_get_user_id());
 		
         if (!empty($score)) {        	
     		switch ($item->get_item_type()) {

+ 20 - 3
main/inc/ajax/admin.ajax.php

@@ -11,9 +11,26 @@ api_protect_admin_script();
 $action = isset($_REQUEST['a']) ? $_REQUEST['a'] : null;
 
 switch ($action) {
-	case 'update_changeable_setting':        
-        $url_id = api_get_current_access_url_id();
-        
+    case 'user_exists':        
+        $user_info = api_get_user_info($_REQUEST['id']);
+        if (empty($user_info)) {
+            echo 0;
+        } else {
+            echo 1;
+        }
+        break;
+    case 'find_coaches':
+        $coaches = SessionManager::get_coaches_by_keyword($_REQUEST['tag']);
+        $json_coaches = array();
+        if (!empty($coaches)) {
+            foreach ($coaches as $coach) {
+                $json_coaches[] = array('key' => $coach['user_id'], 'value' => api_get_person_name($coach['firstname'], $coach['lastname']));
+            }
+        }
+        echo json_encode($json_coaches);
+        break;
+	case 'update_changeable_setting':
+        $url_id = api_get_current_access_url_id();        
         if (api_is_global_platform_admin() && $url_id == 1) {            
             if (isset($_GET['id']) && !empty($_GET['id'])) {                
                 $params = array('variable = ? ' =>  array($_GET['id']));

+ 21 - 0
main/inc/ajax/extra_field.ajax.php

@@ -0,0 +1,21 @@
+<?php
+
+$language_file = array('admin', 'registration', 'userInfo');
+require_once '../global.inc.php';
+$action = $_GET['a'];
+
+switch ($action) {	
+    case 'get_second_select_options':
+        $type = isset($_REQUEST['type']) ? $_REQUEST['type'] : null;
+        $field_id = isset($_REQUEST['field_id']) ? $_REQUEST['field_id'] : null;
+        $option_value_id = isset($_REQUEST['option_value_id']) ? $_REQUEST['option_value_id'] : null;
+        
+        if (!empty($type) && !empty($field_id) && !empty($option_value_id)) {
+            $field_options = new ExtraFieldOption($type);
+            echo $field_options->get_second_select_field_options_by_field($field_id, $option_value_id, true);           
+        }
+        break;
+    default:
+        exit;
+        break;
+}

+ 128 - 29
main/inc/ajax/model.ajax.php

@@ -20,7 +20,6 @@ $sord   = $_REQUEST['sord'];         //asc or desc
 if (!in_array($sord, array('asc','desc'))) {
     $sord = 'desc'; 
 }
-	
 
 if (!in_array($action, array('get_exercise_results', 'get_hotpotatoes_exercise_results', 'get_work_user_list', 'get_timelines', 'get_user_skill_ranking'))) {
 	api_protect_admin_script(true);
@@ -66,30 +65,84 @@ $search_oper     = isset($_REQUEST['searchOper'])   ? $_REQUEST['searchOper']
 $search_string   = isset($_REQUEST['searchString']) ? $_REQUEST['searchString'] : false;
 
 if ($_REQUEST['_search'] == 'true') {
-    $where_condition = ' 1 = 1 ';
-    $where_condition_in_form = get_where_clause($search_field, $search_oper, $search_string);
+    $where_condition = ' 1 = 1 ';    
+    $where_condition_in_form = get_where_clause($search_field, $search_oper, $search_string);    
         
     if (!empty($where_condition_in_form)) {
         $where_condition .= ' AND '.$where_condition_in_form;
-    }
+    }    
+    $filters = isset($_REQUEST['filters']) ? json_decode($_REQUEST['filters']) : false;
+    //var_dump($filters);
     
-    $filters   = isset($_REQUEST['filters']) ? json_decode($_REQUEST['filters']) : false;
+    //for now
+    $extra_field = new ExtraField('session');
+    $extra_fields = array();
     if (!empty($filters)) {
-        $where_condition .= ' AND ( ';
-        $counter = 0;
-        foreach ($filters->rules as $key=>$rule) {
-            $where_condition .= get_where_clause($rule->field,$rule->op, $rule->data);
-            
-            if ($counter < count($filters->rules) -1) {     
-                $where_condition .= $filters->groupOp;
-            }
-            $counter++;
+        
+        //Getting double select if exists
+        $double_select = array();
+        foreach ($filters->rules as $rule) {
+            if (strpos($rule->field, '_second') === false) {
+                
+            } else {
+                $my_field = str_replace('_second', '', $rule->field);
+                $double_select[$my_field] = $rule->data;
+            }                
         }
-        $where_condition .= ' ) ';
-    }        
+        
+        $condition_array = array();
+                
+        foreach ($filters->rules as $rule) {
+            if (strpos($rule->field, 'extra_') === false) {
+                //normal fields
+                $field = $rule->field;
+                $condition_array[] = get_where_clause($field, $rule->op, $rule->data);                
+            } else {
+                //Extra fields
+                
+                //normal
+                if (strpos($rule->field, '_second') === false) {
+                    //No _second
+                    $original_field = str_replace('extra_', '', $rule->field);                    
+                    $field_option = $extra_field->get_handler_field_info_by_field_variable($original_field);
+                    
+                    if ($field_option['field_type'] == ExtraField::FIELD_TYPE_DOUBLE_SELECT) {                        
+                        
+                        if (isset($double_select[$rule->field])) {
+                            $data = explode('#', $rule->data);
+                            //var_dump($data);
+                            $rule->data = $data[1].'::'.$double_select[$rule->field];
+                        } else {
+                            // only was sent 1 select
+                            $data = explode('#', $rule->data);
+                            $rule->data = $data[1];                            
+                        }                        
+                        $condition_array[] = ' ('.get_where_clause($rule->field, $rule->op, $rule->data).') ';                        
+                        $extra_fields[] = array('field' => $rule->field, 'id' => $field_option['id']);
+                    } else {
+                        $condition_array[] = ' ('.get_where_clause($rule->field, $rule->op, $rule->data).') ';
+                        $extra_fields[] = array('field' => $rule->field, 'id' => $field_option['id']);
+                    }
+                } else {
+                    $my_field = str_replace('_second', '', $rule->field);
+                    $original_field = str_replace('extra_', '', $my_field);                    
+                    $field_option = $extra_field->get_handler_field_info_by_field_variable($original_field);                                       
+                    $extra_fields[] = array('field' => $rule->field, 'id' => $field_option['id']);
+                }
+            }            
+        }
+        
+        if (!empty($condition_array)) {
+            $where_condition .= ' AND ( ';    
+            //var_dump($condition_array);
+            $where_condition .= implode($filters->groupOp, $condition_array);
+            
+            $where_condition .= ' ) ';        
+        }        
+    }
 }
+//var_dump($extra_fields);
 //var_dump($where_condition);
-
 // get index row - i.e. user click to sort $sord = $_GET['sord']; 
 // get the direction 
 if (!$sidx) $sidx = 1;
@@ -109,8 +162,7 @@ switch ($action) {
         break;
 	case 'get_exercise_results':
 		require_once api_get_path(SYS_CODE_PATH).'exercice/exercise.lib.php';		
-        $exercise_id = $_REQUEST['exerciseId'];
-        
+        $exercise_id = $_REQUEST['exerciseId'];        
         if (isset($_GET['filter_by_user']) && !empty($_GET['filter_by_user'])) {            
             $filter_user = intval($_GET['filter_by_user']);
             if ($where_condition == "") {
@@ -129,6 +181,17 @@ switch ($action) {
     case 'get_sessions':           
         $count = SessionManager::get_count_admin();
         break;
+    case 'get_extra_fields':
+        $type = $_REQUEST['type'];
+        $obj = new ExtraField($type);
+        $count = $obj->get_count();
+        break;
+    case 'get_extra_field_options':
+        $type = $_REQUEST['type'];
+        $field_id = $_REQUEST['field_id'];
+        $obj = new ExtraFieldOption($type);
+        $count = $obj->get_count_by_field_id($field_id);        
+        break;    
     case 'get_timelines':
         require_once $libpath.'timeline.lib.php';
         $obj        = new Timeline();
@@ -241,9 +304,10 @@ switch ($action) {
 		$columns = array('firstname', 'lastname', 'username', 'group_name', 'exe_date',  'score', 'actions');
 		$result = get_exam_results_hotpotatoes_data($start, $limit, $sidx, $sord, $hotpot_path, $where_condition); //get_exam_results_data($start, $limit, $sidx, $sord, $exercise_id, $where_condition);        
 		break;
-    case 'get_sessions':
-        $columns = array('name', 'nbr_courses', 'nbr_users', 'category_name', 'date_start','date_end', 'coach_name', 'session_active', 'visibility');            
-        $result = SessionManager::get_sessions_admin(array('where'=> $where_condition, 'order'=>"$sidx $sord", 'limit'=> "$start , $limit"));        
+    case 'get_sessions':   
+        $session_columns = SessionManager::get_session_columns();
+        $columns = $session_columns['simple_column_name'];        
+        $result = SessionManager::get_sessions_admin(array('where'=> $where_condition, 'order'=>"$sidx $sord", 'extra' => $extra_fields, 'limit'=> "$start , $limit"));        
         break;    
      case 'get_timelines': 
         $columns = array('headline', 'actions');   
@@ -311,7 +375,7 @@ switch ($action) {
         if(!in_array($sidx, $columns)) {
         	$sidx = 'subject';
         }
-        $result     = Database::select('*', $obj->table, array('order'=>"$sidx $sord", 'LIMIT'=> "$start , $limit"));        
+        $result = Database::select('*', $obj->table, array('order'=>"$sidx $sord", 'LIMIT'=> "$start , $limit"));        
         $new_result = array();
         foreach ($result as $item) {
             $language_info = api_get_language_info($item['language_id']);
@@ -369,7 +433,7 @@ switch ($action) {
         $result = $new_result;
         break;
     case 'get_usergroups':
-        $columns = array('name', 'users', 'courses','sessions','actions');
+        $columns = array('name', 'users', 'courses', 'sessions', 'actions');
         $result     = Database::select('*', $obj->table, array('order'=>"name $sord", 'LIMIT'=> "$start , $limit"));
         $new_result = array();
         if (!empty($result)) {
@@ -387,7 +451,40 @@ switch ($action) {
         }
         //Multidimensional sort
         msort($result, $sidx);
-        break;      
+        break;
+    case 'get_extra_fields':         
+        $obj = new ExtraField($type);
+        $columns = array('field_display_text', 'field_variable', 'field_type', 'field_changeable', 'field_visible', 'field_filter', 'field_order');
+        $result  = Database::select('*', $obj->table, array('order'=>"$sidx $sord", 'LIMIT'=> "$start , $limit"));
+        $new_result = array();
+        if (!empty($result)) {
+            foreach ($result as $item) {            
+                $item['field_type']         = $obj->get_field_type_by_id($item['field_type']);
+                $item['field_changeable']   = $item['field_changeable'] ? Display::return_icon('right.gif') : Display::return_icon('wrong.gif');
+                $item['field_visible']      = $item['field_visible'] ? Display::return_icon('right.gif') : Display::return_icon('wrong.gif');
+                $item['field_filter']       = $item['field_filter'] ? Display::return_icon('right.gif') : Display::return_icon('wrong.gif');
+                $new_result[]        = $item;
+            }
+            $result = $new_result;
+        }        
+        break;
+    case 'get_extra_field_options':
+        $obj = new ExtraFieldOption($type);
+        $columns = array('option_display_text', 'option_value', 'option_order');
+        $result  = Database::select('*', $obj->table, array('where' => array("field_id = ? " => $field_id),'order'=>"$sidx $sord", 'LIMIT'=> "$start , $limit"));
+        /*$new_result = array();
+        if (!empty($result)) {
+            foreach ($result as $item) {            
+                $item['field_type']         = $obj->get_field_type_by_id($item['field_type']);
+                $item['field_changeable']   = $item['field_changeable'] ? Display::return_icon('right.gif') : Display::return_icon('wrong.gif');
+                $item['field_visible']      = $item['field_visible'] ? Display::return_icon('right.gif') : Display::return_icon('wrong.gif');
+                $item['field_filter']       = $item['field_filter'] ? Display::return_icon('right.gif') : Display::return_icon('wrong.gif');
+                $new_result[]        = $item;
+            }
+            $result = $new_result;
+        }*/  
+
+        break;
     default:    
         exit;            
 }
@@ -404,7 +501,10 @@ $allowed_actions = array('get_careers',
                          'get_timelines', 
                          'get_grade_models', 
                          'get_event_email_template',
-                         'get_user_skill_ranking');
+                         'get_user_skill_ranking',
+                         'get_extra_fields',
+                         'get_extra_field_options'
+);
                          	
 //5. Creating an obj to return a json
 if (in_array($action, $allowed_actions)) {
@@ -429,8 +529,7 @@ if (in_array($action, $allowed_actions)) {
             $response->rows[$i]['cell']=$array;
             $i++; 
         }
-    }    
-
+    }
     echo json_encode($response);
 }
-exit;
+exit;

+ 5 - 26
main/inc/ajax/user_manager.ajax.php

@@ -71,34 +71,13 @@ switch ($action) {
 		}
         break;
 	case 'active_user':
-		if (api_is_platform_admin() && api_global_admin_can_edit_admin($_GET['user_id'])) {
-            
+		if (api_is_platform_admin() && api_global_admin_can_edit_admin($_GET['user_id'])) {            
 			$user_id = intval($_GET['user_id']);
-			$status  = intval($_GET['status']);
-            
-			if (!empty($user_id)) {
-				$user_table = Database :: get_main_table(TABLE_MAIN_USER);
-				$sql="UPDATE $user_table SET active='".$status."' WHERE user_id='".$user_id."'";
-				$result = Database::query($sql);
-                
-				//Send and email if account is active
-				if ($status == 1) {
-					$user_info = api_get_user_info($user_id);					
-					$recipient_name = api_get_person_name($user_info['firstname'], $user_info['lastname'], null, PERSON_NAME_EMAIL_ADDRESS);
-					$emailsubject = '['.api_get_setting('siteName').'] '.get_lang('YourReg').' '.api_get_setting('siteName');
-					$email_admin = api_get_setting('emailAdministrator');
-					$sender_name = api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'), null, PERSON_NAME_EMAIL_ADDRESS);
-					$emailbody=get_lang('Dear')." ".stripslashes($recipient_name).",\n\n";					
-					
-					$emailbody.=sprintf(get_lang('YourAccountOnXHasJustBeenApprovedByOneOfOurAdministrators'), api_get_setting('siteName'))."\n";
-					$emailbody.=sprintf(get_lang('YouCanNowLoginAtXUsingTheLoginAndThePasswordYouHaveProvided'), api_get_path(WEB_PATH)).",\n\n";
-					$emailbody.=get_lang('HaveFun')."\n\n";
-					//$emailbody.=get_lang('Problem'). "\n\n". get_lang('Formula');
-					$emailbody.=api_get_person_name(api_get_setting('administratorName'), api_get_setting('administratorSurname'))."\n". get_lang('Manager'). " ".api_get_setting('siteName')."\nT. ".api_get_setting('administratorTelephone')."\n" .get_lang('Email') ." : ".api_get_setting('emailAdministrator');
-					$result = api_mail($recipient_name, $user_info['mail'], $emailsubject, $emailbody, $sender_name, $email_admin);					
-				}
+			$status  = intval($_GET['status']);            
+			if (!empty($user_id)) {                
+                UserManager::change_active_state($user_id, $status, true);
                 echo $status;
-            }				
+            }
 		} else {
 			echo '-1';
 		}

+ 0 - 18
main/inc/global.inc.php

@@ -99,27 +99,11 @@ ini_set('auto_detect_line_endings', '1');
 require_once dirname(__FILE__).'/autoload.inc.php';
 
 require_once $lib_path.'database.lib.php';
-//require_once $lib_path.'template.lib.php'; moved to autoload
-//require_once $lib_path.'display.lib.php';
 require_once $lib_path.'text.lib.php';
-//require_once $lib_path.'image.lib.php';   moved to autoload
 require_once $lib_path.'array.lib.php';
-//require_once $lib_path.'security.lib.php';  moved to autoload
 require_once $lib_path.'events.lib.inc.php';
-//require_once $lib_path.'debug.lib.php';  moved to autoload
-//require_once $lib_path.'rights.lib.php';  moved to autoload
-
 require_once $lib_path.'model.lib.php';
-//require_once $lib_path.'sortable_table.class.php';  moved to autoload
-//require_once $lib_path.'usermanager.lib.php'; moved to autoload
-//require_once $lib_path.'message.lib.php'; moved to autoload
-//require_once $lib_path.'social.lib.php'; moved to autoload
-//require_once $lib_path.'notification.lib.php'; moved to autoload
 require_once $lib_path.'course.lib.php';
-//require_once $lib_path.'sessionmanager.lib.php'; moved to autoload
-//require_once $lib_path.'tracking.lib.php'; moved to autoload
-
-//require_once $lib_path.'formvalidator/FormValidator.class.php'; moved to autoload
 require_once $lib_path.'online.inc.php';
 
 //Here we load the new Doctrine class (just for tests)
@@ -199,8 +183,6 @@ api_initialize_internationalization();
 // Initialization of the default encoding that will be used by the multibyte string routines in the internationalization library.
 api_set_internationalization_default_encoding($charset);
 
-//setting_gettext();
-
 // Initialization of the database encoding to be used.
 Database::query("SET SESSION character_set_server='utf8';");
 Database::query("SET SESSION collation_server='utf8_general_ci';");

+ 11 - 1
main/inc/lib/autoload.class.php

@@ -492,7 +492,7 @@ class Autoload
         $result['Entity\SearchEngineRef'] = '/main/inc/entity/search_engine_ref.class.php';
         $result['Entity\Session'] = '/main/inc/entity/session.class.php';
         $result['Entity\SessionCategory'] = '/main/inc/entity/session_category.class.php';
-        $result['Entity\SessionField'] = '/main/inc/entity/session_field.class.php';
+        $result['Entity\SessionField'] = '/main/inc/entity/session_field.class.php';        
         $result['Entity\SessionFieldValues'] = '/main/inc/entity/session_field_values.class.php';
         $result['Entity\SessionRelCourse'] = '/main/inc/entity/session_rel_course.class.php';
         $result['Entity\SessionRelCourseRelUser'] = '/main/inc/entity/session_rel_course_rel_user.class.php';
@@ -584,6 +584,11 @@ class Autoload
         $result['EventsMail'] = '/main/inc/lib/events_email.class.php';
         $result['Exercise'] = '/main/exercice/exercise.class.php';
         $result['ExerciseLink'] = '/main/gradebook/lib/be/exerciselink.class.php';
+        
+        $result['ExtraField'] = '/main/inc/lib/extra_field.lib.php';
+        $result['ExtraFieldOption'] = '/main/inc/lib/extra_field_option.lib.php';
+        $result['ExtraFieldValue'] = '/main/inc/lib/extra_field_value.lib.php';
+        
         $result['Testcategory'] = '/main/exercice/testcategory.class.php';        
         $result['ExerciseResult'] = '/main/exercice/exercise_result.class.php';
         $result['ExerciseShowFunctions'] = '/main/inc/lib/exercise_show_functions.lib.php';
@@ -804,6 +809,11 @@ class Autoload
         $result['Security'] = '/main/inc/lib/security.lib.php';
         $result['SessionHandler'] = '/main/inc/lib/session_handler.class.php';
         $result['SessionManager'] = '/main/inc/lib/sessionmanager.lib.php';
+        $result['SessionModel'] = '/main/inc/lib/session_model.lib.php';
+        
+        $result['SessionField'] = '/main/inc/lib/session_field.lib.php';
+        $result['SessionFieldValue'] = '/main/inc/lib/session_field_value.lib.php';
+        $result['SessionFieldOption'] = '/main/inc/lib/session_field_option.lib.php';        
         $result['Shibboleth\Admin'] = '/main/auth/shibboleth/app/model/admin.class.php';
         $result['Shibboleth\AdminStore'] = '/main/auth/shibboleth/app/model/admin.class.php';
         $result['Shibboleth\Model'] = '/main/auth/shibboleth/lib/model.class.php';

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

@@ -194,8 +194,10 @@ function return_notification_menu() {
 
         // Display the who's online for the session
         if (isset($user_id) && api_get_session_id() != 0) {
-            $html .= '<li><a href="'.api_get_path(WEB_PATH).'whoisonlinesession.php?id_coach='.$user_id.'&amp;referer='.urlencode($_SERVER['REQUEST_URI']).'" target="_top">'.
+            if (api_is_allowed_to_edit()) {
+                $html .= '<li><a href="'.api_get_path(WEB_PATH).'whoisonlinesession.php?session_id='.api_get_session_id().'&id_coach='.$user_id.'" >'.
                     Display::return_icon('session.png', get_lang('UsersConnectedToMySessions'), array(), ICON_SIZE_TINY).' </a></li>';
+            }
         }
     }
 

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

@@ -171,8 +171,8 @@ class Career extends Model {
         return $cid;
     }    
     
-    public function save($params) {
-	    $id = parent::save($params);
+    public function save($params, $show_query = false) {
+	    $id = parent::save($params, $show_query);
 	    if (!empty($id)) {
 	    	event_system(LOG_CAREER_CREATE, LOG_CAREER_ID, $id, api_get_utc_datetime(), api_get_user_id());
    		}

+ 86 - 141
main/inc/lib/course.lib.php

@@ -674,7 +674,7 @@ class CourseManager {
 
         //2. Include courses in sessions
         if ($include_courses_in_sessions) {
-            $sessions      = Tracking::get_sessions_coached_by_user($user_id);
+            $sessions      = SessionManager::get_sessions_coached_by_user($user_id);
 
             if (!empty($sessions)) {
                 foreach($sessions as $session_item) {
@@ -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,30 +1141,35 @@ 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.'"';
-            $where[] = ' course_rel_user.course_code IS NOT NULL ';
+            $where[] = ' AND course_rel_user.course_code IS NOT NULL ';
             
             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 {
@@ -1344,7 +1373,7 @@ class CourseManager {
     public static function get_teacher_list_from_course_code($course_code) {
         $course_code = Database::escape_string($course_code);
         $teachers = array();        
-        $sql = "SELECT u.user_id, u.lastname, u.firstname, u.email, u.username, u.status 
+        $sql = "SELECT DISTINCT u.user_id, u.lastname, u.firstname, u.email, u.username, u.status 
                 FROM ".Database::get_main_table(TABLE_MAIN_COURSE_USER)." cu INNER JOIN ".Database::get_main_table(TABLE_MAIN_USER)." u 
                 ON (cu.user_id = u.user_id)
                 WHERE   cu.course_code = '$course_code' AND 
@@ -1401,7 +1430,8 @@ class CourseManager {
         $tbl_session_course_user    = Database :: get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
         $coaches = array();
 
-        $sql = "SELECT u.user_id,u.lastname,u.firstname,u.username FROM $tbl_user u,$tbl_session_course_user scu
+        $sql = "SELECT DISTINCT u.user_id, u.lastname, u.firstname, u.username 
+                FROM $tbl_user u, $tbl_session_course_user scu
                 WHERE u.user_id = scu.id_user AND scu.id_session = '$session_id' AND scu.course_code = '$course_code' AND scu.status = 2";
         $rs = Database::query($sql);
 
@@ -2787,7 +2817,6 @@ class CourseManager {
                         $html .= $params['icon'];
                         $html .= '</div>';
                     }
-
                     $html .= '</div>';
 
                     $html .= '<div class="span6">';
@@ -2796,13 +2825,18 @@ class CourseManager {
                         if (!empty($params['subtitle'])) {
                             $html .= '<small>'.$params['subtitle'].'</small>';
                         }
+                        if (!empty($params['dates'])) {
+                            if (!empty($params['subtitle'])) {
+                                $html .= " | ";
+                            }
+                            $html .= '<small>'.$params['dates'].'</small>';
+                        }
                         if (!empty($params['teachers'])) {
                             $html .= '<h5>'.Display::return_icon('teacher.png', get_lang('Teacher'), array(), ICON_SIZE_TINY).$params['teachers'].'</h5>';
                         }
                         if (!empty($params['coaches'])) {
                             $html .= '<h5>'.Display::return_icon('teacher.png', get_lang('Coach'), array(), ICON_SIZE_TINY).$params['coaches'].'</h5>';
-                        }
-                        
+                        }                        
                         
                     $html .= '</div>';
                 $html .= '</div>';
@@ -3143,68 +3177,37 @@ class CourseManager {
      * @todo move code for what's new icons to a separate function to clear things up
      * @todo add a parameter user_id so that it is possible to show the courselist of other users (=generalisation). This will prevent having to write a new function for this.
      */
-    public static function get_logged_user_course_html($course, $session_id = 0, $class = 'courses', $session_accessible = true, $load_dirs = false) {
-        global $nosession, $nbDigestEntries, $digest, $thisCourseSysCode, $orderKey;
-        $user_id  = api_get_user_id();
-        $course_info = api_get_course_info($course['code']);
-        $status_course = CourseManager::get_user_in_course_status($user_id, $course_info['code']);
-
-        $course_info['status'] = empty($session_id) ? $status_course : STUDENT;
-
+    public static function get_logged_user_course_html($course, $session_id = 0, $load_dirs = false) {        
+        $course_info = api_get_course_info($course['code']);                
         $course_info['id_session'] = $session_id;
 
-        if (!$nosession) {
-            global $now, $date_start, $date_end;
-        }
-
-        // Table definitions
-        $main_user_table            = Database :: get_main_table(TABLE_MAIN_USER);
-        $tbl_session                = Database :: get_main_table(TABLE_MAIN_SESSION);
-        $tbl_session_category       = Database :: get_main_table(TABLE_MAIN_SESSION_CATEGORY);
-
-        $course_access_settings     = CourseManager :: get_access_settings($course_info['code']);
-        $course_visibility          = $course_access_settings['visibility'];
-
-        $user_in_course_status      = CourseManager :: get_user_in_course_status(api_get_user_id(), $course_info['code']);
-
-        $is_coach = api_is_coach($course_info['id_session'], $course['code']);
-
         // Display course entry.
-        // Show a hyperlink to the course, unless the course is closed and user is not course admin.
+        // Show a link to the course, unless the course is closed and user is not course admin.
         $session_url = '';
-        $session_title = '';
-
-        if ($session_accessible) {
-            if ($course_visibility != COURSE_VISIBILITY_CLOSED || $user_in_course_status == COURSEMANAGER) {
-                if (!$nosession) {
-                    if (empty($course_info['id_session'])) {
-                        $course_info['id_session'] = 0;
-                    }
-                    if ($user_in_course_status == COURSEMANAGER || ($date_start <= $now && $date_end >= $now) || $date_start == '0000-00-00') {
-                        $session_url = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/?id_session='.$course_info['id_session'];
-                        $session_title = '<a href="'.api_get_path(WEB_COURSE_PATH).$course_info['path'].'/?id_session='.$course_info['id_session'].'">'.$course_info['name'].'</a>';
-                    }
-                } else {
-                    $session_url   = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/';
-                    $session_title = '<a href="'.api_get_path(WEB_COURSE_PATH).$course_info['path'].'/">'.$course_info['name'].'</a>';
-                }
-            } else {
-                $session_title = $course_info['name'].' '.Display::tag('span',get_lang('CourseClosed'), array('class'=>'item_closed'));
-            }
+        $session_title = $course_info['name'];        
+                 
+        if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED || $course_info['user_status_in_course'] == COURSEMANAGER) {                       
+            //if ($course_info['user_status_in_course'] == COURSEMANAGER) {
+                $session_url = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/?id_session='.$course_info['id_session'];
+                $session_title = '<a href="'.api_get_path(WEB_COURSE_PATH).$course_info['path'].'/?id_session='.$course_info['id_session'].'">'.$course_info['name'].'</a>';
+            //}            
         } else {
-            $session_title = $course_info['name'];
+            $session_title = $course_info['name'].' '.Display::tag('span',get_lang('CourseClosed'), array('class'=>'item_closed'));
         }
 
+
         $params = array();
         $params['icon'] = Display::return_icon('blackboard_blue.png', $course_info['name'], array(), ICON_SIZE_LARGE);
         $params['link'] = $session_url;
         $params['title'] = $session_title;
+        
 
         $params['right_actions'] = '';
         
-        if ($course_visibility != COURSE_VISIBILITY_CLOSED) {
+        if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
             if ($load_dirs) {
-                $params['right_actions'] .= '<a id="document_preview_'.$course_info['real_id'].'_'.$course_info['id_session'].'" class="document_preview" href="javascript:void(0);">'.Display::return_icon('folder.png', get_lang('Documents'), array('align' => 'absmiddle'),ICON_SIZE_SMALL).'</a>';
+                $params['right_actions'] .= '<a id="document_preview_'.$course_info['real_id'].'_'.$course_info['id_session'].'" class="document_preview" href="javascript:void(0);">'.
+                                            Display::return_icon('folder.png', get_lang('Documents'), array('align' => 'absmiddle'),ICON_SIZE_SMALL).'</a>';
                 $params['right_actions'] .= Display::div('', array('id' => 'document_result_'.$course_info['real_id'].'_'.$course_info['id_session'], 'class'=>'document_preview_container'));
             }
         }
@@ -3213,80 +3216,22 @@ class CourseManager {
             $session_title .= ' ('.$course_info['visual_code'].') ';
         }
 
-        if (api_get_setting('display_teacher_in_courselist') == 'true') {
-            if (!$nosession) {
-                $teacher_list = CourseManager::get_teacher_list_from_course_code_to_string($course_info['code'], self::USER_SEPARATOR, true);
-                $course_coachs = CourseManager::get_coachs_from_course_to_string($course_info['id_session'], $course['code'], self::USER_SEPARATOR, true);
-
-                if ($course_info['status'] == COURSEMANAGER || ($course_info['status'] == STUDENT && empty($course_info['id_session'])) || empty($course_info['status'])) {
-                    $params['teachers'] = $teacher_list;
-                }
-                if (($course_info['status'] == STUDENT && !empty($course_info['id_session'])) || ($is_coach && $course_info['status'] != COURSEMANAGER)) {
-                    $params['coaches'] = $course_coachs;
-                }
-            } else {
-                $params['teachers'] = $teacher_list;
-            }
+        if (api_get_setting('display_teacher_in_courselist') == 'true') {            
+            $teacher_list = CourseManager::get_teacher_list_from_course_code_to_string($course_info['code'], self::USER_SEPARATOR, true);
+            $course_coachs = CourseManager::get_coachs_from_course_to_string($course_info['id_session'], $course['code'], self::USER_SEPARATOR, true);            
+            $params['teachers'] = $teacher_list;
+            $params['coaches'] = $course_coachs;            
         }
-
         $session_title .= isset($course['special_course']) ? ' '.Display::return_icon('klipper.png', get_lang('CourseAutoRegister')) : '';
 
         // Display the "what's new" icons
-        if ($course_visibility != COURSE_VISIBILITY_CLOSED) {
+        if ($course_info['visibility'] != COURSE_VISIBILITY_CLOSED) {
             $session_title .= Display :: show_notification($course_info);
         }
-
         $params['title'] = $session_title;
         $params['extra'] = '';
-
         $html = self::course_item_html($params, true);
-
-        $session_category_id = null;
-        if (!$nosession) {
-            $session = '';
-            $active = false;
-            if (!empty($course_info['session_name'])) {
-
-                // Request for the name of the general coach
-                $sql = 'SELECT lastname, firstname,sc.name
-                FROM '.$tbl_session.' ts
-                LEFT JOIN '.$main_user_table .' tu
-                ON ts.id_coach = tu.user_id
-                INNER JOIN '.$tbl_session_category.' sc ON ts.session_category_id = sc.id
-                WHERE ts.id='.(int) $course_info['id_session']. ' LIMIT 1';
-
-                $rs = Database::query($sql);
-                $sessioncoach = Database::store_result($rs);
-                $sessioncoach = $sessioncoach[0];
-
-                $session = array();
-                $session['title'] = $course_info['session_name'];
-                $session_category_id = CourseManager::get_session_category_id_by_session_id($course_info['id_session']);
-                $session['category'] = $sessioncoach['name'];
-                if ($course_info['date_start'] == '0000-00-00') {
-                    //$session['dates'] = get_lang('WithoutTimeLimits');
-                    $session['dates'] = '';
-                    if (api_get_setting('show_session_coach') === 'true') {
-                        $session['coach'] = get_lang('GeneralCoach').': '.api_get_person_name($sessioncoach['firstname'], $sessioncoach['lastname']);
-                    }
-                    $active = true;
-                } else {
-                    $session ['dates'] = ' - '.get_lang('From').' '.$course_info['date_start'].' '.get_lang('To').' '.$course_info['date_end'];
-                    if (api_get_setting('show_session_coach') === 'true') {
-                        $session['coach'] = get_lang('GeneralCoach').': '.api_get_person_name($sessioncoach['firstname'], $sessioncoach['lastname']);
-                    }
-                    $active = ($date_start <= $now && $date_end >= $now);
-                }
-            }
-            $user_course_category = '';
-            if (isset($course_info['user_course_cat'])) {
-                 $user_course_category = $course_info['user_course_cat'];
-            }
-            $output = array ($user_course_category, $html, $course_info['id_session'], $session, 'active' => $active, 'session_category_id' => $session_category_id);
-        } else {
-            $output = array ($course_info['user_course_cat'], $html);
-        }
-        return $output;
+        return $html;
     }
 
     /**

+ 20 - 31
main/inc/lib/course_home.lib.php

@@ -819,47 +819,36 @@ class CourseHome {
      * @return string	session data
      */
     public static function show_session_data($id_session) {
-        $session_table 			= Database::get_main_table(TABLE_MAIN_SESSION);
-        $user_table 			= Database::get_main_table(TABLE_MAIN_USER);
-        $session_category_table = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
 
         if ($id_session != strval(intval($id_session))) {
             return '';
         } else {
             $id_session = intval($id_session);
         }
-
-        $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 '.$session_table.'
-                LEFT JOIN '.$user_table.'
-                    ON id_coach = user_id
-                WHERE '.$session_table.'.id='.$id_session;
-
-        $rs = Database::query($sql);
-        $session = Database::store_result($rs);
-        $session = $session[0];
-
-        $sql_category = 'SELECT name FROM '.$session_category_table.' WHERE id = "'.intval($session['session_category_id']).'"';
-        $rs_category = Database::query($sql_category);
-        $session_category = '';
-        if (Database::num_rows($rs_category) > 0) {
-            $rows_session_category = Database::store_result($rs_category);
-            $rows_session_category = $rows_session_category[0];
-            $session_category = $rows_session_category['name'];
-        }
-
-        if ($session['date_start'] == '00-00-0000') {
-            $msg_date = get_lang('NoTimeLimits');
-        } else {
-            $msg_date = get_lang('From').' '.$session['date_start'].' '.get_lang('To').' '.$session['date_end'];
+        
+        $session_info = api_get_session_info($id_session);
+        $session_category = SessionManager::get_session_category($session_info['session_category_id']);
+        
+        $session_category_name = null;
+        if (!empty($session_category)) {
+            $session_category_name = $session_category['name'];
         }
-
+        $user_info = api_get_user_info($session_info['id_coach']);
+        $general_coach = null;
+        if (!empty($user_info)) {
+            $general_coach = $user_info['complete_name'].' ('.$user_info['username'].')';
+        }        
+        $msg_date = SessionManager::parse_session_dates($session_info);
+        
         $output  = '';
         if (!empty($session_category)) {
-            $output .= '<tr><td>'. get_lang('SessionCategory') . ': ' . '<b>' . $session_category .'</b></td></tr>';
+            $output .= '<tr><td>'. get_lang('SessionCategory') . ': ' . '<b>' . $session_category_name .'</b></td></tr>';
         }
-        $output .= '<tr><td style="width:50%">'. get_lang('SessionName') . ': ' . '<b>' . $session['name'] .'</b></td><td>'. get_lang('GeneralCoach') . ': ' . '<b>' . $session['lastname'].' '.$session['firstname'].' ('.$session['username'].')' .'</b></td></tr>';
-        $output .= '<tr><td>'. get_lang('SessionIdentifier') . ': '. Display::return_icon('star.png', ' ', array('align' => 'absmiddle')) .'</td><td>'. get_lang('Date') . ': ' . '<b>' . $msg_date .'</b></td></tr>';
+        $output .= '<tr>
+                        <td style="width:50%">'. get_lang('SessionName') . ': ' . '<b>' . $session_info['name'] .'</b></td>
+                        <td>'. get_lang('GeneralCoach') . ': ' . '<b>' .$general_coach.'</b></td></tr>';
+        $output .= '<tr><td>'. get_lang('SessionIdentifier') . ': '. Display::return_icon('star.png', ' ', array('align' => 'absmiddle')) .'</td>
+                        <td>'. get_lang('Date') . ': ' . '<b>' . $msg_date .'</b></td></tr>';
 
         return $output;
     }

+ 1 - 0
main/inc/lib/database.constants.inc.php

@@ -102,6 +102,7 @@ define('TABLE_MAIN_USER_API_KEY',           'user_api_key');
 define('TABLE_MAIN_COURSE_FIELD',           'course_field');
 define('TABLE_MAIN_COURSE_FIELD_VALUES',    'course_field_values');
 define('TABLE_MAIN_SESSION_FIELD',          'session_field');
+define('TABLE_MAIN_SESSION_FIELD_OPTIONS',  'session_field_options');
 define('TABLE_MAIN_SESSION_FIELD_VALUES',   'session_field_values');
 
 // Message

+ 4 - 7
main/inc/lib/database.lib.php

@@ -1160,7 +1160,7 @@ class Database {
         $params = array_keys($filtred_attributes); //@todo check if the field exists in the table we should use a describe of that table
         $values = array_values($filtred_attributes);
         if (!empty($params) && !empty($values)) {
-            $sql    = 'INSERT INTO '.$table_name.' ('.implode(',',$params).') VALUES ('.implode(',',$values).')';
+            $sql    = 'INSERT INTO '.$table_name.' ('.implode(', ',$params).') VALUES ('.implode(', ',$values).')';
             $result = self::query($sql);
             if ($show_query) {
             	var_dump($sql);
@@ -1178,9 +1178,8 @@ class Database {
      * @example array('where'=> array('type = ? AND category = ?' => array('setting', 'Plugins'))
      * @example array('where'=> array('name = "Julio" AND lastname = "montoya"))
     */
-
-    public static function select($columns, $table_name, $conditions = array(), $type_result = 'all', $option = 'ASSOC') {
-        $conditions = self::parse_conditions($conditions);
+    public static function select($columns, $table_name, $conditions = array(), $type_result = 'all', $option = 'ASSOC') {        
+        $conditions = self::parse_conditions($conditions);        
         
         //@todo we could do a describe here to check the columns ...
         $clean_columns = '';
@@ -1193,7 +1192,6 @@ class Database {
                 $clean_columns = (string)$columns;
             }
         }
-
         $sql    = "SELECT $clean_columns FROM $table_name $conditions";
         //var_dump($sql);
         $result = self::query($sql);
@@ -1230,8 +1228,7 @@ class Database {
             }
             $type_condition = strtolower($type_condition);
             switch ($type_condition) {
-                case 'where':            
-                    
+                case 'where':                    
                     foreach ($condition_data as $condition => $value_array) {                       
                         if (is_array($value_array)) {
                             $clean_values = array();                       

+ 25 - 76
main/inc/lib/display.lib.php

@@ -645,7 +645,7 @@ class Display {
             }
         }
         //some tags don't have this </XXX>
-        if (in_array($tag, array('img','input','br'))) {
+        if (in_array($tag, array('img', 'input', 'br'))) {
             $return_value = '<'.$tag.' '.$attribute_list.' />';
         } else {
             $return_value = '<'.$tag.' '.$attribute_list.' > '.$content.'</'.$tag.'>';
@@ -859,11 +859,11 @@ class Display {
         $obj = new stdClass();
 
         if (!empty($url))
-            $obj->url       = $url;
+            $obj->url  = $url;
 
-        $obj->colNames      = $column_names;
-        $obj->colModel      = $column_model;
-        $obj->pager         = '#'.$div_id.'_pager';
+        $obj->colNames = $column_names;
+        $obj->colModel = $column_model;
+        $obj->pager    = '#'.$div_id.'_pager';
 
         $obj->datatype  = 'json';
         
@@ -895,8 +895,6 @@ class Display {
             $obj->rowNum     = $extra_params['rowNum'];
         }
 
-        //height: 'auto',
-
         $obj->viewrecords = 'true';
 
         if (!empty($extra_params['viewrecords']))
@@ -925,6 +923,26 @@ class Display {
             //Converts the "data":"js_variable" to "data":js_variable othersiwe it will not work
             $json_encode = str_replace('"data":"'.$data_var.'"','"data":'.$data_var.'',$json_encode);
         }
+        
+        //Fixes datainit datepick
+        $json_encode = str_replace('"dataInit"','dataInit', $json_encode);
+        
+        /*$json_encode = str_replace('"dataEvents"','dataEvents', $json_encode);
+        $json_encode = str_replace('"type"','type', $json_encode);
+        $json_encode = str_replace('"fn"','fn', $json_encode);
+        $json_encode = str_replace('"data"','data', $json_encode);
+        $json_encode = str_replace('"attr"','attr', $json_encode);
+        $json_encode = str_replace('"rel"','rel', $json_encode);
+        $json_encode = str_replace('"title"','title', $json_encode);
+        */
+        $json_encode = str_replace('"register_second_select"','register_second_select', $json_encode);
+        
+        $json_encode = str_replace('"fill_second_select"','fill_second_select', $json_encode);
+        
+        $json_encode = str_replace('"date_pick"','date_pick', $json_encode);
+        $json_encode = str_replace('"date_pick_today"','date_pick_today', $json_encode);
+        $json_encode = str_replace('"date_pick_one_month"','date_pick_one_month', $json_encode);
+        
 
         //Fixing true/false js values that doesn't need the ""
         $json_encode = str_replace(':"true"',':true',$json_encode);
@@ -1220,75 +1238,6 @@ class Display {
         }
     } // End function display_digest
 
-    /**
-     * Get the session box details as an array
-     * @param int       Session ID
-     * @return array    Empty array or session array ['title'=>'...','category'=>'','dates'=>'...','coach'=>'...','active'=>true/false,'session_category_id'=>int]
-     */
-    public static function get_session_title_box($session_id) {
-        global $nosession;
-
-        if (!$nosession) {
-            global $now, $date_start, $date_end;
-        }
-
-        $output = array();
-        if (!$nosession) {
-            $main_user_table        = Database :: get_main_table(TABLE_MAIN_USER);
-            $tbl_session            = Database :: get_main_table(TABLE_MAIN_SESSION);            
-            $active = false;
-            // Request for the name of the general coach
-            $sql ='SELECT tu.lastname, tu.firstname, ts.name, ts.date_start, ts.date_end, ts.session_category_id
-                    FROM '.$tbl_session.' ts  LEFT JOIN '.$main_user_table .' tu ON ts.id_coach = tu.user_id
-                    WHERE ts.id='.intval($session_id);
-            $rs = Database::query($sql);
-            $session_info = Database::store_result($rs);
-            $session_info = $session_info[0];
-            $session = array();
-            $session['title'] = $session_info[2];
-            $session['coach'] = '';
-            $session['dates'] =  '';
-            
-            if ($session_info['date_end'] == '0000-00-00' && $session_info['date_start'] == '0000-00-00') {
-                if (api_get_setting('show_session_coach') === 'true') {
-                    $session['coach'] = get_lang('GeneralCoach').': '.api_get_person_name($session_info[1], $session_info[0]);
-                }
-                $active = true;
-            } else {
-                $start = $stop = false;
-                $start_buffer = $stop_buffer = '';
-                if ($session_info['date_start'] == '0000-00-00') {
-                    $session_info['date_start'] = '';
-                } else {
-                    $start = true;
-                    $start_buffer = $session_info['date_start'];
-                    $session_info['date_start'] = get_lang('From').' '.$session_info['date_start'];
-                }
-                if ($session_info['date_end'] == '0000-00-00') {
-                    $session_info['date_end'] = '';
-                } else {
-                    $stop = true;
-                    $stop_buffer = $session_info['date_end'];
-                    $session_info['date_end'] = get_lang('Until').' '.$session_info['date_end'];
-                }
-                if ($start && $stop) {
-                    $session['dates'] = Display::tag('i', sprintf(get_lang('FromDateXToDateY'), $start_buffer, $stop_buffer));
-                } else {
-                    $session['dates'] = Display::tag('i', $session_info['date_start'].' '.$session_info['date_end']);
-                }
-
-                if ( api_get_setting('show_session_coach') === 'true' ) {
-                    $session['coach'] = get_lang('GeneralCoach').': '.api_get_person_name($session_info[1], $session_info[0]);
-                }
-                $active = ($date_start <= $now && $date_end >= $now);
-            }
-            $session['active'] = $active;
-            $session['session_category_id'] = $session_info[5];
-            $output = $session;
-        }
-        return $output;
-    }
-
     /**
      * Return the five star HTML
      * 

+ 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);
         }
@@ -1181,7 +1181,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()));
         }
 
@@ -1343,7 +1343,7 @@ class DocumentManager {
         if ($num == 0) {
             return null;
         }
-        $row = Database::fetch_array($rs);
+        $row    = Database::fetch_array($rs);
         return $row['document_id'];
     }
 
@@ -1352,7 +1352,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);
@@ -1365,7 +1365,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);
@@ -1421,9 +1421,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,
@@ -1440,7 +1438,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))',
@@ -1463,7 +1460,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;
@@ -1513,7 +1509,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());
             }
         }
@@ -1524,7 +1520,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' ";

+ 33 - 3
main/inc/lib/events.lib.inc.php

@@ -566,16 +566,19 @@ function event_system($event_type, $event_value_type, $event_value, $datetime =
     if ($event_value_type == LOG_USER_OBJECT) {
         if (is_array($event_value)) {
             unset($event_value['complete_name']);
+            unset($event_value['complete_name_with_username']);
             unset($event_value['firstName']);
             unset($event_value['lastName']);
             unset($event_value['avatar_small']);
+            unset($event_value['avatar_sys_path']);
             unset($event_value['avatar']);
+            unset($event_value['mail']);
             unset($event_value['password']);
-            unset($event_value['lastLogin']);
+            unset($event_value['lastLogin']);            
             unset($event_value['picture_uri']);
             $event_value = serialize($event_value);
         }
-    }
+    } 
 
     $event_value        = Database::escape_string($event_value);
     $course_info        = api_get_course_info($course_code);
@@ -677,10 +680,33 @@ function get_event_users($event_name) {
     //For tests
     //$sql = 'SELECT user.user_id,  user.firstname, user.lastname FROM '.Database::get_main_table(TABLE_MAIN_USER);
         
-    $user_list = Database::store_result(Database::query($sql), 'ASSOC');    
+    $user_list = Database::store_result(Database::query($sql), 'ASSOC');
     return json_encode($user_list);	
 }
 
+function get_events_by_user_and_type($user_id, $event_type) {
+    global $TABLETRACK_DEFAULT;
+    $user_id = intval($user_id);
+    $event_type = Database::escape_string($event_type);
+    
+    $sql = "SELECT * FROM $TABLETRACK_DEFAULT 
+            WHERE default_value_type = 'user_id' AND 
+                  default_value = $user_id AND
+                  default_event_type = '$event_type'
+            ORDER BY default_date ";
+    $result = Database::query($sql);
+    if ($result) {
+        return Database::store_result($result, 'ASSOC');
+    }
+    return false;
+}
+function get_latest_event_by_user_and_type($user_id, $event_type) {
+    $result = get_events_by_user_and_type($user_id, $event_type);
+    if ($result && !empty($result)) {
+        return $result[0];
+    }
+}
+
 /**
  * Save the new message for one event and for one language
  *
@@ -1412,6 +1438,8 @@ function event_send_mail($event_name, $params) {
     EventsMail::send_mail($event_name, $params);
 }
 
+
+
 /**
  * Internal function checking if the mail was already sent from that user to that user
  * @param string $event_name
@@ -1466,6 +1494,8 @@ function portal_homepage_edited_event_send_mail_filter_func(&$values) {
     return $res;
 }
 
+
+
 /**
  * 
  */

+ 551 - 0
main/inc/lib/extra_field.lib.php

@@ -0,0 +1,551 @@
+<?php
+
+class ExtraField extends model {
+    public $columns = array('id', 'field_type', 'field_variable', 'field_display_text', 'field_default_value', 'field_order', 'field_visible', 'field_changeable', 'field_filter', 'tms');   
+    
+    CONST FIELD_TYPE_TEXT =                    1;
+    CONST FIELD_TYPE_TEXTAREA =                2;
+    CONST FIELD_TYPE_RADIO =                   3;
+    CONST FIELD_TYPE_SELECT =                  4;
+    CONST FIELD_TYPE_SELECT_MULTIPLE =         5;
+    CONST FIELD_TYPE_DATE =                    6;
+    CONST FIELD_TYPE_DATETIME =                7;
+    CONST FIELD_TYPE_DOUBLE_SELECT =           8;
+    CONST FIELD_TYPE_DIVIDER =                 9;
+    CONST FIELD_TYPE_TAG =                     10;
+    CONST FIELD_TYPE_TIMEZONE =                11;
+    CONST FIELD_TYPE_SOCIAL_PROFILE =          12;
+    
+    public $type = 'user'; //or session
+    public $handler_id = 'user_id';
+    
+    function __construct($type) {
+        $this->type = $type;
+        switch ($this->type) {
+            case 'user':            
+                //$this->table_field          = Database::get_main_table(TABLE_MAIN_USER_FIELD);
+                $this->table_field_options  = Database::get_main_table(TABLE_MAIN_USER_FIELD_OPTIONS);
+                $this->table_field_values   = Database::get_main_table(TABLE_MAIN_USER_FIELD_VALUES);
+                
+                //Used for the model
+                $this->table = Database::get_main_table(TABLE_MAIN_USER_FIELD);                
+                $this->handler_id =  'user_id';              
+                break;
+            case 'session':
+                //$this->table_field          = Database::get_main_table(TABLE_MAIN_SESSION_FIELD);
+                $this->table_field_options  = Database::get_main_table(TABLE_MAIN_SESSION_FIELD_OPTIONS);
+                $this->table_field_values   = Database::get_main_table(TABLE_MAIN_SESSION_FIELD_VALUES);
+                $this->handler_id =  'session_id'; 
+                
+                $this->table = Database::get_main_table(TABLE_MAIN_SESSION_FIELD);
+            break;                
+        }        
+    }    
+         
+    public function get_count() {
+        $row = Database::select('count(*) as count', $this->table, array(), 'first');
+        return $row['count'];
+    }
+    
+        
+    public function get_all($where_conditions = array()) {
+        $options = Database::select('*', $this->table, array('where'=>$where_conditions, 'order' =>'field_order ASC'));
+        
+        $sesion_field_option = new SessionFieldOption();
+        if (!empty($options)) {
+            foreach ($options as &$option) {                
+                $option['options'] = $sesion_field_option->get_field_options_by_field($option['id']);
+            }
+        }        
+        return $options;
+    }
+    
+       
+    public function get_handler_field_info_by_field_variable($field_variable) {
+        $field_variable = Database::escape_string($field_variable);
+        $sql_field = "SELECT * FROM {$this->table} WHERE field_variable = '$field_variable'";
+		$result = Database::query($sql_field);
+        if (Database::num_rows($result)) {
+            $r_field = Database::fetch_array($result, 'ASSOC');
+            return $r_field;
+        } else {
+            return false;
+        }
+    }
+    
+    public function get_max_field_order() {        
+        $sql = "SELECT MAX(field_order) FROM {$this->table}";
+        $res = Database::query($sql);
+
+        $order = 0;
+        if (Database::num_rows($res)>0) {
+            $row = Database::fetch_row($res);
+            $order = $row[0]+1;
+        }
+        return $order;
+    }
+    
+    public static function get_extra_fields_by_handler($handler) {
+        $types = array();
+        $types[self::FIELD_TYPE_TEXT]            = get_lang('FieldTypeText');
+        $types[self::FIELD_TYPE_TEXTAREA]        = get_lang('FieldTypeTextarea');
+        $types[self::FIELD_TYPE_RADIO]           = get_lang('FieldTypeRadio');
+        $types[self::FIELD_TYPE_SELECT]          = get_lang('FieldTypeSelect');
+        $types[self::FIELD_TYPE_SELECT_MULTIPLE] = get_lang('FieldTypeSelectMultiple');
+        $types[self::FIELD_TYPE_DATE]            = get_lang('FieldTypeDate');
+        $types[self::FIELD_TYPE_DATETIME]        = get_lang('FieldTypeDatetime');
+        $types[self::FIELD_TYPE_DOUBLE_SELECT]   = get_lang('FieldTypeDoubleSelect');
+        $types[self::FIELD_TYPE_DIVIDER]         = get_lang('FieldTypeDivider');
+        $types[self::FIELD_TYPE_TAG]             = get_lang('FieldTypeTag');
+        $types[self::FIELD_TYPE_TIMEZONE]        = get_lang('FieldTypeTimezone');
+        $types[self::FIELD_TYPE_SOCIAL_PROFILE]  = get_lang('FieldTypeSocialProfile');
+        
+        switch ($handler) {
+            case 'session':                
+                unset($types[self::FIELD_TYPE_TAG]);
+                unset($types[self::FIELD_TYPE_SOCIAL_PROFILE]);            
+                break;
+            case 'user':                
+                break;
+        }
+        return $types;
+    }
+    
+        
+    public function add_elements($form, $item_id = null) {
+        if (empty($form)) {
+            return false;
+        }   
+        $extra_data = false;
+        if (!empty($item_id)) {
+            $extra_data = self::get_handler_extra_data($item_id);            
+            if ($form) {
+                $form->setDefaults($extra_data);
+            }            
+        }        
+        $extra_fields = self::get_all();        
+        $extra = ExtraField::set_extra_fields_in_form($form, $extra_data, $this->type.'_field', false, false, $this->type, $extra_fields);        
+        return $extra;
+    }
+      
+    
+    public function get_handler_extra_data($item_id) {
+        if (empty($item_id)) {
+            return array();
+        }
+		$extra_data = array();		
+        $fields = self::get_all();        
+        $session_field_values = new ExtraFieldValue($this->type);		
+		
+		if (!empty($fields) > 0) {
+			foreach ($fields as $field) {
+                $field_value = $session_field_values->get_values_by_handler_and_field_id($item_id, $field['id']);                    
+                if ($field_value) {
+                    $field_value = $field_value['field_value'];                    
+                    
+                    switch ($field['field_type']) {
+                        case ExtraField::FIELD_TYPE_DOUBLE_SELECT:                            
+                            $selected_options = explode('::', $field_value);                            
+                            $extra_data['extra_'.$field['field_variable']]['extra_'.$field['field_variable']] = $selected_options[0];
+                            $extra_data['extra_'.$field['field_variable']]['extra_'.$field['field_variable'].'_second'] = $selected_options[1];
+                            break;
+                        case ExtraField::FIELD_TYPE_SELECT_MULTIPLE:
+                            $field_value = explode(';', $field_value);                                
+                        case ExtraField::FIELD_TYPE_RADIO:
+                            $extra_data['extra_'.$field['field_variable']]['extra_'.$field['field_variable']] = $field_value;
+                            break;
+                        default:
+                            $extra_data['extra_'.$field['field_variable']] = $field_value;
+                            break;
+                    }
+                }				
+			}
+		}        
+		return $extra_data;
+    }
+    
+    public static function get_all_extra_field_by_type($field_type) {		
+		// all the information of the field
+		$sql = "SELECT * FROM  {$this->table} WHERE field_type='".Database::escape_string($field_type)."'";
+		$result = Database::query($sql);
+        $return = array();
+		while ($row = Database::fetch_array($result)) {
+			$return[] = $row['id'];
+		}
+		return $return;
+	}
+    
+        
+    public function get_field_types() {
+        return self::get_extra_fields_by_handler($this->type);        
+    }
+    
+    public function get_field_type_by_id($id) {            
+        $types = self::get_field_types();
+        if (isset($types[$id])) {
+            return $types[$id];
+        }
+        return null;    
+    }
+    
+    
+    /**
+     * Converts a string like this:
+     * France:Paris;Bretagne;Marseilles;Lyon|Belgique:Bruxelles;Namur;Liège;Bruges|Peru:Lima;Piura;
+     * into
+     * array('France' => array('Paris', 'Bregtane', 'Marseilles'), 'Belgique' => array('Namur', 'Liège', etc
+     * @param string $string
+     * @return array
+     */
+    static function extra_field_double_select_convert_string_to_array($string) {
+        $options = explode('|', $string);
+        $options_parsed = array();
+        $id = 0;
+        if (!empty($options)) {
+            foreach ($options as $sub_options) {
+                $options = explode(':', $sub_options);
+                $sub_sub_options = explode(';', $options[1]);
+                $options_parsed[$id] = array('label' => $options[0], 'options' => $sub_sub_options);
+                $id++;
+            }
+        }
+        return $options_parsed;        
+    }
+    
+    static function extra_field_double_select_convert_array_to_ordered_array($options) {
+        $options_parsed = array();
+        if (!empty($options)) {
+            foreach ($options as $option) {            
+                if ($option['option_value'] == 0 ) {
+                    $options_parsed[$option['id']][] = $option;
+                } else {
+                    $options_parsed[$option['option_value']][] = $option;
+                }
+            }
+        }
+        return $options_parsed;
+    }
+    
+    /**
+  
+     * @param array options the result of the get_field_options_by_field() array
+     */
+    static function extra_field_double_select_convert_array_to_string($options) {
+        $string = null;
+        //var_dump($options);
+        $options_parsed = self::extra_field_double_select_convert_array_to_ordered_array($options);
+        
+        if (!empty($options_parsed)) {
+            foreach ($options_parsed as $option) {
+                foreach ($option as $key => $item) {                
+                    $string .= $item['option_display_text'];          
+                    if ($key == 0) {
+                        $string .= ':';
+                    } else {
+                        if (isset($option[$key+1])) {
+                            $string .= ';';
+                        }
+                    }
+                }
+                $string .= '|';            
+            }
+        }
+        
+        if (!empty($string)) {
+           $string = substr($string, 0, strlen($string)-1);
+        }        
+        return $string;
+    }
+    
+        
+    function clean_parameters($params) {
+        if (!isset($params['field_variable']) || empty($params['field_variable'])) {             
+            $params['field_variable'] = trim(strtolower(str_replace(" ","_", $params['field_display_text'])));	            
+        }
+        
+        if (!isset($params['field_order'])) {
+            $max_order = self::get_max_field_order();
+            $params['field_order'] = $max_order;
+        }
+        return $params;
+    }
+    
+    public function save($params, $show_query = false) {
+        $session_field_info = self::get_handler_field_info_by_field_variable($params['field_variable']);        
+        $params = self::clean_parameters($params);            
+        if ($session_field_info) {
+            return $session_field_info['id'];
+        } else {
+            if (!isset($params['tms'])) {
+                $params['tms'] = api_get_utc_datetime();
+            }
+            $id = parent::save($params, $show_query);
+            if ($id) {            
+                $session_field_option = new SessionFieldOption();
+                $params['field_id'] = $id;
+                $session_field_option->save($params);
+            }
+            return $id;
+        } 
+     }
+     
+          
+    public function update($params) {
+        $params = self::clean_parameters($params);        
+        if (isset($params['id'])) {            
+             $field_option = new ExtraFieldOption($this->type);
+             $params['field_id'] = $params['id'];
+             $field_option->save($params);
+         }
+         parent::update($params);         
+    }
+     
+    public function delete($id) {
+	    parent::delete($id);
+        $field_option = new ExtraFieldOption($this->type);        
+        $field_option->delete_all_options_by_field_id($id);
+        
+        $session_field_values = new ExtraFieldValue($this->type);
+        $session_field_values->delete_all_values_by_field_id($id);       
+    }
+    
+    static function set_extra_fields_in_form($form, $extra_data, $form_name, $admin_permissions = false, $user_id = null, $type = 'user', $extra = null) {          
+        $user_id = intval($user_id);
+        
+        // User extra fields
+        if ($type == 'user') {
+            $extra = UserManager::get_extra_fields(0, 50, 5, 'ASC', true, null, true);            
+        }       
+        
+        $jquery_ready_content = null;
+        
+        if (!empty($extra))
+        foreach ($extra as $field_details) {       
+            if (!$admin_permissions) {
+                if ($field_details['field_visible'] == 0) {
+                    continue;
+                }
+            }           
+            switch ($field_details['field_type']) {
+                case ExtraField::FIELD_TYPE_TEXT:
+                    $form->addElement('text', 'extra_'.$field_details['field_variable'], $field_details['field_display_text'], array('class' => 'span4'));
+                    $form->applyFilter('extra_'.$field_details['field_variable'], 'stripslashes');
+                    $form->applyFilter('extra_'.$field_details['field_variable'], 'trim');                    
+                    if (!$admin_permissions) {
+                        if ($field_details['field_visible'] == 0)	$form->freeze('extra_'.$field_details['field_variable']);
+                    }
+                    break;
+                case ExtraField::FIELD_TYPE_TEXTAREA:
+                    $form->add_html_editor('extra_'.$field_details['field_variable'], $field_details['field_display_text'], false, false, array('ToolbarSet' => 'Profile', 'Width' => '100%', 'Height' => '130'));
+                    //$form->addElement('textarea', 'extra_'.$field_details['field_variable'], $field_details['field_display_text'], array('size' => 80));
+                    $form->applyFilter('extra_'.$field_details['field_variable'], 'stripslashes');
+                    $form->applyFilter('extra_'.$field_details['field_variable'], 'trim');
+                    if (!$admin_permissions) {
+                        if ($field_details['field_visible'] == 0) $form->freeze('extra_'.$field_details['field_variable']);
+                    }
+                    break;
+                case ExtraField::FIELD_TYPE_RADIO:
+                    $group = array();
+                    foreach ($field_details['options'] as $option_id => $option_details) {
+                        $options[$option_details['option_value']] = $option_details['option_display_text'];
+                        $group[] = $form->createElement('radio', 'extra_'.$field_details['field_variable'], $option_details['option_value'],$option_details['option_display_text'].'<br />',$option_details['option_value']);
+                    }
+                    $form->addGroup($group, 'extra_'.$field_details['field_variable'], $field_details['field_display_text'], '');
+                    if (!$admin_permissions) {
+                        if ($field_details['field_visible'] == 0)	$form->freeze('extra_'.$field_details['field_variable']);
+                    }
+                    break;
+                case ExtraField::FIELD_TYPE_SELECT:
+                    $get_lang_variables = false;
+                    if (in_array($field_details['field_variable'], array('mail_notify_message','mail_notify_invitation', 'mail_notify_group_message'))) {
+                        $get_lang_variables = true;
+                    }                
+                    $options = array();
+                   
+                    foreach ($field_details['options'] as $option_id => $option_details) {
+                        //$options[$option_details['option_value']] = $option_details['option_display_text'];
+                        if ($get_lang_variables) {
+                            $options[$option_details['option_value']] = get_lang($option_details['option_display_text']);
+                        } else {
+                          $options[$option_details['option_value']] = $option_details['option_display_text'];  
+                        }
+                    }
+                    if ($get_lang_variables) {
+                        $field_details['field_display_text'] = get_lang($field_details['field_display_text']);
+                    }                    
+                    //chzn-select doesn't work for sessions??
+                    $form->addElement('select','extra_'.$field_details['field_variable'], $field_details['field_display_text'], $options, array('class'=>'', 'id'=>'extra_'.$field_details['field_variable']));
+                    if (!$admin_permissions) {
+                        if ($field_details['field_visible'] == 0) {
+                            $form->freeze('extra_'.$field_details['field_variable']);
+                        }
+                    }
+                    break;
+                case ExtraField::FIELD_TYPE_SELECT_MULTIPLE:
+                    $options = array();
+                    foreach ($field_details['options'] as $option_id => $option_details) {
+                        $options[$option_details['option_value']] = $option_details['option_display_text'];
+                    }
+                    $form->addElement('select','extra_'.$field_details['field_variable'], $field_details['field_display_text'], $options, array('multiple' => 'multiple'));
+                    if (!$admin_permissions) {
+                        if ($field_details['field_visible'] == 0) {
+                            $form->freeze('extra_'.$field_details['field_variable']);
+                        }
+                    }
+                    break;
+                case ExtraField::FIELD_TYPE_DATE:
+                    $form->addElement('datepickerdate', 'extra_'.$field_details['field_variable'], $field_details['field_display_text'], array('form_name' => $form_name));
+                    $form->_elements[$form->_elementIndex['extra_'.$field_details['field_variable']]]->setLocalOption('minYear', 1900);
+                    $defaults['extra_'.$field_details['field_variable']] = date('Y-m-d 12:00:00');
+                    $form -> setDefaults($defaults);
+                    if (!$admin_permissions) {
+                        if ($field_details['field_visible'] == 0) {
+                            $form->freeze('extra_'.$field_details['field_variable']);                            
+                        }
+                    }
+                    $form->applyFilter('theme', 'trim');
+                    break;
+                case ExtraField::FIELD_TYPE_DATETIME:
+                    $form->addElement('datepicker', 'extra_'.$field_details['field_variable'], $field_details['field_display_text'], array('form_name' => $form_name));
+                    $form->_elements[$form->_elementIndex['extra_'.$field_details['field_variable']]]->setLocalOption('minYear', 1900);
+                    $defaults['extra_'.$field_details['field_variable']] = date('Y-m-d 12:00:00');
+                    $form -> setDefaults($defaults);
+                    if (!$admin_permissions) {
+                        if ($field_details['field_visible'] == 0) {
+                            $form->freeze('extra_'.$field_details['field_variable']);
+                        }
+                    }
+                    $form->applyFilter('theme', 'trim');
+                    break;
+                case ExtraField::FIELD_TYPE_DOUBLE_SELECT:
+                    $first_select_id = 'first_extra_'.$field_details['field_variable'];
+                    
+                    $url = api_get_path(WEB_AJAX_PATH).'extra_field.ajax.php?1=1';
+
+                    $jquery_ready_content .= '                        
+                        $("#'.$first_select_id.'").on("change", function() {                   
+                            var id = $(this).val();
+                            if (id) {
+                                $.ajax({ 
+                                    url: "'.$url.'&a=get_second_select_options", 
+                                    dataType: "json",
+                                    data: "type='.$type.'&field_id='.$field_details['id'].'&option_value_id="+id,
+                                    success: function(data) {
+                                        $("#second_extra_'.$field_details['field_variable'].'").empty();
+                                        $.each(data, function(index, value) {
+                                            $("#second_extra_'.$field_details['field_variable'].'").append($("<option/>", {
+                                                value: index,
+                                                text: value
+                                            }));
+                                        });                           
+                                    },            
+                                });  
+                            } else {
+                                $("#second_extra_'.$field_details['field_variable'].'").empty();
+                            }
+                        });';
+                    
+                    $first_id = null;
+                    $second_id = null;
+                    
+                    if (!empty($extra_data)) {
+                        $first_id = $extra_data['extra_'.$field_details['field_variable']]['extra_'.$field_details['field_variable']];
+                        $second_id = $extra_data['extra_'.$field_details['field_variable']]['extra_'.$field_details['field_variable'].'_second'];                        
+                    }
+
+                    $options = ExtraField::extra_field_double_select_convert_array_to_ordered_array($field_details['options']);
+                    $values = array('' => get_lang('Select'));
+                    
+                    $second_values = array();
+                    if (!empty($options)) {                        
+                        foreach ($options as $option) {                            
+                            foreach ($option as $sub_option) {
+                                if ($sub_option['option_value'] == '0') {
+                                    $values[$sub_option['id']] = $sub_option['option_display_text'];
+                                } else {
+                                    if ($first_id === $sub_option['option_value']) {
+                                        $second_values[$sub_option['id']] = $sub_option['option_display_text'];
+                                    }
+                                }
+                            }
+                        }
+                    }                    
+                    $group = array();
+                    $group[] = $form->createElement('select', 'extra_'.$field_details['field_variable'], null, $values, array('id' => $first_select_id));
+                    $group[] = $form->createElement('select', 'extra_'.$field_details['field_variable'].'_second', null, $second_values, array('id'=>'second_extra_'.$field_details['field_variable']));
+                    $form->addGroup($group, 'extra_'.$field_details['field_variable'], $field_details['field_display_text'], '&nbsp;');
+                    
+                    if (!$admin_permissions) {
+                        if ($field_details['field_visible'] == 0) {
+                            $form->freeze('extra_'.$field_details['field_variable']);
+                        }
+                    }
+                    break;
+                case ExtraField::FIELD_TYPE_DIVIDER:
+                    $form->addElement('static', $field_details['field_variable'], '<br /><strong>'.$field_details['field_display_text'].'</strong>');
+                    break;
+                case ExtraField::FIELD_TYPE_TAG:
+                    //the magic should be here
+                    $user_tags = UserManager::get_user_tags($user_id, $field_details['id']);                    
+
+                    $tag_list = '';
+                    if (is_array($user_tags) && count($user_tags) > 0) {
+                        foreach ($user_tags as $tag) {
+                            $tag_list .= '<option value="'.$tag['tag'].'" class="selected">'.$tag['tag'].'</option>';
+                        }
+                    }
+
+                    $multi_select = '<select id="extra_'.$field_details['field_variable'].'" name="extra_'.$field_details['field_variable'].'">
+                                    '.$tag_list.'
+                                    </select>';
+
+                    $form->addElement('label',$field_details['field_display_text'], $multi_select);
+                    $url = api_get_path(WEB_AJAX_PATH).'user_manager.ajax.php';
+                    $complete_text = get_lang('StartToType');
+                    //if cache is set to true the jquery will be called 1 time
+                    $field_variable = $field_details['field_variable'];
+                    $field_id = $field_details['id'];
+                    $jquery_ready_content .=  <<<EOF
+                    $("#extra_$field_variable").fcbkcomplete({
+                        json_url: "$url?a=search_tags&field_id=$field_id",
+                        cache: false,
+                        filter_case: true,
+                        filter_hide: true,
+                        complete_text:"$complete_text",
+                        firstselected: true,
+                        //onremove: "testme",
+                        //onselect: "testme",
+                        filter_selected: true,
+                        newel: true
+                    });
+EOF;
+                    break;
+                case ExtraField::FIELD_TYPE_TIMEZONE:
+                    $form->addElement('select', 'extra_'.$field_details['field_variable'], $field_details['field_display_text'], api_get_timezones(), '');
+                    if ($field_details['field_visible'] == 0)	$form->freeze('extra_'.$field_details['field_variable']);
+                    break;
+                case ExtraField::FIELD_TYPE_SOCIAL_PROFILE:
+                    // get the social network's favicon
+                    $icon_path = UserManager::get_favicon_from_url($extra_data['extra_'.$field_details['field_variable']], $field_details['field_default_value']);
+                    // special hack for hi5
+                    $leftpad = '1.7'; 
+                    $top = '0.4'; 
+                    $domain = parse_url($icon_path, PHP_URL_HOST); 
+                    if ($domain == 'www.hi5.com' or $domain == 'hi5.com') {
+                        $leftpad = '3'; $top = '0';                        
+                    }
+                    // print the input field
+                    $form->addElement('text', 'extra_'.$field_details['field_variable'], $field_details['field_display_text'], array('size' => 60, 'style' => 'background-image: url(\''.$icon_path.'\'); background-repeat: no-repeat; background-position: 0.4em '.$top.'em; padding-left: '.$leftpad.'em; '));
+                    $form->applyFilter('extra_'.$field_details['field_variable'], 'stripslashes');
+                    $form->applyFilter('extra_'.$field_details['field_variable'], 'trim');
+                    if ($field_details['field_visible'] == 0) {	
+                        $form->freeze('extra_'.$field_details['field_variable']);
+                    }
+                    break;
+            }
+        }
+        $return = array();
+        $return['jquery_ready_content'] = $jquery_ready_content;
+        return $return;
+    }
+}

+ 330 - 0
main/inc/lib/extra_field_option.lib.php

@@ -0,0 +1,330 @@
+<?php
+/* For licensing terms, see /license.txt */
+
+class ExtraFieldOption extends Model {
+    public $columns = array('id', 'field_id', 'option_value', 'option_display_text', 'option_order', 'tms');
+     
+    public function __construct($type) {
+        $this->type = $type;
+        switch ($this->type) {            
+            case 'user':            
+                $this->table = Database::get_main_table(TABLE_MAIN_USER_FIELD_OPTIONS);
+                break;
+            case 'session':
+                $this->table = Database::get_main_table(TABLE_MAIN_SESSION_FIELD_OPTIONS);                        
+            break;   
+        }
+    }
+     
+    public function get_count() {
+        $row = Database::select('count(*) as count', $this->table, array(), 'first');
+        return $row['count'];
+    }  
+    
+    public function get_count_by_field_id($field_id) {
+        $row = Database::select('count(*) as count', $this->table, array('where' => array('field_id = ?' => $field_id)), 'first');           
+        return $row['count'];
+    }
+    
+    public function get_field_options_to_string($field_id) {
+        $options = self::get_field_options_by_field($field_id);
+        $new_options = array();        
+        if (!empty($options)) {
+            foreach ($options as $option) {
+                $new_options[] = $option['option_value'].':'.$option['option_display_text'];
+            }
+            $string = implode(';', $new_options);
+            return $string;
+        }
+    }
+    
+    public function delete_all_options_by_field_id($field_id) {
+        $field_id = intval($field_id);
+        $sql = "DELETE FROM  {$this->table} WHERE field_id = $field_id";
+        Database::query($sql);
+    }
+    
+    public function save($params, $show_query = false) {
+        $field_id = intval($params['field_id']);
+        
+        if (empty($field_id)) {
+            return false;
+        }
+        
+        $time = api_get_utc_datetime();     
+        if (!empty($params['field_options']) && 
+            in_array($params['field_type'], array(
+                ExtraField::FIELD_TYPE_RADIO, 
+                ExtraField::FIELD_TYPE_SELECT, 
+                ExtraField::FIELD_TYPE_SELECT_MULTIPLE, 
+                ExtraField::FIELD_TYPE_DOUBLE_SELECT))
+            ) {
+            if ($params['field_type'] == ExtraField::FIELD_TYPE_DOUBLE_SELECT) {
+                //$params['field_options'] = France:Paris;Bretagne;Marseilles;Lyon|Belgique:Bruxelles;Namur;Liège;Bruges|Peru:Lima;Piura;                
+                $options_parsed = ExtraField::extra_field_double_select_convert_string_to_array($params['field_options']);                
+                
+                if (!empty($options_parsed)) {
+                    foreach ($options_parsed as $key => $option) {                        
+                        $sub_options = $option['options'];
+
+                        $new_params = array(
+                            'field_id' => $field_id,                            
+                            'option_value' => 0,
+                            'option_display_text' => $option['label'],
+                            'option_order' => 0,
+                            'tms' => $time,
+                        );
+                        //Looking if option already exists:
+                        $option_info = self::get_field_option_by_field_id_and_option_display_text($field_id, $option['label']);
+                        
+                        if (empty($option_info)) {
+                            $sub_id = parent::save($new_params, $show_query);
+                        } else {
+                            $sub_id = $option_info['id'];
+                            $new_params['id'] = $sub_id;
+                            parent::update($new_params, $show_query);                            
+                        }                        
+                        foreach ($sub_options as $sub_option) {                            
+                            if (!empty($sub_option)) {
+                                $new_params = array(
+                                    'field_id' => $field_id,                            
+                                    'option_value' => $sub_id,
+                                    'option_display_text' => $sub_option,
+                                    'option_order' => 0,
+                                    'tms' => $time,
+                                );
+                                $option_info = self::get_field_option_by_field_id_and_option_display_text_and_option_value($field_id, $sub_option, $sub_id);                                                                
+                                if (empty($option_info)) {
+                                    parent::save($new_params, $show_query);                                     
+                                } else {                                    
+                                    $new_params['id'] = $option_info['id'];
+                                    parent::update($new_params, $show_query);    
+                                }                                
+                            }
+                            
+                        }
+                    }
+                }
+                $list = array();
+            } else {
+                $list = explode(';', $params['field_options']);
+            }
+            
+            if (!empty($list)) {
+                foreach ($list as $option) {
+                    $option_info = self::get_field_option_by_field_and_option($field_id, $option);
+                    
+                    if ($option_info == false) {
+                        $order = self::get_max_order($field_id);                        
+                        $new_params = array(
+                            'field_id' => $field_id,                            
+                            'option_value' => $option,
+                            'option_display_text' => $option,
+                            'option_order' => $order,
+                            'tms' => $time,
+                        );
+                        parent::save($new_params, $show_query);                         
+                    }
+                }
+            }
+        }
+        return true;    
+    }
+    
+    public function save_one_item($params, $show_query = false) {
+        $field_id = intval($params['field_id']);
+        
+        if (empty($field_id)) {
+            return false;
+        }        
+        $params['tms'] = api_get_utc_datetime();
+   
+        if (empty($params['option_order'])) {
+            $order = self::get_max_order($field_id);
+            $params['option_order'] = $order;
+        }
+        parent::save($params, $show_query); 
+    }
+           
+    public function get_field_option_by_field_and_option($field_id, $option_value) {
+        $field_id = intval($field_id);
+        $option_value = Database::escape_string($option_value);
+        
+        $sql = "SELECT * FROM {$this->table} WHERE field_id = $field_id AND option_value = '".$option_value."'";
+        $result = Database::query($sql);
+        if (Database::num_rows($result) > 0) {
+            return Database::store_result($result, 'ASSOC');
+        }
+        return false;        
+    }
+    
+    public function get_field_option_by_field_id_and_option_display_text($field_id, $option_display_text) {
+        $field_id = intval($field_id);
+        $option_display_text = Database::escape_string($option_display_text);
+        
+        $sql = "SELECT * FROM {$this->table} WHERE field_id = $field_id AND option_display_text = '".$option_display_text."'";
+        $result = Database::query($sql);
+        if (Database::num_rows($result) > 0) {
+            return Database::fetch_array($result, 'ASSOC');
+        }
+        return false;        
+    }
+    
+    public function get_field_option_by_field_id_and_option_display_text_and_option_value($field_id, $option_display_text, $option_value) {
+        $field_id = intval($field_id);
+        $option_display_text = Database::escape_string($option_display_text);
+        $option_value = Database::escape_string($option_value);
+        
+        $sql = "SELECT * FROM {$this->table} WHERE field_id = $field_id AND option_display_text = '".$option_display_text."' AND option_value = '$option_value'";        
+        $result = Database::query($sql);
+        if (Database::num_rows($result) > 0) {
+            return Database::fetch_array($result, 'ASSOC');
+        }
+        return false;        
+    }
+    
+    public function get_field_options_by_field($field_id, $add_id_in_array = false, $ordered_by = null) {
+        $field_id = intval($field_id);
+        $option_value = Database::escape_string($option_value);
+        
+        $sql = "SELECT * FROM {$this->table} 
+                WHERE field_id = $field_id ";
+        
+        if (!empty($ordered_by)) {
+            $sql .= " ORDER BY $ordered_by ";
+        }
+        
+        $result = Database::query($sql);
+        if (Database::num_rows($result) > 0) {
+            if ($add_id_in_array) {
+                $options = array();
+                while ($row = Database::fetch_array($result, 'ASSOC')) {                    
+                    $options[$row['id']] = $row;
+                }
+                return $options;
+            } else {
+                return Database::store_result($result, 'ASSOC');
+            }
+        }
+        return false;        
+    }
+    
+    public function get_second_select_field_options_by_field($field_id, $option_value_id, $to_json = false) {
+        $field_id = intval($field_id);
+        $option_value_id = intval($option_value_id);        
+        $options = array();
+        $sql = "SELECT * FROM {$this->table} 
+                WHERE field_id = $field_id AND option_value = $option_value_id 
+                ORDER BY option_display_text";
+        $result = Database::query($sql);
+        if (Database::num_rows($result) > 0) {
+            $options = Database::store_result($result, 'ASSOC');
+        }
+        
+        if ($to_json) {
+            $string = null;
+            if (!empty($options)) {
+                $array = array();
+                foreach ($options as $option) {                    
+                    $array[$option['id']] = $option['option_display_text'];
+                }                
+                $string = json_encode($array);                
+            }
+            return $string;
+            
+        }        
+        return $options;    
+    }
+    
+    public function get_field_options_by_field_to_string($field_id, $ordered_by = null) {        
+        $field = new ExtraField($this->type);
+        $field_info = $field->get($field_id);                
+        $options = self::get_field_options_by_field($field_id, false, $ordered_by);        
+        $elements = array();
+        if (!empty($options)) {
+            switch ($field_info['field_type']) {
+                case ExtraField::FIELD_TYPE_DOUBLE_SELECT:                    
+                    $html = ExtraField::extra_field_double_select_convert_array_to_string($options);                    
+                    break;
+                default:
+                    foreach ($options as $option) {
+                        $elements[]= $option['option_value'];
+                    }
+                    $html = implode(';', $elements);
+                    break;                
+            }
+            
+            return $html;
+        }
+        return null;
+        
+    }
+    
+    public function get_max_order($field_id) {
+        $field_id = intval($field_id);
+        $sql = "SELECT MAX(option_order) FROM {$this->table} WHERE field_id = $field_id";
+        $res = Database::query($sql);
+        $max = 1;
+        if (Database::num_rows($res) > 0) {
+            $row = Database::fetch_array($res);
+            $max = $row[0] + 1;
+        }
+        return $max;
+    }
+    
+    public function update($params) {
+        parent::update($params);
+    }
+    
+    //Form
+    
+    function display() {
+        // action links
+        echo '<div class="actions">';
+       	//echo  '<a href="../admin/index.php">'.Display::return_icon('back.png', get_lang('BackTo').' '.get_lang('PlatformAdmin'),'', ICON_SIZE_MEDIUM).'</a>';	   
+        $field_id = isset($_REQUEST['field_id']) ? intval($_REQUEST['field_id']) : null;
+        echo '<a href="'.api_get_self().'?action=add&type='.$this->type.'&field_id='.$field_id.'">'.Display::return_icon('add_user_fields.png',get_lang('Add'),'', ICON_SIZE_MEDIUM).'</a>';               
+        echo '</div>';
+        echo Display::grid_html('extra_field_options');
+    }
+    
+    public function return_form($url, $action) {
+		$form_name = $this->type.'_field';
+        $form = new FormValidator($form_name, 'post', $url);
+        // Settting the form elements
+        $header = get_lang('Add');        
+        if ($action == 'edit') {
+            $header = get_lang('Modify');
+        }
+        
+        $form->addElement('header', $header);
+        $id = isset($_GET['id']) ? intval($_GET['id']) : '';
+        
+        $form->addElement('hidden', 'id', $id);       
+        $form->addElement('hidden', 'type', $this->type);
+        $form->addElement('hidden', 'field_id', $this->field_id);       
+        
+        $form->addElement('text', 'option_display_text', get_lang('Name'), array('class' => 'span5'));  
+        $form->addElement('text', 'option_value', get_lang('Value'), array('class' => 'span5'));
+        $form->addElement('text', 'option_order', get_lang('Order'), array('class' => 'span2'));
+        
+        $defaults = array();
+        
+        if ($action == 'edit') {
+            // Setting the defaults
+            $defaults = $this->get($id);
+            $form->freeze('option_value');
+        	$form->addElement('button', 'submit', get_lang('Modify'), 'class="save"');
+        } else {            
+        	$form->addElement('button', 'submit', get_lang('Add'), 'class="save"');
+        }
+        
+        $form->setDefaults($defaults);
+    
+        // Setting the rules
+        $form->addRule('option_display_text', get_lang('ThisFieldIsRequired'), 'required');        
+        //$form->addRule('field_variable', get_lang('ThisFieldIsRequired'), 'required');
+        $form->addRule('option_value', get_lang('ThisFieldIsRequired'), 'required');        
+		return $form;
+    }    
+}

+ 192 - 0
main/inc/lib/extra_field_value.lib.php

@@ -0,0 +1,192 @@
+<?php
+
+class ExtraFieldValue extends Model {
+    public $type = null;
+    public $columns = array('id', 'field_id', 'field_value', 'tms');
+    public $handler_id = null;
+     
+    public function __construct($type) {
+        $this->type = $type;
+        $extra_field = new ExtraField($this->type);
+        $this->handler_id = $extra_field->handler_id;
+        switch ($this->type) {
+            case 'user':
+                $this->table = Database::get_main_table(TABLE_MAIN_USER_FIELD_VALUES);
+                $this->table_session_field = Database::get_main_table(TABLE_MAIN_USER_FIELD);                              
+                break;
+            case 'session':
+                $this->table = Database::get_main_table(TABLE_MAIN_SESSION_FIELD_VALUES);
+                $this->table_session_field = Database::get_main_table(TABLE_MAIN_SESSION_FIELD);                
+            break;
+        }
+        $this->columns[] = $this->handler_id;
+    }
+     
+    public function get_count() {
+        $row = Database::select('count(*) as count', $this->table, array(), 'first');
+        return $row['count'];
+    }
+    
+    public function save_field_values($params) {
+        $session_field = new SessionField();
+        if (empty($params['session_id'])) {
+            return false;            
+        }
+        
+        //Parse params        
+        foreach ($params as $key => $value) {
+            if (substr($key, 0, 6) == 'extra_') { //an extra field
+                $field_variable = substr($key, 6);
+                $session_field_info = $session_field->get_handler_field_info_by_field_variable($field_variable);                
+                if ($session_field_info) {                
+                    $new_params = array(
+                        'session_id'    => $params['session_id'],
+                        'field_id'      => $session_field_info['id'],
+                        'field_value'   => $value
+                    );                    
+                    self::save($new_params);
+                }
+            }
+        }        
+    }
+    
+    public function save($params, $show_query = false) {        
+        $session_field = new SessionField();
+        //$session_field_option = new SessionFieldOption();
+        
+        //Setting value to insert
+        $value = $params['field_value'];       
+        
+        $value_to_insert = null;
+        
+        if (is_array($value)) {
+            $value_to_insert = implode(';', $value);            
+		} else {
+			$value_to_insert = Database::escape_string($value);
+		}                
+        $params['field_value'] = $value_to_insert;
+        
+        //If field id exists
+        $session_field_info = $session_field->get($params['field_id']);
+                
+        if ($session_field_info) {            
+            switch ($session_field_info['field_type']) {
+                case ExtraField::FIELD_TYPE_TAG :
+                    break;
+                case ExtraField::FIELD_TYPE_RADIO:
+				case ExtraField::FIELD_TYPE_SELECT:
+				case ExtraField::FIELD_TYPE_SELECT_MULTIPLE:
+                    //$field_options = $session_field_option->get_field_options_by_field($params['field_id']);                  
+					//$params['field_value'] = split(';', $value_to_insert);                    
+                    /*
+					if ($field_options) {
+						$check = false;
+						foreach ($field_options as $option) {
+							if (in_array($option['option_value'], $values)) {
+								$check = true;
+								break;
+							}
+						}
+						if (!$check) {
+							return false; //option value not found
+						}
+					} else {
+						return false; //enumerated type but no option found
+					}*/
+                    break;
+                case ExtraField::FIELD_TYPE_TEXT:
+                case ExtraField::FIELD_TYPE_TEXTAREA:
+                    break;
+                case ExtraField::FIELD_TYPE_DOUBLE_SELECT:
+                    if (is_array($value)) {                        
+                        if (isset($value['extra_'.$session_field_info['field_variable']]) && 
+                            isset($value['extra_'.$session_field_info['field_variable'].'_second'])
+                             ) {
+                            $value_to_insert = $value['extra_'.$session_field_info['field_variable']].'::'.$value['extra_'.$session_field_info['field_variable'].'_second'];                        
+                        } else {
+                            $value_to_insert = null;
+                        }
+                    }
+                default:
+                    break;
+            }            
+            $session_field_values = self::get_values_by_handler_and_field_id($params['session_id'], $params['field_id']);            
+            if ($session_field_values) {
+                self::delete_values_by_handler_and_field_id($params['session_id'], $params['field_id']);                
+            }            
+            $params['field_value'] = $value_to_insert;
+            $params['tms'] = api_get_utc_datetime();            
+            parent::save($params, $show_query);
+        }        
+    }
+    
+    /**
+     * 
+     * @param int $session_id
+     * @param int $field_id
+     * @param bool transform the result to a human readable strings
+     * @return boolean
+     */
+    public function get_values_by_handler_and_field_id($item_id, $field_id, $transform = false) {
+        $field_id = intval($field_id);
+        $item_id = intval($item_id);
+        
+        $sql = "SELECT s.*, field_type FROM {$this->table} s INNER JOIN {$this->table_session_field} sf ON (s.field_id = sf.id)
+                WHERE {$this->handler_id} = '$item_id'  AND field_id = '".$field_id."' ORDER BY id";
+        $result = Database::query($sql);        
+        if (Database::num_rows($result)) {            
+            $result = Database::fetch_array($result, 'ASSOC'); 
+            if ($transform) {
+                if ($result['field_type'] == ExtraField::FIELD_TYPE_DOUBLE_SELECT) {
+                    if (!empty($result['field_value'])) {
+                        $session_field_option = new SessionFieldOption();
+                        $options = explode('::', $result['field_value']);    
+                        // only available for PHP 5.4  :( $result['field_value'] = $session_field_option->get($options[0])['id'].' -> ';
+                        $result = $session_field_option->get($options[0]);
+                        $result_second = $session_field_option->get($options[1]);
+                        if (!empty($result)) {
+                            $result['field_value'] = $result['option_display_text'].' -> ';
+                            $result['field_value'] .= $result_second['option_display_text'];
+                        }
+                    }            
+                }
+            }
+            return $result;
+        } else {
+            return false;
+        }        
+        /*$field = Database::escape_string($field);
+        $sql_field = "SELECT id FROM {$this->table} WHERE field_variable = '$field'";
+		$result = Database::query($sql_field);
+        if (Database::num_rows($result)) {
+            $r_field = Database::fetch_row($result);
+            return $r_field;
+        } else {
+            return false;
+        }*/
+    }
+    
+    /* Get all values by field id */
+    public function get_values_by_field_id($field_id) {        
+        $sql = "SELECT s.*, field_type FROM {$this->table} s INNER JOIN {$this->table_session_field} sf ON (s.field_id = sf.id)
+                WHERE field_id = '".$field_id."' ORDER BY id";
+        $result = Database::query($sql);        
+        if (Database::num_rows($result)) {            
+            return Database::store_result($result, 'ASSOC'); 
+        }
+        return false;
+    }
+    
+    public function delete_all_values_by_field_id($field_id) {
+        $field_id = intval($field_id);
+        $sql = "DELETE FROM  {$this->table} WHERE field_id = $field_id";
+        Database::query($sql); 
+    }
+    
+    public function delete_values_by_handler_and_field_id($item_id, $field_id) {
+        $field_id = intval($field_id);
+        $item_id = intval($item_id);
+        $sql = "DELETE FROM {$this->table} WHERE {$this->handler_id} = '$item_id' AND field_id = '".$field_id."' ";
+        Database::query($sql); 
+    }   
+}

+ 1 - 1
main/inc/lib/formvalidator/Element/style_submit_button.php

@@ -58,7 +58,7 @@ class HTML_QuickForm_stylesubmitbutton extends HTML_QuickForm_stylebutton
         
         if (!isset($attributes['class'])) {
             if (is_array($attributes)) {
-                $attributes['class'] = 'btn';
+                $attributes['class'] = 'btn btn-primary';
             }            
         }
         HTML_QuickForm_stylebutton::HTML_QuickForm_stylebutton($elementName, null, $attributes, $value, $img);

+ 3 - 1
main/inc/lib/formvalidator/FormValidator.class.php

@@ -143,7 +143,9 @@ class FormValidator extends HTML_QuickForm
         $this->registerRule('filetype', null, 'HTML_QuickForm_Rule_Filetype', $dir . 'Rule/Filetype.php');
         $this->registerRule('multiple_required', 'required', 'HTML_QuickForm_Rule_MultipleRequired', $dir . 'Rule/MultipleRequired.php');
         $this->registerRule('url', null, 'HTML_QuickForm_Rule_Url', $dir . 'Rule/Url.php');
-        $this->registerRule('compare_fields', null, 'HTML_QuickForm_Compare_Fields', $dir . 'Rule/CompareFields.php');
+        $this->registerRule('compare_fields', null, 'HTML_QuickForm_Compare_Fields', $dir . 'Rule/CompareFields.php');       
+        $this->registerRule('compare_datetime_text', null, 'HTML_QuickForm_Rule_CompareDateTimeText', $dir . 'Rule/CompareDateTimeText.php');
+        
 
         // Modify the default templates
         $renderer = & $this->defaultRenderer();

+ 27 - 0
main/inc/lib/formvalidator/Rule/CompareDateTimeText.php

@@ -0,0 +1,27 @@
+<?php
+
+require_once 'HTML/QuickForm/Rule/Compare.php';
+/**
+ * QuickForm rule to compare 2 dates
+ */
+class HTML_QuickForm_Rule_CompareDateTimeText extends HTML_QuickForm_Rule_Compare
+{
+    /**
+     * Validate 2 dates          
+     * @param string $operator The operator to use (default '==')
+     * @return boolean True if the 2 given dates match the operator
+     */
+    function validate($values, $operator = null) {
+    	$datetime1 = api_strtotime($values[0]);
+        $datetime2 = api_strtotime($values[1]);   	
+        
+        if (strpos($operator, 'allow_empty') !== false) {
+            $operator = str_replace('allow_empty', '', $operator);            
+            if (!$datetime2 || empty($datetime2)) { 
+                return true;
+            }
+        }
+		$result =  parent::validate(array($datetime1, $datetime2), $operator);        
+        return $result;
+    }
+}

+ 1 - 1
main/inc/lib/formvalidator/Rule/CompareFields.php

@@ -12,7 +12,7 @@ class HTML_QuickForm_Compare_Fields extends HTML_QuickForm_Rule_Compare
      * @param   string the value to compare
 	 * @return boolean True if date is valid
 	 */
-	function validate($values, $operator_and_max_value) {
+	function validate($values, $operator_and_max_value = null) {
         if (is_array($values) && !empty($values) && !empty($operator_and_max_value)) {
            $final_value = 0;
            foreach ($values as $value) {

+ 22 - 11
main/inc/lib/grade_model.lib.php

@@ -8,7 +8,6 @@
 /**
  * Code
  */
-
 /**
  * @package chamilo.library
  */
@@ -105,20 +104,29 @@ class GradeModel extends Model {
         for ($i = 0; $i <= $max;  $i++) {
             $counter = $i;
             $form->addElement('text', 'components['.$i.'][percentage]', null, array('class' => 'span1'));                                        
-            $form->addElement('text', 'components['.$i.'][acronym]',    null, array('class' => 'span1'));
-            $form->addElement('text', 'components['.$i.'][title]',      null, array('class' => 'span3'));        
-            $form->addElement('hidden', 'components['.$i.'][id]',       null, array('class' => 'span3'));
+            $form->addElement('text', 'components['.$i.'][acronym]',    null, array('class' => 'span1', 'placeholder' => get_lang('Acronym')));
+            $form->addElement('text', 'components['.$i.'][title]',      null, array('class' => 'span2', 'placeholder' => get_lang('Title')));            
+            $form->addElement('text', 'components['.$i.'][prefix]',      null, array('class'=> 'span1', 'placeholder' => get_lang('Prefix')));
+            
+            $options = array(0=>0, 1 => 1, 2 => 2, 3=>3, 4=> 4, 5=> 5);
+            $form->addElement('select', 'components['.$i.'][count_elements]', null, $options);
+            
+            $options = array(0=>0, 1 => 1, 2 => 2, 3=>3, 4=> 4, 5=> 5);            
+            $form->addElement('select', 'components['.$i.'][exclusions]',      null, $options);
+            
             
-             $template_percentage =
+            
+            $form->addElement('hidden', 'components['.$i.'][id]');
+            
+            $template_percentage =
             '<div id=' . $i . ' style="display: '.(($i<=$nr_items)?'inline':'none').';" class="control-group">                
                 <p>
                 <label class="control-label">{label}</label>
-                <div class="controls">
-                    <!-- BEGIN required --><span class="form_required">*</span> <!-- END required -->
+                <div class="controls">                    
                     {element} <!-- BEGIN error --><span class="form_error">{error}</span><!-- END error --> % = ';
             
             $template_acronym = '
-            <!-- BEGIN required --><span class="form_required">*</span> <!-- END required -->            
+            <!-- BEGIN required -->      
             {element} {label} <!-- BEGIN error --><span class="form_error">{error}</span> <!-- END error -->';
 
             $template_title =
@@ -131,10 +139,14 @@ class GradeModel extends Model {
             </a>            
             </div></p></div>';
             
-            $renderer->setElementTemplate($template_title, 'components['.$i.'][title]');
+            $renderer->setElementTemplate($template_acronym, 'components['.$i.'][title]');
             $renderer->setElementTemplate($template_percentage ,  'components['.$i.'][percentage]');
             $renderer->setElementTemplate($template_acronym , 'components['.$i.'][acronym]');
             
+            $renderer->setElementTemplate($template_acronym , 'components['.$i.'][prefix]');
+            $renderer->setElementTemplate($template_title , 'components['.$i.'][exclusions]');
+            $renderer->setElementTemplate($template_acronym , 'components['.$i.'][count_elements]');
+            
             if ($i == 0) {
                 $form->addRule('components['.$i.'][percentage]', get_lang('ThisFieldIsRequired'), 'required');
                 $form->addRule('components['.$i.'][title]', get_lang('ThisFieldIsRequired'), 'required');
@@ -256,12 +268,11 @@ class GradeModel extends Model {
 
 class GradeModelComponents extends Model {
     var $table;
-    var $columns = array('id', 'title', 'percentage', 'acronym', 'grade_model_id');
+    var $columns = array('id', 'title', 'percentage', 'acronym', 'grade_model_id', 'prefix', 'exclusions', 'count_elements');
     
 	public function __construct() {
         $this->table =  Database::get_main_table(TABLE_GRADE_MODEL_COMPONENTS);
 	}    
-    
     public function save($params, $show_query = false) {        
 	    $id = parent::save($params, $show_query);  
         return $id;

+ 33 - 22
main/inc/lib/internationalization.lib.php

@@ -562,14 +562,19 @@ function _api_get_timezone() {
  * Returns the given date as a DATETIME in UTC timezone. This function should be used before entering any date in the DB.
  *
  * @param mixed The date to be converted (can be a string supported by date() or a timestamp)
- * @return string The DATETIME in UTC to be inserted in the DB, or null if the format of the argument is not supported
+ * @param bool if the date is not correct return null instead of the current date
+ * @return string The DATETIME in UTC to be inserted in the DB, or null if the format of the argument is not supported 
  *
+ * @author Julio Montoya - Adding the 2nd parameter
  * @author Guillaume Viguier <guillaume.viguier@beeznest.com>
  */
-function api_get_utc_datetime($time = null) {
+function api_get_utc_datetime($time = null, $return_null_if_invalid_date = false) {
     $from_timezone = _api_get_timezone();
-    $to_timezone = 'UTC';
-    if (is_null($time)) {
+    $to_timezone = 'UTC';    
+    if (is_null($time) || empty($time) || $time == '0000-00-00 00:00:00') {
+        if ($return_null_if_invalid_date) {
+            return null;
+        }
         return gmdate('Y-m-d H:i:s');
     }
     // If time is a timestamp, return directly in utc
@@ -599,10 +604,11 @@ function api_get_utc_datetime($time = null) {
  *
  * @author Guillaume Viguier <guillaume.viguier@beeznest.com>
  */
-function api_get_local_time($time = null, $to_timezone = null, $from_timezone = null) {
+function api_get_local_time($time = null, $to_timezone = null, $from_timezone = null, $return_null_if_invalid_date = false) {
     if (!DATE_TIME_INSTALLED) {
         // This occurs when PHP < 5.2
-        if (is_null($time)) {
+        if (is_null($time) || empty($time) || $time == '0000-00-00 00:00:00') {
+            
             $time = time();
         }
         if (is_numeric($time)) {
@@ -620,7 +626,10 @@ function api_get_local_time($time = null, $to_timezone = null, $from_timezone =
         $to_timezone = _api_get_timezone();
     }
     // If time is a timestamp, convert it to a string
-    if (is_null($time)) {
+    if (is_null($time) || empty($time) || $time == '0000-00-00 00:00:00') {
+        if ($return_null_if_invalid_date) {
+            return null;
+        }
         $from_timezone = 'UTC';
         $time = gmdate('Y-m-d H:i:s');
     }
@@ -655,6 +664,23 @@ function api_strtotime($time, $timezone = null) {
     return $timestamp;
 }
 
+
+/**
+ * Converts a date to the right timezone and localizes it in the format given as an argument
+ * @param mixed The time to be converted
+ * @param mixed Format to be used (TIME_NO_SEC_FORMAT, DATE_FORMAT_SHORT, DATE_FORMAT_LONG, DATE_TIME_FORMAT_LONG)
+ * @param string Timezone to be converted from. If null, UTC will be assumed.
+ * @return string Converted and localized date
+ *
+ * @author Guillaume Viguier <guillaume.viguier@beeznest.com>
+ */
+function api_convert_and_format_date($time = null, $format = null, $from_timezone = null) {
+    // First, convert the datetime to the right timezone
+    $time = api_get_local_time($time, null, $from_timezone);
+    // Second, localize the date
+    return api_format_date($time, $format);
+}
+
 /**
  * Returns formated date/time, correspondent to a given language.
  * The given date should be in the timezone chosen by the administrator and/or user. Use api_get_local_time to get it.
@@ -922,21 +948,6 @@ function date_to_str_ago($date) {
     return $str;
 }
 
-/**
- * Converts a date to the right timezone and localizes it in the format given as an argument
- * @param mixed The time to be converted
- * @param mixed Format to be used (TIME_NO_SEC_FORMAT, DATE_FORMAT_SHORT, DATE_FORMAT_LONG, DATE_TIME_FORMAT_LONG)
- * @param string Timezone to be converted from. If null, UTC will be assumed.
- * @return string Converted and localized date
- *
- * @author Guillaume Viguier <guillaume.viguier@beeznest.com>
- */
-function api_convert_and_format_date($time = null, $format = null, $from_timezone = null) {
-    // First, convert the datetime to the right timezone
-    $time = api_get_local_time($time, null, $from_timezone);
-    // Second, localize the date
-    return api_format_date($time, $format);
-}
 
 /**
  * Returns an array of translated week days in short names.

+ 370 - 168
main/inc/lib/javascript/bootstrap/bootstrap.js

@@ -1,5 +1,5 @@
 /* ===================================================
- * bootstrap-transition.js v2.0.4
+ * bootstrap-transition.js v2.1.1
  * 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.1
  * 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.1
  * http://twitter.github.com/bootstrap/javascript.html#buttons
  * ============================================================
  * Copyright 2012 Twitter, Inc.
@@ -200,7 +199,7 @@
   }
 
   Button.prototype.toggle = function () {
-    var $parent = this.$element.parent('[data-toggle="buttons-radio"]')
+    var $parent = this.$element.closest('[data-toggle="buttons-radio"]')
 
     $parent && $parent
       .find('.active')
@@ -243,7 +242,7 @@
   })
 
 }(window.jQuery);/* ==========================================================
- * bootstrap-carousel.js v2.0.4
+ * bootstrap-carousel.js v2.1.1
  * 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.1
  * 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.1
  * 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 && /#/.test(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 form', 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.1
  * 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()
+
+        $(document).off('focusin.modal')
 
-        this.$element.removeClass('in')
+        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.1
  * 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.1
  * 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.1
  * 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.1
  * 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.1
  * 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)
       })
 
@@ -1708,8 +1797,8 @@
         .on('keypress', $.proxy(this.keypress, this))
         .on('keyup',    $.proxy(this.keyup, this))
 
-      if ($.browser.webkit || $.browser.msie) {
-        this.$element.on('keydown', $.proxy(this.keypress, this))
+      if ($.browser.chrome || $.browser.webkit || $.browser.msie) {
+        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.1
+ * 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);

File diff ditekan karena terlalu besar
+ 7 - 0
main/inc/lib/javascript/date/date.js


+ 85 - 0
main/inc/lib/javascript/datetimepicker/jquery-ui-sliderAccess.js

@@ -0,0 +1,85 @@
+/*
+ * jQuery UI Slider Access
+ * By: Trent Richardson [http://trentrichardson.com]
+ * Version 0.2
+ * Last Modified: 12/02/2011
+ * 
+ * Copyright 2011 Trent Richardson
+ * Dual licensed under the MIT and GPL licenses.
+ * http://trentrichardson.com/Impromptu/GPL-LICENSE.txt
+ * http://trentrichardson.com/Impromptu/MIT-LICENSE.txt
+ * 
+ */
+ (function($){
+
+	$.fn.extend({
+		sliderAccess: function(options){
+			options = options || {};
+			options.touchonly = options.touchonly !== undefined? options.touchonly : true; // by default only show it if touch device
+
+			if(options.touchonly === true && !("ontouchend" in document))
+				return $(this);
+				
+			return $(this).each(function(i,obj){
+						var $t = $(this),
+							o = $.extend({},{ 
+											where: 'after',
+											step: $t.slider('option','step'), 
+											upIcon: 'ui-icon-plus', 
+											downIcon: 'ui-icon-minus',
+											text: false,
+											upText: '+',
+											downText: '-',
+											buttonset: true,
+											buttonsetTag: 'span'
+										}, options),
+							$buttons = $('<'+ o.buttonsetTag +' class="ui-slider-access">'+
+											'<button data-icon="'+ o.downIcon +'" data-step="-'+ o.step +'">'+ o.downText +'</button>'+
+											'<button data-icon="'+ o.upIcon +'" data-step="'+ o.step +'">'+ o.upText +'</button>'+
+										'</'+ o.buttonsetTag +'>');
+
+						$buttons.children('button').each(function(j, jobj){
+							var $jt = $(this);
+							$jt.button({ 
+											text: o.text, 
+											icons: { primary: $jt.data('icon') }
+										})
+								.click(function(e){
+											var step = $jt.data('step'),
+												curr = $t.slider('value'),
+												newval = curr += step*1,
+												minval = $t.slider('option','min'),
+												maxval = $t.slider('option','max');
+
+											e.preventDefault();
+											
+											if(newval < minval || newval > maxval)
+												return;
+											
+											$t.slider('value', newval);
+
+											$t.slider("option", "slide").call($t, null, { value: newval });
+										});
+						});
+						
+						// before or after					
+						$t[o.where]($buttons);
+
+						if(o.buttonset){
+							$buttons.removeClass('ui-corner-right').removeClass('ui-corner-left').buttonset();
+							$buttons.eq(0).addClass('ui-corner-left');
+							$buttons.eq(1).addClass('ui-corner-right');
+						}
+
+						// adjust the width so we don't break the original layout
+						var bOuterWidth = $buttons.css({
+									marginLeft: (o.where == 'after'? 10:0), 
+									marginRight: (o.where == 'before'? 10:0)
+								}).outerWidth(true) + 5;
+						var tOuterWidth = $t.outerWidth(true);
+						$t.css('display','inline-block').width(tOuterWidth-bOuterWidth);
+					});		
+		}
+	});
+
+})(jQuery);

+ 6 - 0
main/inc/lib/javascript/datetimepicker/jquery-ui-timepicker-addon.css

@@ -0,0 +1,6 @@
+.ui-timepicker-div .ui-widget-header { margin-bottom: 8px; }
+.ui-timepicker-div dl { text-align: left; }
+.ui-timepicker-div dl dt { height: 25px; margin-bottom: -25px; }
+.ui-timepicker-div dl dd { margin: 0 10px 10px 65px; }
+.ui-timepicker-div td { font-size: 90%; }
+.ui-tpicker-grid-label { background: none; border: none; margin: 0; padding: 0; }

+ 1530 - 0
main/inc/lib/javascript/datetimepicker/jquery-ui-timepicker-addon.js

@@ -0,0 +1,1530 @@
+/*
+* jQuery timepicker addon
+* By: Trent Richardson [http://trentrichardson.com]
+* Version 1.0.1
+* Last Modified: 07/01/2012
+*
+* Copyright 2012 Trent Richardson
+* You may use this project under MIT or GPL licenses.
+* http://trentrichardson.com/Impromptu/GPL-LICENSE.txt
+* http://trentrichardson.com/Impromptu/MIT-LICENSE.txt
+*
+* HERES THE CSS:
+* .ui-timepicker-div .ui-widget-header { margin-bottom: 8px; }
+* .ui-timepicker-div dl { text-align: left; }
+* .ui-timepicker-div dl dt { height: 25px; margin-bottom: -25px; }
+* .ui-timepicker-div dl dd { margin: 0 10px 10px 65px; }
+* .ui-timepicker-div td { font-size: 90%; }
+* .ui-tpicker-grid-label { background: none; border: none; margin: 0; padding: 0; }
+*/
+
+/*jslint evil: true, maxlen: 300, white: false, undef: false, nomen: false, onevar: false */
+
+(function($) {
+
+// Prevent "Uncaught RangeError: Maximum call stack size exceeded"
+$.ui.timepicker = $.ui.timepicker || {};
+if ($.ui.timepicker.version) {
+	return;
+}
+
+$.extend($.ui, { timepicker: { version: "1.0.1" } });
+
+/* Time picker manager.
+   Use the singleton instance of this class, $.timepicker, to interact with the time picker.
+   Settings for (groups of) time pickers are maintained in an instance object,
+   allowing multiple different settings on the same page. */
+
+function Timepicker() {
+	this.regional = []; // Available regional settings, indexed by language code
+	this.regional[''] = { // Default regional settings
+		currentText: 'Now',
+		closeText: 'Done',
+		ampm: false,
+		amNames: ['AM', 'A'],
+		pmNames: ['PM', 'P'],
+		timeFormat: 'hh:mm tt',
+		timeSuffix: '',
+		timeOnlyTitle: 'Choose Time',
+		timeText: 'Time',
+		hourText: 'Hour',
+		minuteText: 'Minute',
+		secondText: 'Second',
+		millisecText: 'Millisecond',
+		timezoneText: 'Time Zone'
+	};
+	this._defaults = { // Global defaults for all the datetime picker instances
+		showButtonPanel: true,
+		timeOnly: false,
+		showHour: true,
+		showMinute: true,
+		showSecond: false,
+		showMillisec: false,
+		showTimezone: false,
+		showTime: true,
+		stepHour: 1,
+		stepMinute: 1,
+		stepSecond: 1,
+		stepMillisec: 1,
+		hour: 0,
+		minute: 0,
+		second: 0,
+		millisec: 0,
+		timezone: null,
+		useLocalTimezone: false,
+		defaultTimezone: "+0000",
+		hourMin: 0,
+		minuteMin: 0,
+		secondMin: 0,
+		millisecMin: 0,
+		hourMax: 23,
+		minuteMax: 59,
+		secondMax: 59,
+		millisecMax: 999,
+		minDateTime: null,
+		maxDateTime: null,
+		onSelect: null,
+		hourGrid: 0,
+		minuteGrid: 0,
+		secondGrid: 0,
+		millisecGrid: 0,
+		alwaysSetTime: true,
+		separator: ' ',
+		altFieldTimeOnly: true,
+		showTimepicker: true,
+		timezoneIso8601: false,
+		timezoneList: null,
+		addSliderAccess: false,
+		sliderAccessArgs: null
+	};
+	$.extend(this._defaults, this.regional['']);
+}
+
+$.extend(Timepicker.prototype, {
+	$input: null,
+	$altInput: null,
+	$timeObj: null,
+	inst: null,
+	hour_slider: null,
+	minute_slider: null,
+	second_slider: null,
+	millisec_slider: null,
+	timezone_select: null,
+	hour: 0,
+	minute: 0,
+	second: 0,
+	millisec: 0,
+	timezone: null,
+	defaultTimezone: "+0000",
+	hourMinOriginal: null,
+	minuteMinOriginal: null,
+	secondMinOriginal: null,
+	millisecMinOriginal: null,
+	hourMaxOriginal: null,
+	minuteMaxOriginal: null,
+	secondMaxOriginal: null,
+	millisecMaxOriginal: null,
+	ampm: '',
+	formattedDate: '',
+	formattedTime: '',
+	formattedDateTime: '',
+	timezoneList: null,
+
+	/* Override the default settings for all instances of the time picker.
+	   @param  settings  object - the new settings to use as defaults (anonymous object)
+	   @return the manager object */
+	setDefaults: function(settings) {
+		extendRemove(this._defaults, settings || {});
+		return this;
+	},
+
+	//########################################################################
+	// Create a new Timepicker instance
+	//########################################################################
+	_newInst: function($input, o) {
+		var tp_inst = new Timepicker(),
+			inlineSettings = {};
+
+		for (var attrName in this._defaults) {
+			var attrValue = $input.attr('time:' + attrName);
+			if (attrValue) {
+				try {
+					inlineSettings[attrName] = eval(attrValue);
+				} catch (err) {
+					inlineSettings[attrName] = attrValue;
+				}
+			}
+		}
+		tp_inst._defaults = $.extend({}, this._defaults, inlineSettings, o, {
+			beforeShow: function(input, dp_inst) {
+				if ($.isFunction(o.beforeShow)) {
+					return o.beforeShow(input, dp_inst, tp_inst);
+                }
+			},
+			onChangeMonthYear: function(year, month, dp_inst) {
+				// Update the time as well : this prevents the time from disappearing from the $input field.
+				tp_inst._updateDateTime(dp_inst);
+				if ($.isFunction(o.onChangeMonthYear)) {
+					o.onChangeMonthYear.call($input[0], year, month, dp_inst, tp_inst);
+                }
+			},
+			onClose: function(dateText, dp_inst) {
+				if (tp_inst.timeDefined === true && $input.val() !== '') {
+					tp_inst._updateDateTime(dp_inst);
+                }
+				if ($.isFunction(o.onClose)) {
+					o.onClose.call($input[0], dateText, dp_inst, tp_inst);
+                }
+			},
+			timepicker: tp_inst // add timepicker as a property of datepicker: $.datepicker._get(dp_inst, 'timepicker');
+		});
+		tp_inst.amNames = $.map(tp_inst._defaults.amNames, function(val) { return val.toUpperCase(); });
+		tp_inst.pmNames = $.map(tp_inst._defaults.pmNames, function(val) { return val.toUpperCase(); });
+
+		if (tp_inst._defaults.timezoneList === null) {
+			var timezoneList = [];
+			for (var i = -11; i <= 12; i++) {
+				timezoneList.push((i >= 0 ? '+' : '-') + ('0' + Math.abs(i).toString()).slice(-2) + '00');
+            }
+			if (tp_inst._defaults.timezoneIso8601) {
+				timezoneList = $.map(timezoneList, function(val) {
+					return val == '+0000' ? 'Z' : (val.substring(0, 3) + ':' + val.substring(3));
+				});
+            }
+			tp_inst._defaults.timezoneList = timezoneList;
+		}
+
+		tp_inst.timezone = tp_inst._defaults.timezone;
+		tp_inst.hour = tp_inst._defaults.hour;
+		tp_inst.minute = tp_inst._defaults.minute;
+		tp_inst.second = tp_inst._defaults.second;
+		tp_inst.millisec = tp_inst._defaults.millisec;
+		tp_inst.ampm = '';
+		tp_inst.$input = $input;
+
+		if (o.altField) {
+			tp_inst.$altInput = $(o.altField)
+				.css({ cursor: 'pointer' })
+				.focus(function(){ $input.trigger("focus"); });
+        }
+
+		if(tp_inst._defaults.minDate===0 || tp_inst._defaults.minDateTime===0)
+		{
+			tp_inst._defaults.minDate=new Date();
+		}
+		if(tp_inst._defaults.maxDate===0 || tp_inst._defaults.maxDateTime===0)
+		{
+			tp_inst._defaults.maxDate=new Date();
+		}
+
+		// datepicker needs minDate/maxDate, timepicker needs minDateTime/maxDateTime..
+		if(tp_inst._defaults.minDate !== undefined && tp_inst._defaults.minDate instanceof Date) {
+			tp_inst._defaults.minDateTime = new Date(tp_inst._defaults.minDate.getTime());
+        }
+		if(tp_inst._defaults.minDateTime !== undefined && tp_inst._defaults.minDateTime instanceof Date) {
+			tp_inst._defaults.minDate = new Date(tp_inst._defaults.minDateTime.getTime());
+        }
+		if(tp_inst._defaults.maxDate !== undefined && tp_inst._defaults.maxDate instanceof Date) {
+			tp_inst._defaults.maxDateTime = new Date(tp_inst._defaults.maxDate.getTime());
+        }
+		if(tp_inst._defaults.maxDateTime !== undefined && tp_inst._defaults.maxDateTime instanceof Date) {
+			tp_inst._defaults.maxDate = new Date(tp_inst._defaults.maxDateTime.getTime());
+        }
+		return tp_inst;
+	},
+
+	//########################################################################
+	// add our sliders to the calendar
+	//########################################################################
+	_addTimePicker: function(dp_inst) {
+		var currDT = (this.$altInput && this._defaults.altFieldTimeOnly) ?
+				this.$input.val() + ' ' + this.$altInput.val() :
+				this.$input.val();
+
+		this.timeDefined = this._parseTime(currDT);
+		this._limitMinMaxDateTime(dp_inst, false);
+		this._injectTimePicker();
+	},
+
+	//########################################################################
+	// parse the time string from input value or _setTime
+	//########################################################################
+	_parseTime: function(timeString, withDate) {
+		if (!this.inst) {
+			this.inst = $.datepicker._getInst(this.$input[0]);
+		}
+		
+		if (withDate || !this._defaults.timeOnly) 
+		{
+			var dp_dateFormat = $.datepicker._get(this.inst, 'dateFormat');
+			try {
+				var parseRes = parseDateTimeInternal(dp_dateFormat, this._defaults.timeFormat, timeString, $.datepicker._getFormatConfig(this.inst), this._defaults);
+				if (!parseRes.timeObj) { return false; }
+				$.extend(this, parseRes.timeObj);
+			} catch (err)
+			{
+				return false;
+			}
+			return true;
+		}
+		else
+		{
+			var timeObj = $.datepicker.parseTime(this._defaults.timeFormat, timeString, this._defaults);
+			if(!timeObj) { return false; }
+			$.extend(this, timeObj);
+			return true;
+		}
+	},
+	
+	//########################################################################
+	// generate and inject html for timepicker into ui datepicker
+	//########################################################################
+	_injectTimePicker: function() {
+		var $dp = this.inst.dpDiv,
+			o = this._defaults,
+			tp_inst = this,
+			// Added by Peter Medeiros:
+			// - Figure out what the hour/minute/second max should be based on the step values.
+			// - Example: if stepMinute is 15, then minMax is 45.
+			hourMax = parseInt((o.hourMax - ((o.hourMax - o.hourMin) % o.stepHour)) ,10),
+			minMax  = parseInt((o.minuteMax - ((o.minuteMax - o.minuteMin) % o.stepMinute)) ,10),
+			secMax  = parseInt((o.secondMax - ((o.secondMax - o.secondMin) % o.stepSecond)) ,10),
+			millisecMax  = parseInt((o.millisecMax - ((o.millisecMax - o.millisecMin) % o.stepMillisec)) ,10),
+			dp_id = this.inst.id.toString().replace(/([^A-Za-z0-9_])/g, '');
+
+		// Prevent displaying twice
+		//if ($dp.find("div#ui-timepicker-div-"+ dp_id).length === 0) {
+		if ($dp.find("div#ui-timepicker-div-"+ dp_id).length === 0 && o.showTimepicker) {
+			var noDisplay = ' style="display:none;"',
+				html =	'<div class="ui-timepicker-div" id="ui-timepicker-div-' + dp_id + '"><dl>' +
+						'<dt class="ui_tpicker_time_label" id="ui_tpicker_time_label_' + dp_id + '"' +
+						((o.showTime) ? '' : noDisplay) + '>' + o.timeText + '</dt>' +
+						'<dd class="ui_tpicker_time" id="ui_tpicker_time_' + dp_id + '"' +
+						((o.showTime) ? '' : noDisplay) + '></dd>' +
+						'<dt class="ui_tpicker_hour_label" id="ui_tpicker_hour_label_' + dp_id + '"' +
+						((o.showHour) ? '' : noDisplay) + '>' + o.hourText + '</dt>',
+				hourGridSize = 0,
+				minuteGridSize = 0,
+				secondGridSize = 0,
+				millisecGridSize = 0,
+				size = null;
+
+            // Hours
+			html += '<dd class="ui_tpicker_hour"><div id="ui_tpicker_hour_' + dp_id + '"' +
+						((o.showHour) ? '' : noDisplay) + '></div>';
+			if (o.showHour && o.hourGrid > 0) {
+				html += '<div style="padding-left: 1px"><table class="ui-tpicker-grid-label"><tr>';
+
+				for (var h = o.hourMin; h <= hourMax; h += parseInt(o.hourGrid,10)) {
+					hourGridSize++;
+					var tmph = (o.ampm && h > 12) ? h-12 : h;
+					if (tmph < 10) { tmph = '0' + tmph; }
+					if (o.ampm) {
+						if (h === 0) {
+                            tmph = 12 +'a';
+                        } else {
+                            if (h < 12) { tmph += 'a'; }
+						    else { tmph += 'p'; }
+                        }
+					}
+					html += '<td>' + tmph + '</td>';
+				}
+
+				html += '</tr></table></div>';
+			}
+			html += '</dd>';
+
+			// Minutes
+			html += '<dt class="ui_tpicker_minute_label" id="ui_tpicker_minute_label_' + dp_id + '"' +
+					((o.showMinute) ? '' : noDisplay) + '>' + o.minuteText + '</dt>'+
+					'<dd class="ui_tpicker_minute"><div id="ui_tpicker_minute_' + dp_id + '"' +
+							((o.showMinute) ? '' : noDisplay) + '></div>';
+
+			if (o.showMinute && o.minuteGrid > 0) {
+				html += '<div style="padding-left: 1px"><table class="ui-tpicker-grid-label"><tr>';
+
+				for (var m = o.minuteMin; m <= minMax; m += parseInt(o.minuteGrid,10)) {
+					minuteGridSize++;
+					html += '<td>' + ((m < 10) ? '0' : '') + m + '</td>';
+				}
+
+				html += '</tr></table></div>';
+			}
+			html += '</dd>';
+
+			// Seconds
+			html += '<dt class="ui_tpicker_second_label" id="ui_tpicker_second_label_' + dp_id + '"' +
+					((o.showSecond) ? '' : noDisplay) + '>' + o.secondText + '</dt>'+
+					'<dd class="ui_tpicker_second"><div id="ui_tpicker_second_' + dp_id + '"'+
+							((o.showSecond) ? '' : noDisplay) + '></div>';
+
+			if (o.showSecond && o.secondGrid > 0) {
+				html += '<div style="padding-left: 1px"><table><tr>';
+
+				for (var s = o.secondMin; s <= secMax; s += parseInt(o.secondGrid,10)) {
+					secondGridSize++;
+					html += '<td>' + ((s < 10) ? '0' : '') + s + '</td>';
+				}
+
+				html += '</tr></table></div>';
+			}
+			html += '</dd>';
+
+			// Milliseconds
+			html += '<dt class="ui_tpicker_millisec_label" id="ui_tpicker_millisec_label_' + dp_id + '"' +
+					((o.showMillisec) ? '' : noDisplay) + '>' + o.millisecText + '</dt>'+
+					'<dd class="ui_tpicker_millisec"><div id="ui_tpicker_millisec_' + dp_id + '"'+
+							((o.showMillisec) ? '' : noDisplay) + '></div>';
+
+			if (o.showMillisec && o.millisecGrid > 0) {
+				html += '<div style="padding-left: 1px"><table><tr>';
+
+				for (var l = o.millisecMin; l <= millisecMax; l += parseInt(o.millisecGrid,10)) {
+					millisecGridSize++;
+					html += '<td>' + ((l < 10) ? '0' : '') + l + '</td>';
+				}
+
+				html += '</tr></table></div>';
+			}
+			html += '</dd>';
+
+			// Timezone
+			html += '<dt class="ui_tpicker_timezone_label" id="ui_tpicker_timezone_label_' + dp_id + '"' +
+					((o.showTimezone) ? '' : noDisplay) + '>' + o.timezoneText + '</dt>';
+			html += '<dd class="ui_tpicker_timezone" id="ui_tpicker_timezone_' + dp_id + '"'	+
+							((o.showTimezone) ? '' : noDisplay) + '></dd>';
+
+			html += '</dl></div>';
+			var $tp = $(html);
+
+				// if we only want time picker...
+			if (o.timeOnly === true) {
+				$tp.prepend(
+					'<div class="ui-widget-header ui-helper-clearfix ui-corner-all">' +
+						'<div class="ui-datepicker-title">' + o.timeOnlyTitle + '</div>' +
+					'</div>');
+				$dp.find('.ui-datepicker-header, .ui-datepicker-calendar').hide();
+			}
+
+			this.hour_slider = $tp.find('#ui_tpicker_hour_'+ dp_id).slider({
+				orientation: "horizontal",
+				value: this.hour,
+				min: o.hourMin,
+				max: hourMax,
+				step: o.stepHour,
+				slide: function(event, ui) {
+					tp_inst.hour_slider.slider( "option", "value", ui.value);
+					tp_inst._onTimeChange();
+				}
+			});
+
+
+			// Updated by Peter Medeiros:
+			// - Pass in Event and UI instance into slide function
+			this.minute_slider = $tp.find('#ui_tpicker_minute_'+ dp_id).slider({
+				orientation: "horizontal",
+				value: this.minute,
+				min: o.minuteMin,
+				max: minMax,
+				step: o.stepMinute,
+				slide: function(event, ui) {
+					tp_inst.minute_slider.slider( "option", "value", ui.value);
+					tp_inst._onTimeChange();
+				}
+			});
+
+			this.second_slider = $tp.find('#ui_tpicker_second_'+ dp_id).slider({
+				orientation: "horizontal",
+				value: this.second,
+				min: o.secondMin,
+				max: secMax,
+				step: o.stepSecond,
+				slide: function(event, ui) {
+					tp_inst.second_slider.slider( "option", "value", ui.value);
+					tp_inst._onTimeChange();
+				}
+			});
+
+			this.millisec_slider = $tp.find('#ui_tpicker_millisec_'+ dp_id).slider({
+				orientation: "horizontal",
+				value: this.millisec,
+				min: o.millisecMin,
+				max: millisecMax,
+				step: o.stepMillisec,
+				slide: function(event, ui) {
+					tp_inst.millisec_slider.slider( "option", "value", ui.value);
+					tp_inst._onTimeChange();
+				}
+			});
+
+			this.timezone_select = $tp.find('#ui_tpicker_timezone_'+ dp_id).append('<select></select>').find("select");
+			$.fn.append.apply(this.timezone_select,
+				$.map(o.timezoneList, function(val, idx) {
+					return $("<option />")
+						.val(typeof val == "object" ? val.value : val)
+						.text(typeof val == "object" ? val.label : val);
+				})
+			);
+			if (typeof(this.timezone) != "undefined" && this.timezone !== null && this.timezone !== "") {
+				var local_date = new Date(this.inst.selectedYear, this.inst.selectedMonth, this.inst.selectedDay, 12);
+				var local_timezone = timeZoneString(local_date);
+				if (local_timezone == this.timezone) {
+					selectLocalTimeZone(tp_inst);
+				} else {
+					this.timezone_select.val(this.timezone);
+				}
+			} else {
+				if (typeof(this.hour) != "undefined" && this.hour !== null && this.hour !== "") {
+					this.timezone_select.val(o.defaultTimezone);
+				} else {
+					selectLocalTimeZone(tp_inst);
+				}
+			}
+			this.timezone_select.change(function() {
+				tp_inst._defaults.useLocalTimezone = false;
+				tp_inst._onTimeChange();
+			});
+
+			// Add grid functionality
+			if (o.showHour && o.hourGrid > 0) {
+				size = 100 * hourGridSize * o.hourGrid / (hourMax - o.hourMin);
+
+				$tp.find(".ui_tpicker_hour table").css({
+					width: size + "%",
+					marginLeft: (size / (-2 * hourGridSize)) + "%",
+					borderCollapse: 'collapse'
+				}).find("td").each( function(index) {
+					$(this).click(function() {
+						var h = $(this).html();
+						if(o.ampm)	{
+							var ap = h.substring(2).toLowerCase(),
+								aph = parseInt(h.substring(0,2), 10);
+							if (ap == 'a') {
+								if (aph == 12) { h = 0; }
+								else { h = aph; }
+							} else if (aph == 12) { h = 12; }
+							else { h = aph + 12; }
+						}
+						tp_inst.hour_slider.slider("option", "value", h);
+						tp_inst._onTimeChange();
+						tp_inst._onSelectHandler();
+					}).css({
+						cursor: 'pointer',
+						width: (100 / hourGridSize) + '%',
+						textAlign: 'center',
+						overflow: 'hidden'
+					});
+				});
+			}
+
+			if (o.showMinute && o.minuteGrid > 0) {
+				size = 100 * minuteGridSize * o.minuteGrid / (minMax - o.minuteMin);
+				$tp.find(".ui_tpicker_minute table").css({
+					width: size + "%",
+					marginLeft: (size / (-2 * minuteGridSize)) + "%",
+					borderCollapse: 'collapse'
+				}).find("td").each(function(index) {
+					$(this).click(function() {
+						tp_inst.minute_slider.slider("option", "value", $(this).html());
+						tp_inst._onTimeChange();
+						tp_inst._onSelectHandler();
+					}).css({
+						cursor: 'pointer',
+						width: (100 / minuteGridSize) + '%',
+						textAlign: 'center',
+						overflow: 'hidden'
+					});
+				});
+			}
+
+			if (o.showSecond && o.secondGrid > 0) {
+				$tp.find(".ui_tpicker_second table").css({
+					width: size + "%",
+					marginLeft: (size / (-2 * secondGridSize)) + "%",
+					borderCollapse: 'collapse'
+				}).find("td").each(function(index) {
+					$(this).click(function() {
+						tp_inst.second_slider.slider("option", "value", $(this).html());
+						tp_inst._onTimeChange();
+						tp_inst._onSelectHandler();
+					}).css({
+						cursor: 'pointer',
+						width: (100 / secondGridSize) + '%',
+						textAlign: 'center',
+						overflow: 'hidden'
+					});
+				});
+			}
+
+			if (o.showMillisec && o.millisecGrid > 0) {
+				$tp.find(".ui_tpicker_millisec table").css({
+					width: size + "%",
+					marginLeft: (size / (-2 * millisecGridSize)) + "%",
+					borderCollapse: 'collapse'
+				}).find("td").each(function(index) {
+					$(this).click(function() {
+						tp_inst.millisec_slider.slider("option", "value", $(this).html());
+						tp_inst._onTimeChange();
+						tp_inst._onSelectHandler();
+					}).css({
+						cursor: 'pointer',
+						width: (100 / millisecGridSize) + '%',
+						textAlign: 'center',
+						overflow: 'hidden'
+					});
+				});
+			}
+
+			var $buttonPanel = $dp.find('.ui-datepicker-buttonpane');
+			if ($buttonPanel.length) { $buttonPanel.before($tp); }
+			else { $dp.append($tp); }
+
+			this.$timeObj = $tp.find('#ui_tpicker_time_'+ dp_id);
+
+			if (this.inst !== null) {
+				var timeDefined = this.timeDefined;
+				this._onTimeChange();
+				this.timeDefined = timeDefined;
+			}
+
+			//Emulate datepicker onSelect behavior. Call on slidestop.
+			var onSelectDelegate = function() {
+				tp_inst._onSelectHandler();
+			};
+			this.hour_slider.bind('slidestop',onSelectDelegate);
+			this.minute_slider.bind('slidestop',onSelectDelegate);
+			this.second_slider.bind('slidestop',onSelectDelegate);
+			this.millisec_slider.bind('slidestop',onSelectDelegate);
+
+			// slideAccess integration: http://trentrichardson.com/2011/11/11/jquery-ui-sliders-and-touch-accessibility/
+			if (this._defaults.addSliderAccess){
+				var sliderAccessArgs = this._defaults.sliderAccessArgs;
+				setTimeout(function(){ // fix for inline mode
+					if($tp.find('.ui-slider-access').length === 0){
+						$tp.find('.ui-slider:visible').sliderAccess(sliderAccessArgs);
+
+						// fix any grids since sliders are shorter
+						var sliderAccessWidth = $tp.find('.ui-slider-access:eq(0)').outerWidth(true);
+						if(sliderAccessWidth){
+							$tp.find('table:visible').each(function(){
+								var $g = $(this),
+									oldWidth = $g.outerWidth(),
+									oldMarginLeft = $g.css('marginLeft').toString().replace('%',''),
+									newWidth = oldWidth - sliderAccessWidth,
+									newMarginLeft = ((oldMarginLeft * newWidth)/oldWidth) + '%';
+
+								$g.css({ width: newWidth, marginLeft: newMarginLeft });
+							});
+						}
+					}
+				},0);
+			}
+			// end slideAccess integration
+
+		}
+	},
+
+	//########################################################################
+	// This function tries to limit the ability to go outside the
+	// min/max date range
+	//########################################################################
+	_limitMinMaxDateTime: function(dp_inst, adjustSliders){
+		var o = this._defaults,
+			dp_date = new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay);
+
+		if(!this._defaults.showTimepicker) { return; } // No time so nothing to check here
+
+		if($.datepicker._get(dp_inst, 'minDateTime') !== null && $.datepicker._get(dp_inst, 'minDateTime') !== undefined && dp_date){
+			var minDateTime = $.datepicker._get(dp_inst, 'minDateTime'),
+				minDateTimeDate = new Date(minDateTime.getFullYear(), minDateTime.getMonth(), minDateTime.getDate(), 0, 0, 0, 0);
+
+			if(this.hourMinOriginal === null || this.minuteMinOriginal === null || this.secondMinOriginal === null || this.millisecMinOriginal === null){
+				this.hourMinOriginal = o.hourMin;
+				this.minuteMinOriginal = o.minuteMin;
+				this.secondMinOriginal = o.secondMin;
+				this.millisecMinOriginal = o.millisecMin;
+			}
+
+			if(dp_inst.settings.timeOnly || minDateTimeDate.getTime() == dp_date.getTime()) {
+				this._defaults.hourMin = minDateTime.getHours();
+				if (this.hour <= this._defaults.hourMin) {
+					this.hour = this._defaults.hourMin;
+					this._defaults.minuteMin = minDateTime.getMinutes();
+					if (this.minute <= this._defaults.minuteMin) {
+						this.minute = this._defaults.minuteMin;
+						this._defaults.secondMin = minDateTime.getSeconds();
+					} else if (this.second <= this._defaults.secondMin){
+						this.second = this._defaults.secondMin;
+						this._defaults.millisecMin = minDateTime.getMilliseconds();
+					} else {
+						if(this.millisec < this._defaults.millisecMin) {
+							this.millisec = this._defaults.millisecMin;
+                        }
+						this._defaults.millisecMin = this.millisecMinOriginal;
+					}
+				} else {
+					this._defaults.minuteMin = this.minuteMinOriginal;
+					this._defaults.secondMin = this.secondMinOriginal;
+					this._defaults.millisecMin = this.millisecMinOriginal;
+				}
+			}else{
+				this._defaults.hourMin = this.hourMinOriginal;
+				this._defaults.minuteMin = this.minuteMinOriginal;
+				this._defaults.secondMin = this.secondMinOriginal;
+				this._defaults.millisecMin = this.millisecMinOriginal;
+			}
+		}
+
+		if($.datepicker._get(dp_inst, 'maxDateTime') !== null && $.datepicker._get(dp_inst, 'maxDateTime') !== undefined && dp_date){
+			var maxDateTime = $.datepicker._get(dp_inst, 'maxDateTime'),
+				maxDateTimeDate = new Date(maxDateTime.getFullYear(), maxDateTime.getMonth(), maxDateTime.getDate(), 0, 0, 0, 0);
+
+			if(this.hourMaxOriginal === null || this.minuteMaxOriginal === null || this.secondMaxOriginal === null){
+				this.hourMaxOriginal = o.hourMax;
+				this.minuteMaxOriginal = o.minuteMax;
+				this.secondMaxOriginal = o.secondMax;
+				this.millisecMaxOriginal = o.millisecMax;
+			}
+
+			if(dp_inst.settings.timeOnly || maxDateTimeDate.getTime() == dp_date.getTime()){
+				this._defaults.hourMax = maxDateTime.getHours();
+				if (this.hour >= this._defaults.hourMax) {
+					this.hour = this._defaults.hourMax;
+					this._defaults.minuteMax = maxDateTime.getMinutes();
+					if (this.minute >= this._defaults.minuteMax) {
+						this.minute = this._defaults.minuteMax;
+						this._defaults.secondMax = maxDateTime.getSeconds();
+					} else if (this.second >= this._defaults.secondMax) {
+						this.second = this._defaults.secondMax;
+						this._defaults.millisecMax = maxDateTime.getMilliseconds();
+					} else {
+						if(this.millisec > this._defaults.millisecMax) { this.millisec = this._defaults.millisecMax; }
+						this._defaults.millisecMax = this.millisecMaxOriginal;
+					}
+				} else {
+					this._defaults.minuteMax = this.minuteMaxOriginal;
+					this._defaults.secondMax = this.secondMaxOriginal;
+					this._defaults.millisecMax = this.millisecMaxOriginal;
+				}
+			}else{
+				this._defaults.hourMax = this.hourMaxOriginal;
+				this._defaults.minuteMax = this.minuteMaxOriginal;
+				this._defaults.secondMax = this.secondMaxOriginal;
+				this._defaults.millisecMax = this.millisecMaxOriginal;
+			}
+		}
+
+		if(adjustSliders !== undefined && adjustSliders === true){
+			var hourMax = parseInt((this._defaults.hourMax - ((this._defaults.hourMax - this._defaults.hourMin) % this._defaults.stepHour)) ,10),
+                minMax  = parseInt((this._defaults.minuteMax - ((this._defaults.minuteMax - this._defaults.minuteMin) % this._defaults.stepMinute)) ,10),
+                secMax  = parseInt((this._defaults.secondMax - ((this._defaults.secondMax - this._defaults.secondMin) % this._defaults.stepSecond)) ,10),
+				millisecMax  = parseInt((this._defaults.millisecMax - ((this._defaults.millisecMax - this._defaults.millisecMin) % this._defaults.stepMillisec)) ,10);
+
+			if(this.hour_slider) {
+				this.hour_slider.slider("option", { min: this._defaults.hourMin, max: hourMax }).slider('value', this.hour);
+            }
+			if(this.minute_slider) {
+				this.minute_slider.slider("option", { min: this._defaults.minuteMin, max: minMax }).slider('value', this.minute);
+            }
+			if(this.second_slider){
+				this.second_slider.slider("option", { min: this._defaults.secondMin, max: secMax }).slider('value', this.second);
+            }
+			if(this.millisec_slider) {
+				this.millisec_slider.slider("option", { min: this._defaults.millisecMin, max: millisecMax }).slider('value', this.millisec);
+            }
+		}
+
+	},
+
+
+	//########################################################################
+	// when a slider moves, set the internal time...
+	// on time change is also called when the time is updated in the text field
+	//########################################################################
+	_onTimeChange: function() {
+		var hour   = (this.hour_slider) ? this.hour_slider.slider('value') : false,
+			minute = (this.minute_slider) ? this.minute_slider.slider('value') : false,
+			second = (this.second_slider) ? this.second_slider.slider('value') : false,
+			millisec = (this.millisec_slider) ? this.millisec_slider.slider('value') : false,
+			timezone = (this.timezone_select) ? this.timezone_select.val() : false,
+			o = this._defaults;
+
+		if (typeof(hour) == 'object') { hour = false; }
+		if (typeof(minute) == 'object') { minute = false; }
+		if (typeof(second) == 'object') { second = false; }
+		if (typeof(millisec) == 'object') { millisec = false; }
+		if (typeof(timezone) == 'object') { timezone = false; }
+
+		if (hour !== false) { hour = parseInt(hour,10); }
+		if (minute !== false) { minute = parseInt(minute,10); }
+		if (second !== false) { second = parseInt(second,10); }
+		if (millisec !== false) { millisec = parseInt(millisec,10); }
+
+		var ampm = o[hour < 12 ? 'amNames' : 'pmNames'][0];
+
+		// If the update was done in the input field, the input field should not be updated.
+		// If the update was done using the sliders, update the input field.
+		var hasChanged = (hour != this.hour || minute != this.minute ||
+				second != this.second || millisec != this.millisec ||
+				(this.ampm.length > 0 &&
+				    (hour < 12) != ($.inArray(this.ampm.toUpperCase(), this.amNames) !== -1)) ||
+				timezone != this.timezone);
+
+		if (hasChanged) {
+
+			if (hour !== false) { this.hour = hour; }
+			if (minute !== false) { this.minute = minute; }
+			if (second !== false) { this.second = second; }
+			if (millisec !== false) { this.millisec = millisec; }
+			if (timezone !== false) { this.timezone = timezone; }
+
+			if (!this.inst) { this.inst = $.datepicker._getInst(this.$input[0]); }
+
+			this._limitMinMaxDateTime(this.inst, true);
+		}
+		if (o.ampm) { this.ampm = ampm; }
+
+		//this._formatTime();
+		this.formattedTime = $.datepicker.formatTime(this._defaults.timeFormat, this, this._defaults);
+		if (this.$timeObj) { this.$timeObj.text(this.formattedTime + o.timeSuffix); }
+		this.timeDefined = true;
+		if (hasChanged) { this._updateDateTime(); }
+	},
+
+	//########################################################################
+	// call custom onSelect.
+	// bind to sliders slidestop, and grid click.
+	//########################################################################
+	_onSelectHandler: function() {
+		var onSelect = this._defaults.onSelect;
+		var inputEl = this.$input ? this.$input[0] : null;
+		if (onSelect && inputEl) {
+			onSelect.apply(inputEl, [this.formattedDateTime, this]);
+		}
+	},
+
+	//########################################################################
+	// left for any backwards compatibility
+	//########################################################################
+	_formatTime: function(time, format) {
+		time = time || { hour: this.hour, minute: this.minute, second: this.second, millisec: this.millisec, ampm: this.ampm, timezone: this.timezone };
+		var tmptime = (format || this._defaults.timeFormat).toString();
+
+		tmptime = $.datepicker.formatTime(tmptime, time, this._defaults);
+
+		if (arguments.length) { return tmptime; }
+		else { this.formattedTime = tmptime; }
+	},
+
+	//########################################################################
+	// update our input with the new date time..
+	//########################################################################
+	_updateDateTime: function(dp_inst) {
+		dp_inst = this.inst || dp_inst;
+		var dt = $.datepicker._daylightSavingAdjust(new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)),
+			dateFmt = $.datepicker._get(dp_inst, 'dateFormat'),
+			formatCfg = $.datepicker._getFormatConfig(dp_inst),
+			timeAvailable = dt !== null && this.timeDefined;
+		this.formattedDate = $.datepicker.formatDate(dateFmt, (dt === null ? new Date() : dt), formatCfg);
+		var formattedDateTime = this.formattedDate;
+		// remove following lines to force every changes in date picker to change the input value
+		// Bug descriptions: when an input field has a default value, and click on the field to pop up the date picker. 
+		// If the user manually empty the value in the input field, the date picker will never change selected value.
+		//if (dp_inst.lastVal !== undefined && (dp_inst.lastVal.length > 0 && this.$input.val().length === 0)) {
+		//	return;
+        //}
+
+		if (this._defaults.timeOnly === true) {
+			formattedDateTime = this.formattedTime;
+		} else if (this._defaults.timeOnly !== true && (this._defaults.alwaysSetTime || timeAvailable)) {
+			formattedDateTime += this._defaults.separator + this.formattedTime + this._defaults.timeSuffix;
+		}
+
+		this.formattedDateTime = formattedDateTime;
+
+		if(!this._defaults.showTimepicker) {
+			this.$input.val(this.formattedDate);
+		} else if (this.$altInput && this._defaults.altFieldTimeOnly === true) {
+			this.$altInput.val(this.formattedTime);
+			this.$input.val(this.formattedDate);
+		} else if(this.$altInput) {
+			this.$altInput.val(formattedDateTime);
+			this.$input.val(formattedDateTime);
+		} else {
+			this.$input.val(formattedDateTime);
+		}
+
+		this.$input.trigger("change");
+	}
+
+});
+
+$.fn.extend({
+	//########################################################################
+	// shorthand just to use timepicker..
+	//########################################################################
+	timepicker: function(o) {
+		o = o || {};
+		var tmp_args = arguments;
+
+		if (typeof o == 'object') { tmp_args[0] = $.extend(o, { timeOnly: true }); }
+
+		return $(this).each(function() {
+			$.fn.datetimepicker.apply($(this), tmp_args);
+		});
+	},
+
+	//########################################################################
+	// extend timepicker to datepicker
+	//########################################################################
+	datetimepicker: function(o) {
+		o = o || {};
+		var tmp_args = arguments;
+
+		if (typeof(o) == 'string'){
+			if(o == 'getDate') {
+				return $.fn.datepicker.apply($(this[0]), tmp_args);
+            }
+			else {
+				return this.each(function() {
+					var $t = $(this);
+					$t.datepicker.apply($t, tmp_args);
+				});
+            }
+		}
+		else {
+			return this.each(function() {
+				var $t = $(this);
+				$t.datepicker($.timepicker._newInst($t, o)._defaults);
+			});
+        }
+	}
+});
+
+$.datepicker.parseDateTime = function(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) {
+	var parseRes = parseDateTimeInternal(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings);
+	if (parseRes.timeObj)
+	{
+		var t = parseRes.timeObj;
+		parseRes.date.setHours(t.hour, t.minute, t.second, t.millisec);
+	}
+
+	return parseRes.date;
+};
+
+$.datepicker.parseTime = function(timeFormat, timeString, options) {
+	
+	//########################################################################
+	// pattern for standard and localized AM/PM markers
+	//########################################################################
+	var getPatternAmpm = function(amNames, pmNames) {
+		var markers = [];
+		if (amNames) {
+			$.merge(markers, amNames);
+        }
+		if (pmNames) {
+			$.merge(markers, pmNames);
+        }
+		markers = $.map(markers, function(val) { return val.replace(/[.*+?|()\[\]{}\\]/g, '\\$&'); });
+		return '(' + markers.join('|') + ')?';
+	};
+   
+	//########################################################################
+	// figure out position of time elements.. cause js cant do named captures
+	//########################################################################
+	var getFormatPositions = function( timeFormat ) {
+		var finds = timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|t{1,2}|z)/g),
+			orders = { h: -1, m: -1, s: -1, l: -1, t: -1, z: -1 };
+
+		if (finds) {
+			for (var i = 0; i < finds.length; i++) {
+				if (orders[finds[i].toString().charAt(0)] == -1) {
+					orders[finds[i].toString().charAt(0)] = i + 1;
+                }
+            }
+        }
+		return orders;
+	};
+    
+	var o = extendRemove(extendRemove({}, $.timepicker._defaults), options || {});
+    
+	var regstr = '^' + timeFormat.toString()
+			.replace(/h{1,2}/ig, '(\\d?\\d)')
+			.replace(/m{1,2}/ig, '(\\d?\\d)')
+			.replace(/s{1,2}/ig, '(\\d?\\d)')
+			.replace(/l{1}/ig, '(\\d?\\d?\\d)')
+			.replace(/t{1,2}/ig, getPatternAmpm(o.amNames, o.pmNames))
+			.replace(/z{1}/ig, '(z|[-+]\\d\\d:?\\d\\d)?')
+			.replace(/\s/g, '\\s?') + o.timeSuffix + '$',
+		order = getFormatPositions(timeFormat),
+		ampm = '',
+		treg;
+
+	treg = timeString.match(new RegExp(regstr, 'i'));
+
+	var resTime = {hour: 0, minute: 0, second: 0, millisec: 0};
+    
+	if (treg) {
+		if (order.t !== -1) {
+			if (treg[order.t] === undefined || treg[order.t].length === 0) {
+				ampm = '';
+				resTime.ampm = '';
+			} else {
+				ampm = $.inArray(treg[order.t], o.amNames) !== -1 ? 'AM' : 'PM';
+				resTime.ampm = o[ampm == 'AM' ? 'amNames' : 'pmNames'][0];
+			}
+		}
+
+		if (order.h !== -1) {
+			if (ampm == 'AM' && treg[order.h] == '12') {
+				resTime.hour = 0; // 12am = 0 hour
+			} else {
+                if (ampm == 'PM' && treg[order.h] != '12') {
+                    resTime.hour = parseInt(treg[order.h],10) + 12; // 12pm = 12 hour, any other pm = hour + 12
+                }
+                else { resTime.hour = Number(treg[order.h]); }
+            }
+		}
+
+		if (order.m !== -1) { resTime.minute = Number(treg[order.m]); }
+		if (order.s !== -1) { resTime.second = Number(treg[order.s]); }
+		if (order.l !== -1) { resTime.millisec = Number(treg[order.l]); }
+		if (order.z !== -1 && treg[order.z] !== undefined) {
+			var tz = treg[order.z].toUpperCase();
+			switch (tz.length) {
+				case 1:	// Z
+					tz = o.timezoneIso8601 ? 'Z' : '+0000';
+					break;
+				case 5:	// +hhmm
+					if (o.timezoneIso8601) {
+						tz = tz.substring(1) == '0000' ?
+							'Z' :
+							tz.substring(0, 3) + ':' + tz.substring(3);
+                    }
+					break;
+				case 6:	// +hh:mm
+					if (!o.timezoneIso8601) {
+						tz = tz == 'Z' || tz.substring(1) == '00:00' ?
+							'+0000' :
+							tz.replace(/:/, '');
+					} else {
+                        if (tz.substring(1) == '00:00') {
+                            tz = 'Z';
+                        }
+                    }
+					break;
+			}
+			resTime.timezone = tz;
+		}
+
+
+		return resTime;
+	}
+
+	return false;
+};
+
+//########################################################################
+// format the time all pretty...
+// format = string format of the time
+// time = a {}, not a Date() for timezones
+// options = essentially the regional[].. amNames, pmNames, ampm
+//########################################################################
+$.datepicker.formatTime = function(format, time, options) {
+	options = options || {};
+	options = $.extend($.timepicker._defaults, options);
+	time = $.extend({hour:0, minute:0, second:0, millisec:0, timezone:'+0000'}, time);
+
+	var tmptime = format;
+	var ampmName = options.amNames[0];
+
+	var hour = parseInt(time.hour, 10);
+	if (options.ampm) {
+		if (hour > 11){
+			ampmName = options.pmNames[0];
+			if(hour > 12) {
+				hour = hour % 12;
+            }
+		}
+		if (hour === 0) {
+			hour = 12;
+        }
+	}
+	tmptime = tmptime.replace(/(?:hh?|mm?|ss?|[tT]{1,2}|[lz])/g, function(match) {
+		switch (match.toLowerCase()) {
+			case 'hh': return ('0' + hour).slice(-2);
+			case 'h':  return hour;
+			case 'mm': return ('0' + time.minute).slice(-2);
+			case 'm':  return time.minute;
+			case 'ss': return ('0' + time.second).slice(-2);
+			case 's':  return time.second;
+			case 'l':  return ('00' + time.millisec).slice(-3);
+			case 'z':  return time.timezone;
+			case 't': case 'tt':
+				if (options.ampm) {
+					if (match.length == 1) {
+						ampmName = ampmName.charAt(0);
+                    }
+					return match.charAt(0) == 'T' ? ampmName.toUpperCase() : ampmName.toLowerCase();
+				}
+				return '';
+		}
+	});
+
+	tmptime = $.trim(tmptime);
+	return tmptime;
+};
+
+//########################################################################
+// the bad hack :/ override datepicker so it doesnt close on select
+// inspired: http://stackoverflow.com/questions/1252512/jquery-datepicker-prevent-closing-picker-when-clicking-a-date/1762378#1762378
+//########################################################################
+$.datepicker._base_selectDate = $.datepicker._selectDate;
+$.datepicker._selectDate = function (id, dateStr) {
+	var inst = this._getInst($(id)[0]),
+		tp_inst = this._get(inst, 'timepicker');
+
+	if (tp_inst) {
+		tp_inst._limitMinMaxDateTime(inst, true);
+		inst.inline = inst.stay_open = true;
+		//This way the onSelect handler called from calendarpicker get the full dateTime
+		this._base_selectDate(id, dateStr);
+		inst.inline = inst.stay_open = false;
+		this._notifyChange(inst);
+		this._updateDatepicker(inst);
+	}
+	else { this._base_selectDate(id, dateStr); }
+};
+
+//#############################################################################################
+// second bad hack :/ override datepicker so it triggers an event when changing the input field
+// and does not redraw the datepicker on every selectDate event
+//#############################################################################################
+$.datepicker._base_updateDatepicker = $.datepicker._updateDatepicker;
+$.datepicker._updateDatepicker = function(inst) {
+
+	// don't popup the datepicker if there is another instance already opened
+	var input = inst.input[0];
+	if($.datepicker._curInst &&
+	   $.datepicker._curInst != inst &&
+	   $.datepicker._datepickerShowing &&
+	   $.datepicker._lastInput != input) {
+		return;
+	}
+
+	if (typeof(inst.stay_open) !== 'boolean' || inst.stay_open === false) {
+
+		this._base_updateDatepicker(inst);
+
+		// Reload the time control when changing something in the input text field.
+		var tp_inst = this._get(inst, 'timepicker');
+		if(tp_inst) {
+			tp_inst._addTimePicker(inst);
+
+			if (tp_inst._defaults.useLocalTimezone) { //checks daylight saving with the new date.
+				var date = new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay, 12);
+				selectLocalTimeZone(tp_inst, date);
+				tp_inst._onTimeChange();
+			}
+		}
+	}
+};
+
+//#######################################################################################
+// third bad hack :/ override datepicker so it allows spaces and colon in the input field
+//#######################################################################################
+$.datepicker._base_doKeyPress = $.datepicker._doKeyPress;
+$.datepicker._doKeyPress = function(event) {
+	var inst = $.datepicker._getInst(event.target),
+		tp_inst = $.datepicker._get(inst, 'timepicker');
+
+	if (tp_inst) {
+		if ($.datepicker._get(inst, 'constrainInput')) {
+			var ampm = tp_inst._defaults.ampm,
+				dateChars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')),
+				datetimeChars = tp_inst._defaults.timeFormat.toString()
+								.replace(/[hms]/g, '')
+								.replace(/TT/g, ampm ? 'APM' : '')
+								.replace(/Tt/g, ampm ? 'AaPpMm' : '')
+								.replace(/tT/g, ampm ? 'AaPpMm' : '')
+								.replace(/T/g, ampm ? 'AP' : '')
+								.replace(/tt/g, ampm ? 'apm' : '')
+								.replace(/t/g, ampm ? 'ap' : '') +
+								" " +
+								tp_inst._defaults.separator +
+								tp_inst._defaults.timeSuffix +
+								(tp_inst._defaults.showTimezone ? tp_inst._defaults.timezoneList.join('') : '') +
+								(tp_inst._defaults.amNames.join('')) +
+								(tp_inst._defaults.pmNames.join('')) +
+								dateChars,
+				chr = String.fromCharCode(event.charCode === undefined ? event.keyCode : event.charCode);
+			return event.ctrlKey || (chr < ' ' || !dateChars || datetimeChars.indexOf(chr) > -1);
+		}
+	}
+
+	return $.datepicker._base_doKeyPress(event);
+};
+
+//#######################################################################################
+// Override key up event to sync manual input changes.
+//#######################################################################################
+$.datepicker._base_doKeyUp = $.datepicker._doKeyUp;
+$.datepicker._doKeyUp = function (event) {
+	var inst = $.datepicker._getInst(event.target),
+		tp_inst = $.datepicker._get(inst, 'timepicker');
+
+	if (tp_inst) {
+		if (tp_inst._defaults.timeOnly && (inst.input.val() != inst.lastVal)) {
+			try {
+				$.datepicker._updateDatepicker(inst);
+			}
+			catch (err) {
+				$.datepicker.log(err);
+			}
+		}
+	}
+
+	return $.datepicker._base_doKeyUp(event);
+};
+
+//#######################################################################################
+// override "Today" button to also grab the time.
+//#######################################################################################
+$.datepicker._base_gotoToday = $.datepicker._gotoToday;
+$.datepicker._gotoToday = function(id) {
+	var inst = this._getInst($(id)[0]),
+		$dp = inst.dpDiv;
+	this._base_gotoToday(id);
+	var tp_inst = this._get(inst, 'timepicker');
+	selectLocalTimeZone(tp_inst);
+	var now = new Date();
+	this._setTime(inst, now);
+	$( '.ui-datepicker-today', $dp).click();
+};
+
+//#######################################################################################
+// Disable & enable the Time in the datetimepicker
+//#######################################################################################
+$.datepicker._disableTimepickerDatepicker = function(target) {
+	var inst = this._getInst(target);
+    if (!inst) { return; }
+    
+	var tp_inst = this._get(inst, 'timepicker');
+	$(target).datepicker('getDate'); // Init selected[Year|Month|Day]
+	if (tp_inst) {
+		tp_inst._defaults.showTimepicker = false;
+		tp_inst._updateDateTime(inst);
+	}
+};
+
+$.datepicker._enableTimepickerDatepicker = function(target) {
+	var inst = this._getInst(target);
+    if (!inst) { return; }
+    
+	var tp_inst = this._get(inst, 'timepicker');
+	$(target).datepicker('getDate'); // Init selected[Year|Month|Day]
+	if (tp_inst) {
+		tp_inst._defaults.showTimepicker = true;
+		tp_inst._addTimePicker(inst); // Could be disabled on page load
+		tp_inst._updateDateTime(inst);
+	}
+};
+
+//#######################################################################################
+// Create our own set time function
+//#######################################################################################
+$.datepicker._setTime = function(inst, date) {
+	var tp_inst = this._get(inst, 'timepicker');
+	if (tp_inst) {
+		var defaults = tp_inst._defaults,
+			// calling _setTime with no date sets time to defaults
+			hour = date ? date.getHours() : defaults.hour,
+			minute = date ? date.getMinutes() : defaults.minute,
+			second = date ? date.getSeconds() : defaults.second,
+			millisec = date ? date.getMilliseconds() : defaults.millisec;
+		//check if within min/max times..
+		// correct check if within min/max times. 	
+		// Rewritten by Scott A. Woodward
+		var hourEq = hour === defaults.hourMin,
+			minuteEq = minute === defaults.minuteMin,
+			secondEq = second === defaults.secondMin;
+		var reset = false;
+		if(hour < defaults.hourMin || hour > defaults.hourMax)  
+			reset = true;
+		else if( (minute < defaults.minuteMin || minute > defaults.minuteMax) && hourEq)
+			reset = true;
+		else if( (second < defaults.secondMin || second > defaults.secondMax ) && hourEq && minuteEq)
+			reset = true;
+		else if( (millisec < defaults.millisecMin || millisec > defaults.millisecMax) && hourEq && minuteEq && secondEq)
+			reset = true;
+		if(reset) {
+			hour = defaults.hourMin;
+			minute = defaults.minuteMin;
+			second = defaults.secondMin;
+			millisec = defaults.millisecMin;
+		}
+		tp_inst.hour = hour;
+		tp_inst.minute = minute;
+		tp_inst.second = second;
+		tp_inst.millisec = millisec;
+		if (tp_inst.hour_slider) tp_inst.hour_slider.slider('value', hour);
+		if (tp_inst.minute_slider) tp_inst.minute_slider.slider('value', minute);
+		if (tp_inst.second_slider) tp_inst.second_slider.slider('value', second);
+		if (tp_inst.millisec_slider) tp_inst.millisec_slider.slider('value', millisec);
+
+		tp_inst._onTimeChange();
+		tp_inst._updateDateTime(inst);
+	}
+};
+
+//#######################################################################################
+// Create new public method to set only time, callable as $().datepicker('setTime', date)
+//#######################################################################################
+$.datepicker._setTimeDatepicker = function(target, date, withDate) {
+	var inst = this._getInst(target);
+    if (!inst) { return; }
+    
+	var tp_inst = this._get(inst, 'timepicker');
+    
+	if (tp_inst) {
+		this._setDateFromField(inst);
+		var tp_date;
+		if (date) {
+			if (typeof date == "string") {
+				tp_inst._parseTime(date, withDate);
+				tp_date = new Date();
+				tp_date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec);
+			}
+			else { tp_date = new Date(date.getTime()); }
+			if (tp_date.toString() == 'Invalid Date') { tp_date = undefined; }
+			this._setTime(inst, tp_date);
+		}
+	}
+
+};
+
+//#######################################################################################
+// override setDate() to allow setting time too within Date object
+//#######################################################################################
+$.datepicker._base_setDateDatepicker = $.datepicker._setDateDatepicker;
+$.datepicker._setDateDatepicker = function(target, date) {
+	var inst = this._getInst(target);
+    if (!inst) { return; }
+    
+	var tp_date = (date instanceof Date) ? new Date(date.getTime()) : date;
+
+	this._updateDatepicker(inst);
+	this._base_setDateDatepicker.apply(this, arguments);
+	this._setTimeDatepicker(target, tp_date, true);
+};
+
+//#######################################################################################
+// override getDate() to allow getting time too within Date object
+//#######################################################################################
+$.datepicker._base_getDateDatepicker = $.datepicker._getDateDatepicker;
+$.datepicker._getDateDatepicker = function(target, noDefault) {
+	var inst = this._getInst(target);
+    if (!inst) { return; }
+    
+    var tp_inst = this._get(inst, 'timepicker');
+
+	if (tp_inst) {
+		this._setDateFromField(inst, noDefault);
+		var date = this._getDate(inst);
+		if (date && tp_inst._parseTime($(target).val(), tp_inst.timeOnly)) { date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec); }
+		return date;
+	}
+	return this._base_getDateDatepicker(target, noDefault);
+};
+
+//#######################################################################################
+// override parseDate() because UI 1.8.14 throws an error about "Extra characters"
+// An option in datapicker to ignore extra format characters would be nicer.
+//#######################################################################################
+$.datepicker._base_parseDate = $.datepicker.parseDate;
+$.datepicker.parseDate = function(format, value, settings) {
+    var splitRes = splitDateTime(format, value, settings);
+	return $.datepicker._base_parseDate(format, splitRes[0], settings);
+};
+
+//#######################################################################################
+// override formatDate to set date with time to the input
+//#######################################################################################
+$.datepicker._base_formatDate = $.datepicker._formatDate;
+$.datepicker._formatDate = function(inst, day, month, year){
+	var tp_inst = this._get(inst, 'timepicker');
+	if(tp_inst) {
+		tp_inst._updateDateTime(inst);
+		return tp_inst.$input.val();
+	}
+	return this._base_formatDate(inst);
+};
+
+//#######################################################################################
+// override options setter to add time to maxDate(Time) and minDate(Time). MaxDate
+//#######################################################################################
+$.datepicker._base_optionDatepicker = $.datepicker._optionDatepicker;
+$.datepicker._optionDatepicker = function(target, name, value) {
+	var inst = this._getInst(target);
+    if (!inst) { return null; }
+    
+	var tp_inst = this._get(inst, 'timepicker');
+	if (tp_inst) {
+		var min = null, max = null, onselect = null;
+		if (typeof name == 'string') { // if min/max was set with the string
+			if (name === 'minDate' || name === 'minDateTime' ) {
+				min = value;
+            }
+			else {
+                if (name === 'maxDate' || name === 'maxDateTime') {
+                    max = value;
+                }
+                else {
+                    if (name === 'onSelect') {
+                        onselect = value;
+                    }
+                }
+            }
+		} else {
+            if (typeof name == 'object') { //if min/max was set with the JSON
+                if (name.minDate) {
+                    min = name.minDate;
+                } else {
+                    if (name.minDateTime) {
+                        min = name.minDateTime;
+                    } else {
+                        if (name.maxDate) {
+                            max = name.maxDate;
+                        } else {
+                            if (name.maxDateTime) {
+                                max = name.maxDateTime;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+		if(min) { //if min was set
+			if (min === 0) {
+				min = new Date();
+            } else {
+				min = new Date(min);
+            }
+
+			tp_inst._defaults.minDate = min;
+			tp_inst._defaults.minDateTime = min;
+		} else if (max) { //if max was set
+			if(max===0) {
+				max=new Date();
+            } else {
+				max= new Date(max);
+            }
+			tp_inst._defaults.maxDate = max;
+			tp_inst._defaults.maxDateTime = max;
+		} else if (onselect) {
+			tp_inst._defaults.onSelect = onselect;
+        }
+	}
+	if (value === undefined) {
+		return this._base_optionDatepicker(target, name);
+    }
+	return this._base_optionDatepicker(target, name, value);
+};
+
+//#######################################################################################
+// jQuery extend now ignores nulls!
+//#######################################################################################
+function extendRemove(target, props) {
+	$.extend(target, props);
+	for (var name in props) {
+		if (props[name] === null || props[name] === undefined) {
+			target[name] = props[name];
+        }
+    }
+	return target;
+}
+
+//#######################################################################################
+// Splits datetime string into date ans time substrings.
+// Throws exception when date can't be parsed
+// If only date is present, time substring eill be '' 
+//#######################################################################################
+var splitDateTime = function(dateFormat, dateTimeString, dateSettings)
+{
+	try {
+		var date = $.datepicker._base_parseDate(dateFormat, dateTimeString, dateSettings);
+	} catch (err) {
+		if (err.indexOf(":") >= 0) {
+			// Hack!  The error message ends with a colon, a space, and
+			// the "extra" characters.  We rely on that instead of
+			// attempting to perfectly reproduce the parsing algorithm.
+            var dateStringLength = dateTimeString.length-(err.length-err.indexOf(':')-2);
+            var timeString = dateTimeString.substring(dateStringLength);
+
+            return [dateTimeString.substring(0, dateStringLength), dateTimeString.substring(dateStringLength)];
+            
+		} else {
+			throw err;
+		}
+	}
+	return [dateTimeString, ''];
+};
+
+//#######################################################################################
+// Internal function to parse datetime interval
+// Returns: {date: Date, timeObj: Object}, where
+//   date - parsed date without time (type Date)
+//   timeObj = {hour: , minute: , second: , millisec: } - parsed time. Optional
+//#######################################################################################
+var parseDateTimeInternal = function(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings)
+{
+    var date;
+    var splitRes = splitDateTime(dateFormat, dateTimeString, dateSettings);
+	date = $.datepicker._base_parseDate(dateFormat, splitRes[0], dateSettings);
+    if (splitRes[1] !== '')
+    {
+        var timeString = splitRes[1];
+        var separator = timeSettings && timeSettings.separator ? timeSettings.separator : $.timepicker._defaults.separator;            
+        if ( timeString.indexOf(separator) !== 0) {
+            throw 'Missing time separator';
+        }
+        timeString = timeString.substring(separator.length);
+        var parsedTime = $.datepicker.parseTime(timeFormat, timeString, timeSettings);
+        if (parsedTime === null) {
+            throw 'Wrong time format';
+        }
+        return {date: date, timeObj: parsedTime};
+    } else {
+        return {date: date};
+    }
+};
+
+//#######################################################################################
+// Internal function to set timezone_select to the local timezone
+//#######################################################################################
+var selectLocalTimeZone = function(tp_inst, date)
+{
+	if (tp_inst && tp_inst.timezone_select) {
+		tp_inst._defaults.useLocalTimezone = true;
+		var now = typeof date !== 'undefined' ? date : new Date();
+		var tzoffset = timeZoneString(now);
+		if (tp_inst._defaults.timezoneIso8601) {
+			tzoffset = tzoffset.substring(0, 3) + ':' + tzoffset.substring(3);
+        }
+		tp_inst.timezone_select.val(tzoffset);
+	}
+};
+
+// Input: Date Object
+// Output: String with timezone offset, e.g. '+0100'
+var timeZoneString = function(date)
+{
+	var off = date.getTimezoneOffset() * -10100 / 60;
+	var timezone = (off >= 0 ? '+' : '-') + Math.abs(off).toString().substr(1);
+	return timezone;
+};
+
+$.timepicker = new Timepicker(); // singleton instance
+$.timepicker.version = "1.0.1";
+
+})(jQuery);

+ 20 - 0
main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-af.js

@@ -0,0 +1,20 @@
+/* Afrikaans translation for the jQuery Timepicker Addon */
+/* Written by Deon Heyns */
+(function($) {
+	$.timepicker.regional['af'] = {
+		timeOnlyTitle: 'Kies Tyd',
+		timeText: 'Tyd ',
+		hourText: 'Ure ',
+		minuteText: 'Minute',
+		secondText: 'Sekondes',
+		millisecText: 'Millisekondes',
+		timezoneText: 'Tydsone',
+		currentText: 'Huidige Tyd',
+		closeText: 'Klaar',
+		timeFormat: 'hh:mm tt',
+		amNames: ['AM', 'A'],
+		pmNames: ['PM', 'P'],
+		ampm: false
+	};
+	$.timepicker.setDefaults($.timepicker.regional['af']);
+})(jQuery);

+ 20 - 0
main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-ca.js

@@ -0,0 +1,20 @@
+/* Catalan translation for the jQuery Timepicker Addon */
+/* Written by Sergi Faber */
+(function($) {
+	$.timepicker.regional['ca'] = {
+		timeOnlyTitle: 'Escollir una hora',
+		timeText: 'Hora',
+		hourText: 'Hores',
+		minuteText: 'Minuts',
+		secondText: 'Segons',
+		millisecText: 'Milisegons',
+		timezoneText: 'Fus horari',
+		currentText: 'Ara',
+		closeText: 'Tancar',
+		timeFormat: 'hh:mm',
+		amNames: ['AM', 'A'],
+		pmNames: ['PM', 'P'],
+		ampm: false
+	};
+	$.timepicker.setDefaults($.timepicker.regional['ca']);
+})(jQuery);

+ 20 - 0
main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-cs.js

@@ -0,0 +1,20 @@
+/* Czech translation for the jQuery Timepicker Addon */
+/* Written by Ondřej Vodáček */
+(function($) {
+	$.timepicker.regional['cs'] = {
+		timeOnlyTitle: 'Vyberte čas',
+		timeText: 'Čas',
+		hourText: 'Hodiny',
+		minuteText: 'Minuty',
+		secondText: 'Vteřiny',
+		millisecText: 'Milisekundy',
+		timezoneText: 'Časové pásmo',
+		currentText: 'Nyní',
+		closeText: 'Zavřít',
+		timeFormat: 'h:m',
+		amNames: ['dop.', 'AM', 'A'],
+		pmNames: ['odp.', 'PM', 'P'],
+		ampm: false
+	};
+	$.timepicker.setDefaults($.timepicker.regional['cs']);
+})(jQuery);

+ 20 - 0
main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-de.js

@@ -0,0 +1,20 @@
+/* German translation for the jQuery Timepicker Addon */
+/* Written by Marvin */
+(function($) {
+	$.timepicker.regional['de'] = {
+		timeOnlyTitle: 'Zeit Wählen',
+		timeText: 'Zeit',
+		hourText: 'Stunde',
+		minuteText: 'Minute',
+		secondText: 'Sekunde',
+		millisecText: 'Millisekunde',
+		timezoneText: 'Zeitzone',
+		currentText: 'Jetzt',
+		closeText: 'Fertig',
+		timeFormat: 'hh:mm tt',
+		amNames: ['vorm.', 'AM', 'A'],
+		pmNames: ['nachm.', 'PM', 'P'],
+		ampm: false
+	};
+	$.timepicker.setDefaults($.timepicker.regional['de']);
+})(jQuery);

+ 20 - 0
main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-el.js

@@ -0,0 +1,20 @@
+/* Hellenic translation for the jQuery Timepicker Addon */
+/* Written by Christos Pontikis */
+(function($) {
+	$.timepicker.regional['el'] = {
+		timeOnlyTitle: 'Επιλογή ώρας',
+		timeText: 'Ώρα',
+		hourText: 'Ώρες',
+		minuteText: 'Λεπτά',
+		secondText: 'Δευτερόλεπτα',
+		millisecText: 'μιλιδευτερόλεπτο',
+		timezoneText: 'Ζώνη ώρας',
+		currentText: 'Τώρα',
+		closeText: 'Κλείσιμο',
+		timeFormat: 'hh:mm',
+		amNames: ['π.μ.', 'AM', 'A'],
+		pmNames: ['μ.μ.', 'PM', 'P'],
+		ampm: false
+	};
+	$.timepicker.setDefaults($.timepicker.regional['el']);
+})(jQuery);

+ 20 - 0
main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-es.js

@@ -0,0 +1,20 @@
+/* Spanish translation for the jQuery Timepicker Addon */
+/* Written by Ianaré Sévi */
+(function($) {
+	$.timepicker.regional['es'] = {
+		timeOnlyTitle: 'Elegir una hora',
+		timeText: 'Hora',
+		hourText: 'Horas',
+		minuteText: 'Minutos',
+		secondText: 'Segundos',
+		millisecText: 'Milisegundos',
+		timezoneText: 'Huso horario',
+		currentText: 'Ahora',
+		closeText: 'Cerrar',
+		timeFormat: 'hh:mm',
+		amNames: ['a.m.', 'AM', 'A'],
+		pmNames: ['p.m.', 'PM', 'P'],
+		ampm: false
+	};
+	$.timepicker.setDefaults($.timepicker.regional['es']);
+})(jQuery);

+ 20 - 0
main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-et.js

@@ -0,0 +1,20 @@
+/* Estonian translation for the jQuery Timepicker Addon */
+/* Written by Karl Sutt (karl@sutt.ee) */
+(function($) {
+	$.timepicker.regional['et'] = {
+		timeOnlyTitle: 'Vali aeg',
+		timeText: 'Aeg',
+		hourText: 'Tund',
+		minuteText: 'Minut',
+		secondText: 'Sekund',
+		millisecText: 'Millisekundis',
+		timezoneText: 'Ajavöönd',
+		currentText: 'Praegu',
+		closeText: 'Valmis',
+		timeFormat: 'hh:mm tt',
+		amNames: ['AM', 'A'],
+		pmNames: ['PM', 'P'],
+		ampm: false
+	};
+	$.timepicker.setDefaults($.timepicker.regional['et']);
+})(jQuery);

+ 20 - 0
main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-fi.js

@@ -0,0 +1,20 @@
+/* Finnish translation for the jQuery Timepicker Addon */
+/* Written by Juga Paazmaya (http://github.com/paazmaya) */
+(function($) {
+	$.timepicker.regional['fi'] = {
+		timeOnlyTitle: 'Valitse aika',
+		timeText: 'Aika',
+		hourText: 'Tunti',
+		minuteText: 'Minuutti',
+		secondText: 'Sekunti',
+		millisecText: 'Millisekunnin',
+		timezoneText: 'Aikavyöhyke',
+		currentText: 'Nyt',
+		closeText: 'Sulje',
+		timeFormat: 'hh:mm',
+		amNames: ['ap.', 'AM', 'A'],
+		pmNames: ['ip.', 'PM', 'P'],
+		ampm: false
+	};
+	$.timepicker.setDefaults($.timepicker.regional['fi']);
+})(jQuery);

+ 20 - 0
main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-fr.js

@@ -0,0 +1,20 @@
+/* French translation for the jQuery Timepicker Addon */
+/* Written by Thomas Lété */
+(function($) {
+	$.timepicker.regional['fr'] = {
+		timeOnlyTitle: 'Choisir une heure',
+		timeText: 'Heure',
+		hourText: 'Heures',
+		minuteText: 'Minutes',
+		secondText: 'Secondes',
+		millisecText: 'Millisecondes',
+		timezoneText: 'Fuseau horaire',
+		currentText: 'Maintenant',
+		closeText: 'Terminé',
+		timeFormat: 'hh:mm',
+		amNames: ['AM', 'A'],
+		pmNames: ['PM', 'P'],
+		ampm: false
+	};
+	$.timepicker.setDefaults($.timepicker.regional['fr']);
+})(jQuery);

+ 20 - 0
main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-gl.js

@@ -0,0 +1,20 @@
+/* Galician translation for the jQuery Timepicker Addon */
+/* Written by David Barral */
+(function($) {
+	$.timepicker.regional['gl'] = {
+		timeOnlyTitle: 'Elixir unha hora',
+		timeText: 'Hora',
+		hourText: 'Horas',
+		minuteText: 'Minutos',
+		secondText: 'Segundos',
+		millisecText: 'Milisegundos',
+		timezoneText: 'Fuso horario',
+		currentText: 'Agora',
+		closeText: 'Pechar',
+		timeFormat: 'hh:mm',
+		amNames: ['a.m.', 'AM', 'A'],
+		pmNames: ['p.m.', 'PM', 'P'],
+		ampm: false
+	};
+	$.timepicker.setDefaults($.timepicker.regional['gl']);
+})(jQuery);

+ 20 - 0
main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-he.js

@@ -0,0 +1,20 @@
+/* Hebrew translation for the jQuery Timepicker Addon */
+/* Written by Lior Lapid */
+(function($) {
+	$.timepicker.regional["he"] = {
+		timeOnlyTitle: "בחירת זמן",
+		timeText: "שעה",
+		hourText: "שעות",
+		minuteText: "דקות",
+		secondText: "שניות",
+		millisecText: "אלפית השנייה",
+		timezoneText: "אזור זמן",
+		currentText: "עכשיו",
+		closeText:"סגור",
+		timeFormat: "hh:mm tt",
+		amNames: ['לפנה"צ', 'AM', 'A'],
+		pmNames: ['אחה"צ', 'PM', 'P'],
+		ampm: false
+	};
+	$.timepicker.setDefaults($.timepicker.regional["he"]);
+})(jQuery);

+ 20 - 0
main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-hu.js

@@ -0,0 +1,20 @@
+/* Hungarian translation for the jQuery Timepicker Addon */
+/* Written by Vas Gábor */
+(function($) {
+	$.timepicker.regional['hu'] = {
+		timeOnlyTitle: 'Válasszon időpontot',
+		timeText: 'Idő',
+		hourText: 'Óra',
+		minuteText: 'Perc',
+		secondText: 'Másodperc',
+		millisecText: 'Milliszekundumos',
+		timezoneText: 'Időzóna',
+		currentText: 'Most',
+		closeText: 'Kész',
+		timeFormat: 'hh:mm tt',
+		amNames: ['de.', 'AM', 'A'],
+		pmNames: ['du.', 'PM', 'P'],
+		ampm: false
+	};
+	$.timepicker.setDefaults($.timepicker.regional['hu']);
+})(jQuery);

+ 20 - 0
main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-id.js

@@ -0,0 +1,20 @@
+/* Indonesian translation for the jQuery Timepicker Addon */
+/* Written by Nia */
+(function($) {
+	$.timepicker.regional['id'] = {
+		timeOnlyTitle: 'Pilih Waktu',
+		timeText: 'Waktu',
+		hourText: 'Pukul',
+		minuteText: 'Menit',
+		secondText: 'Detik',
+		millisecText: 'Milidetik',
+		timezoneText: 'Zona Waktu',
+		currentText: 'Sekarang',
+		closeText: 'OK',
+		timeFormat: 'hh:mm tt',
+		amNames: ['AM', 'A'],
+		pmNames: ['PM', 'P'],
+		ampm: false
+	};
+	$.timepicker.setDefaults($.timepicker.regional['id']);
+})(jQuery);

+ 20 - 0
main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-it.js

@@ -0,0 +1,20 @@
+/* Italian translation for the jQuery Timepicker Addon */
+/* Written by Marco "logicoder" Del Tongo */
+(function($) {
+    $.timepicker.regional['it'] = {
+        timeOnlyTitle: 'Scegli orario',
+        timeText: 'Orario',
+        hourText: 'Ora',
+        minuteText: 'Minuto',
+        secondText: 'Secondo',
+        millisecText: 'Millisecondo',
+        timezoneText: 'Fuso orario',
+        currentText: 'Adesso',
+        closeText: 'Chiudi',
+        timeFormat: 'hh:mm',
+        amNames: ['m.', 'AM', 'A'],
+        pmNames: ['p.', 'PM', 'P'],
+        ampm: false
+    };
+    $.timepicker.setDefaults($.timepicker.regional['it']);
+})(jQuery);

+ 20 - 0
main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-ja.js

@@ -0,0 +1,20 @@
+/* Japanese translation for the jQuery Timepicker Addon */
+/* Written by Jun Omae */
+(function($) {
+	$.timepicker.regional['ja'] = {
+		timeOnlyTitle: '時間を選択',
+		timeText: '時間',
+		hourText: '時',
+		minuteText: '分',
+		secondText: '秒',
+		millisecText: 'ミリ秒',
+		timezoneText: 'タイムゾーン',
+		currentText: '現時刻',
+		closeText: '閉じる',
+		timeFormat: 'hh:mm tt',
+		amNames: ['午前', 'AM', 'A'],
+		pmNames: ['午後', 'PM', 'P'],
+		ampm: false
+	};
+	$.timepicker.setDefaults($.timepicker.regional['ja']);
+})(jQuery);

+ 20 - 0
main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-ko.js

@@ -0,0 +1,20 @@
+/* Korean translation for the jQuery Timepicker Addon */
+/* Written by Genie */
+(function($) {
+	$.timepicker.regional['ko'] = {
+		timeOnlyTitle: '시간 선택',
+		timeText: '시간',
+		hourText: '시',
+		minuteText: '분',
+		secondText: '초',
+		millisecText: '밀리초',
+		timezoneText: '표준 시간대',
+		currentText: '현재 시각',
+		closeText: '닫기',
+		timeFormat: 'tt h:mm',
+		amNames: ['오전', 'AM', 'A'],
+		pmNames: ['오후', 'PM', 'P'],
+		ampm: true
+	};
+	$.timepicker.setDefaults($.timepicker.regional['ko']);
+})(jQuery);

+ 20 - 0
main/inc/lib/javascript/datetimepicker/localization/jquery-ui-timepicker-lt.js

@@ -0,0 +1,20 @@
+/* Lithuanian translation for the jQuery Timepicker Addon */
+/* Written by Irmantas Šiupšinskas */
+(function($) {
+	$.timepicker.regional['lt'] = {
+		timeOnlyTitle: 'Pasirinkite laiką',
+		timeText: 'Laikas',
+		hourText: 'Valandos',
+		minuteText: 'Minutės',
+		secondText: 'Sekundės',
+		millisecText: 'Milisekundės',
+		timezoneText: 'Laiko zona',
+		currentText: 'Dabar',
+		closeText: 'Uždaryti',
+		timeFormat: 'hh:mm',
+		amNames: ['priešpiet', 'AM', 'A'],
+		pmNames: ['popiet', 'PM', 'P'],
+		ampm: false
+	};
+	$.timepicker.setDefaults($.timepicker.regional['lt']);
+})(jQuery);

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini