Update from 1.11.x

pull/3272/head
Julio Montoya 5 years ago
parent cd057a6b65
commit 024a2054bc
  1. 1
      public/main/admin/access_url_check_user_session.php
  2. 1
      public/main/admin/archive_cleanup.php
  3. 8
      public/main/admin/configure_plugin.php
  4. 10
      public/main/admin/course_export.php
  5. 2
      public/main/admin/course_list.php
  6. 2
      public/main/admin/languages.php
  7. 1
      public/main/admin/user_add.php
  8. 3
      public/main/admin/user_edit.php
  9. 4
      public/main/admin/user_information.php
  10. 143
      public/main/admin/user_list.php
  11. 3
      public/main/announcements/announcements.php
  12. 3
      public/main/badge/issued.php
  13. 3
      public/main/badge/issued_all.php
  14. 18
      public/main/calendar/agenda_list.php
  15. 38
      public/main/dropbox/dropbox_class.inc.php
  16. 1
      public/main/dropbox/dropbox_init.inc.php
  17. 1
      public/main/dropbox/update.php
  18. 38
      public/main/exercise/answer.class.php
  19. 1
      public/main/exercise/calculated_answer.class.php
  20. 50
      public/main/exercise/category.php
  21. 287
      public/main/exercise/exercise.class.php
  22. 50
      public/main/exercise/exercise.php
  23. 1
      public/main/exercise/exercise_admin.php
  24. 21
      public/main/exercise/exercise_reminder.php
  25. 95
      public/main/exercise/exercise_report.php
  26. 6
      public/main/exercise/exercise_result.php
  27. 2
      public/main/exercise/exercise_show.php
  28. 33
      public/main/exercise/exercise_submit.php
  29. 87
      public/main/exercise/exercise_submit_modal.php
  30. 10
      public/main/exercise/export/exercise_import.inc.php
  31. 1
      public/main/exercise/fill_blanks.class.php
  32. 9
      public/main/exercise/question.class.php
  33. 3
      public/main/exercise/question_create.php
  34. 379
      public/main/exercise/question_pool.php
  35. 117
      public/main/exercise/recalculate.php
  36. 61
      public/main/exercise/recalculate_all.php
  37. 1
      public/main/exercise/result.php
  38. 1
      public/main/exercise/upload_exercise.php

@ -38,7 +38,6 @@ switch ($action) {
'confirm'
);
}
break;
}

@ -2,7 +2,6 @@
/* For licensing terms, see /license.txt */
// resetting the course id
$cidReset = true;
require_once __DIR__.'/../inc/global.inc.php';

@ -9,7 +9,6 @@
$cidReset = true;
require_once __DIR__.'/../inc/global.inc.php';
// Access restrictions
api_protect_admin_script();
$pluginName = $_GET['name'];
@ -82,6 +81,13 @@ if (isset($form)) {
1
);
}
Event::addEvent(
LOG_PLUGIN_CHANGE,
LOG_PLUGIN_SETTINGS_CHANGE,
$pluginName,
api_get_utc_datetime(),
$user_id
);
/** @var \Plugin $objPlugin */
$objPlugin = $pluginInfo['plugin_class']::create();

@ -17,7 +17,15 @@ $interbreadcrumb[] = ['url' => 'index.php', 'name' => get_lang('Administration')
set_time_limit(0);
$course_list = CourseManager::get_courses_list();
$course_list = CourseManager::get_courses_list(
0,
0,
1,
'ASC',
-1,
'',
api_get_current_access_url_id()
);
$formSent = null;
$courses = $selected_courses = [];

@ -9,9 +9,7 @@
$cidReset = true;
require_once __DIR__.'/../inc/global.inc.php';
$this_section = SECTION_PLATFORM_ADMIN;
api_protect_admin_script();
$sessionId = isset($_GET['session_id']) ? $_GET['session_id'] : null;
/**

@ -10,8 +10,6 @@
*
* @author Patrick Cool, main author
* @author Roan EMbrechts, code cleaning
*
* @since Dokeos 1.6
*/
// we are in the admin area so we do not need a course id

@ -1,4 +1,5 @@
<?php
/* For licensing terms, see /license.txt */
$cidReset = true;

@ -1,4 +1,5 @@
<?php
/* For licensing terms, see /license.txt */
use ChamiloSession as Session;
@ -10,7 +11,7 @@ $this_section = SECTION_PLATFORM_ADMIN;
api_protect_admin_script(true);
$user_id = isset($_GET['user_id']) ? intval($_GET['user_id']) : intval($_POST['user_id']);
$user_id = isset($_GET['user_id']) ? (int) $_GET['user_id'] : (int) $_POST['user_id'];
api_protect_super_admin($user_id, null, true);
$is_platform_admin = api_is_platform_admin() ? 1 : 0;
$userInfo = api_get_user_info($user_id);

@ -1,4 +1,5 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Entity\UserRelUser;
@ -606,7 +607,6 @@ if (isset($_GET['action'])) {
}
Display::display_header($tool_name);
echo Display::toolbarAction('toolbar-user-information', [implode(PHP_EOL, $actions)]);
$fullUrlBig = UserManager::getUserPicture(
@ -662,7 +662,6 @@ if (DRH == $user['status']) {
if ($usersAssigned) {
echo Display::page_subheader(get_lang('List of users assigned to Human Resources manager'));
echo '<div class="row">';
foreach ($usersAssigned as $userAssigned) {
$userAssigned = api_get_user_info($userAssigned['user_id']);
$userPicture = isset($userAssigned['avatar_medium']) ? $userAssigned['avatar_medium'] : $userAssigned['avatar'];
@ -702,7 +701,6 @@ echo Tracking::displayUserSkills(
0,
0
);
if (api_get_configuration_value('allow_career_users')) {
$careers = UserManager::getUserCareers($userId);
if (!empty($careers)) {

@ -1,4 +1,5 @@
<?php
/* For licensing terms, see /license.txt */
use ChamiloSession as Session;
@ -47,7 +48,6 @@ if (isset($_GET['user_id']) && 'login_as' == $action) {
}
api_protect_admin_script(true);
trimVariables();
$url = api_get_path(WEB_AJAX_PATH).'course.ajax.php?a=get_user_courses';
@ -55,6 +55,7 @@ $urlSession = api_get_path(WEB_AJAX_PATH).'session.ajax.php?a=get_user_sessions'
$extraField = new ExtraField('user');
$variables = $extraField->get_all_extra_field_by_type(ExtraField::FIELD_TYPE_TAG);
$variablesSelect = $extraField->get_all_extra_field_by_type(ExtraField::FIELD_TYPE_SELECT);
if (!empty($variablesSelect)) {
$variables = array_merge($variables, $variablesSelect);
}
@ -214,6 +215,9 @@ function prepare_user_sql_query($getCount)
$user_table = Database::get_main_table(TABLE_MAIN_USER);
$admin_table = Database::get_main_table(TABLE_MAIN_ADMIN);
$isMultipleUrl = (api_is_platform_admin() || api_is_session_admin()) && api_get_multiple_access_url();
$urlId = api_get_current_access_url_id();
if ($getCount) {
$sql .= "SELECT COUNT(u.id) AS total_number_of_items FROM $user_table u";
} else {
@ -238,12 +242,19 @@ function prepare_user_sql_query($getCount)
}
// adding the filter to see the user's only of the current access_url
if ((api_is_platform_admin() || api_is_session_admin()) && api_get_multiple_access_url()) {
if ($isMultipleUrl) {
$access_url_rel_user_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
$sql .= " INNER JOIN $access_url_rel_user_table url_rel_user
ON (u.id=url_rel_user.user_id)";
}
$classId = isset($_REQUEST['class_id']) && !empty($_REQUEST['class_id']) ? (int) $_REQUEST['class_id'] : 0;
if ($classId) {
$userGroupTable = Database::get_main_table(TABLE_USERGROUP_REL_USER);
$sql .= " INNER JOIN $userGroupTable ug ON (ug.user_id = u.id)";
}
$keywordList = [
'keyword_firstname',
'keyword_lastname',
@ -270,13 +281,6 @@ function prepare_user_sql_query($getCount)
$keywordListValues = [];
}
/*
// This block is never executed because $keyword_extra_data never exists
if (isset($keyword_extra_data) && !empty($keyword_extra_data)) {
$extra_info = UserManager::get_extra_field_information_by_name($keyword_extra_data);
$field_id = $extra_info['id'];
$sql.= " INNER JOIN user_field_values ufv ON u.id=ufv.user_id AND ufv.field_id=$field_id ";
} */
if (isset($_GET['keyword']) && !empty($_GET['keyword'])) {
$keywordFiltered = Database::escape_string("%".$_GET['keyword']."%");
$sql .= " WHERE (
@ -294,37 +298,44 @@ function prepare_user_sql_query($getCount)
$keyword_admin = '';
if (isset($keywordListValues['keyword_status']) &&
PLATFORM_ADMIN == $keywordListValues['keyword_status']
$keywordListValues['keyword_status'] == PLATFORM_ADMIN
) {
$query_admin_table = " , $admin_table a ";
$keyword_admin = ' AND a.user_id = u.id ';
$keywordListValues['keyword_status'] = '%';
$keywordListValues['keyword_status'] = '';
}
if ($keywordListValues['keyword_status'] === '%') {
$keywordListValues['keyword_status'] = '';
}
$keyword_extra_value = '';
$sql .= " $query_admin_table
WHERE ( 1 = 1 ";
if (!empty($keywordListValues['keyword_firstname'])) {
$sql .= "AND u.firstname LIKE '".Database::escape_string("%".$keywordListValues['keyword_firstname']."%")."'";
}
// This block is never executed because $keyword_extra_data never exists
/*
if (isset($keyword_extra_data) && !empty($keyword_extra_data) &&
!empty($keyword_extra_data_text)) {
$keyword_extra_value = " AND ufv.field_value LIKE '%".trim($keyword_extra_data_text)."%' ";
if (!empty($keywordListValues['keyword_lastname'])) {
$sql .= "AND u.lastname LIKE '".Database::escape_string("%".$keywordListValues['keyword_lastname']."%")."'";
}
*/
$sql .= " $query_admin_table
WHERE (
u.firstname LIKE '".Database::escape_string("%".$keywordListValues['keyword_firstname']."%")."' AND
u.lastname LIKE '".Database::escape_string("%".$keywordListValues['keyword_lastname']."%")."' AND
u.username LIKE '".Database::escape_string("%".$keywordListValues['keyword_username']."%")."' AND
u.email LIKE '".Database::escape_string("%".$keywordListValues['keyword_email']."%")."' AND
u.status LIKE '".Database::escape_string($keywordListValues['keyword_status'])."' ";
if (!empty($keywordListValues['keyword_username'])) {
$sql .= "AND u.username LIKE '".Database::escape_string("%".$keywordListValues['keyword_username']."%")."'";
}
if (!empty($keywordListValues['keyword_email'])) {
$sql .= "AND u.email LIKE '".Database::escape_string("%".$keywordListValues['keyword_email']."%")."'";
}
if (!empty($keywordListValues['keyword_status'])) {
$sql .= "AND u.status = '".Database::escape_string($keywordListValues['keyword_status'])."'";
}
if (!empty($keywordListValues['keyword_officialcode'])) {
$sql .= " AND u.official_code LIKE '".Database::escape_string("%".$keywordListValues['keyword_officialcode']."%")."' ";
}
$sql .= "
$keyword_admin
$keyword_extra_value
";
$sql .= " $keyword_admin $keyword_extra_value ";
if (isset($keywordListValues['keyword_active']) &&
!isset($keywordListValues['keyword_inactive'])
@ -338,12 +349,36 @@ function prepare_user_sql_query($getCount)
$sql .= ' ) ';
}
if ($classId) {
$sql .= " AND ug.usergroup_id = $classId";
}
$preventSessionAdminsToManageAllUsers = api_get_setting('prevent_session_admins_to_manage_all_users');
if (api_is_session_admin() && 'true' === $preventSessionAdminsToManageAllUsers) {
$sql .= ' AND u.creator_id = '.$currentUserId;
$extraConditions = '';
if (api_is_session_admin() && $preventSessionAdminsToManageAllUsers === 'true') {
$extraConditions .= ' AND u.creator_id = '.api_get_user_id();
}
// adding the filter to see the user's only of the current access_url
if ($isMultipleUrl) {
$extraConditions .= ' AND url_rel_user.access_url_id = '.$urlId;
}
$sql .= $extraConditions;
$variables = Session::read('variables_to_show', []);
$extraFields = api_get_configuration_value('user_search_on_extra_fields');
if (!empty($extraFields) && isset($extraFields['extra_fields']) && isset($_GET['keyword'])) {
$extraFieldList = $extraFields['extra_fields'];
if (!empty($extraFieldList)) {
foreach ($extraFieldList as $variable) {
$_GET['extra_'.$variable] = Security::remove_XSS($_GET['keyword']);
}
}
$variables = array_merge($extraFieldList, $variables);
}
if (!empty($variables)) {
$extraField = new ExtraField('user');
$extraFieldResult = [];
@ -360,9 +395,7 @@ function prepare_user_sql_query($getCount)
continue;
}
$info = $extraField->get_handler_field_info_by_field_variable(
$variable
);
$info = $extraField->get_handler_field_info_by_field_variable($variable);
if (empty($info)) {
continue;
@ -372,42 +405,30 @@ function prepare_user_sql_query($getCount)
if (empty($value)) {
continue;
}
if (ExtraField::FIELD_TYPE_TAG == $info['field_type']) {
$result = $extraField->getAllUserPerTag(
$info['id'],
$value
);
$result = empty($result) ? [] : array_column(
$result,
'user_id'
);
if ($info['field_type'] == ExtraField::FIELD_TYPE_TAG) {
$result = $extraField->getAllUserPerTag($info['id'], $value);
$result = empty($result) ? [] : array_column($result, 'user_id');
} else {
$result = UserManager::get_extra_user_data_by_value(
$variable,
$value
);
$result = UserManager::get_extra_user_data_by_value($variable, $value, true);
}
$extraFieldHasData[] = true;
if (!empty($result)) {
$extraFieldResult = array_merge(
$extraFieldResult,
$result
);
$extraFieldResult = array_merge($extraFieldResult, $result);
}
}
}
}
if (!empty($extraFieldHasData)) {
$sql .= " AND (u.id IN ('".implode("','", $extraFieldResult)."')) ";
}
$condition = ' AND ';
// If simple search then use "OR"
if (isset($_GET['keyword']) && !empty($_GET['keyword'])) {
$condition = ' OR ';
}
// adding the filter to see the user's only of the current access_url
if ((api_is_platform_admin() || api_is_session_admin()) &&
api_get_multiple_access_url()
) {
$sql .= ' AND url_rel_user.access_url_id = '.api_get_current_access_url_id();
if (!empty($extraFieldHasData) && !empty($extraFieldResult)) {
$sql .= " $condition (u.id IN ('".implode("','", $extraFieldResult)."') $extraConditions ) ";
}
}
return $sql;
@ -1014,8 +1035,12 @@ if (isset($_GET['keyword'])) {
$parameters['keyword_email'] = Security::remove_XSS($_GET['keyword_email']);
$parameters['keyword_officialcode'] = Security::remove_XSS($_GET['keyword_officialcode']);
$parameters['keyword_status'] = Security::remove_XSS($_GET['keyword_status']);
$parameters['keyword_active'] = Security::remove_XSS($_GET['keyword_active']);
$parameters['keyword_inactive'] = Security::remove_XSS($_GET['keyword_inactive']);
if (isset($_GET['keyword_active'])) {
$parameters['keyword_active'] = Security::remove_XSS($_GET['keyword_active']);
}
if (isset($_GET['keyword_inactive'])) {
$parameters['keyword_inactive'] = Security::remove_XSS($_GET['keyword_inactive']);
}
}
// Create a sortable table with user-data
$parameters['sec_token'] = Security::get_token();

@ -89,6 +89,8 @@ $logInfo = [
];
Event::registerLog($logInfo);
$announcementAttachmentIsDisabled = api_get_configuration_value('disable_announcement_attachment');
switch ($action) {
case 'move':
if (!$allowToEdit) {
@ -136,7 +138,6 @@ switch ($action) {
$sql = "UPDATE $tbl_announcement SET display_order = '$thisAnnouncementOrder'
WHERE c_id = $courseId AND id = $nextAnnouncementId";
Database::query($sql);
break;
}
// STEP 1 : FIND THE ORDER OF THE ANNOUNCEMENT

@ -233,6 +233,9 @@ if ($allowExport) {
if (0 !== strcmp($backpack, $configBackpack)) {
$backpack = $configBackpack;
if (substr($backpack, -1) !== '/') {
$backpack .= '/';
}
}
$htmlHeadXtra[] = '<script src="'.$backpack.'issuer.js"></script>';

@ -220,6 +220,9 @@ foreach ($userSkills as $index => $skillIssue) {
if (0 !== strcmp($backpack, $configBackpack)) {
$backpack = $configBackpack;
if (substr($backpack, -1) !== '/') {
$backpack .= '/';
}
}
$htmlHeadXtra[] = '<script src="'.$backpack.'issuer.js"></script>';

@ -88,21 +88,21 @@ $tpl->assign('show_action', in_array($type, ['course', 'session']));
$tpl->assign('agenda_actions', $actions);
$tpl->assign('is_allowed_to_edit', api_is_allowed_to_edit());
if ('change_visibility' === $action && api_is_allowed_to_edit()) {
if (api_is_allowed_to_edit()) {
if ($action == 'change_visibility') {
$courseInfo = api_get_course_info();
$courseCondition = '';
// This happens when list agenda is not inside a course
if (!empty($courseInfo) && ('course' === $type || 'session' === $type)) {
if (($type == 'course' || $type == 'session' && !empty($courseInfo))) {
// For course and session event types
// Just needs course ID
$courseCondition = '&'.api_get_cidreq();
$agenda->changeVisibility($_GET['id'], $_GET['visibility'], $courseInfo);
} else {
$courseCondition = '&'.api_get_cidreq();
}
header('Location: '.api_get_self().'?type='.$agenda->type.$courseCondition);
exit;
}
$agenda->changeVisibility($_GET['id'], $_GET['visibility'], $courseInfo);
Display::addFlash(Display::return_message(get_lang('Updated')));
header('Location: '.api_get_self().'?type='.$agenda->type.$courseCondition);
exit;
}
$templateName = $tpl->get_template('agenda/event_list.tpl');

@ -91,7 +91,7 @@ class Dropbox_Work
public function createNewWork($uploader_id, $title, $description, $author, $filename, $filesize)
{
// Fill in the properties
$this->uploader_id = intval($uploader_id);
$this->uploader_id = (int) $uploader_id;
$this->filename = $filename;
$this->filesize = $filesize;
$this->title = $title;
@ -103,8 +103,8 @@ class Dropbox_Work
// Check if object exists already. If it does, the old object is used
// with updated information (authors, description, upload_date)
$this->isOldWork = false;
$sql = "SELECT id, upload_date
FROM ".Database::get_course_table(TABLE_DROPBOX_FILE)."
$sql = 'SELECT id, upload_date
FROM '.Database::get_course_table(TABLE_DROPBOX_FILE)."
WHERE
c_id = $course_id AND
filename = '".Database::escape_string($this->filename)."'";
@ -150,21 +150,21 @@ class Dropbox_Work
$this->id = Database::insert(Database::get_course_table(TABLE_DROPBOX_FILE), $params);
if ($this->id) {
$sql = "UPDATE ".Database::get_course_table(TABLE_DROPBOX_FILE)." SET id = iid
$sql = 'UPDATE '.Database::get_course_table(TABLE_DROPBOX_FILE)." SET id = iid
WHERE iid = {$this->id}";
Database::query($sql);
}
}
$sql = "SELECT count(file_id) as count
FROM ".Database::get_course_table(TABLE_DROPBOX_PERSON)."
WHERE c_id = $course_id AND file_id = ".intval($this->id)." AND user_id = ".$this->uploader_id;
$sql = 'SELECT count(file_id) as count
FROM '.Database::get_course_table(TABLE_DROPBOX_PERSON)."
WHERE c_id = $course_id AND file_id = ".intval($this->id).' AND user_id = '.$this->uploader_id;
$result = Database::query($sql);
$row = Database::fetch_array($result);
if (0 == $row['count']) {
// Insert entries into person table
$sql = "INSERT INTO ".Database::get_course_table(TABLE_DROPBOX_PERSON)." (c_id, file_id, user_id)
VALUES ($course_id, ".intval($this->id)." , ".intval($this->uploader_id).")";
$sql = 'INSERT INTO '.Database::get_course_table(TABLE_DROPBOX_PERSON)." (c_id, file_id, user_id)
VALUES ($course_id, ".intval($this->id).' , '.intval($this->uploader_id).')';
Database::query($sql);
}
}
@ -391,7 +391,7 @@ class Dropbox_SentWork extends Dropbox_Work
*/
public function createExistingSentWork($id)
{
$id = intval($id);
$id = (int) $id;
$course_id = api_get_course_int_id();
// Call constructor of Dropbox_Work object
@ -464,10 +464,11 @@ class Dropbox_Person
$sql = "SELECT DISTINCT r.file_id, r.cat_id
FROM $post_tbl r
INNER JOIN $person_tbl p
ON (r.file_id = p.file_id AND r.c_id = $course_id AND p.c_id = $course_id )
ON (r.file_id = p.file_id AND r.c_id = p.c_id)
WHERE
p.user_id = ".intval($this->userId)." AND
r.dest_user_id = ".intval($this->userId)." $condition_session ";
r.c_id = $course_id AND
p.user_id = ".intval($this->userId).' AND
r.dest_user_id = '.intval($this->userId)." $condition_session ";
$result = Database::query($sql);
while ($res = Database::fetch_array($result)) {
@ -479,10 +480,11 @@ class Dropbox_Person
$sql = "SELECT DISTINCT f.id
FROM $file_tbl f
INNER JOIN $person_tbl p
ON (f.id = p.file_id AND f.c_id = $course_id AND p.c_id = $course_id)
ON (f.id = p.file_id AND f.c_id = p.c_id)
WHERE
f.uploader_id = ".intval($this->userId)." AND
p.user_id = ".intval($this->userId)."
f.c_id = $course_id AND
f.uploader_id = ".intval($this->userId).' AND
p.user_id = '.intval($this->userId)."
$condition_session
";
$result = Database::query($sql);
@ -542,7 +544,7 @@ class Dropbox_Person
public function deleteReceivedWork($id)
{
$course_id = api_get_course_int_id();
$id = intval($id);
$id = (int) $id;
// index check
$found = false;
@ -593,7 +595,7 @@ class Dropbox_Person
{
$course_id = api_get_course_int_id();
$id = intval($id);
$id = (int) $id;
// index check
$found = false;

@ -1,4 +1,5 @@
<?php
/* For licensing terms, see /license.txt */
use ChamiloSession as Session;

@ -1,4 +1,5 @@
<?php
/* For licensing terms, see /license.txt */
require_once 'dropbox_init.inc.php';

@ -152,6 +152,33 @@ class Answer
$this->nbrAnswers = $i - 1;
}
/**
* Get answers already added to question.
*
* @return array
*/
public function getAnswers()
{
$table = Database::get_course_table(TABLE_QUIZ_ANSWER);
$questionId = $this->questionId;
$sql = "SELECT * FROM $table
WHERE c_id = {$this->course_id}
AND question_id = $questionId
ORDER BY position";
$result = Database::query($sql);
$answers = [];
// while a record is found
while ($answer = Database::fetch_assoc($result)) {
$answers[] = $answer;
}
return $answers;
}
/**
* @param int $id
*
@ -1027,12 +1054,13 @@ class Answer
*/
public function getJs()
{
//if ($this->questionId == 2)
return "<script>
jsPlumb.ready(function() {
if ($('#drag{$this->questionId}_question').length > 0) {
MatchingDraggable.init('{$this->questionId}');
}
$(window).on('load', function() {
jsPlumb.ready(function() {
if ($('#drag{$this->questionId}_question').length > 0) {
MatchingDraggable.init('{$this->questionId}');
}
});
});
</script>";
}

@ -28,7 +28,6 @@ class CalculatedAnswer extends Question
public function createAnswersForm($form)
{
$defaults = [];
//$defaults['answer'] = get_lang('<table cellspacing="0" cellpadding="10" border="1" width="720" style="" height:=""> <tbody> <tr> <td colspan="2"> <h3>Example fill the form activity : calculate the Body Mass Index</h3> </td> </tr> <tr> <td style="text-align: right;"><strong>Age</strong></td> <td width="75%" style="">[25] years old</td> </tr> <tr> <td style="text-align: right;"><strong>Sex</strong></td> <td style="" text-align:="">[M] (M or F)</td> </tr> <tr> <td style="text-align: right;"><strong>Weight</strong></td> <td style="" text-align:="">95 Kg</td> </tr> <tr> <td style="vertical-align: top; text-align: right;"><strong>Height</strong></td> <td style="vertical-align: top;">1.81 m</td> </tr> <tr> <td style="vertical-align: top; text-align: right;"><strong>Body Mass Index</strong></td> <td style="vertical-align: top;">[29] BMI =Weight/Size<sup>2</sup> (Cf.<a href="http://en.wikipedia.org/wiki/Body_mass_index" onclick="window.open(this.href,'','resizable=yes,location=yes,menubar=no,scrollbars=yes,status=yes,toolbar=no,fullscreen=no,dependent=no,width=800,height=600,left=40,top=40,status'); return false"> Wikipedia article</a>)</td> </tr> </tbody></table>');
$defaults['answer'] = get_lang('DefaultTextInBlanks');
if (!empty($this->id)) {
$objAnswer = new Answer($this->id);

@ -29,6 +29,56 @@ $obj = new ExerciseCategoryManager();
$check = Security::check_token('request');
$token = Security::get_token();
//Add the JS needed to use the jqgrid
$htmlHeadXtra[] = api_get_jqgrid_js();
//The order is important you need to check the the $column variable in the model.ajax.php file
$columns = [
get_lang('Name'),
get_lang('Actions'),
];
// Column config
$column_model = [
[
'name' => 'name',
'index' => 'name',
'width' => '140',
'align' => 'left',
],
[
'name' => 'actions',
'index' => 'actions',
'width' => '40',
'align' => 'left',
'formatter' => 'action_formatter',
'sortable' => 'false',
],
];
// Autowidth
$extra_params['autowidth'] = 'true';
// height auto
$extra_params['height'] = 'auto';
$action_links = $obj->getJqgridActionLinks($token);
$htmlHeadXtra[] = '<script>
$(function() {
// grid definition see the $obj->display() function
'.Display::grid_js(
'categories',
$url,
$columns,
$column_model,
$extra_params,
[],
$action_links,
true
).'
});
</script>';
$url = api_get_self().'?'.api_get_cidreq();
switch ($action) {

@ -1841,6 +1841,7 @@ class Exercise
public function delete()
{
$limitTeacherAccess = api_get_configuration_value('limit_exercise_teacher_access');
if ($limitTeacherAccess && !api_is_platform_admin()) {
return false;
}
@ -3157,6 +3158,7 @@ class Exercise
if (EXERCISE_FEEDBACK_TYPE_POPUP === $this->getFeedbackType()) {
//$params['data-block-div-after-closing'] = "question_div_$question_id";
$params['data-block-closing'] = 'true';
$params['class'] .= ' no-header ';
}
$html .= Display::url(
@ -3405,7 +3407,7 @@ class Exercise
$('#exercise_clock_warning').epiclock({
mode: $.epiclock.modes.countdown,
offset: {seconds: time_left},
format: 'x:i:s',
format: 'x:C:s',
renderer: 'minute'
}).bind('timer', function () {
onExpiredTimeExercise();
@ -3611,7 +3613,7 @@ class Exercise
$answerDestination = null;
$userAnsweredQuestion = false;
$correctAnswerId = null;
$correctAnswerId = [];
for ($answerId = 1; $answerId <= $nbrAnswers; $answerId++) {
$answer = $objAnswerTmp->selectAnswer($answerId);
$answerComment = $objAnswerTmp->selectComment($answerId);
@ -3649,14 +3651,14 @@ class Exercise
if ($studentChoice) {
$questionScore += $answerWeighting;
$answerDestination = $objAnswerTmp->selectDestination($answerId);
$correctAnswerId = $answerId;
$correctAnswerId[] = $answerId;
}
} else {
$studentChoice = $choice == $answerAutoId ? 1 : 0;
if ($studentChoice) {
$questionScore += $answerWeighting;
$answerDestination = $objAnswerTmp->selectDestination($answerId);
$correctAnswerId = $answerId;
$correctAnswerId[] = $answerId;
}
}
@ -3680,6 +3682,7 @@ class Exercise
$studentChoice = isset($choice[$answerAutoId]) ? $choice[$answerAutoId] : null;
if (!empty($studentChoice)) {
$correctAnswerId[] = $answerAutoId;
if ($studentChoice == $answerCorrect) {
$questionScore += $true_score;
} else {
@ -3771,6 +3774,7 @@ class Exercise
$real_answers[$answerId] = (bool) $studentChoice;
if (isset($studentChoice)) {
$correctAnswerId[] = $answerAutoId;
$questionScore += $answerWeighting;
}
}
@ -4098,48 +4102,55 @@ class Exercise
$studentAnswer = trim($listStudentAnswerTemp[$i]);
$studentAnswerToShow = $studentAnswer;
if (empty($studentAnswer)) {
continue;
}
if ($debug) {
error_log("Student answer: $i");
error_log($studentAnswer);
}
if (!$from_database) {
$studentAnswer = FillBlanks::clearStudentAnswer($studentAnswer);
if ($debug) {
error_log("Student answer cleaned:");
error_log($studentAnswer);
}
}
$found = false;
for ($j = 0; $j < count($listTeacherAnswerTemp); $j++) {
$correctAnswer = $listTeacherAnswerTemp[$j];
$type = FillBlanks::getFillTheBlankAnswerType($correctAnswer);
if (FillBlanks::FILL_THE_BLANK_MENU == $type) {
$listMenu = FillBlanks::getFillTheBlankMenuAnswers($correctAnswer, false);
if (!empty($studentAnswer)) {
foreach ($listMenu as $key => $item) {
if ($key == $correctAnswer) {
$studentAnswerToShow = $item;
break;
}
}
}
}
if (!$found) {
if (FillBlanks::isStudentAnswerGood(
$studentAnswer,
$correctAnswer,
$from_database
)
) {
)) {
$questionScore += $answerWeighting[$i];
$totalScore += $answerWeighting[$i];
$listTeacherAnswerTemp[$j] = '';
$found = true;
}
}
$type = FillBlanks::getFillTheBlankAnswerType($correctAnswer);
if ($type == FillBlanks::FILL_THE_BLANK_MENU) {
$listMenu = FillBlanks::getFillTheBlankMenuAnswers($correctAnswer, false);
if (!empty($studentAnswer)) {
foreach ($listMenu as $key => $item) {
if ($key == $correctAnswer) {
$studentAnswerToShow = $item;
break;
}
}
}
}
}
$listCorrectAnswers['student_answer'][$i] = $studentAnswerToShow;
if (!$found) {
$listCorrectAnswers['student_score'][$i] = 0;
} else {
$listCorrectAnswers['student_score'][$i] = 1;
}
$listCorrectAnswers['student_score'][$i] = $found ? 1 : 0;
}
}
$answer = FillBlanks::getAnswerInStudentAttempt($listCorrectAnswers);
@ -4575,6 +4586,7 @@ class Exercise
if (isset($choice[$answerAutoId]) &&
$answerCorrect == $choice[$answerAutoId]
) {
$correctAnswerId[] = $answerAutoId;
$questionScore += $answerWeighting;
$totalScore += $answerWeighting;
$user_answer = Display::span($answerMatching[$choice[$answerAutoId]]);
@ -4749,6 +4761,7 @@ class Exercise
$user_array = substr($user_array, 0, -1) ?: '';
} else {
if (!empty($studentChoice)) {
$correctAnswerId[] = $answerAutoId;
$newquestionList[] = $questionId;
}
@ -6189,6 +6202,9 @@ class Exercise
$data['title'] = PHP_EOL.$this->exercise.' : '.get_lang('Result');
}
$data['number_of_answers'] = count(explode(',', $trackExerciseInfo['data_tracking']));
$data['number_of_answers_saved'] = $this->countUserAnswersSavedInExercise($trackExerciseInfo['exe_id']);
$tpl = new Template(null, false, false, false, false, false, false);
$tpl->assign('data', $data);
$layoutTemplate = $tpl->get_template('exercise/partials/result_exercise.tpl');
@ -7421,7 +7437,6 @@ class Exercise
var params = '.$params.';
$.ajax({
type: "GET",
async: false,
data: params,
url: "'.$url.'",
success: function(return_value) {
@ -8146,7 +8161,7 @@ class Exercise
* @param string $class
* @param string $scoreLabel
* @param string $result
* @param $array
* @param array
*
* @return string
*/
@ -8347,7 +8362,7 @@ class Exercise
$lpId = null;
if (!empty($this->lpList)) {
// Taking only the first LP
$lpId = current($this->lpList);
$lpId = $this->getLpBySession($sessionId);
$lpId = $lpId['lp_id'];
}
@ -8978,10 +8993,226 @@ class Exercise
Session::erase('hotspot_delineation_result');
}
/**
* Get the first LP found matching the session ID.
*
* @param int $sessionId
*
* @return array
*/
public function getLpBySession($sessionId)
{
if (!empty($this->lpList)) {
$sessionId = (int) $sessionId;
foreach ($this->lpList as $lp) {
if ((int) $lp['session_id'] == $sessionId) {
return $lp;
}
}
}
return [
'lp_id' => 0,
'max_score' => 0,
'session_id' => 0,
];
}
public static function saveExerciseInLp($safe_item_id, $safe_exe_id)
{
$lp = Session::read('oLP');
$safe_exe_id = (int) $safe_exe_id;
$safe_item_id = (int) $safe_item_id;
if (empty($lp) || empty($safe_exe_id) || empty($safe_item_id)) {
return false;
}
$viewId = $lp->get_view_id();
$course_id = api_get_course_int_id();
$userId = (int) api_get_user_id();
$viewId = (int) $viewId;
$TBL_TRACK_EXERCICES = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
$TBL_LP_ITEM_VIEW = Database::get_course_table(TABLE_LP_ITEM_VIEW);
$TBL_LP_ITEM = Database::get_course_table(TABLE_LP_ITEM);
$sql = "SELECT start_date, exe_date, exe_result, exe_weighting, exe_exo_id, exe_duration
FROM $TBL_TRACK_EXERCICES
WHERE exe_id = $safe_exe_id AND exe_user_id = $userId";
$res = Database::query($sql);
$row_dates = Database::fetch_array($res);
if (empty($row_dates)) {
return false;
}
$duration = (int) $row_dates['exe_duration'];
$score = (float) $row_dates['exe_result'];
$max_score = (float) $row_dates['exe_weighting'];
$sql = "UPDATE $TBL_LP_ITEM SET
max_score = '$max_score'
WHERE iid = $safe_item_id";
Database::query($sql);
$sql = "SELECT id FROM $TBL_LP_ITEM_VIEW
WHERE
c_id = $course_id AND
lp_item_id = $safe_item_id AND
lp_view_id = $viewId
ORDER BY id DESC
LIMIT 1";
$res_last_attempt = Database::query($sql);
if (Database::num_rows($res_last_attempt) && !api_is_invitee()) {
$row_last_attempt = Database::fetch_row($res_last_attempt);
$lp_item_view_id = $row_last_attempt[0];
$exercise = new Exercise($course_id);
$exercise->read($row_dates['exe_exo_id']);
$status = 'completed';
if (!empty($exercise->pass_percentage)) {
$status = 'failed';
$success = ExerciseLib::isSuccessExerciseResult(
$score,
$max_score,
$exercise->pass_percentage
);
if ($success) {
$status = 'passed';
}
}
$sql = "UPDATE $TBL_LP_ITEM_VIEW SET
status = '$status',
score = $score,
total_time = $duration
WHERE iid = $lp_item_view_id";
Database::query($sql);
$sql = "UPDATE $TBL_TRACK_EXERCICES SET
orig_lp_item_view_id = $lp_item_view_id
WHERE exe_id = ".$safe_exe_id;
Database::query($sql);
}
}
/**
* Get the user answers saved in exercise.
*
* @param int $attemptId
*
* @return array
*/
public function getUserAnswersSavedInExercise($attemptId)
{
$exerciseResult = [];
$attemptList = Event::getAllExerciseEventByExeId($attemptId);
foreach ($attemptList as $questionId => $options) {
foreach ($options as $option) {
$question = Question::read($option['question_id']);
switch ($question->type) {
case FILL_IN_BLANKS:
$option['answer'] = $this->fill_in_blank_answer_to_string($option['answer']);
break;
}
if (!empty($option['answer'])) {
$exerciseResult[] = $questionId;
break;
}
}
}
return $exerciseResult;
}
/**
* Get the number of user answers saved in exercise.
*
* @param int $attemptId
*
* @return int
*/
public function countUserAnswersSavedInExercise($attemptId)
{
$answers = $this->getUserAnswersSavedInExercise($attemptId);
return count($answers);
}
public static function allowAction($action)
{
if (api_is_platform_admin()) {
return true;
}
$limitTeacherAccess = api_get_configuration_value('limit_exercise_teacher_access');
$disableClean = api_get_configuration_value('disable_clean_exercise_results_for_teachers');
switch ($action) {
case 'delete':
if (api_is_allowed_to_edit(null, true)) {
if ($limitTeacherAccess) {
return false;
}
return true;
}
break;
case 'clean_results':
if (api_is_allowed_to_edit(null, true)) {
if ($limitTeacherAccess) {
return false;
}
if ($disableClean) {
return false;
}
return true;
}
break;
}
return false;
}
/**
* Get number of questions in exercise by user attempt.
*
* @return int
*/
private function countQuestionsInExercise()
{
$lpId = isset($_REQUEST['learnpath_id']) ? (int) $_REQUEST['learnpath_id'] : 0;
$lpItemId = isset($_REQUEST['learnpath_item_id']) ? (int) $_REQUEST['learnpath_item_id'] : 0;
$lpItemViewId = isset($_REQUEST['learnpath_item_view_id']) ? (int) $_REQUEST['learnpath_item_view_id'] : 0;
$trackInfo = $this->get_stat_track_exercise_info($lpId, $lpItemId, $lpItemViewId);
if (!empty($trackInfo)) {
$questionIds = explode(',', $trackInfo['data_tracking']);
return count($questionIds);
}
return $this->getQuestionCount();
}
/**
* Gets the question list ordered by the question_order setting (drag and drop).
*
* @param bool $adminView optional
* @param bool $adminView Optional.
*
* @return array
*/

@ -25,6 +25,9 @@ api_protect_course_script(true);
$limitTeacherAccess = api_get_configuration_value('limit_exercise_teacher_access');
$allowDelete = Exercise::allowAction('delete');
$allowClean = Exercise::allowAction('clean_results');
$check = Security::get_existing_token('get');
$currentUrl = api_get_self().'?'.api_get_cidreq();
@ -125,11 +128,13 @@ if ($is_allowedToEdit && !empty($action)) {
break;
case 'delete':
$result = $objExerciseTmp->delete();
if ($result) {
Display::addFlash(Display::return_message(get_lang('Deleted'), 'confirmation'));
// deletes an exercise
if ($allowDelete) {
$result = $objExerciseTmp->delete();
if ($result) {
Display::addFlash(Display::return_message(get_lang('Deleted'), 'confirmation'));
}
}
break;
case 'enable':
if ($limitTeacherAccess && !api_is_platform_admin()) {
@ -165,7 +170,7 @@ if ($is_allowedToEdit && !empty($action)) {
break;
case 'clean_results':
if ($limitTeacherAccess && !api_is_platform_admin()) {
if (false === $allowClean) {
// Teacher change exercise
break;
}
@ -350,21 +355,24 @@ if ($is_allowedToEdit && 'learnpath' !== $origin) {
$actionsLeft .= '<a href="'.api_get_path(WEB_CODE_PATH).'exercise/upload_exercise.php?'.api_get_cidreq().'">'.
Display::return_icon('import_excel.png', get_lang('Import quiz from Excel'), '', ICON_SIZE_MEDIUM).'</a>';
$cleanAll = Display::url(
Display::return_icon(
'clean_all.png',
get_lang('Are you sure to delete all test\'s results ?'),
'',
ICON_SIZE_MEDIUM
),
'#',
[
'data-item-question' => addslashes(get_lang('Clear all learners results for every exercises ?')),
'data-href' => api_get_path(WEB_CODE_PATH).'exercise/exercise.php?'.api_get_cidreq().'&action=clean_all_test&sec_token='.$token,
'data-toggle' => 'modal',
'data-target' => '#confirm-delete',
]
);
$cleanAll = null;
if ($allowClean) {
$cleanAll = Display::url(
Display::return_icon(
'clean_all.png',
get_lang('Are you sure to delete all test\'s results ?'),
'',
ICON_SIZE_MEDIUM
),
'#',
[
'data-item-question' => addslashes(get_lang('Clear all learners results for every exercises ?')),
'data-href' => api_get_path(WEB_CODE_PATH).'exercise/exercise.php?'.api_get_cidreq().'&action=clean_all_test&sec_token='.$token,
'data-toggle' => 'modal',
'data-target' => '#confirm-delete',
]
);
}
if ($limitTeacherAccess) {
if (api_is_platform_admin()) {
@ -409,11 +417,11 @@ if (false === api_get_configuration_value('allow_exercise_categories')) {
}
$down = Display::url($downIcon, $modifyUrl.'&action=down_category&category_id_edit='.$categoryIdItem);
$counter++;
if ($total === $counter) {
$down = Display::url(Display::return_icon('down_na.png'), '#');
}
}
echo Display::page_subheader($category->getName().$up.$down);
echo Exercise::exerciseGridResource($category->getId(), $keyword);
}

@ -12,7 +12,6 @@ use ChamiloSession as Session;
* @author Olivier Brouckaert, Julio Montoya
*/
require_once __DIR__.'/../inc/global.inc.php';
$this_section = SECTION_COURSES;
api_protect_course_script(true);

@ -170,27 +170,8 @@ echo '<script>
$attempt_list = Event::getAllExerciseEventByExeId($exe_id);
$remind_list = $exercise_stat_info['questions_to_check'];
$remind_list = explode(',', $remind_list);
$exercise_result = [];
foreach ($attempt_list as $question_id => $options) {
foreach ($options as $item) {
$question_obj = Question::read($item['question_id']);
switch ($question_obj->type) {
case FILL_IN_BLANKS:
$item['answer'] = $objExercise->fill_in_blank_answer_to_string($item['answer']);
break;
case HOT_SPOT:
break;
}
if ('0' != $item['answer'] && !empty($item['answer'])) {
$exercise_result[] = $question_id;
$exercise_result = $objExercise->getUserAnswersSavedInExercise($exe_id);
break;
}
}
}
echo Display::label(get_lang('Questions without answer'), 'danger');
echo '<div class="clear"></div><br />';

@ -28,6 +28,7 @@ if (api_is_student_boss() && !empty($filter_user)) {
}
$limitTeacherAccess = api_get_configuration_value('limit_exercise_teacher_access');
$allowClean = Exercise::allowAction('clean_results');
if ($limitTeacherAccess && !api_is_platform_admin()) {
api_not_allowed(true);
@ -303,23 +304,8 @@ if (isset($_REQUEST['comments']) &&
WHERE c_id = ".$course_id.' AND id = '.$lp_item_view_id;
Database::query($sql);
if (empty($origin)) {
header('Location: '.api_get_path(WEB_CODE_PATH).'exercise/exercise_report.php?id='.$exercise_id.'&'.api_get_cidreq());
exit;
}
if ('tracking_course' === $origin) {
//Redirect to the course detail in lp
header('Location: '.api_get_path(WEB_CODE_PATH).'exercise/exercise.php?course='.Security::remove_XSS($_GET['course']));
exit;
} else {
// Redirect to the reporting
header(
'Location: '.api_get_path(WEB_CODE_PATH).'mySpace/myStudents.php?origin='.$origin.'&student='.$student_id.'&details=true&course='.api_get_course_id(
).'&session_id='.$session_id
);
exit;
}
header('Location: '.api_get_path(WEB_CODE_PATH).'exercise/exercise_show.php?id='.$id.'&student='.$student_id.'&'.api_get_cidreq());
exit;
}
}
@ -338,36 +324,39 @@ if ($is_allowedToEdit && 'learnpath' != $origin) {
$actions .= '<a id="export_opener" href="'.api_get_self().'?export_report=1&exerciseId='.$exercise_id.'" >'.
Display::return_icon('save.png', get_lang('Export'), '', ICON_SIZE_MEDIUM).'</a>';
// clean result before a selected date icon
$actions .= Display::url(
Display::return_icon(
'clean_before_date.png',
get_lang('Clean all results before a selected date'),
'',
ICON_SIZE_MEDIUM
),
'#',
['onclick' => 'javascript:display_date_picker()']
);
// clean result before a selected date datepicker popup
$actions .= Display::span(
Display::input(
'input',
'datepicker_start',
get_lang('Select a date from the calendar'),
[
'onmouseover' => 'datepicker_input_mouseover()',
'id' => 'datepicker_start',
'onchange' => 'datepicker_input_changed()',
'readonly' => 'readonly',
]
).
Display::button(
'delete',
get_lang('Delete'),
['onclick' => 'submit_datepicker()']
),
['style' => 'display:none', 'id' => 'datepicker_span']
);
// clean result before a selected date icon
if ($allowClean) {
$actions .= Display::url(
Display::return_icon(
'clean_before_date.png',
get_lang('Clean all results before a selected date'),
'',
ICON_SIZE_MEDIUM
),
'#',
['onclick' => 'javascript:display_date_picker()']
);
// clean result before a selected date datepicker popup
$actions .= Display::span(
Display::input(
'input',
'datepicker_start',
get_lang('Select a date from the calendar'),
[
'onmouseover' => 'datepicker_input_mouseover()',
'id' => 'datepicker_start',
'onchange' => 'datepicker_input_changed()',
'readonly' => 'readonly',
]
).
Display::button(
'delete',
get_lang('Delete'),
['onclick' => 'submit_datepicker()']
),
['style' => 'display:none', 'id' => 'datepicker_span']
);
}
}
} else {
$actions .= '<a href="exercise.php">'.
@ -445,7 +434,7 @@ if (($is_allowedToEdit || $is_tutor || api_is_coach()) &&
) {
// ask for the date
$check = Security::check_token('get');
if ($check) {
if ($check && $allowClean) {
$objExerciseTmp = new Exercise();
if ($objExerciseTmp->read($exercise_id)) {
$count = $objExerciseTmp->cleanResults(
@ -594,7 +583,14 @@ if ($is_allowedToEdit || $is_tutor) {
// Column config
$column_model = [
['name' => 'firstname', 'index' => 'firstname', 'width' => '50', 'align' => 'left', 'search' => 'true'],
['name' => 'lastname', 'index' => 'lastname', 'width' => '50', 'align' => 'left', 'formatter' => 'action_formatter', 'search' => 'true'],
[
'name' => 'lastname',
'index' => 'lastname',
'width' => '50',
'align' => 'left',
'formatter' => 'action_formatter',
'search' => 'true',
],
[
'name' => 'login',
'index' => 'username',
@ -718,7 +714,6 @@ $gridJs = Display::grid_js(
for (var i in data) {
colNames[ii++] = i;
}
// capture col names
var html = "";
for (i = 0; i < mya.length; i++) {
data = $("#results").getRowData(mya[i]); // get each row

@ -195,6 +195,12 @@ ExerciseLib::displayQuestionListByAttempt(
$remainingMessage
);
//Unset session for clock time
if (!empty($learnpath_id) && $saveResults) {
// Save attempt in lp
Exercise::saveExerciseInLp($learnpath_item_id, $exe_id);
}
//Unset session for clock time
ExerciseLib::exercise_time_control_delete(
$objExercise->id,

@ -467,7 +467,6 @@ foreach ($questionList as $questionId) {
);
$questionScore = $questionResult['score'];
$totalScore += $questionResult['score'];
break;
case HOT_SPOT:
if ($show_results || $showTotalScoreAndUserChoicesInLastAttempt) {
@ -986,6 +985,7 @@ if ($isFeedbackAllowed && 'learnpath' != $origin && 'student_progress' != $origi
'exeid' => $id,
'origin' => $origin,
'details' => 'true',
'course' => Security::remove_XSS($_GET['cidReq']),
]);
$emailForm = new FormValidator('form-email', 'post', $formUrl, '', ['id' => 'form-email']);

@ -101,7 +101,6 @@ $currentAnswer = isset($_REQUEST['num_answer']) ? (int) $_REQUEST['num_answer']
$logInfo = [
'tool' => TOOL_QUIZ,
'tool_id' => $exerciseId,
'tool_id_detail' => 0,
'action' => $learnpath_id,
'action_details' => $learnpath_id,
];
@ -159,6 +158,8 @@ if (!isset($objExercise) && isset($exerciseInSession)) {
$objExercise = $exerciseInSession;
}
$exerciseInSession = Session::read('objExercise');
//3. $objExercise is not set, then return to the exercise list
if (!is_object($objExercise)) {
if ($debug) {
@ -465,10 +466,6 @@ if (!isset($questionListInSession)) {
$questionList = explode(',', $exercise_stat_info['data_tracking']);
}
Session::write('questionList', $questionList);
if ($debug > 0) {
error_log('$_SESSION[questionList] was set');
}
} else {
if (isset($objExercise) && isset($exerciseInSession)) {
$questionList = Session::read('questionList');
@ -624,7 +621,6 @@ if ($formSent && isset($_POST)) {
error_log('9. $formSent was set');
}
// Initializing
if (!is_array($exerciseResult)) {
$exerciseResult = [];
$exerciseResultCoordinates = [];
@ -684,7 +680,6 @@ if ($formSent && isset($_POST)) {
[]
);
}
//END of saving and qualifying
}
}
}
@ -1107,7 +1102,6 @@ if (!empty($error)) {
var saveDurationUrl = "'.$saveDurationUrl.'";
// Logout of course just in case
$.ajax({
async: false,
url: saveDurationUrl,
success: function (data) {
calledUpdateDuration = true;
@ -1216,7 +1210,7 @@ if (!empty($error)) {
function save_question_list(question_list) {
$.each(question_list, function(key, question_id) {
save_now(question_id, null, false);
save_now(question_id, null);
});
var url = "";
@ -1235,7 +1229,7 @@ if (!empty($error)) {
window.location = "'.$script_php.'?'.$params.'";
}
function save_now(question_id, url_extra, validate) {
function save_now(question_id, url_extra) {
// 1. Normal choice inputs
var my_choice = $(\'*[name*="choice[\'+question_id+\']"]\').serialize();
@ -1266,19 +1260,21 @@ if (!empty($error)) {
// Only for the first time
var dataparam = "'.$params.'&type=simple&question_id="+question_id;
dataparam += "&"+my_choice+"&"+hotspot+"&"+remind_list+"&"+my_choiceDc;
dataparam += "&"+my_choice;
dataparam += hotspot ? ("&" + hotspot) : "";
dataparam += remind_list ? ("&" + remind_list) : "";
dataparam += my_choiceDc ? ("&" + my_choiceDc) : "";
$("#save_for_now_"+question_id).html(\''.
Display::returnFontAwesomeIcon('spinner', null, true, 'fa-spin').'\');
$.ajax({
type:"post",
async: false,
url: "'.api_get_path(WEB_AJAX_PATH).'exercise.ajax.php?'.api_get_cidreq().'&a=save_exercise_by_now",
data: dataparam,
success: function(return_value) {
if (return_value == "ok") {
$("#save_for_now_"+question_id).html(\''.
Display::return_icon('save.png', get_lang('Saved...'), [], ICON_SIZE_SMALL).'\');
Display::return_icon('save.png', get_lang('Saved'), [], ICON_SIZE_SMALL).'\');
} else if (return_value == "error") {
$("#save_for_now_"+question_id).html(\''.
Display::return_icon('error.png', get_lang('Error'), [], ICON_SIZE_SMALL).'\');
@ -1299,7 +1295,7 @@ if (!empty($error)) {
}
$("#save_for_now_"+question_id).html(\''.
Display::return_icon('save.png', get_lang('Saved...'), [], ICON_SIZE_SMALL).'\');
Display::return_icon('save.png', get_lang('Saved'), [], ICON_SIZE_SMALL).'\');
window.location = url;
}
@ -1337,11 +1333,16 @@ if (!empty($error)) {
free_answers = $.param(free_answers);
$("#save_all_response").html(\''.Display::returnFontAwesomeIcon('spinner', null, true, 'fa-spin').'\');
var requestData = "'.$params.'&type=all";
requestData += "&" + my_choice;
requestData += hotspot ? ("&" + hotspot) : "";
requestData += free_answers ? ("&" + free_answers) : "";
requestData += remind_list ? ("&" + remind_list) : "";
$.ajax({
type:"post",
async: false,
url: "'.api_get_path(WEB_AJAX_PATH).'exercise.ajax.php?'.api_get_cidreq().'&a=save_exercise_by_now",
data: "'.$params.'&type=all&"+my_choice+"&"+hotspot+"&"+free_answers+"&"+remind_list,
data: requestData,
success: function(return_value) {
if (return_value == "ok") {
if (validate == "validate") {

@ -72,6 +72,14 @@ function SendEx(num) {
}
</script>';
$header = '';
if ($objExercise->getFeedbackType() === EXERCISE_FEEDBACK_TYPE_POPUP) {
$header = '
<div class="modal-header">
<h4 class="modal-title" id="global-modal-title">'.get_lang('Incorrect').'</h4>
</div>';
}
echo '<div id="delineation-container">';
// Getting the options by js
if (empty($choiceValue) && empty($hotSpot) && $loaded) {
@ -105,6 +113,7 @@ if (empty($choiceValue) && empty($hotSpot) && $loaded) {
$links .= $icon;
}
}
echo $header;
echo '<div class="row"><div class="col-md-5 col-md-offset-7"><h5 class="pull-right">'.$links.'</h5></div></div>';
exit;
}
@ -152,13 +161,11 @@ if (empty($choiceValue) && empty($hotSpot)) {
$url = api_get_path(WEB_CODE_PATH).'exercise/exercise_submit_modal.php?'.api_get_cidreq().$extraUrl;
echo ' url = "'.addslashes($url).'&hotspotcoord="+ hotspotcoord + "&"+ hotspot + "&"+ my_choice;';
echo "$('#global-modal .modal-body').load(url);";
echo '</script>';
exit;
}
$choice = [];
$choice[$questionId] = isset($choiceValue) ? $choiceValue : null;
if (!is_array($exerciseResult)) {
$exerciseResult = [];
}
@ -220,11 +227,6 @@ switch ($answerType) {
break;
case CALCULATED_ANSWER:
/*$_SESSION['calculatedAnswerId'][$questionId] = mt_rand(
1,
$nbrAnswers
);*/
//var_dump($_SESSION['calculatedAnswerId'][$questionId]);
break;
}
@ -247,10 +249,11 @@ $result = $objExercise->manage_answer(
$manageAnswerHtmlContent = ob_get_clean();
$contents = '';
$answerCorrect = false;
$partialCorrect = false;
if (!empty($result)) {
switch ($answerType) {
case UNIQUE_ANSWER:
case MULTIPLE_ANSWER:
case UNIQUE_ANSWER:
case DRAGGABLE:
case HOT_SPOT_DELINEATION:
case CALCULATED_ANSWER:
@ -258,24 +261,79 @@ if (!empty($result)) {
$answerCorrect = true;
}
// Check partial correct
if (false === $answerCorrect) {
if (!empty($result['score'])) {
$partialCorrect = true;
}
}
break;
}
}
if (EXERCISE_FEEDBACK_TYPE_DIRECT === $objExercise->getFeedbackType()) {
$header = '';
if ($objExercise->getFeedbackType() === EXERCISE_FEEDBACK_TYPE_DIRECT) {
if (isset($result['correct_answer_id'])) {
foreach ($result['correct_answer_id'] as $answerId) {
/** @var Answer $answer */
$answerId = $result['correct_answer_id'];
$contents = $objAnswerTmp->selectComment($answerId);
$contents .= $objAnswerTmp->selectComment($answerId);
}
}
} else {
$contents = Display::return_message(get_lang('Incorrect'), 'warning');
$message = get_lang('Incorrect');
//$contents = Display::return_message($message, 'warning');
if ($answerCorrect) {
$contents = Display::return_message(get_lang('Correct'), 'success');
$message = get_lang('Correct');
//$contents = Display::return_message($message, 'success');
} else {
if ($partialCorrect) {
$message = get_lang('PartialCorrect');
}
}
if (HOT_SPOT_DELINEATION === $answerType) {
$comments = '';
if ($answerType != HOT_SPOT_DELINEATION) {
if (isset($result['correct_answer_id'])) {
$table = new HTML_Table(['class' => 'table data_table']);
$row = 0;
$table->setCellContents($row, 0, get_lang('YourAnswer'));
if ($answerType != DRAGGABLE) {
$table->setCellContents($row, 1, get_lang('Comment'));
}
$data = [];
foreach ($result['correct_answer_id'] as $answerId) {
$answer = $objAnswerTmp->getAnswerByAutoId($answerId);
if (!empty($answer) && isset($answer['comment'])) {
$data[] = [$answer['answer'], $answer['comment']];
} else {
$answer = $objAnswerTmp->selectAnswer($answerId);
$comment = $objAnswerTmp->selectComment($answerId);
$data[] = [$answer, $comment];
}
}
if (!empty($data)) {
$row = 1;
foreach ($data as $dataItem) {
$table->setCellContents($row, 0, $dataItem[0]);
$table->setCellContents($row, 1, $dataItem[1]);
$row++;
}
$comments = $table->toHtml();
}
}
}
$contents .= $comments;
$header = '
<div class="modal-header">
<h4 class="modal-title" id="global-modal-title">'.$message.'</h4>
</div>';
}
if ($answerType === HOT_SPOT_DELINEATION) {
$contents = $manageAnswerHtmlContent;
}
$links = '';
@ -353,6 +411,7 @@ if (-1 == $destinationId) {
}
if (!empty($links)) {
echo $header;
echo '<div>'.$contents.'</div>';
echo '<div style="padding-left: 450px"><h5>'.$links.'</h5></div>';
echo '</div>';

@ -354,6 +354,7 @@ function parseQti2($xmlData)
$currentQuestionItemBody = '';
$cardinality = '';
$nonHTMLTagToAvoid = [
'prompt',
'simpleChoice',
'choiceInteraction',
'inlineChoiceInteraction',
@ -387,6 +388,7 @@ function parseQti2($xmlData)
'category' => $node->getAttribute('category'),
'type' => '',
'tempdir' => $questionTempDir,
'description' => null,
];
break;
@ -633,7 +635,15 @@ function parseQti2($xmlData)
$exerciseInfo['description'] = $node->nodeValue;
}
}
break;
case 'prompt':
$description = trim($node->nodeValue);
$description = htmlspecialchars_decode($description);
$description = Security::remove_XSS($description);
if (!empty($description)) {
$exerciseInfo['question'][$currentQuestionIdent]['description'] = $description;
}
break;
}
}

@ -30,7 +30,6 @@ class FillBlanks extends Question
public function createAnswersForm($form)
{
$defaults = [];
//$defaults['answer'] = get_lang('<table cellspacing="0" cellpadding="10" border="1" width="720" style="" height:=""> <tbody> <tr> <td colspan="2"> <h3>Example fill the form activity : calculate the Body Mass Index</h3> </td> </tr> <tr> <td style="text-align: right;"><strong>Age</strong></td> <td width="75%" style="">[25] years old</td> </tr> <tr> <td style="text-align: right;"><strong>Sex</strong></td> <td style="" text-align:="">[M] (M or F)</td> </tr> <tr> <td style="text-align: right;"><strong>Weight</strong></td> <td style="" text-align:="">95 Kg</td> </tr> <tr> <td style="vertical-align: top; text-align: right;"><strong>Height</strong></td> <td style="vertical-align: top;">1.81 m</td> </tr> <tr> <td style="vertical-align: top; text-align: right;"><strong>Body Mass Index</strong></td> <td style="vertical-align: top;">[29] BMI =Weight/Size<sup>2</sup> (Cf.<a href="http://en.wikipedia.org/wiki/Body_mass_index" onclick="window.open(this.href,'','resizable=yes,location=yes,menubar=no,scrollbars=yes,status=yes,toolbar=no,fullscreen=no,dependent=no,width=800,height=600,left=40,top=40,status'); return false"> Wikipedia article</a>)</td> </tr> </tbody></table>');
$defaults['answer'] = get_lang('DefaultTextInBlanks');
$defaults['select_separator'] = 0;
$blankSeparatorNumber = 0;

@ -1357,6 +1357,9 @@ abstract class Question
}
}
$extraField = new ExtraField('question');
$extraField->addElements($form, $this->iid);
// default values
$defaults = [];
$defaults['questionName'] = $this->question;
@ -1400,6 +1403,12 @@ abstract class Question
// modify the exercise
$exercise->addToList($this->id);
$exercise->update_question_positions();
$params = $form->exportValues();
$params['item_id'] = $this->id;
$extraFieldValues = new ExtraFieldValue('question');
$extraFieldValues->saveFieldValues($params);
}
}

@ -2,9 +2,6 @@
/* For licensing terms, see /license.txt */
/**
* Test.
*/
require_once __DIR__.'/../inc/global.inc.php';
// the section (tabs)

@ -252,10 +252,8 @@ if (isset($_REQUEST['action'])) {
case 'clone':
if (!empty($_REQUEST['questions']) && !empty($fromExercise)) {
$questions = $_REQUEST['questions'];
$objExercise = new Exercise();
$objExercise->read($fromExercise, false);
$origin_course_id = (int) $_GET['course_id'];
$origin_course_info = api_get_course_info_by_id($origin_course_id);
$current_course = api_get_course_info();
@ -273,7 +271,7 @@ if (isset($_REQUEST['action'])) {
$new_question_obj = Question::read($new_id);
$new_question_obj->addToList($fromExercise);
//Reading Answers obj of the current course
$new_answer_obj = new Answer($old_question_id, $origin_course_id);
$new_answer_obj = new Answer($questionId, $origin_course_id);
$new_answer_obj->read();
//Duplicating the Answers in the current course
$new_answer_obj->duplicate($new_question_obj, $current_course);
@ -315,27 +313,17 @@ if ('' != $displayMessage) {
}
// Form
echo '<form class="form-horizontal" name="question_pool" method="GET" action="'.$url.'">';
// Title
echo '<legend>'.$nameTools.' - '.$titleAdd.'</legend>';
echo '<input type="hidden" name="fromExercise" value="'.$fromExercise.'">';
// Session list, if sessions are used.
$sessionList = SessionManager::get_sessions_by_user(api_get_user_id(), api_is_platform_admin());
$session_select_list = [];
$session_select_list = ['-1' => get_lang('Select')];
foreach ($sessionList as $item) {
$session_select_list[$item['session_id']] = $item['session_name'];
}
$sessionListToString = Display::select(
'session_id',
$session_select_list,
$session_id,
['onchange' => 'submit_form(this)']
);
echo Display::form_row(get_lang('Session'), $sessionListToString);
// Course list, get course list of session, or for course where user is admin
if (!empty($session_id) && '-1' != $session_id && !empty($sessionList)) {
$course_list = [];
// Course list, get course list of session, or for course where user is admin
if (!empty($session_id) && $session_id != '-1' && !empty($sessionList)) {
$sessionInfo = [];
foreach ($sessionList as $session) {
if ($session['session_id'] == $session_id) {
@ -363,7 +351,7 @@ if (!empty($session_id) && '-1' != $session_id && !empty($sessionList)) {
}
}
$course_select_list = [];
$course_select_list = ['-1' => get_lang('Select')];
foreach ($course_list as $item) {
$courseItemId = $item['real_id'];
$courseInfo = api_get_course_info_by_id($courseItemId);
@ -374,16 +362,7 @@ foreach ($course_list as $item) {
$course_select_list[$courseItemId] .= $courseInfo['title'];
}
$courseListToString = Display::select(
'selected_course',
$course_select_list,
$selected_course,
['onchange' => 'mark_course_id_changed(); submit_form(this);']
);
echo Display::form_row(get_lang('Course'), $courseListToString);
if (empty($selected_course) || '-1' == $selected_course) {
if (empty($selected_course) || $selected_course == '-1') {
$course_info = api_get_course_info();
// no course selected, reset menu test / difficult<EFBFBD> / type de reponse
reset_menu_exo_lvl_type();
@ -438,16 +417,6 @@ if (is_array($exercise_list)) {
}
}
$exerciseListToString = Display::select(
'exerciseId',
$my_exercise_list,
$exerciseId,
['onchange' => 'mark_exercise_id_changed(); submit_form(this);'],
false
);
echo Display::form_row(get_lang('Test'), $exerciseListToString);
// Difficulty list (only from 0 to 5)
$levels = [
-1 => get_lang('All'),
@ -459,15 +428,6 @@ $levels = [
5 => 5,
];
$select_difficulty_html = Display::select(
'exerciseLevel',
$levels,
$exerciseLevel,
['onchange' => 'submit_form(this);'],
false
);
echo Display::form_row(get_lang('Difficulty'), $select_difficulty_html);
// Answer type
$question_list = Question::getQuestionTypeList();
@ -493,31 +453,148 @@ if (!empty($_course)) {
}
// Answer type list
$select_answer_html = Display::select(
$form = new FormValidator('question_pool', 'GET', $url);
$form->addHeader($nameTools.' - '.$titleAdd);
$form->addHidden('fromExercise', $fromExercise);
$form
->addSelect(
'session_id',
get_lang('Session'),
$session_select_list,
['onchange' => 'submit_form(this)', 'id' => 'session_id']
)
->setSelected($session_id);
$form
->addSelect(
'selected_course',
get_lang('Course'),
$course_select_list,
['onchange' => 'mark_course_id_changed(); submit_form(this);', 'id' => 'selected_course']
)
->setSelected($selected_course);
$form
->addSelect(
'courseCategoryId',
get_lang('QuestionCategory'),
$categoryList,
['onchange' => 'submit_form(this);', 'id' => 'courseCategoryId']
)
->setSelected($courseCategoryId);
$form
->addSelect(
'exerciseId',
get_lang('Exercise'),
$my_exercise_list,
['onchange' => 'mark_exercise_id_changed(); submit_form(this);', 'id' => 'exerciseId']
)
->setSelected($exerciseId);
$form
->addSelect(
'exerciseLevel',
get_lang('Difficulty'),
$levels,
['onchange' => 'submit_form(this);', 'id' => 'exerciseLevel']
)
->setSelected($exerciseLevel);
$form
->addSelect(
'answerType',
get_lang('AnswerType'),
$new_question_list,
$answerType,
['onchange' => 'submit_form(this);'],
false
);
['onchange' => 'submit_form(this);', 'id' => 'answerType']
)
->setSelected($answerType);
$form
->addText('question_id', get_lang('Id'), false)
->setValue($questionId);
$form
->addText('description', get_lang('Description'), false)
->setValue(Security::remove_XSS($description));
echo Display::form_row(get_lang('Answer type'), $select_answer_html);
echo Display::form_row(get_lang('Id'), Display::input('text', 'question_id', $questionId));
echo Display::form_row(
get_lang('Description'),
Display::input('text', 'description', Security::remove_XSS($description))
);
$form->addHidden('course_id_changed', '0');
$form->addHidden('exercise_id_changed', '0');
$extraField = new ExtraField('question');
$jsForExtraFields = $extraField->addElements($form, 0, [], true);
$button = '<button class="btn btn-primary save" type="submit" name="name" value="'.get_lang('Filter').'">'.
get_lang('Filter').'</button>';
echo Display::form_row('', $button);
echo "<input type='hidden' id='course_id_changed' name='course_id_changed' value='0' />";
echo "<input type='hidden' id='exercise_id_changed' name='exercise_id_changed' value='0' />";
$form->addButtonFilter(get_lang('Filter'), 'name');
echo $form->display();
echo '<script>$(function () {
'.$jsForExtraFields['jquery_ready_content'].'
})</script>';
?>
</form>
<div class="clear"></div>
<?php
/**
* @return array
*/
function getExtraFieldConditions(array $formValues, $queryType = 'from')
{
$extraField = new ExtraField('question');
$fields = $extraField->get_all(
['visible_to_self = ? AND filter = ?' => [1, 1]],
'display_text'
);
$from = '';
$where = '';
foreach ($fields as $field) {
$variable = $field['variable'];
if (empty($formValues["extra_$variable"])) {
continue;
}
$value = $formValues["extra_$variable"];
switch ($field['field_type']) {
case ExtraField::FIELD_TYPE_CHECKBOX:
$value = $value["extra_$variable"];
break;
case ExtraField::FIELD_TYPE_DOUBLE_SELECT:
if (!isset($value["extra_{$variable}_second"])) {
$value = null;
break;
}
$value = $value["extra_$variable"].'::'.$value["extra_{$variable}_second"];
break;
}
if (empty($value)) {
continue;
}
if ($queryType === 'from') {
$from .= ", extra_field_values efv_$variable, extra_field ef_$variable";
$where .= "AND (
qu.iid = efv_$variable.item_id
AND efv_$variable.field_id = ef_$variable.id
AND ef_$variable.extra_field_type = ".ExtraFieldEntity::QUESTION_FIELD_TYPE."
AND ef_$variable.variable = '$variable'
AND efv_$variable.value = '$value'
)";
} elseif ($queryType === 'join') {
$from .= " INNER JOIN extra_field_values efv_$variable ON qu.iid = efv_$variable.item_id
INNER JOIN extra_field ef_$variable ON efv_$variable.field_id = ef_$variable.id";
$where .= "AND (
ef_$variable.extra_field_type = ".ExtraFieldEntity::QUESTION_FIELD_TYPE."
AND ef_$variable.variable = '$variable'
AND efv_$variable.value = '$value'
)";
}
}
return [
'from' => $from,
'where' => $where,
];
}
function getQuestions(
$getCount,
$start,
@ -530,7 +607,8 @@ function getQuestions(
$answerType,
$questionId,
$description,
$fromExercise = 0
$fromExercise = 0,
$formValues = []
) {
$start = (int) $start;
$length = (int) $length;
@ -561,6 +639,8 @@ function getQuestions(
// if we have selected an exercise in the list-box 'Filter'
if ($exerciseId > 0) {
$efConditions = getExtraFieldConditions($formValues, 'from');
$where = '';
$from = '';
if (isset($courseCategoryId) && $courseCategoryId > 0) {
@ -600,14 +680,18 @@ function getQuestions(
INNER JOIN $TBL_QUESTIONS qu
ON qt.question_id = qu.id
$from
{$efConditions['from']}
WHERE
qt.exercice_id = $exerciseId AND
qt.c_id = $selected_course AND
qu.c_id = $selected_course
$where
$currentExerciseCondition
ORDER BY question_order";
} elseif (-1 == $exerciseId) {
{$efConditions['where']}
ORDER BY BINARY qu.question ASC
";
} elseif ($exerciseId == -1) {
$efConditions = getExtraFieldConditions($formValues, 'join');
// If we have selected the option 'Orphan questions' in the list-box 'Filter'
$level_where = '';
$from = '';
@ -623,7 +707,7 @@ function getQuestions(
}
$answer_where = '';
if (isset($answerType) && $answerType > 0 - 1) {
$answer_where = ' AND type='.$answerType;
$answer_where = ' AND qu.type='.$answerType;
}
if (!empty($questionId)) {
@ -634,57 +718,64 @@ function getQuestions(
$answer_where .= " AND q.description LIKE '%$description%'";
}
$select = ' q.*, r.exercice_id exerciseId ';
$select = ' qu.*, r.exercice_id exerciseId ';
if ($getCount) {
$select = 'count(q.iid) as count';
$select = 'count(qu.iid) as count';
}
// @todo fix this query with the new id field
$sql = " (
SELECT $select
FROM $TBL_QUESTIONS q
FROM $TBL_QUESTIONS qu
INNER JOIN $TBL_EXERCISE_QUESTION r
ON (q.c_id = r.c_id AND q.id = r.question_id)
ON (qu.c_id = r.c_id AND qu.id = r.question_id)
INNER JOIN $TBL_EXERCISES ex
ON (ex.id = r.exercice_id AND ex.c_id = r.c_id)
$from
{$efConditions['from']}
WHERE
ex.c_id = '$selected_course' AND
ex.active = '-1'
$level_where
$answer_where
{$efConditions['where']}
)
UNION
(
SELECT $select
FROM $TBL_QUESTIONS q
FROM $TBL_QUESTIONS qu
LEFT OUTER JOIN $TBL_EXERCISE_QUESTION r
ON (q.c_id = r.c_id AND q.id = r.question_id)
ON (qu.c_id = r.c_id AND qu.id = r.question_id)
$from
{$efConditions['from']}
WHERE
q.c_id = '$selected_course' AND
qu.c_id = '$selected_course' AND
r.question_id is null
$level_where
$answer_where
{$efConditions['where']}
)
UNION
(
SELECT $select
FROM $TBL_QUESTIONS q
FROM $TBL_QUESTIONS qu
INNER JOIN $TBL_EXERCISE_QUESTION r
ON (q.c_id = r.c_id AND q.id = r.question_id)
ON (qu.c_id = r.c_id AND qu.id = r.question_id)
$from
{$efConditions['from']}
WHERE
r.c_id = '$selected_course' AND
(r.exercice_id = '-1' OR r.exercice_id = '0')
$level_where
$answer_where
{$efConditions['where']}
)
";
if ($getCount) {
$sql = "SELECT SUM(count) count FROM ($sql) as total";
}
} else {
$efConditions = getExtraFieldConditions($formValues, 'from');
// All tests for selected course
// If we have not selected any option in the list-box 'Filter'
$filter = '';
@ -728,6 +819,7 @@ function getQuestions(
$TBL_QUESTIONS as qu,
$TBL_EXERCISE_QUESTION as qt,
$TBL_EXERCISES as q
{$efConditions['from']}
$from
WHERE
qu.c_id = $selected_course AND
@ -738,30 +830,38 @@ function getQuestions(
q.id = qt.exercice_id
$filter
$currentExerciseCondition
{$efConditions['where']}
GROUP BY qu.iid
ORDER BY session_id ASC
ORDER BY BINARY qu.question ASC
";
}
if ($getCount) {
$result = Database::query($sql);
$row = Database::fetch_array($result, 'ASSOC');
if ($row) {
return (int) $row['count'];
}
return (int) $row['count'];
return 0;
}
$sql .= " LIMIT $start, $length";
$result = Database::query($sql);
$mainQuestionList = [];
while ($row = Database::fetch_array($result, 'ASSOC')) {
if ($exerciseId == -1 && isQuestionInActiveQuiz($row['iid'])) {
continue;
}
$mainQuestionList[] = $row;
}
return $mainQuestionList;
}
$formValues = $form->validate() ? $form->exportValues() : [];
$nbrQuestions = getQuestions(
true,
null,
@ -774,7 +874,8 @@ $nbrQuestions = getQuestions(
$answerType,
$questionId,
$description,
$fromExercise
$fromExercise,
$formValues
);
$length = api_get_configuration_value('question_pagination_length');
@ -819,7 +920,8 @@ $mainQuestionList = getQuestions(
$answerType,
$questionId,
$description,
$fromExercise
$fromExercise,
$formValues
);
// build the line of the array to display questions
@ -882,8 +984,6 @@ if (is_array($mainQuestionList)) {
continue;
}
$sessionId = isset($question['session_id']) ? $question['session_id'] : null;
//$exerciseName = isset($question['exercise_name']) ? '<br />('.$question['exercise_id'].') ' : null;
if (!$objExercise->hasQuestion($question['id'])) {
$row[] = Display::input(
'checkbox',
@ -940,49 +1040,13 @@ if (is_array($mainQuestionList)) {
}
}
// Display table
$header = [
[
'',
false,
['style' => 'text-align:center'],
['style' => 'text-align:center'],
$headers = [
'',
],
[
get_lang('Question'),
false,
['style' => 'text-align:center'],
'',
],
[
get_lang('QuestionUpperCaseFirstLetter'),
get_lang('Type'),
false,
['style' => 'text-align:center'],
['style' => 'text-align:center'],
'',
],
[
get_lang('Questions category'),
false,
['style' => 'text-align:center'],
['style' => 'text-align:center'],
'',
],
[
get_lang('QuestionCategory'),
get_lang('Difficulty'),
false,
['style' => 'text-align:center'],
['style' => 'text-align:center'],
'',
],
[
$actionLabel,
false,
['style' => 'text-align:center'],
['style' => 'text-align:center'],
'',
],
];
echo $pagination;
@ -992,12 +1056,32 @@ echo '<input type="hidden" name="cidReq" value="'.$_course['code'].'">';
echo '<input type="hidden" name="selected_course" value="'.$selected_course.'">';
echo '<input type="hidden" name="course_id" value="'.$selected_course.'">';
Display::display_sortable_table(
$header,
$data,
'',
['per_page_default' => 999, 'per_page' => 999, 'page_nr' => 1]
$table = new HTML_Table(['class' => 'table table-bordered data_table'], false);
$row = 0;
$column = 0;
foreach ($headers as $header) {
$table->setHeaderContents($row, $column, $header);
$column++;
}
$row = 1;
foreach ($data as $rows) {
$column = 0;
foreach ($rows as $value) {
$table->setCellContents($row, $column, $value);
$table->updateCellAttributes(
$row,
$column,
$value
);
$column++;
}
$row++;
}
$table->display();
echo '</form>';
$tableId = 'question_pool_id';
@ -1143,10 +1227,15 @@ function get_action_icon_for_question(
if ($limitTeacherAccess && !api_is_platform_admin()) {
break;
}
$res = "<a href='".api_get_self().'?'.
if (isQuestionInActiveQuiz($in_questionid)) {
$res = Display::return_icon('delete_na.png', get_lang('ThisQuestionExistsInAnotherExercisesWarning'));
} else {
$res = "<a href='".api_get_self()."?".
api_get_cidreq().$getParams."&delete=$in_questionid' onclick='return confirm_your_choice()'>";
$res .= Display::return_icon('delete.png', get_lang('Delete'));
$res .= '</a>';
$res .= Display::return_icon('delete.png', get_lang('Delete'));
$res .= "</a>";
}
break;
case 'edit':
@ -1189,6 +1278,28 @@ function get_action_icon_for_question(
return $res;
}
/**
* @param int $questionId
*
* @return bool
*/
function isQuestionInActiveQuiz($questionId)
{
$tblQuizRelQuestion = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
$tblQuiz = Database::get_course_table(TABLE_QUIZ_TEST);
$result = Database::fetch_assoc(
Database::query(
"SELECT COUNT(qq.question_id) c FROM $tblQuizRelQuestion qq
INNER JOIN $tblQuiz q ON qq.exercice_id = q.iid
WHERE q.active = 1
AND qq.question_id = $questionId"
)
);
return $result['c'] > 0;
}
/**
* Return the icon for the question type.
*

@ -8,117 +8,28 @@ require_once __DIR__.'/../inc/global.inc.php';
api_protect_course_script(true);
$isAllowedToEdit = api_is_allowed_to_edit(true, true);
if (!$isAllowedToEdit) {
exit;
}
if (!isset($_REQUEST['user'], $_REQUEST['exercise'], $_REQUEST['id'])) {
exit;
}
$courseId = api_get_course_int_id();
$em = Database::getManager();
/** @var TrackEExercises $trackedExercise */
$trackedExercise = $em->getRepository('ChamiloCoreBundle:TrackEExercises')->find($_REQUEST['id']);
if (empty($trackedExercise)) {
exit;
}
$studentId = $trackedExercise->getExeUserId();
$exerciseId = $trackedExercise->getExeExoId();
$exeId = $trackedExercise->getExeId();
if ($studentId != (int) ($_REQUEST['user']) ||
$exerciseId != (int) ($_REQUEST['exercise'])
) {
exit;
}
$questionList = $trackedExercise->getDataTracking();
$isAllowedToEdit = api_is_allowed_to_edit(true, true);
if (empty($questionList)) {
if (!$isAllowedToEdit) {
exit;
}
$questionList = explode(',', $questionList);
$exercise = new Exercise($courseId);
$exercise->read($exerciseId);
$totalScore = 0;
$totalWeight = 0;
$useEvaluationPlugin = false;
$pluginEvaluation = QuestionOptionsEvaluationPlugin::create();
if ('true' === $pluginEvaluation->get(QuestionOptionsEvaluationPlugin::SETTING_ENABLE)) {
$formula = $pluginEvaluation->getFormulaForExercise($exerciseId);
if (!empty($formula)) {
$useEvaluationPlugin = true;
}
}
$studentId = (int) $_REQUEST['user'];
$exerciseId = (int) $_REQUEST['exercise'];
$exeId = (int) $_REQUEST['id'];
if (!$useEvaluationPlugin) {
foreach ($questionList as $questionId) {
$question = Question::read($questionId, api_get_course_info());
$totalWeight += $question->selectWeighting();
// We're inside *one* question. Go through each possible answer for this question
if (MULTIPLE_ANSWER_TRUE_FALSE_DEGREE_CERTAINTY === $question->type) {
$result = $exercise->manage_answer(
$exeId,
$questionId,
[],
'exercise_result',
[],
false,
true,
false,
$exercise->selectPropagateNeg(),
[],
[],
true
);
} else {
$result = $exercise->manage_answer(
$exeId,
$questionId,
[],
'exercise_result',
[],
false,
true,
false,
$exercise->selectPropagateNeg(),
[],
[],
true
);
}
// Adding the new score.
$totalScore += $result['score'];
}
$remindList = $trackedExercise->getQuestionsToCheck();
if (!empty($remindList)) {
$remindList = explode(',', $remindList);
}
} else {
$totalScore = $pluginEvaluation->getResultWithFormula($exeId, $formula);
$totalWeight = $pluginEvaluation->getMaxScore();
}
$table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_EXERCISES);
$sql = "UPDATE $table SET
score = '$totalScore',
max_score = '$totalWeight'
WHERE exe_id = $exeId";
Database::query($sql);
/** @var TrackEExercises $trackedExercise */
$trackedExercise = ExerciseLib::recalculateResult(
$_REQUEST['id'],
$_REQUEST['user'],
$_REQUEST['exercise']
);
$totalScore = $trackedExercise->getExeResult();
$totalWeight = $trackedExercise->getExeWeighting();
echo $totalScore.'/'.$totalWeight;

@ -0,0 +1,61 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Entity\TrackEExercises;
require_once __DIR__.'/../inc/global.inc.php';
api_protect_course_script(true);
if (!isset($_REQUEST['exercise'])) {
api_not_allowed(true);
}
$exerciseId = (int) $_REQUEST['exercise'];
$is_allowedToEdit = api_is_allowed_to_edit(null, true) ||
api_is_drh() ||
api_is_student_boss() ||
api_is_session_admin();
if (!$is_allowedToEdit) {
api_not_allowed(true);
}
$result = ExerciseLib::get_exam_results_data(
0,
0,
1,
'asc',
$exerciseId,
'',
false,
null,
false,
false,
[],
false,
false,
true
);
foreach ($result as $track) {
/** @var TrackEExercises $trackedExercise */
$trackedExercise = ExerciseLib::recalculateResult(
$track['id'],
$track['user_id'],
$exerciseId
);
if (!$trackedExercise) {
Display::addFlash(
Display::return_message(get_lang('BadFormData').'<br>ID: '.$track['id'], 'warning', false)
);
}
}
$url = api_get_path(WEB_CODE_PATH).'exercise/exercise_report.php?'
.api_get_cidreq()
."&exerciseId=$exerciseId";
header("Location: $url");

@ -25,7 +25,6 @@ if (empty($id)) {
api_not_allowed($show_headers);
}
$is_courseTutor = api_is_course_tutor();
$is_allowedToEdit = api_is_allowed_to_edit(null, true) || $is_courseTutor;
// Getting results from the exe_id. This variable also contain all the information about the exercise

@ -149,6 +149,7 @@ function lp_upload_quiz_action_handling()
$questionTypeList = [];
$answerList = [];
$quizTitle = '';
$objPHPExcel = PHPExcel_IOFactory::load($_FILES['user_upload_quiz']['tmp_name']);
$objPHPExcel->setActiveSheetIndex(0);
$worksheet = $objPHPExcel->getActiveSheet();

Loading…
Cancel
Save