Merge branch '1.11.x' of github.com:chamilo/chamilo-lms into 1.11.x

pull/3293/head
Angel Fernando Quiroz Campos 5 years ago
commit fdbf8c86d0
  1. 11
      main/document/document.php
  2. 23
      main/document/record_audio.php
  3. 92
      main/exercise/exercise.class.php
  4. 52
      main/exercise/exercise.php
  5. 66
      main/exercise/exercise_report.php
  6. 11
      main/inc/ajax/record_audio_rtc.ajax.php
  7. 7
      main/inc/lib/javascript/record_audio/record_audio.js
  8. 26
      main/inc/lib/usermanager.lib.php
  9. 3
      main/install/configuration.dist.php
  10. 8
      main/survey/ch_selectivedisplay.php
  11. 4
      main/survey/create_new_survey.php
  12. 45
      main/survey/survey_question.php
  13. 3
      main/template/default/document/record_audio.tpl
  14. 1
      plugin/ims_lti/ImsLtiPlugin.php

@ -1,4 +1,5 @@
<?php
/* For licensing terms, see /license.txt */
use ChamiloSession as Session;
@ -25,8 +26,6 @@ use ChamiloSession as Session;
* 2) Define the directory to display
* 3) Read files and directories from the directory defined in part 2
* 4) Display all of that on an HTML page
*
* @package chamilo.document
*/
require_once __DIR__.'/../inc/global.inc.php';
@ -42,7 +41,7 @@ $allowUseTool = false;
if ($allowDownloadDocumentsByApiKey) {
try {
if ($action != 'download') {
if ($action !== 'download') {
throw new Exception(get_lang('SelectAnAction'));
}
@ -71,7 +70,7 @@ $_user = api_get_user_info();
$courseInfo = api_get_course_info();
$courseId = $courseInfo['real_id'];
$course_dir = $courseInfo['directory'].'/document';
$usePpt2lp = api_get_setting('service_ppt2lp', 'active') == 'true';
$usePpt2lp = api_get_setting('service_ppt2lp', 'active') === 'true';
$sys_course_path = api_get_path(SYS_COURSE_PATH);
$base_work_dir = $sys_course_path.$course_dir;
$http_www = api_get_path(WEB_COURSE_PATH).$courseInfo['directory'].'/document';
@ -83,7 +82,7 @@ $is_certificate_mode = false;
if (isset($_GET['curdirpath'])) {
$is_certificate_mode = DocumentManager::is_certificate_mode($_GET['curdirpath']);
}
if (isset($_REQUEST['certificate']) && $_REQUEST['certificate'] == 'true') {
if (isset($_REQUEST['certificate']) && $_REQUEST['certificate'] === 'true') {
$is_certificate_mode = true;
}
@ -1471,7 +1470,7 @@ if ($isAllowedToEdit ||
'post',
api_get_self()."?add_as_template=$document_id_for_template"
);
$frmAddTemplate ->addHeader(get_lang('AddAsTemplate'));
$frmAddTemplate->addHeader(get_lang('AddAsTemplate'));
$frmAddTemplate->addText('template_title', get_lang('TemplateName'), true);
$frmAddTemplate->addFile('template_image', get_lang('TemplateImage'), ['id' => 'template_image']);
$frmAddTemplate->addButtonSave(get_lang('CreateTemplate'), 'create_template');

@ -1,14 +1,14 @@
<?php
/* For licensing terms, see /license.txt */
use ChamiloSession as Session;
/**
* This file allows record audio files.
*
* @package chamilo.document
*/
require_once __DIR__.'/../inc/global.inc.php';
$this_section = SECTION_COURSES;
$groupRights = Session::read('group_member_with_upload_rights');
$nameTools = get_lang('VoiceRecord');
@ -24,9 +24,7 @@ $document_data = DocumentManager::get_document_data_by_id(
);
if (empty($document_data)) {
if (api_is_in_group()) {
$group_properties = GroupManager::get_group_properties(
api_get_group_id()
);
$group_properties = GroupManager::get_group_properties(api_get_group_id());
$document_id = DocumentManager::get_document_id(
api_get_course_info(),
$group_properties['directory']
@ -43,15 +41,14 @@ $dir = $document_data['path'];
//make some vars
$wamidir = $dir;
if ($wamidir == "/") {
if ($wamidir === "/") {
$wamidir = '';
}
$wamiurlplay = api_get_path(WEB_COURSE_PATH).api_get_course_path().'/document'.$wamidir."/";
$groupId = api_get_group_id();
$is_allowed_to_edit = api_is_allowed_to_edit(null, true);
// Please, do not modify this dirname formatting
// Please, do not modify this dirname formatting.
if (strstr($dir, '..')) {
$dir = '/';
}
@ -77,8 +74,16 @@ if (!is_dir($filepath)) {
//groups //TODO: clean
if (!empty($groupId)) {
$interbreadcrumb[] = ["url" => "../group/group_space.php?".api_get_cidreq(), "name" => get_lang('GroupSpace')];
$group = GroupManager :: get_group_properties($groupId);
$interbreadcrumb[] = [
'url' => api_get_path(WEB_CODE_PATH).'group/group.php?'.api_get_cidreq(),
'name' => get_lang('Groups'),
];
$interbreadcrumb[] = [
"url" => api_get_path(WEB_CODE_PATH)."group/group_space.php?".api_get_cidreq(),
"name" => get_lang('GroupSpace'),
];
$path = explode('/', $dir);
if ('/'.$path[1] != $group['directory']) {
api_not_allowed(true);

@ -8442,6 +8442,9 @@ class Exercise
$sessionId = 0,
$returnData = false
) {
$allowDelete = Exercise::allowAction('delete');
$allowClean = Exercise::allowAction('clean_results');
$TBL_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
$TBL_ITEM_PROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
$TBL_EXERCISE_QUESTION = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
@ -8905,32 +8908,39 @@ class Exercise
);
// Clean exercise
if ($locked == false) {
$clean = Display::url(
Display::return_icon(
'clean.png',
get_lang('CleanStudentResults'),
$clean = '';
if (true === $allowClean) {
if (false == $locked) {
$clean = Display::url(
Display::return_icon(
'clean.png',
get_lang('CleanStudentResults'),
'',
ICON_SIZE_SMALL
),
'',
[
'onclick' => "javascript:if(!confirm('".addslashes(
api_htmlentities(
get_lang('AreYouSureToDeleteResults'),
ENT_QUOTES,
$charset
)
)." ".addslashes($row['title'])."?"."')) return false;",
'href' => 'exercise.php?'.api_get_cidreq(
).'&choice=clean_results&sec_token='.$token.'&exerciseId='.$row['id'],
]
);
} else {
$clean = Display::return_icon(
'clean_na.png',
get_lang('ResourceLockedByGradebook'),
'',
ICON_SIZE_SMALL
),
'',
[
'onclick' => "javascript:if(!confirm('".addslashes(api_htmlentities(get_lang('AreYouSureToDeleteResults'), ENT_QUOTES, $charset))." ".addslashes($row['title'])."?"."')) return false;",
'href' => 'exercise.php?'.api_get_cidreq().'&choice=clean_results&sec_token='.$token.'&exerciseId='.$row['id'],
]
);
} else {
$clean = Display::return_icon(
'clean_na.png',
get_lang('ResourceLockedByGradebook'),
'',
ICON_SIZE_SMALL
);
);
}
}
if ($limitTeacherAccess && !api_is_platform_admin()) {
$clean = '';
}
$actions .= $clean;
// Visible / invisible
// Check if this exercise was added in a LP
@ -9926,6 +9936,44 @@ class Exercise
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.
*

@ -24,6 +24,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();
@ -94,7 +97,7 @@ if ($is_allowedToEdit) {
switch ($action) {
case 'clean_all_test':
if ($check) {
if ($limitTeacherAccess && !api_is_platform_admin()) {
if (false === $allowClean) {
api_not_allowed(true);
}
@ -207,7 +210,9 @@ if (!empty($action) && $is_allowedToEdit) {
switch ($action) {
case 'delete':
$objExerciseTmp->delete();
if ($allowDelete) {
$objExerciseTmp->delete();
}
break;
case 'visible':
if ($limitTeacherAccess && !api_is_platform_admin()) {
@ -303,9 +308,11 @@ if ($is_allowedToEdit) {
break;
case 'delete':
// deletes an exercise
$result = $objExerciseTmp->delete();
if ($result) {
Display::addFlash(Display::return_message(get_lang('ExerciseDeleted'), 'confirmation'));
if ($allowDelete) {
$result = $objExerciseTmp->delete();
if ($result) {
Display::addFlash(Display::return_message(get_lang('ExerciseDeleted'), 'confirmation'));
}
}
break;
case 'enable':
@ -375,7 +382,7 @@ if ($is_allowedToEdit) {
break;
case 'clean_results':
if ($limitTeacherAccess && !api_is_platform_admin()) {
if (false === $allowClean) {
// Teacher change exercise
break;
}
@ -548,21 +555,24 @@ if ($is_allowedToEdit && $origin !== 'learnpath') {
$actionsLeft .= '<a href="'.api_get_path(WEB_CODE_PATH).'exercise/upload_exercise.php?'.api_get_cidreq().'">'.
Display::return_icon('import_excel.png', get_lang('ImportExcelQuiz'), '', ICON_SIZE_MEDIUM).'</a>';
$cleanAll = Display::url(
Display::return_icon(
'clean_all.png',
get_lang('CleanAllStudentsResultsForAllTests'),
'',
ICON_SIZE_MEDIUM
),
'#',
[
'data-item-question' => addslashes(get_lang('AreYouSureToEmptyAllTestResults')),
'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('CleanAllStudentsResultsForAllTests'),
'',
ICON_SIZE_MEDIUM
),
'#',
[
'data-item-question' => addslashes(get_lang('AreYouSureToEmptyAllTestResults')),
'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()) {

@ -30,6 +30,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);
@ -326,37 +327,40 @@ if ($is_allowedToEdit && $origin != 'learnpath') {
Display::return_icon('reload.png', get_lang('RecalculateResults'), [], ICON_SIZE_MEDIUM),
api_get_path(WEB_CODE_PATH).'exercise/recalculate_all.php?'.api_get_cidreq()."&exercise=$exercise_id"
);
// clean result before a selected date icon
$actions .= Display::url(
Display::return_icon(
'clean_before_date.png',
get_lang('CleanStudentsResultsBeforeDate'),
'',
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('SelectADateOnTheCalendar'),
[
'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']
);
if ($allowClean) {
$actions .= Display::url(
Display::return_icon(
'clean_before_date.png',
get_lang('CleanStudentsResultsBeforeDate'),
'',
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('SelectADateOnTheCalendar'),
[
'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">'.
@ -434,7 +438,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(

@ -13,7 +13,7 @@ $courseInfo = api_get_course_info();
$tool = isset($_REQUEST['tool']) ? $_REQUEST['tool'] : '';
$type = isset($_REQUEST['type']) ? $_REQUEST['type'] : 'document'; // can be document or message
if ($type == 'document') {
if ($type === 'document') {
api_protect_course_script();
}
@ -48,6 +48,7 @@ switch ($type) {
if (!is_dir($saveDir)) {
mkdir($saveDir, api_get_permissions_for_new_directories(), true);
}
$uploadedDocument = DocumentManager::upload_document(
$file,
$audioDir,
@ -56,7 +57,13 @@ switch ($type) {
0,
'overwrite',
false,
in_array($tool, ['document', 'exercise'])
in_array($tool, ['document', 'exercise']),
'file',
true,
api_get_user_id(),
$courseInfo,
api_get_session_id(),
api_get_group_id()
);
$error = empty($uploadedDocument) || !is_array($uploadedDocument);

@ -27,11 +27,16 @@ window.RecordAudio = (function () {
formData.append('audio_blob', recordedBlob, fileName + fileExtension);
formData.append('audio_dir', rtcInfo.directory);
var courseParams = "";
if (rtcInfo.cidReq) {
courseParams = "&"+rtcInfo.cidReq;
}
$.ajax({
url: _p.web_ajax + 'record_audio_rtc.ajax.php?' + $.param({
type: rtcInfo.type,
tool: (!!txtName.length ? 'document' : 'exercise')
}),
}) + courseParams,
data: formData,
processData: false,
contentType: false,

@ -7002,6 +7002,19 @@ SQL;
return Database::num_rows($result) > 0;
}
/**
* @param int $userInfo
*
* @throws Exception
*/
public static function deleteUserFiles($userId)
{
$path = self::getUserPathById($userId, 'system');
$fs = new Filesystem();
$fs->remove($path);
}
/**
* @return EncoderFactory
*/
@ -7095,17 +7108,4 @@ SQL;
return $url;
}
/**
* @param int $userInfo
*
* @throws Exception
*/
public static function deleteUserFiles($userId)
{
$path = self::getUserPathById($userId, 'system');
$fs = new Filesystem();
$fs->remove($path);
}
}

@ -1529,6 +1529,9 @@ $_configuration['auth_password_links'] = [
// ALTER TABLE track_e_attempt_recording ADD COLUMN answer longtext default '' AFTER question_id;
//$_configuration['quiz_answer_extra_recording'] = false;
// Disable clean results for teachers
// $_configuration['disable_clean_exercise_results_for_teachers'] = true;
// KEEP THIS AT THE END
// -------- Custom DB changes
// Add user activation by confirmation email

@ -47,14 +47,14 @@ class ch_selectivedisplay extends ch_yesno
$(function() {
var hideQuestion = false;
$(".survey_question").each(function() {
if (hideQuestion) {
var questionClass = $(this).attr("class").trim();
if (hideQuestion) {
$(this).hide();
if ($(this).attr("class") === "survey_question ch_selectivedisplay") {
if (questionClass === "survey_question ch_selectivedisplay") {
$(this).show();
}
}
if ($( this ).attr("class") === "survey_question ch_selectivedisplay") {
if (questionClass === "survey_question ch_selectivedisplay") {
hideQuestion = true;
}
});

@ -267,7 +267,7 @@ if (Gradebook::is_active()) {
$surveytypes[0] = get_lang('Normal');
$surveytypes[1] = get_lang('Conditional');
if ($action == 'add') {
if ($action === 'add') {
$form->addElement('hidden', 'survey_type', 0);
$survey_tree = new SurveyTree();
$list_surveys = $survey_tree->createList($survey_tree->surveylist);
@ -281,7 +281,7 @@ $form->addElement('checkbox', 'shuffle', null, get_lang('ActivateShuffle'));
$input_name_list = null;
if ($action == 'edit' && !empty($survey_id)) {
if ($action === 'edit' && !empty($survey_id)) {
if ($survey_data['anonymous'] == 0) {
$form->addElement(
'checkbox',

@ -534,6 +534,13 @@ 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 '
@ -548,8 +555,22 @@ class survey_question
</script>';
}
/**
* 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;
@ -566,9 +587,17 @@ class survey_question
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::getDependecy($question);
$list = self::getDependency($question);
if (empty($list)) {
return '';
}
@ -603,8 +632,18 @@ class survey_question
return $js;
}
public static function getDependecy($question)
/**
* 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();
@ -619,6 +658,8 @@ class survey_question
}
/**
* This method is not implemented at this level (returns null).
*
* @param array $questionData
* @param array $answers
*/

@ -55,7 +55,7 @@
</div>
<script>
$(document).on('ready', function () {
$(function() {
RecordAudio.init(
{
blockId: '#record-audio-recordrtc',
@ -65,6 +65,7 @@
btnStopId: '#btn-stop-record',
btnSaveId: '#btn-save-record',
plyrPreviewId: '#record-preview',
cidReq :'{{ _p.web_cid_query }}',
directory: '{{ directory }}',
reload_page: 1,
type: 'document'

@ -187,6 +187,7 @@ class ImsLtiPlugin extends Plugin
advantage_services LONGTEXT DEFAULT NULL COMMENT '(DC2Type:json)',
version VARCHAR(255) DEFAULT 'lti1p1' NOT NULL,
launch_presentation LONGTEXT NOT NULL COMMENT '(DC2Type:json)',
replacement_params LONGTEXT NOT NULL COMMENT '(DC2Type:json)',
INDEX IDX_C5E47F7C91D79BD3 (c_id),
INDEX IDX_C5E47F7C82F80D8B (gradebook_eval_id),
INDEX IDX_C5E47F7C727ACA70 (parent_id),

Loading…
Cancel
Save