Skip to content

Commit 13cf7c8

Browse files
Merge pull request #6221 from christianbeeznest/GH-3264
Exercise: Add email sending for reviewed attempts - refs #3264
2 parents 53d5401 + c2061d4 commit 13cf7c8

File tree

3 files changed

+124
-3
lines changed

3 files changed

+124
-3
lines changed

Diff for: public/main/exercise/exercise_report.php

+24-3
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,22 @@
123123

124124
header('Location: '.$urlExportPdf);
125125
exit;
126+
case 'send_email':
127+
$attemptId = (int) $_GET['attemptId'];
128+
ExerciseLib::sendExerciseResultByEmail($attemptId);
129+
Display::addFlash(Display::return_message(get_lang('Email content logged to error_log')));
130+
header('Location: '.api_get_self().'?'.api_get_cidreq().'&exerciseId='.$exercise_id);
131+
exit;
132+
case 'send_all_emails':
133+
$sessionId = api_get_session_id();
134+
$courseId = api_get_course_int_id();
135+
$attempts = ExerciseLib::getReviewedAttemptsInfo($exercise_id, $sessionId);
136+
foreach ($attempts as $attempt) {
137+
ExerciseLib::sendExerciseResultByEmail($attempt['exe_id']);
138+
}
139+
Display::addFlash(Display::return_message(get_lang('All emails sent successfully')));
140+
header('Location: '.api_get_self().'?'.api_get_cidreq().'&exerciseId='.$exercise_id);
141+
exit;
126142
}
127143

128144
if (!empty($_REQUEST['export_report']) && '1' == $_REQUEST['export_report']) {
@@ -470,6 +486,11 @@
470486
api_get_self().'?'.api_get_cidreq().'&action=export_all_results&exerciseId='.$exercise_id
471487
);
472488

489+
$actions .= Display::url(
490+
Display::getMdiIcon(ActionIcon::SEND_ALL_EMAILS, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Send all by email')),
491+
api_get_self().'?'.api_get_cidreq().'&action=send_all_emails&exerciseId='.$exercise_id
492+
);
493+
473494
// clean result before a selected date icon
474495
if ($allowClean) {
475496
$actions .= Display::url(
@@ -731,7 +752,7 @@
731752
//for the top bar
732753
'editoptions' => ['value' => $group_parameters],
733754
],
734-
['name' => 'duration', 'index' => 'exe_duration', 'width' => '150', 'align' => 'left', 'search' => 'true'],
755+
['name' => 'duration', 'index' => 'exe_duration', 'width' => '80', 'align' => 'left', 'search' => 'true'],
735756
['name' => 'start_date', 'index' => 'start_date', 'width' => '150', 'align' => 'left', 'search' => 'true'],
736757
['name' => 'exe_date', 'index' => 'exe_date', 'width' => '150', 'align' => 'left', 'search' => 'true'],
737758
['name' => 'score', 'index' => 'score', 'width' => '120', 'align' => 'center', 'search' => 'true'],
@@ -755,8 +776,8 @@
755776
),
756777
],
757778
],
758-
['name' => 'lp', 'index' => 'orig_lp_id', 'width' => '150', 'align' => 'left', 'search' => 'false'],
759-
['name' => 'actions', 'index' => 'actions', 'width' => '180', 'align' => 'left', 'search' => 'false', 'sortable' => 'false'],
779+
['name' => 'lp', 'index' => 'orig_lp_id', 'width' => '130', 'align' => 'left', 'search' => 'false'],
780+
['name' => 'actions', 'index' => 'actions', 'width' => '240', 'align' => 'left', 'search' => 'false', 'sortable' => 'false'],
760781
];
761782

762783
if ('true' === $officialCodeInList) {

Diff for: public/main/inc/lib/exercise.lib.php

+96
Original file line numberDiff line numberDiff line change
@@ -2357,6 +2357,10 @@ public static function get_exam_results_data(
23572357
.Display::getMdiIcon(ActionIcon::EXPORT_PDF, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Export to PDF'))
23582358
.'</a>';
23592359

2360+
$sendMailUrl = api_get_path(WEB_CODE_PATH).'exercise/exercise_report.php?'.api_get_cidreq().'&action=send_email&exerciseId='.$exercise_id.'&attemptId='.$results[$i]['exe_id'];
2361+
$emailLink = '<a href="'.$sendMailUrl.'">'
2362+
.Display::getMdiIcon(ActionIcon::SEND_SINGLE_EMAIL, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Send by email'))
2363+
.'</a>';
23602364

23612365
$filterByUser = isset($_GET['filter_by_user']) ? (int) $_GET['filter_by_user'] : 0;
23622366
$delete_link = '<a
@@ -2375,7 +2379,11 @@ public static function get_exam_results_data(
23752379
if (3 == $revised) {
23762380
$delete_link = null;
23772381
}
2382+
if (1 !== $revised) {
2383+
$emailLink = '';
2384+
}
23782385
$actions .= $delete_link;
2386+
$actions .= $emailLink;
23792387
}
23802388
} else {
23812389
$attempt_url = api_get_path(WEB_CODE_PATH).'exercise/result.php?'.api_get_cidreq().'&id='.$results[$i]['exe_id'].'&sid='.$sessionId;
@@ -2581,6 +2589,94 @@ public static function get_exam_results_data(
25812589
return $listInfo;
25822590
}
25832591

2592+
/**
2593+
* Returns email content for a specific attempt.
2594+
*/
2595+
public static function getEmailContentForAttempt(int $attemptId): array
2596+
{
2597+
$trackExerciseInfo = self::get_exercise_track_exercise_info($attemptId);
2598+
2599+
if (empty($trackExerciseInfo)) {
2600+
return [
2601+
'to' => '',
2602+
'subject' => 'No exercise info found',
2603+
'message' => 'Attempt ID not found or invalid.',
2604+
];
2605+
}
2606+
2607+
$studentId = $trackExerciseInfo['exe_user_id'];
2608+
$courseInfo = api_get_course_info();
2609+
$teacherId = api_get_user_id();
2610+
2611+
if (
2612+
empty($trackExerciseInfo['orig_lp_id']) ||
2613+
empty($trackExerciseInfo['orig_lp_item_id'])
2614+
) {
2615+
$url = api_get_path(WEB_CODE_PATH).'exercise/result.php?id='.$trackExerciseInfo['exe_id'].'&'.api_get_cidreq()
2616+
.'&show_headers=1&id_session='.api_get_session_id();
2617+
} else {
2618+
$url = api_get_path(WEB_CODE_PATH).'lp/lp_controller.php?action=view&item_id='
2619+
.$trackExerciseInfo['orig_lp_item_id'].'&lp_id='.$trackExerciseInfo['orig_lp_id'].'&'.api_get_cidreq()
2620+
.'&id_session='.api_get_session_id();
2621+
}
2622+
2623+
$message = self::getEmailNotification(
2624+
$teacherId,
2625+
$courseInfo,
2626+
$trackExerciseInfo['title'],
2627+
$url
2628+
);
2629+
2630+
return [
2631+
'to' => $studentId,
2632+
'subject' => get_lang('Corrected test result'),
2633+
'message' => $message,
2634+
];
2635+
}
2636+
2637+
/**
2638+
* Sends the exercise result email to the student.
2639+
*/
2640+
public static function sendExerciseResultByEmail(int $attemptId): void
2641+
{
2642+
$content = self::getEmailContentForAttempt($attemptId);
2643+
2644+
if (empty($content['to'])) {
2645+
return;
2646+
}
2647+
2648+
MessageManager::send_message_simple(
2649+
$content['to'],
2650+
$content['subject'],
2651+
$content['message'],
2652+
api_get_user_id()
2653+
);
2654+
}
2655+
2656+
/**
2657+
* Returns all reviewed attempts for a given exercise and session.
2658+
*/
2659+
public static function getReviewedAttemptsInfo(int $exerciseId, int $sessionId): array
2660+
{
2661+
$courseId = api_get_course_int_id();
2662+
$trackTable = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
2663+
$qualifyTable = Database::get_main_table(TABLE_STATISTIC_TRACK_E_ATTEMPT_QUALIFY);
2664+
2665+
$sessionCondition = api_get_session_condition($sessionId, true, false, 't.session_id');
2666+
2667+
$sql = "
2668+
SELECT DISTINCT t.exe_id
2669+
FROM $trackTable t
2670+
INNER JOIN $qualifyTable q ON (t.exe_id = q.exe_id AND q.author > 0)
2671+
WHERE
2672+
t.c_id = $courseId AND
2673+
t.exe_exo_id = $exerciseId
2674+
$sessionCondition
2675+
";
2676+
2677+
return Database::store_result(Database::query($sql));
2678+
}
2679+
25842680
/**
25852681
* @param $score
25862682
* @param $weight

Diff for: src/CoreBundle/Component/Utils/ActionIcon.php

+4
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ enum ActionIcon: string
104104
case SAVE_FORM = 'content-save';
105105
// Send a message
106106
case SEND_MESSAGE = 'send';
107+
// Send all examsheets by email
108+
case SEND_ALL_EMAILS = 'email-multiple';
109+
// Send a single examsheet by email
110+
case SEND_SINGLE_EMAIL = 'email-outline';
107111
// Add an attachment
108112
case ADD_ATTACHMENT = 'paperclip-plus';
109113
// ? See RESTORE_BACKUP

0 commit comments

Comments
 (0)