LPs: Read lp_item extra field 'no_automatic_validation' see BT#18568

Chamilo by default changes the lp item to status = complete when the
LP is a document. Setting the "no_automatic_validation" to true,
Chamilo will not do that. The HTML file will be in charge of that update
The document can update the status with LMSCommit('iframe');

Example in the HTML:

<script>
    document.addEventListener("DOMContentLoaded", function(event) {
        if (window.parent && window.parent.API) {
            let api = window.parent.API;
            if (api) {
                api.LMSSetValue('cmi.core.score.raw', 100);
                api.LMSSetValue("cmi.core.lesson_status", "completed");
                api.LMSCommit('iframe');
            }
        }
    });
</script>
pull/3859/head
Julio Montoya 5 years ago
parent 210eacf96a
commit 89d96ae259
  1. 10
      main/lp/learnpath.class.php
  2. 17
      main/lp/learnpathItem.class.php
  3. 2
      main/lp/lp_ajax_initialize.php
  4. 152
      main/lp/lp_ajax_save_item.php
  5. 11
      main/lp/lp_ajax_switch_item.php
  6. 5
      main/lp/lp_ajax_switch_item_toc.php
  7. 6
      main/lp/lp_edit_item.php
  8. 1
      main/lp/lp_view.php
  9. 30
      main/lp/scorm_api.php

@ -2574,6 +2574,7 @@ class learnpath
// path, then the rules are completely different: we assume only one
// item exists and the progress of the LP depends on the score
$scoreAsProgressSetting = api_get_configuration_value('lp_score_as_progress_enable');
if ($scoreAsProgressSetting === true) {
$scoreAsProgress = $this->getUseScoreAsProgress();
if ($scoreAsProgress) {
@ -2605,6 +2606,7 @@ class learnpath
if ($completeItems > $total_items) {
$completeItems = $total_items;
}
if ($mode == '%') {
if ($total_items > 0) {
$percentage = ((float) $completeItems / (float) $total_items) * 100;
@ -5596,10 +5598,14 @@ class learnpath
if ($debug) {
error_log('start_current_item will save item with prereq: '.$prereq_check);
}
$this->items[$this->current]->save(false, $prereq_check);
$saveStatus = learnpathItem::isLpItemAutoComplete($this->current);
if ($saveStatus) {
$this->items[$this->current]->save(false, $prereq_check);
}
}
// If sco, then it is supposed to have been updated by some other call.
if ($item_type == 'sco') {
if ($item_type === 'sco') {
$this->items[$this->current]->restart();
}
}

@ -4536,4 +4536,21 @@ class learnpathItem
return $resultFromOtherSessions;
}
}
public static function isLpItemAutoComplete($lpItemId): bool
{
$extraFieldValue = new ExtraFieldValue('lp_item');
$saveAutomatic = $extraFieldValue->get_values_by_handler_and_field_variable(
$lpItemId,
'no_automatic_validation'
);
if (false !== $saveAutomatic && is_array($saveAutomatic) && isset($saveAutomatic['value'])) {
if (1 === (int) $saveAutomatic['value']) {
return false;
}
}
return true;
}
}

@ -45,6 +45,7 @@ function initialize_item($lp_id, $user_id, $view_id, $next_item)
if ($debug) {
error_log('In initialize_item() - new item is '.$next_item);
}
$mylp->start_current_item(true);
if (is_object($mylp->items[$next_item])) {
@ -111,7 +112,6 @@ function initialize_item($lp_id, $user_id, $view_id, $next_item)
}
}
$myobjectives = json_encode($phpobjectives);
$return .=
"olms.score=".$myscore.";".
"olms.max=".$mymax.";".

@ -58,7 +58,8 @@ function save_item(
$courseId = null,
$lmsFinish = 0,
$userNavigatesAway = 0,
$statusSignalReceived = 0
$statusSignalReceived = 0,
$forceIframeSave = 0
) {
$debug = 0;
$return = null;
@ -107,6 +108,15 @@ function save_item(
// This functions sets the $this->db_item_view_id variable needed in get_status() see BT#5069
$myLPI->set_lp_view($view_id);
$my_type = $myLPI->get_type();
$saveStatus = true;
if ('document' === $my_type) {
$saveStatus = learnpathItem::isLpItemAutoComplete($myLPI->getIid());
if ($forceIframeSave) {
$saveStatus = true;
}
}
// Launch the prerequisites check and set error if needed
if (true !== $prerequisitesCheck) {
@ -171,16 +181,22 @@ function save_item(
}
$statusIsSet = false;
// Default behaviour.
if (isset($status) && $status != '' && $status != 'undefined') {
if ($debug > 1) {
error_log('Calling set_status('.$status.')');
}
if ($saveStatus) {
// Default behaviour.
if (isset($status) && $status != '' && $status != 'undefined') {
if ($debug > 1) {
error_log('Calling set_status('.$status.')');
}
$myLPI->set_status($status);
$statusIsSet = true;
if ($debug > 1) {
error_log('Done calling set_status: checking from memory: '.$myLPI->get_status(false));
$myLPI->set_status($status);
$statusIsSet = true;
if ($debug > 1) {
error_log('Done calling set_status: checking from memory: '.$myLPI->get_status(false));
}
} else {
if ($debug > 1) {
error_log('Status not updated');
}
}
} else {
if ($debug > 1) {
@ -188,7 +204,6 @@ function save_item(
}
}
$my_type = $myLPI->get_type();
// Set status to completed for hotpotatoes if score > 80%.
if ($my_type === 'hotpotatoes') {
if ((empty($status) || $status == 'undefined' || $status == 'not attempted') && $max > 0) {
@ -370,25 +385,30 @@ function save_item(
// End of type=='sco'
}
// If no previous condition changed the SCO status, proceed with a
// generic behaviour
if (!$statusIsSet && !$statusSignalReceived) {
// Default behaviour
if (isset($status) && $status != '' && $status != 'undefined') {
if ($debug > 1) {
error_log('Calling set_status('.$status.')');
}
// If no previous condition changed the SCO status, proceed with a generic behaviour
if ($saveStatus) {
if (!$statusIsSet && !$statusSignalReceived) {
// Default behaviour
if (isset($status) && $status != '' && $status != 'undefined') {
if ($debug > 1) {
error_log('Calling set_status('.$status.')');
}
$myLPI->set_status($status);
$myLPI->set_status($status);
if ($debug > 1) {
error_log('Done calling set_status: checking from memory: '.$myLPI->get_status(false));
}
} else {
if ($debug > 1) {
error_log("Status not updated");
if ($debug > 1) {
error_log('Done calling set_status: checking from memory: '.$myLPI->get_status(false));
}
} else {
if ($debug > 1) {
error_log("Status not updated");
}
}
}
} else {
if ($debug > 1) {
error_log("Status not updated");
}
}
if (isset($time) && $time != '' && $time != 'undefined') {
@ -440,7 +460,10 @@ function save_item(
if ($core_exit != 'undefined') {
$myLPI->set_core_exit($core_exit);
}
$myLP->save_item($item_id, false);
if ($saveStatus) {
$myLP->save_item($item_id, false);
}
}
$myStatusInDB = $myLPI->get_status(true);
@ -478,37 +501,39 @@ function save_item(
error_log("progress: $myComplete / $myTotal");
}
if ($myLPI->get_type() !== 'sco') {
// If this object's JS status has not been updated by the SCORM API, update now.
$return .= "olms.lesson_status='".$myStatus."';";
}
$return .= "update_toc('".$myStatus."','".$item_id."');";
$update_list = $myLP->get_update_queue();
foreach ($update_list as $my_upd_id => $my_upd_status) {
if ($my_upd_id != $item_id) {
/* Only update the status from other items (i.e. parents and brothers),
do not update current as we just did it already. */
$return .= "update_toc('".$my_upd_status."','".$my_upd_id."');";
if ($saveStatus) {
if ($myLPI->get_type() !== 'sco') {
// If this object's JS status has not been updated by the SCORM API, update now.
$return .= "olms.lesson_status='".$myStatus."';";
}
}
$progressBarSpecial = false;
$scoreAsProgressSetting = api_get_configuration_value('lp_score_as_progress_enable');
if ($scoreAsProgressSetting === true) {
$scoreAsProgress = $myLP->getUseScoreAsProgress();
if ($scoreAsProgress) {
// Only update score if it was set by scorm.
if (isset($score) && $score != -1) {
$score = $myLPI->get_score();
$maxScore = $myLPI->get_max();
$return .= "update_progress_bar('$score', '$maxScore', '$myProgressMode');";
$return .= "update_toc('".$myStatus."','".$item_id."');";
$update_list = $myLP->get_update_queue();
foreach ($update_list as $my_upd_id => $my_upd_status) {
if ($my_upd_id != $item_id) {
/* Only update the status from other items (i.e. parents and brothers),
do not update current as we just did it already. */
$return .= "update_toc('".$my_upd_status."','".$my_upd_id."');";
}
$progressBarSpecial = true;
}
}
if (!$progressBarSpecial) {
$return .= "update_progress_bar('$myComplete', '$myTotal', '$myProgressMode');";
$progressBarSpecial = false;
$scoreAsProgressSetting = api_get_configuration_value('lp_score_as_progress_enable');
if ($scoreAsProgressSetting === true) {
$scoreAsProgress = $myLP->getUseScoreAsProgress();
if ($scoreAsProgress) {
// Only update score if it was set by scorm.
if (isset($score) && $score != -1) {
$score = $myLPI->get_score();
$maxScore = $myLPI->get_max();
$return .= "update_progress_bar('$score', '$maxScore', '$myProgressMode');";
}
$progressBarSpecial = true;
}
}
if (!$progressBarSpecial) {
$return .= "update_progress_bar('$myComplete', '$myTotal', '$myProgressMode');";
}
}
if (!Session::read('login_as')) {
@ -537,15 +562,17 @@ function save_item(
$return .= 'update_stats();';
}
// To be sure progress is updated.
$myLP->save_last($score);
if ($saveStatus) {
// To be sure progress is updated.
$myLP->save_last($score);
HookLearningPathItemViewed::create()
->setEventData(['item_view_id' => $myLPI->db_item_view_id])
->notifyLearningPathItemViewed();
HookLearningPathItemViewed::create()
->setEventData(['item_view_id' => $myLPI->db_item_view_id])
->notifyLearningPathItemViewed();
Session::write('lpobject', serialize($myLP));
Session::write('oLP', $myLP);
}
Session::write('lpobject', serialize($myLP));
Session::write('oLP', $myLP);
if ($debug > 0) {
error_log("lp_view_session_id :".$myLP->lp_view_session_id);
error_log('---------------- lp_ajax_save_item.php : save_item end ----- ');
@ -593,5 +620,6 @@ echo save_item(
(!empty($_REQUEST['course_id']) ? $_REQUEST['course_id'] : ''),
(empty($_REQUEST['finish']) ? 0 : 1),
(empty($_REQUEST['userNavigatesAway']) ? 0 : 1),
(empty($_REQUEST['statusSignalReceived']) ? 0 : 1)
(empty($_REQUEST['statusSignalReceived']) ? 0 : 1),
isset($_REQUEST['forceIframeSave']) ? (int) $_REQUEST['forceIframeSave'] : 0
);

@ -44,6 +44,8 @@ function switch_item_details($lp_id, $user_id, $view_id, $current_item, $next_it
*/
$mylp = learnpath::getLpFromSession(api_get_course_id(), $lp_id, $user_id);
$new_item_id = 0;
$saveStatus = learnpathItem::isLpItemAutoComplete($current_item);
switch ($next_item) {
case 'next':
$mylp->set_current_item($current_item);
@ -93,8 +95,11 @@ function switch_item_details($lp_id, $user_id, $view_id, $current_item, $next_it
}
$mylp->start_current_item(true);
if ($mylp->force_commit) {
$mylp->save_current();
if ($saveStatus) {
if ($mylp->force_commit) {
$mylp->save_current();
}
}
if (is_object($mylp->items[$new_item_id])) {
@ -106,6 +111,7 @@ function switch_item_details($lp_id, $user_id, $view_id, $current_item, $next_it
$mylpi = new learnpathItem($new_item_id, $user_id);
$mylpi->set_lp_view($view_id);
}
/*
* now get what's needed by the SCORM API:
* -score
@ -263,7 +269,6 @@ function switch_item_details($lp_id, $user_id, $view_id, $current_item, $next_it
"update_progress_bar('$mycomplete','$mytotal','$myprogress_mode');".
$updateMinTime
;
$return .= 'updateGamificationValues(); ';
$mylp->set_error_msg('');
$mylp->prerequisites_match(); // Check the prerequisites are all complete.

@ -34,6 +34,8 @@ function switch_item_toc($lpId, $userId, $viewId, $currentItem, $nextItem)
error_log('In switch_item_toc('.$lpId.','.$userId.','.$viewId.','.$currentItem.','.$nextItem.')', 0);
}
$myLP = learnpath::getLpFromSession(api_get_course_id(), $lpId, $userId);
$saveStatus = learnpathItem::isLpItemAutoComplete($currentItem);
$newItemId = 0;
$oldItemId = 0;
switch ($nextItem) {
@ -79,7 +81,8 @@ function switch_item_toc($lpId, $userId, $viewId, $currentItem, $nextItem)
break;
}
$myLP->start_current_item(true);
if ($myLP->force_commit) {
if ($myLP->force_commit && $saveStatus) {
$myLP->save_current();
}
if (is_object($myLP->items[$newItemId])) {

@ -151,7 +151,7 @@ if (empty($documentInfo)) {
$path_parts = pathinfo($path_file);
if (!empty($path_file) && isset($path_parts['extension']) && $path_parts['extension'] == 'html') {
if (!empty($path_file) && isset($path_parts['extension']) && $path_parts['extension'] === 'html') {
echo $learnPath->return_new_tree();
// Show the template list
echo '<div id="frmModel" class="scrollbar-inner lp-add-item"></div>';
@ -167,6 +167,7 @@ $excludeExtraFields = [
'authorlpitem',
'price',
];
if (api_is_platform_admin()) {
// Only admins can edit this items
$excludeExtraFields = [];
@ -178,6 +179,9 @@ if (isset($is_success) && $is_success === true) {
echo $learnPath->display_item($_GET['id'], $msg);
} else {
$item = $learnPath->getItem($_GET['id']);
if ('document' !== $item->get_type()) {
$excludeExtraFields[] = 'no_automatic_validation';
}
echo $learnPath->display_edit_item($item->getIid(), $excludeExtraFields);
$finalItem = Session::read('finalItem');
if ($finalItem) {

@ -288,6 +288,7 @@ if (!isset($src)) {
break;
}
// This change the status to complete in Chamilo LP.
$lp->start_current_item(); // starts time counter manually if asset
} else {
$src = 'blank.php?error=prerequisites';

@ -280,7 +280,6 @@ function LMSInitialize() {
olms.G_LastError = G_NoError ;
olms.G_LastErrorMessage = 'No error';
olms.lms_initialized = 0;
olms.finishSignalReceived = 0;
olms.statusSignalReceived = 0;
@ -874,7 +873,7 @@ function SetValue(param, val) {
/**
* Saves the current data from JS memory to the LMS database
*/
function savedata(item_id) {
function savedata(item_id, forceIframeSave = 0) {
// Origin can be 'commit', 'finish' or 'terminate' (depending on the calling function)
logit_lms('function savedata(' + item_id + ')', 3);
@ -883,6 +882,10 @@ function savedata(item_id) {
//olms.updatable_vars_list['cmi.core.lesson_status'] = true;
}
if (typeof(forceIframeSave) == 'undefined') {
forceIframeSave = 0;
}
old_item_id = olms.info_lms_item[0];
var item_to_save = olms.lms_item_id;
logit_lms('item_to_save (original value): ' + item_to_save, 3);
@ -890,7 +893,7 @@ function savedata(item_id) {
// If saving session_time value, we assume that all the new info is about
// the old item, not the current one
// if (olms.session_time != '' && olms.session_time != '0') {
if (olms.switch_finished == 0) {
if (olms.switch_finished == 0 && forceIframeSave == 0) {
logit_lms('item_to_save (changed to): ' + old_item_id, 3);
item_to_save = old_item_id;
}
@ -904,7 +907,9 @@ function savedata(item_id) {
olms.lms_course_id,
olms.finishSignalReceived,
olms.userNavigatesAway,
olms.statusSignalReceived
olms.statusSignalReceived,
false,
forceIframeSave
);
olms.info_lms_item[1] = olms.lms_item_id;
@ -935,7 +940,13 @@ function LMSCommit(val) {
olms.G_LastError = G_NoError ;
olms.G_LastErrorMessage = 'No error';
savedata(olms.lms_item_id);
let forceIframeSave = 0;
if (val && 'iframe' == val) {
forceIframeSave = 1;
}
console.log(forceIframeSave);
savedata(olms.lms_item_id, forceIframeSave);
//reinit_updatable_vars_list();
logit_scorm('LMSCommit() end ', 0);
@ -1927,7 +1938,8 @@ function xajax_save_item_scorm(
finishSignalReceived,
userNavigatesAway,
statusSignalReceived,
useSendBeacon
useSendBeacon,
forceIframeSave
) {
if (typeof(finishSignalReceived) == 'undefined') {
finishSignalReceived = 0;
@ -1940,6 +1952,10 @@ function xajax_save_item_scorm(
statusSignalReceived = 0;
}
if (typeof(forceIframeSave) == 'undefined') {
forceIframeSave = 0;
}
var is_interactions='false';
var params = 'lid='+lms_lp_id+'&uid='+lms_user_id+'&vid='+lms_view_id+'&iid='+lms_item_id;
// The missing arguments will be ignored by lp_ajax_save_item.php
@ -1949,6 +1965,8 @@ function xajax_save_item_scorm(
params += '&finishSignalReceived='+finishSignalReceived;
params += '&userNavigatesAway='+userNavigatesAway;
params += '&statusSignalReceived='+statusSignalReceived;
params += '&forceIframeSave='+forceIframeSave;
var my_scorm_values = new Array();
my_scorm_values = process_scorm_values();
for (k=0; k < my_scorm_values.length; k++) {

Loading…
Cancel
Save