1.9.x
Julio Montoya 12 years ago
commit b42a761156
  1. 167
      main/admin/extra_field_options.php
  2. 212
      main/admin/extra_field_workflow.php
  3. 218
      main/admin/extra_fields.php
  4. 27
      main/announcements/announcement_email.class.php
  5. 31
      main/announcements/announcements.inc.php
  6. 6
      main/announcements/announcements.php
  7. 13
      main/course_description/course_description_controller.php
  8. 3
      main/document/document.php
  9. 88
      main/exercice/exercise.class.php
  10. 18
      main/exercice/exercise.lib.php
  11. 2
      main/exercice/exercise_show.php
  12. 84
      main/inc/ajax/course.ajax.php
  13. 14
      main/inc/ajax/course_home.ajax.php
  14. 30
      main/inc/ajax/extra_field.ajax.php
  15. 152
      main/inc/ajax/model.ajax.php
  16. 29
      main/inc/ajax/session.ajax.php
  17. 2
      main/inc/global_error_message.inc.php
  18. 6
      main/inc/introductionSection.inc.php
  19. 5
      main/inc/lib/autoload.class.php
  20. 29
      main/inc/lib/course.lib.php
  21. 4
      main/inc/lib/database.constants.inc.php
  22. 43
      main/inc/lib/display.lib.php
  23. 17
      main/inc/lib/document.lib.php
  24. 29
      main/inc/lib/events.lib.inc.php
  25. 41
      main/inc/lib/export.lib.inc.php
  26. 1648
      main/inc/lib/extra_field.lib.php
  27. 659
      main/inc/lib/extra_field_option.lib.php
  28. 654
      main/inc/lib/extra_field_value.lib.php
  29. 1
      main/inc/lib/fckeditor/editor/plugins/ImageManager/config.inc.php
  30. 12
      main/inc/lib/fileUpload.lib.php
  31. 22
      main/inc/lib/formvalidator/Element/select_ajax.php
  32. 8
      main/inc/lib/main_api.lib.php
  33. 16
      main/inc/lib/pear/HTML/QuickForm.php
  34. 1270
      main/inc/lib/sessionmanager.lib.php
  35. 611
      main/inc/lib/tracking.lib.php
  36. 19
      main/inc/lib/usermanager.lib.php
  37. 8
      main/inc/local.inc.php
  38. 1
      main/lang/english/admin.inc.php
  39. 1
      main/lang/spanish/admin.inc.php
  40. 6
      main/lang/spanish/tracking.inc.php
  41. 1
      main/lang/spanish_latin/trad4all.inc.php
  42. 38
      main/mySpace/myStudents.php
  43. 281
      main/mySpace/myspace.lib.php
  44. 2
      main/newscorm/learnpathList.class.php
  45. 10
      main/newscorm/lp_ajax_save_item.php
  46. 6
      main/newscorm/lp_controller.php
  47. 20
      main/newscorm/lp_edit.php
  48. 10
      main/newscorm/lp_stats.php
  49. 22
      main/newscorm/scorm_api.php
  50. 11
      main/session/index.php

@ -0,0 +1,167 @@
<?php
/* For licensing terms, see /license.txt */
/**
* @package chamilo.admin
*/
// Language files that need to be included.
$language_file = array('admin');
$cidReset = true;
require_once '../inc/global.inc.php';
$this_section = SECTION_PLATFORM_ADMIN;
$type = isset($_REQUEST['type']) ? $_REQUEST['type'] : null;
api_protect_admin_script();
//Add the JS needed to use the jqgrid
$htmlHeadXtra[] = api_get_jqgrid_js();
// setting breadcrumbs
$interbreadcrumb[]=array('url' => 'index.php','name' => get_lang('PlatformAdmin'));
$tool_name = null;
$action = isset($_GET['action']) ? $_GET['action'] : null;
$field_id = isset($_GET['field_id']) ? $_GET['field_id'] : null;
if (empty($field_id)) {
api_not_allowed();
}
if (!in_array($type, ExtraField::getValidExtraFieldTypes())) {
api_not_allowed();
}
$extra_field = new ExtraField($type);
$extra_field_info = $extra_field->get($field_id);
$check = Security::check_token('request');
$token = Security::get_token();
if ($action == 'add') {
$interbreadcrumb[]=array('url' => 'extra_fields.php?type='.$extra_field->type,'name' => $extra_field->pageName);
$interbreadcrumb[]=array('url' => 'extra_fields.php?type='.$extra_field->type.'&action=edit&id='.$extra_field_info['id'],'name' => $extra_field_info['field_display_text']);
$interbreadcrumb[]=array('url' => 'extra_field_options.php?type='.$extra_field->type.'&field_id='.$extra_field_info['id'], 'name' => get_lang('EditExtraFieldOptions'));
$interbreadcrumb[]=array('url' => '#','name' => get_lang('Add'));
} elseif ($action == 'edit') {
$interbreadcrumb[]=array('url' => 'extra_fields.php?type='.$extra_field->type,'name' => $extra_field->pageName);
$interbreadcrumb[]=array('url' => 'extra_fields.php?type='.$extra_field->type.'&action=edit&id='.$extra_field_info['id'],'name' => $extra_field_info['field_display_text']);
$interbreadcrumb[]=array('url' => 'extra_field_options.php?type='.$extra_field->type.'&field_id='.$extra_field_info['id'], 'name' => get_lang('EditExtraFieldOptions'));
$interbreadcrumb[]=array('url' => '#','name' => get_lang('Edit'));
} else {
$interbreadcrumb[]=array('url' => 'extra_fields.php?type='.$extra_field->type,'name' => $extra_field->pageName);
$interbreadcrumb[]=array('url' => 'extra_fields.php?type='.$extra_field->type.'&action=edit&id='.$extra_field_info['id'],'name' => $extra_field_info['field_display_text']);
$interbreadcrumb[]=array('url' => '#','name' => get_lang('EditExtraFieldOptions'));
}
//jqgrid will use this URL to do the selects
$params = 'field_id='.$field_id.'&type='.$extra_field->type;
$url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_extra_field_options&'.$params;
//The order is important you need to check the the $column variable in the model.ajax.php file
$columns = array(get_lang('Name'), get_lang('Value'), get_lang('Order'), get_lang('Actions'));
//Column config
$column_model = array(
array('name'=>'option_display_text', 'index'=>'option_display_text', 'width'=>'180', 'align'=>'left'),
array('name'=>'option_value', 'index'=>'option_value', 'width'=>'', 'align'=>'left','sortable'=>'false'),
array('name'=>'option_order', 'index'=>'option_order', 'width'=>'', 'align'=>'left','sortable'=>'false'),
array('name'=>'actions', 'index'=>'actions', 'width'=>'100', 'align'=>'left','formatter'=>'action_formatter','sortable'=>'false')
);
//Autowidth
$extra_params['autowidth'] = 'true';
//height auto
$extra_params['height'] = 'auto';
//With this function we can add actions to the jgrid (edit, delete, etc)
$action_links = 'function action_formatter(cellvalue, options, rowObject) {
return \'<a href="?action=edit&'.$params.'&id=\'+options.rowId+\'">'.Display::return_icon('edit.png',get_lang('Edit'),'',ICON_SIZE_SMALL).'</a>'.
'&nbsp;<a onclick="javascript:if(!confirm('."\'".addslashes(get_lang("ConfirmYourChoice"))."\'".')) return false;" href="?sec_token='.$token.'&action=delete&'.$params.'&id=\'+options.rowId+\'">'.Display::return_icon('delete.png',get_lang('Delete'),'',ICON_SIZE_SMALL).'</a>'.
'\';
}';
$htmlHeadXtra[]='
<script>
$(function() {
// grid definition see the $obj->display() function
'.Display::grid_js('extra_field_options', $url, $columns, $column_model, $extra_params, array(), $action_links, true).'
});
</script>';
// The header.
Display::display_header($tool_name);
echo Display::page_header($extra_field_info['field_display_text']);
$obj = new ExtraFieldOption($extra_field->type);
$obj->field_id = $field_id;
// Action handling: Add
switch ($action) {
case 'add':
if (api_get_session_id() != 0 && !api_is_allowed_to_session_edit(false, true)) {
api_not_allowed();
}
$url = api_get_self().'?action='.Security::remove_XSS($_GET['action']).'&'.$params;
$form = $obj->return_form($url, 'add');
// The validation or display
if ($form->validate()) {
if ($check) {
$values = $form->exportValues();
$res = $obj->save_one_item($values);
if ($res) {
Display::display_confirmation_message(get_lang('ItemAdded'));
}
}
$obj->display();
} else {
/*echo '<div class="actions">';
echo '<a href="'.api_get_self().'">'.Display::return_icon('back.png',get_lang('Back'),'',ICON_SIZE_MEDIUM).'</a>';
echo '</div>'; */
$form->addElement('hidden', 'sec_token');
$form->setConstants(array('sec_token' => $token));
$form->display();
}
break;
case 'edit':
// Action handling: Editing
$url = api_get_self().'?action='.Security::remove_XSS($_GET['action']).'&id='.intval($_GET['id']).'&'.$params;
$form = $obj->return_form($url, 'edit');
// The validation or display
if ($form->validate()) {
if ($check) {
$values = $form->exportValues();
$res = $obj->update($values);
Display::display_confirmation_message(sprintf(get_lang('ItemUpdated'), $values['name']), false);
}
$obj->display();
} else {
/*echo '<div class="actions">';
echo '<a href="'.api_get_self().'">'.Display::return_icon('back.png',get_lang('Back'),'',ICON_SIZE_MEDIUM).'</a>';
echo '</div>';*/
$form->addElement('hidden', 'sec_token');
$form->setConstants(array('sec_token' => $token));
$form->display();
}
break;
case 'delete':
// Action handling: delete
if ($check) {
$res = $obj->delete($_GET['id']);
if ($res) {
Display::display_confirmation_message(get_lang('ItemDeleted'));
}
}
$obj->display();
break;
default:
$obj->display();
break;
}
Display :: display_footer();

@ -0,0 +1,212 @@
<?php
/* For licensing terms, see /license.txt */
/**
* @package chamilo.admin
*/
// Language files that need to be included.
$language_file = array('admin');
$cidReset = true;
require_once '../inc/global.inc.php';
$this_section = SECTION_PLATFORM_ADMIN;
$type = isset($_REQUEST['type']) ? $_REQUEST['type'] : null;
api_protect_admin_script();
// setting breadcrumbs
$interbreadcrumb[] = array('url' => 'index.php','name' => get_lang('PlatformAdmin'));
$tool_name = null;
$action = isset($_GET['action']) ? $_GET['action'] : null;
$field_id = isset($_GET['field_id']) ? $_GET['field_id'] : null;
if (empty($field_id)) {
api_not_allowed();
}
if (!in_array($type, ExtraField::getValidExtraFieldTypes())) {
api_not_allowed();
}
$extraField = new ExtraField($type);
$extraFieldInfo = $extraField->get($field_id);
$check = Security::check_token('request');
$token = Security::get_token();
if ($action == 'add') {
$interbreadcrumb[]=array('url' => 'extra_fields.php?type='.$extraField->type,'name' => $extraField->pageName);
$interbreadcrumb[]=array('url' => 'extra_fields.php?type='.$extraField->type.'&action=edit&id='.$extraFieldInfo['id'],'name' => $extraFieldInfo['field_display_text']);
$interbreadcrumb[]=array('url' => 'extra_field_options.php?type='.$extraField->type.'&field_id='.$extraFieldInfo['id'], 'name' => get_lang('EditExtraFieldOptions'));
$interbreadcrumb[]=array('url' => '#','name' => get_lang('Add'));
} elseif ($action == 'edit') {
$interbreadcrumb[]=array('url' => 'extra_fields.php?type='.$extraField->type,'name' => $extraField->pageName);
$interbreadcrumb[]=array('url' => 'extra_fields.php?type='.$extraField->type.'&action=edit&id='.$extraFieldInfo['id'],'name' => $extraFieldInfo['field_display_text']);
$interbreadcrumb[]=array('url' => 'extra_field_options.php?type='.$extraField->type.'&field_id='.$extraFieldInfo['id'], 'name' => get_lang('EditExtraFieldOptions'));
$interbreadcrumb[]=array('url' => '#','name' => get_lang('Edit'));
} else {
$interbreadcrumb[]=array('url' => 'extra_fields.php?type='.$extraField->type,'name' => $extraField->pageName);
$interbreadcrumb[]=array('url' => 'extra_fields.php?type='.$extraField->type.'&action=edit&id='.$extraFieldInfo['id'],'name' => $extraFieldInfo['field_display_text']);
$interbreadcrumb[]=array('url' => '#','name' => get_lang('EditExtraFieldOptions'));
}
$roleId = isset($_REQUEST['roleId']) ? $_REQUEST['roleId'] : null;
//jqgrid will use this URL to do the selects
$params = 'field_id='.$field_id.'&type='.$extraField->type.'&roleId='.$roleId;
$paramsNoRole = 'field_id='.$field_id.'&type='.$extraField->type;
//The order is important you need to check the the $column variable in the model.ajax.php file
$columns = array(get_lang('Name'), get_lang('Value'), get_lang('Order'), get_lang('Actions'));
$htmlHeadXtra[]='<script>
function setHidden(obj) {
var name = $(obj).attr("name");
var hiddenName = "hidden_" + name;
if ($("#" + hiddenName).attr("value") == 1) {
$("#" + hiddenName).attr("value", 0);
} else {
$("#" + hiddenName).attr("value", 1);
}
}
function changeStatus(obj) {
var roleId = $(obj).find(":selected").val();
if (roleId != 0) {
window.location.replace("'.api_get_self().'?'.$paramsNoRole.'&roleId="+roleId);
}
}
$().ready( function() {
$(".select_all").on("click", function() {
$("#workflow :checkbox").prop("checked", 1);
$("#workflow :hidden").prop("value", 1);
return false;
});
$(".unselect_all").on("click", function() {
$("#workflow :checkbox").prop("checked", 0);
$("#workflow :hidden").prop("value", 0);
return false;
});
});
</script>';
// The header.
Display::display_header($tool_name);
echo Display::page_header($extraFieldInfo['field_display_text']);
$obj = new ExtraFieldOption($type);
$columns = array('option_display_text', 'option_value', 'option_order');
$result = Database::select('*', $obj->table, array('where' => array("field_id = ? " => $field_id), 'order'=>"option_order ASC"));
$table = new HTML_Table(array('class' => 'data_table'));
$column = 0;
$row = 0;
$table->setHeaderContents($row, $column, get_lang('CurrentStatus'));
$column++;
foreach ($result as $item) {
$table->setHeaderContents($row, $column, $item['option_display_text']);
$column++;
}
$row++;
$form = new FormValidator('workflow', 'post', api_get_self().'?'.$params);
$options = api_get_user_roles();
$options[0] = get_lang('SelectAnOption');
ksort($options);
$form->addElement('select', 'status', get_lang('SelectRole'), $options, array('onclick' => 'changeStatus(this)'));
$checks = $app['orm.em']->getRepository('ChamiloLMS\Entity\ExtraFieldOptionRelFieldOption')->findBy(array('fieldId' => $field_id, 'roleId' => $roleId));
$includedFields = array();
if (!empty($checks)) {
foreach ($checks as $availableField) {
$includedFields[$availableField->getFieldOptionId()][] = $availableField->getRelatedFieldOptionId();
}
}
foreach ($result as $item) {
$column = 0;
$table->setCellContents($row, $column, $item['option_display_text']);
$column++;
$value = null;
foreach ($result as $itemCol) {
$id = 'extra_field_status_'.$item['id'].'_'.$itemCol['id'];
$idForm = 'extra_field_status['.$item['id'].']['.$itemCol['id'].']';
$attributes = array('onclick' => 'setHidden(this)');
$value = 0;
if (isset($includedFields[$itemCol['id']]) && in_array($item['id'], $includedFields[$itemCol['id']])) {
$value = 1;
$attributes['checked'] = 'checked';
}
$element = Display::input('checkbox', $id, null, $attributes);
$table->setCellContents($row, $column, $element);
$form->addElement('hidden', 'hidden_'.$idForm, $value, array('id' => 'hidden_'.$id));
$column++;
}
$row++;
}
if (!empty($roleId)) {
$form->addElement('html', $table->toHtml());
$group = array();
$group[]= $form->createElement('button', 'submit', get_lang('Save'));
$group[]= $form->createElement('button', 'select_all', get_lang('SelectAll'), array('class' => 'btn select_all'));
$group[]= $form->createElement('button', 'unselect_all', get_lang('UnSelectAll'), array('class' => 'btn unselect_all'));
$form->addGroup($group, '', null, ' ');
$form->setDefaults(array('status' => $roleId));
} else {
$form->addElement('button', 'submit', get_lang('Edit'));
}
$form->display();
if ($form->validate()) {
$values = $form->getSubmitValues();
$result = $values['hidden_extra_field_status'];
if (!empty($result)) {
foreach ($result as $id => $items) {
foreach ($items as $subItemId => $value) {
$extraFieldOptionRelFieldOption = $app['orm.em']->getRepository('ChamiloLMS\Entity\ExtraFieldOptionRelFieldOption')->findOneBy(
array(
'fieldId' => $field_id,
'fieldOptionId' => $subItemId,
'roleId' => $roleId,
'relatedFieldOptionId' => $id
)
);
if ($value == 1) {
if (empty($extraFieldOptionRelFieldOption)) {
$extraFieldOptionRelFieldOption = new \ChamiloLMS\Entity\ExtraFieldOptionRelFieldOption();
$extraFieldOptionRelFieldOption->setFieldId($field_id);
$extraFieldOptionRelFieldOption->setFieldOptionId($subItemId);
$extraFieldOptionRelFieldOption->setRelatedFieldOptionId($id);
$extraFieldOptionRelFieldOption->setRoleId($roleId);
$app['orm.ems']['db_write']->persist($extraFieldOptionRelFieldOption);
}
} else {
if ($extraFieldOptionRelFieldOption) {
$app['orm.ems']['db_write']->remove($extraFieldOptionRelFieldOption);
}
}
}
}
$app['orm.ems']['db_write']->flush();
header('Location:'.api_get_self().'?'.$params);
exit;
}
}
Display :: display_footer();

@ -0,0 +1,218 @@
<?php
/* For licensing terms, see /license.txt */
/**
* @package chamilo.admin
*/
// Language files that need to be included.
$language_file = array('admin');
$cidReset = true;
$cidReset = true;
require_once '../inc/global.inc.php';
$extraFieldType = isset($_REQUEST['type']) ? $_REQUEST['type'] : null;
$this_section = SECTION_PLATFORM_ADMIN;
api_protect_admin_script();
//Add the JS needed to use the jqgrid
$htmlHeadXtra[] = api_get_jqgrid_js();
// setting breadcrumbs
$interbreadcrumb[]=array('url' => 'index.php','name' => get_lang('PlatformAdmin'));
$tool_name = null;
$action = isset($_GET['action']) ? $_GET['action'] : null;
if (!in_array($extraFieldType, ExtraField::getValidExtraFieldTypes())) {
api_not_allowed();
}
$check = Security::check_token('request');
$token = Security::get_token();
$obj = new ExtraField($extraFieldType);
$obj->setupBreadcrumb($interbreadcrumb, $action);
//jqgrid will use this URL to do the selects
$url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_extra_fields&type='.$extraFieldType;
//The order is important you need to check the the $column variable in the model.ajax.php file
$columns = $obj->getJqgridColumnNames();
//Column config
$column_model = $obj->getJqgridColumnModel();
//Autowidth
$extra_params['autowidth'] = 'true';
//height auto
$extra_params['height'] = 'auto';
$extra_params['sortname'] = 'field_order';
$action_links = $obj->getJqgridActionLinks($token);
$htmlHeadXtra[]='<script>
$(function() {
// grid definition see the $obj->display() function
'.Display::grid_js($obj->type.'_fields', $url, $columns, $column_model, $extra_params, array(), $action_links, true).'
$("#field_type").on("change", function() {
id = $(this).val();
switch(id) {
case "1":
$("#example").html("'.addslashes(Display::return_icon('userfield_text.png')).'");
break;
case "2":
$("#example").html("'.addslashes(Display::return_icon('userfield_text_area.png')).'");
break;
case "3":
$("#example").html("'.addslashes(Display::return_icon('add_user_field_howto.png')).'");
break;
case "4":
$("#example").html("'.addslashes(Display::return_icon('userfield_drop_down.png')).'");
break;
case "5":
$("#example").html("'.addslashes(Display::return_icon('userfield_multidropdown.png')).'");
break;
case "6":
$("#example").html("'.addslashes(Display::return_icon('userfield_data.png')).'");
break;
case "7":
$("#example").html("'.addslashes(Display::return_icon('userfield_date_time.png')).'");
break;
case "8":
$("#example").html("'.addslashes(Display::return_icon('userfield_doubleselect.png')).'");
break;
case "9":
$("#example").html("'.addslashes(Display::return_icon('userfield_divider.png')).'");
break;
case "10":
$("#example").html("'.addslashes(Display::return_icon('userfield_user_tag.png')).'");
break;
case "11":
$("#example").html("'.addslashes(Display::return_icon('userfield_data.png')).'");
break;
}
});
});
</script>';
// The header.
Display::display_header($tool_name);
// Action handling: Add
switch ($action) {
case 'add':
if (api_get_session_id() != 0 && !api_is_allowed_to_session_edit(false, true)) {
api_not_allowed();
}
$url = api_get_self().'?type='.$obj->type.'&action='.Security::remove_XSS($_GET['action']);
$form = $obj->return_form($url, 'add');
// The validation or display
if ($form->validate()) {
//if ($check) {
$values = $form->exportValues();
$res = $obj->save($values);
if ($res) {
Display::display_confirmation_message(get_lang('ItemAdded'));
}
//}
$obj->display();
} else {
echo '<div class="actions">';
echo '<a href="'.api_get_self().'?type='.$obj->type.'">'.Display::return_icon('back.png',get_lang('Back'),'',ICON_SIZE_MEDIUM).'</a>';
echo '</div>';
$form->addElement('hidden', 'sec_token');
$form->setConstants(array('sec_token' => $token));
$form->display();
}
break;
case 'edit':
// Action handling: Editing
$url = api_get_self().'?type='.$obj->type.'&action='.Security::remove_XSS($_GET['action']).'&id='.intval($_GET['id']);
$form = $obj->return_form($url, 'edit');
// The validation or display
if ($form->validate()) {
//if ($check) {
$values = $form->exportValues();
$res = $obj->update($values);
Display::display_confirmation_message(sprintf(get_lang('ItemUpdated'), $values['field_variable']), false);
//}
$obj->display();
} else {
echo '<div class="actions">';
echo '<a href="'.api_get_self().'?type='.$obj->type.'">'.Display::return_icon('back.png',get_lang('Back'),'',ICON_SIZE_MEDIUM).'</a>';
echo '</div>';
$form->addElement('hidden', 'sec_token');
$form->setConstants(array('sec_token' => $token));
$form->display();
}
break;
case 'delete':
// Action handling: delete
//if ($check) {
$res = $obj->delete($_GET['id']);
if ($res) {
Display::display_confirmation_message(get_lang('ItemDeleted'));
}
//}
$obj->display();
break;
default:
$obj->display();
break;
}
Display :: display_footer();
/*
CREATE TABLE IF NOT EXISTS lp_field(
id INT NOT NULL auto_increment,
field_type int NOT NULL DEFAULT 1,
field_variable varchar(64) NOT NULL,
field_display_text varchar(64),
field_default_value text,
field_order int,
field_visible tinyint default 0,
field_changeable tinyint default 0,
field_filter tinyint default 0,
tms DATETIME NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY(id)
);
DROP TABLE IF EXISTS lp_field_options;
CREATE TABLE IF NOT EXISTS lp_field_options (
id int NOT NULL auto_increment,
field_id int NOT NULL,
option_value text,
option_display_text varchar(64),
option_order int,
tms DATETIME NOT NULL default '0000-00-00 00:00:00',
priority VARCHAR(255),
priority_message VARCHAR(255),
PRIMARY KEY (id)
);
DROP TABLE IF EXISTS lp_field_values;
CREATE TABLE IF NOT EXISTS lp_field_values(
id bigint NOT NULL auto_increment,
lp_id int unsigned NOT NULL,
field_id int NOT NULL,
field_value text,
comment VARCHAR(100) default '',
tms DATETIME NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY(id)
);
ALTER TABLE lp_field_values ADD INDEX (lp_id, field_id);
*/

@ -220,13 +220,16 @@ class AnnouncementEmail
*/
public function message($receiverUserId)
{
//$title = $this->announcement('title');
$content = $this->announcement('content');
$content = stripslashes($content);
$content = AnnouncementManager::parse_content($receiverUserId, $content, $this->course('code'));
$content = AnnouncementManager::parse_content($content, $this->course('code'), $session_id);
$session_id = $this->session_id;
$user_email = $this->sender('mail');
$course_param = api_get_cidreq();
//$course_param = api_get_cidreq();
// Build the link by hand because api_get_cidreq() doesn't accept course params
$course_param = 'cidReq='.api_get_course_id().'&amp;id_session='.$session_id.'&amp;gidReq='.api_get_group_id();
$course_name = $this->course('title');
$result = "<div>$content</div>";
@ -277,7 +280,7 @@ class AnnouncementEmail
/**
* Send emails to users.
*/
public function send()
public function send($sendToUsersInSession = false)
{
$sender = $this->sender();
$subject = $this->subject();
@ -294,6 +297,22 @@ class AnnouncementEmail
$sender['user_id']
);
}
if ($sendToUsersInSession) {
$sessionList = SessionManager::get_session_by_course($this->course['code']);
if (!empty($sessionList)) {
foreach ($sessionList as $sessionInfo) {
$sessionId = $sessionInfo['id'];
$message = $this->message(null, $sessionId);
$userList = CourseManager::get_user_list_from_course_code($this->course['code'], $sessionId);
if (!empty($userList)) {
foreach ($userList as $user) {
MessageManager::send_message_simple($user['user_id'], $subject, $message, $sender['user_id']);
}
}
}
}
}
$this->log_mail_sent();
}

@ -1,15 +1,11 @@
<?php
/* For licensing terms, see /license.txt */
/**
*/
/**
* Include file with functions for the announcements module.
* @author jmontoya
* @package chamilo.announcements
* @todo use OOP
*
*/
class AnnouncementManager
{
@ -42,7 +38,7 @@ class AnnouncementManager
*
* @return mixed
*/
public static function parse_content($userId, $content, $course_code)
public static function parse_content($userId, $content, $course_code, $session_id = 0)
{
$readerInfo = api_get_user_info($userId);
$courseInfo = api_get_course_info($course_code);
@ -56,8 +52,8 @@ class AnnouncementManager
break;
}
}
$course_link = api_get_course_url($course_code, $session_id);
$courseLink = api_get_course_url();
$data['user_name'] = $readerInfo['username'];
$data['user_firstname'] = $readerInfo['firstname'];
$data['user_lastname'] = $readerInfo['lastname'];
@ -236,7 +232,7 @@ class AnnouncementManager
echo "<tr><th style='text-align:right'>$modify_icons</th></tr>";
}
$content = self::parse_content($result['to_user_id'], $content, api_get_course_id());
$content = self::parse_content($result['to_user_id'], $content, api_get_course_id(), api_get_session_id());
echo "<tr><td>$content</td></tr>";
@ -366,13 +362,15 @@ class AnnouncementManager
api_item_property_update($_course, TOOL_ANNOUNCEMENT, $last_id, "AnnouncementAdded", api_get_user_id(), '', $user);
}
}
} else {
// the message is sent to everyone, so we set the group to 0
api_item_property_update($_course, TOOL_ANNOUNCEMENT, $last_id, "AnnouncementAdded", api_get_user_id(), '0');
}
if ($sendToUsersInSession) {
self::addAnnouncementToAllUsersInSessions($last_id);
}
return $last_id;
}
}
@ -490,6 +488,11 @@ class AnnouncementManager
$sql_delete = "DELETE FROM $tbl_item_property WHERE c_id = $course_id AND ref='$id' AND tool='announcement'";
Database::query($sql_delete);
if ($sendToUsersInSession) {
self::addAnnouncementToAllUsersInSessions($id);
}
if ($sendToUsersInSession) {
self::addAnnouncementToAllUsersInSessions($id);
}
@ -552,7 +555,6 @@ class AnnouncementManager
}
}
}
}
/**
@ -709,7 +711,7 @@ class AnnouncementManager
*/
public static function construct_not_selected_select_form($group_list = null, $user_list = null, $to_already_selected)
{
echo '<select id="not_selected_form" name="not_selected_form[]" size="7" class="span4" multiple>';
echo '<select name="not_selected_form[]" size="7" class="span4" multiple>';
// adding the groups to the select form
if ($group_list) {
foreach ($group_list as $this_group) {
@ -1208,12 +1210,9 @@ class AnnouncementManager
Database::query($sql);
}
/**
* @param int $id
*/
public static function send_email($id)
public static function send_email($annoucement_id, $sendToUsersInSession = false)
{
$email = AnnouncementEmail::create(null, $id);
$email->send();
$email = AnnouncementEmail::create(null, $annoucement_id);
$email->send($sendToUsersInSession);
}
}

@ -365,7 +365,7 @@ if (api_is_allowed_to_edit(false,true) OR (api_get_course_setting('allow_user_ed
/* MAIL FUNCTION */
if ($_POST['email_ann'] && empty($_POST['onlyThoseMails'])) {
AnnouncementManager::send_email($id);
AnnouncementManager::send_email($id, $sendToUsersInSession);
}
$message = get_lang('AnnouncementModified');
}
@ -385,7 +385,7 @@ if (api_is_allowed_to_edit(false,true) OR (api_get_course_setting('allow_user_ed
/* MAIL FUNCTION */
if ($_POST['email_ann'] && empty($_POST['onlyThoseMails'])) {
AnnouncementManager::send_email($insert_id);
AnnouncementManager::send_email($insert_id, $sendToUsersInSession);
}
} // end condition token
@ -647,9 +647,11 @@ if ($display_form) {
echo ' </div>
</div>';
if (api_get_session_id() == 0) {
echo '<div class="control-group"><div class="controls">';
echo '<label class="checkbox" ><input name="send_to_users_in_session" type="checkbox" />'.get_lang('SendToUsersInSessions').'</label>';
echo '</div></div>';
}
if (!isset($announcement_to_modify) ) $announcement_to_modify ='';

@ -45,10 +45,10 @@ class CourseDescriptionController { // extends Controller {
$data['default_description_icon'] = $course_description->get_default_description_icon();
$data['messages'] = $messages;
// Fix for chrome XSS filter for videos in iframes - BT#7930
$browser = api_get_navigator();
if (strpos($data['descriptions'], '<iframe') !== false && $browser['name'] == 'Chrome') {
header('X-XSS-Protection: 0');
header("X-XSS-Protection: 0");
}
// render to the view
@ -63,7 +63,8 @@ class CourseDescriptionController { // extends Controller {
* render to listing or edit view
* @param int description type
*/
public function edit($id, $description_type) {
public function edit($id, $description_type)
{
$course_description = new CourseDescription();
$session_id = api_get_session_id();
$course_description->set_session_id($session_id);
@ -75,7 +76,7 @@ class CourseDescriptionController { // extends Controller {
$check = Security::check_token();
if ($check) {
$title = $_POST['title'];
if (api_get_setting('wcag_anysurfer_public_pages')=='true') {
if (api_get_setting('wcag_anysurfer_public_pages') == 'true') {
$content = WCAG_Rendering::prepareXHTML();
} else {
$content = $_POST['contentDescription'];
@ -83,7 +84,6 @@ class CourseDescriptionController { // extends Controller {
$description_type = $_POST['description_type'];
$id = $_POST['id'];
$progress = $_POST['progress'];
$course_description->set_description_type($description_type);
$course_description->set_title($title);
$course_description->set_content($content);
@ -104,8 +104,7 @@ class CourseDescriptionController { // extends Controller {
if ($affected_rows) {
$message['edit'] = true;
}
$this->listing(false,$message);
$this->listing(false, $message);
} else {
$data['error'] = 1;
$data['default_description_titles'] = $course_description->get_default_description_title();

@ -1510,6 +1510,8 @@ if (isset($documentAndFolders) && is_array($documentAndFolders)) {
if ($groupId == 0 || GroupManager::user_has_access($userId, $groupId, GroupManager::GROUP_TOOL_DOCUMENTS)) {
$count = 1;
$countedPaths = array();
$countedPaths = array();
foreach ($documentAndFolders as $key => $document_data) {
$row = array();
$row['id'] = $document_data['id'];
@ -1606,6 +1608,7 @@ if (isset($documentAndFolders) && is_array($documentAndFolders)) {
$row[] = $size;
$row[] = $document_name;
$total_size = $total_size + $size;
if (!isset($countedPaths[$document_data['path']])) {
$total_size = $total_size + $size;
$countedPaths[$document_data['path']] = true;

@ -3410,6 +3410,7 @@ class Exercise
);
return $return_array;
}
/**
* Sends a notification when a user ends an examn
*
@ -3911,13 +3912,13 @@ class Exercise
$isRandomByCategory = $this->selectRandomByCat();
// on tri les categories en fonction du terme entre [] en tete de la description de la categorie
/*
* ex de catégories :
* ex de catégories :
* [biologie] Maitriser les mecanismes de base de la genetique
* [biologie] Relier les moyens de depenses et les agents infectieux
* [biologie] Savoir ou est produite l'enrgie dans les cellules et sous quelle forme
* [chimie] Classer les molles suivant leur pouvoir oxydant ou reacteur
* [chimie] Connaître la denition de la theoie acide/base selon Brönsted
* [chimie] Connaître les charges des particules
* [chimie] Connaître la denition de la theoie acide/base selon Brönsted
* [chimie] Connaître les charges des particules
* On veut dans l'ordre des groupes definis par le terme entre crochet au debut du titre de la categorie
*/
// If test option is Grouped By Categories
@ -4213,4 +4214,85 @@ class Exercise
return api_htmlentities($in_title);
}
/**
* @param int courseid
* @param int sessionid
* @return array exercises
*/
public function getExercisesByCouseSession($courseId, $sessionId)
{
$tbl_quiz = Database::get_course_table(TABLE_QUIZ_TEST);
$sql = "SELECT * FROM $tbl_quiz cq "
. "WHERE "
. "cq.c_id = %s AND "
. "( cq.session_id = %s OR cq.session_id = 0 ) AND "
. "cq.active = 0 "
. "ORDER BY cq.id";
$sql = sprintf($sql, $courseId, $sessionId);
$result = Database::query($sql);
$rows = array();
while($row = Database::fetch_array($result, 'ASSOC')) {
$rows[] = $row;
}
return $rows;
}
/**
* @param int courseid
* @param int sessionid
* @param array quizId
* @return array exercises
*/
public function getExerciseAndResult($courseId, $sessionId, $quizId = array())
{
if (empty($quizId)) {
return array();
}
$ids = is_array($quizId) ? $quizId : array($quizId);
$ids = array_map('intval', $quizId);
$ids = implode(',', $quizId);
$tbl_quiz = Database::get_course_table(TABLE_QUIZ_TEST);
$track_exercises = Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
$whSession = "";
if ($sessionId != 0) {
$sql = "SELECT * FROM $track_exercises te "
. "INNER JOIN c_quiz cq ON cq.id = te.exe_exo_id "
. "INNER JOIN course c ON te.exe_cours_id = c.code AND c.id = cq.c_id "
. "WHERE "
. "c.id = %s AND "
. "te.session_id = %s AND "
. "cq.id IN (%s) "
. "ORDER BY cq.id ";
$sql = sprintf($sql, $courseId, $sessionId, $ids);
$whSession = "te.session_id = %s AND ";
} else {
$sql = "SELECT * FROM $track_exercises te "
. "INNER JOIN c_quiz cq ON cq.id = te.exe_exo_id "
. "INNER JOIN course c ON te.exe_cours_id = c.code AND c.id = cq.c_id "
. "WHERE "
. "c.id = %s AND "
. "cq.id IN (%s) "
. "ORDER BY cq.id ";
$sql = sprintf($sql, $courseId, $ids);
}
$sql = sprintf($sql, $courseId, $sessionId, $ids);
$result = Database::query($sql);
$rows = array();
while($row = Database::fetch_array($result, 'ASSOC')) {
$rows[] = $row;
}
return $rows;
}
}

@ -1482,6 +1482,7 @@ function convert_score($score, $weight) {
* @param int 0 = only inactive exercises
* 1 = only active exercises,
* 2 = all exercises
* 3 = active <> -1
* @return array array with exercise data
*/
function get_all_exercises($course_info = null, $session_id = 0, $check_publication_dates = false, $search_exercise = '', $search_all_sessions = false, $active = 2) {
@ -1511,7 +1512,9 @@ function get_all_exercises($course_info = null, $session_id = 0, $check_publicat
//Show courses by active status
$active_sql = '';
if ($active != 2) {
if ($active == 3) {
$active_sql = ' active <> -1 AND';
} else if ($active != 2) {
$active_sql = sprintf(' active = %d AND', $active);
}
@ -1529,13 +1532,18 @@ function get_all_exercises($course_info = null, $session_id = 0, $check_publicat
}
/**
* Get exercise information by id
* @param int Exercise Id
* @param int $exerciseId Exercise Id
* @param int $courseId The course ID (necessary as c_quiz.id is not unique)
* @return array Exercise info
*/
function get_exercise_by_id($exerciseId = 0)
{
function get_exercise_by_id($exerciseId = 0, $courseId = null) {
$TBL_EXERCICES = Database :: get_course_table(TABLE_QUIZ_TEST);
$conditions = array('where' => array('id = ?' => array($exerciseId)));
if (empty($courseId)) {
$courseId = api_get_course_int_id();
} else {
$courseId = intval($courseId);
}
$conditions = array('where' => array('id = ?' => array($exerciseId), ' AND c_id = ? ' => $courseId));
return Database::select('*', $TBL_EXERCICES, $conditions);
}
/**

@ -166,7 +166,7 @@ if (!empty($track_exercise_info)) {
// if the results_disabled of the Quiz is 1 when block the script
$result_disabled = $track_exercise_info['results_disabled'];
if (!(api_is_platform_admin() || api_is_course_admin()) ) {
if (!(api_is_platform_admin() || api_is_course_admin() || api_is_course_coach()) ) {
if ($result_disabled == 1) {
//api_not_allowed();
$show_results = false;

@ -54,20 +54,33 @@ switch ($action) {
break;
case 'search_course':
if (api_is_platform_admin()) {
if (!empty($_GET['session_id']) && intval($_GET['session_id'])) {
//if session is defined, lets find only courses of this session
$courseList = SessionManager::get_course_list_by_session_id(
intval($_GET['session_id']),
$_GET['q']
);
} else {
//if session is not defined lets search all courses STARTING with $_GET['q']
//TODO change this function to search not only courses STARTING with $_GET['q']
$courseList = Coursemanager::get_courses_list(
0,
10,
1, //$orderby = 1,
0, //offset
0, //howMany
1, //$orderby = 1
'ASC',
-1,
$_REQUEST['q'],
null,
true
-1, //visibility
$_GET['q'],
null, //$urlId
true //AlsoSearchCode
);
}
$results = array();
require_once api_get_path(LIBRARY_PATH).'course_category.lib.php';
if (!empty($courseList)) {
foreach ($courseList as $courseInfo) {
$title = $courseInfo['title'];
@ -81,11 +94,6 @@ switch ($action) {
'text' => $title
);
}
if (!empty($results)) {
/*foreach ($results as &$item) {
$item['id'] = $item['code'];
}*/
echo json_encode($results);
} else {
echo json_encode(array());
@ -118,6 +126,36 @@ switch ($action) {
}
}
break;
case 'search_course_by_session_all':
if (api_is_platform_admin())
{
if ($_GET['session_id'] == 'TODOS' || $_GET['session_id'] == 'T') {
$_GET['session_id'] = '%';
}
$results = SessionManager::get_course_list_by_session_id_like($_GET['session_id'], $_GET['q']);
//$results = SessionManager::get_sessions_list(array('s.name LIKE' => "%".$_REQUEST['q']."%"));
$results2 = array();
if (!empty($results)) {
foreach ($results as $item) {
$item2 = array();
foreach ($item as $id => $internal) {
if ($id == 'id') {
$item2[$id] = $internal;
}
if ($id == 'title') {
$item2['text'] = $internal;
}
}
$results2[] = $item2;
}
echo json_encode($results2);
} else {
echo json_encode(array());
}
}
break;
case 'search_user_by_course':
if (api_is_platform_admin())
{
@ -137,7 +175,7 @@ switch ($action) {
$result = Database::query($sql_query);
while ($user = Database::fetch_assoc($result))
{
$data[] = array('id' => $user['id'], 'text' => $user['username'] );
$data[] = array('id' => $user['id'], 'text' => $user['username'] . ' (' . $user['firstname'] . ' ' . $user['lastname'] . ')');
}
if (!empty($data))
@ -150,24 +188,25 @@ switch ($action) {
}
break;
case 'search_exercise_by_course':
if (api_is_platform_admin())
{
if (api_is_platform_admin()) {
$course = api_get_course_info_by_id($_GET['course_id']);
require_once api_get_path(SYS_CODE_PATH).'exercice/exercise.lib.php';
$session_id = (!empty($_GET['session_id'])) ? intval($_GET['session_id']) : 0 ;
$exercises = get_all_exercises($course, $session_id, false, $_GET['q'], true, 2);
$exercises = get_all_exercises($course, $session_id, false, $_GET['q'], true, 3);
foreach ($exercises as $exercise)
{
$data[] = array('id' => $exercise['id'], 'text' => $exercise['title'] );
foreach ($exercises as $exercise) {
//if (api_get_item_visibility($course, 'quiz', $exercise['id'])) {
$data[] = array('id' => $exercise['id'], 'text' => html_entity_decode($exercise['title']) );
//}
}
if (!empty($data))
{
$data[] = array('id' => 'T', 'text' => 'TODOS');
echo json_encode($data);
} else
{
echo json_encode(array());
echo json_encode(array(array('id' => 'T', 'text' => 'TODOS')));
}
}
break;
@ -176,7 +215,7 @@ switch ($action) {
{
$survey = Database :: get_course_table(TABLE_SURVEY);
$sql = "SELECT survey_id as id, title
$sql = "SELECT survey_id as id, title, anonymous
FROM $survey
WHERE c_id = %d
AND session_id = %d
@ -186,7 +225,8 @@ switch ($action) {
$result = Database::query($sql_query);
while ($survey = Database::fetch_assoc($result))
{
$data[] = array('id' => $survey['id'], 'text' => $survey['title'] );
$survey['title'] .= ($survey['anonymous'] == 1) ? ' (' . get_lang('Anonymous') . ')': '';
$data[] = array('id' => $survey['id'], 'text' => strip_tags(html_entity_decode($survey['title'])));
}
if (!empty($data))
{

@ -135,11 +135,15 @@ switch ($action) {
$count = 0;
foreach ($course_list as $item) {
if (isset($course_id) && !empty($course_id)) {
if ($course_id != $item['id']) {
continue;
}
}
// var_dump($course_list);Exit;
// if(!$item['visibility']) {
// echo "xxx";Exit;
// }
// if (isset($course_id) && !empty($course_id)) {
// if ($course_id != $item['id']) {
// continue;
// }
// }
$list = new LearnpathList(api_get_user_id(), $item['code'], $session_id);
$flat_list = $list->get_flat_list();
$lps[$item['code']] = $flat_list;

@ -0,0 +1,30 @@
<?php
/* For licensing terms, see /license.txt */
$language_file = array('admin', 'registration', 'userInfo');
require_once '../global.inc.php';
$action = $_GET['a'];
switch ($action) {
case 'get_second_select_options':
$type = isset($_REQUEST['type']) ? $_REQUEST['type'] : null;
$field_id = isset($_REQUEST['field_id']) ? $_REQUEST['field_id'] : null;
$option_value_id = isset($_REQUEST['option_value_id']) ? $_REQUEST['option_value_id'] : null;
if (!empty($type) && !empty($field_id) && !empty($option_value_id)) {
$field_options = new ExtraFieldOption($type);
echo $field_options->get_second_select_field_options_by_field($field_id, $option_value_id, true);
}
break;
case 'search_tags':
$type = isset($_REQUEST['type']) ? $_REQUEST['type'] : null;
$fieldId = isset($_REQUEST['field_id']) ? $_REQUEST['field_id'] : null;
$tag = isset($_REQUEST['tag']) ? $_REQUEST['tag'] : null;
$extraFieldOption = new ExtraFieldOption($type);
echo $extraFieldOption->getSearchOptionsByField($tag, $fieldId, 10, 'json');
break;
default:
exit;
break;
}
exit;

@ -316,6 +316,7 @@ switch ($action) {
break;
case 'get_sessions':
$courseId = isset($_GET['course_id']) && !empty($_GET['course_id']) ? intval($_GET['course_id']) : null;
$where_condition = str_replace('category_name', 'sc.name', $where_condition);
if (!empty($courseId)) {
$whereCondition .= " AND c.id = $courseId";
}
@ -324,26 +325,33 @@ switch ($action) {
case 'get_session_lp_progress':
case 'get_session_progress':
//@TODO replace this for a more efficient function (not retrieving the whole data)
$course = api_get_course_info_by_id($courseId);
$users = CourseManager::get_student_list_from_course_code($course['code'], true, intval($_GET['session_id']));
$course = api_get_course_info_by_id($_GET['course_id']);
$users = CourseManager::get_student_list_from_course_code($course['code'], true, $_GET['session_id'], $_GET['date_from'], $_GET['date_to']);
$count = count($users);
break;
case 'get_exercise_progress':
//@TODO replace this for a more efficient function (not retrieving the whole data)
$records = SessionManager::get_exercise_progress(intval($_GET['session_id']), intval($_GET['course_id']), intval($_GET['exercise_id']));
$records = Tracking::get_exercise_progress($_GET['session_id'], $_GET['course_id'], $_GET['exercise_id'], $_GET['date_from'], $_GET['date_to']);
$count = count($records);
break;
case 'get_session_access_overview':
//@TODO replace this for a more efficient function (not retrieving the whole data)
$records = SessionManager::get_user_data_access_tracking_overview($_GET['session_id'], $_GET['course_id'], $_GET['student_id'], $_GET['profile'], $_GET['date_to'], $_GET['date_from'], $options);
$records = SessionManager::get_user_data_access_tracking_overview($_GET['session_id'], $_GET['course_id'], $_GET['student_id'], $_GET['profile'], $_GET['date_from'], $_GET['date_to'], $options);
$count = count($records);
break;
case 'get_survey_overview':
//@TODO replace this for a more efficient function (not retrieving the whole data)
$records = SessionManager::get_survey_overview(intval($_GET['session_id']), intval($_GET['course_id']), intval($_GET['survey_id']), $options);
$records = SessionManager::get_survey_overview($_GET['session_id'], $_GET['course_id'], $_GET['survey_id'], $_GET['date_from'], $_GET['date_to'], $options);
$count = count($records);
break;
/*case 'get_extra_fields':
case 'get_exercise_grade':
//@TODO replace this for a more efficient function (not retrieving the whole data)
$course = api_get_course_info_by_id($_GET['course_id']);
$users = CourseManager::get_student_list_from_course_code($course['code'], true, $_GET['session_id']);
$count = count($users);
break;
case 'get_extra_fields':
$type = $_REQUEST['type'];
$obj = new ExtraField($type);
$count = $obj->get_count();
@ -353,7 +361,7 @@ switch ($action) {
$field_id = $_REQUEST['field_id'];
$obj = new ExtraFieldOption($type);
$count = $obj->get_count_by_field_id($field_id);
break;*/
break;
case 'get_timelines':
require_once $libpath.'timeline.lib.php';
$obj = new Timeline();
@ -720,6 +728,9 @@ switch ($action) {
'name', 'nbr_courses', 'nbr_users', 'category_name', 'date_start','date_end', 'coach_name', 'session_active', 'visibility'
);
//Rename Category_name
$where_condition = str_replace('category_name', 'sc.name', $where_condition);
$result = SessionManager::get_sessions_admin(
array(
'where' => $whereCondition,
@ -729,14 +740,11 @@ switch ($action) {
);
break;
case 'get_exercise_progress':
$sessionId = 0;
if (!empty($_GET['course_id']) && !empty($_GET['exercise_id']))
{
$sessionId = intval($_GET['session_id']);
$courseId = intval($_GET['course_id']);
$exerciseId = intval($_GET['exercise_id']);
$answer = intval($_GET['answer']);
}
$date_from = $_GET['date_from'];
$date_to = $_GET['date_to'];
$columns = array(
'session',
@ -748,11 +756,12 @@ switch ($action) {
'time',
'question_id',
'question',
'description',
'answer',
'correct'
'correct',
);
$result = SessionManager::get_exercise_progress($sessionId, $courseId, $exerciseId, $answer,
$result = Tracking::get_exercise_progress($sessionId, $courseId, $exerciseId, $date_from, $date_to,
array(
'where' => $whereCondition,
'order' => "$sidx $sord",
@ -767,6 +776,7 @@ switch ($action) {
$courseId = intval($_GET['course_id']);
$course = api_get_course_info_by_id($courseId);
}
/**
* Add lessons of course
*
@ -784,7 +794,7 @@ switch ($action) {
}
$columns[] = 'total';
$result = SessionManager::get_session_lp_progress($sessionId, $courseId,
$result = SessionManager::get_session_lp_progress($sessionId, $courseId, $date_from, $date_to,
array(
'where' => $whereCondition,
'order' => "$sidx $sord",
@ -801,6 +811,8 @@ switch ($action) {
$sessionId = intval($_GET['session_id']);
$courseId = intval($_GET['course_id']);
$surveyId = intval($_GET['survey_id']);
$date_from = $_GET['date_from'];
$date_to = $_GET['date_to'];
//$course = api_get_course_info_by_id($courseId);
}
/**
@ -819,7 +831,7 @@ switch ($action) {
$columns[] = $question_id;
}
$result = SessionManager::get_survey_overview($sessionId, $courseId, $surveyId,
$result = SessionManager::get_survey_overview($sessionId, $courseId, $surveyId, $date_from, $date_to,
array(
'where' => $whereCondition,
'order' => "$sidx $sord",
@ -841,7 +853,7 @@ switch ($action) {
'homeworks',
'wikis',
'surveys',
//course description
//exercises
'course_description_progress',
//exercises
'lessons_total' ,
@ -897,6 +909,7 @@ switch ($action) {
'clicks',
'ip',
'timeLoggedIn',
'session'
);
$sessionId = 0;
if (!empty($_GET['course_id']) && !empty($_GET['session_id'])) {
@ -1074,6 +1087,95 @@ switch ($action) {
$result = $new_result;
}
break;
case 'get_exercise_grade':
$objExercise = new Exercise();
$exercises = $objExercise->getExercisesByCouseSession($_GET['course_id'], $_GET['session_id']);
$cntExer = 4;
if (!empty($exercises)) {
$cntExer += count($exercises);
}
$columns = array();
//Get dynamic column names
$i = 1;
$column_names = array();
foreach (range(1, $cntExer) as $cnt) {
switch ($cnt) {
case 1:
$columns[] = 'session';
$column_names[] = get_lang('Section');
break;
case 2:
$columns[] = 'username';
$column_names[] = get_lang('Username');
break;
case 3:
$columns[] = 'name';
$column_names[] = get_lang('Name');
break;
case $cntExer:
$columns[] = 'finalScore';
$column_names[] = get_lang('FinalScore');
break;
default:
$title = "";
if (!empty($exercises[$cnt - 4]['title'])) {
$title = ucwords(strtolower(trim($exercises[$cnt - 4]['title'])));
}
$columns[] = 'exer' . $i;
$column_names[] = $title;
$i++;
break;
}
}
$quizIds = array();
if (!empty($exercises)) {
foreach($exercises as $exercise) {
$quizIds[] = $exercise['id'];
}
}
$course = api_get_course_info_by_id($_GET['course_id']);
$listUserSess = CourseManager::get_student_list_from_course_code($course['code'], true, $_GET['session_id']);
$usersId = array_keys($listUserSess);
$users = UserManager::get_user_list_by_ids($usersId, null, "lastname, firstname", "$start , $limit");
$exeResults = $objExercise->getExerciseAndResult($_GET['course_id'], $_GET['session_id'], $quizIds);
$arrGrade = array();
foreach ($exeResults as $exeResult) {
$arrGrade[$exeResult['exe_user_id']][$exeResult['exe_exo_id']] = $exeResult['exe_result'];
}
$result = array();
$i = 0;
foreach ($users as $user) {
$sessionInfo = SessionManager::fetch($listUserSess[$user['user_id']]['id_session']);
$result[$i]['session'] = $sessionInfo['name'];
$result[$i]['username'] = $user['username'];
$result[$i]['name'] = $user['lastname'] . " " . $user['firstname'];
$j = 1;
$finalScore = 0;
foreach ($quizIds as $quizID) {
$grade = "";
if (!empty($arrGrade [$user['user_id']][$quizID]) || $arrGrade [$user['user_id']][$quizID] == 0) {
$finalScore += $grade = $arrGrade [$user['user_id']][$quizID];
}
$result[$i]['exer' . $j] = $grade;
$j++;
}
if ($finalScore > 20) {
$finalScore = 20;
}
$result[$i]['finalScore'] = number_format($finalScore, 2);
$i++;
}
break;
case 'get_extra_field_options':
$obj = new ExtraFieldOption($type);
$columns = array('option_display_text', 'option_value', 'option_order');
@ -1146,11 +1248,12 @@ $allowed_actions = array(
'get_grade_models',
'get_event_email_template',
'get_user_skill_ranking',
//'get_extra_fields',
//'get_extra_field_options',
'get_extra_fields',
'get_extra_field_options',
//'get_course_exercise_medias',
'get_user_course_report',
'get_user_course_report_resumed'
'get_user_course_report_resumed',
'get_exercise_grade'
);
//5. Creating an obj to return a json
@ -1183,7 +1286,13 @@ if (in_array($action, $allowed_actions)) {
case 'xls':
//TODO add date if exists
$file_name = (!empty($action)) ? $action : 'company_report';
Export::export_table_xls($array, $file_name);
require_once api_get_path(LIBRARY_PATH).'browser/Browser.php';
$browser = new Browser();
if ($browser->getPlatform() == Browser::PLATFORM_WINDOWS) {
Export::export_table_xls_html($array, $file_name, 'ISO-8859-15');
} else {
Export::export_table_xls_html($array, $file_name);
}
break;
case 'csv':
default:
@ -1199,7 +1308,6 @@ if (in_array($action, $allowed_actions)) {
if (!empty($result)) {
foreach ($result as $row) {
//print_r($row);
// if results tab give not id, set id to $i otherwise id="null" for all <tr> of the jqgrid - ref #4235
if (!isset($row['id']) || isset($row['id']) && $row['id'] == '') {
$response->rows[$i]['id']= $i;

@ -47,9 +47,33 @@ switch ($action) {
}
}
break;
case 'search_session_all':
if (api_is_platform_admin()) {
$results = SessionManager::get_sessions_list(array('s.name LIKE' => "%".$_REQUEST['q']."%", 'c.id ='=>$_REQUEST['course_id']));
$results2 = array();
if (!empty($results)) {
foreach ($results as $item) {
$item2 = array();
foreach ($item as $id => $internal) {
if ($id == 'id') {
$item2[$id] = $internal;
}
if ($id == 'name') {
$item2['text'] = $internal;
}
}
$results2[] = $item2;
}
$results2[] = array('T', 'text' => 'TODOS', 'id' => 'T');
echo json_encode($results2);
} else {
echo json_encode(array(array('T', 'text' => 'TODOS', 'id' => 'T')));
}
}
break;
case 'search_session_by_course':
if (api_is_platform_admin()) {
$results = SessionManager::get_sessions_list(array('s.name LIKE' => "%".$_REQUEST['q']."%"));
$results = SessionManager::get_sessions_list(array('s.name LIKE' => "%".$_REQUEST['q']."%", 'c.id ='=>$_REQUEST['course_id']));
$results2 = array();
if (!empty($results)) {
foreach ($results as $item) {
@ -64,9 +88,10 @@ switch ($action) {
}
$results2[] = $item2;
}
$results2[] = array('T', 'text' => 'TODOS', 'id' => 'T');
echo json_encode($results2);
} else {
echo json_encode(array());
echo json_encode(array(array('T', 'text' => 'TODOS', 'id' => 'T')));
}
}
break;

@ -50,7 +50,7 @@ $TechnicalIssuesDescription = 'This portal is currently experiencing technical i
if (is_int($global_error_code) && $global_error_code > 0) {
$theme = 'chamilo/';
$theme = 'chamilo_red_utp/';
$css_path = 'main/css/';
$css_file = $css_path.$theme.'default.css';
$bootstrap_file = $css_path.'bootstrap.css';

@ -280,3 +280,9 @@ if ($intro_dispCommand) {
}
}
$introduction_section .= '</div>';
$browser = api_get_navigator();
if (strpos($introduction_section, '<iframe') !== false && $browser['name'] == 'Chrome') {
header("X-XSS-Protection: 0");
}

@ -917,6 +917,11 @@ class Autoload
$result['UserForm'] = '/main/gradebook/lib/fe/userform.class.php';
$result['UserGroup'] = '/main/inc/lib/usergroup.lib.php';
$result['UserManager'] = '/main/inc/lib/usermanager.lib.php';
$result['ExtraField'] = '/main/inc/lib/extra_field.lib.php';
$result['ExtraFieldOption'] = '/main/inc/lib/extra_field_option.lib.php';
$result['ExtraFieldValue'] = '/main/inc/lib/extra_field_value.lib.php';
$result['UserTable'] = '/main/gradebook/lib/fe/usertable.class.php';
$result['Utf8'] = '/main/inc/lib/system/text/utf8.class.php';
$result['Utf8Decoder'] = '/main/inc/lib/system/text/utf8_decoder.class.php';

@ -1617,10 +1617,13 @@ class CourseManager
* This only returns the users that are registered in this actual course, not linked courses.
*
* @param string $course_code
* @param boolean $full list to true if we want sessions students too
* @param boolean $with_session
* @param integer $session_id
* @param date $date_from
* @param date $date_to
* @return array with user id
*/
public static function get_student_list_from_course_code($course_code, $with_session = false, $session_id = 0) {
public static function get_student_list_from_course_code($course_code, $with_session = false, $session_id = 0, $date_from = null, $date_to = null) {
$session_id = intval($session_id);
$course_code = Database::escape_string($course_code);
@ -1639,11 +1642,27 @@ class CourseManager
// students subscribed to the course through a session
if ($with_session) {
$sql_query = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)."
WHERE course_code = '$course_code' AND status <> 2";
$joinSession = "";
//Session creation date
if (!empty($date_from) && !empty($date_to)) {
$joinSession = "INNER JOIN " . Database::get_main_table(TABLE_MAIN_SESSION) . " s";
}
$sql_query = "SELECT * FROM ".Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER)." scu
$joinSession
WHERE scu.course_code = '$course_code' AND scu.status <> 2";
if (!empty($date_from) && !empty($date_to)) {
$date_from = Database::escape_string($date_from);
$date_to = Database::escape_string($date_to);
$sql_query .= " AND s.date_start >= '$date_from' AND s.date_end <= '$date_to'";
}
if ($session_id != 0) {
$sql_query .= ' AND id_session = '.$session_id;
$sql_query .= ' AND scu.id_session = '.$session_id;
}
$rs = Database::query($sql_query);
while($student = Database::fetch_array($rs)) {
$students[$student['id_user']] = $student;

@ -62,6 +62,10 @@ define('TABLE_MAIN_USER_FIELD', 'user_field');
define('TABLE_MAIN_USER_FIELD_OPTIONS', 'user_field_options');
define('TABLE_MAIN_USER_FIELD_VALUES', 'user_field_values');
define('TABLE_MAIN_LP_FIELD', 'lp_field');
define('TABLE_MAIN_LP_FIELD_OPTIONS', 'lp_field_options');
define('TABLE_MAIN_LP_FIELD_VALUES', 'lp_field_values');
//User tags
define('TABLE_MAIN_TAG', 'tag');
define('TABLE_MAIN_USER_REL_TAG', 'user_rel_tag');

@ -95,9 +95,6 @@ class Display
if (!empty($page_header)) {
self::$global_template->assign('header', $page_header);
}
self::$global_template->assign('course_code', api_get_course_id());
echo self::$global_template->show_header_template();
}
@ -935,15 +932,17 @@ class Display
* This function need to be in the ready jquery function example --> $(function() { <?php echo Display::grid_js('grid' ...); ?> }
* In order to work this function needs the Display::grid_html function with the same div id
*
* @param string div id
* @param string url where the jqgrid will ask for data (if datatype = json)
* @param array Visible columns (you should use get_lang). An array in which we place the names of the columns.
* @param string $div_id div id
* @param string $url url where the jqgrid will ask for data (if datatype = json)
* @param array $column_names Visible columns (you should use get_lang). An array in which we place the names of the columns.
* This is the text that appears in the head of the grid (Header layer).
* Example: colname {name:'date', index:'date', width:120, align:'right'},
* @param array the column model : Array which describes the parameters of the columns.This is the most important part of the grid.
* @param array $column_model the column model : Array which describes the parameters of the columns.This is the most important part of the grid.
* For a full description of all valid values see colModel API. See the url above.
* @param array extra parameters
* @param array data that will be loaded
* @param array $extra_params extra parameters
* @param array $data data that will be loaded
* @param string $formatter A string that will be appended to the JSON returned
* @param bool $fixed_width not implemented yet
* @return string the js code
*
*/
@ -955,7 +954,7 @@ class Display
$extra_params,
$data = array(),
$formatter = '',
$width_fix = false
$fixed_width = false
) {
$obj = new stdClass();
$obj->first = 'first';
@ -1022,9 +1021,12 @@ class Display
// Adding extra params
if (!empty($extra_params)) {
foreach ($extra_params as $key => $element) {
// the groupHeaders key gets a special treatment
if ($key != 'groupHeaders') {
$obj->$key = $element;
}
}
}
// Adding static data.
if (!empty($data)) {
@ -1040,7 +1042,8 @@ class Display
$json_encode = json_encode($obj);
if (!empty($data)) {
//Converts the "data":"js_variable" to "data":js_variable othersiwe it will not work
//Converts the "data":"js_variable" to "data":js_variable,
// otherwise it will not work
$json_encode = str_replace('"data":"'.$data_var.'"', '"data":'.$data_var.'', $json_encode);
}
@ -1055,9 +1058,27 @@ class Display
// Creating the jqgrid element.
$json .= '$("#'.$div_id.'").jqGrid({';
//$json .= $beforeSelectRow;
$json .= $json_encode;
$json .= '});';
//Grouping headers option
if (isset($extra_params['groupHeaders'])) {
$groups = '';
foreach ($extra_params['groupHeaders'] as $group) {
//{ "startColumnName" : "courses", "numberOfColumns" : 1, "titleText" : "Order Info" },
$groups .= '{ "startColumnName" : "' . $group['startColumnName'] . '", "numberOfColumns" : ' . $group['numberOfColumns'] . ', "titleText" : "' . $group['titleText'] . '" },';
}
$json .= '$("#'.$div_id.'").jqGrid("setGroupHeaders", {
"useColSpanStyle" : false,
"groupHeaders" : [
' . $groups . '
]
});';
}
$all_text = addslashes(get_lang('All'));
$json .= '$("'.$obj->pager.' option[value='.$all_value.']").text("'.$all_text.'");';
$json.= "\n";

@ -2695,7 +2695,7 @@ class DocumentManager
$session_condition = " AND props.id_session='" . $session_id . "' ";
}
$sql = "SELECT SUM(size) FROM " . $TABLE_ITEMPROPERTY . " AS props, " . $TABLE_DOCUMENT . " AS docs
$sql = "SELECT coalesce(docs.size, 0), docs.path, docs.filetype FROM " . $TABLE_ITEMPROPERTY . " AS props, " . $TABLE_DOCUMENT . " AS docs
WHERE props.c_id = $course_id AND
docs.c_id = $course_id AND
docs.id = props.ref AND
@ -2703,15 +2703,22 @@ class DocumentManager
props.visibility <> 2
$group_condition
$session_condition
ORDER BY docs.id
";
$result = Database::query($sql);
if ($result && Database::num_rows($result) != 0) {
$row = Database::fetch_row($result);
return $row[0];
//Not count the same file more than once
//if there is more than once just take the last
$docsSize = array();
while ($row = Database::fetch_row($result)) {
$md5Key = md5($row[1]);
if (!empty($row[2]) && $row[2] == 'folder') {
$docsSize[$md5Key] = 4096;
} else {
return 0;
$docsSize[$md5Key] = $row[0];
}
}
return array_sum($docsSize);
}
/**

@ -1472,7 +1472,7 @@ function delete_attempt($exe_id, $user_id, $course_code, $session_id, $question_
* @param int $user_id
* @param string $course_code
* @param int $question_id
* @todo add session_id for 1.10
* @todo add session_id for 10
*/
function delete_attempt_hotspot($exe_id, $user_id, $course_code, $session_id = 0, $question_id) {
$table_track_attempt = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_HOTSPOT);
@ -1504,11 +1504,32 @@ function event_course_login($course_code, $user_id, $session_id) {
$course_code = Database::escape_string($course_code);
$user_id = intval($user_id);
$session_id = intval($session_id);
$session_lifetime = 3600;
$sql = "INSERT INTO $course_tracking_table(course_code, user_id, login_course_date, logout_course_date, counter, session_id)
VALUES('".$course_code."', '".$user_id."', '$time', '$time', '1', '".$session_id."')";
Database::query($sql);
//We select the last record for the current course in the course tracking table
$sql = "SELECT course_access_id FROM $course_tracking_table
WHERE user_id = $user_id AND
course_code = '$course_code' AND
session_id = $session_id AND
login_course_date > '$time' - INTERVAL $session_lifetime SECOND
ORDER BY login_course_date DESC LIMIT 0,1";
$result = Database::query($sql);
//error_log(preg_replace('/\s+/',' ',$sql));
if (Database::num_rows($result) > 0) {
$i_course_access_id = Database::result($result,0,0);
//We update the course tracking table
$sql = "UPDATE $course_tracking_table SET logout_course_date = '$time', counter = counter+1
WHERE course_access_id = ".intval($i_course_access_id)." AND session_id = ".$session_id;
Database::query($sql);
//error_log(preg_replace('/\s+/',' ',$sql));
} else {
$sql="INSERT INTO $course_tracking_table (course_code, user_id, login_course_date, logout_course_date, counter, session_id)" .
"VALUES('".$course_code."', '".$user_id."', '$time', '$time', '1','".$session_id."')";
Database::query($sql);
//error_log(preg_replace('/\s+/',' ',$sql));
}
// Course catalog stats modifications see #4191
CourseManager::update_course_ranking(null, null, null, null, true, false);
}

@ -68,7 +68,7 @@ class Export
$file->put($row);
}
$file->close();
DocumentManager::file_send_for_download($path, true, $filename.'.csv');
DocumentManager::file_send_for_download($path, false, $filename.'.csv');
unlink($path);
exit;
}
@ -78,17 +78,50 @@ class Export
* @param array $data
* @param string $filename
*/
public static function export_table_xls($data, $filename = 'export')
public static function export_table_xls($data, $filename = 'export', $encoding = 'utf-8')
{
$file = api_get_path(SYS_ARCHIVE_PATH).uniqid('').'.xls';
$handle = fopen($file, 'a+');
$systemEncoding = api_get_system_encoding();
foreach ($data as $row) {
fwrite($handle, implode("\t", $row)."\n");
$string = implode("\t", $row);
if ($encoding != 'utf-8') {
$string = api_convert_encoding($string, $encoding, $systemEncoding);
}
fwrite($handle, $string."\n");
}
fclose($handle);
DocumentManager::file_send_for_download($file, true, $filename.'.xls');
DocumentManager::file_send_for_download($file, false, $filename.'.xls');
}
/**
* Export tabular data to XLS-file (as html table)
* @param array $data
* @param string $filename
*/
public static function export_table_xls_html($data, $filename = 'export', $encoding = 'utf-8')
{
$file = api_get_path(SYS_ARCHIVE_PATH).uniqid('').'.xls';
$handle = fopen($file, 'a+');
$systemEncoding = api_get_system_encoding();
fwrite($handle, '<!DOCTYPE html><html><meta http-equiv="Content-Type" content="text/html" charset="utf-8" /><body><table>');
foreach ($data as $id => $row) {
foreach ($row as $id2 => $row2) {
$data[$id][$id2] = api_htmlentities($row2);
}
}
foreach ($data as $row) {
$string = implode("</td><td>", $row);
$string = '<tr><td>' . $string . '</td></tr>';
if ($encoding != 'utf-8') {
$string = api_convert_encoding($string, $encoding, $systemEncoding);
}
fwrite($handle, $string."\n");
}
fwrite($handle, '</table></body></html>');
fclose($handle);
DocumentManager::file_send_for_download($file, false, $filename.'.xls');
}
/**
* Export tabular data to XML-file
* @param array Simple array of data to put in XML

File diff suppressed because it is too large Load Diff

@ -0,0 +1,659 @@
<?php
/* For licensing terms, see /license.txt */
/**
* Declaration of the ExtraFieldOption class
*/
/**
* Handles the extra fields for various objects (users, sessions, courses)
*/
class ExtraFieldOption extends Model
{
public $columns = array(
'id', 'field_id', 'option_value', 'option_display_text', 'option_order', 'priority', 'priority_message', 'tms'
);
/**
* Gets the table for the type of object for which we are using an extra field
* @param string Type of object (course, user or session)
*/
public function __construct($type)
{
$this->type = $type;
switch ($this->type) {
case 'course':
$this->table = Database::get_main_table(TABLE_MAIN_COURSE_FIELD_OPTIONS);
break;
case 'user':
$this->table = Database::get_main_table(TABLE_MAIN_USER_FIELD_OPTIONS);
break;
case 'session':
$this->table = Database::get_main_table(TABLE_MAIN_SESSION_FIELD_OPTIONS);
break;
case 'question':
$this->table = Database::get_main_table(TABLE_MAIN_QUESTION_FIELD_OPTIONS);
break;
case 'lp':
$this->table = Database::get_main_table(TABLE_MAIN_LP_FIELD_OPTIONS);
break;
}
}
/**
* Gets the number of options already available in the table for this item type
* @return int Number of options available
* @assert () >= 0
*/
public function get_count()
{
$row = Database::select('count(*) as count', $this->table, array(), 'first');
return $row['count'];
}
/**
* Gets the number of options available for this field
* @param int Field ID
* @return int Number of options
* @assert ('') === false
* @assert (-1) == 0
* @assert (0) == 0
*/
public function get_count_by_field_id($field_id)
{
if (empty($field_id)) {
return false;
}
$row = Database::select(
'count(*) as count',
$this->table,
array('where' => array('field_id = ?' => $field_id)),
'first'
);
return $row['count'];
}
/**
* Returns a list of options for a specific field, separated by ";"
* @param int Field ID
* @param bool Indicates whether we want the results to be given with their id
* @param string Order by clause (without the "order by") to be added to the SQL query
* @return string List of options separated by ;
* @assert (-1, false, null) == ''
*/
public function get_field_options_to_string($field_id, $add_id_in_array = false, $ordered_by = null)
{
$options = self::get_field_options_by_field($field_id, $add_id_in_array, $ordered_by);
$new_options = array();
if (!empty($options)) {
foreach ($options as $option) {
$new_options[] = $option['option_value'].':'.$option['option_display_text'];
}
$string = implode(';', $new_options);
return $string;
}
return '';
}
/**
* Delete all the options of a specific field
* @param int Field ID
* @result void
* @assert (-1) === false
*/
public function delete_all_options_by_field_id($field_id)
{
$field_id = intval($field_id);
$sql = "DELETE FROM {$this->table} WHERE field_id = $field_id";
$r = Database::query($sql);
return $r;
}
/**
* @param array $params
*
* @return int
*/
public function saveOptions($params, $show_query = false)
{
$optionInfo = self::get_field_option_by_field_and_option($params['field_id'], $params['option_value']);
// Use URLify only for new items
//$optionValue = URLify::filter($params['option_value']);
$optionValue = replace_dangerous_char($params['option_value']);
$option = $params['option_value'];
if ($optionInfo == false) {
$order = self::get_max_order($params['field_id']);
$new_params = array(
'field_id' => $params['field_id'],
'option_value' => trim($optionValue),
'option_display_text' => trim($option),
'option_order' => $order,
'tms' => api_get_utc_datetime(),
);
return parent::save($new_params, $show_query);
}
return false;
}
/**
* Saves an option into the corresponding *_field_options table
* @param array Parameters to be considered for the insertion
* @param bool Whether to show the query (sent to the parent save() method)
* @return bool True on success, false on error
* @assert (array('field_id'=>0), false) === false
* @assert (array('field_id'=>1), false) === true
*/
public function save($params, $show_query = false)
{
$field_id = intval($params['field_id']);
if (empty($field_id)) {
return false;
}
$time = api_get_utc_datetime();
if (!empty($params['field_options']) &&
in_array(
$params['field_type'],
array(
ExtraField::FIELD_TYPE_RADIO,
ExtraField::FIELD_TYPE_SELECT,
ExtraField::FIELD_TYPE_SELECT_MULTIPLE,
ExtraField::FIELD_TYPE_DOUBLE_SELECT
)
)
) {
if ($params['field_type'] == ExtraField::FIELD_TYPE_DOUBLE_SELECT) {
//$params['field_options'] = France:Paris;Bretagne;Marseilles;Lyon|Belgique:Bruxelles;Namur;Liège;Bruges|Peru:Lima;Piura;
$options_parsed = ExtraField::extra_field_double_select_convert_string_to_array(
$params['field_options']
);
if (!empty($options_parsed)) {
foreach ($options_parsed as $key => $option) {
$sub_options = $option['options'];
$new_params = array(
'field_id' => $field_id,
'option_value' => 0,
'option_display_text' => $option['label'],
'option_order' => 0,
'tms' => $time,
);
// Looking if option already exists:
$option_info = self::get_field_option_by_field_id_and_option_display_text(
$field_id,
$option['label']
);
if (empty($option_info)) {
$sub_id = parent::save($new_params, $show_query);
} else {
$sub_id = $option_info['id'];
$new_params['id'] = $sub_id;
parent::update($new_params, $show_query);
}
foreach ($sub_options as $sub_option) {
if (!empty($sub_option)) {
$new_params = array(
'field_id' => $field_id,
'option_value' => $sub_id,
'option_display_text' => $sub_option,
'option_order' => 0,
'tms' => $time,
);
$option_info = self::get_field_option_by_field_id_and_option_display_text_and_option_value(
$field_id,
$sub_option,
$sub_id
);
if (empty($option_info)) {
parent::save($new_params, $show_query);
} else {
$new_params['id'] = $option_info['id'];
parent::update($new_params, $show_query);
}
}
}
}
}
$list = array();
} else {
$list = explode(';', $params['field_options']);
}
if (!empty($list)) {
foreach ($list as $option) {
$option_info = self::get_field_option_by_field_and_option($field_id, $option);
// Use URLify only for new items
$optionValue = URLify::filter($option);
$option = trim($option);
if ($option_info == false) {
$order = self::get_max_order($field_id);
$new_params = array(
'field_id' => $field_id,
'option_value' => trim($optionValue),
'option_display_text' => trim($option),
'option_order' => $order,
'tms' => $time,
);
parent::save($new_params, $show_query);
}
}
}
}
return true;
}
/**
* Save one option item at a time
* @param array Parameters specific to the option
* @param bool Whether to show the query (sent to parent save() method)
* @param bool Whether to insert even if the option already exists
* @return bool True on success, false on failure
* @assert (array('field_id'=>0),false) === false
* @assert (array('field_id'=>0),false) === true
*/
public function save_one_item($params, $show_query = false, $insert_repeated = true)
{
$field_id = intval($params['field_id']);
if (empty($field_id)) {
return false;
}
if (isset($params['option_value'])) {
$params['option_value'] = trim($params['option_value']);
}
if (isset($params['option_display_text'])) {
$params['option_display_text'] = trim($params['option_display_text']);
}
$params['tms'] = api_get_utc_datetime();
if (empty($params['option_order'])) {
$order = self::get_max_order($field_id);
$params['option_order'] = $order;
}
if ($insert_repeated) {
parent::save($params, $show_query);
} else {
$check = self::get_field_option_by_field_and_option($field_id, $params['option_value']);
if ($check == false) {
parent::save($params, $show_query);
}
}
return true;
}
/**
* Get the complete row of a specific option of a specific field
* @param int Field ID
* @param string Value of the option
* @return mixed The row on success or false on failure
* @assert (0,'') === false
*/
public function get_field_option_by_field_and_option($field_id, $option_value)
{
$field_id = intval($field_id);
$option_value = Database::escape_string($option_value);
$sql = "SELECT * FROM {$this->table}
WHERE field_id = $field_id AND option_value = '".$option_value."'";
$result = Database::query($sql);
if (Database::num_rows($result) > 0) {
return Database::store_result($result, 'ASSOC');
}
return false;
}
/**
* Get the complete row of a specific option's display text of a specific field
* @param int Field ID
* @param string Display value of the option
* @return mixed The row on success or false on failure
* @assert (0, '') === false
*/
public function get_field_option_by_field_id_and_option_display_text($field_id, $option_display_text)
{
$field_id = intval($field_id);
$option_display_text = Database::escape_string($option_display_text);
$sql = "SELECT * FROM {$this->table}
WHERE field_id = $field_id AND option_display_text = '".$option_display_text."'";
$result = Database::query($sql);
if (Database::num_rows($result) > 0) {
return Database::fetch_array($result, 'ASSOC');
}
return false;
}
/**
* Get the complete row of a specific option's display text of a specific field
* @param int Field ID
* @param string Display value of the option
* @param string Value of the option
* @return mixed The row on success or false on failure
* @assert (0, '', '') === false
*/
public function get_field_option_by_field_id_and_option_display_text_and_option_value(
$field_id,
$option_display_text,
$option_value
) {
$field_id = intval($field_id);
$option_display_text = Database::escape_string($option_display_text);
$option_value = Database::escape_string($option_value);
$sql = "SELECT * FROM {$this->table}
WHERE
field_id = $field_id AND
option_display_text = '".$option_display_text."' AND
option_value = '$option_value'";
$result = Database::query($sql);
if (Database::num_rows($result) > 0) {
return Database::fetch_array($result, 'ASSOC');
}
return false;
}
/**
* Gets an array of options for a specific field
* @param int The field ID
* @param bool Whether to add the row ID in the result
* @param string Extra ordering query bit
* @result mixed Row on success, false on failure
* @assert (0, '') === false
*/
public function get_field_options_by_field($field_id, $add_id_in_array = false, $ordered_by = null)
{
$field_id = intval($field_id);
$sql = "SELECT * FROM {$this->table} WHERE field_id = $field_id ";
if (!empty($ordered_by)) {
$sql .= " ORDER BY $ordered_by ";
}
$result = Database::query($sql);
if (Database::num_rows($result) > 0) {
if ($add_id_in_array) {
$options = array();
while ($row = Database::fetch_array($result, 'ASSOC')) {
$options[$row['id']] = $row;
}
return $options;
} else {
return Database::store_result($result, 'ASSOC');
}
}
return false;
}
/**
* Get options for a specific field as array or in JSON format suited for the double-select format
* @param int Field ID
* @param int Option value ID
* @param bool Return format (whether it should be formatted to JSON or not)
* @return mixed Row/JSON on success
*/
public function get_second_select_field_options_by_field($field_id, $option_value_id, $to_json = false)
{
$field_id = intval($field_id);
$option_value_id = intval($option_value_id);
$options = array();
$sql = "SELECT * FROM {$this->table}
WHERE field_id = $field_id AND option_value = $option_value_id
ORDER BY option_display_text";
$result = Database::query($sql);
if (Database::num_rows($result) > 0) {
$options = Database::store_result($result, 'ASSOC');
}
if ($to_json) {
$string = null;
if (!empty($options)) {
$array = array();
foreach ($options as $option) {
$array[$option['id']] = $option['option_display_text'];
}
$string = json_encode($array);
}
return $string;
}
return $options;
}
/**
* Get options for a specific field as string split by ;
* @param int Field ID
* @param string Extra query bit for reordering
* @return string HTML string of options
* @assert (0, '') === null
*/
public function get_field_options_by_field_to_string($field_id, $ordered_by = null)
{
$field = new ExtraField($this->type);
$field_info = $field->get($field_id);
$options = self::get_field_options_by_field($field_id, false, $ordered_by);
$elements = array();
if (!empty($options)) {
switch ($field_info['field_type']) {
case ExtraField::FIELD_TYPE_DOUBLE_SELECT:
$html = ExtraField::extra_field_double_select_convert_array_to_string($options);
break;
default:
foreach ($options as $option) {
$elements[] = $option['option_value'];
}
$html = implode(';', $elements);
break;
}
return $html;
}
return null;
}
/**
* Get the maximum order value for a specific field
* @param int Field ID
* @return int Current max ID + 1 (we start from 0)
* @assert (0, '') === 1
*/
public function get_max_order($field_id)
{
$field_id = intval($field_id);
$sql = "SELECT MAX(option_order) FROM {$this->table} WHERE field_id = $field_id";
$res = Database::query($sql);
$max = 1;
if (Database::num_rows($res) > 0) {
$row = Database::fetch_array($res);
$max = $row[0] + 1;
}
return $max;
}
/**
* Update the option using the given params
* @param array $params data to be saved
*/
public function update($params)
{
parent::update($params);
}
/**
* Display a form with the options for the field_id given in REQUEST
* @return void Prints output
*/
function display()
{
// action links
echo '<div class="actions">';
//echo '<a href="../admin/index.php">'.Display::return_icon('back.png', get_lang('BackTo').' '.get_lang('PlatformAdmin'),'', ICON_SIZE_MEDIUM).'</a>';
$field_id = isset($_REQUEST['field_id']) ? intval($_REQUEST['field_id']) : null;
echo '<a href="'.api_get_self(
).'?action=add&type='.$this->type.'&field_id='.$field_id.'">'.Display::return_icon(
'add_user_fields.png',
get_lang('Add'),
'',
ICON_SIZE_MEDIUM
).'</a>';
echo '</div>';
echo Display::grid_html('extra_field_options');
}
public function getPriorityOptions()
{
return array(
'' => get_lang('SelectAnOption'),
1 => get_lang('Success'),
2 => get_lang('Info'),
3 => get_lang('Warning'),
4 => get_lang('Error'),
);
}
public function getPriorityMessageType($priority)
{
switch ($priority) {
case 1:
return 'success';
case 2:
return 'info';
case 3:
return 'warning';
case 4:
return 'error';
}
return null;
}
/**
* Returns an HTML form for the current field
* @param string URL to send the form to (action=...)
* @param string Type of action to offer through the form (edit, usually)
* @return string HTML form
*/
public function return_form($url, $action)
{
$form_name = $this->type.'_field';
$form = new FormValidator($form_name, 'post', $url);
// Settting the form elements
$header = get_lang('Add');
if ($action == 'edit') {
$header = get_lang('Modify');
}
$form->addElement('header', $header);
$id = isset($_GET['id']) ? intval($_GET['id']) : '';
$form->addElement('hidden', 'id', $id);
$form->addElement('hidden', 'type', $this->type);
$form->addElement('hidden', 'field_id', $this->field_id);
$form->addElement('text', 'option_display_text', get_lang('Name'), array('class' => 'span5'));
$form->addElement('text', 'option_value', get_lang('Value'), array('class' => 'span5'));
$form->addElement('text', 'option_order', get_lang('Order'), array('class' => 'span2'));
$form->addElement('select', 'priority', get_lang('Priority'), $this->getPriorityOptions());
$form->addElement('textarea', 'priority_message', get_lang('PriorityMessage'));
$defaults = array();
if ($action == 'edit') {
// Setting the defaults
$defaults = $this->get($id);
$form->freeze('option_value');
$form->addElement('button', 'submit', get_lang('Modify'), 'class="save"');
} else {
$form->addElement('button', 'submit', get_lang('Add'), 'class="save"');
}
$form->setDefaults($defaults);
// Setting the rules
$form->addRule('option_display_text', get_lang('ThisFieldIsRequired'), 'required');
//$form->addRule('field_variable', get_lang('ThisFieldIsRequired'), 'required');
$form->addRule('option_value', get_lang('ThisFieldIsRequired'), 'required');
return $form;
}
/**
* @param string $tag
* @param int $field_id
* @param int $limit
* @return array
*/
public function searchByField($tag, $field_id, $limit = 10)
{
$field_id = intval($field_id);
$limit = intval($limit);
$tag = Database::escape_string($tag);
$sql = "SELECT DISTINCT id, option_display_text
FROM {$this->table}
WHERE
field_id = '".$field_id."' AND
option_value LIKE '%$tag%'
ORDER BY option_value
LIMIT 0, $limit
";
$result = Database::query($sql);
$values = array();
if (Database::num_rows($result)) {
$values = Database::store_result($result, 'ASSOC');
}
return $values;
}
/**
* @param string $tag
* @param int $field_id
* @param int $limit
*
* @return string
*/
public function getSearchOptionsByField($tag, $field_id, $limit = 10)
{
$result = $this->searchByField($tag, $field_id, $limit = 10);
$values = array();
$json = null;
if (!empty($result)) {
foreach ($result as $item) {
$values[] = array(
'value' => $item['id'],
'caption' => $item['option_display_text'],
);
}
$json = json_encode($values);
}
return $json;
}
}

@ -0,0 +1,654 @@
<?php
/* For licensing terms, see /license.txt */
/**
* Declaration for the ExtraFieldValue class, managing the values in extra
* fields for any datatype
* @package chamilo.library
*/
/**
* Class managing the values in extra fields for any datatype
* @package chamilo.library.extrafields
*/
class ExtraFieldValue extends Model
{
public $type = null;
public $columns = array('id', 'field_id', 'field_value', 'tms', 'comment');
/** @var string session_id, course_code, user_id, question id */
public $handler_id = null;
public $entityName;
/**
* Formats the necessary elements for the given datatype
* @param string The type of data to which this extra field applies (user, course, session, ...)
* @return void (or false if unmanaged datatype)
* @assert (-1) === false
*/
public function __construct($type)
{
$this->type = $type;
$extra_field = new ExtraField($this->type);
$this->handler_id = $extra_field->handler_id;
switch ($this->type) {
case 'course':
$this->table = Database::get_main_table(TABLE_MAIN_COURSE_FIELD_VALUES);
$this->table_handler_field = Database::get_main_table(TABLE_MAIN_COURSE_FIELD);
$this->author_id = 'user_id';
$this->entityName = 'ChamiloLMS\Entity\CourseFieldValues';
break;
case 'user':
$this->table = Database::get_main_table(TABLE_MAIN_USER_FIELD_VALUES);
$this->table_handler_field = Database::get_main_table(TABLE_MAIN_USER_FIELD);
$this->author_id = 'author_id';
$this->entityName = 'ChamiloLMS\Entity\UserFieldValues';
break;
case 'session':
$this->table = Database::get_main_table(TABLE_MAIN_SESSION_FIELD_VALUES);
$this->table_handler_field = Database::get_main_table(TABLE_MAIN_SESSION_FIELD);
$this->author_id = 'user_id';
$this->entityName = 'ChamiloLMS\Entity\SessionFieldValues';
break;
case 'question':
$this->table = Database::get_main_table(TABLE_MAIN_QUESTION_FIELD_VALUES);
$this->table_handler_field = Database::get_main_table(TABLE_MAIN_QUESTION_FIELD);
$this->author_id = 'user_id';
$this->entityName = 'ChamiloLMS\Entity\QuestionFieldValues';
break;
case 'lp':
$this->table = Database::get_main_table(TABLE_MAIN_LP_FIELD_VALUES);
$this->table_handler_field = Database::get_main_table(TABLE_MAIN_LP_FIELD);
$this->author_id = 'lp_id';
//$this->entityName = 'ChamiloLMS\Entity\QuestionFieldValues';
break;
default:
//unmanaged datatype, return false to let the caller know it
// didn't work
return false;
}
$this->columns[] = $this->handler_id;
$this->columns[] = $this->author_id;
}
/**
* Gets the number of values stored in the table (all fields together)
* for this type of resource
* @return integer Number of rows in the table
* @assert () !== false
*/
public function get_count()
{
$row = Database::select('count(*) as count', $this->table, array(), 'first');
return $row['count'];
}
/**
* Saves a series of records given as parameter into the coresponding table
* @param array Structured parameter for the insertion into the *_field_values table
* @return mixed false on empty params, void otherwise
* @assert (array()) === false
*/
public function save_field_values($params)
{
$extra_field = new ExtraField($this->type);
if (empty($params[$this->handler_id])) {
return false;
}
foreach ($params as $key => $value) {
$found = strpos($key, '__persist__');
if ($found) {
$tempKey = str_replace('__persist__', '', $key);
if (!isset($params[$tempKey])) {
$params[$tempKey] = array();
}
break;
}
}
// Parse params.
foreach ($params as $key => $value) {
if (substr($key, 0, 6) == 'extra_') {
// An extra field.
$field_variable = substr($key, 6);
$extra_field_info = $extra_field->get_handler_field_info_by_field_variable($field_variable);
if ($extra_field_info) {
$commentVariable = 'extra_'.$field_variable.'_comment';
$comment = isset($params[$commentVariable]) ? $params[$commentVariable] : null;
switch ($extra_field_info['field_type']) {
case ExtraField::FIELD_TYPE_TAG :
$old = self::getAllValuesByItemAndField(
$extra_field_info['id'],
$params[$this->handler_id]
);
$deleteItems = array();
if (!empty($old)) {
$oldIds = array();
foreach ($old as $oldItem) {
$oldIds[] = $oldItem['field_value'];
}
$deleteItems = array_diff($oldIds, $value);
}
foreach ($value as $optionId) {
$new_params = array(
$this->handler_id => $params[$this->handler_id],
'field_id' => $extra_field_info['id'],
'field_value' => $optionId,
'comment' => $comment
);
self::save($new_params);
}
if (!empty($deleteItems)) {
foreach ($deleteItems as $deleteFieldValue) {
self::deleteValuesByHandlerAndFieldAndValue(
$extra_field_info['id'],
$params[$this->handler_id],
$deleteFieldValue
);
}
}
break;
default;
$new_params = array(
$this->handler_id => $params[$this->handler_id],
'field_id' => $extra_field_info['id'],
'field_value' => $value,
'comment' => $comment
);
self::save($new_params);
}
}
}
}
}
/**
* Save values in the *_field_values table
* @param array Structured array with the values to save
* @param boolean Whether to show the insert query (passed to the parent save() method)
* @result mixed The result sent from the parent method
* @assert (array()) === false
*/
public function save($params, $show_query = false)
{
$extra_field = new ExtraField($this->type);
// Setting value to insert.
$value = $params['field_value'];
$value_to_insert = null;
if (is_array($value)) {
$value_to_insert = implode(';', $value);
} else {
$value_to_insert = Database::escape_string($value);
}
$params['field_value'] = $value_to_insert;
//If field id exists
$extra_field_info = $extra_field->get($params['field_id']);
if ($extra_field_info) {
switch ($extra_field_info['field_type']) {
case ExtraField::FIELD_TYPE_RADIO:
case ExtraField::FIELD_TYPE_SELECT:
case ExtraField::FIELD_TYPE_SELECT_MULTIPLE:
//$field_options = $session_field_option->get_field_options_by_field($params['field_id']);
//$params['field_value'] = split(';', $value_to_insert);
/*
if ($field_options) {
$check = false;
foreach ($field_options as $option) {
if (in_array($option['option_value'], $values)) {
$check = true;
break;
}
}
if (!$check) {
return false; //option value not found
}
} else {
return false; //enumerated type but no option found
}*/
break;
case ExtraField::FIELD_TYPE_TEXT:
case ExtraField::FIELD_TYPE_TEXTAREA:
break;
case ExtraField::FIELD_TYPE_DOUBLE_SELECT:
if (is_array($value)) {
if (isset($value['extra_'.$extra_field_info['field_variable']]) &&
isset($value['extra_'.$extra_field_info['field_variable'].'_second'])
) {
$value_to_insert = $value['extra_'.$extra_field_info['field_variable']].'::'.$value['extra_'.$extra_field_info['field_variable'].'_second'];
} else {
$value_to_insert = null;
}
}
break;
default:
break;
}
if ($extra_field_info['field_type'] == ExtraField::FIELD_TYPE_TAG) {
$field_values = self::getAllValuesByItemAndFieldAndValue(
$params[$this->handler_id],
$params['field_id'],
$value
);
} else {
$field_values = self::get_values_by_handler_and_field_id(
$params[$this->handler_id],
$params['field_id']
);
}
$params['field_value'] = $value_to_insert;
$params['tms'] = api_get_utc_datetime();
$params[$this->author_id] = api_get_user_id();
// Insert
if (empty($field_values)) {
if ($extra_field_info['field_loggeable'] == 1) {
global $app;
switch($this->type) {
case 'question':
$extraFieldValue = new ChamiloLMS\Entity\QuestionFieldValues();
$extraFieldValue->setUserId(api_get_user_id());
$extraFieldValue->setQuestionId($params[$this->handler_id]);
break;
case 'course':
$extraFieldValue = new ChamiloLMS\Entity\CourseFieldValues();
$extraFieldValue->setUserId(api_get_user_id());
$extraFieldValue->setQuestionId($params[$this->handler_id]);
break;
case 'user':
$extraFieldValue = new ChamiloLMS\Entity\UserFieldValues();
$extraFieldValue->setUserId($params[$this->handler_id]);
$extraFieldValue->setAuthorId(api_get_user_id());
break;
case 'session':
$extraFieldValue = new ChamiloLMS\Entity\SessionFieldValues();
$extraFieldValue->setUserId(api_get_user_id());
$extraFieldValue->setSessionId($params[$this->handler_id]);
break;
}
if (isset($extraFieldValue)) {
if (!empty($params['field_value'])) {
$extraFieldValue->setComment($params['comment']);
$extraFieldValue->setFieldValue($params['field_value']);
$extraFieldValue->setFieldId($params['field_id']);
$extraFieldValue->setTms(api_get_utc_datetime(null, false, true));
$app['orm.ems']['db_write']->persist($extraFieldValue);
$app['orm.ems']['db_write']->flush();
}
}
} else {
if ($extra_field_info['field_type'] == ExtraField::FIELD_TYPE_TAG) {
$option = new ExtraFieldOption($this->type);
$optionExists = $option->get($params['field_value']);
if (empty($optionExists)) {
$optionParams = array(
'field_id' => $params['field_id'],
'option_value' => $params['field_value']
);
$optionId = $option->saveOptions($optionParams);
} else {
$optionId = $optionExists['id'];
}
$params['field_value'] = $optionId;
if ($optionId) {
return parent::save($params, $show_query);
}
} else {
return parent::save($params, $show_query);
}
}
} else {
// Update
if ($extra_field_info['field_loggeable'] == 1) {
global $app;
switch($this->type) {
case 'question':
$extraFieldValue = $app['orm.ems']['db_write']->getRepository('ChamiloLMS\Entity\QuestionFieldValues')->find($field_values['id']);
$extraFieldValue->setUserId(api_get_user_id());
$extraFieldValue->setQuestionId($params[$this->handler_id]);
break;
case 'course':
$extraFieldValue = $app['orm.ems']['db_write']->getRepository('ChamiloLMS\Entity\CourseFieldValues')->find($field_values['id']);
$extraFieldValue->setUserId(api_get_user_id());
$extraFieldValue->setCourseCode($params[$this->handler_id]);
break;
case 'user':
$extraFieldValue = $app['orm.ems']['db_write']->getRepository('ChamiloLMS\Entity\UserFieldValues')->find($field_values['id']);
$extraFieldValue->setUserId(api_get_user_id());
$extraFieldValue->setAuthorId(api_get_user_id());
break;
case 'session':
$extraFieldValue = $app['orm.ems']['db_write']->getRepository('ChamiloLMS\Entity\SessionFieldValues')->find($field_values['id']);
$extraFieldValue->setUserId(api_get_user_id());
$extraFieldValue->setSessionId($params[$this->handler_id]);
break;
}
if (isset($extraFieldValue)) {
if (!empty($params['field_value'])) {
/*
* If the field value is similar to the previous value then the comment will be the same
in order to no save in the log an empty record
*/
if ($extraFieldValue->getFieldValue() == $params['field_value']) {
if (empty($params['comment'])) {
$params['comment'] = $extraFieldValue->getComment();
}
}
$extraFieldValue->setComment($params['comment']);
$extraFieldValue->setFieldValue($params['field_value']);
$extraFieldValue->setFieldId($params['field_id']);
$extraFieldValue->setTms(api_get_utc_datetime(null, false, true));
$app['orm.ems']['db_write']->persist($extraFieldValue);
$app['orm.ems']['db_write']->flush();
}
}
} else {
$params['id'] = $field_values['id'];
return parent::update($params, $show_query);
}
}
}
}
/**
* Returns the value of the given extra field on the given resource
* @param int Item ID (It could be a session_id, course_id or user_id)
* @param int Field ID (the ID from the *_field table)
* @param bool Whether to transform the result to a human readable strings
* @return mixed A structured array with the field_id and field_value, or false on error
* @assert (-1,-1) === false
*/
public function get_values_by_handler_and_field_id($item_id, $field_id, $transform = false)
{
$field_id = intval($field_id);
$item_id = Database::escape_string($item_id);
$sql = "SELECT s.*, field_type FROM {$this->table} s
INNER JOIN {$this->table_handler_field} sf ON (s.field_id = sf.id)
WHERE {$this->handler_id} = '$item_id' AND
field_id = '".$field_id."'
ORDER BY id";
$result = Database::query($sql);
if (Database::num_rows($result)) {
$result = Database::fetch_array($result, 'ASSOC');
if ($transform) {
if (!empty($result['field_value'])) {
switch ($result['field_type']) {
case ExtraField::FIELD_TYPE_DOUBLE_SELECT:
$field_option = new ExtraFieldOption($this->type);
$options = explode('::', $result['field_value']);
// only available for PHP 5.4 :( $result['field_value'] = $field_option->get($options[0])['id'].' -> ';
$result = $field_option->get($options[0]);
$result_second = $field_option->get($options[1]);
if (!empty($result)) {
$result['field_value'] = $result['option_display_text'].' -> ';
$result['field_value'] .= $result_second['option_display_text'];
}
break;
case ExtraField::FIELD_TYPE_SELECT:
$field_option = new ExtraFieldOption($this->type);
$extra_field_option_result = $field_option->get_field_option_by_field_and_option(
$result['field_id'],
$result['field_value']
);
if (isset($extra_field_option_result[0])) {
$result['field_value'] = $extra_field_option_result[0]['option_display_text'];
}
break;
}
}
}
return $result;
} else {
return false;
}
}
/**
* @param string $tag
* @param int $field_id
* @param int $limit
* @return array
*/
public function searchValuesByField($tag, $field_id, $limit = 10)
{
$field_id = intval($field_id);
$limit = intval($limit);
$tag = Database::escape_string($tag);
$sql = "SELECT DISTINCT s.field_value, s.field_id
FROM {$this->table} s
INNER JOIN {$this->table_handler_field} sf ON (s.field_id = sf.id)
WHERE
field_id = '".$field_id."' AND
field_value LIKE '%$tag%'
ORDER BY field_value
LIMIT 0, $limit
";
$result = Database::query($sql);
$values = array();
if (Database::num_rows($result)) {
$values = Database::store_result($result, 'ASSOC');
}
return $values;
}
/**
* Gets a structured array of the original item and its extra values, using
* a specific original item and a field name (like "branch", or "birthdate")
* @param int Item ID from the original table
* @param string The name of the field we are looking for
* @return mixed Array of results, or false on error or not found
* @assert (-1,'') === false
*/
public function get_values_by_handler_and_field_variable($item_id, $field_variable, $transform = false)
{
$item_id = Database::escape_string($item_id);
$field_variable = Database::escape_string($field_variable);
$sql = "SELECT s.*, field_type FROM {$this->table} s
INNER JOIN {$this->table_handler_field} sf
ON (s.field_id = sf.id)
WHERE
{$this->handler_id} = '$item_id' AND
field_variable = '".$field_variable."'
ORDER BY id";
$result = Database::query($sql);
if (Database::num_rows($result)) {
$result = Database::fetch_array($result, 'ASSOC');
if ($transform) {
if ($result['field_type'] == ExtraField::FIELD_TYPE_DOUBLE_SELECT) {
if (!empty($result['field_value'])) {
$field_option = new ExtraFieldOption($this->type);
$options = explode('::', $result['field_value']);
// only available for PHP 5.4 :( $result['field_value'] = $field_option->get($options[0])['id'].' -> ';
$result = $field_option->get($options[0]);
$result_second = $field_option->get($options[1]);
if (!empty($result)) {
$result['field_value'] = $result['option_display_text'].' -> ';
$result['field_value'] .= $result_second['option_display_text'];
}
}
}
}
return $result;
} else {
return false;
}
}
/**
* Gets the ID from the item (course, session, etc) for which
* the given field is defined with the given value
* @param string Field (type of data) we want to check
* @param string Data we are looking for in the given field
* @return mixed Give the ID if found, or false on failure or not found
* @assert (-1,-1) === false
*/
public function get_item_id_from_field_variable_and_field_value($field_variable, $field_value, $transform = false)
{
$field_value = Database::escape_string($field_value);
$field_variable = Database::escape_string($field_variable);
$sql = "SELECT {$this->handler_id} FROM {$this->table} s
INNER JOIN {$this->table_handler_field} sf
ON (s.field_id = sf.id)
WHERE
field_value = '$field_value' AND
field_variable = '".$field_variable."'
";
$result = Database::query($sql);
if ($result !== false && Database::num_rows($result)) {
$result = Database::fetch_array($result, 'ASSOC');
return $result;
} else {
return false;
}
}
/**
* Get all values for a specific field id
* @param int Field ID
* @return mixed Array of values on success, false on failure or not found
* @assert (-1) === false
*/
public function get_values_by_field_id($field_id)
{
$field_id = intval($field_id);
$sql = "SELECT s.*, field_type FROM {$this->table} s
INNER JOIN {$this->table_handler_field} sf
ON (s.field_id = sf.id)
WHERE field_id = '".$field_id."' ORDER BY id";
$result = Database::query($sql);
if (Database::num_rows($result)) {
return Database::store_result($result, 'ASSOC');
}
return false;
}
/**
* @param int $itemId
* @param int $fieldId
* @return array
*/
public function getAllValuesByItemAndField($itemId, $fieldId)
{
$fieldId = intval($fieldId);
$itemId = intval($itemId);
$sql = "SELECT s.* FROM {$this->table} s
INNER JOIN {$this->table_handler_field} sf
ON (s.field_id = sf.id)
WHERE
field_id = '".$fieldId."' AND
{$this->handler_id} = '$itemId'
ORDER BY field_value";
$result = Database::query($sql);
if (Database::num_rows($result)) {
return Database::store_result($result, 'ASSOC');
}
return false;
}
/**
* @param int $itemId
* @param int $fieldId
* @param string $fieldValue
* @return array|bool
*/
public function getAllValuesByItemAndFieldAndValue($itemId, $fieldId, $fieldValue)
{
$fieldId = intval($fieldId);
$itemId = intval($itemId);
$fieldValue = Database::escape_string($fieldValue);
$sql = "SELECT s.* FROM {$this->table} s
INNER JOIN {$this->table_handler_field} sf
ON (s.field_id = sf.id)
WHERE
field_id = '".$fieldId."' AND
{$this->handler_id} = '$itemId' AND
field_value = $fieldValue
ORDER BY field_value";
$result = Database::query($sql);
if (Database::num_rows($result)) {
return Database::store_result($result, 'ASSOC');
}
return false;
}
/**
* Deletes all the values related to a specific field ID
* @param int Field ID
* @return void
* @assert ('a') == null
*/
public function delete_all_values_by_field_id($field_id)
{
$field_id = intval($field_id);
$sql = "DELETE FROM {$this->table} WHERE field_id = $field_id";
Database::query($sql);
}
/**
* Deletes values of a specific field for a specific item
* @param int Item ID (session id, course id, etc)
* @param int Field ID
* @return void
* @assert (-1,-1) == null
*/
public function delete_values_by_handler_and_field_id($item_id, $field_id)
{
$field_id = intval($field_id);
$item_id = Database::escape_string($item_id);
$sql = "DELETE FROM {$this->table} WHERE {$this->handler_id} = '$item_id' AND field_id = '".$field_id."' ";
Database::query($sql);
}
/**
* @param int $itemId
* @param int $fieldId
* @param int $fieldValue
*/
public function deleteValuesByHandlerAndFieldAndValue($itemId, $fieldId, $fieldValue)
{
$itemId = intval($itemId);
$fieldId = intval($fieldId);
$fieldValue = Database::escape_string($fieldValue);
$sql = "DELETE FROM {$this->table}
WHERE
{$this->handler_id} = '$itemId' AND
field_id = '".$fieldId."' AND
field_value = '$fieldValue'";
Database::query($sql);
}
/**
* Not yet implemented - Compares the field values of two items
* @param int Item 1
* @param int Item 2
* @return mixed Differential array generated from the comparison
*/
public function compare_item_values($item_id, $item_to_compare)
{
}
}

@ -29,6 +29,7 @@
$language_file = array('document');
require_once '../../../../../../inc/global.inc.php';
api_block_anonymous_users();
// Disabling access for anonymous users.
api_block_anonymous_users();

@ -250,10 +250,12 @@ function handle_uploaded_document(
// At least if the directory doesn't exist, tell so
if (!is_dir($where_to_save)) {
if ($output){
if (!mkdir($where_to_save, api_get_permissions_for_new_directories())) {
if ($output) {
Display::display_error_message(get_lang('DestDirectoryDoesntExist').' ('.$upload_path.')');
}
return false;
}
}
// Full path of the destination
$store_path = $where_to_save.$clean_name;
@ -441,7 +443,13 @@ function moveUploadedFile($file, $storePath)
*
* @see - enough_size() uses dir_total_space() function
*/
function enough_size($file_size, $dir, $max_dir_space) {
function enough_size($file_size, $dir, $max_dir_space)
{
// If the directory is the archive directory, safely ignore the size limit
if (api_get_path(SYS_ARCHIVE_PATH) == $dir) {
return true;
}
if ($max_dir_space) {
$already_filled_space = dir_total_space($dir);
if (($file_size + $already_filled_space) > $max_dir_space) {

@ -53,14 +53,30 @@ class HTML_QuickForm_Select_Ajax extends HTML_QuickForm_select
$dataCondition = '$("#'.$this->getAttribute('name').'").select2("data", '.$result.')';
$tags = ', tags : function() { return '.$result.'} ';
}
$width = 'element';
$givenWidth = $this->getAttribute('width');
if (!empty($givenWidth)) {
$width = $givenWidth;
}
//Get the minimumInputLength for select2
$minimumInputLength = ($this->getAttribute('minimumInputLength') > 3)?
$this->getAttribute('minimumInputLength') :
3
;
$plHolder = $this->getAttribute('placeholder');
if (empty($plHolder)) {
$plHolder = get_lang('SelectAnOption');
}
$html .= '<script>
$(function() {
$("#'.$this->getAttribute('name').'").select2({
placeholder: "'.get_lang('SelectAnOption').'",
placeholder: "' . $plHolder . '",
allowClear: true,
width: "element",
minimumInputLength: 2,
width: "'.$width.'",
minimumInputLength: ' . $minimumInputLength . ',
// instead of writing the function to execute the request we use Select2s convenient helper
ajax: {
url: "'.$this->getAttribute('url').'",

@ -3229,16 +3229,18 @@ function api_get_item_visibility($_course, $tool, $id, $session=0)
return -1;
}
$tool = Database::escape_string($tool);
$id = Database::escape_string($id);
$id = intval($id);
$session = (int) $session;
$TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
$course_id = $_course['real_id'];
$course_id = intval($_course['real_id']);
$sql = "SELECT visibility FROM $TABLE_ITEMPROPERTY
WHERE c_id = $course_id AND
tool = '$tool' AND
ref = $id AND
(id_session = $session OR id_session = 0)
ORDER BY id_session DESC, lastedit_date DESC LIMIT 1";
ORDER BY id_session DESC, lastedit_date DESC
LIMIT 1";
$res = Database::query($sql);
if ($res === false || Database::num_rows($res) == 0) { return -1; }
$row = Database::fetch_array($res);

@ -341,14 +341,14 @@ class HTML_QuickForm extends HTML_Common
}
}
$course_id = api_get_course_int_id();
//If I'm in a course replace the default max filesize with the course limits
if (!empty($course_id)) {
$free_course_quota = DocumentManager::get_course_quota() - DocumentManager::documents_total_space();
if (empty($this->_maxFileSize) || $free_course_quota <= $this->_maxFileSize) {
$this->_maxFileSize = intval($free_course_quota);
}
}
// $course_id = api_get_course_int_id();
// //If I'm in a course replace the default max filesize with the course limits
// if (!empty($course_id)) {
// $free_course_quota = DocumentManager::get_course_quota() - DocumentManager::documents_total_space();
// if (empty($this->_maxFileSize) || $free_course_quota <= $this->_maxFileSize) {
// $this->_maxFileSize = intval($free_course_quota);
// }
// }
} // end constructor
// }}}

File diff suppressed because it is too large Load Diff

@ -556,10 +556,19 @@ class Tracking
/**
* Gets the score average from all tests in a course by student
*
* @param mixed Student(s) id
* @param string Course code
* @param int Exercise id (optional), filtered by exercise
* @param int Session id (optional), if param $session_id is null it'll return results including sessions, 0 = session is not filtered
* @param $student_id
* @param $course_code
* @param int $exercise_id
* @param null $session_id
* @param int $active_filter 2 for consider all tests
* 1 for active <> -1
* 0 for active <> 0
* @param int $into_lp 1 for all exercises
* 0 for whitout LP
* @internal param \Student $mixed id
* @internal param \Course $string code
* @internal param \Exercise $int id (optional), filtered by exercise
* @internal param \Session $int id (optional), if param $session_id is null it'll return results including sessions, 0 = session is not filtered
* @return string value (number %) Which represents a round integer about the score average.
*/
public static function get_avg_student_exercise_score($student_id, $course_code, $exercise_id = 0, $session_id = null)
@ -583,8 +592,23 @@ class Tracking
$session_id = intval($session_id);
$condition_session = " AND session_id = $session_id ";
}
if ($active_filter == 1) {
$condition_active = 'AND active <> -1';
} elseif ($active_filter == 0) {
$condition_active = 'AND active <> 0';
} else {
$condition_active = '';
}
$condition_into_lp = '';
$select_lp_id = '';
if ($into_lp == 0) {
$condition_into_lp = 'AND orig_lp_id = 0 AND orig_lp_item_id = 0';
} else {
$select_lp_id = ', orig_lp_id as lp_id ';
}
$sql = "SELECT count(id) FROM $tbl_course_quiz
WHERE c_id = {$course_info['real_id']} AND active <> -1 $condition_quiz ";
WHERE c_id = {$course_info['real_id']} $condition_active $condition_quiz ";
$count_quiz = Database::fetch_row(Database::query($sql));
if (!empty($count_quiz[0]) && !empty($student_id)) {
@ -596,7 +620,7 @@ class Tracking
if (empty($exercise_id)) {
$sql = "SELECT id FROM $tbl_course_quiz
WHERE c_id = {$course_info['real_id']} AND active <> -1 $condition_quiz";
WHERE c_id = {$course_info['real_id']} $condition_active $condition_quiz";
$result = Database::query($sql);
$exercise_list = array();
$exercise_id = null;
@ -613,18 +637,19 @@ class Tracking
$count_quiz = Database::fetch_row(Database::query($sql));
$sql = "SELECT SUM(exe_result/exe_weighting*100) as avg_score, COUNT(*) as num_attempts
$select_lp_id
FROM $tbl_stats_exercise
WHERE exe_exo_id IN ('".$exercise_id."')
$condition_user AND
orig_lp_id = 0 AND
status = '' AND
exe_cours_id = '$course_code' AND
orig_lp_item_id = 0 $condition_session
exe_cours_id = '$course_code'
$condition_session
$condition_into_lp
ORDER BY exe_date DESC";
$res = Database::query($sql);
$row = Database::fetch_array($res);
$quiz_avg_score = 0;
$quiz_avg_score = null;
if (!empty($row['avg_score'])) {
$quiz_avg_score = round($row['avg_score'],2);
@ -636,7 +661,26 @@ class Tracking
if (is_array($student_id)) {
$quiz_avg_score = round($quiz_avg_score / count($student_id), 2);
}
if ($into_lp == 0) {
return $quiz_avg_score;
} else {
if (!empty($row['lp_id'])) {
$tbl_lp = Database::get_course_table(TABLE_LP_MAIN);
$tbl_course = Database::get_main_table(TABLE_MAIN_COURSE);
$sql = "SELECT lp.name FROM $tbl_lp as lp, $tbl_course as c WHERE
c.code = '$course_code' AND
lp.id = ".$row['lp_id']." AND
lp.c_id = c.id
LIMIT 1;
";
$result = Database::query($sql);
$row_lp = Database::fetch_row($result);
$lp_name = $row_lp[0];
return array($quiz_avg_score, $lp_name);
} else {
return array($quiz_avg_score, null);
}
}
}
}
return null;
@ -644,41 +688,50 @@ class Tracking
/**
* Get count student's exercise COMPLETED attempts
* @param int tudent id
* @param string Course code
* @param int Exercise id
* @param int Learning path id (optional), for showing attempts inside a learning path $lp_id and $lp_item_id params are required.
* @param int Learning path item id (optional), for showing attempts inside a learning path $lp_id and $lp_item_id params are required.
*
* @param $student_id
* @param $course_code
* @param $exercise_id
* @param int $lp_id
* @param int $lp_item_id
* @param int $session_id
* @param int $find_all_lp 0 = just LP specified
* 1 = LP specified or whitout LP,
* 2 = all rows
* @internal param \Student $int id
* @internal param \Course $string code
* @internal param \Exercise $int id
* @internal param \Learning $int path id (optional), for showing attempts inside a learning path $lp_id and $lp_item_id params are required.
* @internal param \Learning $int path item id (optional), for showing attempts inside a learning path $lp_id and $lp_item_id params are required.
* @return int count of attempts
*/
public static function count_student_exercise_attempts(
$student_id,
$course_code,
$exercise_id,
$lp_id = 0,
$lp_item_id = 0,
$session_id = 0
) {
public static function count_student_exercise_attempts($student_id, $course_code, $exercise_id, $lp_id = 0, $lp_item_id = 0, $session_id = 0, $find_all_lp = 0) {
$course_code = Database::escape_string($course_code);
$student_id = intval($student_id);
$exercise_id = intval($exercise_id);
$session_id = intval($session_id);
$count_attempts = 0;
if (!empty($lp_id)) $lp_id = intval($lp_id);
if (!empty($lp_item_id)) $lp_id = intval($lp_item_id);
$tbl_stats_exercices = Database :: get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
$sql = "SELECT COUNT(ex.exe_id) as essais FROM $tbl_stats_exercices AS ex
WHERE ex.exe_cours_id = '$course_code'
AND ex.exe_exo_id = $exercise_id
AND status = ''
AND orig_lp_id = $lp_id
AND orig_lp_item_id = $lp_item_id
AND exe_user_id= $student_id
AND session_id = $session_id ";
if ($find_all_lp == 1) {
$sql .= "AND (orig_lp_id = $lp_id OR orig_lp_id = 0)
AND (orig_lp_item_id = $lp_item_id OR orig_lp_item_id = 0)";
} elseif ($find_all_lp == 0) {
$sql .= "AND orig_lp_id = $lp_id
AND orig_lp_item_id = $lp_item_id";
}
$rs = Database::query($sql);
$row = Database::fetch_row($rs);
$count_attempts = $row[0];
@ -749,6 +802,162 @@ class Tracking
return $result.'%';
}
/**
* get teacher progress by course and session
* @param int course id
* @param int session id
* @return data array
*/
static function get_teachers_progress_by_course($courseId, $sessionId)
{
$course = api_get_course_info_by_id($courseId);
//get teachers
$sql = "SELECT scu.id_session, scu.id_user, s.name
FROM session_rel_course_rel_user scu, session s
WHERE scu.id_session = s.id
AND scu.status = 2
AND scu.visibility = 1
AND scu.course_code = '%s'
AND scu.id_session = %s";
$query = sprintf($sql,$course['code'], $sessionId);
$rs = Database::query($query);
$teachers = array();
while ($teacher = Database::fetch_array($rs,'ASSOC')) {
$teachers[] = $teacher;
}
foreach ($teachers as $teacher) {
//total documents added
$sql = "SELECT count(*) as total
FROM c_item_property
WHERE lastedit_type = 'DocumentAdded'
AND c_id = %s
AND insert_user_id = %s
AND id_session = %s";
$query = sprintf($sql,
$courseId,
$teacher['id_user'],
$teacher['id_session']
);
//error_log($query);
$rs = Database::query($query);
$totalDocuments = 0;
if ($rs) {
$row = Database::fetch_row($rs);
$totalDocuments = $row[0];
}
//total links added
$sql = "SELECT count(*) as total
FROM c_item_property
WHERE lastedit_type = 'LinkAdded'
AND c_id = %s
AND insert_user_id = %s
AND id_session = %s";
$query = sprintf($sql,
$courseId,
$teacher['id_user'],
$teacher['id_session']
);
$rs = Database::query($query);
$totalLinks = 0;
if ($rs) {
$row = Database::fetch_row($rs);
$totalLinks = $row[0];
}
//total forums added
$sql = "SELECT count(*) as total
FROM c_item_property
WHERE lastedit_type = 'ForumthreadVisible'
AND c_id = %s
AND insert_user_id = %s
AND id_session = %s";
$query = sprintf($sql,
$courseId,
$teacher['id_user'],
$teacher['id_session']
);
$rs = Database::query($query);
$totalForums = 0;
if ($rs) {
$row = Database::fetch_row($rs);
$totalForums = $row[0];
}
//total wikis added
$sql = "SELECT COUNT(DISTINCT(ref)) as total
FROM c_item_property
WHERE lastedit_type = 'WikiAdded'
AND c_id = %s
AND insert_user_id = %s
AND id_session = %s";
$query = sprintf($sql,
$courseId,
$teacher['id_user'],
$teacher['id_session']
);
$rs = Database::query($query);
$totalWikis = 0;
if ($rs) {
$row = Database::fetch_row($rs);
$totalWikis = $row[0];
}
//total works added
$sql = "SELECT COUNT(*) as total
FROM c_item_property
WHERE lastedit_type = 'DirectoryCreated'
AND tool = 'work'
AND c_id = %s
AND insert_user_id = %s
AND id_session = %s";
$query = sprintf($sql,
$courseId,
$teacher['id_user'],
$teacher['id_session']
);
$rs = Database::query($query);
$totalWorks = 0;
if ($rs) {
$row = Database::fetch_row($rs);
$totalWorks = $row[0];
}
//total announcements added
$sql = "SELECT COUNT(*) as total
FROM c_item_property
WHERE lastedit_type = 'AnnouncementAdded'
AND c_id = %s
AND insert_user_id = %s
AND id_session = %s";
$query = sprintf($sql,
$courseId,
$teacher['id_user'],
$teacher['id_session']
);
$rs = Database::query($query);
$totalAnnouncements = 0;
if ($rs) {
$row = Database::fetch_row($rs);
$totalAnnouncements = $row[0];
}
$tutor = get_user_info_by_id($teacher['id_user']);
$data[] = array(
'course' => $course['title'],
'session' => $teacher['name'],
'tutor' => $tutor['username'] . ' - ' . $tutor['lastname'] . ' ' . $tutor['firstname'],
'documents' => $totalDocuments,
'links' => $totalLinks,
'forums' => $totalForums,
'works' => $totalWorks,
'wikis' => $totalWikis,
'announcements' => $totalAnnouncements,
);
}
return $data;
}
/**
* Returns the average student progress in the learning paths of the given
* course.
@ -2368,46 +2577,132 @@ class Tracking
return $data;
}
/**
* Get total clicks by session
* @param int Session id (optional), if param $session_id is null(default) it'll return results including sessions, 0 = session is not filtered
* @return array data
* @todo implement total click by $course_id
* Get total clicks
* THIS FUNCTION IS NOT BEEN USED, IT WAS MEANT TO BE USE WITH track_e_course_access.date_from and track_e_course_access.date_to,
* BUT NO ROW MATCH THE CONDITION, IT SHOULD BE FINE TO USE IT WHEN YOU USE USER DEFINED DATES AND NO CHAMILO DATES
* @param int User Id
* @param int Course Id
* @param int Session Id (optional), if param $session_id is null(default) it'll return results including sessions, 0 = session is not filtered
* @param string Date from
* @param string Date to
* @return array Data
* @author César Perales cesar.perales@beeznest.com 2014-01-16
*/
public static function get_total_clicks_by_session($session_id = null)
public static function get_total_clicks($userId, $courseId, $sessionId = 0, $date_from = '', $date_to = '')
{
$course = api_get_course_info_by_id($courseId);
$tables = array(
TABLE_STATISTIC_TRACK_E_LASTACCESS => array('access_session_id','access_user_id'),
TABLE_STATISTIC_TRACK_E_ACCESS => array('access_session_id', 'access_user_id'),
#TABLE_STATISTIC_TRACK_E_LOGIN,
TABLE_STATISTIC_TRACK_E_DOWNLOADS => array('down_session_id', 'down_user_id'),
TABLE_STATISTIC_TRACK_E_LINKS => array('links_session_id', 'links_user_id'),
TABLE_STATISTIC_TRACK_E_ONLINE => array('session_id', 'login_user_id'),
TABLE_STATISTIC_TRACK_E_LASTACCESS => array(
'course' => 'access_cours_code',
'session' => 'access_session_id',
'user' => 'access_user_id',
'start_date'=> 'access_date',
),
TABLE_STATISTIC_TRACK_E_ACCESS => array(
'course' => 'access_cours_code',
'session' => 'access_session_id',
'user' => 'access_user_id',
'start_date'=> 'access_date',
),
#TABLE_STATISTIC_TRACK_E_LOGIN, array(,, 'login_date', 'logout_date');
TABLE_STATISTIC_TRACK_E_DOWNLOADS => array(
'course' => 'down_cours_id',
'session' => 'down_session_id',
'user' => 'down_user_id',
'start_date'=> 'down_date',
),
TABLE_STATISTIC_TRACK_E_LINKS => array(
'course' => 'links_cours_id',
'session' => 'links_session_id',
'user' => 'links_user_id',
'start_date'=> 'links_date',
),
TABLE_STATISTIC_TRACK_E_ONLINE => array(
'course' => 'course',
'session' => 'session_id',
'user' => 'login_user_id',
'start_date'=> 'login_date',
),
#TABLE_STATISTIC_TRACK_E_HOTPOTATOES,
TABLE_STATISTIC_TRACK_E_COURSE_ACCESS => array('session_id', 'user_id'),
TABLE_STATISTIC_TRACK_E_EXERCICES => array('session_id', 'exe_user_id'),
TABLE_STATISTIC_TRACK_E_ATTEMPT => array('session_id', 'user_id'),
/*TABLE_STATISTIC_TRACK_E_COURSE_ACCESS => array(
'course' => 'course_code',
'session' => 'session_id',
'user' => 'user_id',
'start_date'=> 'login_course_date',
'end_date' => 'logout_course_date',
),*/
TABLE_STATISTIC_TRACK_E_EXERCICES => array(
'course' => 'exe_cours_id',
'session' => 'session_id',
'user' => 'exe_user_id',
'start_date'=> 'exe_date',
),
TABLE_STATISTIC_TRACK_E_ATTEMPT => array(
'course' => 'course_code',
'session' => 'session_id',
'user' => 'user_id',
'start_date'=> 'tms',
),
#TABLE_STATISTIC_TRACK_E_ATTEMPT_RECORDING,
#TABLE_STATISTIC_TRACK_E_DEFAULT,
TABLE_STATISTIC_TRACK_E_UPLOADS => array('upload_session_id', 'upload_user_id'),
TABLE_STATISTIC_TRACK_E_UPLOADS => array(
'course' => 'upload_cours_id',
'session' => 'upload_session_id',
'user' => 'upload_user_id',
'start_date'=> 'upload_date',
),
#TABLE_STATISTIC_TRACK_E_HOTSPOT,
#TABLE_STATISTIC_TRACK_E_ITEM_PROPERTY,
#TABLE_STATISTIC_TRACK_E_OPEN,
);
if (isset($_GET['session_id']) && !empty($_GET['session_id'])) {
$sessionId = intval($_GET['session_id']);
}
$error_sql = '';
foreach ($tables as $tableName => $fields) {
$sql = sprintf('SELECT %s as user, count(*) as total FROM %s WHERE %s = %s GROUP BY %s', $fields[1], $tableName, $fields[0], $sessionId, $fields[1]);
//If session is defined, add it to query
$where = '';
if (isset($sessionId) && !empty($sessionId)) {
$sessionField = $fields['session'];
$where .= " AND $sessionField = $sessionId";
}
//filter by date
if (!empty($date_from) && !empty($date_to)) {
$fieldStartDate = $fields['start_date'];
if (!isset($fields['end_date'])) {
$where .= sprintf(" AND ($fieldStartDate BETWEEN '%s' AND '%s' )", $date_from, $date_to) ;
} else {
$fieldEndDate = $fields['end_date'];
$where .= sprintf(" AND fieldStartDate >= '%s'
AND $fieldEndDate <= '%s'", $date_from, $date_to);
}
}
//query
$sql = "SELECT %s as user, count(*) as total
FROM %s
WHERE %s = '%s'
AND %s = %s
$where
GROUP BY %s";
$sql = sprintf($sql,
$fields['user'], //user field
$tableName, //FROM
$fields['course'], //course condition
$course['code'], //course condition
$fields['user'], //user condition
$userId, //user condition
$fields['user'] //GROUP BY
);
$rs = Database::query($sql);
//iterate query
if (Database::num_rows($rs) > 0) {
while ($row = Database::fetch_array($rs)) {
$data[$row['user']] = (isset($data[$row['user']])) ? $data[$row['user']] + $row[total]: $row['total'];
}
}
}
return $data;
}
@ -3518,6 +3813,228 @@ class Tracking
return $form;
}
/**
* Get the progress of a exercise
* @param int $sessionId The session ID (session.id)
* @param int $courseId The course ID (course.id)
* @param int $exerciseId The quiz ID (c_quiz.id)
* @param int $answer The answer status (0 = incorrect, 1 = correct, 2 = both)
* @param array $options An array of options you can pass to the query (limit, where and order)
* @return array An array with the data of exercise(s) progress
*/
public static function get_exercise_progress($sessionId = 0, $courseId = 0, $exerciseId = 0, $date_from, $date_to, $options = array())
{
$sessionId = intval($sessionId);
$courseId = intval($courseId);
$exerciseId = intval($exerciseId);
$date_from = Database::escape_string($date_from);
$date_to = Database::escape_string($date_to);
/*
* This method gets the data by blocks, as previous attempts at one single
* query made it take ages. The logic of query division is described below
*/
// Get tables names
$tuser = Database::get_main_table(TABLE_MAIN_USER);
$tquiz = Database::get_course_table(TABLE_QUIZ_TEST);
$tquiz_answer = Database::get_course_table(TABLE_QUIZ_ANSWER);
$tquiz_question = Database::get_course_table(TABLE_QUIZ_QUESTION);
$tquiz_rel_question = Database::get_course_table(TABLE_QUIZ_TEST_QUESTION);
$ttrack_exercises = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
$ttrack_attempt = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_ATTEMPT);
require_once api_get_path(SYS_CODE_PATH).'exercice/exercise.lib.php';
$sessions = array();
$courses = array();
// if session ID is defined but course ID is empty, get all the courses
// from that session
if (!empty($sessionId) && empty($courseId)) {
// $courses is an array of course int id as index and course details hash as value
$courses = SessionManager::get_course_list_by_session_id($sessionId);
$sessions[$sessionId] = api_get_session_info($sessionId);
} elseif (empty($sessionId) && !empty($courseId)) {
// if, to the contrary, course is defined but not sessions, get the sessions that include this course
// $sessions is an array like: [0] => ('id' => 3, 'name' => 'Session 35'), [1] => () etc;
$course = api_get_course_info_by_id($courseId);
$sessionsTemp = SessionManager::get_session_by_course($course['code']);
$courses[$courseId] = $course;
foreach ($sessionsTemp as $sessionItem) {
$sessions[$sessionItem['id']] = $sessionItem;
}
} elseif (!empty($courseId) && !empty($sessionId)) {
//none is empty
$course = api_get_course_info_by_id($courseId);
$courses[$courseId] = array($course['code']);
$courses[$courseId]['code'] = $course['code'];
$sessions[$sessionId] = api_get_session_info($sessionId);
} else {
//both are empty, not enough data, return an empty array
return array();
}
// Now we have two arrays of courses and sessions with enough data to proceed
// If no course could be found, we shouldn't return anything. Sessions can be empty (then we only return the pure-course-context results)
if (count($courses) < 1) {
return array();
}
$data = array();
// The following loop is less expensive than what it seems:
// - if a course was defined, then we only loop through sessions
// - if a session was defined, then we only loop through courses
// - if a session and a course were defined, then we only loop once
foreach ($courses as $courseIdx => $courseData) {
$where = '';
$whereParams = array();
$whereCourseCode = $courseData['code'];
$whereSessionParams = '';
if (count($sessions > 0)) {
foreach ($sessions as $sessionIdx => $sessionData) {
if (!empty($sessionIdx)) {
$whereSessionParams .= $sessionIdx.',';
}
}
$whereSessionParams = substr($whereSessionParams,0,-1);
}
if (!empty($exerciseId)) {
$exerciseId = intval($exerciseId);
$where .= ' AND q.id = %d ';
$whereParams[] = $exerciseId;
}
/*
* This feature has been disabled for now, to avoid having to
* join two very large tables
//2 = show all questions (wrong and correct answered)
if ($answer != 2) {
$answer = intval($answer);
//$where .= ' AND qa.correct = %d';
//$whereParams[] = $answer;
}
*/
$limit = '';
if (!empty($options['limit'])) {
$limit = " LIMIT ".$options['limit'];
}
if (!empty($options['where'])) {
$where .= ' AND '.Database::escape_string($options['where']);
}
$order = '';
if (!empty($options['order'])) {
$order = " ORDER BY ".$options['order'];
}
if (!empty($date_to) && !empty($date_from)) {
$where .= sprintf(" AND (te.start_date BETWEEN '%s 00:00:00' AND '%s 23:59:59')", $date_from, $date_to);
}
$sql = "SELECT
te.session_id,
ta.id as attempt_id,
te.exe_user_id as user_id,
te.exe_id as exercise_attempt_id,
ta.question_id,
ta.answer as answer_id,
ta.tms as time,
te.exe_exo_id as quiz_id,
CONCAT ('c', q.c_id, '_e', q.id) as exercise_id,
q.title as quiz_title,
qq.description as description
FROM $ttrack_exercises te
INNER JOIN $ttrack_attempt ta ON ta.exe_id = te.exe_id
INNER JOIN $tquiz q ON q.id = te.exe_exo_id
INNER JOIN $tquiz_rel_question rq ON rq.exercice_id = q.id AND rq.c_id = q.c_id
INNER JOIN $tquiz_question qq ON qq.id = rq.question_id
AND qq.c_id = rq.c_id
AND qq.position = rq.question_order
AND ta.question_id = rq.question_id
WHERE te.exe_cours_id = '$whereCourseCode' ".(empty($whereSessionParams)?'':"AND te.session_id IN ($whereSessionParams)")."
AND q.c_id = $courseIdx
$where $order $limit";
$sql_query = vsprintf($sql, $whereParams);
// Now browse through the results and get the data
$rs = Database::query($sql_query);
$userIds = array();
$questionIds = array();
$answerIds = array();
while ($row = Database::fetch_array($rs)) {
//only show if exercise is visible
if (api_get_item_visibility($courseData, 'quiz', $row['exercise_id'])) {
$userIds[$row['user_id']] = $row['user_id'];
$questionIds[$row['question_id']] = $row['question_id'];
$answerIds[$row['question_id']][$row['answer_id']] = $row['answer_id'];
$row['session'] = $sessions[$row['session_id']];
$data[] = $row;
}
}
// Now fill questions data. Query all questions and answers for this test to avoid
$sqlQuestions = "SELECT tq.c_id, tq.id as question_id, tq.question, tqa.id_auto,
tqa.answer, tqa.correct, tq.position, tqa.id_auto as answer_id
FROM $tquiz_question tq, $tquiz_answer tqa
WHERE tqa.question_id =tq.id and tqa.c_id = tq.c_id
AND tq.c_id = $courseIdx AND tq.id IN (".implode(',',$questionIds).")";
$resQuestions = Database::query($sqlQuestions);
$answer = array();
$question = array();
while ($rowQuestion = Database::fetch_assoc($resQuestions)) {
$questionId = $rowQuestion['question_id'];
$answerId = $rowQuestion['answer_id'];
$answer[$questionId][$answerId] = array(
'position' => $rowQuestion['position'],
'question' => $rowQuestion['question'],
'answer' => $rowQuestion['answer'],
'correct' => $rowQuestion['correct']
);
$question[$questionId]['question'] = $rowQuestion['question'];
}
// Now fill users data
$sqlUsers = "SELECT user_id, username, lastname, firstname FROM $tuser WHERE user_id IN (".implode(',',$userIds).")";
$resUsers = Database::query($sqlUsers);
while ($rowUser = Database::fetch_assoc($resUsers)) {
$users[$rowUser['user_id']] = $rowUser;
}
foreach ($data as $id => $row) {
$rowQuestId = $row['question_id'];
$rowAnsId = $row['answer_id'];
$data[$id]['session'] = $sessions[$row['session_id']]['name'];
$data[$id]['firstname'] = $users[$row['user_id']]['firstname'];
$data[$id]['lastname'] = $users[$row['user_id']]['lastname'];
$data[$id]['username'] = $users[$row['user_id']]['username'];
$data[$id]['answer'] = $answer[$rowQuestId][$rowAnsId]['answer'];
$data[$id]['correct'] = ($answer[$rowQuestId][$rowAnsId]['correct'] == 0 ? get_lang('No') : get_lang('Yes'));
$data[$id]['question'] = $question[$rowQuestId]['question'];
$data[$id]['question_id'] = $rowQuestId;
$data[$id]['description'] = $row['description'];
}
/*
The minimum expected array structure at the end is:
attempt_id,
session name,
exercise_id,
quiz_title,
username,
lastname,
firstname,
time,
question_id,
question,
answer,
*/
}
return $data;
}
}
/**

@ -932,11 +932,14 @@ class UserManager
}
/**
* @param array $ids
* @param null $active
* @return array
* Get the users by ID
* @param array $ids student ids
* @param string $active
* @param string $order
* @param string $limit
* @return array $result student information
*/
public static function get_user_list_by_ids($ids = array(), $active = null)
public static function get_user_list_by_ids($ids = array(), $active = null, $order = null, $limit = null)
{
if (empty($ids)) {
return array();
@ -952,6 +955,14 @@ class UserManager
$sql .= ' AND active='.($active ? '1' : '0');
}
if (!is_null($order)) {
$sql .= ' ORDER BY ' . $order;
}
if (!is_null($limit)) {
$sql .= ' LIMIT ' . $limit;
}
$rs = Database::query($sql);
$result = array();
while ($row = Database::fetch_array($rs)) {

@ -763,6 +763,7 @@ if (isset($cidReset) && $cidReset) {
//Course login
if (isset($_user['user_id'])) {
event_course_login($_course['code'], $_user['user_id'], api_get_session_id());
error_log(__FILE__);
}
}
} else {
@ -822,7 +823,7 @@ if (isset($cidReset) && $cidReset) {
// these lines are usefull for tracking. Indeed we can have lost the id_session and not the cid.
// Moreover, if we want to track a course with another session it can be usefull
if (!empty($_GET['id_session'])) {
if (!empty($_GET['id_session']) && is_numeric($_GET['id_session'])) {
$tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
$sql = 'SELECT name FROM '.$tbl_session . ' WHERE id="'.intval($_SESSION['id_session']). '"';
$rs = Database::query($sql);
@ -885,19 +886,18 @@ if (isset($cidReset) && $cidReset) {
login_course_date > now() - INTERVAL $session_lifetime SECOND
ORDER BY login_course_date DESC LIMIT 0,1";
$result = Database::query($sql);
if (Database::num_rows($result) > 0) {
$i_course_access_id = Database::result($result,0,0);
//We update the course tracking table
$sql = "UPDATE $course_tracking_table SET logout_course_date = '$time', counter = counter+1
WHERE course_access_id = ".intval($i_course_access_id)." AND session_id = ".api_get_session_id();
//error_log($sql);
Database::query($sql);
//error_log(preg_replace('/\s+/',' ',$sql));
} else {
$sql="INSERT INTO $course_tracking_table (course_code, user_id, login_course_date, logout_course_date, counter, session_id)" .
"VALUES('".$course_code."', '".$_user['user_id']."', '$time', '$time', '1','".api_get_session_id()."')";
//error_log($sql);
Database::query($sql);
//error_log(preg_replace('/\s+/',' ',$sql));
}
}
}

@ -48,6 +48,7 @@ $ConfigureHomePage = "Edit portal homepage";
$CourseCreateActiveToolsTitle = "Modules active upon course creation";
$CourseCreateActiveToolsComment = "Which tools have to be enabled (visible) by default when a new course is created?";
$SearchUsers = "Search users";
$SearchUser = "Search users";
$CreateUser = "Create user";
$ModifyInformation = "Edit information";
$ModifyUser = "Edit user";

@ -44,6 +44,7 @@ $ConfigureHomePage = "Configuración de la página principal";
$CourseCreateActiveToolsTitle = "Módulos activos al crear un curso";
$CourseCreateActiveToolsComment = "¿Qué herramientas serán activadas (visibles) por defecto al crear un curso?";
$SearchUsers = "Búsqueda de usuarios";
$SearchUser = "Buscar usuarios";
$CreateUser = "Crear usuario";
$ModifyInformation = "Modificar información";
$ModifyUser = "Modificar usuario";

@ -379,4 +379,10 @@ $FollowedSessions = "Sesiones seguidas";
$FollowedCourses = "Cursos seguidos";
$FollowedUsers = "Usuarios seguidos";
$Timeline = "Línea del tiempo";
$QuestionId = "ID de pregunta";
$ExerciseId = "ID de ejercicio";
$QuestionTitle = "Título pregunta";
$DisplayGradeOverview = "Reporte de Notas por Curso";
$LpGradeReport = "Reporte de Notas por Curso";
$FinalScore = "Nota Final";
?>

@ -398,4 +398,5 @@ $AssessmentQuestions = "¿ Cómo van a ser evaluados los estudiantes ? ¿ Cuále
$AssessmentInformation = "Ejemplos de las preguntas de examen. Criterios de evaluación. Pistas y trucos.";
$UploadADocument = "Subir un documento";
$LowerCaseUser = "usuario";
$ChooseEvaluation = "Seleccione la Evaluación";
?>

@ -202,8 +202,7 @@ if ($check) {
}
Security::clear_token();
}
//Generate a new token
// user info
$user_info = api_get_user_info($student_id);
@ -861,7 +860,8 @@ if (empty($_GET['details'])) {
<table class="data_table">
<tr>
<th><?php echo get_lang('Exercices'); ?></th>
<th><?php echo get_lang('AverageScore').' '.Display :: return_icon('info3.gif', get_lang('AverageScore'), array('align' => 'absmiddle', 'hspace' => '3px')) ?></th>
<th><?php echo get_lang('LearningPath');?></th>
<th><?php echo get_lang('AvgCourseScore').' '.Display :: return_icon('info3.gif', get_lang('AverageScore'), array('align' => 'absmiddle', 'hspace' => '3px')) ?></th>
<th><?php echo get_lang('Attempts'); ?></th>
<th><?php echo get_lang('LatestAttempt'); ?></th>
<th><?php echo get_lang('AllAttempts'); ?></th>
@ -878,7 +878,6 @@ if (empty($_GET['details'])) {
$t_quiz = Database :: get_course_table(TABLE_QUIZ_TEST);
$sql_exercices = "SELECT quiz.title, id FROM " . $t_quiz . " AS quiz
WHERE quiz.c_id = ".$info_course['real_id']." AND
active='1' AND
(quiz.session_id = $session_id OR quiz.session_id = 0)
ORDER BY quiz.title ASC ";
@ -887,14 +886,23 @@ if (empty($_GET['details'])) {
if (Database :: num_rows($result_exercices) > 0) {
while ($exercices = Database :: fetch_array($result_exercices)) {
$exercise_id = intval($exercices['id']);
$count_attempts = Tracking::count_student_exercise_attempts($student_id, $course_code, $exercise_id, 0, 0, $session_id);
$score_percentage = Tracking::get_avg_student_exercise_score($student_id, $course_code, $exercise_id, $session_id);
$lp_name = '';
$count_attempts = Tracking::count_student_exercise_attempts($student_id, $course_code, $exercise_id, 0, 0, $session_id, 2);
$score_percentage = Tracking::get_avg_student_exercise_score($student_id, $course_code, $exercise_id, $session_id, 1, 0);
if (!isset($score_percentage) && $count_attempts > 0) {
$scores_lp = Tracking::get_avg_student_exercise_score($student_id, $course_code, $exercise_id, $session_id, 2, 1);
$score_percentage = $scores_lp[0];
$lp_name = $scores_lp[1];
} else {
$lp_name = '-';
}
$lp_name = (!empty($lp_name))? $lp_name: get_lang('NoLearnpath');
$csv_content[] = array (
$exercices['title'],
$score_percentage . '%',
$count_attempts
);
if ($i % 2) $css_class = 'row_odd';
@ -902,6 +910,16 @@ if (empty($_GET['details'])) {
echo '<tr class="'.$css_class.'"><td>'.$exercices['title'].'</td>';
echo '<td>';
if (!empty($lp_name)) {
echo $lp_name;
} else {
echo '-';
}
echo '</td>';
echo '<td>';
if ($count_attempts > 0) {
@ -920,9 +938,7 @@ if (empty($_GET['details'])) {
exe_user_id ="'.$student_id.'" AND
exe_cours_id ="'.$course_code.'" AND
session_id ="'.$session_id.'" AND
status = "" AND
orig_lp_id = 0 AND
orig_lp_item_id = 0
status = ""
ORDER BY exe_date DESC LIMIT 1';
$result_last_attempt = Database::query($sql_last_attempt);
if (Database :: num_rows($result_last_attempt) > 0) {

@ -274,7 +274,7 @@ class MySpace {
* Display a sortable table that contains an overview off all the progress of the user in a session
* @author César Perales <cesar.perales@beeznest.com>, Beeznest Team
*/
public function display_tracking_lp_progress_overview($sessionId = '', $courseId = '') {
public static function display_tracking_lp_progress_overview($sessionId = '', $courseId = '', $date_from, $date_to) {
$course = api_get_course_info_by_id($courseId);
/**
@ -316,7 +316,7 @@ class MySpace {
$action_links = '';
// jqgrid will use this URL to do the selects
$url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_session_lp_progress&session_id=' . intval($sessionId) . '&course_id=' . intval($courseId);
$url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_session_lp_progress&session_id=' . $sessionId . '&course_id=' . $courseId . '&date_to=' . $date_to . '&date_from=' . $date_from;
//Table Id
$tableId = 'lpProgress';
@ -344,13 +344,17 @@ class MySpace {
}
/**
* Display a sortable table that contains an overview off all the progress of the user in a session
* @param int $sessionId The session ID
* @param int $courseId The course ID
* @param int $exerciseId The quiz ID
* @param int $answer Answer status (0 = incorrect, 1 = correct, 2 = both)
* @return string HTML array of results formatted for gridJS
* @author César Perales <cesar.perales@beeznest.com>, Beeznest Team
*/
function display_tracking_exercise_progress_overview($sessionId = 0, $courseId = 0, $exerciseId = 0, $answer = 2) {
static function display_tracking_exercise_progress_overview($sessionId = 0, $courseId = 0, $exerciseId = 0, $date_from, $date_to) {
/**
* Column name
* The order is important you need to check the $column variable in the model.ajax.php file
* Column names
* The column order is important. Check $column variable in the main/inc/ajax/model.ajax.php file
*/
$columns = array(
get_lang('Session'),
@ -362,6 +366,7 @@ class MySpace {
get_lang('Time'),
get_lang('QuestionId'),
get_lang('QuestionTitle'),
get_lang('WorkDescription'),
get_lang('Answer'),
get_lang('Correct'),
);
@ -379,14 +384,14 @@ class MySpace {
array('name'=>'time', 'index'=>'time', 'align'=>'left', 'search' => 'true', 'wrap_cell' => "true"),
array('name'=>'question_id', 'index'=>'question_id', 'align'=>'left', 'search' => 'true'),
array('name'=>'question', 'index'=>'question', 'align'=>'left', 'search' => 'true', 'wrap_cell' => "true"),
array('name'=>'description', 'index'=>'description', 'align'=>'left', 'width' => '550', 'search' => 'true', 'wrap_cell' => "true"),
array('name'=>'answer', 'index'=>'answer', 'align'=>'left', 'search' => 'true', 'wrap_cell' => "true"),
array('name'=>'correct', 'index'=>'correct', 'align'=>'left', 'search' => 'true'),
array('name'=>'correct', 'index'=>'correct', 'align'=>'left', 'search' => 'true', 'wrap_cell' => "true"),
);
//get dinamic column names
//get dynamic column names
$action_links = '';
// jqgrid will use this URL to do the selects
$url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_exercise_progress&session_id=' . intval($sessionId) . '&course_id=' . intval($courseId) . '&exercise_id=' . intval($exerciseId) . '&answer=' . intval($answer);
$url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_exercise_progress&session_id=' . $sessionId . '&course_id=' . $courseId . '&exercise_id=' . $exerciseId . '&date_to=' . $date_to . '&date_from=' . $date_from;
//Autowidth
$extra_params['autowidth'] = 'true';
@ -395,7 +400,7 @@ class MySpace {
$extra_params['height'] = 'auto';
$tableId = 'exerciseProgressOverview';
$table = Display::grid_js($tableId, $url, $columns, $column_model, $extra_params, array(), $action_links, true);
$table = Display::grid_js($tableId, $url, $columns, $column_model, $extra_params, array(), '', true);
$return = '<script>$(function() {'. $table .
'jQuery("#'.$tableId.'").jqGrid("navGrid","#'.$tableId.'_pager",{view:false, edit:false, add:false, del:false, search:false, excel:true});
@ -410,11 +415,126 @@ class MySpace {
$return .= Display::grid_html($tableId);
return $return;
}
/**
* Display a sortable table that contains an overview off all the progress of the user in a session
* @param int $sessionId The session ID
* @param int $courseId The course ID
* @param null $date_from
* @param null $date_to
* @internal param int $exerciseId The quiz ID
* @internal param int $answer Answer status (0 = incorrect, 1 = correct, 2 = both)
* @return string HTML array of results formatted for gridJS
* @author Francis Gonzales <francis.gonzales@beeznest.com>, Beeznest Team
*/
static function display_tracking_grade_overview($sessionId = 0, $courseId = 0, $date_from = null, $date_to = null)
{
/**
* Column names
* The column order is important. Check $column variable in the main/inc/ajax/model.ajax.php file
*/
$objExercise = new Exercise();
$exercises = $objExercise->getExercisesByCouseSession($courseId, $sessionId);
$cntExer = 4;
if (!empty($exercises)) {
$cntExer += count($exercises);
}
$column = array();
$column_model = array();
$i = 1;
//Get dynamic column names
foreach (range(1, $cntExer) as $cnt) {
switch ($cnt) {
case 1:
$column[] = get_lang('Section');
$column_model[] = array(
'name' => 'session',
'index' => 'session',
'align' => 'center',
'search' => 'true',
);
break;
case 2:
$column[] = get_lang('Username');
$column_model[] = array(
'name' => 'username',
'index' => 'username',
'align' => 'center',
'search' => 'true',
);
break;
case 3:
$column[] = get_lang('FirstName');
$column_model[] = array(
'name' => 'name',
'index' => 'name',
'align' => 'left',
'search' => 'true',
);
break;
case $cntExer:
$column[] = get_lang('FinalScore');
$column_model[] = array(
'name' => 'finalscore',
'index' => 'finalscore',
'align' => 'center',
'search' => 'true',
'wrap_cell' => "true"
);
break;
default:
$title = "";
if (!empty($exercises[$cnt - 4]['title'])) {
$title = ucwords(strtolower(trim($exercises[$cnt - 4]['title'])));
}
$column[] = $title;
$column_model[] = array(
'name' => 'exer' . $i,
'index' => 'exer' . $i,
'align' => 'center',
'search' => 'true',
'wrap_cell' => "true"
);
$i++;
break;
}
}
//end get dynamic column names
// jqgrid will use this URL to do the selects
$url = api_get_path(WEB_AJAX_PATH) . 'model.ajax.php?a=get_exercise_grade&session_id=' . $sessionId . '&course_id=' . $courseId;
//Autowidth
$extra_params['autowidth'] = 'true';
//height auto
$extra_params['height'] = 'auto';
$tableId = 'exerciseGradeOverview';
$table = Display::grid_js($tableId, $url, $column, $column_model, $extra_params, array(), '', true);
$return = '<script>$(function() {' . $table .
'jQuery("#' . $tableId . '").jqGrid("navGrid","#' . $tableId . '_pager",{view:false, edit:false, add:false, del:false, search:false, excel:true});
jQuery("#' . $tableId . '").jqGrid("navButtonAdd","#' . $tableId . '_pager",{
caption:"",
title:"' . get_lang('ExportExcel') . '",
onClickButton : function () {
jQuery("#' . $tableId . '").jqGrid("excelExport",{"url":"' . $url . '&export_format=xls"});
}
});
});</script>';
$return .= Display::grid_html($tableId);
return $return;
}
/**
* Display a sortable table that contains an overview off all the progress of the user in a session
* @author César Perales <cesar.perales@beeznest.com>, Beeznest Team
*/
function display_survey_overview($sessionId = 0, $courseId = 0, $surveyId = 0, $answer = 2) {
function display_survey_overview($sessionId = 0, $courseId = 0, $surveyId = 0, $date_from, $date_to) {
$course = api_get_course_info_by_id($courseId);
/**
@ -451,7 +571,7 @@ class MySpace {
$action_links = '';
// jqgrid will use this URL to do the selects
$url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_survey_overview&session_id=' . intval($sessionId) . '&course_id=' . intval($courseId) . '&survey_id=' . intval($surveyId);
$url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_survey_overview&session_id=' . $sessionId . '&course_id=' . $courseId . '&survey_id=' . $surveyId . '&date_to=' . $date_to . '&date_from=' . $date_from;
//Table Id
$tableId = 'lpProgress';
@ -481,7 +601,7 @@ class MySpace {
* Display a sortable table that contains an overview off all the progress of the user in a session
* @author César Perales <cesar.perales@beeznest.com>, Beeznest Team
*/
function display_tracking_progress_overview($sessionId = 0, $courseId = 0) {
static function display_tracking_progress_overview($sessionId = 0, $courseId = 0, $date_from, $date_to) {
//The order is important you need to check the the $column variable in the model.ajax.php file
$columns = array(
@ -490,15 +610,13 @@ class MySpace {
get_lang('Username'),
#get_lang('Profile'),
get_lang('Total'),
get_lang('CourseDescription'),
get_lang('Courses'),
get_lang('LearningPaths'),
get_lang('Exercises'),
get_lang('Forums'),
get_lang('Assignments'),
get_lang('ToolWiki'),
get_lang('ToolSurvey'),
//course description
get_lang('CourseDescriptionProgress'),
//Learning paths
get_lang('LearnpathsTotal'),
get_lang('LearnpathsDone'),
@ -534,56 +652,54 @@ class MySpace {
//Column config
$column_model = array(
array('name'=>'lastname', 'index'=>'lastname', 'align'=>'left', 'search' => 'true'),
array('name'=>'firstname', 'index'=>'firstname', 'align'=>'left', 'search' => 'true'),
array('name'=>'username', 'index'=>'username', 'align'=>'left', 'search' => 'true'),
#array('name'=>'profile', 'index'=>'username', 'align'=>'left', 'search' => 'true'),
array('name'=>'total', 'index'=>'total', 'align'=>'left', 'search' => 'true'),
array('name'=>'courses', 'index'=>'courses', 'align'=>'left', 'search' => 'true'),
array('name'=>'lessons', 'index'=>'lessons', 'align'=>'left', 'search' => 'true'),
array('name'=>'exercises', 'index'=>'exercises', 'align'=>'left', 'search' => 'true'),
array('name'=>'forums', 'index'=>'forums', 'align'=>'left', 'search' => 'true'),
array('name'=>'homeworks', 'index'=>'homeworks', 'align'=>'left', 'search' => 'true'),
array('name'=>'wikis', 'index'=>'wikis', 'align'=>'left', 'search' => 'true'),
array('name'=>'surveys', 'index'=>'surveys', 'align'=>'left', 'search' => 'true'),
//Course description
array('name'=>'course_description_progress', 'index'=>'course_description_progress', 'align'=>'left', 'search' => 'true'),
array('name'=>'lastname', 'index'=>'lastname', 'align'=>'left'),
array('name'=>'firstname', 'index'=>'firstname', 'align'=>'left'),
array('name'=>'username', 'index'=>'username', 'align'=>'left'),
#array('name'=>'profile', 'index'=>'username', 'align'=>'left'),
array('name'=>'total', 'index'=>'total', 'align'=>'left'),
array('name'=>'courses', 'index'=>'courses', 'align'=>'left', 'sortable' => 'false'),
array('name'=>'lessons', 'index'=>'lessons', 'align'=>'left', 'sortable' => 'false'),
array('name'=>'exercises', 'index'=>'exercises', 'align'=>'left', 'sortable' => 'false'),
array('name'=>'forums', 'index'=>'forums', 'align'=>'left', 'sortable' => 'false'),
array('name'=>'homeworks', 'index'=>'homeworks', 'align'=>'left', 'sortable' => 'false'),
array('name'=>'wikis', 'index'=>'wikis', 'align'=>'left', 'sortable' => 'false'),
array('name'=>'surveys', 'index'=>'surveys', 'align'=>'left', 'sortable' => 'false'),
//Lessons
array('name'=>'lessons_total', 'index'=>'lessons_total', 'align'=>'left', 'search' => 'true'),
array('name'=>'lessons_done', 'index'=>'lessons_done', 'align'=>'left', 'search' => 'true'),
array('name'=>'lessons_left', 'index'=>'lessons_left', 'align'=>'left', 'search' => 'true'),
array('name'=>'lessons_progress', 'index'=>'lessons_progress', 'align'=>'left', 'search' => 'true'),
array('name'=>'lessons_total', 'index'=>'lessons_total', 'align'=>'center', 'sortable' => 'false'),
array('name'=>'lessons_done', 'index'=>'lessons_done', 'align'=>'center', 'sortable' => 'false'),
array('name'=>'lessons_left', 'index'=>'lessons_left', 'align'=>'center', 'sortable' => 'false'),
array('name'=>'lessons_progress', 'index'=>'lessons_progress', 'align'=>'center', 'sortable' => 'false'),
//Exercises
array('name'=>'exercises_total', 'index'=>'exercises_total', 'align'=>'left', 'search' => 'true'),
array('name'=>'exercises_done', 'index'=>'exercises_done', 'align'=>'left', 'search' => 'true'),
array('name'=>'exercises_left', 'index'=>'exercises_left', 'align'=>'left', 'search' => 'true'),
array('name'=>'exercises_progress', 'index'=>'exercises_progress', 'align'=>'left', 'search' => 'true'),
array('name'=>'exercises_total', 'index'=>'exercises_total', 'align'=>'center', 'sortable' => 'false'),
array('name'=>'exercises_done', 'index'=>'exercises_done', 'align'=>'center', 'sortable' => 'false'),
array('name'=>'exercises_left', 'index'=>'exercises_left', 'align'=>'center', 'sortable' => 'false'),
array('name'=>'exercises_progress', 'index'=>'exercises_progress', 'align'=>'center', 'sortable' => 'false'),
//Assignments
array('name'=>'forums_total', 'index'=>'forums_total', 'align'=>'left', 'search' => 'true'),
array('name'=>'forums_done', 'index'=>'forums_done', 'align'=>'left', 'search' => 'true'),
array('name'=>'forums_left', 'index'=>'forums_left', 'align'=>'left', 'search' => 'true'),
array('name'=>'forums_progress', 'index'=>'forums_progress', 'align'=>'left', 'search' => 'true'),
array('name'=>'forums_total', 'index'=>'forums_total', 'align'=>'center', 'sortable' => 'false'),
array('name'=>'forums_done', 'index'=>'forums_done', 'align'=>'center', 'sortable' => 'false'),
array('name'=>'forums_left', 'index'=>'forums_left', 'align'=>'center', 'sortable' => 'false'),
array('name'=>'forums_progress', 'index'=>'forums_progress', 'align'=>'center', 'sortable' => 'false'),
//Assignments
array('name'=>'assigments_total', 'index'=>'assigments_total', 'align'=>'left', 'search' => 'true'),
array('name'=>'assigments_done', 'index'=>'assigments_done', 'align'=>'left', 'search' => 'true'),
array('name'=>'assigments_left', 'index'=>'assigments_left', 'align'=>'left', 'search' => 'true'),
array('name'=>'assigments_progress', 'index'=>'assigments_progress', 'align'=>'left', 'search' => 'true'),
array('name'=>'assigments_total', 'index'=>'assigments_total', 'align'=>'center', 'sortable' => 'false'),
array('name'=>'assigments_done', 'index'=>'assigments_done', 'align'=>'center', 'sortable' => 'false'),
array('name'=>'assigments_left', 'index'=>'assigments_left', 'align'=>'center', 'sortable' => 'false'),
array('name'=>'assigments_progress', 'index'=>'assigments_progress', 'align'=>'center', 'sortable' => 'false'),
//Assignments
array('name'=>'wiki_total', 'index'=>'wiki_total', 'align'=>'left', 'search' => 'true'),
array('name'=>'wiki_revisions', 'index'=>'wiki_revisions', 'align'=>'left', 'search' => 'true'),
array('name'=>'wiki_read', 'index'=>'wiki_read', 'align'=>'left', 'search' => 'true'),
array('name'=>'wiki_unread', 'index'=>'wiki_unread', 'align'=>'left', 'search' => 'true'),
array('name'=>'wiki_progress', 'index'=>'wiki_progress', 'align'=>'left', 'search' => 'true'),
array('name'=>'wiki_total', 'index'=>'wiki_total', 'align'=>'center', 'sortable' => 'false'),
array('name'=>'wiki_revisions', 'index'=>'wiki_revisions', 'align'=>'center', 'sortable' => 'false'),
array('name'=>'wiki_read', 'index'=>'wiki_read', 'align'=>'center', 'sortable' => 'false'),
array('name'=>'wiki_unread', 'index'=>'wiki_unread', 'align'=>'center', 'sortable' => 'false'),
array('name'=>'wiki_progress', 'index'=>'wiki_progress', 'align'=>'center', 'sortable' => 'false'),
//Surveys
array('name'=>'surveys_total', 'index'=>'surveys_total', 'align'=>'left', 'search' => 'true'),
array('name'=>'surveys_done', 'index'=>'surveys_done', 'align'=>'left', 'search' => 'true'),
array('name'=>'surveys_left', 'index'=>'surveys_left', 'align'=>'left', 'search' => 'true'),
array('name'=>'surveys_progress', 'index'=>'surveys_progress', 'align'=>'left', 'search' => 'true'),
array('name'=>'surveys_total', 'index'=>'surveys_total', 'align'=>'center', 'sortable' => 'false'),
array('name'=>'surveys_done', 'index'=>'surveys_done', 'align'=>'center', 'sortable' => 'false'),
array('name'=>'surveys_left', 'index'=>'surveys_left', 'align'=>'center', 'sortable' => 'false'),
array('name'=>'surveys_progress', 'index'=>'surveys_progress', 'align'=>'center', 'sortable' => 'false'),
);
$action_links = '';
// jqgrid will use this URL to do the selects
$url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_session_progress&session_id=' . intval($sessionId) . '&course_id=' . intval($courseId);
$url = api_get_path(WEB_AJAX_PATH).'model.ajax.php?a=get_session_progress&session_id=' . $sessionId . '&course_id=' . $courseId . '&date_to=' . $date_to . '&date_from=' . $date_from;
//Table Id
$tableId = 'progressOverview';
@ -591,6 +707,47 @@ class MySpace {
//Autowidth
$extra_params['autowidth'] = 'true';
$extra_params['shrinkToFit'] = 'true';
$extra_params['headertitles'] = 'true';
$extra_params['groupHeaders'] = array(
'courses_detail' => array(
"startColumnName" => 'courses',
"numberOfColumns" => 7,
"titleText" => get_lang('Global'),
),
'lessons' => array(
"startColumnName" => 'lessons_total',
"numberOfColumns" => 4,
"titleText" => get_lang('LearningPaths'),
),
'exercises' => array(
"startColumnName" => 'exercises_total',
"numberOfColumns" => 4,
"titleText" => get_lang('Exercises'),
),
'forums' => array(
"startColumnName" => 'forums_total',
"numberOfColumns" => 4,
"titleText" => get_lang('Forums'),
),
'assignments' => array(
"startColumnName" => 'assigments_total',
"numberOfColumns" => 4,
"titleText" => get_lang('Assignments'),
),
'wikis' => array(
"startColumnName" => 'wiki_total',
"numberOfColumns" => 5,
"titleText" => get_lang('Wiki'),
),
'surveys' => array(
"startColumnName" => 'surveys_total',
"numberOfColumns" => 4,
"titleText" => get_lang('Survey'),
),
);
//height auto
$extra_params['height'] = 'auto';
@ -614,16 +771,17 @@ class MySpace {
* @author César Perales <cesar.perales@beeznest.com>, Beeznest Team
* @version Chamilo 1.9.6
*/
function display_tracking_access_overview($sessionId = 0, $courseId = 0, $studentId = '', $profile = '', $date_to, $date_from) {
static function display_tracking_access_overview($sessionId = 0, $courseId = 0, $studentId = '', $profile = '', $date_from, $date_to) {
//The order is important you need to check the the $column variable in the model.ajax.php file
$columns = array(
get_lang('LoginDate'),
get_lang('Username'),
get_lang('Firstname'),
get_lang('Lastname'),
get_lang('UserName'),
get_lang('LastName'),
get_lang('FirstName'),
get_lang('Clicks'),
get_lang('IP'),
get_lang('TimeLoggedIn'),
get_lang('Section'),
);
$column_model = array(
@ -634,6 +792,7 @@ class MySpace {
array('name'=>'clicks', 'index'=>'clicks', 'align'=>'left', 'search' => 'true'),
array('name'=>'ip', 'index'=>'ip', 'align'=>'left', 'search' => 'true'),
array('name'=>'timeloggedin', 'index'=>'timeLoggedIn', 'align'=>'left', 'search' => 'true'),
array('name'=>'session', 'index'=>'session', 'align'=>'left')
);
$action_links = '';

@ -170,7 +170,7 @@ class learnpathList {
* @param int Id of session
* @return array List of lessons with lessons id as keys
*/
function get_course_lessons($course_code, $session_id) {
static function get_course_lessons($course_code, $session_id) {
$tbl_course_lp = Database::get_course_table(TABLE_LP_MAIN);
$course = api_get_course_info($course_code);

@ -44,7 +44,7 @@ require_once 'aiccItem.class.php';
* @param array Interactions array
* @param string Core exit SCORM string
*/
function save_item($lp_id, $user_id, $view_id, $item_id, $score = -1, $max = -1, $min = -1, $status = '', $time = 0, $suspend = '', $location = '', $interactions = array(), $core_exit = 'none')
function save_item($lp_id, $user_id, $view_id, $item_id, $score = -1, $max = -1, $min = -1, $status = '', $time = 0, $suspend = '', $location = '', $interactions = array(), $core_exit = 'none', $sessionId = null, $courseId = null)
{
global $debug;
$return = null;
@ -58,6 +58,9 @@ function save_item($lp_id, $user_id, $view_id, $item_id, $score = -1, $max = -1,
$mylp = null;
$lpobject = Session::read('lpobject');
if (!is_object($lpobject) && isset($sessionId) && isset($courseId)) {
$lpobject = new learnpathItem($lp_id, $user_id, $courseId);
}
if (isset($lpobject)) {
$oLP = unserialize($lpobject);
if ($debug) error_log("lpobject was set");
@ -305,5 +308,8 @@ echo save_item(
(!empty($_REQUEST['suspend'])?$_REQUEST['suspend']:null),
(!empty($_REQUEST['loc'])?$_REQUEST['loc']:null),
$interactions,
(!empty($_REQUEST['core_exit'])?$_REQUEST['core_exit']:'')
(!empty($_REQUEST['core_exit'])?$_REQUEST['core_exit']:''),
'',
(!empty($_REQUEST['session_id'])?$_REQUEST['session_id']:''),
(!empty($_REQUEST['course_id'])?$_REQUEST['course_id']:'')
);

@ -864,6 +864,12 @@ switch ($action) {
$_SESSION['oLP']->delete_lp_image();
}
$extraFieldValue = new ExtraFieldValue('lp');
$params = array(
'lp_id' => $_SESSION['oLP']->id
);
$extraFieldValue->save_field_values($_REQUEST);
if ($_FILES['lp_preview_image']['size'] > 0)
$_SESSION['oLP']->upload_image($_FILES['lp_preview_image']);

@ -50,11 +50,6 @@ function activate_end_date() {
</script>';
Display::display_header(get_lang('CourseSettings'), 'Path');
echo $_SESSION['oLP']->build_action_menu();
$gradebook = isset($_GET['gradebook']) ? Security::remove_XSS($_GET['gradebook']) : null;
$defaults=array();
@ -198,6 +193,9 @@ if (api_is_platform_admin()) {
$defaults['use_max_score'] = $_SESSION['oLP']->use_max_score;
}
$extraField = new ExtraField('lp');
$extra = $extraField->addElements($form, $_SESSION['oLP']->get_id());
//Submit button
$form->addElement('style_submit_button', 'Submit',get_lang('SaveLPSettings'),'class="save"');
@ -205,12 +203,24 @@ $form->addElement('style_submit_button', 'Submit',get_lang('SaveLPSettings'),'cl
$form->addElement('hidden', 'action', 'update_lp');
$form->addElement('hidden', 'lp_id', $_SESSION['oLP']->get_id());
$htmlHeadXtra[] = '<script src="'.api_get_path(WEB_LIBRARY_PATH).'javascript/tag/jquery.fcbkcomplete.js" type="text/javascript" language="javascript"></script>';
$htmlHeadXtra[] = '<link href="'.api_get_path(WEB_LIBRARY_PATH).'javascript/tag/style.css" rel="stylesheet" type="text/css" />';
$htmlHeadXtra[] ='<script>
$(function() {
'.$extra['jquery_ready_content'].'
});
</script>';
$defaults['publicated_on'] = ($publicated_on!='0000-00-00 00:00:00' && !empty($publicated_on))? api_get_local_time($publicated_on) : date('Y-m-d 12:00:00');
$defaults['expired_on'] = ($expired_on !='0000-00-00 00:00:00' && !empty($expired_on) )? api_get_local_time($expired_on): date('Y-m-d 12:00:00',time()+84600);
$form->setDefaults($defaults);
Display::display_header(get_lang('CourseSettings'), 'Path');
echo $_SESSION['oLP']->build_action_menu();
echo '<div class="row">';
if ($_SESSION['oLP']->get_hide_toc_frame() == 1) {

@ -48,7 +48,7 @@ $course_id = $course_info['real_id'];
if (isset($_GET['student_id'])) {
$student_id = intval($_GET['student_id']);
}
$session_id = api_get_session_id();
$session_id = ($_GET['id_session'])? intval($_GET['id_session']) : api_get_session_id();
$session_condition = api_get_session_condition($session_id);
//When origin is not set that means that the lp_stats are viewed from the "man running" icon
@ -859,10 +859,10 @@ if (!empty($a_my_id)) {
//var_dump($my_studen_id, $my_course_id,$a_my_id);
if (isset($_GET['extend_attempt'])) {
//"Right green cross" extended
$total_score = Tracking::get_avg_student_score($my_studen_id, $my_course_id, $a_my_id, api_get_session_id(), false, false);
$total_score = Tracking::get_avg_student_score($my_studen_id, $my_course_id, $a_my_id, $session_id, false, false);
} else {
//"Left green cross" extended
$total_score = Tracking::get_avg_student_score($my_studen_id, $my_course_id, $a_my_id, api_get_session_id(), false, true);
$total_score = Tracking::get_avg_student_score($my_studen_id, $my_course_id, $a_my_id, $session_id, false, true);
}
} else {
// Extend all "left green cross"
@ -870,12 +870,12 @@ if (!empty($a_my_id)) {
$my_course_id = Database::escape_string($_GET['course']);
// var_dump($student_id, $my_course_id );
if (!empty($student_id) && !empty($my_course_id)) {
$total_score = Tracking::get_avg_student_score($student_id, $my_course_id, array(intval($_GET['lp_id'])), api_get_session_id(), false, false);
$total_score = Tracking::get_avg_student_score($student_id, $my_course_id, array(intval($_GET['lp_id'])), $session_id, false, false);
} else {
$total_score = 0;
}
} else {
$total_score = Tracking::get_avg_student_score(api_get_user_id(), api_get_course_id(), array(intval($_GET['lp_id'])), api_get_session_id(), false, false);
$total_score = Tracking::get_avg_student_score(api_get_user_id(), api_get_course_id(), array(intval($_GET['lp_id'])), $session_id, false, false);
}
}

@ -183,8 +183,8 @@ olms.lms_item_lesson_mode = '<?php echo $oItem->get_lesson_mode();?>';
olms.lms_item_launch_data = '<?php echo addslashes($oItem->get_launch_data());?>';
olms.lms_item_core_exit = '<?php echo $oItem->get_core_exit();?>';
olms.lms_course_id = '<?php echo $oLP->get_course_int_id(); ?>';
olms.lms_session_id = '<?php echo api_get_session_id(); ?>';
olms.lms_course_code = '<?php echo $oLP->getCourseCode(); ?>';
<?php echo $oLP->get_items_details_as_js('olms.lms_item_types');?>
olms.asset_timer = 0;
@ -1498,13 +1498,31 @@ function switch_item(current_item, next_item){
* @return void
* @uses lp_ajax_save_item.php through an AJAX call
*/
function xajax_save_item(lms_lp_id, lms_user_id, lms_view_id, lms_item_id, score, max, min, lesson_status, session_time, suspend_data, lesson_location, interactions, lms_item_core_exit, item_type) {
function xajax_save_item(
lms_lp_id,
lms_user_id,
lms_view_id,
lms_item_id,
score,
max,
min,
lesson_status,
session_time,
suspend_data,
lesson_location,
interactions,
lms_item_core_exit,
item_type,
session_id,
course_id) {
var params = '';
params += 'lid='+lms_lp_id+'&uid='+lms_user_id+'&vid='+lms_view_id;
params += '&iid='+lms_item_id+'&s='+score+'&max='+max+'&min='+min;
params += '&status='+lesson_status+'&t='+session_time;
params += '&suspend='+suspend_data+'&loc='+lesson_location;
params += '&core_exit='+lms_item_core_exit;
params += '&session_id='+session_id;
params += '&course_id='+course_id;
//console.info(session_time);
if (olms.lms_lp_type == 1 || item_type == 'document') {
logit_lms('xajax_save_item with params:' + params,3);

@ -119,7 +119,16 @@ if (!empty($course_list)) {
true
);
$lp_list = $list->get_flat_list();
$lp_count = count($lp_list);
$lp_count = 0;
if(!empty($lp_list)) {
foreach ($lp_list as $valLp) {
if($valLp['lp_visibility']) {
$lp_count++;
}
}
}
$course_info = api_get_course_info($course_data['code']);
$exercise_count = count(get_all_exercises($course_info, $session_id, true));

Loading…
Cancel
Save