';
+ return $html;
+ }
} //end class Display
\ No newline at end of file
diff --git a/main/inc/lib/events.lib.inc.php b/main/inc/lib/events.lib.inc.php
index f5539768d1..68c9db57ab 100644
--- a/main/inc/lib/events.lib.inc.php
+++ b/main/inc/lib/events.lib.inc.php
@@ -484,24 +484,34 @@ function exercise_attempt($score, $answer, $question_id, $exe_id, $position, $ex
$file = Database::escape_string(basename($nano->load_filename_if_exists(false)));
}
- $sql = "INSERT INTO $TBL_TRACK_ATTEMPT (exe_id, user_id, question_id, answer, marks, course_code, session_id, position, tms, filename)
- VALUES (
- ".$exe_id.",
- ".$user_id.",
- '".$question_id."',
- '".$answer."',
- '".$score."',
- '".api_get_course_id()."',
- '".api_get_session_id()."',
- '".$position."',
- '".$now."',
- '".$file."'
- )";
-
- if ($debug) error_log("Saving question attempt: ");
- if ($debug) error_log($sql);
if (!empty($question_id) && !empty($exe_id) && !empty($user_id)) {
+
+ //Check if attempt exists
+ $sql = "SELECT exe_id FROM $TBL_TRACK_ATTEMPT WHERE exe_id = $exe_id AND user_id = $user_id AND question_id = $question_id";
+ $result = Database::query($sql);
+ if (Database::num_rows($result)) {
+ if ($debug) error_log("Attempt already exist: exe_id: $exe_id - user_id:$user_id - question_id:$question_id");
+ //The attempt already exist do not update use update_event_exercice() instead
+ return false;
+ }
+ $sql = "INSERT INTO $TBL_TRACK_ATTEMPT (exe_id, user_id, question_id, answer, marks, course_code, session_id, position, tms, filename)
+ VALUES (
+ ".$exe_id.",
+ ".$user_id.",
+ '".$question_id."',
+ '".$answer."',
+ '".$score."',
+ '".api_get_course_id()."',
+ '".api_get_session_id()."',
+ '".$position."',
+ '".$now."',
+ '".$file."'
+ )";
+
+ if ($debug) error_log("Saving question attempt: ");
+ if ($debug) error_log($sql);
+
$res = Database::query($sql);
if (defined('ENABLED_LIVE_EXERCISE_TRACKING')){
$recording_table = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING);
diff --git a/main/inc/lib/mail.lib.inc.php b/main/inc/lib/mail.lib.inc.php
index cebb07e044..375a01f479 100644
--- a/main/inc/lib/mail.lib.inc.php
+++ b/main/inc/lib/mail.lib.inc.php
@@ -80,6 +80,10 @@ function api_mail_html($recipient_name, $recipient_email, $subject, $message, $s
$mail->AddReplyTo($sender_email, $sender_name);
}
+ if (isset($extra_headers['reply_to'])) {
+ $mail->AddReplyTo($extra_headers['reply_to']['mail'], $extra_headers['reply_to']['name']);
+ }
+
// Attachments
// $mail->AddAttachment($path);
// $mail->AddAttachment($path, $filename);
diff --git a/main/inc/lib/tracking.lib.php b/main/inc/lib/tracking.lib.php
index 1defb02510..fa0c376393 100644
--- a/main/inc/lib/tracking.lib.php
+++ b/main/inc/lib/tracking.lib.php
@@ -2657,8 +2657,7 @@ class Tracking {
$weighting = $exercise_stat['exe_weighting'];
$exe_id = $exercise_stat['exe_id'];
- //$latest_attempt_url .= ' '.Display::return_icon('quiz.gif', get_lang('Quiz')).' ';
- $latest_attempt_url .= '../exercice/exercise_show.php?origin=myprogress&id='.$exe_id.'&cidReq='.$course_info['code'].'&id_session='.$session_id;
+ $latest_attempt_url .= api_get_path(WEB_CODE_PATH).'exercice/result.php?id='.$exe_id.'&cidReq='.$course_info['code'].'&show_headers=1&id_session='.$session_id;
$percentage_score_result = Display::url(show_score($score, $weighting), $latest_attempt_url);
$my_score = 0;
if (!empty($weighting) && intval($weighting) != 0) {
diff --git a/main/inc/lib/usermanager.lib.php b/main/inc/lib/usermanager.lib.php
index c554908594..e639dfe8e4 100644
--- a/main/inc/lib/usermanager.lib.php
+++ b/main/inc/lib/usermanager.lib.php
@@ -366,12 +366,15 @@ class UserManager {
}
/**
- * Can user be deleted?
- * This functions checks if there's a course in which the given user is the
+ * Can user be deleted? This function checks whether there's a course
+ * in which the given user is the
* only course administrator. If that is the case, the user can't be
* deleted because the course would remain without a course admin.
* @param int $user_id The user id
* @return boolean true if user can be deleted
+ * @assert (null) === false
+ * @assert (-1) === false
+ * @assert ('abc') === false
*/
public static function can_delete_user($user_id) {
global $_configuration;
@@ -394,9 +397,14 @@ class UserManager {
}
/**
- * Delete a user from the platform
- * @param int $user_id The user id
+ * Delete a user from the platform, and all its belongings. This is a
+ * very dangerous function that should only be accessible by
+ * super-admins. Other roles should only be able to disable a user,
+ * which removes access to the platform but doesn't delete anything.
+ * @param int The ID of th user to be deleted
* @return boolean true if user is succesfully deleted, false otherwise
+ * @assert (null) === false
+ * @assert ('abc') === false
*/
public static function delete_user($user_id) {
@@ -513,14 +521,16 @@ class UserManager {
}
/**
- * Deactivate users. Can be called either as:
- *
- * - UserManager :: delete_users(1, 2, 3);
+ * Deletes users completely. Can be called either as:
+ * - UserManager :: delete_users(1, 2, 3); or
* - UserManager :: delete_users(array(1, 2, 3));
- *
* @param array|int $ids
* @return boolean True if at least one user was successfuly deleted. False otherwise.
* @author Laurent Opprecht
+ * @uses UserManager::delete_user() to actually delete each user
+ * @assert (null) === false
+ * @assert (-1) === false
+ * @assert (array(-1)) === false
*/
static function delete_users($ids = array()) {
$result = false;
@@ -534,14 +544,14 @@ class UserManager {
}
/**
- * Deactivate users. Can be called either as:
- *
+ * Disable users. Can be called either as:
* - UserManager :: deactivate_users(1, 2, 3);
* - UserManager :: deactivate_users(array(1, 2, 3));
- *
* @param array|int $ids
* @return boolean
* @author Laurent Opprecht
+ * @assert (null) === false
+ * @assert (array(-1)) === false
*/
static function deactivate_users($ids = array()) {
if (empty($ids)) {
@@ -557,14 +567,14 @@ class UserManager {
}
/**
- * Activate users. Can be called either as:
- *
+ * Enable users. Can be called either as:
* - UserManager :: activate_users(1, 2, 3);
* - UserManager :: activate_users(array(1, 2, 3));
- *
- * @param array|int $ids
+ * @param array|int IDs of the users to enable
* @return boolean
* @author Laurent Opprecht
+ * @assert (null) === false
+ * @assert (array(-1)) === false
*/
static function activate_users($ids = array()) {
if (empty($ids)) {
@@ -583,6 +593,8 @@ class UserManager {
* @param int $user_id
* @param string $openid
* @return boolean true if the user information was updated
+ * @assert (false,'') === false
+ * @assert (-1,'') === false
*/
public static function update_openid($user_id, $openid) {
$table_user = Database :: get_main_table(TABLE_MAIN_USER);
@@ -594,22 +606,23 @@ class UserManager {
}
/**
- * Update user information
- * @param int $user_id
- * @param string $firstname
- * @param string $lastname
- * @param string $username
- * @param string $password
- * @param string $auth_source
- * @param string $email
- * @param int $status
- * @param string $official_code
- * @param string $phone
- * @param string $picture_uri
+ * Update user information with all the parameters passed to this function
+ * @param int The ID of the user to be updated
+ * @param string The user's firstname
+ * @param string The user's lastname
+ * @param string The user's username (login)
+ * @param string The user's password
+ * @param string The authentication source (default: "platform")
+ * @param string The user's e-mail address
+ * @param int The user's status
+ * @param string The user's official code (usually just an internal institutional code)
+ * @param string The user's phone number
+ * @param string The user's picture URL (internal to the Chamilo directory)
* @param int The user ID of the person who registered this user (optional, defaults to null)
* @param int The department of HR in which the user is registered (optional, defaults to 0)
* @param array A series of additional fields to add to this user as extra fields (optional, defaults to null)
* @return boolean true if the user information was updated
+ * @assert (false) === false
*/
public static function update_user($user_id, $firstname, $lastname, $username, $password = null, $auth_source = null, $email, $status, $official_code, $phone, $picture_uri, $expiration_date, $active, $creator_id = null, $hr_dept_id = 0, $extra = null, $language = 'english', $encrypt_method = '', $send_email = false, $reset_password = 0) {
global $_configuration;
@@ -721,6 +734,9 @@ class UserManager {
*
* @param int user_id
* @param int Enable or disable
+ * @return void
+ * @assert (-1,0) === false
+ * @assert (1,1) === true
*/
public static function change_active_state($user_id, $active, $send_email_if_activated = false) {
$user_id = intval($user_id);
@@ -760,6 +776,8 @@ class UserManager {
* Disables a user
*
* @param int User id
+ * @uses UserManager::change_active_state() to actually disable the user
+ * @assert (0) === false
*/
public static function disable($user_id) {
self::change_active_state($user_id, 0);
@@ -769,17 +787,21 @@ class UserManager {
* Enable a user
*
* @param int User id
+ * @uses UserManager::change_active_state() to actually disable the user
+ * @assert (0) === false
*/
public static function enable($user_id) {
self::change_active_state($user_id, 1);
}
/**
- * Returns the user's id based on the original id and field name in the extra fields. Returns 0 if no user was found
- *
+ * Returns the user's id based on the original id and field name in
+ * the extra fields. Returns 0 if no user was found. This function is
+ * mostly useful in the context of a web services-based sinchronization
* @param string Original user id
* @param string Original field name
* @return int User id
+ * @assert ('0','---') === 0
*/
public static function get_user_id_from_original_id($original_user_id_value, $original_user_id_name) {
$t_uf = Database::get_main_table(TABLE_MAIN_USER_FIELD);
@@ -798,8 +820,11 @@ class UserManager {
* Check if a username is available
* @param string the wanted username
* @return boolean true if the wanted username is available
+ * @assert ('') === false
+ * @assert ('xyzxyzxyz') === true
*/
public static function is_username_available($username) {
+ if (empty($username)) { return false; }
$table_user = Database :: get_main_table(TABLE_MAIN_USER);
$sql = "SELECT username FROM $table_user WHERE username = '".Database::escape_string($username)."'";
$res = Database::query($sql);
@@ -815,6 +840,8 @@ class UserManager {
* @return string Suggests a username that contains only ASCII-letters and digits, without check for uniqueness within the system.
* @author Julio Montoya Armas
* @author Ivan Tcholakov, 2009 - rework about internationalization.
+ * @assert ('','') === false
+ * @assert ('a','b') === 'ab'
*/
public static function create_username($firstname, $lastname, $language = null, $encoding = null) {
if (is_null($encoding)) {
diff --git a/main/lang/english/admin.inc.php b/main/lang/english/admin.inc.php
index 6d9ecafb5b..e29cf6fb53 100644
--- a/main/lang/english/admin.inc.php
+++ b/main/lang/english/admin.inc.php
@@ -1257,6 +1257,8 @@ $SessionStartDate = "Access start date";
$SessionDisplayEndDate = "End date to display";
$SessionDisplayStartDate = "Start date to display";
$UserHasNoCourse = "This user is not subscribed to any course";
+$SessionPageEnabledComment = "When this option is enabled, the session title is a link to a special session page. When disabled, it is only a text title, without link. The session page linked to might be confusing for some users, which is why you might want to disable it.";
+$SessionPageEnabledTitle = "Enable session link in courses list";
$ThisValueIsUsedInTheCourseURL = "This value is used in the course URL";
$ThereAreUsersUsingThisLanguageYouWantToDisableThisLanguageAndSetUsersWithTheDefaultPortalLanguage = "There are users using this language. Do you want to disable this language and set all this users with the default portal language?";
$SessionTutorsCanSeeExpiredSessionsResultsComment = "Can session tutors see the reports for their session after it has expired?";
diff --git a/main/lang/english/learnpath.inc.php b/main/lang/english/learnpath.inc.php
index a41afd05e3..cbd5f5c5b1 100644
--- a/main/lang/english/learnpath.inc.php
+++ b/main/lang/english/learnpath.inc.php
@@ -247,6 +247,9 @@ $ModifyHotPotatoes = "Modify hotpotatoes";
$SaveHotpotatoes = "Save hotpotatoes";
$ReturnToLPList = "Return to list";
$LpPrerequisiteDescription = "Selecting another learning path as a prerequisite will hide the current prerequisite until the one in prerequisite is fully completed (100%)";
+$PrerequisitesOptions = "Prerequisites options";
+$ClearAllPrerequisites = "Clear all prerequisites";
+$SetPrerequisiteForEachItem = "Set previous step as prerequisite for each step";
$ClickOnTheLearnerViewToSeeYourLearningPath = "Click on the [Learner view] button to see your learning path";
$ExerciseCantBeEditedAfterAddingToTheLP = "Exercise can't be edited after being added to the Learning Path";
$EnableTimeLimits = "Enable availability limits";
diff --git a/main/lang/english/tracking.inc.php b/main/lang/english/tracking.inc.php
index d239616bfc..0a1c78bac8 100644
--- a/main/lang/english/tracking.inc.php
+++ b/main/lang/english/tracking.inc.php
@@ -269,6 +269,9 @@ $LinkInvisible = "Link made invisible";
$LinkAdded = "Link added";
$Minutes = "Minutes";
$BackupCreated = "Backup created";
+$TrainingHoursAccumulated = "Training hours accumulated";
+$ManHours = "Man hours";
+$NotesObtained = "Notes obtained";
$DisplayCourseOverview = "Courses overview";
$DisplaySessionOverview = "Sessions overview";
$TotalNumberOfMessages = "Total number of messages";
diff --git a/main/lang/english/trad4all.inc.php b/main/lang/english/trad4all.inc.php
index a6b77c7504..ddea0c5b38 100644
--- a/main/lang/english/trad4all.inc.php
+++ b/main/lang/english/trad4all.inc.php
@@ -950,6 +950,7 @@ $SkillXWithCourseX = "%s with %s";
$ToGetToLearnXYouWillNeedToTakeOneOfTheFollowingCourses = "To get to learn %s you will need to take one of the following courses:";
$YourSkillRankingX = "Your skill ranking: %s";
$ManageSkills = "Manage skills";
+$StartDateMustBeBeforeTheEndDate = "Start date must be before the end date";
$SkillRoot = "Root";
$SkillInfo = "Skill info";
$GetNewSkills = "Get new skills";
@@ -976,6 +977,7 @@ $NumberOfCoursesPrivate = "Number of private courses";
$NumberOfCoursesClosed = "Number of closed courses";
$NumberOfCoursesTotal = "Total number of courses";
$NumberOfUsersActive = "Number of active users";
+$Approved = "Approved";
$EditSettings = "Edit settings";
$ThisValueCantBeChanged = "This value can't be changed.";
$TotalAvailableUsers = "Total available users";
diff --git a/main/newscorm/learnpath.class.php b/main/newscorm/learnpath.class.php
index d95723b3e3..8186f94a5b 100644
--- a/main/newscorm/learnpath.class.php
+++ b/main/newscorm/learnpath.class.php
@@ -113,6 +113,8 @@ class learnpath {
}
}
+ $this->set_course_int_id($course_id);
+
// Check learnpath ID.
if (empty($lp_id)) {
$this->error = 'Learnpath ID is empty';
@@ -3608,7 +3610,6 @@ class learnpath {
$prereq_string = $this->items[$item]->get_prereq_string();
}
-
if (empty($prereq_string)) {
return true;
}
@@ -4043,7 +4044,6 @@ class learnpath {
} else {
return false;
}
-
}
/**
@@ -4234,7 +4234,7 @@ class learnpath {
if ($this->debug > 2) {
error_log('New LP - lp updated with new preview requisite : ' . $this->requisite, 0);
}
- $res = Database::query($sql);
+ Database::query($sql);
return true;
}
@@ -4368,7 +4368,7 @@ class learnpath {
if ($this->debug > 2) {
error_log('New LP - lp updated with new expired_on : ' . $this->modified_on, 0);
}
- $res = Database::query($sql);
+ Database::query($sql);
return true;
}
@@ -5308,6 +5308,18 @@ class learnpath {
$return .= '' . Display :: return_icon('upload_audio.png', get_lang('UpdateAllAudioFragments'),'',ICON_SIZE_MEDIUM).'';
$return .= '' . Display :: return_icon('settings.png', get_lang('CourseSettings'),'',ICON_SIZE_MEDIUM).'';
+
+ $buttons = array(
+ array(
+ 'title' => get_lang('SetPrerequisiteForEachItem'),
+ 'href' => 'lp_controller.php?'.api_get_cidreq().'&action=set_previous_step_as_prerequisite&lp_id=' . $_SESSION['oLP']->lp_id,
+ ),
+ array(
+ 'title' => get_lang('ClearAllPrerequisites'),
+ 'href' => 'lp_controller.php?'.api_get_cidreq().'&action=clear_prerequisites&lp_id=' . $_SESSION['oLP']->lp_id,
+ ),
+ );
+ $return .= Display::group_button(get_lang('PrerequisitesOptions'), $buttons);
$return .= '