Browse Source

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

Julio Montoya 10 năm trước cách đây
mục cha
commit
c17906cc26
74 tập tin đã thay đổi với 1572 bổ sung894 xóa
  1. 8 0
      .gitignore
  2. 3 0
      documentation/installation_guide.html
  3. 3 0
      documentation/installation_guide_es_ES.html
  4. 3 0
      documentation/installation_guide_fr_FR.html
  5. 3 0
      documentation/installation_guide_it_IT.html
  6. 4 0
      main/admin/add_users_to_session.php
  7. 2 2
      main/admin/session_edit.php
  8. 4 0
      main/admin/user_list.php
  9. 2 2
      main/admin/user_move_stats.php
  10. 156 149
      main/exercice/admin.php
  11. 1 1
      main/exercice/exercice.php
  12. 17 10
      main/exercice/exercise.class.php
  13. 1 1
      main/exercice/exercise_history.php
  14. 3 1
      main/exercice/exercise_report.php
  15. 1 1
      main/exercice/exercise_result.class.php
  16. 4 2
      main/exercice/exercise_show.php
  17. 2 2
      main/exercice/exercise_submit.php
  18. 1 1
      main/exercice/hotpotatoes_exercise_report.php
  19. 1 1
      main/exercice/mark_free_answer.php
  20. 7 6
      main/exercice/overview.php
  21. 490 490
      main/exercice/question.class.php
  22. 1 1
      main/gradebook/gradebook_result.class.php
  23. 2 2
      main/gradebook/lib/be/exerciselink.class.php
  24. 1 1
      main/inc/ajax/exercise.ajax.php
  25. 1 1
      main/inc/ajax/model.ajax.php
  26. 2 2
      main/inc/lib/api.lib.php
  27. 1 1
      main/inc/lib/course.lib.php
  28. 1 1
      main/inc/lib/database.constants.inc.php
  29. 23 22
      main/inc/lib/events.lib.inc.php
  30. 11 9
      main/inc/lib/exercise.lib.php
  31. 1 1
      main/inc/lib/hook/HookEvent.php
  32. 2 2
      main/inc/lib/hook/HookManagement.php
  33. 1 1
      main/inc/lib/hook/HookObserver.php
  34. 1 1
      main/inc/lib/hook/interfaces/base/HookEventInterface.php
  35. 1 1
      main/inc/lib/hook/interfaces/base/HookObserverInterface.php
  36. 1 1
      main/inc/lib/myspace.lib.php
  37. 4 4
      main/inc/lib/online.inc.php
  38. 32 6
      main/inc/lib/sessionmanager.lib.php
  39. 8 8
      main/inc/lib/tracking.lib.php
  40. 5 2
      main/install/db_main.sql
  41. 19 16
      main/install/db_stats.sql
  42. 12 0
      main/install/install.lib.php
  43. 1 1
      main/install/migrate-db-1.9.0-1.10.0-post.sql
  44. 13 2
      main/install/migrate-db-1.9.0-1.10.0-pre.sql
  45. 1 1
      main/install/update-db-1.9.0-1.10.0.inc.php
  46. 7 0
      main/lang/english/trad4all.inc.php
  47. 7 0
      main/lang/spanish/trad4all.inc.php
  48. 2 2
      main/mySpace/myStudents.php
  49. 1 1
      main/mySpace/progression.php
  50. 1 1
      main/mySpace/reussite.php
  51. 3 3
      main/newscorm/learnpathItem.class.php
  52. 1 1
      main/newscorm/lp_view.php
  53. 1 1
      main/reports/modules/quiz.php
  54. 1 1
      main/tracking/courseLog.php
  55. 1 1
      main/tracking/exams.php
  56. 1 1
      main/tracking/personnalLog.php
  57. 9 7
      plugin/advanced_subscription/ajax/advanced_subscription.ajax.php
  58. 4 0
      plugin/advanced_subscription/config.php
  59. 157 0
      plugin/advanced_subscription/cron/notify_by_mail.php
  60. 4 1
      plugin/advanced_subscription/lang/english.php
  61. 11 8
      plugin/advanced_subscription/lang/spanish.php
  62. 148 48
      plugin/advanced_subscription/src/AdvancedSubscriptionPlugin.php
  63. 66 53
      plugin/advanced_subscription/src/HookAdvancedSubscription.php
  64. 203 0
      plugin/advanced_subscription/src/scripts/insert_session_fields.php
  65. 20 0
      plugin/advanced_subscription/src/scripts/insert_sessions_categories.php
  66. 5 0
      plugin/advanced_subscription/test/mails.php
  67. 49 0
      plugin/advanced_subscription/test/ws_session_user.php
  68. 2 2
      plugin/advanced_subscription/views/admin_view.tpl
  69. 1 1
      plugin/advanced_subscription/views/reminder_notice_superior.tpl
  70. 2 2
      plugin/advanced_subscription/views/reminder_notice_superior_max.tpl
  71. 1 1
      plugin/advanced_subscription/views/student_no_superior_notice_admin.tpl
  72. 1 1
      tests/datafiller/fill_whoisonline.php
  73. 1 1
      tests/scripts/fix_exercise_score_in_lp.php
  74. 1 1
      tests/scripts/move_users.php

+ 8 - 0
.gitignore

@@ -17,6 +17,14 @@ home/*
 main/upload/users/*
 main/upload/users/*
 !main/upload/users/index.html
 !main/upload/users/index.html
 
 
+# Session images
+main/upload/sessions/*
+!main/upload/sessions/index.html
+
+# Course images
+main/upload/courses/*
+!main/upload/courses/index.html
+
 # Logs and databases #
 # Logs and databases #
 *.log
 *.log
 
 

+ 3 - 0
documentation/installation_guide.html

@@ -144,10 +144,13 @@ The following directories need to be readable, writeable and executable by your
 <ul>
 <ul>
   <li>[chamilo]/main/inc/conf/</li>
   <li>[chamilo]/main/inc/conf/</li>
   <li>[chamilo]/main/upload/users/</li>
   <li>[chamilo]/main/upload/users/</li>
+  <li>[chamilo]/main/upload/sessions/</li>
+  <li>[chamilo]/main/upload/courses/</li>
   <li>[chamilo]/main/default_course_document/images/</li>
   <li>[chamilo]/main/default_course_document/images/</li>
   <li>[chamilo]/archive/</li>
   <li>[chamilo]/archive/</li>
   <li>[chamilo]/courses/</li>
   <li>[chamilo]/courses/</li>
   <li>[chamilo]/home/</li>
   <li>[chamilo]/home/</li>
+  <li>[chamilo]/data/</li>
 </ul>
 </ul>
 Optionally, you can do the same to the following directories if you want to
 Optionally, you can do the same to the following directories if you want to
 enable CSS styles package upload and sub-language definition:
 enable CSS styles package upload and sub-language definition:

+ 3 - 0
documentation/installation_guide_es_ES.html

@@ -132,10 +132,13 @@ Remplace [chamilo] por el directorio en el cual está ubicado su Chamilo:
 <ul>
 <ul>
   <li>[chamilo]/main/inc/conf/</li>
   <li>[chamilo]/main/inc/conf/</li>
   <li>[chamilo]/main/upload/users/</li>
   <li>[chamilo]/main/upload/users/</li>
+  <li>[chamilo]/main/upload/sessions/</li>
+  <li>[chamilo]/main/upload/courses/</li>
   <li>[chamilo]/main/default_course_document/images/</li>
   <li>[chamilo]/main/default_course_document/images/</li>
   <li>[chamilo]/archive/</li>
   <li>[chamilo]/archive/</li>
   <li>[chamilo]/courses/</li>
   <li>[chamilo]/courses/</li>
   <li>[chamilo]/home/</li>
   <li>[chamilo]/home/</li>
+  <li>[chamilo]/data/</li>
 </ul>
 </ul>
 Opcionalmente, puede hacer lo mismo a los directorios siguientes si desea
 Opcionalmente, puede hacer lo mismo a los directorios siguientes si desea
 activar la subida de paquetes de estilos CSS y la definición de sub-idiomas:
 activar la subida de paquetes de estilos CSS y la definición de sub-idiomas:

+ 3 - 0
documentation/installation_guide_fr_FR.html

@@ -176,10 +176,13 @@ Remplacez [chamilo] par le répertoire où vous avez placé le contenu du zip:
 <ul>
 <ul>
   <li>[chamilo]/main/inc/conf/</li>
   <li>[chamilo]/main/inc/conf/</li>
   <li>[chamilo]/main/upload/users/</li>
   <li>[chamilo]/main/upload/users/</li>
+  <li>[chamilo]/main/upload/sessions/</li>
+  <li>[chamilo]/main/upload/courses/</li>
   <li>[chamilo]/main/default_course_document/images/</li>
   <li>[chamilo]/main/default_course_document/images/</li>
   <li>[chamilo]/archive/</li>
   <li>[chamilo]/archive/</li>
   <li>[chamilo]/courses/</li>
   <li>[chamilo]/courses/</li>
   <li>[chamilo]/home/</li>
   <li>[chamilo]/home/</li>
+  <li>[chamilo]/data/</li>
 </ul>
 </ul>
 Optionnellement, vous pouvez faire la même chose pour les répertoires suivants
 Optionnellement, vous pouvez faire la même chose pour les répertoires suivants
 si vous souhaitez permettre l'envoi de styles CSS ou la définition de nouvelles
 si vous souhaitez permettre l'envoi de styles CSS ou la définition de nouvelles

+ 3 - 0
documentation/installation_guide_it_IT.html

@@ -108,10 +108,13 @@
 <ul>
 <ul>
   <li class="li2"><span class="s1">[chamilo]/main/inc/conf/</span></li>
   <li class="li2"><span class="s1">[chamilo]/main/inc/conf/</span></li>
   <li class="li2"><span class="s1">[chamilo]/main/upload/users/</span></li>
   <li class="li2"><span class="s1">[chamilo]/main/upload/users/</span></li>
+  <li clasS="li2">[chamilo]/main/upload/sessions/</li>
+  <li class="li2">[chamilo]/main/upload/courses/</li>
   <li class="li2"><span class="s1">[chamilo]/main/default_course_document/images/</span></li>
   <li class="li2"><span class="s1">[chamilo]/main/default_course_document/images/</span></li>
   <li class="li2"><span class="s1">[chamilo]/archive/</span></li>
   <li class="li2"><span class="s1">[chamilo]/archive/</span></li>
   <li class="li2"><span class="s1">[chamilo]/courses/</span></li>
   <li class="li2"><span class="s1">[chamilo]/courses/</span></li>
   <li class="li2"><span class="s1">[chamilo]/home/</span></li>
   <li class="li2"><span class="s1">[chamilo]/home/</span></li>
+  <li class="li2"><span class="s1">[chamilo]/data/</span></li>
 </ul>
 </ul>
 <p class="p3"><span class="s1"></span><br></p>
 <p class="p3"><span class="s1"></span><br></p>
 <p class="p2"><span class="s1">Opzionalmente puoi fare lo stesso alle seguenti cartelle se vuoi consentire il caricamento dei pacchetti di stile CSS (CSS styles package) e la definizione di sotto-linguaggi (sub-language definition):</span></p>
 <p class="p2"><span class="s1">Opzionalmente puoi fare lo stesso alle seguenti cartelle se vuoi consentire il caricamento dei pacchetti di stile CSS (CSS styles package) e la definizione di sotto-linguaggi (sub-language definition):</span></p>

+ 4 - 0
main/admin/add_users_to_session.php

@@ -96,6 +96,10 @@ function search_users($needle, $type)
 
 
         $cond_user_id = '';
         $cond_user_id = '';
 
 
+        if (api_is_session_admin() && api_get_setting('prevent_session_admins_to_manage_all_users')  == 'true') {
+            $order_clause = " AND user.creator_id = ".api_get_user_id().$order_clause;
+        }
+
         // Only for single & multiple
         // Only for single & multiple
         if (in_array($type, array('single','multiple')))
         if (in_array($type, array('single','multiple')))
         if (!empty($id_session)) {
         if (!empty($id_session)) {

+ 2 - 2
main/admin/session_edit.php

@@ -92,13 +92,13 @@ foreach ($coaches as $coach) {
     $coachesOption[$coach['user_id']] = "$personName ({$coach['username']})";
     $coachesOption[$coach['user_id']] = "$personName ({$coach['username']})";
 }
 }
 
 
-$Categories = SessionManager::get_all_session_category();
+$categoriesList = SessionManager::get_all_session_category();
 
 
 $categoriesOption = array(
 $categoriesOption = array(
     '0' => get_lang('None')
     '0' => get_lang('None')
 );
 );
 
 
-if ($Categories != false) {
+if ($categoriesList != false) {
     foreach ($categoriesList as $categoryItem) {
     foreach ($categoriesList as $categoryItem) {
         $categoriesOption[$categoryItem['id']] = $categoryItem['name'];
         $categoriesOption[$categoryItem['id']] = $categoryItem['name'];
     }
     }

+ 4 - 0
main/admin/user_list.php

@@ -446,6 +446,10 @@ function get_user_data($from, $number_of_items, $column, $direction) {
     $from 	= intval($from);
     $from 	= intval($from);
     $number_of_items = intval($number_of_items);
     $number_of_items = intval($number_of_items);
 
 
+    if (api_is_session_admin() && api_get_setting('prevent_session_admins_to_manage_all_users')  == 'true') {
+        $sql .= " WHERE u.creator_id = ".api_get_user_id();
+    }
+
 	$sql .= " ORDER BY col$column $direction ";
 	$sql .= " ORDER BY col$column $direction ";
 	$sql .= " LIMIT $from,$number_of_items";
 	$sql .= " LIMIT $from,$number_of_items";
 
 

+ 2 - 2
main/admin/user_move_stats.php

@@ -116,7 +116,7 @@ if (isset($_REQUEST['load_ajax'])) {
                 $course_info = api_get_course_info($origin_course_code);
                 $course_info = api_get_course_info($origin_course_code);
                 $course_id = $course_info['real_id'];
                 $course_id = $course_info['real_id'];
 
 
-                $TABLETRACK_EXERCICES       = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+                $TABLETRACK_EXERCICES       = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
                 $TBL_TRACK_ATTEMPT          = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
                 $TBL_TRACK_ATTEMPT          = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
                 $TBL_TRACK_E_COURSE_ACCESS  = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
                 $TBL_TRACK_E_COURSE_ACCESS  = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
                 $TBL_TRACK_E_LAST_ACCESS    = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
                 $TBL_TRACK_E_LAST_ACCESS    = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
@@ -581,7 +581,7 @@ $htmlHeadXtra[] = '<script type="text/javascript">
  </script>';
  </script>';
 
 
 function get_courses_list_by_user_id_based_in_exercises($user_id) {
 function get_courses_list_by_user_id_based_in_exercises($user_id) {
-    $TABLETRACK_EXERCICES       = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+    $TABLETRACK_EXERCICES       = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
     $user_id = intval($user_id);
     $user_id = intval($user_id);
     //$sql = "SELECT DISTINCT exe_user_id, exe_cours_id as code, session_id as id_session FROM $TABLETRACK_EXERCICES WHERE exe_user_id = $user_id GROUP BY exe_user_id, exe_cours_id ORDER by exe_user_id, exe_cours_id ASC";
     //$sql = "SELECT DISTINCT exe_user_id, exe_cours_id as code, session_id as id_session FROM $TABLETRACK_EXERCICES WHERE exe_user_id = $user_id GROUP BY exe_user_id, exe_cours_id ORDER by exe_user_id, exe_cours_id ASC";
     $sql = "SELECT DISTINCT exe_user_id, exe_cours_id as code, session_id as id_session
     $sql = "SELECT DISTINCT exe_user_id, exe_cours_id as code, session_id as id_session

+ 156 - 149
main/exercice/admin.php

@@ -1,49 +1,49 @@
 <?php
 <?php
 /* For licensing terms, see /license.txt */
 /* For licensing terms, see /license.txt */
 /**
 /**
-*	Exercise administration
-* 	This script allows to manage (create, modify) an exercise and its questions
-*
-*	 Following scripts are includes for a best code understanding :
-*
-* 	- exercise.class.php : for the creation of an Exercise object
-* 	- question.class.php : for the creation of a Question object
-* 	- answer.class.php : for the creation of an Answer object
-* 	- exercise.lib.php : functions used in the exercise tool
-* 	- exercise_admin.inc.php : management of the exercise
-* 	- question_admin.inc.php : management of a question (statement & answers)
-* 	- statement_admin.inc.php : management of a statement
-* 	- answer_admin.inc.php : management of answers
-* 	- question_list_admin.inc.php : management of the question list
-*
-* 	Main variables used in this script :
-*
-* 	- $is_allowedToEdit : set to 1 if the user is allowed to manage the exercise
-* 	- $objExercise : exercise object
-* 	- $objQuestion : question object
-* 	- $objAnswer : answer object
-* 	- $aType : array with answer types
-* 	- $exerciseId : the exercise ID
-* 	- $picturePath : the path of question pictures
-* 	- $newQuestion : ask to create a new question
-* 	- $modifyQuestion : ID of the question to modify
-* 	- $editQuestion : ID of the question to edit
-* 	- $submitQuestion : ask to save question modifications
-* 	- $cancelQuestion : ask to cancel question modifications
-* 	- $deleteQuestion : ID of the question to delete
-* 	- $moveUp : ID of the question to move up
-* 	- $moveDown : ID of the question to move down
-* 	- $modifyExercise : ID of the exercise to modify
-* 	- $submitExercise : ask to save exercise modifications
-* 	- $cancelExercise : ask to cancel exercise modifications
-* 	- $modifyAnswers : ID of the question which we want to modify answers for
-* 	- $cancelAnswers : ask to cancel answer modifications
-* 	- $buttonBack : ask to go back to the previous page in answers of type "Fill in blanks"
-*
-*	@package chamilo.exercise
-* 	@author Olivier Brouckaert
-* Modified by Hubert Borderiou 21-10-2011 Question by category
-*/
+ *	Exercise administration
+ * 	This script allows to manage (create, modify) an exercise and its questions
+ *
+ *	 Following scripts are includes for a best code understanding :
+ *
+ * 	- exercise.class.php : for the creation of an Exercise object
+ * 	- question.class.php : for the creation of a Question object
+ * 	- answer.class.php : for the creation of an Answer object
+ * 	- exercise.lib.php : functions used in the exercise tool
+ * 	- exercise_admin.inc.php : management of the exercise
+ * 	- question_admin.inc.php : management of a question (statement & answers)
+ * 	- statement_admin.inc.php : management of a statement
+ * 	- answer_admin.inc.php : management of answers
+ * 	- question_list_admin.inc.php : management of the question list
+ *
+ * 	Main variables used in this script :
+ *
+ * 	- $is_allowedToEdit : set to 1 if the user is allowed to manage the exercise
+ * 	- $objExercise : exercise object
+ * 	- $objQuestion : question object
+ * 	- $objAnswer : answer object
+ * 	- $aType : array with answer types
+ * 	- $exerciseId : the exercise ID
+ * 	- $picturePath : the path of question pictures
+ * 	- $newQuestion : ask to create a new question
+ * 	- $modifyQuestion : ID of the question to modify
+ * 	- $editQuestion : ID of the question to edit
+ * 	- $submitQuestion : ask to save question modifications
+ * 	- $cancelQuestion : ask to cancel question modifications
+ * 	- $deleteQuestion : ID of the question to delete
+ * 	- $moveUp : ID of the question to move up
+ * 	- $moveDown : ID of the question to move down
+ * 	- $modifyExercise : ID of the exercise to modify
+ * 	- $submitExercise : ask to save exercise modifications
+ * 	- $cancelExercise : ask to cancel exercise modifications
+ * 	- $modifyAnswers : ID of the question which we want to modify answers for
+ * 	- $cancelAnswers : ask to cancel answer modifications
+ * 	- $buttonBack : ask to go back to the previous page in answers of type "Fill in blanks"
+ *
+ *	@package chamilo.exercise
+ * 	@author Olivier Brouckaert
+ * Modified by Hubert Borderiou 21-10-2011 Question by category
+ */
 
 
 use \ChamiloSession as Session;
 use \ChamiloSession as Session;
 
 
@@ -61,21 +61,21 @@ $is_allowedToEdit = api_is_allowed_to_edit(null,true);
 $sessionId = api_get_session_id();
 $sessionId = api_get_session_id();
 
 
 if (!$is_allowedToEdit) {
 if (!$is_allowedToEdit) {
-	api_not_allowed(true);
+    api_not_allowed(true);
 }
 }
 
 
 /*  stripslashes POST data  */
 /*  stripslashes POST data  */
 if($_SERVER['REQUEST_METHOD'] == 'POST') {
 if($_SERVER['REQUEST_METHOD'] == 'POST') {
-	foreach($_POST as $key=>$val) {
-		if(is_string($val)) {
-			$_POST[$key]=stripslashes($val);
-		} elseif(is_array($val)) {
-			foreach($val as $key2=>$val2) {
-				$_POST[$key][$key2]=stripslashes($val2);
-			}
-		}
-		$GLOBALS[$key]=$_POST[$key];
-	}
+    foreach($_POST as $key=>$val) {
+        if(is_string($val)) {
+            $_POST[$key]=stripslashes($val);
+        } elseif(is_array($val)) {
+            foreach($val as $key2=>$val2) {
+                $_POST[$key][$key2]=stripslashes($val2);
+            }
+        }
+        $GLOBALS[$key]=$_POST[$key];
+    }
 }
 }
 
 
 if (empty($exerciseId)) {
 if (empty($exerciseId)) {
@@ -109,21 +109,24 @@ $cancelExercise = isset($cancelExercise) ? $cancelExercise : null;
 $cancelAnswers = isset($cancelAnswers) ? $cancelAnswers : null;
 $cancelAnswers = isset($cancelAnswers) ? $cancelAnswers : null;
 $modifyIn = isset($modifyIn) ? $modifyIn : null;
 $modifyIn = isset($modifyIn) ? $modifyIn : null;
 $cancelQuestion = isset($cancelQuestion) ? $cancelQuestion : null;
 $cancelQuestion = isset($cancelQuestion) ? $cancelQuestion : null;
-$_course = api_get_course_info();
 
 
 /* Cleaning all incomplete attempts of the admin/teacher to avoid weird problems
 /* Cleaning all incomplete attempts of the admin/teacher to avoid weird problems
     when changing the exercise settings, number of questions, etc */
     when changing the exercise settings, number of questions, etc */
 
 
 Event::delete_all_incomplete_attempts(
 Event::delete_all_incomplete_attempts(
-	api_get_user_id(),
-	$exerciseId,
-	api_get_course_int_id(),
-	api_get_session_id()
+    api_get_user_id(),
+    $exerciseId,
+    api_get_course_int_id(),
+    api_get_session_id()
 );
 );
 
 
 // get from session
 // get from session
 $objExercise = isset($_SESSION['objExercise']) ? $_SESSION['objExercise'] : null;
 $objExercise = isset($_SESSION['objExercise']) ? $_SESSION['objExercise'] : null;
 $objQuestion = isset($_SESSION['objQuestion']) ? $_SESSION['objQuestion'] : null;
 $objQuestion = isset($_SESSION['objQuestion']) ? $_SESSION['objQuestion'] : null;
+if (isset($_REQUEST['convertAnswer'])) {
+    $objQuestion = $objQuestion->swapSimpleAnswerTypes();
+    $_SESSION['objQuestion'] = $objQuestion;
+}
 $objAnswer   = isset($_SESSION['objAnswer']) ? $_SESSION['objAnswer'] : null;
 $objAnswer   = isset($_SESSION['objAnswer']) ? $_SESSION['objAnswer'] : null;
 
 
 // document path
 // document path
@@ -173,135 +176,136 @@ if (!empty($_GET['action']) && $_GET['action'] == 'exportqti2' && !empty($_GET['
 
 
 // Exercise object creation.
 // Exercise object creation.
 if (!is_object($objExercise)) {
 if (!is_object($objExercise)) {
-	// construction of the Exercise object
-	$objExercise = new Exercise();
+    // construction of the Exercise object
+    $objExercise = new Exercise();
 
 
-	// creation of a new exercise if wrong or not specified exercise ID
-	if ($exerciseId) {
-	    $objExercise->read($exerciseId);
-	}
-	// saves the object into the session
-	Session::write('objExercise', $objExercise);
+    // creation of a new exercise if wrong or not specified exercise ID
+    if ($exerciseId) {
+        $objExercise->read($exerciseId);
+    }
+    // saves the object into the session
+    Session::write('objExercise', $objExercise);
 }
 }
 
 
 // Exercise can be edited in their course.
 // Exercise can be edited in their course.
 if ($objExercise->sessionId != $sessionId) {
 if ($objExercise->sessionId != $sessionId) {
     api_not_allowed(true);
     api_not_allowed(true);
+    /*header('Location: '.api_get_path(WEB_CODE_PATH).'exercice/exercice.php?'.api_get_cidreq());
+    exit;*/
 }
 }
 
 
 // doesn't select the exercise ID if we come from the question pool
 // doesn't select the exercise ID if we come from the question pool
 if (!$fromExercise) {
 if (!$fromExercise) {
-	// gets the right exercise ID, and if 0 creates a new exercise
-	if (!$exerciseId = $objExercise->selectId()) {
-		$modifyExercise='yes';
-	}
+    // gets the right exercise ID, and if 0 creates a new exercise
+    if (!$exerciseId = $objExercise->selectId()) {
+        $modifyExercise='yes';
+    }
 }
 }
 
 
 $nbrQuestions = $objExercise->selectNbrQuestions();
 $nbrQuestions = $objExercise->selectNbrQuestions();
 
 
 // Question object creation.
 // Question object creation.
 if ($editQuestion || $newQuestion || $modifyQuestion || $modifyAnswers) {
 if ($editQuestion || $newQuestion || $modifyQuestion || $modifyAnswers) {
-	if ($editQuestion || $newQuestion) {
+    if ($editQuestion || $newQuestion) {
 
 
-		// reads question data
-		if ($editQuestion) {
-			// question not found
-			if (!$objQuestion = Question::read($editQuestion)) {
-				api_not_allowed();
-			}
-			// saves the object into the session
-			Session::write('objQuestion',$objQuestion);
-		}
-	}
+        // reads question data
+        if ($editQuestion) {
+            // question not found
+            if (!$objQuestion = Question::read($editQuestion)) {
+                api_not_allowed();
+            }
+            // saves the object into the session
+            Session::write('objQuestion',$objQuestion);
+        }
+    }
 
 
-	// checks if the object exists
-	if (is_object($objQuestion)) {
-		// gets the question ID
-		$questionId = $objQuestion->selectId();
-	}
+    // checks if the object exists
+    if(is_object($objQuestion)) {
+        // gets the question ID
+        $questionId = $objQuestion->selectId();
+    }
 }
 }
 
 
 // if cancelling an exercise
 // if cancelling an exercise
 if ($cancelExercise) {
 if ($cancelExercise) {
-	// existing exercise
-	if ($exerciseId) {
-		unset($modifyExercise);
-	} else {
+    // existing exercise
+    if($exerciseId) {
+        unset($modifyExercise);
+    } else {
         // new exercise
         // new exercise
-		// goes back to the exercise list
-		header('Location: '.api_get_path(WEB_CODE_PATH).'exercice/exercice.php?'.api_get_cidreq());
-		exit();
-	}
+        // goes back to the exercise list
+        header('Location: '.api_get_path(WEB_CODE_PATH).'exercice/exercice.php?'.api_get_cidreq());
+        exit();
+    }
 }
 }
 
 
 // if cancelling question creation/modification
 // if cancelling question creation/modification
 if ($cancelQuestion) {
 if ($cancelQuestion) {
-	// if we are creating a new question from the question pool
-	if (!$exerciseId && !$questionId) {
-		// goes back to the question pool
-		header('Location: question_pool.php');
-		exit();
-	} else {
-		// goes back to the question viewing
-		$editQuestion = $modifyQuestion;
-		unset($newQuestion, $modifyQuestion);
-	}
+    // if we are creating a new question from the question pool
+    if(!$exerciseId && !$questionId) {
+        // goes back to the question pool
+        header('Location: question_pool.php');
+        exit();
+    } else {
+        // goes back to the question viewing
+        $editQuestion=$modifyQuestion;
+        unset($newQuestion,$modifyQuestion);
+    }
 }
 }
 
 
 if (!empty($clone_question) && !empty($objExercise->id)) {
 if (!empty($clone_question) && !empty($objExercise->id)) {
-	$old_question_obj = Question::read($clone_question);
-	$old_question_obj->question = $old_question_obj->question.' - '.get_lang('Copy');
+    $old_question_obj = Question::read($clone_question);
+    $old_question_obj->question = $old_question_obj->question.' - '.get_lang('Copy');
 
 
-	$new_id = $old_question_obj->duplicate();
-	$new_question_obj = Question::read($new_id);
-	$new_question_obj->addToList($exerciseId);
+    $new_id = $old_question_obj->duplicate();
+    $new_question_obj = Question::read($new_id);
+    $new_question_obj->addToList($exerciseId);
 
 
-	// This should be moved to the duplicate function
-	$new_answer_obj = new Answer($clone_question);
-	$new_answer_obj->read();
-	$new_answer_obj->duplicate($new_id);
+    // This should be moved to the duplicate function
+    $new_answer_obj = new Answer($clone_question);
+    $new_answer_obj->read();
+    $new_answer_obj->duplicate($new_id);
 
 
     //Reloading tne $objExercise obj
     //Reloading tne $objExercise obj
     $objExercise->read($objExercise->id);
     $objExercise->read($objExercise->id);
 
 
-	header('Location: admin.php?'.api_get_cidreq().'&exerciseId='.$objExercise->id);
-	exit;
+    header('Location: admin.php?'.api_get_cidreq().'&exerciseId='.$objExercise->id);
+    exit;
 }
 }
 
 
 // if cancelling answer creation/modification
 // if cancelling answer creation/modification
 if ($cancelAnswers) {
 if ($cancelAnswers) {
-	// goes back to the question viewing
-	$editQuestion=$modifyAnswers;
-	unset($modifyAnswers);
+    // goes back to the question viewing
+    $editQuestion=$modifyAnswers;
+    unset($modifyAnswers);
 }
 }
-
 $nameTools = null;
 $nameTools = null;
 // modifies the query string that is used in the link of tool name
 // modifies the query string that is used in the link of tool name
 if ($editQuestion || $modifyQuestion || $newQuestion || $modifyAnswers) {
 if ($editQuestion || $modifyQuestion || $newQuestion || $modifyAnswers) {
-	$nameTools = get_lang('QuestionManagement');
+    $nameTools = get_lang('QuestionManagement');
 }
 }
 
 
 if (isset($_SESSION['gradebook'])){
 if (isset($_SESSION['gradebook'])){
-	$gradebook=	$_SESSION['gradebook'];
+    $gradebook=	$_SESSION['gradebook'];
 }
 }
 
 
 if (!empty($gradebook) && $gradebook=='view') {
 if (!empty($gradebook) && $gradebook=='view') {
-	$interbreadcrumb[]= array(
+    $interbreadcrumb[]= array(
         'url' => '../gradebook/'.$_SESSION['gradebook_dest'],
         'url' => '../gradebook/'.$_SESSION['gradebook_dest'],
         'name' => get_lang('ToolGradebook')
         'name' => get_lang('ToolGradebook')
     );
     );
 }
 }
 
 
-$interbreadcrumb[] = array("url" => "exercice.php?".api_get_cidreq(),"name" => get_lang('Exercices'));
+$interbreadcrumb[] = array("url" => "exercice.php","name" => get_lang('Exercices'));
 if (isset($_GET['newQuestion']) || isset($_GET['editQuestion']) ) {
 if (isset($_GET['newQuestion']) || isset($_GET['editQuestion']) ) {
-    $interbreadcrumb[] = array("url" => "admin.php?exerciseId=".$objExercise->id.'&'.api_get_cidreq(), "name" => $objExercise->name);
+    $interbreadcrumb[] = array("url" => "admin.php?exerciseId=".$objExercise->id, "name" => $objExercise->name);
 } else {
 } else {
     $interbreadcrumb[] = array("url" => "#", "name" => $objExercise->name);
     $interbreadcrumb[] = array("url" => "#", "name" => $objExercise->name);
 }
 }
 
 
 // shows a link to go back to the question pool
 // shows a link to go back to the question pool
 if (!$exerciseId && $nameTools != get_lang('ExerciseManagement')){
 if (!$exerciseId && $nameTools != get_lang('ExerciseManagement')){
-	$interbreadcrumb[] = array(
+    $interbreadcrumb[]=array(
         "url" => api_get_path(WEB_CODE_PATH)."exercice/question_pool.php?fromExercise=$fromExercise&".api_get_cidreq(),
         "url" => api_get_path(WEB_CODE_PATH)."exercice/question_pool.php?fromExercise=$fromExercise&".api_get_cidreq(),
         "name" => get_lang('QuestionPool')
         "name" => get_lang('QuestionPool')
     );
     );
@@ -309,11 +313,11 @@ if (!$exerciseId && $nameTools != get_lang('ExerciseManagement')){
 
 
 // if the question is duplicated, disable the link of tool name
 // if the question is duplicated, disable the link of tool name
 if ($modifyIn == 'thisExercise') {
 if ($modifyIn == 'thisExercise') {
-	if ($buttonBack)	{
-		$modifyIn='allExercises';
-	} else {
-		$noPHP_SELF=true;
-	}
+    if($buttonBack)	{
+        $modifyIn='allExercises';
+    } else {
+        $noPHP_SELF=true;
+    }
 }
 }
 $htmlHeadXtra[] = '<script>
 $htmlHeadXtra[] = '<script>
 
 
@@ -332,6 +336,8 @@ function multiple_answer_true_false_onchange(variable) {
     }
     }
     document.getElementById(weight_id).value = array_result[result];
     document.getElementById(weight_id).value = array_result[result];
 }
 }
+
+
 </script>';
 </script>';
 
 
 $htmlHeadXtra[] = "<script type=\"text/javascript\" src=\"../plugin/hotspot/JavaScriptFlashGateway.js\"></script>
 $htmlHeadXtra[] = "<script type=\"text/javascript\" src=\"../plugin/hotspot/JavaScriptFlashGateway.js\"></script>
@@ -493,35 +499,36 @@ if ($inATest) {
     echo '<span style="float:right">'.sprintf(get_lang('XQuestionsWithTotalScoreY'), $objExercise->selectNbrQuestions(), $maxScoreAllQuestions).'</span>';
     echo '<span style="float:right">'.sprintf(get_lang('XQuestionsWithTotalScoreY'), $objExercise->selectNbrQuestions(), $maxScoreAllQuestions).'</span>';
     echo '</div>';
     echo '</div>';
 } else if (isset($_GET['newQuestion'])) {
 } else if (isset($_GET['newQuestion'])) {
-	// we are in create a new question from question pool not in a test
-	echo '<div class="actions">';
-	echo '<a href="'.api_get_path(WEB_CODE_PATH).'exercice/admin.php?'.api_get_cidreq().'">'.
+    // we are in create a new question from question pool not in a test
+    echo '<div class="actions">';
+    echo '<a href="'.api_get_path(WEB_CODE_PATH).'exercice/admin.php?'.api_get_cidreq().'">'.
         Display::return_icon('back.png', get_lang('GoBackToQuestionList'),'',ICON_SIZE_MEDIUM).'</a>';
         Display::return_icon('back.png', get_lang('GoBackToQuestionList'),'',ICON_SIZE_MEDIUM).'</a>';
-	echo '</div>';
+    echo '</div>';
 } else {
 } else {
-	// If we are in question_pool but not in an test, go back to question create in pool
-	echo '<div class="actions">';
-	echo '<a href="'.api_get_path(WEB_CODE_PATH).'exercice/question_pool.php?'.api_get_cidreq().'">'.
+    // If we are in question_pool but not in an test, go back to question create in pool
+    echo '<div class="actions">';
+    echo '<a href="'.api_get_path(WEB_CODE_PATH).'exercice/question_pool.php?'.api_get_cidreq().'">'.
         Display::return_icon('back.png', get_lang('GoBackToQuestionList'),'',ICON_SIZE_MEDIUM).
         Display::return_icon('back.png', get_lang('GoBackToQuestionList'),'',ICON_SIZE_MEDIUM).
         '</a>';
         '</a>';
-	echo '</div>';
+    echo '</div>';
 }
 }
 
 
 if (isset($_GET['message'])) {
 if (isset($_GET['message'])) {
-	if (in_array($_GET['message'], array('ExerciseStored', 'ItemUpdated', 'ItemAdded'))) {
-		Display::display_confirmation_message(get_lang($_GET['message']));
-	}
+    if (in_array($_GET['message'], array('ExerciseStored', 'ItemUpdated', 'ItemAdded'))) {
+        Display::display_confirmation_message(get_lang($_GET['message']));
+    }
 }
 }
 
 
 if ($newQuestion || $editQuestion) {
 if ($newQuestion || $editQuestion) {
-	// statement management
-	$type = isset($_REQUEST['answerType']) ? Security::remove_XSS($_REQUEST['answerType']) : null;
-	echo '<input type="hidden" name="Type" value="'.$type.'" />';
+    // statement management
+    $type = isset($_REQUEST['answerType']) ? Security::remove_XSS($_REQUEST['answerType']) : null;
+    echo '<input type="hidden" name="Type" value="'.$type.'" />';
 
 
     if ($newQuestion == 'yes') {
     if ($newQuestion == 'yes') {
         $objExercise->edit_exercise_in_lp = true;
         $objExercise->edit_exercise_in_lp = true;
     }
     }
-	require 'question_admin.inc.php';
+
+    require 'question_admin.inc.php';
 }
 }
 
 
 if (isset($_GET['hotspotadmin'])) {
 if (isset($_GET['hotspotadmin'])) {
@@ -531,12 +538,12 @@ if (isset($_GET['hotspotadmin'])) {
     if (!$objQuestion) {
     if (!$objQuestion) {
         api_not_allowed();
         api_not_allowed();
     }
     }
-	require 'hotspot_admin.inc.php';
+    require 'hotspot_admin.inc.php';
 }
 }
 
 
 if (!$newQuestion && !$modifyQuestion && !$editQuestion && !isset($_GET['hotspotadmin'])) {
 if (!$newQuestion && !$modifyQuestion && !$editQuestion && !isset($_GET['hotspotadmin'])) {
-	// question list management
-	require 'question_list_admin.inc.php';
+    // question list management
+    require 'question_list_admin.inc.php';
 }
 }
 
 
 // if we are in question authoring, display warning to user is feedback not shown at the end of the test -ref #6619
 // if we are in question authoring, display warning to user is feedback not shown at the end of the test -ref #6619

+ 1 - 1
main/exercice/exercice.php

@@ -51,7 +51,7 @@ $TBL_DOCUMENT = Database :: get_course_table(TABLE_DOCUMENT);
 $TBL_ITEM_PROPERTY = Database :: get_course_table(TABLE_ITEM_PROPERTY);
 $TBL_ITEM_PROPERTY = Database :: get_course_table(TABLE_ITEM_PROPERTY);
 $TBL_EXERCICE_QUESTION = Database :: get_course_table(TABLE_QUIZ_TEST_QUESTION);
 $TBL_EXERCICE_QUESTION = Database :: get_course_table(TABLE_QUIZ_TEST_QUESTION);
 $TBL_EXERCICES = Database :: get_course_table(TABLE_QUIZ_TEST);
 $TBL_EXERCICES = Database :: get_course_table(TABLE_QUIZ_TEST);
-$TBL_TRACK_EXERCICES = Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+$TBL_TRACK_EXERCICES = Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
 
 
 // document path
 // document path
 $documentPath = api_get_path(SYS_COURSE_PATH).$courseInfo['path']."/document";
 $documentPath = api_get_path(SYS_COURSE_PATH).$courseInfo['path']."/document";

+ 17 - 10
main/exercice/exercise.class.php

@@ -1571,7 +1571,7 @@ class Exercise
      */
      */
     public function clean_results($cleanLpTests = false, $cleanResultBeforeDate = null)
     public function clean_results($cleanLpTests = false, $cleanResultBeforeDate = null)
     {
     {
-        $table_track_e_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $table_track_e_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $table_track_e_attempt   = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
         $table_track_e_attempt   = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
 
 
         $sql_where = '  AND
         $sql_where = '  AND
@@ -1617,7 +1617,7 @@ class Exercise
         }
         }
 
 
         $session_id = api_get_session_id();
         $session_id = api_get_session_id();
-        // delete TRACK_E_EXERCICES table
+        // delete TRACK_E_EXERCISES table
         $sql = "DELETE FROM $table_track_e_exercises
         $sql = "DELETE FROM $table_track_e_exercises
                 WHERE exe_cours_id = '".api_get_course_id()."'
                 WHERE exe_cours_id = '".api_get_course_id()."'
                 AND exe_exo_id = ".$this->id."
                 AND exe_exo_id = ".$this->id."
@@ -1710,7 +1710,7 @@ class Exercise
         $lp_item_view_id = 0,
         $lp_item_view_id = 0,
         $status = 'incomplete'
         $status = 'incomplete'
     ) {
     ) {
-        $track_exercises = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $track_exercises = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         if (empty($lp_id)) {
         if (empty($lp_id)) {
             $lp_id = 0;
             $lp_id = 0;
         }
         }
@@ -1758,11 +1758,13 @@ class Exercise
         $questionList = array(),
         $questionList = array(),
         $weight = 0
         $weight = 0
     ) {
     ) {
-        $track_exercises = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $track_exercises = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $safe_lp_id = intval($safe_lp_id);
         $safe_lp_id = intval($safe_lp_id);
         $safe_lp_item_id = intval($safe_lp_item_id);
         $safe_lp_item_id = intval($safe_lp_item_id);
         $safe_lp_item_view_id = intval($safe_lp_item_view_id);
         $safe_lp_item_view_id = intval($safe_lp_item_view_id);
 
 
+        $trackValues = array();
+
         if (empty($safe_lp_id)) {
         if (empty($safe_lp_id)) {
             $safe_lp_id = 0;
             $safe_lp_id = 0;
         }
         }
@@ -1788,6 +1790,7 @@ class Exercise
             'orig_lp_item_id'  => $safe_lp_item_id,
             'orig_lp_item_id'  => $safe_lp_item_id,
             'orig_lp_item_view_id'  => $safe_lp_item_view_id,
             'orig_lp_item_view_id'  => $safe_lp_item_view_id,
             'exe_weighting'=> $weight,
             'exe_weighting'=> $weight,
+            'user_ip' => api_get_real_ip()
         );
         );
 
 
         if ($this->expired_time != 0) {
         if ($this->expired_time != 0) {
@@ -1795,7 +1798,6 @@ class Exercise
         }
         }
 
 
         $id = Database::insert($track_exercises, $params);
         $id = Database::insert($track_exercises, $params);
-
         return $id;
         return $id;
     }
     }
 
 
@@ -3601,7 +3603,7 @@ class Exercise
         }
         }
 
 
         if ($saved_results) {
         if ($saved_results) {
-            $stat_table = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+            $stat_table = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
             $sql = 'UPDATE ' . $stat_table . ' SET
             $sql = 'UPDATE ' . $stat_table . ' SET
                         exe_result = exe_result + ' . floatval($questionScore) . '
                         exe_result = exe_result + ' . floatval($questionScore) . '
                     WHERE exe_id = ' . $exeId;
                     WHERE exe_id = ' . $exeId;
@@ -3876,9 +3878,10 @@ class Exercise
      * @param array $user_data result of api_get_user_info()
      * @param array $user_data result of api_get_user_info()
      * @param null $start_date
      * @param null $start_date
      * @param null $duration
      * @param null $duration
+     * @param string $ip Optional. The user IP
      * @return string
      * @return string
      */
      */
-    public function show_exercise_result_header($user_data, $start_date = null, $duration = null)
+    public function show_exercise_result_header($user_data, $start_date = null, $duration = null, $ip = null)
     {
     {
         $array = array();
         $array = array();
 
 
@@ -3908,6 +3911,10 @@ class Exercise
             $array[] = array('title' => get_lang("Duration"), 'content' => $duration);
             $array[] = array('title' => get_lang("Duration"), 'content' => $duration);
         }
         }
 
 
+        if (!empty($ip)) {
+            $array[] = array("title" => get_lang("IP"), "content" => $ip);
+        }
+
         $html  = Display::page_header(
         $html  = Display::page_header(
             Display::return_icon('quiz_big.png', get_lang('Result')).' '.$this->exercise.' : '.get_lang('Result')
             Display::return_icon('quiz_big.png', get_lang('Result')).' '.$this->exercise.' : '.get_lang('Result')
         );
         );
@@ -4283,7 +4290,7 @@ class Exercise
 
 
     public function get_stat_track_exercise_info_by_exe_id($exe_id)
     public function get_stat_track_exercise_info_by_exe_id($exe_id)
     {
     {
-        $track_exercises = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $track_exercises = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $exe_id = intval($exe_id);
         $exe_id = intval($exe_id);
         $sql_track = "SELECT * FROM $track_exercises WHERE exe_id = $exe_id ";
         $sql_track = "SELECT * FROM $track_exercises WHERE exe_id = $exe_id ";
         $result = Database::query($sql_track);
         $result = Database::query($sql_track);
@@ -4317,7 +4324,7 @@ class Exercise
         $exercise_info = self::get_stat_track_exercise_info_by_exe_id($exe_id);
         $exercise_info = self::get_stat_track_exercise_info_by_exe_id($exe_id);
         $question_id = intval($question_id);
         $question_id = intval($question_id);
         $exe_id = intval($exe_id);
         $exe_id = intval($exe_id);
-        $track_exercises = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $track_exercises = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         if ($exercise_info) {
         if ($exercise_info) {
 
 
             if (empty($exercise_info['questions_to_check'])) {
             if (empty($exercise_info['questions_to_check'])) {
@@ -4555,7 +4562,7 @@ class Exercise
         $ids = is_array($quizId) ? $quizId : array($quizId);
         $ids = is_array($quizId) ? $quizId : array($quizId);
         $ids = array_map('intval', $ids);
         $ids = array_map('intval', $ids);
         $ids = implode(',', $ids);
         $ids = implode(',', $ids);
-        $track_exercises = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $track_exercises = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         if ($sessionId != 0) {
         if ($sessionId != 0) {
             $sql = "SELECT * FROM $track_exercises te "
             $sql = "SELECT * FROM $track_exercises te "
               . "INNER JOIN c_quiz cq ON cq.id = te.exe_exo_id "
               . "INNER JOIN c_quiz cq ON cq.id = te.exe_exo_id "

+ 1 - 1
main/exercice/exercise_history.php

@@ -37,7 +37,7 @@ $interbreadcrumb[]= array ('url' => 'exercise_history.php'.'?exe_id='.intval($_G
 $TBL_USER          	    = Database::get_main_table(TABLE_MAIN_USER);
 $TBL_USER          	    = Database::get_main_table(TABLE_MAIN_USER);
 $TBL_EXERCICES			= Database::get_course_table(TABLE_QUIZ_TEST);
 $TBL_EXERCICES			= Database::get_course_table(TABLE_QUIZ_TEST);
 $TBL_EXERCICES_QUESTION	= Database::get_course_table(TABLE_QUIZ_QUESTION);
 $TBL_EXERCICES_QUESTION	= Database::get_course_table(TABLE_QUIZ_QUESTION);
-$TBL_TRACK_EXERCICES	= Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+$TBL_TRACK_EXERCICES	= Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
 $TBL_TRACK_ATTEMPT_RECORDING= Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING);
 $TBL_TRACK_ATTEMPT_RECORDING= Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING);
 Display::display_header($nameTools,get_lang('Exercise'));
 Display::display_header($nameTools,get_lang('Exercise'));
 
 

+ 3 - 1
main/exercice/exercise_report.php

@@ -41,7 +41,7 @@ $is_allowedToEdit = api_is_allowed_to_edit(null, true) || api_is_drh() || api_is
 $is_tutor = api_is_allowed_to_edit(true);
 $is_tutor = api_is_allowed_to_edit(true);
 
 
 $TBL_QUESTIONS = Database :: get_course_table(TABLE_QUIZ_QUESTION);
 $TBL_QUESTIONS = Database :: get_course_table(TABLE_QUIZ_QUESTION);
-$TBL_TRACK_EXERCICES = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+$TBL_TRACK_EXERCICES = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
 $TBL_TRACK_ATTEMPT = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
 $TBL_TRACK_ATTEMPT = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
 $TBL_TRACK_ATTEMPT_RECORDING = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING);
 $TBL_TRACK_ATTEMPT_RECORDING = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING);
 $TBL_LP_ITEM_VIEW = Database :: get_course_table(TABLE_LP_ITEM_VIEW);
 $TBL_LP_ITEM_VIEW = Database :: get_course_table(TABLE_LP_ITEM_VIEW);
@@ -415,6 +415,7 @@ if ($is_allowedToEdit || $is_tutor) {
         get_lang('StartDate'),
         get_lang('StartDate'),
         get_lang('EndDate'),
         get_lang('EndDate'),
         get_lang('Score'),
         get_lang('Score'),
+        get_lang('IP'),
         get_lang('Status'),
         get_lang('Status'),
         get_lang('ToolLearnpath'),
         get_lang('ToolLearnpath'),
         get_lang('Actions')
         get_lang('Actions')
@@ -440,6 +441,7 @@ if ($is_allowedToEdit || $is_tutor) {
         array('name' => 'start_date', 'index' => 'start_date', 'width' => '60', 'align' => 'left', 'search' => 'true'),
         array('name' => 'start_date', 'index' => 'start_date', 'width' => '60', 'align' => 'left', 'search' => 'true'),
         array('name' => 'exe_date', 'index' => 'exe_date', 'width' => '60', 'align' => 'left', 'search' => 'true'),
         array('name' => 'exe_date', 'index' => 'exe_date', 'width' => '60', 'align' => 'left', 'search' => 'true'),
         array('name' => 'score', 'index' => 'exe_result', 'width' => '50', 'align' => 'left', 'search' => 'true'),
         array('name' => 'score', 'index' => 'exe_result', 'width' => '50', 'align' => 'left', 'search' => 'true'),
+        array('name' => 'ip', 'index' => 'user_ip', 'width' => '40', 'align' => 'center', 'search' => 'true'),
         array('name' => 'status', 'index' => 'revised', 'width' => '40', 'align' => 'left', 'search' => 'true', 'stype' => 'select',
         array('name' => 'status', 'index' => 'revised', 'width' => '40', 'align' => 'left', 'search' => 'true', 'stype' => 'select',
             //for the bottom bar
             //for the bottom bar
             'searchoptions' => array(
             'searchoptions' => array(

+ 1 - 1
main/exercice/exercise_result.class.php

@@ -52,7 +52,7 @@ class ExerciseResult
         $TBL_TABLE_LP_MAIN = Database::get_course_table(TABLE_LP_MAIN);
         $TBL_TABLE_LP_MAIN = Database::get_course_table(TABLE_LP_MAIN);
 
 
         $TBL_USER = Database::get_main_table(TABLE_MAIN_USER);
         $TBL_USER = Database::get_main_table(TABLE_MAIN_USER);
-        $TBL_TRACK_EXERCISES = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $TBL_TRACK_EXERCISES = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $TBL_TRACK_ATTEMPT_RECORDING = Database:: get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING);
         $TBL_TRACK_ATTEMPT_RECORDING = Database:: get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING);
 
 
         $cid = api_get_course_id();
         $cid = api_get_course_id();

+ 4 - 2
main/exercice/exercise_show.php

@@ -33,7 +33,7 @@ if ($origin == 'learnpath') {
 // Database table definitions
 // Database table definitions
 $TBL_EXERCICE_QUESTION 	= Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
 $TBL_EXERCICE_QUESTION 	= Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
 $TBL_QUESTIONS         	= Database::get_course_table(TABLE_QUIZ_QUESTION);
 $TBL_QUESTIONS         	= Database::get_course_table(TABLE_QUIZ_QUESTION);
-$TBL_TRACK_EXERCICES    = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+$TBL_TRACK_EXERCICES    = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
 $TBL_TRACK_ATTEMPT		= Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
 $TBL_TRACK_ATTEMPT		= Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
 
 
 // General parameters passed via POST/GET
 // General parameters passed via POST/GET
@@ -215,7 +215,9 @@ if ($show_results || $show_only_total_score) {
     //Shows exercise header
     //Shows exercise header
     echo $objExercise->show_exercise_result_header(
     echo $objExercise->show_exercise_result_header(
         $user_info,
         $user_info,
-        api_convert_and_format_date($exercise_date)
+        api_convert_and_format_date($exercise_date),
+        null,
+        $track_exercise_info['user_ip']
     );
     );
 }
 }
 
 

+ 2 - 2
main/exercice/exercise_submit.php

@@ -148,7 +148,7 @@ $current_expired_time_key = ExerciseLib::get_time_control_key($objExercise->id,
 $_SESSION['duration_time'][$current_expired_time_key] = $current_timestamp;
 $_SESSION['duration_time'][$current_expired_time_key] = $current_timestamp;
 
 
 if ($time_control) {
 if ($time_control) {
-	// Get the expired time of the current exercice in track_e_exercices
+	// Get the expired time of the current exercice in track_e_exercises
 	$total_seconds = $objExercise->expired_time*60;
 	$total_seconds = $objExercise->expired_time*60;
 }
 }
 
 
@@ -358,7 +358,7 @@ if ($time_control) {
 	        if ($debug) {error_log('7.9. $clock_expired_time: '.$clock_expired_time); }
 	        if ($debug) {error_log('7.9. $clock_expired_time: '.$clock_expired_time); }
 
 
 			// First we update the attempt to today
 			// First we update the attempt to today
-			/* How the expired time is changed into "track_e_exercices" table,
+			/* How the expired time is changed into "track_e_exercises" table,
                then the last attempt for this student should be changed too */
                then the last attempt for this student should be changed too */
 	        $sql = "UPDATE $exercice_attemp_table SET
 	        $sql = "UPDATE $exercice_attemp_table SET
 	                tms = '".api_get_utc_datetime()."'
 	                tms = '".api_get_utc_datetime()."'

+ 1 - 1
main/exercice/hotpotatoes_exercise_report.php

@@ -35,7 +35,7 @@ $is_allowedToEdit = api_is_allowed_to_edit(null, true) || api_is_drh();
 $is_tutor = api_is_allowed_to_edit(true);
 $is_tutor = api_is_allowed_to_edit(true);
 
 
 $TBL_QUESTIONS = Database :: get_course_table(TABLE_QUIZ_QUESTION);
 $TBL_QUESTIONS = Database :: get_course_table(TABLE_QUIZ_QUESTION);
-$TBL_TRACK_EXERCICES = Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+$TBL_TRACK_EXERCICES = Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
 $TBL_TRACK_HOTPOTATOES_EXERCICES = Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_HOTPOTATOES);
 $TBL_TRACK_HOTPOTATOES_EXERCICES = Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_HOTPOTATOES);
 $TBL_LP_ITEM_VIEW = Database :: get_course_table(TABLE_LP_ITEM_VIEW);
 $TBL_LP_ITEM_VIEW = Database :: get_course_table(TABLE_LP_ITEM_VIEW);
 
 

+ 1 - 1
main/exercice/mark_free_answer.php

@@ -82,7 +82,7 @@ if ($action == 'mark') {
 	if (!empty($_POST['score']) AND $_POST['score'] < $obj_question->selectWeighting() AND $_POST['score'] >= 0) {
 	if (!empty($_POST['score']) AND $_POST['score'] < $obj_question->selectWeighting() AND $_POST['score'] >= 0) {
 		//mark the user mark into the database using something similar to the following function:
 		//mark the user mark into the database using something similar to the following function:
 
 
-		$exercise_table = Database::get_statistic_table('track_e_exercices');
+		$exercise_table = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
 		#global $origin, $tbl_learnpath_user, $learnpath_id, $learnpath_item_id;
 		#global $origin, $tbl_learnpath_user, $learnpath_id, $learnpath_item_id;
 		$sql = "SELECT * FROM $exercise_table
 		$sql = "SELECT * FROM $exercise_table
 			    WHERE exe_user_id = ".intval($my_usr)." AND exe_cours_id = '".Database::escape_string($my_cid)."' AND exe_exo_id = ".intval($my_exe)."
 			    WHERE exe_user_id = ".intval($my_usr)." AND exe_cours_id = '".Database::escape_string($my_cid)."' AND exe_exo_id = ".intval($my_exe)."

+ 7 - 6
main/exercice/overview.php

@@ -133,7 +133,7 @@ if ($visible_return['value'] == false) {
 $attempts = Event::getExerciseResultsByUser(
 $attempts = Event::getExerciseResultsByUser(
     api_get_user_id(),
     api_get_user_id(),
     $objExercise->id,
     $objExercise->id,
-    api_get_course_id(),
+    api_get_course_int_id(),
     api_get_session_id(),
     api_get_session_id(),
     $learnpath_id,
     $learnpath_id,
     $learnpath_item_id,
     $learnpath_item_id,
@@ -182,7 +182,8 @@ if (!empty($attempts) && $visible_return['value'] == true) {
             'date' => api_convert_and_format_date(
             'date' => api_convert_and_format_date(
                 $attempt_result['start_date'],
                 $attempt_result['start_date'],
                 DATE_TIME_FORMAT_LONG
                 DATE_TIME_FORMAT_LONG
-            )
+            ),
+            'userIp' => $attempt_result['user_ip']
         );
         );
         $attempt_link .= "&nbsp;&nbsp;&nbsp;" . $teacher_revised;
         $attempt_link .= "&nbsp;&nbsp;&nbsp;" . $teacher_revised;
 
 
@@ -217,17 +218,17 @@ if (!empty($attempts) && $visible_return['value'] == true) {
 	switch ($objExercise->results_disabled) {
 	switch ($objExercise->results_disabled) {
 		case RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS:
 		case RESULT_DISABLE_SHOW_SCORE_AND_EXPECTED_ANSWERS:
         case RESULT_DISABLE_SHOW_FINAL_SCORE_ONLY_WITH_CATEGORIES:
         case RESULT_DISABLE_SHOW_FINAL_SCORE_ONLY_WITH_CATEGORIES:
-			$header_names = array(get_lang('Attempt'), get_lang('StartDate'), get_lang('Score'), get_lang('Details'));
+			$header_names = array(get_lang('Attempt'), get_lang('StartDate'), get_lang('IP'), get_lang('Score'), get_lang('Details'));
 			break;
 			break;
 		case RESULT_DISABLE_NO_SCORE_AND_EXPECTED_ANSWERS:
 		case RESULT_DISABLE_NO_SCORE_AND_EXPECTED_ANSWERS:
-			$header_names = array(get_lang('Attempt'), get_lang('StartDate'));
+			$header_names = array(get_lang('Attempt'), get_lang('StartDate'), get_lang('IP'));
 			break;
 			break;
 		case RESULT_DISABLE_SHOW_SCORE_ONLY:
 		case RESULT_DISABLE_SHOW_SCORE_ONLY:
             if ($objExercise->feedback_type != EXERCISE_FEEDBACK_TYPE_END) {
             if ($objExercise->feedback_type != EXERCISE_FEEDBACK_TYPE_END) {
-			    $header_names = array(get_lang('Attempt'), get_lang('StartDate'), get_lang('Score'));
+			    $header_names = array(get_lang('Attempt'), get_lang('StartDate'), get_lang('IP'), get_lang('Score'));
             }
             }
             else {
             else {
-                $header_names = array(get_lang('Attempt'), get_lang('StartDate'), get_lang('Score'), get_lang('Details'));
+                $header_names = array(get_lang('Attempt'), get_lang('StartDate'), get_lang('IP'), get_lang('Score'), get_lang('Details'));
             }
             }
 			break;
 			break;
 	}
 	}

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 490 - 490
main/exercice/question.class.php


+ 1 - 1
main/gradebook/gradebook_result.class.php

@@ -88,7 +88,7 @@ class GradeBookResult
         $return = array();
         $return = array();
         $TBL_EXERCISES          = Database::get_course_table(TABLE_QUIZ_TEST);
         $TBL_EXERCISES          = Database::get_course_table(TABLE_QUIZ_TEST);
         $TBL_USER          	    = Database::get_main_table(TABLE_MAIN_USER);
         $TBL_USER          	    = Database::get_main_table(TABLE_MAIN_USER);
-        $TBL_TRACK_EXERCISES	= Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $TBL_TRACK_EXERCISES	= Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $TBL_TRACK_HOTPOTATOES	= Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_HOTPOTATOES);
         $TBL_TRACK_HOTPOTATOES	= Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_HOTPOTATOES);
 
 
         $cid = api_get_course_id();
         $cid = api_get_course_id();

+ 2 - 2
main/gradebook/lib/be/exerciselink.class.php

@@ -138,7 +138,7 @@ class ExerciseLink extends AbstractLink
      */
      */
     public function has_results()
     public function has_results()
     {
     {
-        $tbl_stats = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $tbl_stats = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $session_id = api_get_session_id();
         $session_id = api_get_session_id();
         $sql = 'SELECT count(exe_id) AS number FROM '.$tbl_stats."
         $sql = 'SELECT count(exe_id) AS number FROM '.$tbl_stats."
                 WHERE
                 WHERE
@@ -159,7 +159,7 @@ class ExerciseLink extends AbstractLink
      */
      */
     public function calc_score($stud_id = null)
     public function calc_score($stud_id = null)
     {
     {
-        $tblStats = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $tblStats = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $tblHp = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTPOTATOES);
         $tblHp = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTPOTATOES);
         $tblDoc = Database::get_course_table(TABLE_DOCUMENT);
         $tblDoc = Database::get_course_table(TABLE_DOCUMENT);
 
 

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

@@ -42,7 +42,7 @@ switch ($action) {
             $sidx = 1;
             $sidx = 1;
         }
         }
 
 
-        $track_exercise = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $track_exercise = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $user_table = Database::get_main_table(TABLE_MAIN_USER);
         $user_table = Database::get_main_table(TABLE_MAIN_USER);
         $track_attempt = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
         $track_attempt = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
 
 

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

@@ -658,7 +658,7 @@ switch ($action) {
         $documentPath = api_get_path(SYS_COURSE_PATH) . $course['path'] . "/document";
         $documentPath = api_get_path(SYS_COURSE_PATH) . $course['path'] . "/document";
         if ($is_allowedToEdit || api_is_student_boss()) {
         if ($is_allowedToEdit || api_is_student_boss()) {
             $columns = array(
             $columns = array(
-                'firstname', 'lastname', 'username', 'group_name', 'exe_duration', 'start_date', 'exe_date', 'score', 'status', 'lp', 'actions'
+                'firstname', 'lastname', 'username', 'group_name', 'exe_duration', 'start_date', 'exe_date', 'score',  'user_ip', 'status', 'lp', 'actions'
             );
             );
             $officialCodeInList = api_get_configuration_value('show_official_code_exercise_result_list');
             $officialCodeInList = api_get_configuration_value('show_official_code_exercise_result_list');
             if ($officialCodeInList == true) {
             if ($officialCodeInList == true) {

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

@@ -6770,7 +6770,7 @@ function api_user_is_login($user_id = null) {
  * Guess the real ip for register in the database, even in reverse proxy cases.
  * Guess the real ip for register in the database, even in reverse proxy cases.
  * To be recognized, the IP has to be found in either $_SERVER['REMOTE_ADDR'] or
  * To be recognized, the IP has to be found in either $_SERVER['REMOTE_ADDR'] or
  * in $_SERVER['HTTP_X_FORWARDED_FOR'], which is in common use with rproxies.
  * in $_SERVER['HTTP_X_FORWARDED_FOR'], which is in common use with rproxies.
- * @return string the real ip of teh user.
+ * @return string the user's real ip (unsafe - escape it before inserting to db)
  * @author Jorge Frisancho Jibaja <jrfdeft@gmail.com>, USIL - Some changes to allow the use of real IP using reverse proxy
  * @author Jorge Frisancho Jibaja <jrfdeft@gmail.com>, USIL - Some changes to allow the use of real IP using reverse proxy
  * @version CEV CHANGE 24APR2012
  * @version CEV CHANGE 24APR2012
  */
  */
@@ -6779,7 +6779,7 @@ function api_get_real_ip(){
     global $debug;
     global $debug;
     $ip = trim($_SERVER['REMOTE_ADDR']);
     $ip = trim($_SERVER['REMOTE_ADDR']);
     if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
     if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
-        list($ip1,$ip2) = split(',',$_SERVER['HTTP_X_FORWARDED_FOR']);
+        list($ip1, $ip2) = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
         $ip = trim($ip1);
         $ip = trim($ip1);
     }
     }
     if (!empty($debug)) error_log('Real IP: '.$ip);
     if (!empty($debug)) error_log('Real IP: '.$ip);

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

@@ -2211,7 +2211,7 @@ class CourseManager
 
 
         $table_stats_hotpots = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTPOTATOES);
         $table_stats_hotpots = Database::get_main_table(TABLE_STATISTIC_TRACK_E_HOTPOTATOES);
         $table_stats_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
         $table_stats_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
-        $table_stats_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $table_stats_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $table_stats_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS);
         $table_stats_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS);
         $table_stats_lastaccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
         $table_stats_lastaccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
         $table_stats_course_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
         $table_stats_course_access = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);

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

@@ -134,7 +134,7 @@ define('TABLE_STATISTIC_TRACK_E_LINKS',             'track_e_links');
 define('TABLE_STATISTIC_TRACK_E_ONLINE',            'track_e_online');
 define('TABLE_STATISTIC_TRACK_E_ONLINE',            'track_e_online');
 define('TABLE_STATISTIC_TRACK_E_HOTPOTATOES',       'track_e_hotpotatoes');
 define('TABLE_STATISTIC_TRACK_E_HOTPOTATOES',       'track_e_hotpotatoes');
 define('TABLE_STATISTIC_TRACK_E_COURSE_ACCESS',     'track_e_course_access');
 define('TABLE_STATISTIC_TRACK_E_COURSE_ACCESS',     'track_e_course_access');
-define('TABLE_STATISTIC_TRACK_E_EXERCICES',         'track_e_exercices');
+define('TABLE_STATISTIC_TRACK_E_EXERCISES',         'track_e_exercises');
 define('TABLE_STATISTIC_TRACK_E_ATTEMPT',           'track_e_attempt');
 define('TABLE_STATISTIC_TRACK_E_ATTEMPT',           'track_e_attempt');
 define('TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING', 'track_e_attempt_recording');
 define('TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING', 'track_e_attempt_recording');
 define('TABLE_STATISTIC_TRACK_E_DEFAULT',           'track_e_default');
 define('TABLE_STATISTIC_TRACK_E_DEFAULT',           'track_e_default');

+ 23 - 22
main/inc/lib/events.lib.inc.php

@@ -68,7 +68,7 @@ class Event
 
 
         $reallyNow = api_get_utc_datetime();
         $reallyNow = api_get_utc_datetime();
 
 
-        $sql = "INSERT INTO ".$TABLETRACK_LOGIN." (login_user_id, login_ip, login_date, logout_date) VALUES
+        $sql = "INSERT INTO ".$TABLETRACK_LOGIN." (login_user_id, user_ip, login_date, logout_date) VALUES
                     ('".$userId."',
                     ('".$userId."',
                     '".Database::escape_string(api_get_real_ip())."',
                     '".Database::escape_string(api_get_real_ip())."',
                     '".$reallyNow."',
                     '".$reallyNow."',
@@ -348,7 +348,7 @@ class Event
                 $status = Database::escape_string($status);
                 $status = Database::escape_string($status);
             }
             }
 
 
-            $TABLETRACK_EXERCICES = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+            $TABLETRACK_EXERCICES = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
 
 
             if (!empty($question_list)) {
             if (!empty($question_list)) {
                 $question_list = array_map('intval', $question_list);
                 $question_list = array_map('intval', $question_list);
@@ -374,11 +374,12 @@ class Event
         		   orig_lp_id 			= '".Database::escape_string($learnpath_id)."',
         		   orig_lp_id 			= '".Database::escape_string($learnpath_id)."',
         		   orig_lp_item_id 		= '".Database::escape_string($learnpath_item_id)."',
         		   orig_lp_item_id 		= '".Database::escape_string($learnpath_item_id)."',
                    orig_lp_item_view_id = '".Database::escape_string($learnpath_item_view_id)."',
                    orig_lp_item_view_id = '".Database::escape_string($learnpath_item_view_id)."',
-        		   exe_duration 		= '".Database::escape_string($duration)."',
-        		   exe_date				= '".$end_date."',
-        		   status 				= '".$status."',
-        		   questions_to_check 	= '".$remind_list."',
-        		   data_tracking    	= '".implode(',', $question_list)."'
+        		   exe_duration = '".Database::escape_string($duration)."',
+        		   exe_date = '".$end_date."',
+        		   status = '".$status."',
+        		   questions_to_check = '".$remind_list."',
+        		   data_tracking = '".implode(',', $question_list)."',
+                   user_ip = '" . Database::escape_string(api_get_real_ip()) . "'
         		 WHERE exe_id = '".Database::escape_string($exeid)."'";
         		 WHERE exe_id = '".Database::escape_string($exeid)."'";
             $res = Database::query($sql);
             $res = Database::query($sql);
 
 
@@ -915,7 +916,7 @@ class Event
      */
      */
     public static function get_attempt_count($user_id, $exerciseId, $lp_id, $lp_item_id, $lp_item_view_id)
     public static function get_attempt_count($user_id, $exerciseId, $lp_id, $lp_item_id, $lp_item_view_id)
     {
     {
-        $stat_table = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $stat_table = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $user_id = intval($user_id);
         $user_id = intval($user_id);
         $exerciseId = intval($exerciseId);
         $exerciseId = intval($exerciseId);
         $lp_id = intval($lp_id);
         $lp_id = intval($lp_id);
@@ -950,7 +951,7 @@ class Event
      */
      */
     public static function get_attempt_count_not_finished($user_id, $exerciseId, $lp_id, $lp_item_id)
     public static function get_attempt_count_not_finished($user_id, $exerciseId, $lp_id, $lp_item_id)
     {
     {
-        $stat_table = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $stat_table = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $user_id = intval($user_id);
         $user_id = intval($user_id);
         $exerciseId = intval($exerciseId);
         $exerciseId = intval($exerciseId);
         $lp_id = intval($lp_id);
         $lp_id = intval($lp_id);
@@ -995,7 +996,7 @@ class Event
         }
         }
 
 
         $track_e_exercises = Database::get_main_table(
         $track_e_exercises = Database::get_main_table(
-            TABLE_STATISTIC_TRACK_E_EXERCICES
+            TABLE_STATISTIC_TRACK_E_EXERCISES
         );
         );
         $track_attempts = Database::get_main_table(
         $track_attempts = Database::get_main_table(
             TABLE_STATISTIC_TRACK_E_ATTEMPT
             TABLE_STATISTIC_TRACK_E_ATTEMPT
@@ -1094,7 +1095,7 @@ class Event
      */
      */
     public static function delete_all_incomplete_attempts($user_id, $exercise_id, $course_id, $session_id = 0)
     public static function delete_all_incomplete_attempts($user_id, $exercise_id, $course_id, $session_id = 0)
     {
     {
-        $track_e_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $track_e_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $user_id = intval($user_id);
         $user_id = intval($user_id);
         $exercise_id = intval($exercise_id);
         $exercise_id = intval($exercise_id);
         $course_id = intval($course_id);
         $course_id = intval($course_id);
@@ -1130,7 +1131,7 @@ class Event
      */
      */
     public static function get_all_exercise_results($exercise_id, $courseId, $session_id = 0, $load_question_list = true, $user_id = null)
     public static function get_all_exercise_results($exercise_id, $courseId, $session_id = 0, $load_question_list = true, $user_id = null)
     {
     {
-        $TABLETRACK_EXERCICES = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $TABLETRACK_EXERCICES = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $TBL_TRACK_ATTEMPT = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
         $TBL_TRACK_ATTEMPT = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
         $courseId = intval($courseId);
         $courseId = intval($courseId);
         $exercise_id = intval($exercise_id);
         $exercise_id = intval($exercise_id);
@@ -1175,7 +1176,7 @@ class Event
      */
      */
     public static function get_all_exercise_results_by_course($courseId, $session_id = 0, $get_count = true)
     public static function get_all_exercise_results_by_course($courseId, $session_id = 0, $get_count = true)
     {
     {
-        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $table_track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
         $table_track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
         $courseId = intval($courseId);
         $courseId = intval($courseId);
         $session_id = intval($session_id);
         $session_id = intval($session_id);
@@ -1219,7 +1220,7 @@ class Event
      */
      */
     public static function get_all_exercise_results_by_user($user_id, $courseId, $session_id = 0)
     public static function get_all_exercise_results_by_user($user_id, $courseId, $session_id = 0)
     {
     {
-        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $table_track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
         $table_track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
         $courseId = intval($courseId);
         $courseId = intval($courseId);
         $session_id = intval($session_id);
         $session_id = intval($session_id);
@@ -1258,7 +1259,7 @@ class Event
      */
      */
     public static function get_exercise_results_by_attempt($exe_id, $status = null)
     public static function get_exercise_results_by_attempt($exe_id, $status = null)
     {
     {
-        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $table_track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
         $table_track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
         $table_track_attempt_recording = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING);
         $table_track_attempt_recording = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING);
         $exe_id = intval($exe_id);
         $exe_id = intval($exe_id);
@@ -1303,7 +1304,7 @@ class Event
      */
      */
     public static function getExerciseResultsByUser($user_id, $exercise_id, $courseId, $session_id = 0, $lp_id = 0, $lp_item_id = 0, $order = null)
     public static function getExerciseResultsByUser($user_id, $exercise_id, $courseId, $session_id = 0, $lp_id = 0, $lp_item_id = 0, $order = null)
     {
     {
-        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $table_track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
         $table_track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
         $table_track_attempt_recording = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING);
         $table_track_attempt_recording = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING);
         $courseId = intval($courseId);
         $courseId = intval($courseId);
@@ -1358,7 +1359,7 @@ class Event
      */
      */
     public static function count_exercise_attempts_by_user($user_id, $exercise_id, $courseId, $session_id = 0)
     public static function count_exercise_attempts_by_user($user_id, $exercise_id, $courseId, $session_id = 0)
     {
     {
-        $TABLETRACK_EXERCICES = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $TABLETRACK_EXERCICES = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $courseId = intval($courseId);
         $courseId = intval($courseId);
         $exercise_id = intval($exercise_id);
         $exercise_id = intval($exercise_id);
         $session_id = intval($session_id);
         $session_id = intval($session_id);
@@ -1393,7 +1394,7 @@ class Event
      */
      */
     public static function get_best_exercise_results_by_user($exercise_id, $courseId, $session_id = 0)
     public static function get_best_exercise_results_by_user($exercise_id, $courseId, $session_id = 0)
     {
     {
-        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $table_track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
         $table_track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
         $courseId = intval($courseId);
         $courseId = intval($courseId);
         $exercise_id = intval($exercise_id);
         $exercise_id = intval($exercise_id);
@@ -1442,7 +1443,7 @@ class Event
      */
      */
     public static function get_best_attempt_exercise_results_per_user($user_id, $exercise_id, $courseId, $session_id = 0)
     public static function get_best_attempt_exercise_results_per_user($user_id, $exercise_id, $courseId, $session_id = 0)
     {
     {
-        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $courseId = intval($courseId);
         $courseId = intval($courseId);
         $exercise_id = intval($exercise_id);
         $exercise_id = intval($exercise_id);
         $session_id = intval($session_id);
         $session_id = intval($session_id);
@@ -1492,7 +1493,7 @@ class Event
      */
      */
     public static function count_exercise_result_not_validated($exercise_id, $courseId, $session_id = 0)
     public static function count_exercise_result_not_validated($exercise_id, $courseId, $session_id = 0)
     {
     {
-        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $table_track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING);
         $table_track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING);
         $courseId = intval($courseId);
         $courseId = intval($courseId);
         $session_id = intval($session_id);
         $session_id = intval($session_id);
@@ -1526,7 +1527,7 @@ class Event
      */
      */
     public static function get_count_exercises_attempted_by_course($courseId, $session_id = 0)
     public static function get_count_exercises_attempted_by_course($courseId, $session_id = 0)
     {
     {
-        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $courseId = intval($courseId);
         $courseId = intval($courseId);
         $session_id = intval($session_id);
         $session_id = intval($session_id);
 
 
@@ -1555,7 +1556,7 @@ class Event
      */
      */
     public static function get_all_exercise_event_from_lp($exercise_id, $courseId, $session_id = 0)
     public static function get_all_exercise_event_from_lp($exercise_id, $courseId, $session_id = 0)
     {
     {
-        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $table_track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $table_track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
         $table_track_attempt = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
         $courseId = intval($courseId);
         $courseId = intval($courseId);
         $exercise_id = intval($exercise_id);
         $exercise_id = intval($exercise_id);

+ 11 - 9
main/inc/lib/exercise.lib.php

@@ -1133,7 +1133,7 @@ class ExerciseLib
     {
     {
         $TBL_EXERCICES = Database::get_course_table(TABLE_QUIZ_TEST);
         $TBL_EXERCICES = Database::get_course_table(TABLE_QUIZ_TEST);
         $TBL_TRACK_EXERCICES = Database::get_main_table(
         $TBL_TRACK_EXERCICES = Database::get_main_table(
-            TABLE_STATISTIC_TRACK_E_EXERCICES
+            TABLE_STATISTIC_TRACK_E_EXERCISES
         );
         );
         $TBL_COURSE = Database::get_main_table(TABLE_MAIN_COURSE);
         $TBL_COURSE = Database::get_main_table(TABLE_MAIN_COURSE);
         $exe_id = intval($exe_id);
         $exe_id = intval($exe_id);
@@ -1445,7 +1445,7 @@ class ExerciseLib
         $TBL_GROUP_REL_USER = Database:: get_course_table(TABLE_GROUP_USER);
         $TBL_GROUP_REL_USER = Database:: get_course_table(TABLE_GROUP_USER);
         $TBL_GROUP = Database:: get_course_table(TABLE_GROUP);
         $TBL_GROUP = Database:: get_course_table(TABLE_GROUP);
         $TBL_TRACK_EXERCICES = Database:: get_main_table(
         $TBL_TRACK_EXERCICES = Database:: get_main_table(
-            TABLE_STATISTIC_TRACK_E_EXERCICES
+            TABLE_STATISTIC_TRACK_E_EXERCISES
         );
         );
         $TBL_TRACK_HOTPOTATOES = Database:: get_main_table(
         $TBL_TRACK_HOTPOTATOES = Database:: get_main_table(
             TABLE_STATISTIC_TRACK_E_HOTPOTATOES
             TABLE_STATISTIC_TRACK_E_HOTPOTATOES
@@ -1592,7 +1592,8 @@ class ExerciseLib
                     revised,
                     revised,
                     group_name,
                     group_name,
                     group_id,
                     group_id,
-                    orig_lp_id";
+                    orig_lp_id,
+                    te.user_ip";
             }
             }
 
 
             $sql = " $sql_select
             $sql = " $sql_select
@@ -2722,7 +2723,7 @@ class ExerciseLib
         $session_id
         $session_id
     ) {
     ) {
         $track_exercises = Database::get_main_table(
         $track_exercises = Database::get_main_table(
-            TABLE_STATISTIC_TRACK_E_EXERCICES
+            TABLE_STATISTIC_TRACK_E_EXERCISES
         );
         );
         $track_attempt = Database::get_main_table(
         $track_attempt = Database::get_main_table(
             TABLE_STATISTIC_TRACK_E_ATTEMPT
             TABLE_STATISTIC_TRACK_E_ATTEMPT
@@ -2771,7 +2772,7 @@ class ExerciseLib
         $session_id
         $session_id
     ) {
     ) {
         $track_exercises = Database::get_main_table(
         $track_exercises = Database::get_main_table(
-            TABLE_STATISTIC_TRACK_E_EXERCICES
+            TABLE_STATISTIC_TRACK_E_EXERCISES
         );
         );
         $track_attempt = Database::get_main_table(
         $track_attempt = Database::get_main_table(
             TABLE_STATISTIC_TRACK_E_ATTEMPT
             TABLE_STATISTIC_TRACK_E_ATTEMPT
@@ -2841,7 +2842,7 @@ class ExerciseLib
         $session_id
         $session_id
     ) {
     ) {
         $track_exercises = Database::get_main_table(
         $track_exercises = Database::get_main_table(
-            TABLE_STATISTIC_TRACK_E_EXERCICES
+            TABLE_STATISTIC_TRACK_E_EXERCISES
         );
         );
         $track_hotspot = Database::get_main_table(
         $track_hotspot = Database::get_main_table(
             TABLE_STATISTIC_TRACK_E_HOTSPOT
             TABLE_STATISTIC_TRACK_E_HOTSPOT
@@ -2915,7 +2916,7 @@ class ExerciseLib
         $current_answer = null
         $current_answer = null
     ) {
     ) {
         $track_exercises = Database::get_main_table(
         $track_exercises = Database::get_main_table(
-            TABLE_STATISTIC_TRACK_E_EXERCICES
+            TABLE_STATISTIC_TRACK_E_EXERCISES
         );
         );
         $track_attempt = Database::get_main_table(
         $track_attempt = Database::get_main_table(
             TABLE_STATISTIC_TRACK_E_ATTEMPT
             TABLE_STATISTIC_TRACK_E_ATTEMPT
@@ -3130,7 +3131,7 @@ class ExerciseLib
         $session_id
         $session_id
     ) {
     ) {
         $track_exercises = Database::get_main_table(
         $track_exercises = Database::get_main_table(
-            TABLE_STATISTIC_TRACK_E_EXERCICES
+            TABLE_STATISTIC_TRACK_E_EXERCISES
         );
         );
         $track_attempt = Database::get_main_table(
         $track_attempt = Database::get_main_table(
             TABLE_STATISTIC_TRACK_E_ATTEMPT
             TABLE_STATISTIC_TRACK_E_ATTEMPT
@@ -3301,7 +3302,8 @@ class ExerciseLib
                     $exercise_stat_info['start_date'],
                     $exercise_stat_info['start_date'],
                     DATE_TIME_FORMAT_LONG
                     DATE_TIME_FORMAT_LONG
                 ),
                 ),
-                $exercise_stat_info['duration']
+                $exercise_stat_info['duration'],
+                $exercise_stat_info['user_ip']
             );
             );
         }
         }
 
 

+ 1 - 1
main/inc/lib/hook/HookEvent.php

@@ -36,7 +36,7 @@ abstract class HookEvent implements HookEventInterface
 
 
     /**
     /**
      * Return the singleton instance of Hook event.
      * Return the singleton instance of Hook event.
-     * @return HookEventInterface|null
+     * @return static
      */
      */
     public static function create()
     public static function create()
     {
     {

+ 2 - 2
main/inc/lib/hook/HookManagement.php

@@ -88,8 +88,8 @@ class HookManagement implements HookManagementInterface
     public function deleteHook($eventName, $observerClassName, $type)
     public function deleteHook($eventName, $observerClassName, $type)
     {
     {
         if ($type === HOOK_EVENT_TYPE_ALL) {
         if ($type === HOOK_EVENT_TYPE_ALL) {
-            $this->insertHook($eventName, $observerClassName, HOOK_EVENT_TYPE_PRE);
-            $this->insertHook($eventName, $observerClassName, HOOK_EVENT_TYPE_POST);
+            $this->deleteHook($eventName, $observerClassName, HOOK_EVENT_TYPE_PRE);
+            $this->deleteHook($eventName, $observerClassName, HOOK_EVENT_TYPE_POST);
         } else {
         } else {
             $this->insertHookIfNotExist($eventName, $observerClassName);
             $this->insertHookIfNotExist($eventName, $observerClassName);
 
 

+ 1 - 1
main/inc/lib/hook/HookObserver.php

@@ -34,7 +34,7 @@ abstract class HookObserver implements HookObserverInterface
     /**
     /**
      * Return the singleton instance of Hook observer.
      * Return the singleton instance of Hook observer.
      * If Hook Management plugin is not enabled, will return NULL
      * If Hook Management plugin is not enabled, will return NULL
-     * @return HookEventInterface|null
+     * @return static
      */
      */
     public static function create()
     public static function create()
     {
     {

+ 1 - 1
main/inc/lib/hook/interfaces/base/HookEventInterface.php

@@ -33,7 +33,7 @@ interface HookEventInterface
 
 
     /**
     /**
      * Return the singleton instance of Hook event.
      * Return the singleton instance of Hook event.
-     * @return HookEventInterface|null
+     * @return static
      */
      */
     public static function create();
     public static function create();
 
 

+ 1 - 1
main/inc/lib/hook/interfaces/base/HookObserverInterface.php

@@ -10,7 +10,7 @@ interface HookObserverInterface
 {
 {
     /**
     /**
      * Return the singleton instance of Hook observer.
      * Return the singleton instance of Hook observer.
-     * @return HookEventInterface|null
+     * @return static
      */
      */
     public static function create();
     public static function create();
 
 

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

@@ -1878,7 +1878,7 @@ class MySpace
     {
     {
         $questions_answered = 0;
         $questions_answered = 0;
         $sql = 'SELECT exe_result , exe_weighting
         $sql = 'SELECT exe_result , exe_weighting
-            FROM '.Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES)."
+            FROM '.Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES)."
             WHERE exe_cours_id = '".Database::escape_string($course_code)."'
             WHERE exe_cours_id = '".Database::escape_string($course_code)."'
             AND exe_user_id = '".intval($user_id)."'";
             AND exe_user_id = '".intval($user_id)."'";
         if($session_id !== false) {
         if($session_id !== false) {

+ 4 - 4
main/inc/lib/online.inc.php

@@ -24,9 +24,9 @@ function LoginCheck($uid) {
 	$uid = (int) $uid;
 	$uid = (int) $uid;
 	$online_table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE);
 	$online_table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ONLINE);
     if (!empty($uid)) {
     if (!empty($uid)) {
-        $login_ip = '';
+        $user_ip = '';
         if (!empty($_SERVER['REMOTE_ADDR'])) {
         if (!empty($_SERVER['REMOTE_ADDR'])) {
-            $login_ip = Database::escape_string($_SERVER['REMOTE_ADDR']);
+            $user_ip = Database::escape_string(api_get_real_ip());
         }
         }
 
 
 		$login_date = api_get_utc_datetime();
 		$login_date = api_get_utc_datetime();
@@ -38,9 +38,9 @@ function LoginCheck($uid) {
 		// if the $_course array exists this means we are in a course and we have to store this in the who's online table also
 		// if the $_course array exists this means we are in a course and we have to store this in the who's online table also
 		// to have the x users in this course feature working
 		// to have the x users in this course feature working
 		if (is_array($_course) && count($_course)>0 && !empty($_course['id'])) {
 		if (is_array($_course) && count($_course)>0 && !empty($_course['id'])) {
-            $query = "REPLACE INTO ".$online_table ." (login_id,login_user_id,login_date,login_ip, c_id, session_id, access_url_id) VALUES ($uid,$uid,'$login_date','$login_ip', '".$_course['real_id']."' , '$session_id' , '$access_url_id' )";
+            $query = "REPLACE INTO ".$online_table ." (login_id,login_user_id,login_date,user_ip, c_id, session_id, access_url_id) VALUES ($uid,$uid,'$login_date','$user_ip', '".$_course['real_id']."' , '$session_id' , '$access_url_id' )";
 		} else {
 		} else {
-            $query = "REPLACE INTO ".$online_table ." (login_id,login_user_id,login_date,login_ip, session_id, access_url_id) VALUES ($uid,$uid,'$login_date','$login_ip', '$session_id', '$access_url_id')";
+            $query = "REPLACE INTO ".$online_table ." (login_id,login_user_id,login_date,user_ip, session_id, access_url_id) VALUES ($uid,$uid,'$login_date','$user_ip', '$session_id', '$access_url_id')";
 		}
 		}
 		@Database::query($query);
 		@Database::query($query);
 	}
 	}

+ 32 - 6
main/inc/lib/sessionmanager.lib.php

@@ -434,7 +434,7 @@ class SessionManager
                                 ";
                                 ";
         }
         }
 
 
-        $select = "SELECT * FROM (SELECT
+        $select = "SELECT DISTINCT * FROM (SELECT
                 IF (
                 IF (
 					(s.date_start <= '$today' AND '$today' <= s.date_end) OR
 					(s.date_start <= '$today' AND '$today' <= s.date_end) OR
                     (s.nb_days_access_before_beginning > 0 AND DATEDIFF(s.date_start,'" . $today . "' " . ") <= s.nb_days_access_before_beginning) OR
                     (s.nb_days_access_before_beginning > 0 AND DATEDIFF(s.date_start,'" . $today . "' " . ") <= s.nb_days_access_before_beginning) OR
@@ -1271,17 +1271,17 @@ class SessionManager
 
 
         foreach ($return as $key => $info) {
         foreach ($return as $key => $info) {
             //Search for ip, we do less querys if we iterate the final array
             //Search for ip, we do less querys if we iterate the final array
-            $sql = sprintf("SELECT login_ip FROM $track_e_login WHERE login_user_id = %d AND login_date < '%s' ORDER BY login_date DESC LIMIT 1", $info['user_id'], $info['logindate']); //TODO add select by user too
+            $sql = sprintf("SELECT user_ip FROM $track_e_login WHERE login_user_id = %d AND login_date < '%s' ORDER BY login_date DESC LIMIT 1", $info['user_id'], $info['logindate']); //TODO add select by user too
             $result = Database::query($sql);
             $result = Database::query($sql);
             $ip = Database::fetch_assoc($result);
             $ip = Database::fetch_assoc($result);
             //if no ip founded, we search the closest higher ip
             //if no ip founded, we search the closest higher ip
-            if (empty($ip['login_ip'])) {
-                $sql = sprintf("SELECT login_ip FROM $track_e_login WHERE login_user_id = %d AND login_date > '%s'  ORDER BY login_date ASC LIMIT 1", $info['user_id'], $info['logindate']); //TODO add select by user too
+            if (empty($ip['user_ip'])) {
+                $sql = sprintf("SELECT user_ip FROM $track_e_login WHERE login_user_id = %d AND login_date > '%s'  ORDER BY login_date ASC LIMIT 1", $info['user_id'], $info['logindate']); //TODO add select by user too
                 $result = Database::query($sql);
                 $result = Database::query($sql);
                 $ip = Database::fetch_assoc($result);
                 $ip = Database::fetch_assoc($result);
             }
             }
             #add ip to final array
             #add ip to final array
-            $return[$key]['ip'] = $ip['login_ip'];
+            $return[$key]['ip'] = $ip['user_ip'];
         }
         }
         return $return;
         return $return;
     }
     }
@@ -5485,7 +5485,19 @@ class SessionManager
                     )
                     )
                 )
                 )
             );
             );
-
+            $whereFieldVariables = array();
+            $whereFieldIds = array();
+            if (
+                is_array($fieldsArray) &&
+                count($fieldsArray) > 0
+            ) {
+                $whereParams = '?';
+                for ($i = 1; $i < count($fieldsArray); $i++) {
+                    $whereParams .= ', ?';
+                }
+                $whereFieldVariables = 'field_variable IN ( ' . $whereParams .' )';
+                $whereFieldIds = 'field_id IN ( ' . $whereParams .  ' )';
+            }
             // Get session fields
             // Get session fields
             $extraField = new ExtraField('session');
             $extraField = new ExtraField('session');
             $questionMarks = substr(str_repeat('?, ', count($fieldsArray)), 0, -2);
             $questionMarks = substr(str_repeat('?, ', count($fieldsArray)), 0, -2);
@@ -5794,4 +5806,18 @@ class SessionManager
 
 
         return $resultData;
         return $resultData;
     }
     }
+
+    public static function isValidId($sessionId)
+    {
+        $sessionId = intval($sessionId);
+        if ($sessionId > 0) {
+            $rows = Database::select('id', Database::get_main_table(TABLE_MAIN_SESSION), array('where' => array('id = ?' => $sessionId)));
+            if (!empty($rows)) {
+
+                return true;
+            }
+        }
+
+        return false;
+    }
 }
 }

+ 8 - 8
main/inc/lib/tracking.lib.php

@@ -119,7 +119,7 @@ class Tracking
         $TBL_LP_VIEW = Database :: get_course_table(TABLE_LP_VIEW);
         $TBL_LP_VIEW = Database :: get_course_table(TABLE_LP_VIEW);
         $tbl_quiz_questions = Database :: get_course_table(TABLE_QUIZ_QUESTION);
         $tbl_quiz_questions = Database :: get_course_table(TABLE_QUIZ_QUESTION);
         $TBL_QUIZ = Database :: get_course_table(TABLE_QUIZ_TEST);
         $TBL_QUIZ = Database :: get_course_table(TABLE_QUIZ_TEST);
-        $tbl_stats_exercices = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $tbl_stats_exercices = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $tbl_stats_attempts = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
         $tbl_stats_attempts = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
 
 
         $sql = "SELECT max(view_count)
         $sql = "SELECT max(view_count)
@@ -1606,7 +1606,7 @@ class Tracking
     	if (!empty($course_info)) {
     	if (!empty($course_info)) {
     		// table definition
     		// table definition
     		$tbl_course_quiz     = Database::get_course_table(TABLE_QUIZ_TEST);
     		$tbl_course_quiz     = Database::get_course_table(TABLE_QUIZ_TEST);
-    		$tbl_stats_exercise  = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+    		$tbl_stats_exercise  = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
 
 
     		// Compose a filter based on optional exercise given
     		// Compose a filter based on optional exercise given
     		$condition_quiz = "";
     		$condition_quiz = "";
@@ -1756,7 +1756,7 @@ class Tracking
 
 
     	$lp_id = intval($lp_id);
     	$lp_id = intval($lp_id);
         $lp_item_id = intval($lp_item_id);
         $lp_item_id = intval($lp_item_id);
-    	$tbl_stats_exercices = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+    	$tbl_stats_exercices = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
 
 
     	$sql = "SELECT COUNT(ex.exe_id) as essais FROM $tbl_stats_exercices AS ex
     	$sql = "SELECT COUNT(ex.exe_id) as essais FROM $tbl_stats_exercices AS ex
                 WHERE  ex.exe_cours_id = '$course_code'
                 WHERE  ex.exe_cours_id = '$course_code'
@@ -1797,7 +1797,7 @@ class Tracking
         if (empty($exercise_list)) {
         if (empty($exercise_list)) {
             return '0%';
             return '0%';
         }
         }
-        $tbl_stats_exercices = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $tbl_stats_exercices = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $exercise_list = array_keys($exercise_list);
         $exercise_list = array_keys($exercise_list);
         $exercise_list = array_map('intval', $exercise_list);
         $exercise_list = array_map('intval', $exercise_list);
 
 
@@ -2123,7 +2123,7 @@ class Tracking
         }
         }
 
 
         if ($debug) echo '<h1>Tracking::get_avg_student_score</h1>';
         if ($debug) echo '<h1>Tracking::get_avg_student_score</h1>';
-        $tbl_stats_exercices = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $tbl_stats_exercices = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $tbl_stats_attempts = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
         $tbl_stats_attempts = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
 
 
         $course = api_get_course_info($course_code);
         $course = api_get_course_info($course_code);
@@ -3724,7 +3724,7 @@ class Tracking
                 'start_date'=> 'login_course_date',
                 'start_date'=> 'login_course_date',
                 'end_date'  => 'logout_course_date',
                 'end_date'  => 'logout_course_date',
                 ),*/
                 ),*/
-            TABLE_STATISTIC_TRACK_E_EXERCICES => array(
+            TABLE_STATISTIC_TRACK_E_EXERCISES => array(
                 'course'    => 'c_id',
                 'course'    => 'c_id',
                 'session'   => 'session_id',
                 'session'   => 'session_id',
                 'user'      => 'exe_user_id',
                 'user'      => 'exe_user_id',
@@ -5189,7 +5189,7 @@ class Tracking
         $tquiz_answer = Database::get_course_table(TABLE_QUIZ_ANSWER);
         $tquiz_answer = Database::get_course_table(TABLE_QUIZ_ANSWER);
         $tquiz_question = Database::get_course_table(TABLE_QUIZ_QUESTION);
         $tquiz_question = Database::get_course_table(TABLE_QUIZ_QUESTION);
         $tquiz_rel_question = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
         $tquiz_rel_question = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
-        $ttrack_exercises  = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+        $ttrack_exercises  = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
         $ttrack_attempt    = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
         $ttrack_attempt    = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
 
 
         $sessions = array();
         $sessions = array();
@@ -6534,7 +6534,7 @@ class TrackingUserLog
             return false;
             return false;
         }
         }
         $table_login = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
         $table_login = Database :: get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
-        $sql_ip = "SELECT login_date, login_ip FROM $table_login WHERE login_user_id = $user_id AND login_date < '$event_date' ORDER BY login_date DESC LIMIT 1";
+        $sql_ip = "SELECT login_date, user_ip FROM $table_login WHERE login_user_id = $user_id AND login_date < '$event_date' ORDER BY login_date DESC LIMIT 1";
         $ip = '';
         $ip = '';
         $res_ip = Database::query($sql_ip);
         $res_ip = Database::query($sql_ip);
         if ($res_ip !== false && Database::num_rows($res_ip)>0) {
         if ($res_ip !== false && Database::num_rows($res_ip)>0) {

+ 5 - 2
main/install/db_main.sql

@@ -883,7 +883,8 @@ VALUES
 ('tool_visible_by_default_at_creation','forums','checkbox','Tools','true','ToolVisibleByDefaultAtCreationTitle','ToolVisibleByDefaultAtCreationComment',NULL,'Forums', 1),
 ('tool_visible_by_default_at_creation','forums','checkbox','Tools','true','ToolVisibleByDefaultAtCreationTitle','ToolVisibleByDefaultAtCreationComment',NULL,'Forums', 1),
 ('tool_visible_by_default_at_creation','quiz','checkbox','Tools','true','ToolVisibleByDefaultAtCreationTitle','ToolVisibleByDefaultAtCreationComment',NULL,'Quiz', 1),
 ('tool_visible_by_default_at_creation','quiz','checkbox','Tools','true','ToolVisibleByDefaultAtCreationTitle','ToolVisibleByDefaultAtCreationComment',NULL,'Quiz', 1),
 ('tool_visible_by_default_at_creation','gradebook','checkbox','Tools','true','ToolVisibleByDefaultAtCreationTitle','ToolVisibleByDefaultAtCreationComment',NULL,'Gradebook', 1),
 ('tool_visible_by_default_at_creation','gradebook','checkbox','Tools','true','ToolVisibleByDefaultAtCreationTitle','ToolVisibleByDefaultAtCreationComment',NULL,'Gradebook', 1),
-('chamilo_database_version', NULL, 'textfield',NULL, '1.10.0.10','DatabaseVersion','', NULL, NULL, 0);
+('prevent_session_admins_to_manage_all_users', NULL, 'radio', 'Session', 'false', 'PreventSessionAdminsToManageAllUsersTitle', 'PreventSessionAdminsToManageAllUsersComment', NULL, NULL, 1),
+('chamilo_database_version', NULL, 'textfield',NULL, '1.10.0.12','DatabaseVersion','', NULL, NULL, 0);
 UNLOCK TABLES;
 UNLOCK TABLES;
 /*!40000 ALTER TABLE settings_current ENABLE KEYS */;
 /*!40000 ALTER TABLE settings_current ENABLE KEYS */;
 
 
@@ -1223,7 +1224,9 @@ VALUES
 ('show_hot_courses', 'true', 'Yes'),
 ('show_hot_courses', 'true', 'Yes'),
 ('show_hot_courses', 'false', 'No'),
 ('show_hot_courses', 'false', 'No'),
 ('enable_webcam_clip', 'true', 'Yes'),
 ('enable_webcam_clip', 'true', 'Yes'),
-('enable_webcam_clip', 'false', 'No');
+('enable_webcam_clip', 'false', 'No'),
+('prevent_session_admins_to_manage_all_users', 'true', 'Yes'),
+('prevent_session_admins_to_manage_all_users', 'false', 'No');
 
 
 UNLOCK TABLES;
 UNLOCK TABLES;
 
 

+ 19 - 16
main/install/db_stats.sql

@@ -58,6 +58,7 @@ CREATE TABLE track_e_access (
   c_id int not null,
   c_id int not null,
   access_tool varchar(30) default NULL,
   access_tool varchar(30) default NULL,
   access_session_id int NOT NULL default 0,
   access_session_id int NOT NULL default 0,
+  user_ip varchar(39) NOT NULL default '',
   PRIMARY KEY  (access_id),
   PRIMARY KEY  (access_id),
   KEY access_user_id (access_user_id),
   KEY access_user_id (access_user_id),
   KEY access_c_id (c_id),
   KEY access_c_id (c_id),
@@ -108,8 +109,8 @@ CREATE TABLE track_e_downloads (
   KEY down_cours_id (down_cours_id)
   KEY down_cours_id (down_cours_id)
 );
 );
 
 
-DROP TABLE IF EXISTS track_e_exercices;
-CREATE TABLE track_e_exercices (
+DROP TABLE IF EXISTS track_e_exercises;
+CREATE TABLE track_e_exercises (
   exe_id int NOT NULL auto_increment,
   exe_id int NOT NULL auto_increment,
   exe_user_id int unsigned default NULL,
   exe_user_id int unsigned default NULL,
   exe_date datetime NOT NULL default '0000-00-00 00:00:00',
   exe_date datetime NOT NULL default '0000-00-00 00:00:00',
@@ -118,23 +119,24 @@ CREATE TABLE track_e_exercices (
   exe_exo_id mediumint unsigned NOT NULL default 0,
   exe_exo_id mediumint unsigned NOT NULL default 0,
   exe_result float(6,2) NOT NULL default 0,
   exe_result float(6,2) NOT NULL default 0,
   exe_weighting float(6,2) NOT NULL default 0,
   exe_weighting float(6,2) NOT NULL default 0,
+  user_ip varchar(39) NOT NULL default '',
   PRIMARY KEY  (exe_id),
   PRIMARY KEY  (exe_id),
   KEY exe_user_id (exe_user_id),
   KEY exe_user_id (exe_user_id),
   KEY exe_cours_id (exe_cours_id)
   KEY exe_cours_id (exe_cours_id)
 );
 );
 
 
-ALTER TABLE track_e_exercices ADD status varchar(20) NOT NULL default '';
-ALTER TABLE track_e_exercices ADD data_tracking text NOT NULL default '';
-ALTER TABLE track_e_exercices ADD start_date datetime NOT NULL default '0000-00-00 00:00:00';
-ALTER TABLE track_e_exercices ADD steps_counter SMALLINT UNSIGNED NOT NULL default 0;
-ALTER TABLE track_e_exercices ADD session_id SMALLINT UNSIGNED NOT NULL default 0;
-ALTER TABLE track_e_exercices ADD INDEX ( session_id ) ;
-ALTER TABLE track_e_exercices ADD orig_lp_id int  NOT NULL default 0;
-ALTER TABLE track_e_exercices ADD orig_lp_item_id int  NOT NULL default 0;
-ALTER TABLE track_e_exercices ADD exe_duration int UNSIGNED NOT NULL default 0;
-ALTER TABLE track_e_exercices ADD COLUMN expired_time_control datetime NOT NULL DEFAULT '0000-00-00 00:00:00';
-ALTER TABLE track_e_exercices ADD COLUMN orig_lp_item_view_id INT NOT NULL DEFAULT 0;
-ALTER TABLE track_e_exercices ADD COLUMN questions_to_check TEXT  NOT NULL DEFAULT '';
+ALTER TABLE track_e_exercises ADD status varchar(20) NOT NULL default '';
+ALTER TABLE track_e_exercises ADD data_tracking text NOT NULL default '';
+ALTER TABLE track_e_exercises ADD start_date datetime NOT NULL default '0000-00-00 00:00:00';
+ALTER TABLE track_e_exercises ADD steps_counter SMALLINT UNSIGNED NOT NULL default 0;
+ALTER TABLE track_e_exercises ADD session_id SMALLINT UNSIGNED NOT NULL default 0;
+ALTER TABLE track_e_exercises ADD INDEX ( session_id ) ;
+ALTER TABLE track_e_exercises ADD orig_lp_id int  NOT NULL default 0;
+ALTER TABLE track_e_exercises ADD orig_lp_item_id int  NOT NULL default 0;
+ALTER TABLE track_e_exercises ADD exe_duration int UNSIGNED NOT NULL default 0;
+ALTER TABLE track_e_exercises ADD COLUMN expired_time_control datetime NOT NULL DEFAULT '0000-00-00 00:00:00';
+ALTER TABLE track_e_exercises ADD COLUMN orig_lp_item_view_id INT NOT NULL DEFAULT 0;
+ALTER TABLE track_e_exercises ADD COLUMN questions_to_check TEXT  NOT NULL DEFAULT '';
 
 
 DROP TABLE IF EXISTS track_e_attempt;
 DROP TABLE IF EXISTS track_e_attempt;
 CREATE TABLE track_e_attempt (
 CREATE TABLE track_e_attempt (
@@ -205,7 +207,7 @@ CREATE TABLE track_e_login (
   login_id int NOT NULL auto_increment,
   login_id int NOT NULL auto_increment,
   login_user_id int unsigned NOT NULL default 0,
   login_user_id int unsigned NOT NULL default 0,
   login_date datetime NOT NULL default '0000-00-00 00:00:00',
   login_date datetime NOT NULL default '0000-00-00 00:00:00',
-  login_ip varchar(39) NOT NULL default '',
+  user_ip varchar(39) NOT NULL default '',
   logout_date datetime NULL default NULL,
   logout_date datetime NULL default NULL,
   PRIMARY KEY  (login_id),
   PRIMARY KEY  (login_id),
   KEY login_user_id (login_user_id)
   KEY login_user_id (login_user_id)
@@ -216,7 +218,7 @@ CREATE TABLE track_e_online (
   login_id int NOT NULL auto_increment,
   login_id int NOT NULL auto_increment,
   login_user_id int unsigned NOT NULL default 0,
   login_user_id int unsigned NOT NULL default 0,
   login_date datetime NOT NULL default '0000-00-00 00:00:00',
   login_date datetime NOT NULL default '0000-00-00 00:00:00',
-  login_ip varchar(39) NOT NULL default '',
+  user_ip varchar(39) NOT NULL default '',
   course varchar(40) default NULL,
   course varchar(40) default NULL,
   c_id int NOT NULL,
   c_id int NOT NULL,
   session_id INT NOT NULL DEFAULT 0,
   session_id INT NOT NULL DEFAULT 0,
@@ -258,6 +260,7 @@ CREATE TABLE track_e_course_access (
   logout_course_date datetime default NULL,
   logout_course_date datetime default NULL,
   counter int NOT NULL,
   counter int NOT NULL,
   session_id int NOT NULL default 0,
   session_id int NOT NULL default 0,
+  user_ip varchar(39) NOT NULL default '',
   PRIMARY KEY  (course_access_id)
   PRIMARY KEY  (course_access_id)
 );
 );
 
 

+ 12 - 0
main/install/install.lib.php

@@ -1416,6 +1416,18 @@ function display_requirements($installType, $badUpdatePath, $updatePath = '', $u
             @chmod($checked_writable, $perm);
             @chmod($checked_writable, $perm);
         }
         }
 
 
+        $checkedWritable = api_get_path(SYS_CODE_PATH).'upload/sessions/';
+        if (!is_writable($checkedWritable)) {
+            $notwritable[] = $checkedWritable;
+            @chmod($checkedWritable, $perm);
+        }
+
+        $checkedWritable = api_get_path(SYS_CODE_PATH).'upload/courses/';
+        if (!is_writable($checkedWritable)) {
+            $notwritable[] = $checkedWritable;
+            @chmod($checkedWritable, $perm);
+        }
+
         $checked_writable = api_get_path(SYS_CODE_PATH).'default_course_document/images/';
         $checked_writable = api_get_path(SYS_CODE_PATH).'default_course_document/images/';
         if (!is_writable($checked_writable)) {
         if (!is_writable($checked_writable)) {
             $notwritable[] = $checked_writable;
             $notwritable[] = $checked_writable;

+ 1 - 1
main/install/migrate-db-1.9.0-1.10.0-post.sql

@@ -17,7 +17,7 @@
 ALTER TABLE track_e_access DROP COLUMN access_cours_code;
 ALTER TABLE track_e_access DROP COLUMN access_cours_code;
 ALTER TABLE track_e_default DROP COLUMN default_cours_code;
 ALTER TABLE track_e_default DROP COLUMN default_cours_code;
 ALTER TABLE track_e_lastaccess DROP COLUMN access_cours_code;
 ALTER TABLE track_e_lastaccess DROP COLUMN access_cours_code;
-ALTER TABLE track_e_exercices DROP COLUMN exe_cours_id;
+ALTER TABLE track_e_exercises DROP COLUMN exe_cours_id;
 ALTER TABLE track_e_downloads DROP COLUMN down_cours_id;
 ALTER TABLE track_e_downloads DROP COLUMN down_cours_id;
 ALTER TABLE track_e_hotpotatoes DROP COLUMN exe_cours_id;
 ALTER TABLE track_e_hotpotatoes DROP COLUMN exe_cours_id;
 ALTER TABLE track_e_links DROP COLUMN links_cours_id;
 ALTER TABLE track_e_links DROP COLUMN links_cours_id;

+ 13 - 2
main/install/migrate-db-1.9.0-1.10.0-pre.sql

@@ -36,12 +36,14 @@ ALTER TABLE skill ADD COLUMN criteria text DEFAULT '';
 
 
 ALTER TABLE gradebook_category ADD COLUMN generate_certificates TINYINT NOT NULL DEFAULT 0;
 ALTER TABLE gradebook_category ADD COLUMN generate_certificates TINYINT NOT NULL DEFAULT 0;
 
 
+RENAME TABLE track_e_exercices TO track_e_exercises;
+
 ALTER TABLE session_rel_user ADD COLUMN duration int;
 ALTER TABLE session_rel_user ADD COLUMN duration int;
 
 
 ALTER TABLE track_e_access ADD COLUMN c_id int NOT NULL;
 ALTER TABLE track_e_access ADD COLUMN c_id int NOT NULL;
 ALTER TABLE track_e_default ADD COLUMN c_id int NOT NULL;
 ALTER TABLE track_e_default ADD COLUMN c_id int NOT NULL;
 ALTER TABLE track_e_lastaccess ADD COLUMN c_id int NOT NULL;
 ALTER TABLE track_e_lastaccess ADD COLUMN c_id int NOT NULL;
-ALTER TABLE track_e_exercices ADD COLUMN c_id int NOT NULL;
+ALTER TABLE track_e_exercises ADD COLUMN c_id int NOT NULL;
 ALTER TABLE track_e_downloads ADD COLUMN c_id int NOT NULL;
 ALTER TABLE track_e_downloads ADD COLUMN c_id int NOT NULL;
 ALTER TABLE track_e_hotpotatoes ADD COLUMN c_id int NOT NULL;
 ALTER TABLE track_e_hotpotatoes ADD COLUMN c_id int NOT NULL;
 ALTER TABLE track_e_links ADD COLUMN c_id int NOT NULL;
 ALTER TABLE track_e_links ADD COLUMN c_id int NOT NULL;
@@ -52,8 +54,17 @@ ALTER TABLE track_e_attempt ADD COLUMN c_id int NOT NULL;
 DELETE FROM settings_current WHERE variable = 'wcag_anysurfer_public_pages';
 DELETE FROM settings_current WHERE variable = 'wcag_anysurfer_public_pages';
 DELETE FROM settings_options WHERE variable = 'wcag_anysurfer_public_pages';
 DELETE FROM settings_options WHERE variable = 'wcag_anysurfer_public_pages';
 
 
+INSERT INTO settings_current (variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url_changeable) VALUES ('prevent_session_admins_to_manage_all_users', NULL, 'radio', 'Session', 'false', 'PreventSessionAdminsToManageAllUsersTitle', 'PreventSessionAdminsToManageAllUsersComment', NULL, NULL, 1);
+INSERT INTO settings_options (variable, value, display_text) VALUES ('prevent_session_admins_to_manage_all_users', 'true', 'Yes'), ('prevent_session_admins_to_manage_all_users', 'false', 'No');
+
+ALTER TABLE track_e_access ADD COLUMN user_ip varchar(39) NOT NULL default '';
+ALTER TABLE track_e_exercises ADD COLUMN user_ip varchar(39) NOT NULL default '';
+ALTER TABLE track_e_course_access ADD COLUMN user_ip varchar(39) NOT NULL default '';
+ALTER TABLE track_e_online CHANGE COLUMN login_ip user_ip varchar(39) NOT NULL DEFAULT '';
+ALTER TABLE track_e_login CHANGE COLUMN login_ip user_ip varchar(39) NOT NULL DEFAULT '';
+
 -- Do not move this query
 -- Do not move this query
-UPDATE settings_current SET selected_value = '1.10.0.10' WHERE variable = 'chamilo_database_version';
+UPDATE settings_current SET selected_value = '1.10.0.12' WHERE variable = 'chamilo_database_version';
 
 
 -- xxCOURSExx
 -- xxCOURSExx
 
 

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

@@ -112,7 +112,7 @@ if (defined('SYSTEM_INSTALLATION')) {
                     'track_e_course_access' => 'course_code',
                     'track_e_course_access' => 'course_code',
                     'track_e_online' => 'course',
                     'track_e_online' => 'course',
                     'track_e_attempt' => 'course_code',
                     'track_e_attempt' => 'course_code',
-                    'track_e_exercices' => 'exe_cours_id'
+                    'track_e_exercises' => 'exe_cours_id'
                 );
                 );
 
 
                 foreach ($fields as $table => $key) {
                 foreach ($fields as $table => $key) {

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

@@ -316,7 +316,10 @@ $YourVersionNotUpToDate = "Your version is not up-to-date";
 $Hotpotatoes = "Hotpotatoes";
 $Hotpotatoes = "Hotpotatoes";
 $CourseCategoriesAreGlobal = "Course categories are global over multiple portals configurations. Changes are only allowed in the main administrative portal.";
 $CourseCategoriesAreGlobal = "Course categories are global over multiple portals configurations. Changes are only allowed in the main administrative portal.";
 $UserIsNotATeacher = "User is not a teacher";
 $UserIsNotATeacher = "User is not a teacher";
+$ConvertToMultipleAnswer = "Convert to multiple answer";
 $ThisItemIsInvisibleForStudentsButYouHaveAccessAsTeacher = "This item is invisible for learner but you have access as teacher.";
 $ThisItemIsInvisibleForStudentsButYouHaveAccessAsTeacher = "This item is invisible for learner but you have access as teacher.";
+$PreventSessionAdminsToManageAllUsersTitle = "Prevent session admins to manage all users";
+$AllowSessionAdminsToSeeAllUsersComment = "When this option is not enabled (default), session administrators can only see the users they have created.";
 $DeleteAllAttendances = "Delete all created attendances";
 $DeleteAllAttendances = "Delete all created attendances";
 $Unsubscribe = "Unsubscribe";
 $Unsubscribe = "Unsubscribe";
 $AddForum = "Add a forum";
 $AddForum = "Add a forum";
@@ -1060,9 +1063,12 @@ $CourseProgram = "Description";
 $ThisCourseDescriptionIsEmpty = "There is no course description so far.";
 $ThisCourseDescriptionIsEmpty = "There is no course description so far.";
 $QuestionPlan = "Help";
 $QuestionPlan = "Help";
 $NewBloc = "Other";
 $NewBloc = "Other";
+$InProcess = "In process";
 $CourseDescriptionUpdated = "The description has been updated";
 $CourseDescriptionUpdated = "The description has been updated";
 $CourseDescriptionDeleted = "Description has been deleted";
 $CourseDescriptionDeleted = "Description has been deleted";
+$PreventSessionAdminsToManageAllUsersComment = "By enabling this option, session admins will only be able to see, in the administration page, the users they created.";
 $FieldTypeFile = "File upload";
 $FieldTypeFile = "File upload";
+$ConvertToUniqueAnswer = "Convert to unique answer";
 $NextWeek = "Next Week";
 $NextWeek = "Next Week";
 $DragAndDropAnElementHere = "Drag and drop an element here";
 $DragAndDropAnElementHere = "Drag and drop an element here";
 $ThereAreNoRegisteredDatetimeYet = "There is no date/time registered yet";
 $ThereAreNoRegisteredDatetimeYet = "There is no date/time registered yet";
@@ -1076,6 +1082,7 @@ $AttendanceCalendar = "Attendance calendar";
 $QualifyAttendanceGradebook = "Grade the attendance list in the assessment tool";
 $QualifyAttendanceGradebook = "Grade the attendance list in the assessment tool";
 $CreateANewAttendance = "Create a new attendance list";
 $CreateANewAttendance = "Create a new attendance list";
 $Attendance = "Attendance";
 $Attendance = "Attendance";
+$AllowSessionAdminsToSeeAllUsersTitle = "Allow session administrators to see all users";
 $GeneralDescription = "Description";
 $GeneralDescription = "Description";
 $GeneralDescriptionQuestions = "What is the goal of the training? Are there prerequisites? How is this training connected to other training?";
 $GeneralDescriptionQuestions = "What is the goal of the training? Are there prerequisites? How is this training connected to other training?";
 $GeneralDescriptionInformation = "Describe the training (number of hours, sser number, location) and trainer (name, office, Tel., e-mail, office hours . . . .).";
 $GeneralDescriptionInformation = "Describe the training (number of hours, sser number, location) and trainer (name, office, Tel., e-mail, office hours . . . .).";

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

@@ -316,7 +316,10 @@ $YourVersionNotUpToDate = "Su versión está actualizada";
 $Hotpotatoes = "Hotpotatoes";
 $Hotpotatoes = "Hotpotatoes";
 $CourseCategoriesAreGlobal = "Las categorías de cursos son globales en la configuración de múltiples portales, pero los cambios son permitidos solamente en la sesión administrativa del portal principal.";
 $CourseCategoriesAreGlobal = "Las categorías de cursos son globales en la configuración de múltiples portales, pero los cambios son permitidos solamente en la sesión administrativa del portal principal.";
 $UserIsNotATeacher = "El usuario no es un profesor.";
 $UserIsNotATeacher = "El usuario no es un profesor.";
+$ConvertToMultipleAnswer = "Convertir a respuesta múltiple";
 $ThisItemIsInvisibleForStudentsButYouHaveAccessAsTeacher = "Este item no es visible para un estudiante pero podrá acceder a él como profesor";
 $ThisItemIsInvisibleForStudentsButYouHaveAccessAsTeacher = "Este item no es visible para un estudiante pero podrá acceder a él como profesor";
+$PreventSessionAdminsToManageAllUsersTitle = "Impedir a los admins de sesiones de gestionar todos los usuarios";
+$AllowSessionAdminsToSeeAllUsersComment = "Cuando esta opción está desactivada los administradores de sesión solamente podrán ver sus usuarios.";
 $DeleteAllAttendances = "Eliminar todas las asistencias creadas";
 $DeleteAllAttendances = "Eliminar todas las asistencias creadas";
 $Unsubscribe = "Dar de baja";
 $Unsubscribe = "Dar de baja";
 $AddForum = "Añadir un foro";
 $AddForum = "Añadir un foro";
@@ -1060,9 +1063,12 @@ $CourseProgram = "Descripción del curso";
 $ThisCourseDescriptionIsEmpty = "Descripción no disponible";
 $ThisCourseDescriptionIsEmpty = "Descripción no disponible";
 $QuestionPlan = "Cuestiones clave";
 $QuestionPlan = "Cuestiones clave";
 $NewBloc = "Apartado personalizado";
 $NewBloc = "Apartado personalizado";
+$InProcess = "En proceso";
 $CourseDescriptionUpdated = "La descripción del curso ha sido actualizada";
 $CourseDescriptionUpdated = "La descripción del curso ha sido actualizada";
 $CourseDescriptionDeleted = "La descripción del curso ha sido borrada";
 $CourseDescriptionDeleted = "La descripción del curso ha sido borrada";
+$PreventSessionAdminsToManageAllUsersComment = "Por activar esta opción, los administradores de sesiones podrán ver, en las páginas de administración, exclúsivamente los usuarios que ellos mismos han creado.";
 $FieldTypeFile = "Subida de archivo";
 $FieldTypeFile = "Subida de archivo";
+$ConvertToUniqueAnswer = "Convertir a respuesta única";
 $NextWeek = "Semana siguiente";
 $NextWeek = "Semana siguiente";
 $DragAndDropAnElementHere = "Arrastrar y soltar un elemento aquí";
 $DragAndDropAnElementHere = "Arrastrar y soltar un elemento aquí";
 $ThereAreNoRegisteredDatetimeYet = "Aún no hay registrada ninguna fecha/hora";
 $ThereAreNoRegisteredDatetimeYet = "Aún no hay registrada ninguna fecha/hora";
@@ -1076,6 +1082,7 @@ $AttendanceCalendar = "Calendario de asistencia";
 $QualifyAttendanceGradebook = "Calificar la lista de asistencia";
 $QualifyAttendanceGradebook = "Calificar la lista de asistencia";
 $CreateANewAttendance = "Crear una lista de asistencia";
 $CreateANewAttendance = "Crear una lista de asistencia";
 $Attendance = "Asistencia";
 $Attendance = "Asistencia";
+$AllowSessionAdminsToSeeAllUsersTitle = "Permitir a los administradores de sesión ver todos los usuarios";
 $GeneralDescription = "Descripción general";
 $GeneralDescription = "Descripción general";
 $GeneralDescriptionQuestions = "¿Cuál es el objetivo de este curso? ¿Hay requisitos previos? ¿Qué relación tiene con otros cursos?";
 $GeneralDescriptionQuestions = "¿Cuál es el objetivo de este curso? ¿Hay requisitos previos? ¿Qué relación tiene con otros cursos?";
 $GeneralDescriptionInformation = "Descripción del curso (número de horas, código, lugar donde se desarrollará, etc.). Profesorado (nombre, despacho, teléfono, correo electrónico, etc.).";
 $GeneralDescriptionInformation = "Descripción del curso (número de horas, código, lugar donde se desarrollará, etc.). Profesorado (nombre, despacho, teléfono, correo electrónico, etc.).";

+ 2 - 2
main/mySpace/myStudents.php

@@ -164,7 +164,7 @@ if (isset($_GET['details'])) {
 
 
 // Database Table Definitions
 // Database Table Definitions
 $tbl_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
 $tbl_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
-$tbl_stats_exercices = Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+$tbl_stats_exercices = Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
 
 
 if (isset($_GET['user_id']) && $_GET['user_id'] != "") {
 if (isset($_GET['user_id']) && $_GET['user_id'] != "") {
     $user_id = intval($_GET['user_id']);
     $user_id = intval($_GET['user_id']);
@@ -201,7 +201,7 @@ if ($check) {
                     $session_id
                     $session_id
                 );
                 );
 
 
-                //@todo delete the stats.track_e_exercices records. First implement this http://support.chamilo.org/issues/1334
+                //@todo delete the stats.track_e_exercises records. First implement this http://support.chamilo.org/issues/1334
                 $message = Display::return_message(
                 $message = Display::return_message(
                     get_lang('LPWasReset'),
                     get_lang('LPWasReset'),
                     'success'
                     'success'

+ 1 - 1
main/mySpace/progression.php

@@ -29,7 +29,7 @@ $tbl_course 		= Database :: get_main_table(TABLE_MAIN_COURSE);
 $tbl_user 			= Database :: get_main_table(TABLE_MAIN_USER);
 $tbl_user 			= Database :: get_main_table(TABLE_MAIN_USER);
 $tbl_session_course = Database :: get_main_table(TABLE_MAIN_SESSION_COURSE);
 $tbl_session_course = Database :: get_main_table(TABLE_MAIN_SESSION_COURSE);
 $tbl_session 		= Database :: get_main_table(TABLE_MAIN_SESSION);
 $tbl_session 		= Database :: get_main_table(TABLE_MAIN_SESSION);
-$tbl_track_exercice = Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+$tbl_track_exercice = Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
 
 
 /*
 /*
  	MAIN CODE
  	MAIN CODE

+ 1 - 1
main/mySpace/reussite.php

@@ -27,7 +27,7 @@ $tbl_course 		= Database :: get_main_table(TABLE_MAIN_COURSE);
 $tbl_user 			= Database :: get_main_table(TABLE_MAIN_USER);
 $tbl_user 			= Database :: get_main_table(TABLE_MAIN_USER);
 $tbl_session_course = Database :: get_main_table(TABLE_MAIN_SESSION_COURSE);
 $tbl_session_course = Database :: get_main_table(TABLE_MAIN_SESSION_COURSE);
 $tbl_session 		= Database :: get_main_table(TABLE_MAIN_SESSION);
 $tbl_session 		= Database :: get_main_table(TABLE_MAIN_SESSION);
-$tbl_track_exercice = Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+$tbl_track_exercice = Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
 
 
 /*
 /*
 ===============================================================================
 ===============================================================================

+ 3 - 3
main/newscorm/learnpathItem.class.php

@@ -2511,7 +2511,7 @@ class learnpathItem
                                             if ($returnstatus) {
                                             if ($returnstatus) {
                                                 //AND origin_lp_item_id = '.$user_id.'
                                                 //AND origin_lp_item_id = '.$user_id.'
                                                 $sql = 'SELECT exe_result, exe_weighting
                                                 $sql = 'SELECT exe_result, exe_weighting
-                                                        FROM ' . Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES) . '
+                                                        FROM ' . Database :: get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES) . '
                                                     WHERE   exe_exo_id = ' . $items[$refs_list[$prereqs_string]]->path . '
                                                     WHERE   exe_exo_id = ' . $items[$refs_list[$prereqs_string]]->path . '
                                                         AND exe_user_id = ' . $user_id . '
                                                         AND exe_user_id = ' . $user_id . '
                                                         AND orig_lp_id = ' . $this->lp_id . ' AND orig_lp_item_id = ' . $prereqs_string . '
                                                         AND orig_lp_id = ' . $this->lp_id . ' AND orig_lp_item_id = ' . $prereqs_string . '
@@ -2542,7 +2542,7 @@ class learnpathItem
                                             // Checking in the database.
                                             // Checking in the database.
                                             $sql = 'SELECT exe_result, exe_weighting
                                             $sql = 'SELECT exe_result, exe_weighting
                                                     FROM ' . Database :: get_statistic_table(
                                                     FROM ' . Database :: get_statistic_table(
-                                                    TABLE_STATISTIC_TRACK_E_EXERCICES
+                                                    TABLE_STATISTIC_TRACK_E_EXERCISES
                                                 ) . '
                                                 ) . '
                                                     WHERE exe_exo_id = ' . $items[$refs_list[$prereqs_string]]->path . '
                                                     WHERE exe_exo_id = ' . $items[$refs_list[$prereqs_string]]->path . '
                                                         AND exe_user_id = ' . $user_id . ' AND orig_lp_id = ' . $this->lp_id . ' AND orig_lp_item_id = ' . $prereqs_string . ' ';
                                                         AND exe_user_id = ' . $user_id . ' AND orig_lp_id = ' . $this->lp_id . ' AND orig_lp_item_id = ' . $prereqs_string . ' ';
@@ -3867,7 +3867,7 @@ class learnpathItem
                         $my_status = ' ';
                         $my_status = ' ';
                         $total_time = ' ';
                         $total_time = ' ';
                         if (!empty($_REQUEST['exeId'])) {
                         if (!empty($_REQUEST['exeId'])) {
-                            $TBL_TRACK_EXERCICES = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+                            $TBL_TRACK_EXERCICES = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
 
 
                             $safe_exe_id = intval($_REQUEST['exeId']);
                             $safe_exe_id = intval($_REQUEST['exeId']);
                             $sql = "SELECT start_date,exe_date
                             $sql = "SELECT start_date,exe_date

+ 1 - 1
main/newscorm/lp_view.php

@@ -215,7 +215,7 @@ if (!empty($_REQUEST['exeId']) &&
     global $src;
     global $src;
     $_SESSION['oLP']->items[$_SESSION['oLP']->current]->write_to_db();
     $_SESSION['oLP']->items[$_SESSION['oLP']->current]->write_to_db();
 
 
-    $TBL_TRACK_EXERCICES = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+    $TBL_TRACK_EXERCICES = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
     $TBL_LP_ITEM_VIEW = Database::get_course_table(TABLE_LP_ITEM_VIEW);
     $TBL_LP_ITEM_VIEW = Database::get_course_table(TABLE_LP_ITEM_VIEW);
     $TBL_LP_ITEM = Database::get_course_table(TABLE_LP_ITEM);
     $TBL_LP_ITEM = Database::get_course_table(TABLE_LP_ITEM);
     $safe_item_id = intval($_GET['lp_item_id']);
     $safe_item_id = intval($_GET['lp_item_id']);

+ 1 - 1
main/reports/modules/quiz.php

@@ -26,7 +26,7 @@ function reports_modules_quiz_quizVal($quiz, $key_id) {
 			'session_id, -1 as attempt, exe_result as score, '.
 			'session_id, -1 as attempt, exe_result as score, '.
 			REPORTS_PROGRESS_COMPLETED.' as progress, '.
 			REPORTS_PROGRESS_COMPLETED.' as progress, '.
 			'exe_duration as time, exe_date as ts from '.
 			'exe_duration as time, exe_date as ts from '.
-			Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES).
+			Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES).
 			' where exe_cours_id = '."'".$quiz['course_code']."'".
 			' where exe_cours_id = '."'".$quiz['course_code']."'".
 			' and exe_exo_id='.$quiz['child_id']);
 			' and exe_exo_id='.$quiz['child_id']);
 }
 }

+ 1 - 1
main/tracking/courseLog.php

@@ -150,7 +150,7 @@ $TABLETRACK_ACCESS      = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTA
 $TABLETRACK_LINKS       = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LINKS);
 $TABLETRACK_LINKS       = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LINKS);
 $TABLETRACK_DOWNLOADS   = Database::get_main_table(TABLE_STATISTIC_TRACK_E_DOWNLOADS);
 $TABLETRACK_DOWNLOADS   = Database::get_main_table(TABLE_STATISTIC_TRACK_E_DOWNLOADS);
 $TABLETRACK_ACCESS_2    = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS);
 $TABLETRACK_ACCESS_2    = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCESS);
-$TABLETRACK_EXERCISES 	= Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+$TABLETRACK_EXERCISES 	= Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
 $TABLECOURSUSER	        = Database::get_main_table(TABLE_MAIN_COURSE_USER);
 $TABLECOURSUSER	        = Database::get_main_table(TABLE_MAIN_COURSE_USER);
 $TABLECOURSE	        = Database::get_main_table(TABLE_MAIN_COURSE);
 $TABLECOURSE	        = Database::get_main_table(TABLE_MAIN_COURSE);
 $table_user             = Database::get_main_table(TABLE_MAIN_USER);
 $table_user             = Database::get_main_table(TABLE_MAIN_USER);

+ 1 - 1
main/tracking/exams.php

@@ -468,7 +468,7 @@ function export_complete_report_xls($filename, $array)
 
 
 function processStudentList($filter_score, $global, $exercise, $courseInfo, $sessionId, $newSessionList)
 function processStudentList($filter_score, $global, $exercise, $courseInfo, $sessionId, $newSessionList)
 {
 {
-    $exerciseStatsTable = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+    $exerciseStatsTable = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
 
 
     if (empty($sessionId)) {
     if (empty($sessionId)) {
         $students = CourseManager::get_student_list_from_course_code(
         $students = CourseManager::get_student_list_from_course_code(

+ 1 - 1
main/tracking/personnalLog.php

@@ -51,7 +51,7 @@ $TABLETRACK_ACCESS      = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ACCES
 $TABLETRACK_LINKS 		= Database::get_main_table(TABLE_STATISTIC_TRACK_E_LINKS);
 $TABLETRACK_LINKS 		= Database::get_main_table(TABLE_STATISTIC_TRACK_E_LINKS);
 $TABLETRACK_DOWNLOADS 	= Database::get_main_table(TABLE_STATISTIC_TRACK_E_DOWNLOADS);
 $TABLETRACK_DOWNLOADS 	= Database::get_main_table(TABLE_STATISTIC_TRACK_E_DOWNLOADS);
 $TABLETRACK_LOGIN 		= Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
 $TABLETRACK_LOGIN 		= Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
-$TABLETRACK_EXERCICES   = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+$TABLETRACK_EXERCICES   = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
 
 
 
 
 $limitOfDisplayedLogins = 25; // number of logins to display
 $limitOfDisplayedLogins = 25; // number of logins to display

+ 9 - 7
plugin/advanced_subscription/ajax/advanced_subscription.ajax.php

@@ -21,7 +21,9 @@ $data['currentUserId'] = intval($_REQUEST['current_user_id']);
 $data['studentUserId'] = intval($_REQUEST['u']);
 $data['studentUserId'] = intval($_REQUEST['u']);
 $data['queueId'] = intval($_REQUEST['q']);
 $data['queueId'] = intval($_REQUEST['q']);
 $data['newStatus'] = intval($_REQUEST['e']);
 $data['newStatus'] = intval($_REQUEST['e']);
-$data['is_connected'] = isset($_REQUEST['is_connected']) ? boolval($_REQUEST['is_connected']) : false;
+// Student always is connected
+// $data['is_connected'] = isset($_REQUEST['is_connected']) ? boolval($_REQUEST['is_connected']) : false;
+$data['is_connected'] = true;
 $data['profile_completed'] = isset($_REQUEST['profile_completed']) ? floatval($_REQUEST['profile_completed']) : 0;
 $data['profile_completed'] = isset($_REQUEST['profile_completed']) ? floatval($_REQUEST['profile_completed']) : 0;
 // Init result array
 // Init result array
 $result = array('error' => true, 'errorMessage' => get_lang('ThereWasAnError'));
 $result = array('error' => true, 'errorMessage' => get_lang('ThereWasAnError'));
@@ -227,20 +229,20 @@ if ($verified) {
                     $data['signature'] = api_get_setting('Institution');
                     $data['signature'] = api_get_setting('Institution');
                     $data['admin_view_url'] = api_get_path(WEB_PLUGIN_PATH) . 'advanced_subscription/src/admin_view.php?s=' . $data['sessionId'];
                     $data['admin_view_url'] = api_get_path(WEB_PLUGIN_PATH) . 'advanced_subscription/src/admin_view.php?s=' . $data['sessionId'];
                     // Check if exist and action in data
                     // Check if exist and action in data
-                    if (empty($data['action'])) {
+                    if (empty($data['mailAction'])) {
                         // set action in data by new status
                         // set action in data by new status
                         switch ($data['newStatus']) {
                         switch ($data['newStatus']) {
                             case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_APPROVED:
                             case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_APPROVED:
-                                $data['action'] = ADVANCED_SUBSCRIPTION_ACTION_SUPERIOR_APPROVE;
+                                $data['mailAction'] = ADVANCED_SUBSCRIPTION_ACTION_SUPERIOR_APPROVE;
                                 break;
                                 break;
                             case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_DISAPPROVED:
                             case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_DISAPPROVED:
-                                $data['action'] = ADVANCED_SUBSCRIPTION_ACTION_SUPERIOR_DISAPPROVE;
+                                $data['mailAction'] = ADVANCED_SUBSCRIPTION_ACTION_SUPERIOR_DISAPPROVE;
                                 break;
                                 break;
                             case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_APPROVED:
                             case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_APPROVED:
-                                $data['action'] = ADVANCED_SUBSCRIPTION_ACTION_ADMIN_APPROVE;
+                                $data['mailAction'] = ADVANCED_SUBSCRIPTION_ACTION_ADMIN_APPROVE;
                                 break;
                                 break;
                             case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_DISAPPROVED:
                             case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_DISAPPROVED:
-                                $data['action'] = ADVANCED_SUBSCRIPTION_ACTION_ADMIN_DISAPPROVE;
+                                $data['mailAction'] = ADVANCED_SUBSCRIPTION_ACTION_ADMIN_DISAPPROVE;
                                 break;
                                 break;
                             default:
                             default:
                                 break;
                                 break;
@@ -253,7 +255,7 @@ if ($verified) {
                     }
                     }
 
 
                     // Send mails
                     // Send mails
-                    $result['mailIds'] = $plugin->sendMail($data, $data['action']);
+                    $result['mailIds'] = $plugin->sendMail($data, $data['mailAction']);
                     // Check if mails were sent
                     // Check if mails were sent
                     if (!empty($result['mailIds'])) {
                     if (!empty($result['mailIds'])) {
                         $result['error'] = false;
                         $result['error'] = false;

+ 4 - 0
plugin/advanced_subscription/config.php

@@ -15,6 +15,10 @@ define('ADVANCED_SUBSCRIPTION_ACTION_SUPERIOR_SELECT', 3);
 define('ADVANCED_SUBSCRIPTION_ACTION_ADMIN_APPROVE', 4);
 define('ADVANCED_SUBSCRIPTION_ACTION_ADMIN_APPROVE', 4);
 define('ADVANCED_SUBSCRIPTION_ACTION_ADMIN_DISAPPROVE', 5);
 define('ADVANCED_SUBSCRIPTION_ACTION_ADMIN_DISAPPROVE', 5);
 define('ADVANCED_SUBSCRIPTION_ACTION_STUDENT_REQUEST_NO_BOSS', 6);
 define('ADVANCED_SUBSCRIPTION_ACTION_STUDENT_REQUEST_NO_BOSS', 6);
+define('ADVANCED_SUBSCRIPTION_ACTION_REMINDER_STUDENT', 7);
+define('ADVANCED_SUBSCRIPTION_ACTION_REMINDER_SUPERIOR', 8);
+define('ADVANCED_SUBSCRIPTION_ACTION_REMINDER_SUPERIOR_MAX', 9);
+define('ADVANCED_SUBSCRIPTION_ACTION_REMINDER_ADMIN', 10);
 
 
 define('ADVANCED_SUBSCRIPTION_QUEUE_STATUS_NO_QUEUE', -1);
 define('ADVANCED_SUBSCRIPTION_QUEUE_STATUS_NO_QUEUE', -1);
 define('ADVANCED_SUBSCRIPTION_QUEUE_STATUS_START', 0);
 define('ADVANCED_SUBSCRIPTION_QUEUE_STATUS_START', 0);

+ 157 - 0
plugin/advanced_subscription/cron/notify_by_mail.php

@@ -0,0 +1,157 @@
+<?php
+/* For license terms, see /license.txt */
+/**
+ * This script generates four session categories.
+ * @package chamilo.plugin.advanced_subscription
+ */
+
+/**
+ * Init
+ */
+
+require_once __DIR__ . '/../config.php';
+$plugin = AdvancedSubscriptionPlugin::create();
+$now = api_get_utc_datetime();
+$weekAgo = api_get_utc_datetime('-1 week');
+$sessionExtraField = new ExtraField('session');
+$sessionExtraFieldValue = new ExtraFieldValue('session');
+/**
+ * Get session list
+ */
+$joinTables = Database::get_main_table(TABLE_MAIN_SESSION) . ' s INNER JOIN ' .
+    Database::get_main_table(TABLE_MAIN_SESSION_USER) . ' su ON s.id = su.id_session INNER JOIN ' .
+    Database::get_main_table(TABLE_MAIN_USER_REL_USER) . ' uu ON su.id_user = uu.user_id INNER JOIN ' .
+    Database::get_main_table(TABLE_ADVANCED_SUBSCRIPTION_QUEUE) . ' asq ON su.id_session = asq.session_id AND su.id_user = asq.user_id';
+$columns = 's.id AS session_id, uu.friend_user_id AS superior_id, uu.user_id AS student_id, asq.id AS queue_id, asq.status AS status';
+$conditions = array(
+    'where' => array(
+        's.date_start >= ? AND uu.relation_type = ? AND asq.updated_at <= ?' => array(
+            $now,
+            USER_RELATION_TYPE_BOSS,
+            $weekAgo,
+        )
+    ),
+    'order' => 's.id',
+);
+
+$queueList = Database::select($columns, $joinTables, $conditions);
+
+/**
+ * Remind students
+ */
+$sessionInfoList = array();
+foreach ($queueList as $queueItem) {
+    if (!isset($sessionInfoList[$queueItem['session_id']])) {
+        $sessionInfoList[$queueItem['session_id']] = api_get_session_info($queueItem['session_id']);
+    }
+}
+
+foreach ($queueList as $queueItem) {
+    switch ($queueItem['status']) {
+        case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_START:
+            // No break
+        case ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_APPROVED:
+            $data = array('sessionId' => $queueItem['session_id']);
+            $data['session'] = api_get_session_info($queueItem['session_id']);
+            $data['student'] = api_get_user_info($queueItem['student_id']);
+            $plugin->sendMail($data, ADVANCED_SUBSCRIPTION_ACTION_REMINDER_STUDENT);
+            break;
+        default:
+            break;
+    }
+}
+
+/**
+ * Remind superiors
+ */
+// Get recommended number of participants
+$sessionRecommendedNumber = array();
+foreach ($queueList as $queueItem) {
+    $row =
+        $sessionExtraFieldValue->get_values_by_handler_and_field_variable(
+            $queueItem['session_id'],
+            'recommended_number_of_participants'
+    );
+    $sessionRecommendedNumber[$queueItem['session_id']] = $row['field_value'];
+}
+// Group student by superior and session
+$queueBySuperior = array();
+foreach ($queueList as $queueItem) {
+    $queueBySuperior[$queueItem['session_id']][$queueItem['superior_id']][$queueItem['student_id']]['status'] = $queueItem['status'];
+}
+
+foreach ($queueBySuperior as $sessionId => $superiorStudents) {
+    $data = array(
+        'sessionId' => $sessionId,
+        'session' => $sessionInfoList[$sessionId],
+        'students' => array(),
+
+    );
+    $dataUrl = array(
+        'action' => 'confirm',
+        'sessionId' => $sessionId,
+        'currentUserId' => 0,
+        'newStatus' => ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_APPROVED,
+        'studentUserId' => 0,
+        'is_connected' => true,
+        'profile_completed' => 0,
+    );
+    foreach ($superiorStudents as $superiorId => $students) {
+        $data['superior'] = api_get_user_info($superiorId);
+        // Check if superior has at least one student
+        if (count($students) > 0) {
+            foreach ($students as $studentId => $studentInfo) {
+                if ($studentInfo['status'] == ADVANCED_SUBSCRIPTION_QUEUE_STATUS_START) {
+                    $data['students'][$studentId] = api_get_user_info($studentId);
+                    $dataUrl['studentUserId'] = $studentId;
+                    $dataUrl['newStatus'] = ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_APPROVED;
+                    $data['students'][$studentId]['acceptUrl'] = $plugin->getQueueUrl($dataUrl);
+                    $dataUrl['newStatus'] = ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_DISAPPROVED;
+                    $data['students'][$studentId]['rejectUrl'] = $plugin->getQueueUrl($dataUrl);
+                }
+            }
+
+            if (is_array($data['students']) && count($data['students']) > 0) {
+                // Check if superior have more than recommended
+                if ($sessionRecommendedNumber[$sessionId] >= count($students)) {
+                    // Is greater or equal than recommended
+                    $plugin->sendMail($data, ADVANCED_SUBSCRIPTION_ACTION_REMINDER_SUPERIOR);
+                } else {
+                    // Is less than recommended
+                    $plugin->sendMail($data, ADVANCED_SUBSCRIPTION_ACTION_REMINDER_SUPERIOR_MAX);
+                }
+            }
+
+        }
+    }
+}
+
+/**
+ * Remind admins
+ */
+$admins = UserManager::get_all_administrators();
+$isWesternNameOrder = api_is_western_name_order();
+foreach ($admins as &$admin) {
+    $admin['complete_name'] = $isWesternNameOrder ?
+        $admin['firstname'] . ', ' . $admin['lastname'] :
+        $admin['lastname'] . ', ' . $admin['firstname']
+    ;
+}
+unset($admin);
+$queueByAdmin = array();
+foreach ($queueList as $queueItem) {
+    if ($queueItem['status'] == ADVANCED_SUBSCRIPTION_QUEUE_STATUS_BOSS_APPROVED) {
+        $queueByAdmin[$queueItem['session_id']]['students'][$queueItem['student_id']]['user_id'] = $queueItem['student_id'];
+    }
+}
+$data = array(
+    'admins' => $admins,
+);
+foreach ($queueByAdmin as $sessionId => $studentInfo) {
+    $data['sessionId'] = $sessionId;
+    $data['admin_view_url'] = api_get_path(WEB_PLUGIN_PATH) .
+        'advanced_subscription/src/admin_view.php?s=' . $data['sessionId'];
+    $data['session'] = $sessionInfoList[$sessionId];
+    $data['students'] = $studentInfo['students'];
+    $plugin->sendMail($data, ADVANCED_SUBSCRIPTION_ACTION_REMINDER_ADMIN);
+}

+ 4 - 1
plugin/advanced_subscription/lang/english.php

@@ -37,7 +37,7 @@ $strings['AdvancedSubscriptionQueueStart'] = "Your subscription request is pendi
 $strings['AdvancedSubscriptionQueueBossDisapproved'] = "We are sorry, your subscription was rejected by your boss.";
 $strings['AdvancedSubscriptionQueueBossDisapproved'] = "We are sorry, your subscription was rejected by your boss.";
 $strings['AdvancedSubscriptionQueueBossApproved'] = "Your subscription request has been accepted by your boss, now is pending for vacancies.";
 $strings['AdvancedSubscriptionQueueBossApproved'] = "Your subscription request has been accepted by your boss, now is pending for vacancies.";
 $strings['AdvancedSubscriptionQueueAdminDisapproved'] = "We are sorry, your subscription was rejected by the administrator.";
 $strings['AdvancedSubscriptionQueueAdminDisapproved'] = "We are sorry, your subscription was rejected by the administrator.";
-$strings['AdvancedSubscriptionQueueAdminApproved'] = "Congratulation, your subscription request has been accepted by administrator";
+$strings['AdvancedSubscriptionQueueAdminApproved'] = "Congratulations!, your subscription request has been accepted by administrator.";
 $strings['AdvancedSubscriptionQueueDefaultX'] = "There was an error, queue status %d is not defined by system.";
 $strings['AdvancedSubscriptionQueueDefaultX'] = "There was an error, queue status %d is not defined by system.";
 
 
 // Mail translations
 // Mail translations
@@ -48,6 +48,9 @@ $strings['MailStudentRequestSelect'] = 'Student registration requests selection'
 $strings['MailAdminAccept'] = 'Registration request accepted by administrator';
 $strings['MailAdminAccept'] = 'Registration request accepted by administrator';
 $strings['MailAdminReject'] = 'Registration request rejected by administrator';
 $strings['MailAdminReject'] = 'Registration request rejected by administrator';
 $strings['MailStudentRequestNoBoss'] = 'Student registration request without boss';
 $strings['MailStudentRequestNoBoss'] = 'Student registration request without boss';
+$strings['MailRemindStudent'] = 'Subscription request reminder';
+$strings['MailRemindSuperior'] = 'Subscription request are pending your approval';
+$strings['MailRemindAdmin'] = 'Course subscription are pending your approval';
 
 
 // TPL langs
 // TPL langs
 // Admin view
 // Admin view

+ 11 - 8
plugin/advanced_subscription/lang/spanish.php

@@ -31,14 +31,14 @@ $strings['AdvancedSubscriptionNotMoreAble'] = "Lo sentimos, usted ya no cumple c
 $strings['AdvancedSubscriptionIncompleteParams'] = "Los parámetros enviados no están completos o no son los correctos.";
 $strings['AdvancedSubscriptionIncompleteParams'] = "Los parámetros enviados no están completos o no son los correctos.";
 $strings['AdvancedSubscriptionIsNotEnabled'] = "La inscripción avanzada no está activada";
 $strings['AdvancedSubscriptionIsNotEnabled'] = "La inscripción avanzada no está activada";
 
 
-$strings['AdvancedSubscriptionNoQueue'] = "You are not subscribed for this course.";
-$strings['AdvancedSubscriptionNoQueueIsAble'] = "You are not subscribed, but you are qualified for this course.";
-$strings['AdvancedSubscriptionQueueStart'] = "Your subscription request is pending for approval by your boss, please wait attentive.";
-$strings['AdvancedSubscriptionQueueBossDisapproved'] = "We are sorry, your subscription was rejected by your boss.";
-$strings['AdvancedSubscriptionQueueBossApproved'] = "Your subscription request has been accepted by your boss, now is pending for vacancies.";
-$strings['AdvancedSubscriptionQueueAdminDisapproved'] = "We are sorry, your subscription was rejected by the administrator.";
-$strings['AdvancedSubscriptionQueueAdminApproved'] = "Congratulation, your subscription request has been accepted by administrator";
-$strings['AdvancedSubscriptionQueueDefaultX'] = "There was an error, queue status %d is not defined by system.";
+$strings['AdvancedSubscriptionNoQueue'] = "Usted no está inscrito para este curso.";
+$strings['AdvancedSubscriptionNoQueueIsAble'] = "Usted no está inscrito, pero está calificado para este curso.";
+$strings['AdvancedSubscriptionQueueStart'] = "Su solicitud de inscripción está pendiente de la aprobación de su jefe, por favor espere atentamente.";
+$strings['AdvancedSubscriptionQueueBossDisapproved'] = "Lo sentimos, tu inscripción fue rechazada por tu jefe.";
+$strings['AdvancedSubscriptionQueueBossApproved'] = "Tu solicitud de inscripción ha sido aceptado por tu jefe, ahora está en espera de vacantes.";
+$strings['AdvancedSubscriptionQueueAdminDisapproved'] = "Lo sentimos, Tu inscripción ha sido rechazada por el administrador.";
+$strings['AdvancedSubscriptionQueueAdminApproved'] = "¡Felicitaciones! Tu inscripción ha sido aceptada por el administrador.";
+$strings['AdvancedSubscriptionQueueDefaultX'] = "Hubo un error el estado en cola %d no está definido en el sistema.";
 
 
 // Mail translations
 // Mail translations
 $strings['MailStudentRequest'] = 'Solicitud de registro de estudiante';
 $strings['MailStudentRequest'] = 'Solicitud de registro de estudiante';
@@ -48,6 +48,9 @@ $strings['MailStudentRequestSelect'] = 'Selección de solicitudes de registro de
 $strings['MailAdminAccept'] = 'Solicitud de registro aceptada por administrador';
 $strings['MailAdminAccept'] = 'Solicitud de registro aceptada por administrador';
 $strings['MailAdminReject'] = 'Solicitud de registro rechazada por administrador';
 $strings['MailAdminReject'] = 'Solicitud de registro rechazada por administrador';
 $strings['MailStudentRequestNoBoss'] = 'Solicitud de registro de estudiante sin superior';
 $strings['MailStudentRequestNoBoss'] = 'Solicitud de registro de estudiante sin superior';
+$strings['MailRemindStudent'] = 'Recordatorio de la solicitud de inscripción';
+$strings['MailRemindSuperior'] = 'Solicitudes de inscripción estan pendientes de tu aprobación';
+$strings['MailRemindAdmin'] = 'Inscripciones de cursos estan pendientes de tu aprobación';
 
 
 // TPL translations
 // TPL translations
 // Admin view
 // Admin view

+ 148 - 48
plugin/advanced_subscription/src/AdvancedSubscriptionPlugin.php

@@ -111,64 +111,104 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface
      */
      */
     public function isAllowedToDoRequest($userId, $params = array())
     public function isAllowedToDoRequest($userId, $params = array())
     {
     {
-        if (isset($params['is_connected']) && isset($params['profile_completed'])) {
-            $isAllowed = null;
-            $plugin = self::create();
-            $wsUrl = $plugin->get('ws_url');
-            // @TODO: Get connection status from user by WS
-            $isConnected = $params['is_connected'];
-            if ($isConnected) {
-                $profileCompletedMin = (float) $plugin->get('min_profile_percentage');
-                // @TODO: Get completed profile percentage by WS
+        $isAllowed = null;
+        $plugin = self::create();
+        $wsUrl = $plugin->get('ws_url');
+        // Student always is connected
+        $isConnected = true;
+        if ($isConnected) {
+            $profileCompletedMin = (float) $plugin->get('min_profile_percentage');
+            if (is_string($wsUrl) && !empty($wsUrl)) {
+                $options = array(
+                    'location' => $wsUrl,
+                    'uri' => $wsUrl
+                );
+                $client = new SoapClient(null, $options);
+                $userInfo = UserManager::get_user_info_by_id($userId);
+                try {
+                    $profileCompleted = $client->__soapCall('getProfileCompletionPercentage', $userInfo['extra']['drupal_user_id']);
+                } catch (\Exception $e) {
+                    $profileCompleted = 0;
+                }
+            } elseif (isset($params['profile_completed'])) {
                 $profileCompleted = (float) $params['profile_completed'];
                 $profileCompleted = (float) $params['profile_completed'];
-                if ($profileCompleted > $profileCompletedMin) {
-                    $checkInduction = $plugin->get('check_induction');
-                    // @TODO: check if user have completed at least one induction session
-                    $completedInduction = true;
-                    if (!$checkInduction || $completedInduction) {
-                        $uitMax = $plugin->get('yearly_cost_unit_converter');
-                        $uitMax *= $plugin->get('yearly_cost_limit');
-                        // @TODO: Get UIT completed by user this year by WS
-                        $uitUser = 0;
-                        $extra = new ExtraFieldValue('session');
-                        $var = $extra->get_values_by_handler_and_field_variable($params['session_id'], 'cost');
-                        $uitUser += $var['field_value'];
-                        if ($uitMax >= $uitUser) {
-                            $expendedTimeMax = $plugin->get('yearly_hours_limit');
-                            // @TODO: Get Expended time from user data
-                            $expendedTime = 0;
-                            $var = $extra->get_values_by_handler_and_field_variable($params['session_id'], 'duration');
-                            $expendedTime += $var['field_value'];
-                            if ($expendedTimeMax >= $expendedTime) {
-                                $expendedNumMax = $plugin->get('courses_count_limit');
-                                // @TODO: Get Expended num from user
-                                $expendedNum = 0;
-                                if ($expendedNumMax >= $expendedNum) {
-                                    $isAllowed = true;
-                                } else {
-                                    throw new \Exception($this->get_lang('AdvancedSubscriptionCourseXLimitReached'));
-                                }
+            } else {
+                $profileCompleted = 0;
+            }
+            if ($profileCompleted >= $profileCompletedMin) {
+                $checkInduction = $plugin->get('check_induction');
+                // @TODO: check if user have completed at least one induction session
+                $completedInduction = true;
+                if (!$checkInduction || $completedInduction) {
+                    $uitMax = $plugin->get('yearly_cost_unit_converter');
+                    $uitMax *= $plugin->get('yearly_cost_limit');
+                    $uitUser = 0;
+                    $now = new DateTime(api_get_utc_datetime());
+                    $newYearDate = $plugin->get('course_session_credit_year_start_date');
+                    $newYearDate = !empty($newYearDate) ?
+                        new \DateTime($newYearDate . $now->format('/Y')) :
+                        $now;
+                    $extra = new ExtraFieldValue('session');
+                    $joinSessionTable = Database::get_main_table(TABLE_MAIN_SESSION_USER) . ' su INNER JOIN ' .
+                        Database::get_main_table(TABLE_MAIN_SESSION) . ' s ON s.id = su.id_session';
+                    $whereSessionParams = 'su.relation_type = ? AND s.date_start >= ? AND su.id_user = ?';
+                    $whereSessionParamsValues = array(
+                        0,
+                        $newYearDate->format('Y-m-d'),
+                        $userId
+                    );
+                    $whereSession = array(
+                        'where' => array(
+                            $whereSessionParams => $whereSessionParamsValues
+                        )
+                    );
+                    $selectSession = 's.id AS id';
+                    $sessions = Database::select(
+                        $selectSession,
+                        $joinSessionTable,
+                        $whereSession
+                    );
+
+                    if (is_array($sessions) && count($sessions) > 0) {
+                        foreach ($sessions as $session) {
+                            $var = $extra->get_values_by_handler_and_field_variable($session['id'], 'cost');
+                            $uitUser += $var['field_value'];
+                        }
+                    }
+                    if ($uitMax >= $uitUser) {
+                        $expendedTimeMax = $plugin->get('yearly_hours_limit');
+                        $expendedTime = 0;
+                        if (is_array($sessions) && count($sessions) > 0) {
+                            foreach ($sessions as $session) {
+                                $var = $extra->get_values_by_handler_and_field_variable($session['id'], 'teaching_hours');
+                                $expendedTime += $var['field_value'];
+                            }
+                        }
+                        if ($expendedTimeMax >= $expendedTime) {
+                            $expendedNumMax = $plugin->get('courses_count_limit');
+                            $expendedNum = count($sessions);
+                            if ($expendedNumMax >= $expendedNum) {
+                                $isAllowed = true;
                             } else {
                             } else {
-                                throw new \Exception($this->get_lang('AdvancedSubscriptionTimeXLimitReached'));
+                                throw new \Exception($this->get_lang('AdvancedSubscriptionCourseXLimitReached'));
                             }
                             }
                         } else {
                         } else {
-                            throw new \Exception($this->get_lang('AdvancedSubscriptionCostXLimitReached'));
+                            throw new \Exception($this->get_lang('AdvancedSubscriptionTimeXLimitReached'));
                         }
                         }
                     } else {
                     } else {
-                        throw new \Exception($this->get_lang('AdvancedSubscriptionIncompleteInduction'));
+                        throw new \Exception($this->get_lang('AdvancedSubscriptionCostXLimitReached'));
                     }
                     }
                 } else {
                 } else {
-                    throw new \Exception($this->get_lang('AdvancedSubscriptionProfileIncomplete'));
+                    throw new \Exception($this->get_lang('AdvancedSubscriptionIncompleteInduction'));
                 }
                 }
             } else {
             } else {
-                throw new \Exception($this->get_lang('AdvancedSubscriptionNotConnected'));
+                throw new \Exception($this->get_lang('AdvancedSubscriptionProfileIncomplete'));
             }
             }
-
-            return $isAllowed;
         } else {
         } else {
-            throw new \Exception($this->get_lang('AdvancedSubscriptionIncompleteParams'));
+            throw new \Exception($this->get_lang('AdvancedSubscriptionNotConnected'));
         }
         }
 
 
+        return $isAllowed;
     }
     }
 
 
     /**
     /**
@@ -213,6 +253,7 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface
         $queueTable = Database::get_main_table(TABLE_ADVANCED_SUBSCRIPTION_QUEUE);
         $queueTable = Database::get_main_table(TABLE_ADVANCED_SUBSCRIPTION_QUEUE);
         $attributes = array(
         $attributes = array(
             'last_message_id' => $mailId,
             'last_message_id' => $mailId,
+            'updated_at' => api_get_utc_datetime(),
         );
         );
 
 
         $num = Database::update(
         $num = Database::update(
@@ -254,7 +295,7 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface
 
 
     /**
     /**
      * Send message for the student subscription approval to a specific session
      * Send message for the student subscription approval to a specific session
-     * @param int $studentId
+     * @param int|array $studentId
      * @param int $receiverId
      * @param int $receiverId
      * @param string $subject
      * @param string $subject
      * @param string $content
      * @param string $content
@@ -272,7 +313,14 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface
 
 
         if ($save && !empty($mailId)) {
         if ($save && !empty($mailId)) {
             // Save as sent message
             // Save as sent message
-            $this->saveLastMessage($mailId, $studentId, $sessionId);
+            if (is_array($studentId) && !empty($studentId)) {
+                foreach ($studentId as $student) {
+                    $this->saveLastMessage($mailId, $student['user_id'], $sessionId);
+                }
+            } else {
+                $studentId = intval($studentId);
+                $this->saveLastMessage($mailId, $studentId, $sessionId);
+            }
         }
         }
         return $mailId;
         return $mailId;
     }
     }
@@ -542,6 +590,50 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface
                     );
                     );
                 }
                 }
                 break;
                 break;
+            case ADVANCED_SUBSCRIPTION_ACTION_REMINDER_STUDENT:
+                $mailIds['render'] = $this->sendMailMessage(
+                    $data['student']['user_id'],
+                    $data['student']['user_id'],
+                    $this->get_lang('MailRemindStudent'),
+                    $template->fetch('/advanced_subscription/views/reminder_notice_student.tpl'),
+                    $data['sessionId'],
+                    true
+                );
+                break;
+            case ADVANCED_SUBSCRIPTION_ACTION_REMINDER_SUPERIOR:
+                $mailIds['render'] = $this->sendMailMessage(
+                    $data['students'],
+                    $data['superior']['user_id'],
+                    $this->get_lang('MailRemindSuperior'),
+                    $template->fetch('/advanced_subscription/views/reminder_notice_superior.tpl'),
+                    $data['sessionId'],
+                    true
+                );
+                break;
+            case ADVANCED_SUBSCRIPTION_ACTION_REMINDER_SUPERIOR_MAX:
+                $mailIds['render'] = $this->sendMailMessage(
+                    $data['students'],
+                    $data['superior']['user_id'],
+                    $this->get_lang('MailRemindSuperior'),
+                    $template->fetch('/advanced_subscription/views/reminder_notice_superior_max.tpl'),
+                    $data['sessionId'],
+                    true
+                );
+                break;
+            case ADVANCED_SUBSCRIPTION_ACTION_REMINDER_ADMIN:
+                // Mail to admin
+                foreach ($data['admins'] as $adminId => $admin) {
+                    $template->assign('admin', $admin);
+                    $mailIds[] = $this->sendMailMessage(
+                        $data['students'],
+                        $adminId,
+                        $this->get_lang('MailRemindAdmin'),
+                        $template->fetch('/advanced_subscription/views/reminder_notice_admin.tpl'),
+                        $data['sessionId'],
+                        true
+                    );
+                }
+                break;
             default:
             default:
                 break;
                 break;
         }
         }
@@ -664,6 +756,8 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface
                 if ($vacancy >= 0) {
                 if ($vacancy >= 0) {
 
 
                     return $vacancy;
                     return $vacancy;
+                } else {
+                    return 0;
                 }
                 }
             }
             }
         }
         }
@@ -686,7 +780,7 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface
             $extraField = new ExtraField('session');
             $extraField = new ExtraField('session');
             // Get session fields
             // Get session fields
             $fieldList = $extraField->get_all(array(
             $fieldList = $extraField->get_all(array(
-                'field_variable IN ( ?, ?, ?, ?, ?)' => $fieldsArray
+                'field_variable IN ( ?, ?, ?, ?, ?, ?, ? )' => $fieldsArray
             ));
             ));
             // Index session fields
             // Index session fields
             $fields = array();
             $fields = array();
@@ -711,6 +805,12 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface
             }
             }
             $sessionArray['description'] = SessionManager::getDescriptionFromSessionId($sessionId);
             $sessionArray['description'] = SessionManager::getDescriptionFromSessionId($sessionId);
 
 
+            if (isset($sessionArray['brochure'])) {
+                $sessionArray['brochure'] = api_get_path(WEB_CODE_PATH) . $sessionArray['brochure'];
+            }
+            if (isset($sessionArray['banner'])) {
+                $sessionArray['banner'] = api_get_path(WEB_CODE_PATH) . $sessionArray['banner'];
+            }
             return $sessionArray;
             return $sessionArray;
         }
         }
 
 
@@ -783,7 +883,7 @@ class AdvancedSubscriptionPlugin extends Plugin implements HookPluginInterface
             'e=' . intval($params['newStatus']) . '&' .
             'e=' . intval($params['newStatus']) . '&' .
             'u=' . intval($params['studentUserId']) . '&' .
             'u=' . intval($params['studentUserId']) . '&' .
             'q=' . intval($params['queueId']) . '&' .
             'q=' . intval($params['queueId']) . '&' .
-            'is_connected=' . intval($params['is_connected']) . '&' .
+            'is_connected=' . true . '&' .
             'profile_completed=' . intval($params['profile_completed']) . '&' .
             'profile_completed=' . intval($params['profile_completed']) . '&' .
             'v=' . $this->generateHash($params);
             'v=' . $this->generateHash($params);
         return $url;
         return $url;

+ 66 - 53
plugin/advanced_subscription/src/HookAdvancedSubscription.php

@@ -17,14 +17,14 @@ class HookAdvancedSubscription extends HookObserver implements
     HookWSRegistrationObserverInterface,
     HookWSRegistrationObserverInterface,
     HookNotificationContentObserverInterface
     HookNotificationContentObserverInterface
 {
 {
-    public $plugin;
+    public static $plugin;
 
 
     /**
     /**
      * Constructor. Calls parent, mainly.
      * Constructor. Calls parent, mainly.
      */
      */
     protected function __construct()
     protected function __construct()
     {
     {
-        $this->plugin = AdvancedSubscriptionPlugin::create();
+        self::$plugin = AdvancedSubscriptionPlugin::create();
         parent::__construct(
         parent::__construct(
             'plugin/advanced_subscription/src/HookAdvancedSubscription.class.php',
             'plugin/advanced_subscription/src/HookAdvancedSubscription.class.php',
             'advanced_subscription'
             'advanced_subscription'
@@ -93,7 +93,7 @@ class HookAdvancedSubscription extends HookObserver implements
                     // session.date_end
                     // session.date_end
                     'date_end' => array('name' => 'date_end', 'type' => 'xsd:string'),
                     'date_end' => array('name' => 'date_end', 'type' => 'xsd:string'),
                     // session.human_text_duration
                     // session.human_text_duration
-                    'duration' => array('name' => 'duration', 'type' => 'xsd:string'),
+                    'human_text_duration' => array('name' => 'human_text_duration', 'type' => 'xsd:string'),
                     // session.vacancies
                     // session.vacancies
                     'vacancies' => array('name' => 'vacancies', 'type' => 'xsd:string'),
                     'vacancies' => array('name' => 'vacancies', 'type' => 'xsd:string'),
                     // session.schedule
                     // session.schedule
@@ -167,8 +167,8 @@ class HookAdvancedSubscription extends HookObserver implements
                     'place' => array('name' => 'place', 'type' => 'xsd:string'),
                     'place' => array('name' => 'place', 'type' => 'xsd:string'),
                     // session.allow_visitors
                     // session.allow_visitors
                     'allow_visitors' => array('name' => 'allow_visitors', 'type' => 'xsd:string'),
                     'allow_visitors' => array('name' => 'allow_visitors', 'type' => 'xsd:string'),
-                    // session.duration
-                    'duration' => array('name' => 'duration', 'type' => 'xsd:int'),
+                    // session.teaching_hours
+                    'teaching_hours' => array('name' => 'teaching_hours', 'type' => 'xsd:int'),
                     // session.brochure
                     // session.brochure
                     'brochure' => array('name' => 'brochure', 'type' => 'xsd:string'),
                     'brochure' => array('name' => 'brochure', 'type' => 'xsd:string'),
                     // session.banner
                     // session.banner
@@ -402,6 +402,7 @@ class HookAdvancedSubscription extends HookObserver implements
         } else {
         } else {
             // Nothing to do
             // Nothing to do
         }
         }
+
         return false;
         return false;
     }
     }
 
 
@@ -438,13 +439,12 @@ class HookAdvancedSubscription extends HookObserver implements
 
 
         // Get the session brief List by category
         // Get the session brief List by category
         $fields = array(
         $fields = array(
+            'id',
             'short_description',
             'short_description',
             'mode',
             'mode',
             'human_text_duration',
             'human_text_duration',
             'vacancies',
             'vacancies',
-            'brochure',
-            'target',
-            'schedule'
+            'schedule',
         );
         );
         $sessionList = SessionManager::getShortSessionListAndExtraByCategory(
         $sessionList = SessionManager::getShortSessionListAndExtraByCategory(
             $sessionCategoryId,
             $sessionCategoryId,
@@ -459,7 +459,7 @@ class HookAdvancedSubscription extends HookObserver implements
      * @param $params
      * @param $params
      * @return null|soap_fault
      * @return null|soap_fault
      */
      */
-    public function WSSessionGetDetailsByUser($params)
+    public static function WSSessionGetDetailsByUser($params)
     {
     {
         global $debug;
         global $debug;
 
 
@@ -475,53 +475,66 @@ class HookAdvancedSubscription extends HookObserver implements
         if (is_array($params) && !empty($params['session_id']) && !empty($params['user_id'])) {
         if (is_array($params) && !empty($params['session_id']) && !empty($params['user_id'])) {
             $userId = (int) $params['user_id'];
             $userId = (int) $params['user_id'];
             $sessionId = (int) $params['session_id'];
             $sessionId = (int) $params['session_id'];
-            // Check if student is already subscribed
-
-            $plugin = AdvancedSubscriptionPlugin::create();
-            $isOpen = $plugin->isSessionOpen($sessionId);
-            $status = $plugin->getQueueStatus($userId, $sessionId);
-            $vacancy = $plugin->getVacancy($sessionId);
-            $data = $plugin->getSessionDetails($sessionId);
-            if (!empty($data) && is_array($data)) {
-                $data['status'] = $status;
-                // 5 Cases:
-                if ($isOpen) {
-                    // Go to Course session
-                    $data['action_url'] = $plugin->getSessionUrl($sessionId);
-                } else {
-                    try {
-                        $isAble = $plugin->isAllowedToDoRequest($userId, $params);
-                        $data['message'] = $plugin->getStatusMessage($status, $isAble);
-                    } catch (\Exception $e) {
-                        $data['message'] = $e->getMessage();
-                    }
-                    $params['action'] = 'subscribe';
-                    $params['sessionId'] = intval($sessionId);
-                    $params['currentUserId'] = 0; // No needed
-                    $params['studentUserId'] = intval($userId);
-                    $params['queueId'] = 0; // No needed
-                    $params['newStatus'] = ADVANCED_SUBSCRIPTION_QUEUE_STATUS_START;
-                    if ($vacancy > 0) {
-                        // Check conditions
-                        if ($status === ADVANCED_SUBSCRIPTION_QUEUE_STATUS_NO_QUEUE) {
-                            // No in Queue, require queue subscription url action
-                            $data['action_url'] = $plugin->getQueueUrl($params);
-                        } elseif ($status === ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_APPROVED) {
-                            // send url action
-                            $data['action_url'] = $plugin->getSessionUrl($sessionId);
-                        } else {
-                            // In queue, output status message, no more info.
-                        }
+            // Check if user exists
+            if (
+                UserManager::is_user_id_valid($userId) &&
+                SessionManager::isValidId($sessionId)
+            ) {
+                // Check if student is already subscribed
+                $plugin = AdvancedSubscriptionPlugin::create();
+                $isOpen = $plugin->isSessionOpen($sessionId);
+                $status = $plugin->getQueueStatus($userId, $sessionId);
+                $vacancy = $plugin->getVacancy($sessionId);
+                $data = $plugin->getSessionDetails($sessionId);
+                if (!empty($data) && is_array($data)) {
+                    $data['status'] = $status;
+                    // Vacancy and queue status cases:
+                    if ($isOpen) {
+                        // Go to Course session
+                        $data['action_url'] = self::$plugin->getSessionUrl($sessionId);
                     } else {
                     } else {
-                        if ($status === ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_APPROVED) {
-                            $data['action_url'] = $plugin->getSessionUrl($sessionId);
+                        try {
+                            $isAllowed = self::$plugin->isAllowedToDoRequest($userId, $params);
+                            $data['message'] = self::$plugin->getStatusMessage($status, $isAllowed);
+                        } catch (\Exception $e) {
+                            $data['message'] = $e->getMessage();
+                        }
+                        $params['action'] = 'subscribe';
+                        $params['sessionId'] = intval($sessionId);
+                        $params['currentUserId'] = 0; // No needed
+                        $params['studentUserId'] = intval($userId);
+                        $params['queueId'] = 0; // No needed
+                        $params['newStatus'] = ADVANCED_SUBSCRIPTION_QUEUE_STATUS_START;
+                        if ($vacancy > 0) {
+                            // Check conditions
+                            if ($status == ADVANCED_SUBSCRIPTION_QUEUE_STATUS_NO_QUEUE) {
+                                // No in Queue, require queue subscription url action
+                                $data['action_url'] = self::$plugin->getQueueUrl($params);
+                            } elseif ($status == ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_APPROVED) {
+                                // send url action
+                                $data['action_url'] = self::$plugin->getSessionUrl($sessionId);
+                            } else {
+                                // In queue, output status message, no more info.
+                            }
                         } else {
                         } else {
-                            // in Queue or not, cannot be subscribed to session
-                            $data['action_url'] = $plugin->getQueueUrl($params);
+                            if ($status == ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_APPROVED) {
+                                $data['action_url'] = self::$plugin->getSessionUrl($sessionId);
+                            } elseif ($status == ADVANCED_SUBSCRIPTION_QUEUE_STATUS_NO_QUEUE) {
+                                // in Queue or not, cannot be subscribed to session
+                                $data['action_url'] = self::$plugin->getQueueUrl($params);
+                            } else {
+                                // In queue, output status message, no more info.
+                            }
                         }
                         }
                     }
                     }
+                    $result = $data;
+                } else {
+                    // Return soap fault No result was found
+                    $result = return_error(WS_ERROR_NOT_FOUND_RESULT);
                 }
                 }
-                $result = $data;
+            } else {
+                // Return soap fault No result was found
+                $result = return_error(WS_ERROR_NOT_FOUND_RESULT);
             }
             }
         } else {
         } else {
             // Return soap fault Not valid input params
             // Return soap fault Not valid input params
@@ -587,14 +600,14 @@ class HookAdvancedSubscription extends HookObserver implements
         $plugin = AdvancedSubscriptionPlugin::create();
         $plugin = AdvancedSubscriptionPlugin::create();
         foreach ($sessionList as &$session) {
         foreach ($sessionList as &$session) {
             // Add validated and queue users count
             // Add validated and queue users count
-            $session['validated_user_num'] = $plugin->countQueueByParams(
+            $session['validated_user_num'] = self::$plugin->countQueueByParams(
                 array(
                 array(
                     'sessions' => array($session['id']),
                     'sessions' => array($session['id']),
                     'status' => array(ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_APPROVED)
                     'status' => array(ADVANCED_SUBSCRIPTION_QUEUE_STATUS_ADMIN_APPROVED)
 
 
                 )
                 )
             );
             );
-            $session['waiting_user_num'] = $plugin->countQueueByParams(
+            $session['waiting_user_num'] = self::$plugin->countQueueByParams(
                 array(
                 array(
                     'sessions' => array($session['id']),
                     'sessions' => array($session['id']),
                     'status' => array(
                     'status' => array(

+ 203 - 0
plugin/advanced_subscription/src/scripts/insert_session_fields.php

@@ -0,0 +1,203 @@
+<?php
+/* For license terms, see /license.txt */
+/**
+ * This script generates session fields needed for this plugin
+ * @package chamilo.plugin.advanced_subscription
+ */
+
+//exit;
+
+require_once __DIR__ . '/../../config.php';
+
+api_protect_admin_script();
+
+$teachingHours = new ExtraField('session');
+$teachingHours->save(array(
+    'field_type' => ExtraField::FIELD_TYPE_INTEGER,
+    'field_variable' => 'teaching_hours',
+    'field_display_text' => get_lang('TeachingHours'),
+    'field_visible' => 1,
+    'field_changeable' => 1
+));
+
+$cost = new ExtraField('session');
+$cost->save(array(
+    'field_type' => ExtraField::FIELD_TYPE_FLOAT,
+    'field_variable' => 'cost',
+    'field_display_text' => get_lang('Cost'),
+    'field_visible' => 1,
+    'field_changeable' => 1
+));
+
+$vacancies = new ExtraField('session');
+$vacancies->save(array(
+    'field_type' => ExtraField::FIELD_TYPE_INTEGER,
+    'field_variable' => 'vacancies',
+    'field_display_text' => get_lang('Vacancies'),
+    'field_visible' => 1,
+    'field_changeable' => 1
+));
+
+$recommendedNumberOfParticipants = new ExtraField('session');
+$recommendedNumberOfParticipants->save(array(
+    'field_type' => ExtraField::FIELD_TYPE_INTEGER,
+    'field_variable' => 'recommended_number_of_participants',
+    'field_display_text' => get_lang('RecommendedNumberOfParticipants'),
+    'field_visible' => 1,
+    'field_changeable' => 1
+));
+
+$place = new ExtraField('session');
+$place->save(array(
+    'field_type' => ExtraField::FIELD_TYPE_TEXT,
+    'field_variable' => 'place',
+    'field_display_text' => get_lang('Place'),
+    'field_visible' => 1,
+    'field_changeable' => 1
+));
+
+$schedule = new ExtraField('session');
+$schedule->save(array(
+    'field_type' => ExtraField::FIELD_TYPE_TEXT,
+    'field_variable' => 'schedule',
+    'field_display_text' => get_lang('Schedule'),
+    'field_visible' => 1,
+    'field_changeable' => 1
+));
+
+$allowVisitors = new ExtraField('session');
+$allowVisitors->save(array(
+    'field_type' => ExtraField::FIELD_TYPE_CHECKBOX,
+    'field_variable' => 'allow_visitors',
+    'field_display_text' => get_lang('AllowVisitors'),
+    'field_visible' => 1,
+    'field_changeable' => 1
+));
+
+$modeOptions = array(
+    get_lang('Online'),
+    get_lang('Presencial'),
+    get_lang('B-Learning')
+);
+
+$mode = new ExtraField('session');
+$mode->save(array(
+    'field_type' => ExtraField::FIELD_TYPE_SELECT,
+    'field_variable' => 'mode',
+    'field_display_text' => get_lang('Mode'),
+    'field_visible' => 1,
+    'field_changeable' => 1,
+    'field_options' => implode('; ', $modeOptions)
+));
+
+$isInductionSession = new ExtraField('session');
+$isInductionSession->save(array(
+    'field_type' => ExtraField::FIELD_TYPE_CHECKBOX,
+    'field_variable' => 'is_induccion_session',
+    'field_display_text' => get_lang('IsInductionSession'),
+    'field_visible' => 1,
+    'field_changeable' => 1
+));
+
+$isOpenSession = new ExtraField('session');
+$isOpenSession->save(array(
+    'field_type' => ExtraField::FIELD_TYPE_CHECKBOX,
+    'field_variable' => 'is_open_session',
+    'field_display_text' => get_lang('IsOpenSession'),
+    'field_visible' => 1,
+    'field_changeable' => 1
+));
+
+$duration = new ExtraField('session');
+$duration->save(array(
+    'field_type' => ExtraField::FIELD_TYPE_TEXT,
+    'field_variable' => 'human_text_duration',
+    'field_display_text' => get_lang('DurationInWords'),
+    'field_visible' => 1,
+    'field_changeable' => 1
+));
+
+$showStatusOptions = array(
+    get_lang('Open'),
+    get_lang('InProcess'),
+    get_lang('Closed')
+);
+
+$showStatus = new ExtraField('session');
+$showStatus->save(array(
+    'field_type' => ExtraField::FIELD_TYPE_SELECT,
+    'field_variable' => 'show_status',
+    'field_display_text' => get_lang('ShowStatus'),
+    'field_visible' => 1,
+    'field_changeable' => 1,
+    'field_options' => implode('; ', $showStatusOptions)
+));
+
+$publicationStartDate = new ExtraField('session');
+$publicationStartDate->save(array(
+    'field_type' => ExtraField::FIELD_TYPE_DATE,
+    'field_variable' => 'publication_start_date',
+    'field_display_text' => get_lang('PublicationStartDate'),
+    'field_visible' => 1,
+    'field_changeable' => 1
+));
+
+$publicationEndDate = new ExtraField('session');
+$publicationEndDate->save(array(
+    'field_type' => ExtraField::FIELD_TYPE_DATE,
+    'field_variable' => 'publication_end_date',
+    'field_display_text' => get_lang('PublicationEndDate'),
+    'field_visible' => 1,
+    'field_changeable' => 1
+));
+
+$banner = new ExtraField('session');
+$banner->save(array(
+    'field_type' => ExtraField::FIELD_TYPE_FILE_IMAGE,
+    'field_variable' => 'banner',
+    'field_display_text' => get_lang('SessionBanner'),
+    'field_visible' => 1,
+    'field_changeable' => 1
+));
+
+$brochure = new ExtraField('session');
+$brochure->save(array(
+    'field_type' => ExtraField::FIELD_TYPE_FILE,
+    'field_variable' => 'brochure',
+    'field_display_text' => get_lang('Brochure'),
+    'field_visible' => 1,
+    'field_changeable' => 1
+));
+
+$targetOptions = array(
+    get_lang('Minedu'),
+    get_lang('Regiones')
+);
+
+$target = new ExtraField('session');
+$target->save(array(
+    'field_type' => ExtraField::FIELD_TYPE_SELECT,
+    'field_variable' => 'target',
+    'field_display_text' => get_lang('Target'),
+    'field_visible' => 1,
+    'field_changeable' => 1,
+    'field_options' => implode('; ', $targetOptions)
+));
+
+$shortDescription = new ExtraField('session');
+$shortDescription->save(array(
+    'field_type' => ExtraField::FIELD_TYPE_TEXT,
+    'field_variable' => 'short_description',
+    'field_display_text' => get_lang('ShortSescription'),
+    'field_visible' => 1,
+    'field_changeable' => 1
+));
+
+$id = new ExtraField('session');
+$id->save(array(
+    'field_type' => ExtraField::FIELD_TYPE_TEXT,
+    'field_variable' => 'id',
+    'field_display_text' => get_lang('Id'),
+    'field_visible' => 1,
+    'field_changeable' => 1
+));

+ 20 - 0
plugin/advanced_subscription/src/scripts/insert_sessions_categories.php

@@ -0,0 +1,20 @@
+<?php
+/* For license terms, see /license.txt */
+/**
+ * This script generates four session categories.
+ * @package chamilo.plugin.advanced_subscription
+ */
+require_once __DIR__ . '/../../config.php';
+
+api_protect_admin_script();
+
+$categories = array(
+    'capacitaciones',
+    'programas',
+    'especializaciones',
+    'cursos prácticos'
+);
+$tableSessionCategory = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
+foreach ($categories as $category) {
+    Database::query("INSERT INTO $tableSessionCategory (name) VALUES ('$category')");
+}

+ 5 - 0
plugin/advanced_subscription/test/mails.php

@@ -1,4 +1,9 @@
 <?php
 <?php
+/* For license terms, see /license.txt */
+/**
+ * A script to render all mails templates
+ * @package chamilo.plugin.advanced_subscription
+ */
 
 
 require_once __DIR__ . '/../config.php';
 require_once __DIR__ . '/../config.php';
 
 

+ 49 - 0
plugin/advanced_subscription/test/ws_session_user.php

@@ -0,0 +1,49 @@
+<?php
+/* For license terms, see /license.txt */
+/**
+ * A script to test session details by user web service
+ * @package chamilo.plugin.advanced_subscription
+ */
+
+/**
+ * Init
+ */
+require_once __DIR__ . '/../config.php';
+// Protect test
+api_protect_admin_script();
+
+// exit;
+
+$plugin = AdvancedSubscriptionPlugin::create();
+$hookPlugin = HookAdvancedSubscription::create();
+// Get params from request (GET or POST)
+$params = array();
+// Init result array
+$params['user_id'] = intval($_REQUEST['u']);
+$params['session_id'] = intval($_REQUEST['s']);
+$params['profile_completed'] = 100;
+$params['secret_key'] = 'ed639d402804ffa347b489be3e42f28058e402bf';
+
+// Registration soap wsdl
+$wsUrl = 'http://chamilo19.net/main/webservices/registration.soap.php?wsdl';
+$options = array(
+    'location' => $wsUrl,
+    'uri' => $wsUrl,
+);
+
+/**
+ * WS test
+ */
+try {
+    // Init soap client
+    $client = new SoapClient(null, $options);
+    // Soap call to WS
+    $result = $client->__soapCall('HookAdvancedSubscription..WSSessionGetDetailsByUser', array($params));
+    echo '<pre>', print_r($result, 1) , '</pre>';
+    if (is_object($result) && isset($result->action_url)) {
+        echo '<br />';
+        echo Display::url($result->message, $result->action_url);
+    }
+} catch (\Exception $e) {
+    echo '<pre>', print_r($e, 1) , '</pre>';
+}

+ 2 - 2
plugin/advanced_subscription/views/admin_view.tpl

@@ -54,13 +54,13 @@
                                 class="btn btn-success btn-advanced-subscription btn-accept"
                                 class="btn btn-success btn-advanced-subscription btn-accept"
                                 href="{{ student.acceptUrl }}"
                                 href="{{ student.acceptUrl }}"
                             >
                             >
-                                {{ 'Accept' | get_plugin_lang('AdvancedSubscriptionPlugin') }}
+                                {{ 'AcceptInfinitive' | get_plugin_lang('AdvancedSubscriptionPlugin') }}
                             </a>
                             </a>
                             <a
                             <a
                                 class="btn btn-danger btn-advanced-subscription btn-reject"
                                 class="btn btn-danger btn-advanced-subscription btn-reject"
                                 href="{{ student.rejectUrl }}"
                                 href="{{ student.rejectUrl }}"
                             >
                             >
-                                {{ 'Reject' | get_plugin_lang('AdvancedSubscriptionPlugin') }}
+                                {{ 'RejectInfinitive' | get_plugin_lang('AdvancedSubscriptionPlugin') }}
                             </a>
                             </a>
                         </td>
                         </td>
                     </tr>
                     </tr>

+ 1 - 1
plugin/advanced_subscription/views/reminder_notice_superior.tpl

@@ -54,7 +54,7 @@
                         <table width="100%" border="0" cellspacing="3" cellpadding="4" style="background:#EDE9EA">
                         <table width="100%" border="0" cellspacing="3" cellpadding="4" style="background:#EDE9EA">
                             {% for student in students %}
                             {% for student in students %}
                             <tr>
                             <tr>
-                                <td valign="middle"><img src="{{ student.picture.file }}" width="50" height="50" alt=""></td>
+                                <td valign="middle"><img src="{{ student.avatar }}" width="50" height="50" alt=""></td>
                                 <td valign="middle"><h4>{{ student.complete_name }}</h4></td>
                                 <td valign="middle"><h4>{{ student.complete_name }}</h4></td>
                                 <td valign="middle"><a href="{{ student.acceptUrl }}"><img src="{{ _p.web_plugin }}advanced_subscription/views/img/aprobar.png" width="90" height="25" alt=""></a></td>
                                 <td valign="middle"><a href="{{ student.acceptUrl }}"><img src="{{ _p.web_plugin }}advanced_subscription/views/img/aprobar.png" width="90" height="25" alt=""></a></td>
                                 <td valign="middle"><a href="{{ student.rejectUrl }}"><img src="{{ _p.web_plugin }}advanced_subscription/views/img/desaprobar.png" width="90" height="25" alt=""></a></td>
                                 <td valign="middle"><a href="{{ student.rejectUrl }}"><img src="{{ _p.web_plugin }}advanced_subscription/views/img/desaprobar.png" width="90" height="25" alt=""></a></td>

+ 2 - 2
plugin/advanced_subscription/views/reminder_notice_superior_max.tpl

@@ -55,9 +55,9 @@
           <table width="100%" border="0" cellspacing="3" cellpadding="4" style="background:#EDE9EA">
           <table width="100%" border="0" cellspacing="3" cellpadding="4" style="background:#EDE9EA">
             {% for student in students %}
             {% for student in students %}
             <tr>
             <tr>
-              <td valign="middle"><img src="{{ student.picture.file }}" width="50" height="50" alt=""></td>
+              <td valign="middle"><img src="{{ student.avatar }}" width="50" height="50" alt=""></td>
               <td valign="middle"><h4>{{ student.complete_name }}</h4></td>
               <td valign="middle"><h4>{{ student.complete_name }}</h4></td>
-              <td valign="middle"><a href="{{ student.approveUrl }}"><img src="{{ _p.web_plugin }}advanced_subscription/views/img/aprobar.png" width="90" height="25" alt=""></a></td>
+              <td valign="middle"><a href="{{ student.acceptUrl }}"><img src="{{ _p.web_plugin }}advanced_subscription/views/img/aprobar.png" width="90" height="25" alt=""></a></td>
               <td valign="middle"><a href="{{ student.rejectUrl }}"><img src="{{ _p.web_plugin }}advanced_subscription/views/img/desaprobar.png" width="90" height="25" alt=""></a></td>
               <td valign="middle"><a href="{{ student.rejectUrl }}"><img src="{{ _p.web_plugin }}advanced_subscription/views/img/desaprobar.png" width="90" height="25" alt=""></a></td>
             </tr>
             </tr>
             {% endfor %}
             {% endfor %}

+ 1 - 1
plugin/advanced_subscription/views/student_no_superior_notice_admin.tpl

@@ -49,7 +49,7 @@
                     <td height="356">&nbsp;</td>
                     <td height="356">&nbsp;</td>
                     <td valign="top"><p>{{ "MailDear" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
                     <td valign="top"><p>{{ "MailDear" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
                         <h2>{{ admin.complete_name }}</h2>
                         <h2>{{ admin.complete_name }}</h2>
-                        <p>{{ "MailContentStudentRequestNoSuperiorToAdmin"| get_plugin_lang("AdvancedSubscriptionPlugin") | format(complete_name_with_username, session.name, admin_view_url) }}</p>
+                        <p>{{ "MailContentStudentRequestNoSuperiorToAdmin"| get_plugin_lang("AdvancedSubscriptionPlugin") | format(student.complete_name_with_username, session.name, admin_view_url) }}</p>
                         <p>{{ "MailThankYou" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
                         <p>{{ "MailThankYou" | get_plugin_lang("AdvancedSubscriptionPlugin") }}</p>
                         <h3>{{ signature }}</h3></td>
                         <h3>{{ signature }}</h3></td>
                     <td>&nbsp;</td>
                     <td>&nbsp;</td>

+ 1 - 1
tests/datafiller/fill_whoisonline.php

@@ -21,7 +21,7 @@ function fill_whoisonline()
 	//filling the table
 	//filling the table
 	for ($i=1;$i <=$max;$i++) {
 	for ($i=1;$i <=$max;$i++) {
 		$date = api_get_utc_datetime();
 		$date = api_get_utc_datetime();
-		$sql = "INSERT INTO	$table_e_online (login_id, login_user_id, login_date, login_ip, c_id, session_id, access_url_id)
+		$sql = "INSERT INTO	$table_e_online (login_id, login_user_id, login_date, user_ip, c_id, session_id, access_url_id)
 				VALUES ('$i', '$i', '$date', '127.0.0.1', '', '0','1')";
 				VALUES ('$i', '$i', '$date', '127.0.0.1', '', '0','1')";
 		$rs = Database::query($sql);
 		$rs = Database::query($sql);
 	}
 	}

+ 1 - 1
tests/scripts/fix_exercise_score_in_lp.php

@@ -11,7 +11,7 @@ require_once '../../main/inc/global.inc.php';
 
 
 api_protect_admin_script();
 api_protect_admin_script();
 
 
-$tableExercise = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+$tableExercise = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
 $tableCourse = Database::get_main_table(TABLE_MAIN_COURSE);
 $tableCourse = Database::get_main_table(TABLE_MAIN_COURSE);
 
 
 $sql = "SELECT
 $sql = "SELECT

+ 1 - 1
tests/scripts/move_users.php

@@ -66,7 +66,7 @@ function moveUserFromCourseToCourse($originCourse, $destinationCourse, $debug =
     }
     }
     $output .= 'Moving students who have no exe results from course '.$originCourse.' to course '.$destinationCourse.$eol;
     $output .= 'Moving students who have no exe results from course '.$originCourse.' to course '.$destinationCourse.$eol;
     $tableCRU = Database::get_main_table(TABLE_MAIN_COURSE_USER);
     $tableCRU = Database::get_main_table(TABLE_MAIN_COURSE_USER);
-    $tableTEE = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
+    $tableTEE = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
     // Get the users who have passed an exam in the course of origin
     // Get the users who have passed an exam in the course of origin
     $sql = "SELECT distinct(exe_user_id) FROM $tableTEE
     $sql = "SELECT distinct(exe_user_id) FROM $tableTEE
         WHERE exe_cours_id = '$originCourse'";
         WHERE exe_cours_id = '$originCourse'";

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác