Skip to content

Commit 7e95c3d

Browse files
committed
Merge remote-tracking branch 'origin/1.11.x' into 1.11.x
2 parents c7290da + ab6c212 commit 7e95c3d

File tree

418 files changed

+27964
-3097
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

418 files changed

+27964
-3097
lines changed

documentation/changelog.html

Lines changed: 406 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
3+
require_once __DIR__.'/../../../vendor/autoload.php';
4+
require_once __DIR__.'/../../../app/AppKernel.php';
5+
6+
$kernel = new AppKernel('', '');
7+
8+
// Check for 'action' parameter in the GET request
9+
if (isset($_GET['action'])) {
10+
$action = $_GET['action'];
11+
12+
if ($action == 'time') {
13+
// Load the Chamilo configuration
14+
$alreadyInstalled = false;
15+
if (file_exists($kernel->getConfigurationFile())) {
16+
require_once $kernel->getConfigurationFile();
17+
$alreadyInstalled = true;
18+
}
19+
20+
// Load the API library BEFORE loading the Chamilo configuration
21+
require_once $_configuration['root_sys'].'main/inc/lib/api.lib.php';
22+
23+
if (api_get_configuration_value('session_lifetime_controller')) {
24+
// Get the session
25+
session_name('ch_sid');
26+
session_start();
27+
28+
$session = new ChamiloSession();
29+
30+
$endTime = 0;
31+
$isExpired = false;
32+
$timeLeft = -1;
33+
34+
$currentTime = time();
35+
36+
// Existing code for time action
37+
if ($alreadyInstalled && api_get_user_id()) {
38+
$endTime = $session->end_time();
39+
$isExpired = $session->is_expired();
40+
} else {
41+
// Chamilo not installed or user not logged in
42+
$endTime = $currentTime + 315360000; // This sets a default end time far in the future
43+
$isExpired = false;
44+
}
45+
46+
$timeLeft = $endTime - $currentTime;
47+
}
48+
else {
49+
$endTime = 999999;
50+
$isExpired = false;
51+
$timeLeft = 999999;
52+
}
53+
54+
if ($endTime > 0) {
55+
echo json_encode(['sessionEndDate' => $endTime, 'sessionTimeLeft' => $timeLeft, 'sessionExpired' => $isExpired]);
56+
} else {
57+
http_response_code(500);
58+
echo json_encode(['error' => 'Error retrieving data from the current session']);
59+
}
60+
} elseif ($action == 'logout') {
61+
require_once __DIR__.'/../../../main/inc/global-min.inc.php';
62+
63+
$userId = api_get_user_id();
64+
online_logout($userId, false);
65+
echo json_encode(['message' => 'Logged out successfully']);
66+
} else {
67+
// Handle unexpected action value
68+
http_response_code(400);
69+
echo json_encode(['error' => 'Invalid action parameter']);
70+
}
71+
} else {
72+
// No action provided
73+
http_response_code(400);
74+
echo json_encode(['error' => 'No action parameter provided']);
75+
}

main/inc/lib/banner.lib.php

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -89,19 +89,22 @@ function get_tabs($courseId = null)
8989
$navigation['session_my_space']['key'] = 'my-space';
9090
$navigation['session_my_space']['icon'] = 'my-space.png';
9191
} else {
92-
$navigation['session_my_progress']['url'] = api_get_path(WEB_CODE_PATH);
93-
// Link to my progress
94-
switch (api_get_setting('gamification_mode')) {
95-
case 1:
96-
$navigation['session_my_progress']['url'] .= 'gamification/my_progress.php';
97-
break;
98-
default:
99-
$navigation['session_my_progress']['url'] .= 'auth/my_progress.php';
100-
}
92+
$hideMyProgressTab = api_get_configuration_value('hide_my_progress_tab');
93+
if (true !== $hideMyProgressTab) {
94+
$navigation['session_my_progress']['url'] = api_get_path(WEB_CODE_PATH);
95+
// Link to my progress
96+
switch (api_get_setting('gamification_mode')) {
97+
case 1:
98+
$navigation['session_my_progress']['url'] .= 'gamification/my_progress.php';
99+
break;
100+
default:
101+
$navigation['session_my_progress']['url'] .= 'auth/my_progress.php';
102+
}
101103

102-
$navigation['session_my_progress']['title'] = get_lang('MyProgress');
103-
$navigation['session_my_progress']['key'] = 'my-progress';
104-
$navigation['session_my_progress']['icon'] = 'my-progress.png';
104+
$navigation['session_my_progress']['title'] = get_lang('MyProgress');
105+
$navigation['session_my_progress']['key'] = 'my-progress';
106+
$navigation['session_my_progress']['icon'] = 'my-progress.png';
107+
}
105108
}
106109
}
107110

main/inc/lib/display.lib.php

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1572,6 +1572,11 @@ public static function show_notification($courseInfo, $loadAjax = true)
15721572
$row = Database::fetch_array($result, 'ASSOC');
15731573
$latestDate = $row['access_date'];
15741574
}
1575+
// Get a timestamp format copy, for use in c_lp_item_view below
1576+
$originalTimeZone = date_default_timezone_get();
1577+
date_default_timezone_set('UTC');
1578+
$latestTimestamp = strtotime($latestDate);
1579+
date_default_timezone_set($originalTimeZone);
15751580

15761581
$sessionCondition = api_get_session_condition(
15771582
$sessionId,
@@ -1596,6 +1601,7 @@ public static function show_notification($courseInfo, $loadAjax = true)
15961601
$group_ids[] = 0; //add group 'everyone'
15971602
$notifications = [];
15981603
if ($tools) {
1604+
$latestLocalDate = $latestDate;
15991605
foreach ($tools as $tool) {
16001606
$toolName = $tool['name'];
16011607
$toolName = Database::escape_string($toolName);
@@ -1604,6 +1610,13 @@ public static function show_notification($courseInfo, $loadAjax = true)
16041610
if ($toolName == 'student_publication' || $toolName == 'work') {
16051611
$toolCondition = " (tool = 'work' OR tool = 'student_publication') AND ";
16061612
}
1613+
if ($toolName == 'learnpath') {
1614+
// Make sure c_lp_item_view is considered in the latestDate calculation for LPs
1615+
$lpLatest = self::getLatestLpView($course_id, $user_id, $sessionId, $latestTimestamp);
1616+
if (!empty($lpLatest)) {
1617+
$latestLocalDate = $lpLatest;
1618+
}
1619+
}
16071620

16081621
$toolName = addslashes($toolName);
16091622

@@ -1614,7 +1627,7 @@ public static function show_notification($courseInfo, $loadAjax = true)
16141627
lastedit_type NOT LIKE '%Deleted%' AND
16151628
lastedit_type NOT LIKE '%deleted%' AND
16161629
lastedit_type NOT LIKE '%DocumentInvisible%' AND
1617-
lastedit_date > '$latestDate' AND
1630+
lastedit_date > '$latestLocalDate' AND
16181631
lastedit_user_id != $user_id $sessionCondition AND
16191632
visibility != 2 AND
16201633
(to_user_id IN ('$user_id', '0') OR to_user_id IS NULL) AND
@@ -3071,4 +3084,40 @@ public static function returnHeaderWithPercentage($header, $percentage)
30713084

30723085
return "$header<br><small>$percentHtml</small>";
30733086
}
3087+
3088+
/**
3089+
* Get the latest view (later than given date) in any LP in this course/session
3090+
* as datetime format, or null
3091+
* @param int $courseId
3092+
* @param int $userId
3093+
* @param int $sessionId
3094+
* @param int $latestTimestamp The latest time for the tool in general, as obtained through track_e_access
3095+
* @return string|null The latest view if later than $latestTimestamp, or null otherwise
3096+
*/
3097+
public static function getLatestLpView(int $courseId, int $userId, int $sessionId, int $latestTimestamp): ?string
3098+
{
3099+
// Control if the latest view in c_lp_view is more recent than in track_e_access
3100+
// Use case: a user skipped the course home page by following a direct link to a LP in an email
3101+
// $latestDate is in datetime format, while c_lp_item_view.start_time is in EPOCH
3102+
$t_lp_item_view = Database::get_course_table(TABLE_LP_ITEM_VIEW);
3103+
$t_lp_view = Database::get_course_table(TABLE_LP_VIEW);
3104+
$sql = "SELECT cliv.start_time FROM $t_lp_item_view cliv
3105+
INNER JOIN $t_lp_view clv ON cliv.lp_view_id = clv.id
3106+
WHERE
3107+
clv.c_id = $courseId AND
3108+
clv.user_id = $userId AND
3109+
clv.session_id = $sessionId AND
3110+
cliv.start_time > $latestTimestamp
3111+
ORDER BY cliv.start_time DESC
3112+
LIMIT 1";
3113+
$resultItems = Database::query($sql);
3114+
if (Database::num_rows($resultItems)) {
3115+
$rowItems = Database::fetch_assoc($resultItems);
3116+
$controlDate = $rowItems['start_time'];
3117+
// convert to date
3118+
return date('Y-m-d H:i:s', $controlDate);
3119+
}
3120+
3121+
return null;
3122+
}
30743123
}

main/inc/lib/message.lib.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3049,6 +3049,57 @@ public static function getUsersThatHadConversationWithUser($userId, $startDate =
30493049
return $userList;
30503050
}
30513051

3052+
/**
3053+
* Retrieves a list of users with whom the specified user has exchanged messages within an optional date range.
3054+
*
3055+
* @param int $userId The user ID for whom to retrieve message exchange.
3056+
* @param string|null $startDate Start date to filter the messages (optional).
3057+
* @param string|null $endDate End date to filter the messages (optional).
3058+
*
3059+
* @return array Array of user information for each user with whom the specified user has exchanged messages.
3060+
*/
3061+
public static function getMessageExchangeWithUser($userId, $startDate = null, $endDate = null)
3062+
{
3063+
$messagesTable = Database::get_main_table(TABLE_MESSAGE);
3064+
$userId = (int) $userId;
3065+
3066+
if ($startDate !== null) {
3067+
$startDate = Database::escape_string($startDate);
3068+
}
3069+
if ($endDate !== null) {
3070+
$endDate = Database::escape_string($endDate);
3071+
}
3072+
3073+
$sql = "SELECT DISTINCT user_sender_id AS user_id
3074+
FROM $messagesTable
3075+
WHERE user_receiver_id = $userId" .
3076+
($startDate ? " AND send_date >= '$startDate'" : "") .
3077+
($endDate ? " AND send_date <= '$endDate'" : "") .
3078+
" UNION
3079+
SELECT DISTINCT user_receiver_id
3080+
FROM $messagesTable
3081+
WHERE user_sender_id = $userId" .
3082+
($startDate ? " AND send_date >= '$startDate'" : "") .
3083+
($endDate ? " AND send_date <= '$endDate'" : "");
3084+
3085+
$result = Database::query($sql);
3086+
$users = Database::store_result($result);
3087+
3088+
$userList = [];
3089+
foreach ($users as $userData) {
3090+
$userId = $userData['user_id'];
3091+
if (empty($userId)) {
3092+
continue;
3093+
}
3094+
$userInfo = api_get_user_info($userId);
3095+
if ($userInfo) {
3096+
$userList[$userId] = $userInfo;
3097+
}
3098+
}
3099+
3100+
return $userList;
3101+
}
3102+
30523103
/**
30533104
* @param int $userId
30543105
* @param int $otherUserId

main/inc/lib/moodleexport/MoodleExport.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ private function createMoodleBackupXml(string $destinationDir, int $version): vo
117117
$siteHash = md5(uniqid(mt_rand(), true));
118118
$wwwRoot = api_get_path(WEB_PATH);
119119

120+
$courseStartDate = strtotime($courseInfo['creation_date']);
121+
$courseEndDate = $courseStartDate + (365 * 24 * 60 * 60);
122+
120123
// Build the XML content for the backup
121124
$xmlContent = '<?xml version="1.0" encoding="UTF-8"?>' . PHP_EOL;
122125
$xmlContent .= '<moodle_backup>' . PHP_EOL;
@@ -137,8 +140,8 @@ private function createMoodleBackupXml(string $destinationDir, int $version): vo
137140
$xmlContent .= ' <original_course_format>' . get_lang('Topics') . '</original_course_format>' . PHP_EOL;
138141
$xmlContent .= ' <original_course_fullname>' . htmlspecialchars($courseInfo['title']) . '</original_course_fullname>' . PHP_EOL;
139142
$xmlContent .= ' <original_course_shortname>' . htmlspecialchars($courseInfo['code']) . '</original_course_shortname>' . PHP_EOL;
140-
$xmlContent .= ' <original_course_startdate>' . $courseInfo['startdate'] . '</original_course_startdate>' . PHP_EOL;
141-
$xmlContent .= ' <original_course_enddate>' . $courseInfo['enddate'] . '</original_course_enddate>' . PHP_EOL;
143+
$xmlContent .= ' <original_course_startdate>' . $courseStartDate . '</original_course_startdate>' . PHP_EOL;
144+
$xmlContent .= ' <original_course_enddate>' . $courseEndDate . '</original_course_enddate>' . PHP_EOL;
142145
$xmlContent .= ' <original_course_contextid>' . $courseInfo['real_id'] . '</original_course_contextid>' . PHP_EOL;
143146
$xmlContent .= ' <original_system_contextid>' . api_get_current_access_url_id() . '</original_system_contextid>' . PHP_EOL;
144147

main/inc/lib/moodleexport/QuizExport.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ public function getData(int $quizId, int $sectionId): array
5252
$quizResources = $this->course->resources[RESOURCE_QUIZ];
5353

5454
foreach ($quizResources as $quiz) {
55+
if ($quiz->obj->iid == -1) {
56+
continue;
57+
}
58+
5559
if ($quiz->obj->iid == $quizId) {
5660
$contextid = $quiz->obj->c_id;
5761

main/inc/lib/sessionmanager.lib.php

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8085,16 +8085,31 @@ public static function setForm(FormValidator $form, array $sessionInfo = [])
80858085

80868086
$form->addElement('checkbox', 'show_description', null, get_lang('ShowDescription'));
80878087

8088+
$visibilityOptions = [
8089+
SESSION_VISIBLE_READ_ONLY => get_lang('SessionReadOnly'),
8090+
SESSION_VISIBLE => get_lang('SessionAccessible'),
8091+
SESSION_INVISIBLE => api_ucfirst(get_lang('SessionNotAccessible')),
8092+
];
8093+
8094+
$visibilityOptionsConfiguration = api_get_configuration_value('session_visibility_after_end_date_options_configuration');
8095+
if (!empty($visibilityOptionsConfiguration)) {
8096+
foreach ($visibilityOptionsConfiguration['visibility_options_to_hide'] as $option) {
8097+
$option = trim($option);
8098+
if (defined($option)) {
8099+
$constantValue = constant($option);
8100+
if (isset($visibilityOptions[$constantValue])) {
8101+
unset($visibilityOptions[$constantValue]);
8102+
}
8103+
}
8104+
}
8105+
}
8106+
80888107
$visibilityGroup = [];
80898108
$visibilityGroup[] = $form->createElement(
80908109
'select',
80918110
'session_visibility',
80928111
null,
8093-
[
8094-
SESSION_VISIBLE_READ_ONLY => get_lang('SessionReadOnly'),
8095-
SESSION_VISIBLE => get_lang('SessionAccessible'),
8096-
SESSION_INVISIBLE => api_ucfirst(get_lang('SessionNotAccessible')),
8097-
]
8112+
$visibilityOptions
80988113
);
80998114
$form->addGroup(
81008115
$visibilityGroup,

main/install/configuration.dist.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,9 @@
990990
// Block access to any user to "my progress" page
991991
//$_configuration['block_my_progress_page'] = false;
992992

993+
// Hides the "my progress" tab from the navigation menu
994+
//$_configuration['hide_my_progress_tab'] = false;
995+
993996
// Add user extra fields in report: main/mySpace/exercise_category_report.php
994997
//$_configuration['exercise_category_report_user_extra_fields'] = ['fields' => ['skype', 'rssfeeds']];
995998

@@ -2389,6 +2392,14 @@
23892392
// they are only accessible during the active duration).
23902393
//$_configuration['session_coach_access_after_duration_end'] = false;
23912394

2395+
// Hide visibility options for session visibility after end date.
2396+
// Admitted options: SESSION_VISIBLE_READ_ONLY, SESSION_VISIBLE, SESSION_INVISIBLE
2397+
/*$_configuration['session_visibility_after_end_date_options_configuration'] = [
2398+
'visibility_options_to_hide' => [
2399+
'SESSION_VISIBLE_READ_ONLY '
2400+
]
2401+
];*/
2402+
23922403
// Restrict the list of students to subscribe in the course session. And disable
23932404
// registration for users in all courses from Resume Session page
23942405
//$_configuration['session_course_users_subscription_limited_to_session_users'] = false;
@@ -2588,3 +2599,6 @@
25882599
// is '$1EdTech-CC-FILEBASE$' (the latest), but previous versions of the standard
25892600
// recommended '$IMS-CC-FILEBASE$', so you might want to use that for greater compatibility.
25902601
//$_configuration['commoncartridge_path_token'] = '$IMS-CC-FILEBASE$';
2602+
2603+
// Set the following parameter to true to enable a session lifetime controller that notifies users that their session is about to expire
2604+
//$_configuration['session_lifetime_controller'] = false;

main/install/version.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
/**
1414
* Variables used from the main/install/index.php.
1515
*/
16-
$new_version = '1.11.26';
16+
$new_version = '1.11.28';
1717
$new_version_status = 'stable';
1818
$new_version_last_id = 0;
1919
$new_version_stable = true;

0 commit comments

Comments
 (0)