Exercise: Add option to export results attempts in zip - refs BT#20691

pull/4694/head
Christian 3 years ago
parent 3957b5933b
commit 67ff7589a5
  1. 170
      main/admin/export_exercise_results.php
  2. 5
      main/admin/index.php
  3. 28
      main/exercise/exercise.class.php
  4. 15
      main/exercise/exercise_report.php
  5. 39
      main/exercise/exercise_show.php
  6. 72
      main/inc/lib/exercise.lib.php
  7. 8
      main/inc/lib/pdf.lib.php

@ -0,0 +1,170 @@
<?php
/* For licensing terms, see /license.txt */
$cidReset = true;
require_once __DIR__.'/../inc/global.inc.php';
// Setting the section (for the tabs).
$this_section = SECTION_PLATFORM_ADMIN;
api_protect_admin_script(true);
$sessionId = isset($_REQUEST['session_id']) ? (int) $_REQUEST['session_id'] : null;
$courseId = isset($_GET['selected_course']) ? (int) $_GET['selected_course'] : null;
$exerciseId = isset($_REQUEST['exerciseId']) ? (int) $_REQUEST['exerciseId'] : null;
$courseIdChanged = isset($_GET['course_id_changed']) ? (int) $_GET['course_id_changed'] : null;
$exerciseIdChanged = isset($_GET['exercise_id_changed']) ? (int) $_GET['exercise_id_changed'] : null;
// Get the session list
$sessionList = SessionManager::get_sessions_by_user(api_get_user_id(), api_is_platform_admin());
// Course list, get course list of session, or for course where user is admin
$courseList = [];
if (!empty($sessionId) && $sessionId != '-1' && !empty($sessionList)) {
$sessionInfo = [];
foreach ($sessionList as $session) {
if ($session['session_id'] == $sessionId) {
$sessionInfo = $session;
}
}
$courseList = $sessionInfo['courses'];
} else {
if (api_is_platform_admin()) {
$courseList = CourseManager::get_courses_list(0, 0, 'title');
} else {
$courseList = CourseManager::get_course_list_of_user_as_course_admin(api_get_user_id());
}
}
$courseInfo = [];
if (empty($courseId)) {
$exerciseId = 0;
} else {
$courseInfo = api_get_course_info_by_id($courseId);
}
$interbreadcrumb[] = ['url' => 'index.php', 'name' => get_lang('PlatformAdmin')];
$confirmYourChoice = addslashes(get_lang('ConfirmYourChoice'));
$htmlHeadXtra[] = "
<script>
function submit_form(obj) {
document.export_all_results_form.submit();
}
function mark_course_id_changed() {
$('#course_id_changed').val('0');
}
function mark_exercise_id_changed() {
$('#exercise_id_changed').val('0');
}
function confirm_your_choice() {
return confirm('$confirmYourChoice');
}
</script>";
$sessionSelectList = [0 => get_lang('Select')];
foreach ($sessionList as $item) {
$sessionSelectList[$item['session_id']] = $item['session_name'];
}
$courseSelectList = [0 => get_lang('Select')];
foreach ($courseList as $item) {
$courseItemId = $item['real_id'];
$courseInfo = api_get_course_info_by_id($courseItemId);
$courseSelectList[$courseItemId] = '';
if ($courseItemId == $courseId) {
$courseSelectList[$courseItemId] = '>&nbsp;&nbsp;&nbsp;&nbsp;';
}
$courseSelectList[$courseItemId] = $courseInfo['title'];
}
// If course has changed, reset the menu default
if (!empty($courseSelectList) && !in_array($courseId, array_keys($courseSelectList))) {
$courseId = 0;
}
$courseInfo = api_get_course_info_by_id($courseId);
// Get exercise list for this course
$exerciseList = ExerciseLib::get_all_exercises_for_course_id(
$courseInfo,
$sessionId,
$courseId,
false
);
$exerciseSelectList = [];
$exerciseSelectList = [0 => get_lang('Select')];
if (is_array($exerciseList)) {
foreach ($exerciseList as $row) {
$exerciseTitle = $row['title'];
$exerciseSelectList[$row['iid']] = $exerciseTitle;
}
}
$url = api_get_self().'?'.api_get_cidreq().'&'.http_build_query(
[
'session_id' => $sessionId,
'selected_course' => $courseId,
'exerciseId' => $exerciseId,
'course_id_changed' => $courseIdChanged,
'exercise_id_changed' => $exerciseIdChanged,
]
);
// Form
$form = new FormValidator('export_all_results_form', 'GET', $url);
$form->addHeader(get_lang('ExportExerciseAllResults'));
$form
->addSelect(
'session_id',
get_lang('Session'),
$sessionSelectList,
['onchange' => 'submit_form(this)', 'id' => 'session_id']
)
->setSelected($sessionId);
$form
->addSelect(
'selected_course',
get_lang('Course'),
$courseSelectList,
['onchange' => 'mark_course_id_changed(); submit_form(this);', 'id' => 'selected_course']
)
->setSelected($courseId);
$form
->addSelect(
'exerciseId',
get_lang('Exercise'),
$exerciseSelectList
)
->setSelected($exerciseId);
$form->addHidden('course_id_changed', '0');
$form->addHidden('exercise_id_changed', '0');
$form->addButtonExport(get_lang('Export'), 'name');
if ($form->validate()) {
$values = $form->getSubmitValues();
if (!empty($values['exerciseId']) && !empty($values['selected_course'])) {
$sessionId = (int) $values['session_id'];
$courseId = (int) $values['selected_course'];
$exerciseId = (int) $values['exerciseId'];
ExerciseLib::exportExerciseAllResultsZip($sessionId, $courseId, $exerciseId);
}
}
Display::display_header(get_lang('ExportExerciseAllResults'));
echo Display::return_message(
get_lang('ThisProcessCantakeALongTime'),
'normal',
false,
);
echo $form->display();
Display::display_footer();

@ -623,6 +623,11 @@ if (api_is_platform_admin() || ($allowCareer && api_is_session_admin())) {
'url' => 'resource_sequence.php',
'label' => get_lang('ResourcesSequencing'),
];
$items[] = [
'class' => 'item-export-exercise-results',
'url' => 'export_exercise_results.php',
'label' => get_lang('ExportExerciseAllResults'),
];
}
$blocks['sessions']['items'] = $items;

@ -8426,7 +8426,7 @@ class Exercise
*
* @return array exercises
*/
public function getExerciseAndResult($courseId, $sessionId, $quizId = [])
public function getExerciseAndResult($courseId, $sessionId, $quizId = [], $status = null)
{
if (empty($quizId)) {
return [];
@ -8439,22 +8439,30 @@ class Exercise
$ids = array_map('intval', $ids);
$ids = implode(',', $ids);
$track_exercises = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
$condition = '';
if (isset($status)) {
$condition .= " AND te.status = '$status' ";
}
if (0 != $sessionId) {
$sql = "SELECT * FROM $track_exercises te
INNER JOIN c_quiz cq ON cq.iid = te.exe_exo_id
WHERE
te.id = %s AND
te.session_id = %s AND
cq.iid IN (%s)
INNER JOIN c_quiz cq ON cq.iid = te.exe_exo_id
WHERE
te.c_id = %s AND
te.session_id = %s AND
cq.iid IN (%s)
$condition
ORDER BY cq.iid";
$sql = sprintf($sql, $courseId, $sessionId, $ids);
} else {
$sql = "SELECT * FROM $track_exercises te
INNER JOIN c_quiz cq ON cq.iid = te.exe_exo_id
WHERE
te.id = %s AND
cq.iid IN (%s)
INNER JOIN c_quiz cq ON cq.iid = te.exe_exo_id
WHERE
te.c_id = %s AND
cq.iid IN (%s)
$condition
ORDER BY cq.iid";
$sql = sprintf($sql, $courseId, $ids);
}

@ -149,6 +149,16 @@ if (!empty($_REQUEST['export_report']) && $_REQUEST['export_report'] == '1') {
$objExerciseTmp = new Exercise();
$exerciseExists = $objExerciseTmp->read($exercise_id);
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : null;
switch ($action) {
case 'export_all_results':
$sessionId = api_get_session_id();
$courseId = api_get_course_int_id();
ExerciseLib::exportExerciseAllResultsZip($sessionId, $courseId, $exercise_id);
break;
}
//Send student email @todo move this code in a class, library
if (isset($_REQUEST['comments']) &&
$_REQUEST['comments'] === 'update' &&
@ -438,6 +448,11 @@ if ($is_allowedToEdit && $origin !== 'learnpath') {
api_get_path(WEB_CODE_PATH).'exercise/recalculate_all.php?'.api_get_cidreq()."&exercise=$exercise_id"
);
$actions .= Display::url(
Display::return_icon('export_pdf.png', get_lang('ExportExerciseAllResults'), [], ICON_SIZE_MEDIUM),
api_get_self().'?'.api_get_cidreq().'&action=export_all_results&exerciseId='.$exercise_id
);
// clean result before a selected date icon
if ($allowClean) {
$actions .= Display::url(

@ -20,6 +20,7 @@ $origin = api_get_origin();
$currentUserId = api_get_user_id();
$printHeaders = 'learnpath' === $origin;
$id = isset($_REQUEST['id']) ? (int) $_REQUEST['id'] : 0; //exe id
$exportTypeAllResults = ('export' === $_GET['action'] && 'all_results' === $_GET['export_type']);
if (empty($id)) {
api_not_allowed(true);
@ -38,15 +39,17 @@ $learnpath_id = $track_exercise_info['orig_lp_id'];
$learnpath_item_id = $track_exercise_info['orig_lp_item_id'];
$lp_item_view_id = $track_exercise_info['orig_lp_item_view_id'];
$isBossOfStudent = false;
if (api_is_student_boss()) {
// Check if boss has access to user info.
if (UserManager::userIsBossOfStudent($currentUserId, $student_id)) {
$isBossOfStudent = true;
if (!$exportTypeAllResults) {
if (api_is_student_boss()) {
// Check if boss has access to user info.
if (UserManager::userIsBossOfStudent($currentUserId, $student_id)) {
$isBossOfStudent = true;
} else {
api_not_allowed($printHeaders);
}
} else {
api_not_allowed($printHeaders);
api_protect_course_script($printHeaders, false, true);
}
} else {
api_protect_course_script($printHeaders, false, true);
}
// Database table definitions
@ -93,7 +96,8 @@ $is_allowedToEdit =
api_is_course_tutor() ||
api_is_session_admin() ||
api_is_drh() ||
api_is_student_boss();
api_is_student_boss() ||
$exportTypeAllResults;
if (!empty($sessionId) && !$is_allowedToEdit) {
if (api_is_course_session_coach(
@ -982,7 +986,24 @@ if ('export' === $action) {
'orientation' => 'P',
];
$pdf = new PDF('A4', $params['orientation'], $params);
$pdf->html_to_pdf_with_template($content, false, false, true);
if ('all_results' === $_GET['export_type']) {
$sessionId = api_get_session_id();
$courseId = api_get_course_int_id();
$exportName = 'S'.$sessionId.'-C'.$courseId.'-T'.$exercise_id;
$baseDir = api_get_path(SYS_ARCHIVE_PATH);
$folderName = 'pdfexport-'.$exportName;
$exportFolderPath = $baseDir.$folderName;
if (!is_dir($exportFolderPath)) {
@mkdir($exportFolderPath);
}
$pdfFileName = $user_info['firstname'].' '.$user_info['lastname'].'-attemptId'.$id.'.pdf';
$pdfFileName = api_replace_dangerous_char($pdfFileName);
$fileNameToSave = $exportFolderPath.'/'.$pdfFileName;
$pdf->html_to_pdf_with_template($content, true, false, true, [], 'F', $fileNameToSave);
} else {
$pdf->html_to_pdf_with_template($content, false, false, true);
}
exit;
}

@ -7150,4 +7150,76 @@ EOT;
error_log("Exercise ping received: exe_id = $exeId. _user not found in session.");
}
public static function saveFileExerciseResultPdf(
int $exeId,
int $courseId,
int $sessionId
) {
$cinfo = api_get_course_info_by_id($courseId);
$courseCode = $cinfo['code'];
$cidReq = 'cidReq='.$courseCode.'&id_session='.$sessionId.'&gidReq=0&gradebook=0';
$url = api_get_path(WEB_PATH).'main/exercise/exercise_show.php?'.$cidReq.'&id='.$exeId.'&action=export&export_type=all_results';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_COOKIE, session_id());
curl_setopt($ch, CURLOPT_AUTOREFERER, true);
curl_setopt($ch, CURLOPT_COOKIESESSION, true);
curl_setopt($ch, CURLOPT_FAILONERROR, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
curl_close($ch);
}
public static function exportExerciseAllResultsZip(
int $sessionId,
int $courseId,
int $exerciseId
) {
$objExerciseTmp = new Exercise($courseId);
$exeResults = $objExerciseTmp->getExerciseAndResult(
$courseId,
$sessionId,
$exerciseId,
''
);
if (!empty($exeResults)) {
$exportName = 'S'.$sessionId.'-C'.$courseId.'-T'.$exerciseId;
$baseDir = api_get_path(SYS_ARCHIVE_PATH);
$folderName = 'pdfexport-'.$exportName;
$exportFolderPath = $baseDir.$folderName;
// 1. Cleans the export folder if it exists.
if (is_dir($exportFolderPath)) {
rmdirr($exportFolderPath);
}
// 2. Create the pdfs inside a new export folder path.
if (!empty($exeResults)) {
foreach ($exeResults as $exeResult) {
$exeId = (int) $exeResult['exe_id'];
ExerciseLib::saveFileExerciseResultPdf($exeId, $courseId, $sessionId);
}
}
// 3. If export folder is not empty will be zipped.
$isFolderPathEmpty = (file_exists($exportFolderPath) && 2 == count(scandir($exportFolderPath)));
if (!$isFolderPathEmpty) {
$exportFilePath = $baseDir.$exportName.'.zip';
$zip = new \PclZip($exportFilePath);
$zip->create($exportFolderPath, PCLZIP_OPT_REMOVE_PATH, $exportFolderPath);
rmdirr($exportFolderPath);
DocumentManager::file_send_for_download($exportFilePath, true, $exportName.'.zip');
exit;
}
}
return false;
}
}

@ -109,7 +109,9 @@ class PDF
$saveToFile = false,
$returnHtml = false,
$addDefaultCss = false,
$extraRows = []
$extraRows = [],
$outputMode = 'D',
$fileToSave = null
) {
if (empty($this->template)) {
$tpl = new Template('', false, false, false, false, true, false);
@ -173,9 +175,9 @@ class PDF
$css,
$this->params['filename'],
$this->params['course_code'],
'D',
$outputMode,
$saveToFile,
null,
$fileToSave,
$returnHtml,
$addDefaultCss
);

Loading…
Cancel
Save