Update from 1.11.x

pull/3272/head
Julio Montoya 6 years ago
parent 024a2054bc
commit a0a31da801
  1. 139
      public/main/inc/lib/exercise.lib.php
  2. 2537
      public/main/inc/lib/extra_field.lib.php
  3. 44
      public/main/inc/lib/extra_field_option.lib.php
  4. 81
      public/main/inc/lib/extra_field_value.lib.php
  5. 35
      public/main/inc/lib/glossary.lib.php
  6. 60
      public/main/inc/lib/groupmanager.lib.php
  7. 2
      public/main/inc/lib/image.lib.php
  8. 3
      public/main/inc/lib/legal.lib.php
  9. 179
      public/main/inc/lib/message.lib.php
  10. 95
      public/main/inc/lib/myspace.lib.php
  11. 362
      public/main/inc/lib/sessionmanager.lib.php
  12. 29
      public/main/inc/lib/sortable_table.class.php
  13. 2
      public/main/inc/lib/text.lib.php
  14. 385
      public/main/inc/lib/tracking.lib.php
  15. 62
      public/main/inc/lib/usergroup.lib.php
  16. 11
      public/main/inc/lib/usermanager.lib.php
  17. 19
      public/main/inc/lib/webservices/Rest.php
  18. 1
      src/CoreBundle/Controller/IndexController.php
  19. 1
      src/CoreBundle/Controller/SecurityController.php
  20. 2
      src/CoreBundle/Entity/User.php
  21. 1
      src/CoreBundle/EventListener/TwigListener.php
  22. 2
      src/CoreBundle/Security/LoginFormAuthenticator.php

@ -930,7 +930,12 @@ class ExerciseLib
WHERE exe_id = $exe_id AND question_id= $questionId";
$rsLastAttempt = Database::query($sql);
$rowLastAttempt = Database::fetch_array($rsLastAttempt);
$answer = $rowLastAttempt['answer'];
$answer = null;
if (isset($rowLastAttempt['answer'])) {
$answer = $rowLastAttempt['answer'];
}
if (empty($answer)) {
$_SESSION['calculatedAnswerId'][$questionId] = mt_rand(
1,
@ -1277,7 +1282,7 @@ HTML;
$s .= "
<script>
$(function() {
jsPlumb.ready(function() {
$(window).on('load', function() {
jsPlumb.connect({
source: 'window_$windowId',
target: 'window_{$questionId}_{$selectedIndex}_answer',
@ -1349,7 +1354,7 @@ HTML;
if (DRAGGABLE == $answerType) {
$isVertical = 'v' == $objQuestionTmp->extra;
$s .= "</ul>";
$s .= "</div>";
$s .= "</div></div>"; // col-md-12
$counterAnswer = 1;
$s .= $isVertical ? '' : '<div class="row">';
for ($answerId = 1; $answerId <= $nbrAnswers; $answerId++) {
@ -1361,7 +1366,8 @@ HTML;
<div class="'.($isVertical ? 'col-md-12' : 'col-xs-12 col-sm-4 col-md-3 col-lg-2').'">
<div class="droppable-item">
<span class="number">'.$counterAnswer.'.</span>
<div id="drop_'.$windowId.'" class="droppable">&nbsp;</div>
<div id="drop_'.$windowId.'" class="droppable">
</div>
</div>
</div>
';
@ -1779,6 +1785,7 @@ HOTSPOT;
* @param array $userExtraFieldsToAdd
* @param bool $useCommaAsDecimalPoint
* @param bool $roundValues
* @param bool $getOnyIds
*
* @return array
*/
@ -1795,7 +1802,8 @@ HOTSPOT;
$showExerciseCategories = false,
$userExtraFieldsToAdd = [],
$useCommaAsDecimalPoint = false,
$roundValues = false
$roundValues = false,
$getOnyIds = false
) {
//@todo replace all this globals
global $filter;
@ -2033,7 +2041,10 @@ HOTSPOT;
if (!empty($column)) {
$sql .= " ORDER BY $column $direction ";
}
$sql .= " LIMIT $from, $number_of_items";
if (!$getOnyIds) {
$sql .= " LIMIT $from, $number_of_items";
}
$results = [];
$resx = Database::query($sql);
@ -2570,6 +2581,7 @@ HOTSPOT;
$percentage = float_format($percentage, 1);
$score = float_format($score, 1);
$weight = float_format($weight, 1);
if ($roundValues) {
$whole = floor($percentage); // 1
$fraction = $percentage - $whole; // .25
@ -4239,16 +4251,15 @@ EOT;
}
}
if (($show_results || $show_only_score) && 'embeddable' !== $origin) {
if (isset($exercise_stat_info['exe_user_id'])) {
if (!empty($studentInfo)) {
if ('embeddable' !== $origin &&
!empty($exercise_stat_info['exe_user_id']) &&
!empty($studentInfo)
) {
// Shows exercise header
echo $objExercise->showExerciseResultHeader(
$studentInfo,
$exercise_stat_info
);
}
}
}
// Display text when test is finished #4074 and for LP #4227
@ -4690,11 +4701,8 @@ EOT;
$data = [];
/** @var TrackEExercises $item */
foreach ($result as $item) {
$bestAttemp = self::get_best_attempt_by_user($item['exeUserId'], $exerciseId, $courseId, $sessionId = 0);
$data[] = $bestAttemp;
$data[] = self::get_best_attempt_by_user($item['exeUserId'], $exerciseId, $courseId, $sessionId);
}
usort(
@ -4715,7 +4723,6 @@ EOT;
// flags to display the same position in case of tie
$lastScore = $data[0]['score'];
$position = 1;
$data = array_map(
function ($item) use (&$lastScore, &$position) {
if ($item['score'] < $lastScore) {
@ -5205,4 +5212,104 @@ EOT;
return Category::getDownloadCertificateBlock($certificate);
}
/**
* @param int $exeId ID from track_e_exercises
* @param int $userId User ID
* @param int $exerciseId Exercise ID
* @param int $courseId Optional. Coure ID.
*
* @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException
* @throws \Doctrine\ORM\TransactionRequiredException
*
* @return TrackEExercises|null
*/
public static function recalculateResult($exeId, $userId, $exerciseId, $courseId = 0)
{
if (empty($userId) || empty($exerciseId)) {
return null;
}
$em = Database::getManager();
/** @var TrackEExercises $trackedExercise */
$trackedExercise = $em->getRepository('ChamiloCoreBundle:TrackEExercises')->find($exeId);
if (empty($trackedExercise)) {
return null;
}
if ($trackedExercise->getExeUserId() != $userId ||
$trackedExercise->getExeExoId() != $exerciseId
) {
return null;
}
$questionList = $trackedExercise->getDataTracking();
if (empty($questionList)) {
return null;
}
$questionList = explode(',', $questionList);
$exercise = new Exercise($courseId);
$courseInfo = $courseId ? api_get_course_info_by_id($courseId) : [];
if ($exercise->read($exerciseId) === false) {
return null;
}
$totalScore = 0;
$totalWeight = 0;
$pluginEvaluation = QuestionOptionsEvaluationPlugin::create();
$formula = 'true' === $pluginEvaluation->get(QuestionOptionsEvaluationPlugin::SETTING_ENABLE)
? $pluginEvaluation->getFormulaForExercise($exerciseId)
: 0;
if (empty($formula)) {
foreach ($questionList as $questionId) {
$question = Question::read($questionId, $courseInfo);
if (false === $question) {
continue;
}
$totalWeight += $question->selectWeighting();
// We're inside *one* question. Go through each possible answer for this question
$result = $exercise->manage_answer(
$exeId,
$questionId,
[],
'exercise_result',
[],
false,
true,
false,
$exercise->selectPropagateNeg(),
[],
[],
true
);
// Adding the new score.
$totalScore += $result['score'];
}
} else {
$totalScore = $pluginEvaluation->getResultWithFormula($exeId, $formula);
$totalWeight = $pluginEvaluation->getMaxScore();
}
$trackedExercise
->setExeResult($totalScore)
->setExeWeighting($totalWeight);
$em->persist($trackedExercise);
$em->flush();
return $trackedExercise;
}
}

File diff suppressed because it is too large Load Diff

@ -1,4 +1,5 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Entity\ExtraFieldOptions;
@ -46,19 +47,6 @@ class ExtraFieldOption extends Model
return $this->extraField;
}
/**
* 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.
*
@ -75,7 +63,7 @@ class ExtraFieldOption extends Model
return false;
}
$extraFieldType = $this->getExtraField()->getExtraFieldType();
$fieldId = intval($fieldId);
$fieldId = (int) $fieldId;
$sql = "SELECT count(*) as count
FROM $this->table o
@ -125,11 +113,10 @@ class ExtraFieldOption extends Model
*/
public function delete_all_options_by_field_id($field_id)
{
$field_id = intval($field_id);
$field_id = (int) $field_id;
$sql = "DELETE FROM {$this->table} WHERE field_id = $field_id";
$r = Database::query($sql);
return $r;
return Database::query($sql);
}
/**
@ -173,7 +160,7 @@ class ExtraFieldOption extends Model
*/
public function save($params, $showQuery = false)
{
$field_id = intval($params['field_id']);
$field_id = (int) $params['field_id'];
if (empty($field_id)) {
return false;
@ -421,7 +408,7 @@ class ExtraFieldOption extends Model
*/
public function get_field_option_by_field_and_option($field_id, $option_value)
{
$field_id = intval($field_id);
$field_id = (int) $field_id;
$option_value = Database::escape_string($option_value);
$extraFieldType = $this->getExtraField()->getExtraFieldType();
@ -452,7 +439,7 @@ class ExtraFieldOption extends Model
*/
public function get_field_option_by_field_id_and_option_display_text($field_id, $option_display_text)
{
$field_id = intval($field_id);
$field_id = (int) $field_id;
$option_display_text = Database::escape_string($option_display_text);
$extraFieldType = $this->getExtraField()->getExtraFieldType();
@ -487,7 +474,7 @@ class ExtraFieldOption extends Model
$option_display_text,
$option_value
) {
$field_id = intval($field_id);
$field_id = (int) $field_id;
$option_display_text = Database::escape_string($option_display_text);
$option_value = Database::escape_string($option_value);
$extraFieldType = $this->getExtraField()->getExtraFieldType();
@ -520,7 +507,7 @@ class ExtraFieldOption extends Model
*/
public function get_field_options_by_field($field_id, $add_id_in_array = false, $ordered_by = null)
{
$field_id = intval($field_id);
$field_id = (int) $field_id;
$orderBy = null;
switch ($ordered_by) {
@ -589,7 +576,7 @@ class ExtraFieldOption extends Model
public function get_second_select_field_options_by_field($option_value_id, $to_json = false)
{
$em = Database::getManager();
$option = $em->find('ChamiloCoreBundle:ExtraFieldOptions', intval($option_value_id));
$option = $em->find('ChamiloCoreBundle:ExtraFieldOptions', $option_value_id);
if (!$option) {
return !$to_json ? [] : '{}';
@ -676,7 +663,7 @@ class ExtraFieldOption extends Model
*/
public function get_max_order($field_id)
{
$field_id = intval($field_id);
$field_id = (int) $field_id;
$sql = "SELECT MAX(option_order)
FROM {$this->table}
WHERE field_id = $field_id";
@ -758,7 +745,7 @@ class ExtraFieldOption extends Model
}
$form->addElement('header', $header);
$id = isset($_GET['id']) ? intval($_GET['id']) : '';
$id = isset($_GET['id']) ? (int) $_GET['id'] : '';
$form->addElement('hidden', 'id', $id);
$form->addElement('hidden', 'type', $this->type);
@ -817,9 +804,10 @@ class ExtraFieldOption extends Model
*/
public function searchByField($tag, $field_id, $limit = 10)
{
$field_id = intval($field_id);
$limit = intval($limit);
$field_id = (int) $field_id;
$limit = (int) $limit;
$tag = Database::escape_string($tag);
$sql = "SELECT DISTINCT id, option_display_text
FROM {$this->table}
WHERE
@ -928,7 +916,7 @@ class ExtraFieldOption extends Model
/**
* @param string $variable
*
* @return array|\Chamilo\CoreBundle\Entity\ExtraFieldOptions[]
* @return array|ExtraFieldOptions[]
*/
public function getOptionsByFieldVariable($variable)
{

@ -1,4 +1,5 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Entity\ExtraField as EntityExtraField;
@ -81,6 +82,7 @@ class ExtraFieldValue extends Model
* @param bool $showQuery
* @param array $saveOnlyThisFields
* @param array $avoidFields do not insert/modify this field
* @param bool $forceSave
*
* @return mixed false on empty params, void otherwise
* @assert (array()) === false
@ -90,7 +92,8 @@ class ExtraFieldValue extends Model
$onlySubmittedFields = false,
$showQuery = false,
$saveOnlyThisFields = [],
$avoidFields = []
$avoidFields = [],
$forceSave = false
) {
foreach ($params as $key => $value) {
$found = strpos($key, '__persist__');
@ -116,19 +119,22 @@ class ExtraFieldValue extends Model
// Parse params.
foreach ($extraFields as $fieldDetails) {
$field_variable = $fieldDetails['variable'];
if ($forceSave === false) {
// if the field is not visible to the user in the end, we need to apply special rules
if (1 != $fieldDetails['visible_to_self']) {
//only admins should be able to add those values
if (!api_is_platform_admin(true, true)) {
// although if not admin but sent through a CLI script, we should accept it as well
if (PHP_SAPI != 'cli') {
continue; //not a CLI script, so don't write the value to DB
//only admins should be able to add those values
if (!api_is_platform_admin(true, true)) {
// although if not admin but sent through a CLI script, we should accept it as well
if (PHP_SAPI != 'cli') {
continue; //not a CLI script, so don't write the value to DB
}
}
}
}
$field_variable = $fieldDetails['variable'];
if ($onlySubmittedFields && !isset($params['extra_'.$field_variable])) {
continue;
}
@ -362,6 +368,32 @@ class ExtraFieldValue extends Model
];
$this->save($newParams);
break;
case ExtraField::FIELD_TYPE_DATE:
$d = DateTime::createFromFormat('Y-m-d', $value);
$valid = $d && $d->format('Y-m-d') === $value;
if ($valid) {
$newParams = [
'item_id' => $params['item_id'],
'field_id' => $extraFieldInfo['id'],
'value' => $value,
'comment' => $comment,
];
$this->save($newParams, $showQuery);
}
break;
case ExtraField::FIELD_TYPE_DATETIME:
$d = DateTime::createFromFormat('Y-m-d H:i', $value);
$valid = $d && $d->format('Y-m-d H:i') === $value;
if ($valid) {
$newParams = [
'item_id' => $params['item_id'],
'field_id' => $extraFieldInfo['id'],
'value' => $value,
'comment' => $comment,
];
$this->save($newParams, $showQuery);
}
break;
default:
$newParams = [
@ -408,7 +440,9 @@ class ExtraFieldValue extends Model
$extraFieldInfo = $extra_field->get_handler_field_info_by_field_variable(
$params['variable']
);
$params['field_id'] = $extraFieldInfo['id'];
if ($extraFieldInfo) {
$params['field_id'] = $extraFieldInfo['id'];
}
}
if ($extraFieldInfo) {
@ -721,31 +755,38 @@ class ExtraFieldValue extends Model
* Gets the ID from the item (course, session, etc) for which
* the given field is defined with the given value.
*
* @param string $field_variable Field (type of data) we want to check
* @param string $field_value Data we are looking for in the given field
* @param string $variable Field (type of data) we want to check
* @param string $value Data we are looking for in the given field
* @param bool $transform Whether to transform the result to a human readable strings
* @param bool $last Whether to return the last element or simply the first one we get
* @param bool $useLike
*
* @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,
$variable,
$value,
$transform = false,
$last = false,
$all = false
$all = false,
$useLike = false
) {
$field_value = Database::escape_string($field_value);
$field_variable = Database::escape_string($field_variable);
$value = Database::escape_string($value);
$variable = Database::escape_string($variable);
$valueCondition = " value = '$value' AND ";
if ($useLike) {
$valueCondition = " value LIKE '%".$value."%' AND ";
}
$extraFieldType = $this->getExtraField()->getExtraFieldType();
$sql = "SELECT item_id FROM {$this->table} s
INNER JOIN {$this->table_handler_field} sf
ON (s.field_id = sf.id)
WHERE
value = '$field_value' AND
variable = '".$field_variable."' AND
$valueCondition
variable = '".$variable."' AND
sf.extra_field_type = $extraFieldType
ORDER BY item_id
";
@ -757,7 +798,7 @@ class ExtraFieldValue extends Model
$sql .= ' DESC';
}
$result = Database::query($sql);
if (false !== $result && Database::num_rows($result)) {
if ($result !== false && Database::num_rows($result)) {
if ($all) {
$result = Database::store_result($result, 'ASSOC');
} else {
@ -765,9 +806,9 @@ class ExtraFieldValue extends Model
}
return $result;
} else {
return false;
}
return false;
}
/**

@ -73,25 +73,42 @@ class GlossaryManager
*
* @author Isaac Flores <florespaz_isaac@hotmail.com>
*
* @param string $glossary_name The glossary term name
* @param string $name The glossary term name
*
* @return array The glossary info
*/
public static function get_glossary_term_by_glossary_name($glossary_name)
public static function get_glossary_term_by_glossary_name($name)
{
$table = Database::get_course_table(TABLE_GLOSSARY);
$session_id = api_get_session_id();
$course_id = api_get_course_int_id();
$sql_filter = api_get_session_condition($session_id);
$sql = 'SELECT * FROM '.$table.'
$sessionCondition = api_get_session_condition($session_id);
$glossaryName = Security::remove_XSS($name);
$glossaryName = api_convert_encoding($glossaryName, 'UTF-8', 'UTF-8');
$glossaryName = trim($glossaryName);
$parsed = $glossaryName;
if (api_get_configuration_value('save_titles_as_html')) {
$parsed = api_htmlentities($parsed);
$parsed = "%$parsed%";
}
$sql = "SELECT * FROM $table
WHERE
c_id = '.$course_id.' AND
name LIKE trim("'.Database::escape_string($glossary_name).'")'.$sql_filter;
c_id = $course_id AND
(
name LIKE '".Database::escape_string($glossaryName)."'
OR
name LIKE '".Database::escape_string($parsed)."'
)
$sessionCondition
LIMIT 1
";
$rs = Database::query($sql);
if (Database::num_rows($rs) > 0) {
$row = Database::fetch_array($rs, 'ASSOC');
return $row;
if (Database::num_rows($rs) > 0) {
return Database::fetch_array($rs, 'ASSOC');
}
return [];

@ -16,10 +16,6 @@ use Chamilo\CourseBundle\Entity\CGroupRelUser;
*/
class GroupManager
{
/* VIRTUAL_COURSE_CATEGORY:
in this category groups are created based on the virtual course of a course*/
public const VIRTUAL_COURSE_CATEGORY = 1;
/* DEFAULT_GROUP_CATEGORY:
When group categories aren't available (platform-setting),
all groups are created in this 'dummy'-category*/
@ -653,17 +649,18 @@ class GroupManager
public static function getGroupListFilterByName($name, $categoryId, $courseId)
{
$name = trim($name);
$name = Database::escape_string($name);
$categoryId = (int) $categoryId;
$courseId = (int) $courseId;
if (empty($name)) {
return [];
}
$name = Database::escape_string($name);
$courseId = (int) $courseId;
$table_group = Database::get_course_table(TABLE_GROUP);
$sql = "SELECT * FROM $table_group
WHERE c_id = $courseId AND name LIKE '%$name%'";
if (!empty($categoryId)) {
$categoryId = intval($categoryId);
$sql .= " AND category_id = $categoryId";
}
$sql .= " ORDER BY name";
@ -1234,8 +1231,8 @@ class GroupManager
}
if (!empty($start) && !empty($limit)) {
$start = intval($start);
$limit = intval($limit);
$start = (int) $start;
$limit = (int) $limit;
$sql .= " LIMIT $start, $limit";
}
$res = Database::query($sql);
@ -1473,11 +1470,11 @@ class GroupManager
public static function number_of_students($group_id, $course_id = null)
{
$table = Database::get_course_table(TABLE_GROUP_USER);
$group_id = intval($group_id);
$group_id = (int) $group_id;
$course_id = (int) $course_id;
if (empty($course_id)) {
$course_id = api_get_course_int_id();
} else {
$course_id = intval($course_id);
}
$sql = "SELECT COUNT(*) AS number_of_students
FROM $table
@ -1498,7 +1495,7 @@ class GroupManager
public static function maximum_number_of_students($group_id)
{
$table = Database::get_course_table(TABLE_GROUP);
$group_id = intval($group_id);
$group_id = (int) $group_id;
$course_id = api_get_course_int_id();
$sql = "SELECT max_student FROM $table
WHERE c_id = $course_id AND iid = $group_id";
@ -2247,10 +2244,11 @@ class GroupManager
*
* @param int $user_id
* @param int $courseId
* @param int|null $sessionId
*
* @return array
*/
public static function getAllGroupPerUserSubscription($user_id, $courseId = 0)
public static function getAllGroupPerUserSubscription($user_id, $courseId = 0, $sessionId = null)
{
$table_group_user = Database::get_course_table(TABLE_GROUP_USER);
$table_tutor_user = Database::get_course_table(TABLE_GROUP_TUTOR);
@ -2267,6 +2265,12 @@ class GroupManager
WHERE
g.c_id = $courseId AND
(gu.user_id = $user_id OR tu.user_id = $user_id) ";
if (null !== $sessionId) {
$sessionId = (int) $sessionId;
$sql .= " AND g.session_id = $sessionId ";
}
$res = Database::query($sql);
$groups = [];
while ($group = Database::fetch_array($res, 'ASSOC')) {
@ -2284,7 +2288,7 @@ class GroupManager
*/
public static function process_groups($group_list, $category_id = 0)
{
global $charset;
$charset = 'UTF-8';
$category_id = (int) $category_id;
$totalRegistered = 0;
$group_data = [];
@ -2292,13 +2296,16 @@ class GroupManager
$session_id = api_get_session_id();
$user_id = $user_info['user_id'];
$hideGroup = api_get_setting('hide_course_group_if_no_tools_available');
$extraField = new ExtraField('survey');
$surveyGroupExists = $extraField->get_handler_field_info_by_field_variable('group_id') ? true : false;
$url = api_get_path(WEB_CODE_PATH).'group/';
foreach ($group_list as $this_group) {
// Validation when belongs to a session
$session_img = api_get_session_image($this_group['session_id'], $user_info['status']);
// All the tutors of this group
$tutorsids_of_group = self::get_subscribed_tutors($this_group, true);
$tutors = self::get_subscribed_tutors($this_group, true);
$isMember = self::is_subscribed($user_id, $this_group);
// Create a new table-row
@ -2344,8 +2351,8 @@ class GroupManager
// Tutor name
$tutor_info = '';
if (count($tutorsids_of_group) > 0) {
foreach ($tutorsids_of_group as $tutor_id) {
if (count($tutors) > 0) {
foreach ($tutors as $tutor_id) {
$tutor = api_get_user_info($tutor_id);
$username = api_htmlentities(
sprintf(get_lang('Login: %s'), $tutor['username']),
@ -2405,7 +2412,6 @@ class GroupManager
}
}
$url = api_get_path(WEB_CODE_PATH).'group/';
// Edit-links
if (api_is_allowed_to_edit(false, true) &&
!(api_is_session_general_coach() && intval($this_group['session_id']) != $session_id)
@ -2427,10 +2433,18 @@ class GroupManager
$edit_actions .= '<a href="'.$url.'group_overview.php?action=export&type=xls&'.api_get_cidreq(true, false).'&id='.$this_group['id'].'" title="'.get_lang('Export users list').'">'.
Display::return_icon('export_excel.png', get_lang('Export'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
$edit_actions .= '<a href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=fill_one&id='.$this_group['id'].'" onclick="javascript: if(!confirm('."'".addslashes(api_htmlentities(get_lang('Please confirm your choice'), ENT_QUOTES))."'".')) return false;" title="'.get_lang('Fill the group randomly with course students').'">'.
Display::return_icon('fill.png', get_lang('Fill the group randomly with course students'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
if ($surveyGroupExists) {
$edit_actions .= Display::url(
Display::return_icon('survey.png', get_lang('ExportSurveyResults'), '', ICON_SIZE_SMALL),
$url.'group_overview.php?action=export_surveys&'.api_get_cidreq(true, false).'&id='.$this_group['id']
).'&nbsp;';
}
$edit_actions .= '<a href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=fill_one&id='.$this_group['id'].'"
onclick="javascript: if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."'".')) return false;" title="'.get_lang('FillGroup').'">'.
Display::return_icon('fill.png', get_lang('FillGroup'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
$edit_actions .= '<a href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=delete_one&id='.$this_group['id'].'" onclick="javascript: if(!confirm('."'".addslashes(api_htmlentities(get_lang('Please confirm your choice'), ENT_QUOTES))."'".')) return false;" title="'.get_lang('Delete').'">'.
$edit_actions .= '<a href="'.api_get_self().'?'.api_get_cidreq(true, false).'&category='.$category_id.'&action=delete_one&id='.$this_group['id'].'"
onclick="javascript: if(!confirm('."'".addslashes(api_htmlentities(get_lang('ConfirmYourChoice'), ENT_QUOTES))."'".')) return false;" title="'.get_lang('Delete').'">'.
Display::return_icon('delete.png', get_lang('Delete'), '', ICON_SIZE_SMALL).'</a>&nbsp;';
$row[] = $edit_actions;
@ -2899,7 +2913,7 @@ class GroupManager
*
* @return string
*/
public static function getOverview($courseId, $keyword = null)
public static function getOverview($courseId, $keyword = '')
{
$content = null;
$categories = self::get_categories();

@ -139,6 +139,8 @@ class Image
/**
* Image wrapper class.
*
* @package chamilo.include.image
*/
abstract class ImageWrapper
{

@ -1,4 +1,5 @@
<?php
/* For licensing terms, see /license.txt */
/**
@ -320,7 +321,7 @@ class LegalManager
// max 2000 chars
$languages[] = $legal[1];
if (strlen($legal[2]) > 2000) {
$legal[2] = substr($legal[2], 0, 2000).' ... ';
$legal[2] = substr(strip_tags($legal[2]), 0, 2000).' ... ';
}
if (0 == $legal[4]) {
$legal[4] = get_lang('HTML');

@ -187,7 +187,8 @@ class MessageManager
title as col1,
send_date as col2,
msg_status as col3,
user_sender_id
user_sender_id,
user_receiver_id
FROM $table
WHERE
$whereConditions
@ -206,6 +207,7 @@ class MessageManager
$sendDate = $row['col2'];
$status = $row['col3'];
$senderId = $row['user_sender_id'];
$receiverId = $row['user_receiver_id'];
$title = Security::remove_XSS($title, STUDENT, true);
$title = cut($title, 80, true);
@ -216,6 +218,9 @@ class MessageManager
}
$userInfo = api_get_user_info($senderId);
if ($type == self::MESSAGE_TYPE_OUTBOX) {
$userInfo = api_get_user_info($receiverId);
}
$message[3] = '';
if (!empty($senderId) && !empty($userInfo)) {
$message[1] = '<a '.$class.' href="'.$viewUrl.'&id='.$messageId.'">'.$title.'</a><br />';
@ -569,6 +574,7 @@ class MessageManager
} else {
$params = [
'user_sender_id' => $user_sender_id,
'user_receiver_id' => $receiver_user_id,
'msg_status' => $status,
'send_date' => $now,
'title' => $subject,
@ -577,9 +583,6 @@ class MessageManager
'parent_id' => $parent_id,
'update_date' => $now,
];
if (!empty($receiver_user_id)) {
$params['user_receiver_id'] = $receiver_user_id;
}
$messageId = Database::insert($table, $params);
}
@ -2459,6 +2462,92 @@ class MessageManager
return $messages;
}
/**
* Get the data of the last received messages for a user.
*
* @param int $userId The user id
* @param int $lastId The id of the last received message
*
* @return array
*/
public static function getReceivedMessages($userId, $lastId = 0)
{
$userId = intval($userId);
$lastId = intval($lastId);
if (empty($userId)) {
return [];
}
$messagesTable = Database::get_main_table(TABLE_MESSAGE);
$userTable = Database::get_main_table(TABLE_MAIN_USER);
$sql = "SELECT m.*, u.user_id, u.lastname, u.firstname, u.picture_uri
FROM $messagesTable as m
INNER JOIN $userTable as u
ON m.user_sender_id = u.user_id
WHERE
m.user_receiver_id = $userId AND
m.msg_status IN (".MESSAGE_STATUS_NEW.", ".MESSAGE_STATUS_UNREAD.")
AND m.id > $lastId
ORDER BY m.send_date DESC";
$result = Database::query($sql);
$messages = [];
if ($result !== false) {
while ($row = Database::fetch_assoc($result)) {
$pictureInfo = UserManager::get_user_picture_path_by_id($row['user_id'], 'web');
$row['pictureUri'] = $pictureInfo['dir'].$pictureInfo['file'];
$messages[] = $row;
}
}
return $messages;
}
/**
* Get the data of the last received messages for a user.
*
* @param int $userId The user id
* @param int $lastId The id of the last received message
*
* @return array
*/
public static function getSentMessages($userId, $lastId = 0)
{
$userId = intval($userId);
$lastId = intval($lastId);
if (empty($userId)) {
return [];
}
$messagesTable = Database::get_main_table(TABLE_MESSAGE);
$userTable = Database::get_main_table(TABLE_MAIN_USER);
$sql = "SELECT m.*, u.user_id, u.lastname, u.firstname, u.picture_uri
FROM $messagesTable as m
INNER JOIN $userTable as u
ON m.user_receiver_id = u.user_id
WHERE
m.user_sender_id = $userId
AND m.msg_status = ".MESSAGE_STATUS_OUTBOX."
AND m.id > $lastId
ORDER BY m.send_date DESC";
$result = Database::query($sql);
$messages = [];
if ($result !== false) {
while ($row = Database::fetch_assoc($result)) {
$pictureInfo = UserManager::get_user_picture_path_by_id($row['user_id'], 'web');
$row['pictureUri'] = $pictureInfo['dir'].$pictureInfo['file'];
$messages[] = $row;
}
}
return $messages;
}
/**
* Check whether a message has attachments.
*
@ -2565,7 +2654,7 @@ class MessageManager
/**
* Send a notification to all admins when a new user is registered.
*/
public static function sendNotificationByRegisteredUser(User $user)
public static function sendNotificationOfNewRegisteredUser(User $user)
{
$tplMailBody = new Template(
null,
@ -2606,6 +2695,86 @@ class MessageManager
}
}
/**
* Send a notification to all admins when a new user is registered
* while the approval method is used for users registration.
*/
public static function sendNotificationOfNewRegisteredUserApproval(User $user)
{
$tplMailBody = new Template(
null,
false,
false,
false,
false,
false,
false
);
$tplMailBody->assign('user', $user);
$tplMailBody->assign('is_western_name_order', api_is_western_name_order());
$userId = $user->getId();
$url_edit = Display::url(
api_get_path(WEB_CODE_PATH).'admin/user_edit.php?user_id='.$userId,
api_get_path(WEB_CODE_PATH).'admin/user_edit.php?user_id='.$userId
);
$tplMailBody->assign(
'manageUrl',
$url_edit
);
// Get extra field values for this user and reformat the array
$extraFieldValues = new ExtraFieldValue('user');
$userExtraFields = $extraFieldValues->getAllValuesByItem($userId);
$values = [];
foreach ($userExtraFields as $field => $value) {
$values[$value['variable']] = $value['value'];
}
$tplMailBody->assign(
'extra',
$values
);
$layoutContent = '';
$emailbody = '';
if (api_get_configuration_value('mail_template_system') == true) {
$mailTemplateManager = new MailTemplateManager();
$templateText = $mailTemplateManager->getTemplateByType('new_user_mail_to_admin_approval.tpl');
if (empty($templateText)) {
} else {
// custom procedure to load a template as a string (doesn't use cache so may slow down)
$template = $tplMailBody->twig->createTemplate($templateText);
$emailbody = $template->render($tplMailBody->params);
}
}
if (empty($emailbody)) {
$layoutContent = $tplMailBody->get_template('mail/new_user_mail_to_admin_approval.tpl');
$emailbody = $tplMailBody->fetch($layoutContent);
}
$emailsubject = '['.get_lang('ApprovalForNewAccount').'] '.$user->getUsername();
if (api_get_configuration_value('send_inscription_notification_to_general_admin_only')) {
$email = api_get_setting('emailAdministrator');
$firstname = api_get_setting('administratorSurname');
$lastname = api_get_setting('administratorName');
api_mail_html("$firstname $lastname", $email, $emailsubject, $emailbody);
} else {
$admins = UserManager::get_all_administrators();
foreach ($admins as $admin_info) {
self::send_message(
$admin_info['user_id'],
$emailsubject,
$emailbody,
[],
[],
null,
null,
null,
null,
$userId
);
}
}
}
/**
* Get the error log from failed mailing
* This assumes a complex setup where you have a cron script regularly copying the mail queue log

@ -399,7 +399,13 @@ class MySpace
$is_western_name_order = api_is_western_name_order();
}
$sort_by_first_name = api_sort_by_first_name();
$tracking_column = isset($_GET['tracking_list_coaches_column']) ? $_GET['tracking_list_coaches_column'] : ($is_western_name_order xor $sort_by_first_name) ? 1 : 0;
if (isset($_GET['tracking_list_coaches_column'])) {
$tracking_column = (int) $_GET['tracking_list_coaches_column'];
} else {
$tracking_column = ($is_western_name_order xor $sort_by_first_name) ? 1 : 0;
}
$tracking_direction = (isset($_GET['tracking_list_coaches_direction']) && in_array(strtoupper($_GET['tracking_list_coaches_direction']), ['ASC', 'DESC', 'ASCENDING', 'DESCENDING', '0', '1'])) ? $_GET['tracking_list_coaches_direction'] : 'DESC';
// Prepare array for column order - when impossible, use some of user names.
if ($is_western_name_order) {
@ -1905,12 +1911,22 @@ class MySpace
'.Display::return_icon('2rightarrow.png', get_lang('Details')).'
</a>
</center>';
$scoreInCourse = null;
if (null !== $avg_score_in_course) {
if (is_numeric($avg_score_in_course)) {
$scoreInCourse = $avg_score_in_course.'%';
} else {
$scoreInCourse = $avg_score_in_course;
}
}
$csv_content[] = [
api_html_entity_decode($row_course[1], ENT_QUOTES, $charset),
$nb_students_in_course,
$avg_time_spent_in_course,
is_null($avg_progress_in_course) ? null : $avg_progress_in_course.'%',
is_null($avg_score_in_course) ? null : is_numeric($avg_score_in_course) ? $avg_score_in_course.'%' : $avg_score_in_course,
$scoreInCourse,
is_null($avg_score_in_exercise) ? null : $avg_score_in_exercise.'%',
$avg_messages_in_course,
$avg_assignments_in_course,
@ -2673,7 +2689,8 @@ class MySpace
}
if (isset($_GET['date']) && !empty($_GET['date'])) {
$dates = DateRangePicker::parseDateRange($_GET['date']);
$dateRangePicker = new DateRangePicker('date');
$dates = $dateRangePicker->parseDateRange($_GET['date']);
if (isset($dates['start']) && !empty($dates['start'])) {
$dates['start'] = Database::escape_string($dates['start']);
$sql .= " AND login_course_date >= '".$dates['start']."'";
@ -2736,6 +2753,7 @@ class MySpace
* @param int $sessionId
* @param string $start_date
* @param string $end_date
* @param bool $addUserIp
*
* @author Jorge Frisancho Jibaja
* @author Julio Montoya <gugli100@gmail.com> fixing the function
@ -2749,14 +2767,15 @@ class MySpace
$course_info,
$sessionId,
$start_date,
$end_date
$end_date,
$addUserIp = false
) {
$table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
$user_id = (int) $user_id;
$connections = [];
if (!empty($course_info)) {
$courseId = (int) $course_info['real_id'];
$end_date = add_day_to($end_date);
$end_date = self::add_day_to($end_date);
$start_date = Database::escape_string($start_date);
$end_date = Database::escape_string($end_date);
@ -2764,7 +2783,8 @@ class MySpace
$sql = "SELECT
login_course_date,
logout_course_date,
TIMESTAMPDIFF(SECOND, login_course_date, logout_course_date) duration
TIMESTAMPDIFF(SECOND, login_course_date, logout_course_date) duration,
user_ip
FROM $table
WHERE
user_id = $user_id AND
@ -2776,20 +2796,23 @@ class MySpace
$rs = Database::query($sql);
while ($row = Database::fetch_array($rs)) {
$connections[] = [
$item = [
'login' => $row['login_course_date'],
'logout' => $row['logout_course_date'],
'duration' => $row['duration'],
];
if ($addUserIp) {
$item['user_ip'] = $row['user_ip'];
}
$connections[] = $item;
}
}
return $connections;
}
}
/**
* @param $user_id
* @param int $user_id
* @param array $course_info
* @param int $sessionId
* @param null $start_date
@ -2797,15 +2820,15 @@ class MySpace
*
* @return array
*/
function get_stats($user_id, $course_info, $sessionId, $start_date = null, $end_date = null)
public static function getStats($user_id, $course_info, $sessionId, $start_date = null, $end_date = null)
{
$table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
$result = [];
if (!empty($course_info)) {
$stringStartDate = '';
$stringEndDate = '';
if (null != $start_date && null != $end_date) {
$end_date = add_day_to($end_date);
if ($start_date != null && $end_date != null) {
$end_date = self::add_day_to($end_date);
$start_date = Database::escape_string($start_date);
$end_date = Database::escape_string($end_date);
@ -2843,7 +2866,7 @@ function get_stats($user_id, $course_info, $sessionId, $start_date = null, $end_
return $result;
}
function add_day_to($end_date)
public static function add_day_to($end_date)
{
$foo_date = strtotime($end_date);
$foo_date = strtotime(' +1 day', $foo_date);
@ -2852,36 +2875,6 @@ function add_day_to($end_date)
return $foo_date;
}
/**
* Converte an array to a table in html.
*
* @param array $result
*
* @author Jorge Frisancho Jibaja
*
* @version OCT-22- 2010
*
* @return string
*/
function convert_to_string($result)
{
$html = '<table class="table">';
if (!empty($result)) {
foreach ($result as $key => $data) {
$html .= '<tr><td>';
$html .= api_get_local_time($data['login']);
$html .= '</td>';
$html .= '<td>';
$html .= api_time_to_hms(api_strtotime($data['logout']) - api_strtotime($data['login']));
$html .= '</tr></td>';
}
}
$html .= '</table>';
return $html;
}
/**
* This function draw the graphic to be displayed on the user view as an image.
*
@ -2896,7 +2889,7 @@ function convert_to_string($result)
*
* @return string
*/
function grapher($sql_result, $start_date, $end_date, $type = '')
public static function grapher($sql_result, $start_date, $end_date, $type = '')
{
if (empty($start_date)) {
$start_date = '';
@ -2936,10 +2929,10 @@ function grapher($sql_result, $start_date, $end_date, $type = '')
$logout = api_strtotime($data['logout']);
//creating the main array
if (isset($main_month_year[date('m-Y', $login)])) {
$main_month_year[date('m-Y', $login)] += float_format(($logout - $login) / 60, 0);
$main_month_year[date('m-Y', $login)] += (float) ($logout - $login) / 60;
}
if (isset($main_day[date('d-m-Y', $login)])) {
$main_day[date('d-m-Y', $login)] += float_format(($logout - $login) / 60, 0);
$main_day[date('d-m-Y', $login)] += (float) ($logout - $login) / 60;
}
if ($i > 500) {
break;
@ -3096,15 +3089,13 @@ function grapher($sql_result, $start_date, $end_date, $type = '')
$myCache->saveFromCache($chartHash, $imgPath);
$imgPath = api_get_path(WEB_ARCHIVE_PATH).$chartHash;
}
$html = '<img src="'.$imgPath.'">';
return $html;
return '<img src="'.$imgPath.'">';
} else {
$foo_img = api_convert_encoding(
'<div id="messages" class="warning-message">'.get_lang('Graphic not available').'</div>',
return api_convert_encoding(
'<div id="messages" class="warning-message">'.get_lang('GraphicNotAvailable').'</div>',
'UTF-8'
);
return $foo_img;
}
}
}

@ -25,6 +25,10 @@ use Monolog\Logger;
*/
class SessionManager
{
public const STATUS_PLANNED = 1;
public const STATUS_PROGRESS = 2;
public const STATUS_FINISHED = 3;
public const STATUS_CANCELLED = 4;
// See BT#4871
public const SESSION_CHANGE_USER_REASON_SCHEDULE = 1;
public const SESSION_CHANGE_USER_REASON_CLASSROOM = 2;
@ -487,9 +491,10 @@ class SessionManager
* Get session list for a session admin or platform admin.
*
* @param int $userId User Id for the session admin.
* @param array $options Optional. Order and limit keys.
* @param bool $getCount Optional. Whether to get all the results or only the count.
* @param array $columns Optional. Columns from jqGrid.
* @param array $options Order and limit keys.
* @param bool $getCount Whether to get all the results or only the count.
* @param array $columns Columns from jqGrid.
* @param string $listType
*
* @return array
*/
@ -497,7 +502,8 @@ class SessionManager
$userId,
$options = [],
$getCount = false,
$columns = []
$columns = [],
$listType = 'all'
) {
$tblSession = Database::get_main_table(TABLE_MAIN_SESSION);
$sessionCategoryTable = Database::get_main_table(TABLE_MAIN_SESSION_CATEGORY);
@ -523,10 +529,11 @@ class SessionManager
$extraFieldModel = new ExtraFieldModel('session');
$conditions = $extraFieldModel->parseConditions($options);
$sqlInjectJoins = $conditions['inject_joins'];
$where .= $conditions['where'];
$sqlInjectWhere = $conditions['inject_where'];
$inject_extra_fields = $conditions['inject_extra_fields'];
$injectExtraFields = $conditions['inject_extra_fields'];
$order = $conditions['order'];
$limit = $conditions['limit'];
@ -553,13 +560,18 @@ class SessionManager
access_end_date,
s.visibility,
s.session_category_id,
$inject_extra_fields
$injectExtraFields
s.id
";
if ($showCountUsers) {
$select .= ', count(su.user_id) users';
}
if (api_get_configuration_value('allow_session_status')) {
$select .= ', status';
}
if (isset($options['order'])) {
$isMakingOrder = 0 === strpos($options['order'], 'category_name');
}
@ -600,6 +612,43 @@ class SessionManager
}
}
$date = api_get_utc_datetime();
switch ($listType) {
case 'all':
break;
case 'active':
$query .= "AND (
(s.access_end_date IS NULL)
OR
(
s.access_start_date IS NOT NULL AND
s.access_end_date IS NOT NULL AND
s.access_start_date <= '$date' AND s.access_end_date >= '$date')
OR
(
s.access_start_date IS NULL AND
s.access_end_date IS NOT NULL AND
s.access_end_date >= '$date'
)
)";
break;
case 'close':
$query .= "AND (
(
s.access_start_date IS NOT NULL AND
s.access_end_date IS NOT NULL AND
s.access_start_date <= '$date' AND s.access_end_date <= '$date')
OR
(
s.access_start_date IS NULL AND
s.access_end_date IS NOT NULL AND
s.access_end_date <= '$date'
)
)";
break;
}
if ($showCountUsers) {
$query .= ' GROUP by s.id';
}
@ -616,8 +665,12 @@ class SessionManager
$sessions = Database::store_result($result, 'ASSOC');
if ($getCount) {
return $sessions[0]['total_rows'];
if ('all' === $listType) {
if ($getCount) {
return $sessions[0]['total_rows'];
}
return $sessions;
}
return $sessions;
@ -630,6 +683,7 @@ class SessionManager
* @param bool $getCount Whether to get all the results or only the count
* @param array $columns
* @param array $extraFieldsToLoad
* @param string $listType
*
* @return mixed Integer for number of rows, or array of results
* @assert ([],true) !== false
@ -638,27 +692,25 @@ class SessionManager
$options = [],
$getCount = false,
$columns = [],
$extraFieldsToLoad = []
$extraFieldsToLoad = [],
$listType = 'all'
) {
$showCountUsers = false;
if (!$getCount && !empty($columns['column_model'])) {
foreach ($columns['column_model'] as $column) {
if ('users' == $column['name']) {
if ('users' === $column['name']) {
$showCountUsers = true;
}
}
}
$userId = api_get_user_id();
$sessions = self::getSessionsForAdmin($userId, $options, $getCount, $columns);
$sessions = self::getSessionsForAdmin($userId, $options, $getCount, $columns, $listType);
if ($getCount) {
return (int) $sessions;
}
$formattedSessions = [];
$categories = self::get_all_session_category();
$orderedCategories = [];
if (!empty($categories)) {
@ -743,10 +795,12 @@ class SessionManager
}
}
$categoryName = isset($orderedCategories[$session['session_category_id']])
? $orderedCategories[$session['session_category_id']]
: '';
$categoryName = isset($orderedCategories[$session['session_category_id']]) ? $orderedCategories[$session['session_category_id']] : '';
$session['category_name'] = $categoryName;
if (isset($session['status'])) {
$session['status'] = self::getStatusLabel($session['status']);
}
$formattedSessions[] = $session;
}
@ -1361,7 +1415,6 @@ class SessionManager
$date_to = '',
$options
) {
//escaping variables
$sessionId = intval($sessionId);
$courseId = intval($courseId);
$studentId = intval($studentId);
@ -4310,6 +4363,24 @@ class SessionManager
return Database::store_result($result, 'ASSOC');
}
/**
* @param int $user_id
*
* @return array
*
* @deprecated use get_sessions_by_general_coach()
*/
public static function get_sessions_by_coach($user_id)
{
$session_table = Database::get_main_table(TABLE_MAIN_SESSION);
return Database::select(
'*',
$session_table,
['where' => ['id_coach = ?' => $user_id]]
);
}
/**
* @param int $user_id
* @param int $courseId
@ -4452,21 +4523,33 @@ class SessionManager
$inOneMonth = api_get_local_time($inOneMonth);
if (api_strtotime($s['access_start_date']) < $now) {
$s['access_start_date'] = api_get_local_time($now);
} else {
$s['access_start_date'] = api_get_local_time($s['access_start_date']);
}
if (api_strtotime($s['display_start_date']) < $now) {
$s['display_start_date'] = api_get_local_time($now);
} else {
$s['display_start_date'] = api_get_local_time($s['display_start_date']);
}
if (api_strtotime($s['coach_access_start_date']) < $now) {
$s['coach_access_start_date'] = api_get_local_time($now);
} else {
$s['coach_access_start_date'] = api_get_local_time($s['coach_access_start_date']);
}
if (api_strtotime($s['access_end_date']) < $now) {
$s['access_end_date'] = $inOneMonth;
} else {
$s['access_end_date'] = api_get_local_time($s['access_end_date']);
}
if (api_strtotime($s['display_end_date']) < $now) {
$s['display_end_date'] = $inOneMonth;
} else {
$s['display_end_date'] = api_get_local_time($s['display_end_date']);
}
if (api_strtotime($s['coach_access_end_date']) < $now) {
$s['coach_access_end_date'] = $inOneMonth;
} else {
$s['coach_access_end_date'] = api_get_local_time($s['coach_access_end_date']);
}
$extraFieldValue = new ExtraFieldValue('session');
@ -5995,13 +6078,6 @@ class SessionManager
$direction = in_array(strtolower($direction), ['asc', 'desc']) ? $direction : 'asc';
$column = Database::escape_string($column);
$limitCondition = '';
if (isset($from) && isset($numberItems)) {
$from = (int) $from;
$numberItems = (int) $numberItems;
$limitCondition = "LIMIT $from, $numberItems";
}
$urlId = api_get_current_access_url_id();
$sessionConditions = '';
@ -6042,34 +6118,34 @@ class SessionManager
}
switch ($status) {
case 'admin':
case 'drh':
break;
case 'drh_all':
// Show all by DRH
if (empty($sessionIdList)) {
$sessionsListSql = self::get_sessions_followed_by_drh(
$sessionListFollowed = self::get_sessions_followed_by_drh(
$userId,
null,
null,
false,
true,
true
);
} else {
if (!empty($sessionListFollowed)) {
$sessionIdList = array_column($sessionListFollowed, 'id');
}
}
if (!empty($sessionIdList)) {
$sessionIdList = array_map('intval', $sessionIdList);
$sessionsListSql = "'".implode("','", $sessionIdList)."'";
}
if (!empty($sessionsListSql)) {
$sessionConditions = " AND s.id IN ($sessionsListSql) ";
}
break;
case 'session_admin':
$sessionConditions = " AND s.id_coach = $userId ";
$userConditionsFromDrh = '';
break;
case 'admin':
break;
case 'teacher':
case 'session_admin':
$sessionConditions = " AND s.id_coach = $userId ";
$userConditionsFromDrh = '';
break;
@ -6123,18 +6199,18 @@ class SessionManager
$sql = "$masterSelect (
($select
FROM $tbl_session s
INNER JOIN $tbl_session_rel_access_url url ON (url.session_id = s.id)
INNER JOIN $tbl_session_rel_course_rel_user su ON (s.id = su.session_id)
INNER JOIN $tbl_user u ON (u.user_id = su.user_id)
INNER JOIN $tbl_session_rel_access_url url ON (url.session_id = s.id)
$where
$sessionConditions
$userConditionsFromDrh
) UNION (
$select
FROM $tbl_course c
INNER JOIN $tbl_course_rel_access_url url ON (url.c_id = c.id)
INNER JOIN $tbl_course_user cu ON (cu.c_id = c.id)
INNER JOIN $tbl_user u ON (u.user_id = cu.user_id)
INNER JOIN $tbl_course_rel_access_url url ON (url.c_id = c.id)
$where
$courseConditions
$userConditionsFromDrh
@ -6158,11 +6234,18 @@ class SessionManager
$column = str_replace('u.', '', $column);
$sql .= " ORDER BY $column $direction ";
}
$limitCondition = '';
if (isset($from) && isset($numberItems)) {
$from = (int) $from;
$numberItems = (int) $numberItems;
$limitCondition = "LIMIT $from, $numberItems";
}
$sql .= $limitCondition;
$result = Database::query($sql);
$result = Database::store_result($result);
return $result;
return Database::store_result($result);
}
/**
@ -7523,7 +7606,7 @@ class SessionManager
/**
* @param int $sessionId
* @param array $extraFieldsToInclude
* @param array $extraFieldsToInclude (empty means all)
*
* @return array
*/
@ -7539,7 +7622,7 @@ class SessionManager
}
$sessionExtraField = new ExtraFieldModel('session');
$fieldList = $sessionExtraField->get_all([
$fieldList = $sessionExtraField->get_all(empty($extraFieldsToInclude) ? [] : [
"variable IN ( ".implode(", ", $variablePlaceHolders)." ) " => $variables,
]);
@ -7556,23 +7639,15 @@ class SessionManager
// Get session field values
$extra = new ExtraFieldValue('session');
$sessionFieldValueList = $extra->get_all(
[
"field_id IN ( ".implode(", ", $variablePlaceHolders)." )" => array_keys($fields),
]
);
foreach ($sessionFieldValueList as $sessionFieldValue) {
// Match session field values to session
if ($sessionFieldValue['item_id'] != $sessionId) {
continue;
}
// Check if session field value is set in session field list
if (!isset($fields[$sessionFieldValue['field_id']])) {
continue;
$sessionFieldValueList = [];
foreach (array_keys($fields) as $fieldId) {
$sessionFieldValue = $extra->get_values_by_handler_and_field_id($sessionId, $fieldId);
if ($sessionFieldValue != false) {
$sessionFieldValueList[$fieldId] = $sessionFieldValue;
}
}
foreach ($sessionFieldValueList as $sessionFieldValue) {
$extrafieldVariable = $fields[$sessionFieldValue['field_id']];
$extrafieldValue = $sessionFieldValue['value'];
@ -7592,7 +7667,7 @@ class SessionManager
*/
public static function isValidId($sessionId)
{
$sessionId = intval($sessionId);
$sessionId = (int) $sessionId;
if ($sessionId > 0) {
$rows = Database::select(
'id',
@ -7838,18 +7913,11 @@ class SessionManager
$form->addElement('html', '<div id="advanced_params_options" style="display:none">');
if (empty($sessionId)) {
$sessions = self::formatSessionsAdminForGrid();
$sessionList = [];
$sessionList[] = '';
foreach ($sessions as $session) {
$sessionList[$session['id']] = strip_tags($session['name']);
}
$form->addSelect(
$form->addSelectAjax(
'session_template',
get_lang('Session template'),
$sessionList,
['id' => 'system_template']
get_lang('SessionTemplate'),
[],
['url' => api_get_path(WEB_AJAX_PATH).'session.ajax.php?a=search_template_session', 'id' => 'system_template']
);
}
@ -8139,7 +8207,7 @@ class SessionManager
* @return array
*/
public static function getGridColumns(
$listType = 'simple',
$listType = 'all',
$extraFields = [],
$addExtraFields = true
) {
@ -8184,7 +8252,9 @@ class SessionManager
],
];
break;
case 'simple':
case 'all':
case 'active':
case 'close':
$columns = [
'#',
get_lang('Name'),
@ -8303,20 +8373,72 @@ class SessionManager
get_lang('Course title'),
];
$columnModel = [
['name' => 'name', 'index' => 's.name', 'width' => '200', 'align' => 'left', 'search' => 'true', 'searchoptions' => ['sopt' => $operators]],
['name' => 'display_start_date', 'index' => 'display_start_date', 'width' => '70', 'align' => 'left', 'search' => 'true', 'searchoptions' => ['dataInit' => 'date_pick_today', 'sopt' => $date_operators]],
['name' => 'display_end_date', 'index' => 'display_end_date', 'width' => '70', 'align' => 'left', 'search' => 'true', 'searchoptions' => ['dataInit' => 'date_pick_one_month', 'sopt' => $date_operators]],
['name' => 'coach_name', 'index' => 'coach_name', 'width' => '70', 'align' => 'left', 'search' => 'false', 'searchoptions' => ['sopt' => $operators]],
['name' => 'session_active', 'index' => 'session_active', 'width' => '25', 'align' => 'left', 'search' => 'true', 'stype' => 'select',
[
'name' => 'name',
'index' => 's.name',
'width' => '200',
'align' => 'left',
'search' => 'true',
'searchoptions' => ['sopt' => $operators],
],
[
'name' => 'display_start_date',
'index' => 'display_start_date',
'width' => '70',
'align' => 'left',
'search' => 'true',
'searchoptions' => ['dataInit' => 'date_pick_today', 'sopt' => $date_operators],
],
[
'name' => 'display_end_date',
'index' => 'display_end_date',
'width' => '70',
'align' => 'left',
'search' => 'true',
'searchoptions' => ['dataInit' => 'date_pick_one_month', 'sopt' => $date_operators],
],
[
'name' => 'coach_name',
'index' => 'coach_name',
'width' => '70',
'align' => 'left',
'search' => 'false',
'searchoptions' => ['sopt' => $operators],
],
[
'name' => 'session_active',
'index' => 'session_active',
'width' => '25',
'align' => 'left',
'search' => 'true',
'stype' => 'select',
// for the bottom bar
'searchoptions' => [
'defaultValue' => '1',
'value' => '1:'.get_lang('active').';0:'.get_lang('inactive'), ],
'value' => '1:'.get_lang('Active').';0:'.get_lang('Inactive'),
],
// for the top bar
'editoptions' => ['value' => '" ":'.get_lang('All').';1:'.get_lang('active').';0:'.get_lang('inactive')],
'editoptions' => [
'value' => '" ":'.get_lang('All').';1:'.get_lang('Active').';0:'.get_lang(
'Inactive'
),
],
],
[
'name' => 'visibility',
'index' => 'visibility',
'width' => '40',
'align' => 'left',
'search' => 'false',
],
[
'name' => 'course_title',
'index' => 'course_title',
'width' => '50',
'hidden' => 'true',
'search' => 'true',
'searchoptions' => ['searchhidden' => 'true', 'sopt' => $operators],
],
['name' => 'visibility', 'index' => 'visibility', 'width' => '40', 'align' => 'left', 'search' => 'false'],
['name' => 'course_title', 'index' => 'course_title', 'width' => '50', 'hidden' => 'true', 'search' => 'true', 'searchoptions' => ['searchhidden' => 'true', 'sopt' => $operators]],
];
break;
@ -8511,7 +8633,7 @@ class SessionManager
}
if (isset($params['access_start_date'])) {
$params[''] = api_format_date($params['access_start_date'], DATE_TIME_FORMAT_SHORT);
$params['access_start_date'] = api_format_date($params['access_start_date'], DATE_TIME_FORMAT_SHORT);
}
if (isset($params['access_end_date'])) {
@ -8572,7 +8694,7 @@ class SessionManager
}
$today = api_get_utc_datetime();
$inject_extra_fields = null;
$injectExtraFields = null;
$extra_fields_info = [];
//for now only sessions
@ -8584,7 +8706,7 @@ class SessionManager
$extra_fields = $options['extra'];
if (!empty($extra_fields)) {
foreach ($extra_fields as $extra) {
$inject_extra_fields .= " IF (fv.field_id = {$extra['id']}, fvo.option_display_text, NULL ) as {$extra['field']} , ";
$injectExtraFields .= " IF (fv.field_id = {$extra['id']}, fvo.option_display_text, NULL ) as {$extra['field']} , ";
if (isset($extra_fields_info[$extra['id']])) {
$info = $extra_fields_info[$extra['id']];
} else {
@ -8629,7 +8751,7 @@ class SessionManager
access_end_date,
s.visibility,
u.user_id,
$inject_extra_fields
$injectExtraFields
c.title as course_title,
s.id ";
@ -9161,10 +9283,10 @@ class SessionManager
/**
* @return int
*/
public static function getCountUsersInCourseSession(
Course $course,
Session $session
) {
public static function getCountUsersInCourseSession(Course $course, Session $session)
{
$urlId = api_get_current_access_url_id();
return Database::getManager()
->createQuery("
SELECT COUNT(scu)
@ -9172,15 +9294,19 @@ class SessionManager
INNER JOIN ChamiloCoreBundle:SessionRelUser su
WITH scu.user = su.user
AND scu.session = su.session
INNER JOIN ChamiloCoreBundle:AccessUrlRelUser a
WITH a.user = su.user
WHERE
scu.course = :course AND
su.relationType <> :relationType AND
scu.session = :session
scu.session = :session AND
a.portal = :url
")
->setParameters([
'course' => $course->getId(),
'relationType' => SESSION_RELATION_TYPE_RRHH,
'session' => $session->getId(),
'url' => $urlId,
])
->getSingleScalarResult();
}
@ -9347,6 +9473,64 @@ class SessionManager
return $list[$status];
}
public static function getDefaultSessionTab()
{
$default = 'all';
$view = api_get_configuration_value('default_session_list_view');
if (!empty($view)) {
$default = $view;
}
return $default;
}
/**
* @return array
*/
public static function getSessionListTabs($listType)
{
$tabs = [
[
'content' => get_lang('AllSessionsShort'),
'url' => api_get_path(WEB_CODE_PATH).'session/session_list.php?list_type=all',
],
[
'content' => get_lang('ActiveSessionsShort'),
'url' => api_get_path(WEB_CODE_PATH).'session/session_list.php?list_type=active',
],
[
'content' => get_lang('ClosedSessionsShort'),
'url' => api_get_path(WEB_CODE_PATH).'session/session_list.php?list_type=close',
],
[
'content' => get_lang('SessionListCustom'),
'url' => api_get_path(WEB_CODE_PATH).'session/session_list.php?list_type=custom',
],
/*[
'content' => get_lang('Complete'),
'url' => api_get_path(WEB_CODE_PATH).'session/session_list_simple.php?list_type=complete',
],*/
];
switch ($listType) {
case 'all':
$default = 1;
break;
case 'active':
$default = 2;
break;
case 'close':
$default = 3;
break;
case 'custom':
$default = 4;
break;
}
return Display::tabsOnlyLink($tabs, $default);
}
/**
* @param int $id
*

@ -1,4 +1,5 @@
<?php
/* For licensing terms, see /license.txt */
use ChamiloSession as Session;
@ -93,7 +94,7 @@ class SortableTable extends HTML_Table
public $use_jqgrid = false;
public $table_id = null;
public $headers = [];
public $actionButtons = [];
/**
* The array containing all data for this table.
*/
@ -123,7 +124,7 @@ class SortableTable extends HTML_Table
* @param string $default_order_direction The default order direction;
* either the constant 'ASC' or 'DESC'
* @param string $table_id
* @param array $parameters They are custom attributes of the table
* @param array $attributes They are custom attributes of the table
*/
public function __construct(
$table_name = 'table',
@ -133,17 +134,20 @@ class SortableTable extends HTML_Table
$default_items_per_page = 20,
$default_order_direction = 'ASC',
$table_id = null,
$parameters = []
$attributes = []
) {
if (empty($table_id)) {
$table_id = $table_name.uniqid('table', true);
}
if (isset($parameters) && empty($parameters)) {
$parameters = ['class' => 'table table-bordered data_table', 'id' => $table_id];
if (empty($attributes)) {
$attributes = [];
$attributes['class'] = 'table table-bordered data_table';
$attributes['id'] = $table_id;
}
$this->table_id = $table_id;
parent::__construct($parameters);
parent::__construct($attributes);
$this->table_name = $table_name;
$this->additional_parameters = [];
$this->param_prefix = $table_name.'_';
@ -160,7 +164,6 @@ class SortableTable extends HTML_Table
if (true === $cleanSessionData) {
$this->cleanUrlSessionParams();
}
// Allow to change paginate in multiples tabs
//Session::erase($this->param_prefix.'per_page');
$this->per_page = Session::read($this->param_prefix.'per_page', $default_items_per_page);
@ -341,6 +344,13 @@ class SortableTable extends HTML_Table
echo $this->return_table();
}
public function toArray()
{
$headers = array_column($this->getHeaders(), 'label');
return array_merge([$headers], $this->table_data);
}
/**
* Displays the table, complete with navigation buttons to browse through
* the data-pages.
@ -482,7 +492,6 @@ class SortableTable extends HTML_Table
.grid_element_0 { width:100px; height: 100px; float:left; text-align:center; margin-bottom:5px;}
.grid_element_1 { width:100px; float:left; text-align:center;margin-bottom:5px;}
.grid_element_2 { width:150px; float:left;}
.grid_selectbox { width:30%; float:left;}
.grid_title { width:30%; float:left;}
.grid_nav { }
@ -667,9 +676,8 @@ class SortableTable extends HTML_Table
$pager = $this->get_pager();
$offset = $pager->getOffsetByPageId();
$from = $offset[0] - 1;
$table_data = $this->get_table_data($from);
$table_data = $this->get_table_data($from, $this->per_page, $this->column);
$this->processHeaders();
if (is_array($table_data)) {
$count = 1;
foreach ($table_data as &$row) {
@ -755,6 +763,7 @@ class SortableTable extends HTML_Table
if (true === $this->hideItemSelector) {
return '';
}
$result[] = '<form method="GET" action="'.api_get_self().'" style="display:inline;">';
$param[$this->param_prefix.'direction'] = $this->direction;
$param[$this->param_prefix.'page_nr'] = $this->page_nr;

@ -777,6 +777,8 @@ function cut($text, $maxchar, $embed = false)
*/
function float_format($number, $flag = 1, $decimalPoint = '.', $thousandsSeparator = ',')
{
$flag = (int) $flag;
if (is_numeric($number)) {
if (!$number) {
$result = (2 == $flag ? '0.'.str_repeat('0', EXERCISE_NUMBER_OF_DECIMALS) : '0');

@ -1,4 +1,5 @@
<?php
/* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Entity\Course;
@ -158,7 +159,6 @@ class Tracking
$hideTime = api_get_configuration_value('hide_lp_time');
$allowNewTracking = api_get_configuration_value('use_new_tracking_in_lp_item');
$lp_id = (int) $lp_id;
if ($allowNewTracking) {
@ -327,9 +327,9 @@ class Tracking
$chapterTypes = learnpath::getChapterTypes();
$accessToPdfExport = api_is_allowed_to_edit(false, false, true);
$minimunAvailable = self::minimumTimeAvailable($session_id, $course_id);
$minimumAvailable = self::minimumTimeAvailable($session_id, $course_id);
$timeCourse = [];
if ($minimunAvailable) {
if ($minimumAvailable) {
$timeCourse = self::getCalculateTime($user_id, $course_id, $session_id);
Session::write('trackTimeCourse', $timeCourse);
}
@ -534,7 +534,7 @@ class Tracking
$time_for_total = $row['mytime'];
$attemptTime = $row['mytime'];
if ($minimunAvailable) {
if ($minimumAvailable) {
$lp_time = $timeCourse[TOOL_LEARNPATH];
$lpTime = null;
if (isset($lp_time[$lp_id])) {
@ -1041,12 +1041,10 @@ class Tracking
if ($extend_this_attempt || $extend_all) {
$list1 = learnpath::get_iv_interactions_array($row['iv_id'], $course_id);
foreach ($list1 as $id => $interaction) {
if (0 == ($counter % 2)) {
$oddclass = 'row_even';
if (($counter % 2) == 0) {
$oddclass = 'row_odd';
} else {
$oddclass = 'row_even';
}
$timeRow = '<td class="lp_time">'.$interaction['time'].'</td>';
if ($hideTime) {
$timeRow = '';
@ -1067,13 +1065,12 @@ class Tracking
</tr>';
$counter++;
}
$list2 = learnpath::get_iv_objectives_array($row['iv_id'], $course_id);
$list2 = learnpath::get_iv_objectives_array($row['iv_id'], $course_id);
foreach ($list2 as $id => $interaction) {
if (0 == ($counter % 2)) {
$oddclass = 'row_even';
if (($counter % 2) == 0) {
$oddclass = 'row_odd';
} else {
$oddclass = 'row_even';
}
$output .= '<tr class="'.$oddclass.'">
<td></td>
@ -1651,6 +1648,7 @@ class Tracking
* @param string $timeFilter type of time filter: 'last_week' or 'custom'
* @param string $start_date start date date('Y-m-d H:i:s')
* @param string $end_date end date date('Y-m-d H:i:s')
* @param bool $returnAllRecords
*
* @return int
*/
@ -1658,7 +1656,8 @@ class Tracking
$userId,
$timeFilter = 'last_7_days',
$start_date = null,
$end_date = null
$end_date = null,
$returnAllRecords = false
) {
$tbl_track_login = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
$condition_time = '';
@ -1667,7 +1666,17 @@ class Tracking
$userList = array_map('intval', $userId);
$userCondition = " login_user_id IN ('".implode("','", $userList)."')";
} else {
$userCondition = " login_user_id = ".intval($userId);
$userId = (int) $userId;
$userCondition = " login_user_id = $userId ";
}
$url_condition = null;
$tbl_url_rel_user = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
$url_table = null;
if (api_is_multiple_url_enabled()) {
$access_url_id = api_get_current_access_url_id();
$url_table = ", $tbl_url_rel_user as url_users";
$url_condition = " AND u.login_user_id = url_users.user_id AND access_url_id='$access_url_id'";
}
if (empty($timeFilter)) {
@ -1687,6 +1696,17 @@ class Tracking
$condition_time = " AND (login_date >= '{$newDate->format('Y-m-d H:i:s')}'";
$condition_time .= "AND logout_date <= '{$today->format('Y-m-d H:i:s')}') ";
break;
case 'wide':
if (!empty($start_date) && !empty($end_date)) {
$start_date = Database::escape_string($start_date);
$end_date = Database::escape_string($end_date);
$condition_time = ' AND (
(login_date >= "'.$start_date.'" AND login_date <= "'.$end_date.'") OR
(logout_date >= "'.$start_date.'" AND logout_date <= "'.$end_date.'") OR
(login_date <= "'.$start_date.'" AND logout_date >= "'.$end_date.'")
) ';
}
break;
case 'custom':
if (!empty($start_date) && !empty($end_date)) {
$start_date = Database::escape_string($start_date);
@ -1696,9 +1716,19 @@ class Tracking
break;
}
$sql = 'SELECT SUM(TIMESTAMPDIFF(SECOND, login_date, logout_date)) diff
FROM '.$tbl_track_login.'
WHERE '.$userCondition.$condition_time;
if ($returnAllRecords) {
$sql = "SELECT login_date, logout_date, TIMESTAMPDIFF(SECOND, login_date, logout_date) diff
FROM $tbl_track_login u $url_table
WHERE $userCondition $condition_time $url_condition
ORDER BY login_date";
$rs = Database::query($sql);
return Database::store_result($rs, 'ASSOC');
}
$sql = "SELECT SUM(TIMESTAMPDIFF(SECOND, login_date, logout_date)) diff
FROM $tbl_track_login u $url_table
WHERE $userCondition $condition_time $url_condition";
$rs = Database::query($sql);
$row = Database::fetch_array($rs, 'ASSOC');
$diff = $row['diff'];
@ -1736,7 +1766,6 @@ class Tracking
$endDate = Database::escape_string($endDate);
$condition_time = ' (login_date >= "'.$startDate.'" AND logout_date <= "'.$endDate.'" ) ';
}
$sql = "SELECT SUM(TIMESTAMPDIFF(SECOND, login_date, logout_date)) diff
FROM $tbl_track_login u $url_table
WHERE $condition_time $url_condition";
@ -1790,7 +1819,7 @@ class Tracking
*
* @param int $user_id
* @param int $courseId
* @param int Session id (optional)
* @param int $session_id
*
* @return int Time in seconds
*/
@ -1807,18 +1836,20 @@ class Tracking
if (self::minimumTimeAvailable($session_id, $courseId)) {
$courseTime = self::getCalculateTime($user_id, $courseId, $session_id);
$time = isset($courseTime['total_time']) ? $courseTime['total_time'] : 0;
return $time;
return isset($courseTime['total_time']) ? $courseTime['total_time'] : 0;
}
$conditionUser = '';
$session_id = (int) $session_id;
if (is_array($user_id)) {
$user_id = array_map('intval', $user_id);
$conditionUser = " AND user_id IN (".implode(',', $user_id).") ";
} else {
$user_id = (int) $user_id;
$conditionUser = " AND user_id = $user_id ";
if (!empty($user_id)) {
$user_id = (int) $user_id;
$conditionUser = " AND user_id = $user_id ";
}
}
$table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
@ -1834,6 +1865,7 @@ class Tracking
}
$sql .= $conditionUser;
$rs = Database::query($sql);
$row = Database::fetch_array($rs);
@ -3074,7 +3106,7 @@ class Tracking
if (!empty($course_code)) {
$course = api_get_course_info($course_code);
$courseId = $course['real_id'];
$conditions[] = " c_id = $courseId";
$conditions[] = " lp.c_id = $courseId";
}
// Get course tables names
@ -3085,13 +3117,13 @@ class Tracking
// Compose a filter based on optional learning paths list given
if (!empty($lp_ids) && count($lp_ids) > 0) {
$conditions[] = ' id IN ('.implode(',', $lp_ids).') ';
$conditions[] = ' lp.id IN ('.implode(',', $lp_ids).') ';
}
// Compose a filter based on optional session id
$session_id = (int) $session_id;
if (!empty($session_id)) {
$conditions[] = " session_id = $session_id ";
$conditions[] = " lp_view.session_id = $session_id ";
}
if (is_array($student_id)) {
@ -3135,7 +3167,7 @@ class Tracking
* @param int $session_id Session id (optional), if param $session_id is null(default)
* it'll return results including sessions, 0 = session is not filtered
*
* @return int Total time
* @return int Total time in seconds
*/
public static function get_time_spent_in_lp(
$student_id,
@ -3338,6 +3370,54 @@ class Tracking
return $lastTime;
}
public static function getFirstConnectionTimeInLp(
$student_id,
$course_code,
$lp_id,
$session_id = 0
) {
$course = api_get_course_info($course_code);
$student_id = (int) $student_id;
$lp_id = (int) $lp_id;
$session_id = (int) $session_id;
$time = 0;
if (!empty($course)) {
$course_id = $course['real_id'];
$lp_table = Database::get_course_table(TABLE_LP_MAIN);
$t_lpv = Database::get_course_table(TABLE_LP_VIEW);
$t_lpiv = Database::get_course_table(TABLE_LP_ITEM_VIEW);
// Check the real number of LPs corresponding to the filter in the
// database (and if no list was given, get them all)
$sql = "SELECT id FROM $lp_table
WHERE c_id = $course_id AND id = $lp_id ";
$row = Database::query($sql);
$count = Database::num_rows($row);
// calculates first connection time
if ($count > 0) {
$sql = 'SELECT MIN(start_time)
FROM '.$t_lpiv.' AS item_view
INNER JOIN '.$t_lpv.' AS view
ON (item_view.lp_view_id = view.id AND item_view.c_id = view.c_id)
WHERE
status != "not attempted" AND
item_view.c_id = '.$course_id.' AND
view.c_id = '.$course_id.' AND
view.lp_id = '.$lp_id.' AND
view.user_id = '.$student_id.' AND
view.session_id = '.$session_id;
$rs = Database::query($sql);
if (Database::num_rows($rs) > 0) {
$time = Database::result($rs, 0, 0);
}
}
}
return $time;
}
/**
* gets the list of students followed by coach.
*
@ -5824,7 +5904,6 @@ class Tracking
$count = 0;
foreach ($exercise_result as $result) {
$percentage = $result * 100;
//echo $percentage.' - '.$min.' - '.$max."<br />";
if ($percentage >= $min && $percentage <= $max) {
//echo ' is > ';
$count++;
@ -6550,11 +6629,17 @@ class Tracking
foreach ($results as $item) {
if (empty($beforeItem)) {
$beforeItem = $item;
if (empty($min)) {
$min = $item['date_reg'];
}
if (empty($max)) {
$max = $item['date_reg'];
}
continue;
}
$partialTime = $item['date_reg'] - $beforeItem['date_reg'];
if ($item['date_reg'] > $max) {
$max = $item['date_reg'];
}
@ -6787,14 +6872,104 @@ class Tracking
*/
public static function isAllowToTrack($sessionId)
{
$allow =
return
api_is_platform_admin(true, true) ||
SessionManager::user_is_general_coach(api_get_user_id(), $sessionId) ||
api_is_allowed_to_create_course() ||
api_is_course_tutor() ||
api_is_course_admin();
}
public static function getCourseLpProgress($userId, $sessionId)
{
$controller = new IndexManager(get_lang('MyCourses'));
$data = $controller->returnCoursesAndSessions($userId);
$courseList = $data['courses'];
$result = [];
if ($courseList) {
//$counter = 1;
foreach ($courseList as $course) {
$courseId = $course['course_id'];
$courseInfo = api_get_course_info_by_id($courseId);
if (empty($courseInfo)) {
continue;
}
$courseCode = $courseInfo['code'];
$lpTimeList = self::getCalculateTime($userId, $courseId, $sessionId);
// total progress
$list = new LearnpathList(
$userId,
$courseInfo,
0,
'lp.publicatedOn ASC',
true,
null,
true
);
$list = $list->get_flat_list();
$totalProgress = 0;
$totalTime = 0;
if (!empty($list)) {
foreach ($list as $lp_id => $learnpath) {
if (!$learnpath['lp_visibility']) {
continue;
}
$lpProgress = self::get_avg_student_progress($userId, $courseCode, [$lp_id], $sessionId);
$time = isset($lpTimeList[TOOL_LEARNPATH][$lp_id]) ? $lpTimeList[TOOL_LEARNPATH][$lp_id] : 0;
if ($lpProgress == 100) {
if (!empty($time)) {
$timeInMinutes = $time / 60;
$min = (int) learnpath::getAccumulateWorkTimePrerequisite($lp_id, $courseId);
if ($timeInMinutes >= $min) {
$totalProgress++;
}
}
}
$totalTime += $time;
}
if (!empty($totalProgress)) {
$totalProgress = (float) api_number_format($totalProgress / count($list) * 100, 2);
}
}
$progress = self::get_avg_student_progress($userId, $courseCode, [], $sessionId);
$result[] = [
'module' => $courseInfo['name'],
'progress' => $progress,
'qualification' => $totalProgress,
'activeTime' => $totalTime,
];
}
}
return $result;
}
/**
* @param int $userId
* @param int $courseId
* @param int $sessionId
*
* @return int
*/
public static function getNumberOfCourseAccessDates($userId, $courseId, $sessionId)
{
$tblTrackCourseAccess = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
$sessionCondition = api_get_session_condition($sessionId);
$courseId = (int) $courseId;
$userId = (int) $userId;
$sql = "SELECT COUNT(DISTINCT (DATE(login_course_date))) AS c
FROM $tblTrackCourseAccess
WHERE c_id = $courseId $sessionCondition AND user_id = $userId";
$result = Database::fetch_assoc(Database::query($sql));
return $allow;
return (int) $result['c'];
}
}
@ -7359,21 +7534,21 @@ class TrackingCourseLog
*
* @return int
*/
public static function get_number_of_users()
public static function get_number_of_users($conditions)
{
global $user_ids;
$conditions['get_count'] = true;
return count($user_ids);
return self::get_user_data(null, null, null, null, $conditions);
}
/**
* Get data for users list in sortable with pagination.
*
* @param $from
* @param $number_of_items
* @param int $from
* @param int $number_of_items
* @param $column
* @param $direction
* @param $includeInvitedUsers boolean Whether include the invited users
* @param $conditions
*
* @return array
*/
@ -7382,9 +7557,11 @@ class TrackingCourseLog
$number_of_items,
$column,
$direction,
$includeInvitedUsers = false
$conditions = []
) {
global $user_ids, $course_code, $export_csv, $session_id;
$includeInvitedUsers = $conditions['include_invited_users']; // include the invited users
$getCount = isset($conditions['get_count']) ? $conditions['get_count'] : false;
$csv_content = [];
$course_code = Database::escape_string($course_code);
@ -7395,10 +7572,10 @@ class TrackingCourseLog
// get all users data from a course for sortable with limit
if (is_array($user_ids)) {
$user_ids = array_map('intval', $user_ids);
$condition_user = " WHERE user.user_id IN (".implode(',', $user_ids).") ";
$condition_user = " WHERE user.id IN (".implode(',', $user_ids).") ";
} else {
$user_ids = (int) $user_ids;
$condition_user = " WHERE user.user_id = $user_ids ";
$condition_user = " WHERE user.id = $user_ids ";
}
if (!empty($_GET['user_keyword'])) {
@ -7411,11 +7588,11 @@ class TrackingCourseLog
) ";
}
$url_table = null;
$url_condition = null;
$url_table = '';
$url_condition = '';
if (api_is_multiple_url_enabled()) {
$url_table = ", $tbl_url_rel_user as url_users";
$url_condition = " AND user.user_id = url_users.user_id AND access_url_id = '$access_url_id'";
$url_table = " INNER JOIN $tbl_url_rel_user as url_users ON (user.id = url_users.user_id)";
$url_condition = " AND access_url_id = '$access_url_id'";
}
$invitedUsersCondition = '';
@ -7423,13 +7600,46 @@ class TrackingCourseLog
$invitedUsersCondition = " AND user.status != ".INVITEE;
}
$sql = "SELECT user.user_id as user_id,
$select = '
SELECT user.id as user_id,
user.official_code as col0,
user.lastname as col1,
user.firstname as col2,
user.username as col3
FROM $tbl_user as user $url_table
$condition_user $url_condition $invitedUsersCondition";
user.username as col3';
if ($getCount) {
$select = ' SELECT COUNT(distinct(user.id)) as count ';
}
$sqlInjectJoins = '';
$where = 'AND 1 = 1 ';
$sqlInjectWhere = '';
if (!empty($conditions)) {
if (isset($conditions['inject_joins'])) {
$sqlInjectJoins = $conditions['inject_joins'];
}
if (isset($conditions['where'])) {
$where = $conditions['where'];
}
if (isset($conditions['inject_where'])) {
$sqlInjectWhere = $conditions['inject_where'];
}
$injectExtraFields = !empty($conditions['inject_extra_fields']) ? $conditions['inject_extra_fields'] : 1;
$injectExtraFields = rtrim($injectExtraFields, ', ');
if (false === $getCount) {
$select .= " , $injectExtraFields";
}
}
$sql = "$select
FROM $tbl_user as user
$url_table
$sqlInjectJoins
$condition_user
$url_condition
$invitedUsersCondition
$where
$sqlInjectWhere
";
if (!in_array($direction, ['ASC', 'DESC'])) {
$direction = 'ASC';
@ -7439,16 +7649,26 @@ class TrackingCourseLog
$from = (int) $from;
$number_of_items = (int) $number_of_items;
if ($getCount) {
$res = Database::query($sql);
$row = Database::fetch_array($res);
return $row['count'];
}
$sql .= " ORDER BY col$column $direction ";
$sql .= " LIMIT $from, $number_of_items";
$res = Database::query($sql);
$users = [];
$course_info = api_get_course_info($course_code);
$courseInfo = api_get_course_info($course_code);
$courseId = $courseInfo['real_id'];
$courseCode = $courseInfo['code'];
$total_surveys = 0;
$total_exercises = ExerciseLib::get_all_exercises(
$course_info,
$courseInfo,
$session_id,
false,
null,
@ -7458,33 +7678,33 @@ class TrackingCourseLog
if (empty($session_id)) {
$survey_user_list = [];
$survey_list = SurveyManager::get_surveys($course_code, $session_id);
$total_surveys = count($survey_list);
foreach ($survey_list as $survey) {
$surveyList = SurveyManager::get_surveys($course_code, $session_id);
if ($surveyList) {
$total_surveys = count($surveyList);
foreach ($surveyList as $survey) {
$user_list = SurveyManager::get_people_who_filled_survey(
$survey['survey_id'],
false,
$course_info['real_id']
$courseId
);
foreach ($user_list as $user_id) {
isset($survey_user_list[$user_id]) ? $survey_user_list[$user_id]++ : $survey_user_list[$user_id] = 1;
}
}
}
}
$courseInfo = api_get_course_info($course_code);
$courseId = $courseInfo['real_id'];
$urlBase = api_get_path(WEB_CODE_PATH).'mySpace/myStudents.php?details=true&cidReq='.$course_code.
$urlBase = api_get_path(WEB_CODE_PATH).'mySpace/myStudents.php?details=true&cidReq='.$courseCode.
'&course='.$course_code.'&origin=tracking_course&id_session='.$session_id;
$sortByFirstName = api_sort_by_first_name();
Session::write('user_id_list', []);
$userIdList = [];
while ($user = Database::fetch_array($res, 'ASSOC')) {
$userIdList[] = $user['user_id'];
$user['official_code'] = $user['col0'];
$user['username'] = $user['col3'];
$user['time'] = api_time_to_hms(
Tracking::get_time_spent_on_the_course(
$user['user_id'],
@ -7561,8 +7781,16 @@ class TrackingCourseLog
);
if ($export_csv) {
$user['first_connection'] = api_get_local_time($user['first_connection']);
$user['last_connection'] = api_get_local_time($user['last_connection']);
if (!empty($user['first_connection'])) {
$user['first_connection'] = api_get_local_time($user['first_connection']);
} else {
$user['first_connection'] = '-';
}
if (!empty($user['last_connection'])) {
$user['last_connection'] = api_get_local_time($user['last_connection']);
} else {
$user['last_connection'] = '-';
}
}
if (empty($session_id)) {
@ -7599,6 +7827,12 @@ class TrackingCourseLog
if (empty($session_id)) {
$user_row['survey'] = $user['survey'];
} else {
$userSession = SessionManager::getUserSession($user['user_id'], $session_id);
$user_row['registered_at'] = '';
if ($userSession) {
$user_row['registered_at'] = api_get_local_time($userSession['registered_at']);
}
}
$user_row['first_connection'] = $user['first_connection'];
@ -7607,6 +7841,7 @@ class TrackingCourseLog
// we need to display an additional profile field
if (isset($_GET['additional_profile_field'])) {
$data = Session::read('additional_user_profile_info');
$extraFieldInfo = Session::read('extra_field_info');
foreach ($_GET['additional_profile_field'] as $fieldId) {
if (isset($data[$fieldId]) && isset($data[$fieldId][$user['user_id']])) {
@ -7646,6 +7881,7 @@ class TrackingCourseLog
Session::erase('additional_user_profile_info');
Session::erase('extra_field_info');
Session::write('user_id_list', $userIdList);
return $users;
}
@ -7708,9 +7944,9 @@ class TrackingCourseLog
$direction = 'ASC';
}
$column = intval($column);
$from = intval($from);
$number_of_items = intval($number_of_items);
$column = (int) $column;
$from = (int) $from;
$number_of_items = (int) $number_of_items;
$sql .= " ORDER BY col$column $direction ";
$sql .= " LIMIT $from,$number_of_items";
@ -7718,12 +7954,11 @@ class TrackingCourseLog
$res = Database::query($sql);
$users = [];
$course_info = api_get_course_info($course_code);
$sortByFirstName = api_sort_by_first_name();
while ($user = Database::fetch_array($res, 'ASSOC')) {
$courseInfo = api_get_course_info($course_code);
$courseId = $courseInfo['real_id'];
$courseInfo = api_get_course_info($course_code);
$courseId = $courseInfo['real_id'];
while ($user = Database::fetch_array($res, 'ASSOC')) {
$user['official_code'] = $user['col0'];
$user['lastname'] = $user['col1'];
$user['firstname'] = $user['col2'];
@ -7827,6 +8062,11 @@ class TrackingCourseLog
api_get_path(WEB_CODE_PATH).'tracking/course_log_events.php?'.api_get_cidreq()
);
$lpLink = Display::url(
Display::return_icon('scorms.png', get_lang('CourseLPsGenericStats'), [], ICON_SIZE_MEDIUM),
api_get_path(WEB_CODE_PATH).'tracking/lp_report.php?'.api_get_cidreq()
);
$attendanceLink = '';
if (!empty($sessionId)) {
$attendanceLink = Display::url(
@ -7890,6 +8130,12 @@ class TrackingCourseLog
);
}
break;
case 'lp':
$lpLink = Display::url(
Display::return_icon('scorms_na.png', get_lang('CourseLPsGenericStats'), [], ICON_SIZE_MEDIUM),
'#'
);
break;
}
$items = [
@ -7899,6 +8145,7 @@ class TrackingCourseLog
$resourcesLink,
$examLink,
$eventsLink,
$lpLink,
$attendanceLink,
];

@ -95,9 +95,11 @@ class UserGroup extends Model
*
* @return array|int
*/
public function getUserGroupUsers($id, $getCount = false)
public function getUserGroupUsers($id, $getCount = false, $start = 0, $limit = 0)
{
$id = (int) $id;
$start = (int) $start;
$limit = (int) $limit;
$select = ' u.* ';
if ($getCount) {
@ -116,7 +118,15 @@ class UserGroup extends Model
FROM $this->usergroup_rel_user_table u
WHERE u.usergroup_id = $id";
}
$limitCondition = '';
if (!empty($start) && !empty($limit)) {
$limitCondition = " LIMIT $start, $limit";
}
$sql .= $limitCondition;
$result = Database::query($sql);
if ($getCount) {
if (Database::num_rows($result)) {
$row = Database::fetch_array($result);
@ -232,6 +242,56 @@ class UserGroup extends Model
return 0;
}
/**
* @param int $course_id
* @param int $type
*
* @return mixed
*/
public function getUserGroupByCourseWithDataCount($course_id, $type = -1)
{
if ($this->getUseMultipleUrl()) {
$course_id = (int) $course_id;
$urlId = api_get_current_access_url_id();
$sql = "SELECT count(c.usergroup_id) as count
FROM {$this->usergroup_rel_course_table} c
INNER JOIN {$this->access_url_rel_usergroup} a
ON (c.usergroup_id = a.usergroup_id)
WHERE access_url_id = $urlId AND course_id = $course_id
";
$result = Database::query($sql);
if (Database::num_rows($result)) {
$row = Database::fetch_array($result);
return $row['count'];
}
return 0;
} else {
$typeCondition = '';
if ($type != -1) {
$type = (int) $type;
$typeCondition = " AND group_type = $type ";
}
$sql = "SELECT count(c.usergroup_id) as count
FROM {$this->usergroup_rel_course_table} c
INNER JOIN {$this->table} a
ON (c.usergroup_id = a.id)
WHERE
course_id = $course_id
$typeCondition
";
$result = Database::query($sql);
if (Database::num_rows($result)) {
$row = Database::fetch_array($result);
return $row['count'];
}
return 0;
}
}
/**
* @param string $name
*

@ -188,6 +188,8 @@ class UserManager
) {
$authSource = !empty($authSource) ? $authSource : PLATFORM_AUTH_SOURCE;
$creatorId = empty($creatorId) ? api_get_user_id() : 0;
$creatorInfo = api_get_user_info($creatorId);
$creatorEmail = isset($creatorInfo['email']) ? $creatorInfo['email'] : '';
$hook = Container::instantiateHook(HookCreateUser::class);
if (!empty($hook)) {
@ -529,7 +531,8 @@ class UserManager
null,
null,
null,
$additionalParameters
$additionalParameters,
$creatorEmail
);
$layoutContent = $tplContent->get_template('mail/new_user_second_email_confirmation.tpl');
@ -555,7 +558,8 @@ class UserManager
null,
null,
null,
$additionalParameters
$additionalParameters,
$creatorEmail
);
} else {
if (!empty($emailBodyTemplate)) {
@ -587,7 +591,8 @@ class UserManager
null,
null,
null,
$additionalParameters
$additionalParameters,
$creatorEmail
);
}
}

@ -37,6 +37,7 @@ class Rest extends WebService
const GET_COURSE_FORUM_THREAD = 'course_forumthread';
const GET_COURSE_LEARNPATHS = 'course_learnpaths';
const GET_COURSE_LEARNPATH = 'course_learnpath';
const GET_COURSE_LP_PROGRESS = 'course_lp_progress';
const SAVE_FORUM_POST = 'save_forum_post';
const GET_USER_SESSIONS = 'user_sessions';
const SAVE_USER_MESSAGE = 'save_user_message';
@ -45,21 +46,33 @@ class Rest extends WebService
const SAVE_FORUM_THREAD = 'save_forum_thread';
const SAVE_COURSE = 'save_course';
const SAVE_USER = 'save_user';
const SAVE_USER_JSON = 'save_user_json';
const SUBSCRIBE_USER_TO_COURSE = 'subscribe_user_to_course';
const EXTRAFIELD_GCM_ID = 'gcm_registration_id';
const GET_USER_MESSAGES_RECEIVED = 'user_messages_received';
const GET_USER_MESSAGES_SENT = 'user_messages_sent';
const DELETE_USER_MESSAGE = 'delete_user_message';
const SET_MESSAGE_READ = 'set_message_read';
const CREATE_CAMPUS = 'add_campus';
const EDIT_CAMPUS = 'edit_campus';
const DELETE_CAMPUS = 'delete_campus';
const SAVE_SESSION = 'save_session';
const GET_USERS = 'get_users';
const GET_COURSE = 'get_courses';
const GET_COURSES = 'get_courses';
const ADD_COURSES_SESSION = 'add_courses_session';
const ADD_USER_SESSION = 'add_users_session';
const ADD_USERS_SESSION = 'add_users_session';
const CREATE_SESSION_FROM_MODEL = 'create_session_from_model';
const SUBSCRIBE_USER_TO_SESSION_FROM_USERNAME = 'subscribe_user_to_session_from_username';
const GET_SESSION_FROM_EXTRA_FIELD = 'get_session_from_extra_field';
const UPDATE_USER_FROM_USERNAME = 'update_user_from_username';
const USERNAME_EXIST = 'username_exist';
const GET_COURSE_QUIZ_MDL_COMPAT = 'get_course_quiz_mdl_compat';
/**
* @var Session
*/
private $session;
/**
* @var Course
*/
@ -265,7 +278,7 @@ class Rest extends WebService
'title' => $this->course->getTitle(),
'code' => $this->course->getCode(),
'directory' => $this->course->getDirectory(),
'urlPicture' => Container::getIllustrationRepository()->getIllustrationUrl($this->course);
'urlPicture' => Container::getIllustrationRepository()->getIllustrationUrl($this->course),
'teachers' => $teachers,
'tools' => array_map(
function ($tool) {

@ -8,7 +8,6 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\SerializerInterface;
/**

@ -6,7 +6,6 @@ namespace Chamilo\CoreBundle\Controller;
use Chamilo\CoreBundle\Entity\User;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;

@ -15,7 +15,6 @@ use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\EquatableInterface;
use Symfony\Component\Security\Core\User\UserInterface;
@ -1684,7 +1683,6 @@ class User implements UserInterface, EquatableInterface
return in_array($name, $this->getGroupNames());
}
public function removeGroup($group)
{
if ($this->getGroups()->contains($group)) {

@ -14,6 +14,7 @@ use Twig\Environment;
class TwigListener
{
private $twig;
public function __construct(Environment $twig, SerializerInterface $serializer, TokenStorageInterface $tokenStorage)
{
$this->twig = $twig;

@ -79,7 +79,7 @@ class LoginFormAuthenticator extends AbstractFormLoginAuthenticator implements P
$data = json_decode($request->getContent(), true);
$username = $data['username'];
$password = $data['password'];
//$token = $data['csrf_token'];
//$token = $data['csrf_token'];
} else {
$username = $request->request->get('username');
$password = $request->request->get('password');

Loading…
Cancel
Save