Skip to content

Commit e207c07

Browse files
committed
Merge branch 'master' of github.com:chamilo/chamilo-lms
2 parents f1b0005 + abdb829 commit e207c07

5 files changed

Lines changed: 208 additions & 74 deletions

File tree

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,45 @@
11
<?php
22
/* For license terms, see /license.txt */
33

4+
use Chamilo\CoreBundle\Entity\User;
45
use Chamilo\CoreBundle\Framework\Container;
56

67
require_once __DIR__.'/../inc/global.inc.php';
78

8-
$token = $_GET['token'] ?? '';
9+
$token = (string) ($_GET['token'] ?? '');
10+
$token = trim($token);
911

10-
if (!ctype_alnum($token)) {
12+
// Allow typical tokens (alnum, "_" and "-") to avoid rejecting UUID-like tokens.
13+
if ($token === '' || !preg_match('/^[a-zA-Z0-9_-]+$/', $token)) {
1114
$token = '';
1215
}
1316

14-
/** @var \Chamilo\CoreBundle\Entity\User $user */
15-
$user = Container::getUserRepository()->findUserByConfirmationToken($token);
17+
/** @var User|null $user */
18+
$user = null;
19+
if ($token !== '') {
20+
$user = Container::getUserRepository()->findOneBy(['confirmationToken' => $token]);
21+
}
1622

1723
if ($user) {
18-
$user->setActive(1); // Set to 1 to activate the user
24+
$user->setActive(1);
1925
$user->setConfirmationToken(null);
2026

2127
Database::getManager()->persist($user);
2228
Database::getManager()->flush();
2329

24-
// See where to redirect the user to, if any redirection has been set
30+
// Default redirect
2531
$url = api_get_path(WEB_PATH);
2632

27-
if (!empty($_GET['c'])) {
28-
$courseCode = Security::remove_XSS($_GET['c']);
29-
}
30-
if (!empty($_GET['s'])) {
31-
$sessionId = (int) $_GET['s'];
33+
$courseId = !empty($_GET['c']) ? (int) $_GET['c'] : 0;
34+
$sessionId = !empty($_GET['s']) ? (int) $_GET['s'] : 0;
35+
36+
$courseCode = '';
37+
if ($courseId > 0) {
38+
$courseInfo = api_get_course_info_by_id($courseId);
39+
$courseCode = (string) ($courseInfo['code'] ?? $courseInfo['course_code'] ?? $courseInfo['directory'] ?? '');
3240
}
3341

34-
// Get URL to a course, to a session, or an empty string
42+
// Get URL to a course (in session), to a session, or empty.
3543
$courseUrl = api_get_course_url($courseCode, $sessionId);
3644
if (!empty($courseUrl)) {
3745
$url = $courseUrl;
@@ -47,12 +55,13 @@
4755
Display::addFlash(
4856
Display::return_message(get_lang('User confirmed. Now you can login the platform.'), 'success')
4957
);
58+
5059
header('Location: '.$url);
5160
exit;
52-
} else {
53-
Display::addFlash(
54-
Display::return_message(get_lang('Link expired, please try again.'))
55-
);
56-
header('Location: '.api_get_path(WEB_PATH));
57-
exit;
5861
}
62+
63+
Display::addFlash(
64+
Display::return_message(get_lang('Link expired, please try again.'))
65+
);
66+
header('Location: '.api_get_path(WEB_PATH));
67+
exit;

public/main/gradebook/lib/be/attendancelink.class.php

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -101,20 +101,32 @@ public function calc_score(?int $studentId = null, ?string $type = null): array
101101

102102
// Load attendance settings (qualify max + require unique mode)
103103
$sql = 'SELECT attendance_qualify_max, require_unique
104-
FROM '.$this->get_attendance_table().'
105-
WHERE iid = '.$attendanceId;
104+
FROM '.$this->get_attendance_table().'
105+
WHERE iid = '.(int) $attendanceId;
106106
$query = Database::query($sql);
107107
$attendance = Database::fetch_assoc($query);
108108

109109
$qualifyMax = (float) ($attendance['attendance_qualify_max'] ?? 0);
110110
$requireUnique = !empty($attendance['require_unique']);
111111

112112
// Avoid gradebook showing 0/0 in require-unique mode when qualify max was never set.
113-
if ($requireUnique && $qualifyMax <= 0) {
113+
if ($requireUnique && $qualifyMax <= 0.0) {
114114
// Using 100 matches the UI expectation ("100% when present at least once").
115115
$qualifyMax = 100.0;
116116
}
117117

118+
if (!$requireUnique && $qualifyMax <= 0.0) {
119+
$sqlTotal = 'SELECT COUNT(*) AS total
120+
FROM '.$tbl_calendar.'
121+
WHERE attendance_id = '.(int) $attendanceId;
122+
$rowTotal = Database::fetch_assoc(Database::query($sqlTotal));
123+
$totalDates = (int) ($rowTotal['total'] ?? 0);
124+
125+
if ($totalDates > 0) {
126+
$qualifyMax = (float) $totalDates;
127+
}
128+
}
129+
118130
// ------------------------------------------------------------
119131
// Require-unique mode: 100% score if present at least once
120132
// This is calculated from attendance sheets to avoid relying on
@@ -130,8 +142,8 @@ public function calc_score(?int $studentId = null, ?string $type = null): array
130142
$sqlHasPresence = 'SELECT 1
131143
FROM '.$tbl_sheet.' s
132144
INNER JOIN '.$tbl_calendar.' c ON c.iid = s.attendance_calendar_id
133-
WHERE c.attendance_id = '.$attendanceId.'
134-
AND s.user_id = '.$studentId.'
145+
WHERE c.attendance_id = '.(int) $attendanceId.'
146+
AND s.user_id = '.(int) $studentId.'
135147
AND s.presence IN (1, 2, 3)
136148
LIMIT 1';
137149

@@ -156,7 +168,7 @@ public function calc_score(?int $studentId = null, ?string $type = null): array
156168
MAX(CASE WHEN s.presence IN (1, 2, 3) THEN 1 ELSE 0 END) AS has_presence
157169
FROM '.$tbl_sheet.' s
158170
INNER JOIN '.$tbl_calendar.' c ON c.iid = s.attendance_calendar_id
159-
WHERE c.attendance_id = '.$attendanceId.'
171+
WHERE c.attendance_id = '.(int) $attendanceId.'
160172
GROUP BY s.user_id';
161173

162174
$rs = Database::query($sqlAll);
@@ -173,7 +185,7 @@ public function calc_score(?int $studentId = null, ?string $type = null): array
173185

174186
// Compute stats (keep legacy behavior when qualifyMax is 0)
175187
foreach ($students as $uid => $finalScore) {
176-
if (0 != $qualifyMax) {
188+
if (0.0 != $qualifyMax) {
177189
$resultCount++;
178190
$sumRatio += $finalScore / $qualifyMax;
179191
$sumScore += $finalScore;
@@ -205,8 +217,8 @@ public function calc_score(?int $studentId = null, ?string $type = null): array
205217
}
206218

207219
$sql = 'SELECT user_id, score
208-
FROM '.$tbl_attendance_result.'
209-
WHERE attendance_id = '.$attendanceId;
220+
FROM '.$tbl_attendance_result.'
221+
WHERE attendance_id = '.(int) $attendanceId;
210222

211223
if (null !== $studentId) {
212224
$sql .= ' AND user_id = '.(int) $studentId;
@@ -219,7 +231,7 @@ public function calc_score(?int $studentId = null, ?string $type = null): array
219231
if ($row = Database::fetch_assoc($scores)) {
220232
$score = (float) ($row['score'] ?? 0);
221233
if ('default' === $type) {
222-
return [$qualifyMax > 0 ? ($score / $qualifyMax) : 0.0, 1];
234+
return [$qualifyMax > 0.0 ? ($score / $qualifyMax) : 0.0, 1];
223235
}
224236

225237
return [$score, $qualifyMax];
@@ -256,7 +268,7 @@ public function calc_score(?int $studentId = null, ?string $type = null): array
256268

257269
// Compute stats
258270
foreach ($students as $uid => $finalScore) {
259-
if (0 != $qualifyMax) {
271+
if (0.0 != $qualifyMax) {
260272
$resultCount++;
261273
$sumRatio += $finalScore / $qualifyMax;
262274
$sumScore += $finalScore;

src/CoreBundle/Entity/User.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1275,7 +1275,7 @@ public function getConfirmationToken(): ?string
12751275
return $this->confirmationToken;
12761276
}
12771277

1278-
public function setConfirmationToken(string $confirmationToken): self
1278+
public function setConfirmationToken(?string $confirmationToken): self
12791279
{
12801280
$this->confirmationToken = $confirmationToken;
12811281

src/CoreBundle/Resources/views/LearnPath/menubar.html.twig

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@
4242
>
4343
<i class="mdi-home mdi" aria-hidden="true"></i>
4444
</a>
45-
{{ navigation_bar }}
45+
<span data-lp-menu="nav">
46+
{{ navigation_bar }}
47+
</span>
4648
</div>
4749
<button title="{{ 'Options'|trans }}" class="menu-button icons" type="button" data-lp-menu="toggle">
4850
<i class="mdi-menu mdi" aria-hidden="true"></i>

0 commit comments

Comments
 (0)