public/main/my_space/session.php
<?php
/* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Component\Utils\ActionIcon;
use Chamilo\CoreBundle\Component\Utils\ToolIcon;
use Chamilo\CoreBundle\Component\Utils\ObjectIcon;
use Chamilo\CoreBundle\Entity\Course;
ob_start();
$cidReset = true;
require_once __DIR__.'/../inc/global.inc.php';
api_block_anonymous_users();
$this_section = SECTION_TRACKING;
$export_csv = false;
if (isset($_REQUEST['export']) && 'csv' == $_REQUEST['export']) {
$export_csv = true;
}
$action = isset($_GET['action']) ? $_GET['action'] : '';
$id_coach = api_get_user_id();
if (isset($_REQUEST['id_coach']) && '' != $_REQUEST['id_coach']) {
$id_coach = (int) $_REQUEST['id_coach'];
}
$allowToTrack = api_is_platform_admin(true, true) || api_is_teacher();
if (!$allowToTrack) {
api_not_allowed(true);
}
$studentId = isset($_GET['student']) ? (int) $_GET['student'] : 0;
$sessionId = isset($_GET['sid']) ? (int) $_GET['sid'] : 0;
$currentUrl = api_get_self().'?student='.$studentId.'&sid='.$sessionId;
switch ($action) {
case 'export_to_pdf':
$allStudents = isset($_GET['all_students']) && 1 === (int) $_GET['all_students'] ? true : false;
$sessionToExport = isset($_GET['session_to_export']) ? (int) $_GET['session_to_export'] : 0;
$sessionEntity = $sessionToExport ? api_get_session_entity($sessionToExport) : null;
$type = isset($_GET['type']) ? $_GET['type'] : 'attendance';
if (empty($sessionEntity)) {
api_not_allowed(true);
}
$courses = Tracking::get_courses_list_from_session($sessionToExport);
/** @var array<int, Course> $courseEntityList */
$courseEntityList = array_map(fn(array $courseInfo) => api_get_course_entity($courseInfo['c_id']), $courses);
$studentList = [$studentId];
if ($allStudents) {
$users = SessionManager::get_users_by_session($sessionToExport, 0);
$studentList = array_column($users, 'user_id');
}
$totalCourses = count($courses);
$scoreDisplay = ScoreDisplay::instance();
$table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
$pdfList = [];
foreach ($studentList as $studentId) {
$studentInfo = api_get_user_info($studentId);
$timeSpent = 0;
$numberVisits = 0;
$progress = 0;
$timeSpentPerCourse = [];
$progressPerCourse = [];
foreach ($courseEntityList as $course) {
$courseTimeSpent = Tracking::get_time_spent_on_the_course($studentId, $course->getId(), $sessionToExport);
$timeSpentPerCourse[$course->getId()] = $courseTimeSpent;
$timeSpent += $courseTimeSpent;
$sql = "SELECT DISTINCT count(course_access_id) as count
FROM $table
WHERE
c_id = {$course->getId()} AND
session_id = $sessionToExport AND
user_id = $studentId";
$result = Database::query($sql);
$row = Database::fetch_array($result);
$numberVisits += $row['count'];
$courseProgress = Tracking::get_avg_student_progress(
$studentId,
$course,
[],
$sessionEntity
);
$progressPerCourse[$course->getId()] = $courseProgress;
$progress += $courseProgress;
}
$average = round($progress / $totalCourses, 1);
$average = empty($average) ? '0%' : $average.'%';
$first = Tracking::get_first_connection_date($studentId);
$last = Tracking::get_last_connection_date($studentId);
$timeSpentContent = '';
$pdfTitle = get_lang('AttestationOfAttendance');
if ('attendance' === $type) {
$table = new HTML_Table(['class' => 'table table-hover table-striped data_table']);
$column = 0;
$row = 0;
$headers = [
get_lang('Time spent'),
get_lang('Number of visits'),
get_lang('Global progress'),
get_lang('First connection'),
get_lang('Last connexion date'),
];
foreach ($headers as $header) {
$table->setHeaderContents($row, $column, $header);
$column++;
}
$table->setCellContents(1, 0, api_time_to_hms($timeSpent));
$table->setCellContents(1, 1, $numberVisits);
$table->setCellContents(1, 2, $average);
$table->setCellContents(1, 3, $first);
$table->setCellContents(1, 4, $last);
$timeSpentContent = $table->toHtml();
} else {
$pdfTitle = get_lang('Certificate of achievement');
}
$courseTable = '';
if (!empty($courses)) {
$courseTable .= '<table class="table table-hover table-striped data_table">';
$courseTable .= '<thead>';
$courseTable .= '<tr>
<th>'.get_lang('Formation unit').'</th>
<th>'.get_lang('Connection time').'</th>
<th>'.get_lang('Progress').'</th>';
if ('attendance' === $type) {
$courseTable .= '<th>'.get_lang('Score').'</th>';
}
$courseTable .= '</tr>';
$courseTable .= '</thead>';
$courseTable .= '<tbody>';
$totalCourseTime = 0;
$totalAttendance = [0, 0];
$totalScore = 0;
$totalProgress = 0;
$gradeBookTotal = [0, 0];
$totalEvaluations = '0/0 (0%)';
foreach ($courseEntityList as $course) {
$courseInfoItem = api_get_course_info_by_id($course->getId());
$courseCodeItem = $courseInfoItem['code'];
$isSubscribed = CourseManager::is_user_subscribed_in_course(
$studentId,
$courseCodeItem,
true,
$sessionToExport
);
if ($isSubscribed) {
$timeInSeconds = $timeSpentPerCourse[$course->getId()];
$totalCourseTime += $timeInSeconds;
$time_spent_on_course = api_time_to_hms($timeInSeconds);
$progress = $progressPerCourse[$course->getId()];
$totalProgress += $progress;
$bestScore = Tracking::get_avg_student_score(
$studentId,
$course,
[],
$sessionEntity,
false,
false,
true
);
if (is_numeric($bestScore)) {
$totalScore += $bestScore;
}
$progress = empty($progress) ? '0%' : $progress.'%';
$score = empty($bestScore) ? '0%' : $bestScore.'%';
$courseTable .= '<tr>
<td>
<a href="'.$courseInfoItem['course_public_url'].'?id_session='.$sessionToExport.'">'.
$courseInfoItem['title'].'</a>
</td>
<td >'.$time_spent_on_course.'</td>
<td >'.$progress.'</td>';
if ('attendance' === $type) {
$courseTable .= '<td >'.$score.'</td>';
}
$courseTable .= '</tr>';
}
}
$totalAttendanceFormatted = $scoreDisplay->display_score($totalAttendance);
$totalScoreFormatted = $scoreDisplay->display_score([$totalScore / $totalCourses, 100], SCORE_AVERAGE);
$totalProgressFormatted = $scoreDisplay->display_score(
[$totalProgress / $totalCourses, 100],
SCORE_AVERAGE
);
$totalEvaluations = $scoreDisplay->display_score($gradeBookTotal);
$totalTimeFormatted = api_time_to_hms($totalCourseTime);
$courseTable .= '
<tr>
<th>'.get_lang('Total').'</th>
<th>'.$totalTimeFormatted.'</th>
<th>'.$totalProgressFormatted.'</th>
';
if ('attendance' === $type) {
$courseTable .= '<th>'.$totalScoreFormatted.'</th>';
}
$courseTable .= '</tr>';
$courseTable .= '</tbody></table>';
}
$tpl = new Template('', false, false, false, true, false, false);
$tpl->assign('title', $pdfTitle);
$tpl->assign('session_title', $sessionEntity->getTitle());
$tpl->assign('session_info', $sessionEntity);
$sessionCategoryTitle = '';
if ($sessionEntity->getCategory()) {
$sessionCategoryTitle = $sessionEntity->getCategory()->getTitle();
}
$dateData = SessionManager::parseSessionDates($sessionEntity, false);
$dateToString = $dateData['access'];
$tpl->assign('session_display_dates', $dateToString);
$tpl->assign('session_category_title', $sessionCategoryTitle);
$tpl->assign('student', $studentInfo['complete_name']);
$tpl->assign('student_info', $studentInfo);
$tpl->assign('student_info_extra_fields', UserManager::get_extra_user_data($studentInfo['user_id']));
$tpl->assign('table_progress', $timeSpentContent);
$tpl->assign(
'subtitle',
sprintf(
get_lang('InSessionXYouHadTheFollowingResults'),
$sessionEntity->getTitle()
)
);
$tpl->assign('table_course', $courseTable);
$template = 'pdf_export_student.tpl';
if ('achievement' === $type) {
$template = 'certificate_achievement.tpl';
}
$content = $tpl->fetch($tpl->get_template('my_space/'.$template));
$params = [
'pdf_title' => get_lang('Resume'),
'session_info' => $sessionEntity,
'course_info' => '',
'pdf_date' => '',
'student_info' => $studentInfo,
'show_grade_generated_date' => true,
'show_real_course_teachers' => false,
'show_teacher_as_myself' => false,
'orientation' => 'P',
];
@$pdf = new PDF('A4', $params['orientation'], $params);
$pdf->setBackground($tpl->theme);
$mode = 'D';
$pdfName = $sessionEntity->getTitle().'_'.$studentInfo['complete_name'];
if ($allStudents) {
$mode = 'F';
$pdfName = $studentInfo['complete_name'];
}
$pdf->set_footer();
$result = @$pdf->content_to_pdf(
$content,
null,
$pdfName,
null,
$mode,
false,
null,
false,
true,
false
);
$pdfList[] = $result;
}
if (empty($pdfList)) {
api_not_allowed(true);
}
// Creating a ZIP file.
$tempZipFile = api_get_path(SYS_ARCHIVE_PATH).uniqid('report_session_'.$sessionToExport, true).'.zip';
$zip = new PclZip($tempZipFile);
foreach ($pdfList as $file) {
$zip->add(
$file,
PCLZIP_OPT_REMOVE_PATH,
api_get_path(SYS_ARCHIVE_PATH)
);
}
$name = $sessionEntity->getTitle().'_'.api_get_utc_datetime().'.zip';
DocumentManager::file_send_for_download($tempZipFile, true, $name);
exit;
break;
}
$htmlHeadXtra[] = api_get_jqgrid_js();
$interbreadcrumb[] = ['url' => 'index.php', 'name' => get_lang('Reporting')];
Display::display_header(get_lang('Course sessions'));
if (api_is_platform_admin(true, true)) {
$a_sessions = SessionManager::get_sessions_followed_by_drh(api_get_user_id());
if (!api_is_session_admin()) {
$menu_items[] = Display::url(
Display::getMdiIcon(ToolIcon::TRACKING, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('View my progress')),
api_get_path(WEB_CODE_PATH).'auth/my_progress.php'
);
$menu_items[] = Display::url(
Display::getMdiIcon(ObjectIcon::USER, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Learners')),
'index.php?view=drh_students&display=yourstudents'
);
$menu_items[] = Display::url(
Display::getMdiIcon(ObjectIcon::TEACHER, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Teachers')),
'teachers.php'
);
$menu_items[] = Display::url(
Display::getMdiIcon(ObjectIcon::COURSE, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Courses')),
'course.php'
);
$menu_items[] = Display::url(
Display::getMdiIcon(ObjectIcon::SESSION, 'ch-tool-icon-disabled', null, ICON_SIZE_MEDIUM, get_lang('Course sessions')),
'#'
);
} else {
$menu_items[] = Display::url(
Display::getMdiIcon(ObjectIcon::TEACHER, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Trainers')),
'session_admin_teachers.php'
);
}
$menu_items[] = Display::url(
Display::getMdiIcon(ObjectIcon::ASSIGNMENT, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Assignments report')),
api_get_path(WEB_CODE_PATH).'my_space/works_in_session_report.php'
);
$menu_items[] = Display::url(
Display::getMdiIcon(ObjectIcon::TIME_REPORT, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Teachers time report by session')),
api_get_path(WEB_CODE_PATH).'admin/teachers_time_by_session_report.php'
);
if (!api_is_session_admin()) {
$menu_items[] = Display::url(
Display::getMdiIcon(ObjectIcon::SURVEY_DOODLE, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Course sessionsPlanCalendar')),
api_get_path(WEB_CODE_PATH)."calendar/planification.php"
);
}
if (api_is_drh()) {
$menu_items[] = Display::url(
Display::getMdiIcon(ObjectIcon::SESSION, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('SessionFilterReport')),
api_get_path(WEB_CODE_PATH).'my_space/session_filter.php'
);
}
$actionsLeft = '';
$nb_menu_items = count($menu_items);
if ($nb_menu_items > 1) {
foreach ($menu_items as $key => $item) {
$actionsLeft .= $item;
}
}
$actionsRight = '';
if (count($a_sessions) > 0) {
$actionsRight = Display::url(
Display::getMdiIcon(ActionIcon::PRINT, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Print')),
'javascript: void(0);',
['onclick' => 'javascript: window.print();']
);
$actionsRight .= Display::url(
Display::getMdiIcon(ActionIcon::EXPORT_CSV, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('CSV export')),
api_get_self().'?export=csv'
);
}
$toolbar = Display::toolbarAction('toolbar-session', [$actionsLeft, $actionsRight]);
echo $toolbar;
echo Display::page_header(get_lang('Your sessions'));
} elseif (api_is_teacher()) {
$actionsRight = Display::url(
Display::getMdiIcon(ObjectIcon::TIME_REPORT, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Teachers time report by session')),
api_get_path(WEB_CODE_PATH).'admin/teachers_time_by_session_report.php'
);
$toolbar = Display::toolbarAction('toolbar-session', ['', $actionsRight]);
echo $toolbar;
echo Display::page_header(get_lang('Your sessions'));
} else {
$a_sessions = Tracking::get_sessions_coached_by_user($id_coach);
}
$form = new FormValidator(
'search_course',
'post',
api_get_path(WEB_CODE_PATH).'my_space/session.php'
);
$form->addElement('text', 'keyword', get_lang('Keyword'));
$extraFieldSession = new ExtraField('session');
$extraFieldSession->addElements(
$form,
null,
[], //exclude
true
);
$form->addButtonSearch(get_lang('Search'));
$keyword = '';
$result = SessionManager::getGridColumns('my_space');
$columns = $result['columns'];
$columnModel = $result['column_model'];
$filterToString = '';
if ($form->validate()) {
$values = $form->getSubmitValues();
$keyword = Security::remove_XSS($form->getSubmitValue('keyword'));
$extraField = new ExtraField('session');
$extraFields = $extraField->get_all(null, 'option_order');
$extraFields = array_column($extraFields, 'variable');
$filter = new stdClass();
foreach ($columnModel as $col) {
if (isset($values[$col['index']]) && !empty($values[$col['index']]) &&
in_array(str_replace('extra_', '', $col['index']), $extraFields)
) {
$rule = new stdClass();
$index = $col['index'];
$rule->field = $index;
$rule->op = 'in';
$data = $values[$index];
if (is_array($data) && array_key_exists($index, $data)) {
$data = $data[$index];
}
$rule->data = Security::remove_XSS($data);
$filter->rules[] = $rule;
$filter->groupOp = 'AND';
}
}
$filterToString = json_encode($filter);
}
$form->setDefaults(['keyword' => $keyword]);
$url = api_get_path(WEB_AJAX_PATH).
'model.ajax.php?a=get_sessions_tracking&_search=true&_force_search=true&filters='.$filterToString.'&keyword='.$keyword;
// Column config
$extraParams = [
'autowidth' => 'true',
'height' => 'auto',
];
/*$extraParams['postData'] = [
'filters' => [
'groupOp' => 'AND',
'rules' => $result['rules'],
],
];*/
$urlAjaxExtraField = api_get_path(WEB_AJAX_PATH).'extra_field.ajax.php?1=1';
$orderUrl = api_get_path(WEB_AJAX_PATH).'session.ajax.php?a=order';
?>
<script>
function setSearchSelect(columnName) {
$("#sessions").jqGrid('setColProp', columnName, {
});
}
var added_cols = [];
var original_cols = [];
function clean_cols(grid, added_cols) {
// Cleaning
for (key in added_cols) {
grid.hideCol(key);
}
grid.showCol('name');
grid.showCol('display_start_date');
grid.showCol('display_end_date');
grid.showCol('course_title');
}
function show_cols(grid, added_cols) {
grid.showCol('name').trigger('reloadGrid');
for (key in added_cols) {
grid.showCol(key);
}
}
var second_filters = [];
$(function() {
date_pick_today = function(elem) {
$(elem).datetimepicker({dateFormat: "yy-mm-dd"});
$(elem).datetimepicker('setDate', (new Date()));
}
date_pick_one_month = function(elem) {
$(elem).datetimepicker({dateFormat: "yy-mm-dd"});
next_month = Date.today().next().month();
$(elem).datetimepicker('setDate', next_month);
}
// Great hack
register_second_select = function(elem) {
second_filters[$(elem).val()] = $(elem);
}
fill_second_select = function(elem) {
$(elem).on("change", function() {
composed_id = $(this).val();
field_id = composed_id.split("#")[0];
id = composed_id.split("#")[1];
$.ajax({
url: "<?php echo $urlAjaxExtraField; ?>&a=get_second_select_options",
dataType: "json",
data: "type=session&field_id="+field_id+"&option_value_id="+id,
success: function(data) {
my_select = second_filters[field_id];
my_select.empty();
$.each(data, function(index, value) {
my_select.append($("<option/>", {
value: index,
text: value
}));
});
}
});
});
}
<?php
echo Display::grid_js(
'sessions',
$url,
$columns,
$columnModel,
$extraParams,
[],
null,
true
);
?>
setSearchSelect("status");
var grid = $("#sessions"),
prmSearch = {
multipleSearch : true,
overlay : false,
width: 'auto',
caption: '<?php echo addslashes(get_lang('Search')); ?>',
formclass:'data_table',
onSearch : function() {
var postdata = grid.jqGrid('getGridParam', 'postData');
if (postdata && postdata.filters) {
filters = jQuery.parseJSON(postdata.filters);
clean_cols(grid, added_cols);
added_cols = [];
$.each(filters, function(key, value) {
if (key == 'rules') {
$.each(value, function(subkey, subvalue) {
added_cols[subvalue.field] = subvalue.field;
});
}
});
show_cols(grid, added_cols);
}
},
onReset: function() {
clean_cols(grid, added_cols);
}
};
original_cols = grid.jqGrid('getGridParam', 'colModel');
grid.jqGrid('navGrid','#sessions_pager',
{edit:false,add:false,del:false},
{height:280,reloadAfterSubmit:false}, // edit options
{height:280,reloadAfterSubmit:false}, // add options
{reloadAfterSubmit:false},// del options
prmSearch
);
<?php
// Create the searching dialog.
//echo 'grid.searchGrid(prmSearch);';
?>
// Fixes search table.
var searchDialogAll = $("#fbox_"+grid[0].id);
searchDialogAll.addClass("table");
var searchDialog = $("#searchmodfbox_"+grid[0].id);
searchDialog.addClass("ui-jqgrid ui-widget ui-widget-content ui-corner-all");
searchDialog.css({position:"adsolute", "z-index":"100", "float":"left", "top":"55%", "left" : "25%", "padding" : "5px", "border": "1px solid #CCC"})
var gbox = $("#gbox_"+grid[0].id);
gbox.before(searchDialog);
gbox.css({clear:"left"});
// Select first elements by default
$('.input-elm').each(function() {
$(this).find('option:first').attr('selected', 'selected');
});
$('.delete-rule').each(function(){
$(this).click(function(){
$('.input-elm').each(function(){
$(this).find('option:first').attr('selected', 'selected');
});
});
});
});
</script>
<?php
$form->display();
echo Display::grid_html('sessions');
Display::display_footer();