';
if (!api_is_session_general_coach() || 'true' == $extend_rights_for_coachs) {
// Action links
@@ -209,7 +298,6 @@ if (api_is_session_general_coach() && 'false' == $extend_rights_for_coachs) {
Display::display_footer();
/* Bypass functions to make direct use from SortableTable possible */
-
function get_number_of_surveys()
{
return SurveyUtil::get_number_of_surveys();
@@ -222,7 +310,7 @@ function get_survey_data($from, $number_of_items, $column, $direction)
function modify_filter($survey_id)
{
- return SurveyUtil::modify_filter($survey_id);
+ return SurveyUtil::modify_filter($survey_id, false);
}
function modify_filter_drh($survey_id)
@@ -234,6 +322,7 @@ function get_number_of_surveys_for_coach()
{
return SurveyUtil::get_number_of_surveys_for_coach();
}
+
function get_survey_data_for_coach($from, $number_of_items, $column, $direction)
{
return SurveyUtil::get_survey_data_for_coach($from, $number_of_items, $column, $direction);
diff --git a/public/main/survey/survey_question.php b/public/main/survey/survey_question.php
index 05e0b8e8b6..3e6caabfd7 100644
--- a/public/main/survey/survey_question.php
+++ b/public/main/survey/survey_question.php
@@ -1,4 +1,5 @@
addSelect(
'parent_id',
get_lang('Parent'),
$options,
- ['id' => 'parent_id', 'placeholder' => get_lang('Please select an option')]
+ ['id' => 'parent_id', 'placeholder' => get_lang('SelectAnOption')]
);
- $url = api_get_path(WEB_AJAX_PATH).'survey.ajax.php?'.api_get_cidreq();
+ $url = api_get_path(WEB_AJAX_PATH).
+ 'survey.ajax.php?'.api_get_cidreq().'&a=load_question_options&survey_id='.$surveyId;
$form->addHtml('
');
- $form->addHtml('
');
- $form->addHidden('option_id', 0);
+
+ $style = 'display:none';
+ $options = [];
+ if (!empty($optionId) && !empty($parentId)) {
+ $parentData = SurveyManager::get_question($parentId);
+ $style = '';
+ foreach ($parentData['answer_data'] as $answer) {
+ $options[$answer['iid']] = strip_tags($answer['data']);
+ }
+ }
+
+ $form->addHtml('
');
+ $form->addSelect(
+ 'parent_option_id',
+ get_lang('Option'),
+ $options,
+ ['id' => 'parent_option_id', 'disable_js' => true]
+ );
+ $form->addHtml('
');
}
/**
@@ -88,6 +124,10 @@ class survey_question
return new ch_score();
case 'yesno':
return new ch_yesno();
+ case 'selectivedisplay':
+ return new ch_selectivedisplay();
+ case 'multiplechoiceother':
+ return new ch_multiplechoiceother();
default:
api_not_allowed(true);
break;
@@ -109,37 +149,69 @@ class survey_question
$surveyId = isset($_GET['survey_id']) ? (int) $_GET['survey_id'] : null;
$type = isset($_GET['type']) ? Security::remove_XSS($_GET['type']) : null;
- $toolName = Display::return_icon(
- SurveyManager::icon_question($type),
- get_lang(ucfirst($type)),
- ['align' => 'middle', 'height' => '22px']
- ).' ';
-
- if ('add' == $action) {
- $toolName .= get_lang('Add a question').': ';
- } elseif ('edit' == $action) {
- $toolName .= get_lang('Edit question').': ';
+ $actionHeader = get_lang('EditQuestion').': ';
+ if ($action === 'add') {
+ $actionHeader = get_lang('AddQuestion').': ';
}
- switch ($_GET['type']) {
+ $questionComment = '';
+ $allowParent = false;
+ switch ($type) {
+ case 'open':
+ $toolName = get_lang('Open');
+ $questionComment = get_lang('QuestionTags');
+ $allowParent = true;
+ break;
case 'yesno':
- $toolName .= get_lang('Yes / No');
+ $toolName = get_lang('YesNo');
+ $allowParent = true;
break;
case 'multiplechoice':
- $toolName .= get_lang('Multiple choice');
+ $toolName = get_lang('UniqueSelect');
+ $allowParent = true;
break;
case 'multipleresponse':
- $toolName .= get_lang('Multiple answers');
+ $toolName = get_lang('MultipleResponse');
+ $allowParent = true;
+ break;
+ case 'selectivedisplay':
+ $toolName = get_lang('SurveyQuestionSelectiveDisplay');
+ $questionComment = get_lang('SurveyQuestionSelectiveDisplayComment');
+ $allowParent = true;
+ break;
+ case 'multiplechoiceother':
+ $toolName = get_lang('SurveyMultipleAnswerWithOther');
+ $allowParent = true;
+ break;
+ case 'pagebreak':
+ $toolName = get_lang(api_ucfirst($type));
+ $allowParent = false;
break;
default:
- $toolName .= get_lang(api_ucfirst($type));
+ $toolName = get_lang(api_ucfirst($type));
+ $allowParent = true;
+ break;
}
+ if (false === api_get_configuration_value('survey_question_dependency')) {
+ $allowParent = false;
+ }
+
+ $icon = Display::return_icon(
+ SurveyManager::icon_question($type),
+ $toolName,
+ ['align' => 'middle', 'height' => '22px']
+ ).' ';
+
+ $toolName = $icon.$actionHeader.$toolName;
$sharedQuestionId = isset($formData['shared_question_id']) ? $formData['shared_question_id'] : null;
$url = api_get_self().'?action='.$action.'&type='.$type.'&survey_id='.$surveyId.'&question_id='.$questionId.'&'.api_get_cidreq();
$form = new FormValidator('question_form', 'post', $url);
$form->addHeader($toolName);
+ if (!empty($questionComment)) {
+ $form->addHtml(Display::return_message($questionComment, 'info', false));
+ }
$form->addHidden('survey_id', $surveyId);
$form->addHidden('question_id', $questionId);
$form->addHidden('shared_question_id', Security::remove_XSS($sharedQuestionId));
@@ -163,11 +235,14 @@ class survey_question
$form->addCheckBox('is_required', get_lang('Mandatory?'), get_lang('Yes'));
}
+ if ($allowParent) {
+ $this->addParentMenu($formData, $form, $surveyData);
+ }
// When survey type = 1??
if (1 == $surveyData['survey_type']) {
$table_survey_question_group = Database::get_course_table(TABLE_SURVEY_QUESTION_GROUP);
$sql = 'SELECT id,name FROM '.$table_survey_question_group.'
- WHERE survey_id = '.(int) $_GET['survey_id'].'
+ WHERE survey_id = '.$surveyId.'
ORDER BY name';
$rs = Database::query($sql);
$glist = null;
@@ -317,7 +392,9 @@ class survey_question
}
/**
- * This solution is a little bit strange but I could not find a different solution.
+ * Deleting a specific answer is only saved in the session until the
+ * "Save question" button is pressed. This means all options are kept
+ * in the survey_question_option table until the question is saved.
*/
if (isset($_POST['delete_answer'])) {
$deleted = false;
@@ -327,16 +404,36 @@ class survey_question
Session::write('answer_count', $counter);
}
+ $newAnswers = [];
+ $newAnswersId = [];
foreach ($formData['answers'] as $key => &$value) {
if ($key > $deleted) {
- $formData['answers'][$key - 1] = $formData['answers'][$key];
+ // swap with previous (deleted) option slot
+ $newAnswers[$key - 1] = $formData['answers'][$key];
+ $newAnswersId[$key - 1] = $formData['answersid'][$key];
unset($formData['answers'][$key]);
+ unset($formData['answersid'][$key]);
+ } elseif ($key === $deleted) {
+ // delete option
+ unset($formData['answers'][$deleted]);
+ unset($formData['answersid'][$deleted]);
+ } else {
+ // keep as is
+ $newAnswers[$key] = $value;
+ $newAnswersId[$key] = $formData['answersid'][$key];
}
}
+ unset($formData['answers']);
+ unset($formData['answersid']);
+ $formData['answers'] = $newAnswers;
+ $formData['answersid'] = $newAnswersId;
}
// Adding an answer
if (isset($_POST['buttons']) && isset($_POST['buttons']['add_answer'])) {
+ if (isset($_REQUEST['type']) && 'multiplechoiceother' === $_REQUEST['type']) {
+ $counter--;
+ }
$counter++;
Session::write('answer_count', $counter);
}
@@ -348,12 +445,18 @@ class survey_question
foreach ($formData['answers'] as $index => &$data) {
if ($index > $counter) {
unset($formData['answers'][$index]);
+ unset($formData['answersid'][$index]);
}
}
}
if (!isset($_POST['delete_answer'])) {
- if (isset($formData['answers'])) {
+ // Make sure we have an array of answers
+ if (!isset($formData['answers'])) {
+ $formData['answers'] = [];
+ }
+ // Check if no deleted answer remains at the end of the answers
+ // array and add empty answers if the array is too short
foreach ($formData['answers'] as $index => $data) {
if ($index > $counter) {
unset($formData['answers'][$index]);
@@ -363,7 +466,6 @@ class survey_question
for ($i = 0; $i <= $counter; $i++) {
if (!isset($formData['answers'][$i])) {
$formData['answers'][$i] = '';
- }
}
}
}
@@ -390,13 +492,11 @@ class survey_question
if (isset($_POST['buttons']) && isset($_POST['buttons']['save'])) {
Session::erase('answer_count');
Session::erase('answer_list');
- $message = SurveyManager::save_question(
- $surveyData,
- $formData
- );
+ $message = SurveyManager::save_question($surveyData, $formData, true, $dataFromDatabase);
- if ('QuestionAdded' == $message || 'QuestionUpdated' == $message) {
- header('Location: '.api_get_path(WEB_CODE_PATH).'survey/survey.php?survey_id='.intval($_GET['survey_id']).'&message='.$message.'&'.api_get_cidreq());
+ if ($message === 'QuestionAdded' || $message === 'QuestionUpdated') {
+ $url = api_get_path(WEB_CODE_PATH).'survey/survey.php?survey_id='.intval($_GET['survey_id']).'&message='.$message.'&'.api_get_cidreq();
+ header('Location: '.$url);
exit;
}
}
@@ -435,6 +535,131 @@ class survey_question
}
/**
+ * Get the JS for questions that can depend on a previous question
+ * (and that hides those questions until something changes in the previous
+ * question).
+ *
+ * @return string HTML code
+ */
+ public static function getJs()
+ {
+ return '
+
+ ';
+ }
+
+ /**
+ * Get the question parents recursively, if any. This function depends on
+ * the existence of a parent_id field, which depends on the
+ * 'survey_question_dependency' setting and its corresponding SQL
+ * requirements.
+ *
+ * @param int $questionId The c_survey_question.question.id
+ * @param array $list An array of parents to be extended by this method
+ *
+ * @return array The completed array of parents
+ */
+ public static function getParents($questionId, $list = [])
+ {
+ if (true !== api_get_configuration_value('survey_question_dependency')) {
+ return $list;
+ }
+ $courseId = api_get_course_int_id();
+ $questionId = (int) $questionId;
+
+ $table = Database::get_course_table(TABLE_SURVEY_QUESTION);
+ $sql = "SELECT parent_id FROM $table
+ WHERE c_id = $courseId AND question_id = $questionId ";
+ $result = Database::query($sql);
+ $row = Database::fetch_array($result, 'ASSOC');
+ if ($row && !empty($row['parent_id'])) {
+ $list[] = $row['parent_id'];
+ $list = self::getParents($row['parent_id'], $list);
+ }
+
+ return $list;
+ }
+
+ /**
+ * Creates the JS code for the given parent question so that it shows
+ * the children questions when a specific answer of the parent is selected.
+ *
+ * @param array $question An array with the question details
+ *
+ * @return string JS code to add to the HTML survey question page
+ */
+ public static function getQuestionJs($question)
+ {
+ $list = self::getDependency($question);
+ if (empty($list)) {
+ return '';
+ }
+
+ $js = '';
+ $questionId = $question['question_id'];
+ $newList = [];
+ foreach ($list as $child) {
+ $childQuestionId = $child['question_id'];
+ $optionId = $child['parent_option_id'];
+ $newList[$optionId] = $childQuestionId;
+ }
+
+ $js .= '
+ ';
+
+ return $js;
+ }
+
+ /**
+ * Returns the (children) questions that have the given question as parent.
+ *
+ * @param array $question An array describing the parent question
+ *
+ * @return array The questions that have the given question as parent
+ */
+ public static function getDependency($question)
+ {
+ if (true !== api_get_configuration_value('survey_question_dependency')) {
+ return [];
+ }
+ $table = Database::get_course_table(TABLE_SURVEY_QUESTION);
+ $questionId = $question['question_id'];
+ $courseId = api_get_course_int_id();
+
+ // Getting the information of the question
+ $sql = "SELECT * FROM $table
+ WHERE c_id = $courseId AND parent_id = $questionId ";
+ $result = Database::query($sql);
+ $row = Database::store_result($result, 'ASSOC');
+
+ return $row;
+ }
+
+ /**
+ * This method is not implemented at this level (returns null).
+ *
* @param array $questionData
* @param array $answers
*/
diff --git a/public/main/tracking/courseLog.php b/public/main/tracking/courseLog.php
index da0158f981..b5b45f2665 100644
--- a/public/main/tracking/courseLog.php
+++ b/public/main/tracking/courseLog.php
@@ -8,11 +8,22 @@ use ChamiloSession as Session;
require_once __DIR__.'/../inc/global.inc.php';
$current_course_tool = TOOL_TRACKING;
-$courseId = api_get_course_id();
-$courseInfo = api_get_course_info($courseId);
//keep course_code form as it is loaded (global) by the table's get_user_data
-$course_code = $courseCode = $courseInfo['code'];
+$courseInfo = api_get_course_info();
+if (empty($courseInfo)) {
+ api_not_allowed(true);
+}
$sessionId = api_get_session_id();
+$is_allowedToTrack = Tracking::isAllowToTrack($sessionId);
+
+if (!$is_allowedToTrack) {
+ api_not_allowed(true);
+}
+
+//keep course_code form as it is loaded (global) by the table's get_user_data
+$courseCode = $courseInfo['code'];
+$courseId = $courseInfo['real_id'];
+
// PERSON_NAME_DATA_EXPORT is buggy
$sortByFirstName = api_sort_by_first_name();
$from_myspace = false;
@@ -31,12 +42,6 @@ if ('myspace' === $from) {
$this_section = 'session_my_space';
}
-$is_allowedToTrack = Tracking::isAllowToTrack($sessionId);
-
-if (!$is_allowedToTrack) {
- api_not_allowed(true);
-}
-
// If the user is a HR director (drh)
if (api_is_drh()) {
// Blocking course for drh
@@ -180,7 +185,6 @@ if (isset($_GET['additional_profile_field'])) {
$fieldId,
$user_array
);
-
$extra_info[$fieldId] = UserManager::get_extra_field_information($fieldId);
}
}
@@ -320,15 +324,81 @@ if ($showReporting) {
$trackingColumn = isset($_GET['users_tracking_column']) ? $_GET['users_tracking_column'] : null;
$trackingDirection = isset($_GET['users_tracking_direction']) ? $_GET['users_tracking_direction'] : null;
+$hideReports = api_get_configuration_value('hide_course_report_graph');
+$conditions = [];
+
+$groupList = GroupManager::get_group_list(null, $courseInfo, 1, $sessionId);
+
+$class = new UserGroup();
+//$options['where'] = [' usergroup.course_id = ? ' => $courseId];
+//$classes = $class->getUserGroupInCourse($options);
+$classes = $class->get_all();
// Show the charts part only if there are students subscribed to this course/session
if ($nbStudents > 0) {
- $usersTracking = TrackingCourseLog::get_user_data(null, $nbStudents, $trackingColumn, $trackingDirection, false);
+ // Classes
+ $formClass = new FormValidator(
+ 'classes',
+ 'get',
+ api_get_self().'?'.api_get_cidreq().'&'.$additionalParams
+ );
+ $formClass->addHidden('cidReq', $courseCode);
+ $formClass->addHidden('id_session', $sessionId);
+ $groupIdList = ['--'];
+ $select = $formClass->addSelect('class_id', get_lang('Class').'/'.get_lang('Group'), $groupIdList);
+ $groupIdList = [];
+ foreach ($classes as $class) {
+ //$groupIdList['class_'.$class['id']] = $class['name'];
+ $groupIdList[] = ['text' => $class['name'], 'value' => 'class_'.$class['id']];
+ }
+ $select->addOptGroup($groupIdList, get_lang('Class'));
+ $groupIdList = [];
+ foreach ($groupList as $group) {
+ $groupIdList[] = ['text' => $group['name'], 'value' => 'group_'.$group['id']];
+ //$groupIdList['group_'.$group['id']] = $group['name'];
+ }
+ $select->addOptGroup($groupIdList, get_lang('Group'));
+ $formClass->addButtonSearch(get_lang('Search'));
+
+ // Groups
+ /*$formGroup = new FormValidator(
+ 'groups',
+ 'get',
+ api_get_self().'?'.api_get_cidreq().'&'.$additionalParams
+ );
+ $formGroup->addHidden('cidReq', $courseCode);
+ $formGroup->addHidden('id_session', $sessionId);
+ $groupIdList = ['--'];
+ foreach ($groupList as $group) {
+ $groupIdList[$group['id']] = $group['name'];
+ }
+ $formGroup->addSelect('group_id', get_lang('Group'), $groupIdList);
+ $formGroup->addButtonSearch(get_lang('Search'));*/
+
+ // Extra fields
+ $formExtraField = new FormValidator(
+ 'extra_fields',
+ 'get',
+ api_get_self().'?'.api_get_cidreq().'&'.$additionalParams
+ );
+ $formExtraField->addHidden('cidReq', $courseCode);
+ $formExtraField->addHidden('id_session', $sessionId);
+ if (isset($_GET['additional_profile_field'])) {
+ foreach ($_GET['additional_profile_field'] as $fieldId) {
+ $fieldId = Security::remove_XSS($fieldId);
+ $formExtraField->addHidden('additional_profile_field[]', $fieldId);
+ //$formGroup->addHidden('additional_profile_field[]', $fieldId);
+ $formClass->addHidden('additional_profile_field[]', $fieldId);
+ }
+ }
+
+ $extraField = new ExtraField('user');
+ $extraField->addElements($formExtraField, 0, [], true);
+ $formExtraField->addButtonSearch(get_lang('Search'));
$numberStudentsCompletedLP = 0;
$averageStudentsTestScore = 0;
$scoresDistribution = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
-
$userScoreList = [];
$listStudentIds = [];
$timeStudent = [];
@@ -336,15 +406,71 @@ if ($nbStudents > 0) {
$category = Category::load(
null,
null,
- $course_code,
+ $courseCode,
null,
null,
$sessionId
);
- $hideReports = api_get_configuration_value('hide_course_report_graph');
+ $conditions = [];
+ $fields = [];
+
+ if ($formClass->validate()) {
+ $classId = null;
+ $groupId = null;
+
+ $part = $formClass->getSubmitValue('class_id');
+ $item = explode('_', $part);
+ if (isset($item[0]) && isset($item[1])) {
+ if ('class' === $item[0]) {
+ $classId = (int) $item[1];
+ } else {
+ $groupId = (int) $item[1];
+ }
+ }
+
+ if (!empty($classId)) {
+ $whereCondition = " AND gu.usergroup_id = $classId ";
+ $tableGroup = Database::get_main_table(TABLE_USERGROUP_REL_USER);
+ $joins = " INNER JOIN $tableGroup gu ON (user.id = gu.user_id) ";
+ $conditions = ['where' => $whereCondition, 'inject_joins' => $joins];
+ }
+
+ if (!empty($groupId)) {
+ $whereCondition = " AND gu.group_id = $groupId ";
+ $tableGroup = Database::get_course_table(TABLE_GROUP_USER);
+ $joins = " INNER JOIN $tableGroup gu ON (user.id = gu.user_id) ";
+ $conditions = ['where' => $whereCondition, 'inject_joins' => $joins];
+ }
+ }
- if (false === $hideReports) {
+ /*if ($formGroup->validate()) {
+ $groupId = (int) $formGroup->getSubmitValue('group_id');
+ if (!empty($groupId)) {
+ $whereCondition = " AND gu.group_id = $groupId ";
+ $tableGroup = Database::get_course_table(TABLE_GROUP_USER);
+ $joins = " INNER JOIN $tableGroup gu ON (user.id = gu.user_id) ";
+ $conditions = ['where' => $whereCondition, 'inject_joins' => $joins];
+ }
+ }*/
+
+ if ($formExtraField->validate()) {
+ $extraResult = $extraField->processExtraFieldSearch($_REQUEST, $formExtraField, 'user');
+ if (!empty($extraResult)) {
+ $conditions = $extraResult['condition'];
+ $fields = $extraResult['fields'];
+ }
+ }
+
+ if ($hideReports === false) {
+ $conditions['include_invited_users'] = false;
+ $usersTracking = TrackingCourseLog::get_user_data(
+ null,
+ $nbStudents,
+ $trackingColumn,
+ $trackingDirection,
+ $conditions
+ );
foreach ($usersTracking as $userTracking) {
$userInfo = api_get_user_info_from_username($userTracking[3]);
if (empty($userInfo)) {
@@ -391,7 +517,6 @@ if ($nbStudents > 0) {
$averageStudentsTestScore = round($averageStudentsTestScore / $nbStudents);
$colors = ChamiloApi::getColorPalette(true, true, 10);
-
$tpl->assign('chart_colors', json_encode($colors));
$tpl->assign('certificate_count', $certificateCount);
$tpl->assign('score_distribution', json_encode($scoresDistribution));
@@ -411,7 +536,25 @@ if ($nbStudents > 0) {
$html .= Display::page_subheader2(get_lang('Learners list'));
if ($nbStudents > 0) {
- $getLangXDays = get_lang('%s days');
+ $mainForm = new FormValidator(
+ 'filter',
+ 'get',
+ api_get_self().'?'.api_get_cidreq().'&'.$additionalParams
+ );
+ $mainForm->addButtonAdvancedSettings(
+ 'advanced_search',
+ [get_lang('AdvancedSearch')]
+ );
+ $mainForm->addHtml('
');
+ $mainForm->addHtml($formClass->returnForm());
+ $mainForm->addHtml($formExtraField->returnForm());
+ $mainForm->addHtml('
');
+
+ //$html .= $formClass->returnForm();
+ //$html .= $formExtraField->returnForm();
+ $html .= $mainForm->returnForm();
+
+ $getLangXDays = get_lang('XDays');
$form = new FormValidator(
'reminder_form',
'get',
@@ -435,20 +578,18 @@ if ($nbStudents > 0) {
'since',
Display::returnFontAwesomeIcon('warning').get_lang('Remind learners inactive since'),
$options,
- ['disable_js' => true]
+ ['disable_js' => true, 'class' => 'col-sm-3']
);
$el->setSelected(7);
-
$form->addElement('hidden', 'action', 'add');
$form->addElement('hidden', 'remindallinactives', 'true');
$form->addElement('hidden', 'cidReq', $courseInfo['code']);
$form->addElement('hidden', 'id_session', api_get_session_id());
$form->addButtonSend(get_lang('Notify'));
- $extra_field_select = TrackingCourseLog::display_additional_profile_fields();
-
- if (!empty($extra_field_select)) {
- $html .= $extra_field_select;
+ $extraFieldSelect = TrackingCourseLog::display_additional_profile_fields();
+ if (!empty($extraFieldSelect)) {
+ $html .= $extraFieldSelect;
}
$html .= $form->returnForm();
@@ -459,6 +600,7 @@ if ($nbStudents > 0) {
$_GET['users_tracking_per_page'] = 1000000;
}
+ if ($hideReports === false) {
$table = new SortableTableFromArray(
$usersTracking,
1,
@@ -466,13 +608,22 @@ if ($nbStudents > 0) {
'users_tracking'
);
$table->total_number_of_items = $nbStudents;
+ } else {
+ $conditions['include_invited_users'] = true;
+ $table = new SortableTable(
+ 'users_tracking',
+ ['TrackingCourseLog', 'get_number_of_users'],
+ ['TrackingCourseLog', 'get_user_data'],
+ 1,
+ 20
+ );
+ $table->setDataFunctionParams($conditions);
+ }
$parameters['cidReq'] = isset($_GET['cidReq']) ? Security::remove_XSS($_GET['cidReq']) : '';
$parameters['id_session'] = $sessionId;
$parameters['from'] = isset($_GET['myspace']) ? Security::remove_XSS($_GET['myspace']) : null;
- $table->set_additional_parameters($parameters);
-
$headers = [];
// tab of header texts
$table->set_header(0, get_lang('Code'), true);
@@ -546,42 +697,39 @@ if ($nbStudents > 0) {
if (empty($sessionId)) {
$table->set_header(12, get_lang('Survey'), false);
$headers['survey'] = get_lang('Survey');
- $table->set_header(13, get_lang('First access to course'), false);
- $headers['first_login'] = get_lang('First access to course');
- $table->set_header(14, get_lang('Latest access in course'), false);
- $headers['latest_login'] = get_lang('Latest access in course');
+ } else {
+ $table->set_header(12, get_lang('RegisteredDate'), false);
+ $headers['registered_at'] = get_lang('RegisteredDate');
+ }
+ $table->set_header(13, get_lang('FirstLoginInCourse'), false);
+ $headers['first_login'] = get_lang('FirstLoginInCourse');
+ $table->set_header(14, get_lang('LatestLoginInCourse'), false);
+ $headers['latest_login'] = get_lang('LatestLoginInCourse');
if (isset($_GET['additional_profile_field'])) {
$counter = 15;
foreach ($_GET['additional_profile_field'] as $fieldId) {
$table->set_header($counter, $extra_info[$fieldId]['display_text'], false);
$headers[$extra_info[$fieldId]['variable']] = $extra_info[$fieldId]['display_text'];
$counter++;
+ $parameters['additional_profile_field'] = $fieldId;
}
-
$table->set_header($counter, get_lang('Details'), false);
$headers['details'] = get_lang('Details');
} else {
$table->set_header(15, get_lang('Details'), false);
$headers['details'] = get_lang('Details');
}
- } else {
- $table->set_header(12, get_lang('First access to course'), false);
- $headers['first_login'] = get_lang('First access to course');
- $table->set_header(13, get_lang('Latest access in course'), false);
- $headers['latest_login'] = get_lang('Latest access in course');
- if (isset($_GET['additional_profile_field'])) {
- $counter = 15;
- foreach ($_GET['additional_profile_field'] as $fieldId) {
- $table->set_header($counter, $extra_info[$fieldId]['display_text'], false);
- $headers[$extra_info[$fieldId]['variable']] = $extra_info[$fieldId]['display_text'];
- $counter++;
+ if (!empty($fields)) {
+ foreach ($fields as $key => $value) {
+ $key = Security::remove_XSS($key);
+ $value = Security::remove_XSS($value);
+ $parameters[$key] = $value;
}
- } else {
- $table->set_header(14, get_lang('Details'), false);
- $headers['Details'] = get_lang('Details');
}
- }
+ $parameters['cidReq'] = $courseCode;
+ $parameters['id_session'] = $sessionId;
+ $table->set_additional_parameters($parameters);
// display buttons to un hide hidden columns
$html .= '
';
$index = 0;
@@ -609,8 +757,210 @@ if ($nbStudents > 0) {
$html .= Display::return_message(get_lang('No users in course'), 'warning', true);
}
+$groupContent = '';
echo Display::panel($html, $titleSession);
+$groupTable = new HTML_Table(['class' => 'table table-bordered data_table']);
+$column = 0;
+$groupTable->setHeaderContents(0, $column++, get_lang('Name'));
+$groupTable->setHeaderContents(0, $column++, get_lang('TrainingTime'));
+$groupTable->setHeaderContents(0, $column++, get_lang('AverageTrainingTime'));
+$groupTable->setHeaderContents(0, $column++, get_lang('CourseProgress'));
+$groupTable->setHeaderContents(0, $column++, get_lang('ExerciseAverage'));
+
+$exerciseList = ExerciseLib::get_all_exercises(
+ $courseInfo,
+ $sessionId,
+ false,
+ null,
+ false,
+ 3
+);
+//$groupList = null;
+if (!empty($groupList)) {
+ $totalTime = null;
+ $totalLpProgress = null;
+ $totalScore = null;
+ $totalAverageTime = null;
+ $totalBestScoreAverageNotInLP = 0;
+ $row = 1;
+ foreach ($groupList as $groupInfo) {
+ $column = 0;
+ $groupTable->setCellContents($row, $column++, $groupInfo['name']);
+ $usersInGroup = GroupManager::getStudents($groupInfo['iid']);
+
+ $time = null;
+ $lpProgress = null;
+ $score = null;
+ $averageTime = null;
+ $bestScoreAverageNotInLP = null;
+ if (!empty($usersInGroup)) {
+ $usersInGroup = array_column($usersInGroup, 'user_id');
+ $userInGroupCount = count($usersInGroup);
+ $timeInSeconds = Tracking::get_time_spent_on_the_course(
+ $usersInGroup,
+ $courseId,
+ $sessionId
+ );
+ $totalTime += $timeInSeconds;
+ if (!empty($timeInSeconds)) {
+ $time = api_time_to_hms($timeInSeconds);
+ $averageTime = $timeInSeconds / $userInGroupCount;
+ $totalAverageTime += $averageTime;
+ $averageTime = api_time_to_hms($averageTime);
+ }
+
+ $totalGroupLpProgress = 0;
+ foreach ($usersInGroup as $studentId) {
+ $lpProgress = Tracking::get_avg_student_progress(
+ $usersInGroup,
+ $courseCode,
+ [],
+ $sessionId
+ );
+ $totalGroupLpProgress += $lpProgress;
+ }
+
+ if (empty($totalGroupLpProgress)) {
+ $totalGroupLpProgress = '';
+ } else {
+ $lpProgress = $totalGroupLpProgress / $userInGroupCount;
+ $totalLpProgress += $totalGroupLpProgress;
+ }
+
+ if (!empty($exerciseList)) {
+ foreach ($exerciseList as $exerciseData) {
+ foreach ($usersInGroup as $userId) {
+ $results = Event::get_best_exercise_results_by_user(
+ $exerciseData['id'],
+ $courseInfo['real_id'],
+ 0,
+ $userId
+ );
+ $best = 0;
+ if (!empty($results)) {
+ foreach ($results as $result) {
+ if (!empty($result['exe_weighting'])) {
+ $score = $result['exe_result'] / $result['exe_weighting'];
+ if ($score > $best) {
+ $best = $score;
+ }
+ }
+ }
+ }
+ $bestScoreAverageNotInLP += $best;
+ }
+ }
+ $bestScoreAverageNotInLP = round(
+ $bestScoreAverageNotInLP / count($exerciseList) * 100 / $userInGroupCount,
+ 2
+ );
+
+ $totalBestScoreAverageNotInLP += $bestScoreAverageNotInLP;
+ }
+
+ if (empty($score)) {
+ $score = '';
+ }
+ if (empty($lpProgress)) {
+ $lpProgress = '';
+ }
+ if (empty($bestScoreAverageNotInLP)) {
+ $bestScoreAverageNotInLP = '';
+ }
+ }
+
+ $groupTable->setCellContents($row, $column++, $time);
+ $groupTable->setCellContents($row, $column++, $averageTime);
+ $groupTable->setCellContents($row, $column++, $lpProgress);
+ $groupTable->setCellContents($row, $column++, $bestScoreAverageNotInLP);
+ $row++;
+ }
+
+ $column = 0;
+ $totalTime = api_time_to_hms($totalTime);
+ $totalAverageTime = api_time_to_hms($totalAverageTime);
+ $groupTable->setCellContents($row, $column++, get_lang('Total'));
+ $groupTable->setCellContents($row, $column++, $totalTime);
+ $groupTable->setCellContents($row, $column++, $totalAverageTime);
+ $groupTable->setCellContents($row, $column++, round($totalLpProgress / count($groupList), 2).'% ');
+ $groupTable->setCellContents($row, $column++, round($totalBestScoreAverageNotInLP / count($groupList), 2).'% ');
+} else {
+ $userIdList = Session::read('user_id_list');
+
+ if (!empty($userIdList)) {
+ $studentIdList = $userIdList;
+ } else {
+ $studentIdList = array_column($studentList, 'user_id');
+ }
+ $nbStudents = count($studentIdList);
+
+ $timeInSeconds = Tracking::get_time_spent_on_the_course(
+ $studentIdList,
+ $courseId,
+ $sessionId
+ );
+ $averageTime = null;
+ if (!empty($timeInSeconds)) {
+ $time = api_time_to_hms($timeInSeconds);
+ $averageTime = $timeInSeconds / $nbStudents;
+ $averageTime = api_time_to_hms($averageTime);
+ }
+ $totalLpProgress = 0;
+ foreach ($studentIdList as $studentId) {
+ $lpProgress = Tracking::get_avg_student_progress(
+ $studentId,
+ $courseCode,
+ [],
+ $sessionId
+ );
+ $totalLpProgress += $lpProgress;
+ }
+
+ $lpProgress = round($totalLpProgress / $nbStudents, 2).' %';
+ $totalBestScoreAverageNotInLP = 0;
+ $bestScoreAverageNotInLP = 0;
+ if (!empty($exerciseList)) {
+ foreach ($exerciseList as $exerciseData) {
+ foreach ($studentIdList as $userId) {
+ $results = Event::get_best_exercise_results_by_user(
+ $exerciseData['id'],
+ $courseInfo['real_id'],
+ $sessionId,
+ $userId
+ );
+ $best = 0;
+ if (!empty($results)) {
+ foreach ($results as $result) {
+ if (!empty($result['exe_weighting'])) {
+ $score = $result['exe_result'] / $result['exe_weighting'];
+ if ($score > $best) {
+ $best = $score;
+ }
+ }
+ }
+ }
+
+ $bestScoreAverageNotInLP += $best;
+ }
+ }
+ $bestScoreAverageNotInLP = round(
+ $bestScoreAverageNotInLP / count($exerciseList) * 100 / $nbStudents,
+ 2
+ ).' %';
+ }
+
+ $row = 1;
+ $column = 0;
+ $groupTable->setCellContents($row, $column++, get_lang('Total'));
+ $groupTable->setCellContents($row, $column++, $time);
+ $groupTable->setCellContents($row, $column++, $averageTime);
+ $groupTable->setCellContents($row, $column++, $lpProgress);
+ $groupTable->setCellContents($row, $column++, $bestScoreAverageNotInLP);
+}
+
+echo Display::panel($groupTable->toHtml(), '');
+
// Send the csv file if asked.
if ($export_csv) {
$csv_headers = [];
@@ -633,6 +983,8 @@ if ($export_csv) {
if (empty($sessionId)) {
$csv_headers[] = get_lang('Survey');
+ } else {
+ $csv_headers[] = get_lang('RegistrationDate');
}
$csv_headers[] = get_lang('First access to course');
diff --git a/public/main/work/edit.php b/public/main/work/edit.php
index 074d78d7f6..3b82d118ce 100644
--- a/public/main/work/edit.php
+++ b/public/main/work/edit.php
@@ -87,7 +87,9 @@ if (!empty($my_folder_data)) {
if (!empty($homework['expires_on']) || !empty($homework['ends_on'])) {
$time_now = time();
- if (!empty($homework['expires_on'])) {
+ if (!empty($homework['expires_on']) &&
+ !empty($homework['expires_on'])
+ ) {
$time_expires = api_strtotime($homework['expires_on'], 'UTC');
$difference = $time_expires - $time_now;
if ($difference < 0) {
@@ -238,6 +240,7 @@ if ($form->validate()) {
/*$add_to_update = ', qualificator_id ='."'".api_get_user_id()."', ";
$add_to_update .= ' qualification = '."'".api_float_val($_POST['qualification'])."',";
$add_to_update .= ' date_of_qualification = '."'".api_get_utc_datetime()."'";*/
+
if (isset($_POST['send_email'])) {
$url = api_get_path(WEB_CODE_PATH).'work/view.php?'.api_get_cidreq().'&id='.$item_to_edit_id;
$subject = sprintf(get_lang('There\'s a new feedback in work: %s'), $studentPublication->getTitle());
diff --git a/public/main/work/edit_work.php b/public/main/work/edit_work.php
index b84510a69e..277194b5a5 100644
--- a/public/main/work/edit_work.php
+++ b/public/main/work/edit_work.php
@@ -116,8 +116,14 @@ if ($form->validate()) {
}
$workId = $params['work_id'];
+ $editCheck = false;
$workData = get_work_data_by_id($workId);
- $editCheck = true;
+
+ if (!empty($workData)) {
+ $editCheck = true;
+ } else {
+ $editCheck = true;
+ }
if ($editCheck) {
updateWork($workData['iid'], $params, $courseInfo, $sessionId);
diff --git a/public/main/work/view.php b/public/main/work/view.php
index ac53096b84..d520608ae9 100644
--- a/public/main/work/view.php
+++ b/public/main/work/view.php
@@ -10,13 +10,15 @@ require_once 'work.lib.php';
$id = isset($_GET['id']) ? (int) $_GET['id'] : null;
$work = get_work_data_by_id($id);
-if (empty($id) || empty($work)) {
+if (empty($work)) {
api_not_allowed(true);
}
-if (1 != $work['active']) {
- api_not_allowed(true);
-}
+protectWork(api_get_course_info(), $work['parent_id']);
+
+$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : null;
+$page = isset($_REQUEST['page']) ? $_REQUEST['page'] : null;
+
$work['title'] = isset($work['title']) ? Security::remove_XSS($work['title']) : '';
$work['description'] = isset($work['description']) ? Security::remove_XSS($work['description']) : '';
@@ -26,23 +28,29 @@ $interbreadcrumb[] = [
'name' => get_lang('Assignments'),
];
-$my_folder_data = get_work_data_by_id($work['parent_id']);
+$folderData = get_work_data_by_id($work['parent_id']);
$courseInfo = api_get_course_info();
-$blockScoreEdition = api_get_configuration_value('block_student_publication_score_edition');
+$isCourseManager = api_is_platform_admin() || api_is_coach() || api_is_allowed_to_edit(false, false, true);
-if ($blockScoreEdition && !empty($work['qualification']) && !api_is_platform_admin()) {
- api_not_allowed(true);
+$allowEdition = false;
+if ($isCourseManager) {
+ $allowEdition = true;
+ if (!empty($work['qualification']) && api_get_configuration_value('block_student_publication_score_edition')) {
+ $allowEdition = false;
+ }
}
-protectWork(api_get_course_info(), $work['parent_id']);
+if (api_is_platform_admin()) {
+ $allowEdition = true;
+}
$isDrhOfCourse = CourseManager::isUserSubscribedInCourseAsDrh(
api_get_user_id(),
$courseInfo
);
-if ((user_is_author($id) || $isDrhOfCourse || (api_is_allowed_to_edit() || api_is_coach())) ||
+if ((user_is_author($id) || $isDrhOfCourse || $allowEdition) ||
(
0 == $courseInfo['show_score'] &&
1 == $work['active'] &&
@@ -50,13 +58,13 @@ if ((user_is_author($id) || $isDrhOfCourse || (api_is_allowed_to_edit() || api_i
)
) {
if ((api_is_allowed_to_edit() || api_is_coach()) || api_is_drh()) {
- $url_dir = api_get_path(WEB_CODE_PATH).'work/work_list_all.php?id='.$my_folder_data['id'].'&'.api_get_cidreq();
+ $url_dir = api_get_path(WEB_CODE_PATH).'work/work_list_all.php?id='.$folderData['id'].'&'.api_get_cidreq();
} else {
- $url_dir = api_get_path(WEB_CODE_PATH).'work/work_list.php?id='.$my_folder_data['id'].'&'.api_get_cidreq();
+ $url_dir = api_get_path(WEB_CODE_PATH).'work/work_list.php?id='.$folderData['id'].'&'.api_get_cidreq();
}
$userInfo = api_get_user_info($work['user_id']);
- $interbreadcrumb[] = ['url' => $url_dir, 'name' => $my_folder_data['title']];
+ $interbreadcrumb[] = ['url' => $url_dir, 'name' => $folderData['title']];
$interbreadcrumb[] = ['url' => '#', 'name' => $userInfo['complete_name']];
$interbreadcrumb[] = ['url' => '#', 'name' => $work['title']];
@@ -65,13 +73,10 @@ if ((user_is_author($id) || $isDrhOfCourse || (api_is_allowed_to_edit() || api_i
1 == $work['active'] &&
1 == $work['accepted']
) ||
- (api_is_allowed_to_edit() || api_is_coach()) || user_is_author($id) || $isDrhOfCourse
+ $isCourseManager || user_is_author($id) || $isDrhOfCourse
) {
- $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : null;
- $page = isset($_REQUEST['page']) ? $_REQUEST['page'] : null;
-
- if ('edit' === $page) {
- $url = api_get_path(WEB_CODE_PATH).'work/edit.php?id='.$my_folder_data['id'].'&item_id='.$work['id'].'&'.api_get_cidreq();
+ if ($page === 'edit') {
+ $url = api_get_path(WEB_CODE_PATH).'work/edit.php?id='.$folderData['id'].'&item_id='.$work['id'].'&'.api_get_cidreq();
} else {
$url = api_get_path(WEB_CODE_PATH).'work/view.php?id='.$work['id'].'&'.api_get_cidreq();
@@ -91,14 +96,12 @@ if ((user_is_author($id) || $isDrhOfCourse || (api_is_allowed_to_edit() || api_i
addWorkComment(
api_get_course_info(),
api_get_user_id(),
- $my_folder_data,
+ $folderData,
$work,
$_POST
);
- if (api_is_allowed_to_edit()) {
- $qualification = isset($_POST['qualification']) ? api_float_val($_POST['qualification']) : null;
- if (null !== $qualification) {
+ if ($allowEdition) {
$work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
$sql = "UPDATE $work_table
SET
@@ -107,21 +110,16 @@ if ((user_is_author($id) || $isDrhOfCourse || (api_is_allowed_to_edit() || api_i
date_of_qualification = '".api_get_utc_datetime()."'
WHERE c_id = ".$courseInfo['real_id']." AND id = $id";
Database::query($sql);
- }
-
- Display::addFlash(Display::return_message(get_lang('Update successful')));
+ Display::addFlash(Display::return_message(get_lang('Updated')));
$resultUpload = uploadWork(
- $my_folder_data,
+ $folderData,
$courseInfo,
true,
$work
);
if ($resultUpload) {
- $work_table = Database::get_course_table(
- TABLE_STUDENT_PUBLICATION
- );
-
+ $work_table = Database::get_course_table(TABLE_STUDENT_PUBLICATION);
if (isset($resultUpload['url']) && !empty($resultUpload['url'])) {
$title = isset($resultUpload['filename']) && !empty($resultUpload['filename']) ? $resultUpload['filename'] : get_lang('Untitled');
$urlToSave = Database::escape_string($resultUpload['url']);
@@ -138,11 +136,6 @@ if ((user_is_author($id) || $isDrhOfCourse || (api_is_allowed_to_edit() || api_i
}
}
- $blockScoreEdition = api_get_configuration_value('block_student_publication_score_edition');
-
- if ($blockScoreEdition && !api_is_platform_admin()) {
- $url = api_get_path(WEB_CODE_PATH).'work/work_list_all.php?'.api_get_cidreq().'&id='.$my_folder_data['id'];
- }
header('Location: '.$url);
exit;
@@ -159,29 +152,24 @@ if ((user_is_author($id) || $isDrhOfCourse || (api_is_allowed_to_edit() || api_i
break;
case 'delete_correction':
- if (isset($work['url_correction']) && !empty($work['url_correction'])) {
- if (api_is_allowed_to_edit()) {
+ if ($allowEdition && isset($work['url_correction']) && !empty($work['url_correction'])) {
deleteCorrection($courseInfo, $work);
- Display::addFlash(
- Display::return_message(get_lang('Deleted'))
- );
- }
+ Display::addFlash(Display::return_message(get_lang('Deleted')));
}
header('Location: '.$url);
exit;
-
break;
}
$comments = getWorkComments($work);
- $commentForm = getWorkCommentForm($work, $my_folder_data);
+ $commentForm = getWorkCommentForm($work, $folderData);
$tpl = new Template();
$tpl->assign('work', $work);
$tpl->assign('comments', $comments);
-
$actions = '';
+
if (isset($work['contains_file']) && !empty($work['contains_file'])) {
if (isset($work['download_url']) && !empty($work['download_url'])) {
$actions = Display::url(
@@ -220,7 +208,8 @@ if ((user_is_author($id) || $isDrhOfCourse || (api_is_allowed_to_edit() || api_i
),
$work['download_url'].'&correction=1'
);
- if (api_is_allowed_to_edit()) {
+
+ if ($allowEdition) {
$actions .= Display::url(
Display::return_icon(
'delete.png',
diff --git a/public/main/work/work.lib.php b/public/main/work/work.lib.php
index a01241f00a..30a3e3c9ac 100644
--- a/public/main/work/work.lib.php
+++ b/public/main/work/work.lib.php
@@ -407,11 +407,14 @@ function getUniqueStudentAttemptsTotal($workId, $groupId, $course_id, $sessionId
}
/**
+ * @param mixed $workId
* @param int $groupId
* @param int $course_id
* @param int $sessionId
* @param int $userId user id to filter
* @param array $onlyUserList only parse this user list
+ *
+ * @return mixed
*/
function getUniqueStudentAttempts(
$workId,
@@ -1854,6 +1857,8 @@ function get_work_user_list(
$course_info
);
+ $isDrhOfSession = !empty(SessionManager::getSessionFollowedByDrh(api_get_user_id(), $session_id));
+
$groupIid = 0;
if ($group_id) {
$groupInfo = GroupManager::get_group_properties($group_id);
@@ -1870,7 +1875,7 @@ function get_work_user_list(
$extra_conditions = " (work.post_group_id = '0' OR work.post_group_id is NULL) ";
}
- if ($is_allowed_to_edit || $isDrhOfCourse) {
+ if ($is_allowed_to_edit || $isDrhOfCourse || $isDrhOfSession) {
$extra_conditions .= ' AND work.active IN (0, 1) ';
} else {
if (isset($course_info['show_score']) &&
@@ -2114,6 +2119,7 @@ function get_work_user_list(
$work_date = api_get_local_time($work['sent_date']);
$date = date_to_str_ago($work['sent_date']).' '.$work_date;
$work['formatted_date'] = $work_date.' '.$add_string;
+ $work['expiry_note'] = $add_string;
$work['sent_date_from_db'] = $work['sent_date'];
$work['sent_date'] = '
'.
$add_string.' '.Display::dateToStringAgoAndLongDate($work['sent_date']).'
';
@@ -2165,6 +2171,12 @@ function get_work_user_list(
dropZone: $(this)
});
});
+
+ $('.getSingleCompilatio').on('click', function () {
+ var parts = $(this).parent().attr('id').split('id_avancement');
+ getSingleCompilatio(parts[1]);
+ });
+
$('#file_upload_".$item_id."').fileupload({
add: function (e, data) {
$('#progress_$item_id').html();
@@ -2317,7 +2329,7 @@ function get_work_user_list(
/**
* Send reminder to users who have not given the task.
*
- * @param int $task_data
+ * @param int
*
* @return array
*
@@ -2537,8 +2549,8 @@ function user_is_author($itemId, $userId = null, $courseId = 0, $sessionId = 0)
/**
* Get list of users who have not given the task.
*
- * @param int $task_id
- * @param int $studentId
+ * @param int
+ * @param int
*
* @return array
*
@@ -2644,7 +2656,7 @@ function get_list_users_without_publication($task_id, $studentId = 0)
/**
* Display list of users who have not given the task.
*
- * @param int $task_id task id
+ * @param int task id
* @param int $studentId
*
* @author cvargas carlos.vargas@beeznest.com cfasanando, christian.fasanado@beeznest.com
@@ -3583,8 +3595,21 @@ function getWorkCommentForm($work, $workParent)
$qualification = $workParent['qualification'];
- if (api_is_allowed_to_edit()) {
- if (!empty($qualification) && (int) $qualification > 0) {
+ $isCourseManager = api_is_platform_admin() || api_is_coach() || api_is_allowed_to_edit(false, false, true);
+ $allowEdition = false;
+ if ($isCourseManager) {
+ $allowEdition = true;
+ if (!empty($work['qualification']) && api_get_configuration_value('block_student_publication_score_edition')) {
+ $allowEdition = false;
+ }
+ }
+
+ if (api_is_platform_admin()) {
+ $allowEdition = true;
+ }
+
+ if ($allowEdition) {
+ if (!empty($qualification) && intval($qualification) > 0) {
$model = ExerciseLib::getCourseScoreModel();
if (empty($model)) {
$form->addFloat(
@@ -3768,10 +3793,10 @@ function uploadWork($my_folder_data, $_course, $isCorrection = false, $workInfo
$filename = add_ext_on_mime(stripslashes($file['name']), $file['type']);
// Replace dangerous characters
+ $filename = api_replace_dangerous_char($filename);
//$filename = api_replace_dangerous_char($filename);
- // Transform any .php file in .phps fo security
- //$filename = php2phps($filename);
+ $filename = php2phps($filename);
$filesize = filesize($file['tmp_name']);
if (empty($filesize)) {