Statistics: Fix errors and improve data handling in admin reports - refs BT#22248

pull/5966/head
Christian Beeznest 9 months ago
parent ac17881087
commit c6e300ee0c
  1. 4
      public/main/admin/statistics/index.php
  2. 1
      public/main/inc/lib/database.constants.inc.php
  3. 121
      public/main/inc/lib/statistics.lib.php
  4. 23
      public/main/inc/lib/zombie/zombie_manager.class.php
  5. 16
      public/main/inc/lib/zombie/zombie_report.class.php

@ -372,6 +372,8 @@ switch ($report) {
$sessions = []; $sessions = [];
if ($validated) { if ($validated) {
$values = $form->getSubmitValues(); $values = $form->getSubmitValues();
$dateStart = $values['range_start'];
$dateEnd = $values['range_end'];
$first = DateTime::createFromFormat('Y-m-d', $dateStart); $first = DateTime::createFromFormat('Y-m-d', $dateStart);
$second = DateTime::createFromFormat('Y-m-d', $dateEnd); $second = DateTime::createFromFormat('Y-m-d', $dateEnd);
$numberOfWeeks = 0; $numberOfWeeks = 0;
@ -549,7 +551,7 @@ switch ($report) {
foreach ($sessions as $session) { foreach ($sessions as $session) {
$courseList = SessionManager::getCoursesInSession($session['id']); $courseList = SessionManager::getCoursesInSession($session['id']);
$table->setCellContents($row, 0, $session['name']); $table->setCellContents($row, 0, $session['title']);
$table->setCellContents($row, 1, api_get_local_time($session['display_start_date'])); $table->setCellContents($row, 1, api_get_local_time($session['display_start_date']));
$table->setCellContents($row, 2, api_get_local_time($session['display_end_date'])); $table->setCellContents($row, 2, api_get_local_time($session['display_end_date']));

@ -232,6 +232,7 @@ define('TABLE_NOTEBOOK', 'notebook');
// Message // Message
define('TABLE_MESSAGE', 'message'); define('TABLE_MESSAGE', 'message');
define('TABLE_MESSAGE_ATTACHMENT', 'message_attachment'); define('TABLE_MESSAGE_ATTACHMENT', 'message_attachment');
define('TABLE_MESSAGE_REL_USER', 'message_rel_user');
// Attendance Sheet // Attendance Sheet
define('TABLE_ATTENDANCE', 'attendance'); define('TABLE_ATTENDANCE', 'attendance');

@ -2,6 +2,7 @@
/* For licensing terms, see /license.txt */ /* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Component\Utils\ChamiloApi; use Chamilo\CoreBundle\Component\Utils\ChamiloApi;
use Chamilo\CoreBundle\Entity\MessageRelUser;
use Chamilo\CoreBundle\Entity\UserRelUser; use Chamilo\CoreBundle\Entity\UserRelUser;
use Chamilo\CoreBundle\Component\Utils\ActionIcon; use Chamilo\CoreBundle\Component\Utils\ActionIcon;
@ -136,47 +137,48 @@ class Statistics
$tblCourseCategory = Database::get_main_table(TABLE_MAIN_CATEGORY); $tblCourseCategory = Database::get_main_table(TABLE_MAIN_CATEGORY);
$tblCourseRelCategory = Database::get_main_table(TABLE_MAIN_COURSE_REL_CATEGORY); $tblCourseRelCategory = Database::get_main_table(TABLE_MAIN_COURSE_REL_CATEGORY);
$urlId = api_get_current_access_url_id(); $urlId = api_get_current_access_url_id();
$active_filter = $onlyActive ? ' AND active = 1' : '';
$status_filter = isset($status) ? ' AND status = '.intval($status) : ''; $conditions = [];
$conditions[] = "u.active <> " . USER_SOFT_DELETED;
if ($onlyActive) {
$conditions[] = "u.active = 1";
}
if (isset($status)) {
$conditions[] = "u.status = " . intval($status);
}
$where = implode(' AND ', $conditions);
if (api_is_multiple_url_enabled()) { if (api_is_multiple_url_enabled()) {
$sql = "SELECT COUNT(DISTINCT(u.id)) AS number $sql = "SELECT COUNT(DISTINCT(u.id)) AS number
FROM $user_table as u, $access_url_rel_user_table as url FROM $user_table as u
WHERE INNER JOIN $access_url_rel_user_table as url ON u.id = url.user_id
u.active <> ".USER_SOFT_DELETED." AND WHERE $where AND url.access_url_id = $urlId";
u.id = url.user_id AND
access_url_id = $urlId
$status_filter $active_filter";
if (isset($categoryCode)) { if (isset($categoryCode)) {
$categoryCode = Database::escape_string($categoryCode); $categoryCode = Database::escape_string($categoryCode);
$sql = "SELECT COUNT(DISTINCT(cu.user_id)) AS number $sql = "SELECT COUNT(DISTINCT(cu.user_id)) AS number
FROM $course_user_table cu, $course_table c, $access_url_rel_user_table as url, $tblCourseRelCategory crc, $tblCourseCategory cc FROM $course_user_table cu
WHERE INNER JOIN $course_table c ON c.id = cu.c_id
c.id = cu.c_id AND INNER JOIN $access_url_rel_user_table as url ON cu.user_id = url.user_id
cc.code = '$categoryCode' AND INNER JOIN $tblCourseRelCategory crc ON crc.course_id = c.id
crc.course_category_id = cc.id AND INNER JOIN $tblCourseCategory cc ON cc.id = crc.course_category_id
crc.course_id = c.id AND WHERE $where AND url.access_url_id = $urlId AND cc.code = '$categoryCode'";
cu.user_id = url.user_id AND
access_url_id = $urlId
$status_filter $active_filter";
} }
} else { } else {
$sql = "SELECT COUNT(DISTINCT(id)) AS number $sql = "SELECT COUNT(DISTINCT(id)) AS number
FROM $user_table FROM $user_table u
WHERE 1 = 1 AND active <> ".USER_SOFT_DELETED." $status_filter $active_filter"; WHERE $where";
if (isset($categoryCode)) { if (isset($categoryCode)) {
$categoryCode = Database::escape_string($categoryCode); $categoryCode = Database::escape_string($categoryCode);
$status_filter = isset($status) ? ' AND status = '.intval($status) : '';
$sql = "SELECT COUNT(DISTINCT(cu.user_id)) AS number $sql = "SELECT COUNT(DISTINCT(cu.user_id)) AS number
FROM $course_user_table cu, $course_table c, $tblCourseRelCategory crc, $tblCourseCategory cc FROM $course_user_table cu
WHERE INNER JOIN $course_table c ON c.id = cu.c_id
c.id = cu.c_id AND INNER JOIN $tblCourseRelCategory crc ON crc.course_id = c.id
cc.code = '$categoryCode' AND INNER JOIN $tblCourseCategory cc ON cc.id = crc.course_category_id
crc.course_category_id = cc.id AND INNER JOIN $user_table u ON u.id = cu.user_id
crc.course_id = c.id AND WHERE $where AND cc.code = '$categoryCode'";
$status_filter
$active_filter
";
} }
} }
@ -890,7 +892,7 @@ class Statistics
'get', 'get',
api_get_path(WEB_CODE_PATH).'admin/statistics/index.php', api_get_path(WEB_CODE_PATH).'admin/statistics/index.php',
'', '',
'width=200px', ['style' => 'width:200px'],
false false
); );
$renderer = &$form->defaultRenderer(); $renderer = &$form->defaultRenderer();
@ -941,7 +943,7 @@ class Statistics
$access_url_rel_course_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE); $access_url_rel_course_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
$urlId = api_get_current_access_url_id(); $urlId = api_get_current_access_url_id();
$columns[0] = 't.c_id'; $columns[0] = 'c_id';
$columns[1] = 'access_date'; $columns[1] = 'access_date';
$sql_order[SORT_ASC] = 'ASC'; $sql_order[SORT_ASC] = 'ASC';
$sql_order[SORT_DESC] = 'DESC'; $sql_order[SORT_DESC] = 'DESC';
@ -972,15 +974,15 @@ class Statistics
if (api_is_multiple_url_enabled()) { if (api_is_multiple_url_enabled()) {
$sql = "SELECT * FROM $table t , $access_url_rel_course_table a $sql = "SELECT * FROM $table t , $access_url_rel_course_table a
WHERE WHERE
t.c_id = a.c_id AND c_id = a.c_id AND
access_url_id='".$urlId."' access_url_id='".$urlId."'
GROUP BY t.c_id GROUP BY c_id
HAVING t.c_id <> '' HAVING c_id <> ''
AND DATEDIFF( '".api_get_utc_datetime()."' , access_date ) <= ".$date_diff; AND DATEDIFF( '".api_get_utc_datetime()."' , access_date ) <= ".$date_diff;
} else { } else {
$sql = "SELECT * FROM $table t $sql = "SELECT * FROM $table t
GROUP BY t.c_id GROUP BY c_id
HAVING t.c_id <> '' HAVING c_id <> ''
AND DATEDIFF( '".api_get_utc_datetime()."' , access_date ) <= ".$date_diff; AND DATEDIFF( '".api_get_utc_datetime()."' , access_date ) <= ".$date_diff;
} }
$sql .= ' ORDER BY `'.$columns[$column].'` '.$sql_order[$direction]; $sql .= ' ORDER BY `'.$columns[$column].'` '.$sql_order[$direction];
@ -1030,33 +1032,42 @@ class Statistics
*/ */
public static function getMessages($messageType) public static function getMessages($messageType)
{ {
$message_table = Database::get_main_table(TABLE_MESSAGE); $messageTable = Database::get_main_table(TABLE_MESSAGE);
$user_table = Database::get_main_table(TABLE_MAIN_USER); $messageRelUserTable = Database::get_main_table(TABLE_MESSAGE_REL_USER);
$access_url_rel_user_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER); $userTable = Database::get_main_table(TABLE_MAIN_USER);
$accessUrlRelUserTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
$urlId = api_get_current_access_url_id(); $urlId = api_get_current_access_url_id();
switch ($messageType) { switch ($messageType) {
case 'sent': case 'sent':
$field = 'user_sender_id'; $field = 'm.user_sender_id';
$joinCondition = "m.id = mru.message_id AND mru.receiver_type = " . MessageRelUser::TYPE_SENDER;
break; break;
case 'received': case 'received':
$field = 'user_receiver_id'; $field = 'mru.user_id';
$joinCondition = "m.id = mru.message_id AND mru.receiver_type = " . MessageRelUser::TYPE_TO;
break; break;
} }
if (api_is_multiple_url_enabled()) { if (api_is_multiple_url_enabled()) {
$sql = "SELECT lastname, firstname, username, COUNT($field) AS count_message $sql = "SELECT u.lastname, u.firstname, u.username, COUNT(DISTINCT m.id) AS count_message
FROM $access_url_rel_user_table as url, $message_table m FROM $messageTable m
LEFT JOIN $user_table u ON m.$field = u.id AND u.active <> ".USER_SOFT_DELETED." INNER JOIN $messageRelUserTable mru ON $joinCondition
WHERE url.user_id = m.$field AND access_url_id='".$urlId."' INNER JOIN $userTable u ON $field = u.id
GROUP BY m.$field INNER JOIN $accessUrlRelUserTable url ON u.id = url.user_id
ORDER BY count_message DESC "; WHERE url.access_url_id = $urlId
AND u.active <> " . USER_SOFT_DELETED . "
GROUP BY $field
ORDER BY count_message DESC";
} else { } else {
$sql = "SELECT lastname, firstname, username, COUNT($field) AS count_message $sql = "SELECT u.lastname, u.firstname, u.username, COUNT(DISTINCT m.id) AS count_message
FROM $message_table m FROM $messageTable m
LEFT JOIN $user_table u ON m.$field = u.id AND u.active <> ".USER_SOFT_DELETED." INNER JOIN $messageRelUserTable mru ON $joinCondition
GROUP BY m.$field ORDER BY count_message DESC "; INNER JOIN $userTable u ON $field = u.id
WHERE u.active <> " . USER_SOFT_DELETED . "
GROUP BY $field
ORDER BY count_message DESC";
} }
$res = Database::query($sql); $res = Database::query($sql);
$messages_sent = []; $messages_sent = [];
@ -1065,9 +1076,9 @@ class Statistics
$messages['username'] = get_lang('Unknown'); $messages['username'] = get_lang('Unknown');
} }
$users = api_get_person_name( $users = api_get_person_name(
$messages['firstname'], $messages['firstname'],
$messages['lastname'] $messages['lastname']
).'<br />('.$messages['username'].')'; ) . '<br />(' . $messages['username'] . ')';
$messages_sent[$users] = $messages['count_message']; $messages_sent[$users] = $messages['count_message'];
} }
@ -1144,7 +1155,7 @@ class Statistics
"SELECT count(distinct(login_user_id)) AS number ". "SELECT count(distinct(login_user_id)) AS number ".
" FROM $table $table_url ". " FROM $table $table_url ".
" WHERE DATE_ADD(login_date, INTERVAL 31 DAY) >= '$now' $where_url"; " WHERE DATE_ADD(login_date, INTERVAL 31 DAY) >= '$now' $where_url";
$sql[sprintf(get_lang('Last %i months'), 6)] = $sql[sprintf(get_lang('Last %d months'), 6)] =
"SELECT count(distinct(login_user_id)) AS number ". "SELECT count(distinct(login_user_id)) AS number ".
" FROM $table $table_url ". " FROM $table $table_url ".
" WHERE DATE_ADD(login_date, INTERVAL 6 MONTH) >= '$now' $where_url"; " WHERE DATE_ADD(login_date, INTERVAL 6 MONTH) >= '$now' $where_url";

@ -36,8 +36,14 @@ class ZombieManager
$column = 'user.firstname', $column = 'user.firstname',
$direction = 'desc' $direction = 'desc'
) { ) {
$column = str_replace('user.', '', $column);
if (empty($column)) { if (empty($column)) {
$column = 'user.firstname'; $column = 'firstname';
}
$validColumns = ['id', 'official_code', 'firstname', 'lastname', 'username', 'auth_source', 'email', 'status', 'registration_date', 'active', 'login_date'];
if (!in_array($column, $validColumns)) {
$column = 'firstname';
} }
$ceiling = is_numeric($ceiling) ? (int) $ceiling : strtotime($ceiling); $ceiling = is_numeric($ceiling) ? (int) $ceiling : strtotime($ceiling);
$ceiling = date('Y-m-d H:i:s', $ceiling); $ceiling = date('Y-m-d H:i:s', $ceiling);
@ -46,7 +52,7 @@ class ZombieManager
$login_table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN); $login_table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
$sql = 'SELECT $sql = 'SELECT
user.user_id, user.id,
user.official_code, user.official_code,
user.firstname, user.firstname,
user.lastname, user.lastname,
@ -66,20 +72,20 @@ class ZombieManager
WHERE WHERE
access.login_date = (SELECT MAX(a.login_date) access.login_date = (SELECT MAX(a.login_date)
FROM $login_table as a FROM $login_table as a
WHERE a.login_user_id = user.user_id WHERE a.login_user_id = user.id
) AND ) AND
access.login_date <= '$ceiling' AND access.login_date <= '$ceiling' AND
user.user_id = access.login_user_id AND user.id = access.login_user_id AND
url.user_id = user.user_id AND url.access_url_id=$current_url_id"; url.user_id = user.id AND url.access_url_id=$current_url_id";
} else { } else {
$sql .= " FROM $user_table as user, $login_table as access $sql .= " FROM $user_table as user, $login_table as access
WHERE WHERE
access.login_date = (SELECT MAX(a.login_date) access.login_date = (SELECT MAX(a.login_date)
FROM $login_table as a FROM $login_table as a
WHERE a.login_user_id = user.user_id WHERE a.login_user_id = user.id
) AND ) AND
access.login_date <= '$ceiling' AND access.login_date <= '$ceiling' AND
user.user_id = access.login_user_id"; user.id = access.login_user_id";
} }
if ($active_only) { if ($active_only) {
@ -87,6 +93,7 @@ class ZombieManager
} }
$sql .= !str_contains($sql, 'WHERE') ? ' WHERE user.active <> '.USER_SOFT_DELETED : ' AND user.active <> '.USER_SOFT_DELETED; $sql .= !str_contains($sql, 'WHERE') ? ' WHERE user.active <> '.USER_SOFT_DELETED : ' AND user.active <> '.USER_SOFT_DELETED;
$column = str_replace('user.', '', $column);
$sql .= " ORDER BY `$column` $direction"; $sql .= " ORDER BY `$column` $direction";
if (!is_null($from) && !is_null($count)) { if (!is_null($from) && !is_null($count)) {
$count = (int) $count; $count = (int) $count;
@ -107,7 +114,7 @@ class ZombieManager
$zombies = self::listZombies($ceiling); $zombies = self::listZombies($ceiling);
$ids = []; $ids = [];
foreach ($zombies as $zombie) { foreach ($zombies as $zombie) {
$ids[] = $zombie['user_id']; $ids[] = $zombie['id'];
} }
UserManager::deactivate_users($ids); UserManager::deactivate_users($ids);
} }

@ -3,7 +3,7 @@
/* For licensing terms, see /license.txt */ /* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Component\Utils\StateIcon; use Chamilo\CoreBundle\Component\Utils\StateIcon;
use Symfony\Component\HttpFoundation\Request;
/** /**
* Description of zombie_report. * Description of zombie_report.
* *
@ -14,12 +14,14 @@ use Chamilo\CoreBundle\Component\Utils\StateIcon;
class ZombieReport implements Countable class ZombieReport implements Countable
{ {
protected $additional_parameters = []; protected $additional_parameters = [];
protected $request;
protected $parameters_form = null; protected $parameters_form = null;
public function __construct($additional_parameters = []) public function __construct($additional_parameters = [], Request $request = null)
{ {
$this->additional_parameters = $additional_parameters; $this->additional_parameters = $additional_parameters;
$this->request = $request ?? Request::createFromGlobals();
} }
/** /**
@ -121,7 +123,7 @@ class ZombieReport implements Countable
public function get_ceiling($format = null) public function get_ceiling($format = null)
{ {
$result = Request::get('ceiling'); $result = $this->request->get('ceiling');
$result = $result ? $result : ZombieManager::last_year(); $result = $result ? $result : ZombieManager::last_year();
$result = is_array($result) && 1 == count($result) ? reset($result) : $result; $result = is_array($result) && 1 == count($result) ? reset($result) : $result;
@ -137,7 +139,7 @@ class ZombieReport implements Countable
public function get_active_only() public function get_active_only()
{ {
$result = Request::get('active_only', false); $result = $this->request->get('active_only', $this->request->query->get('active_only'));
$result = 'true' === $result ? true : $result; $result = 'true' === $result ? true : $result;
$result = 'false' === $result ? false : $result; $result = 'false' === $result ? false : $result;
$result = (bool) $result; $result = (bool) $result;
@ -156,12 +158,12 @@ class ZombieReport implements Countable
return 'display'; return 'display';
} }
return Request::post('action', 'display'); return $this->request->request->get('action', 'display');
} }
public function perform_action() public function perform_action()
{ {
$ids = Request::post('id'); $ids = $this->request->request->get('id');
if (empty($ids)) { if (empty($ids)) {
return $ids; return $ids;
} }
@ -198,7 +200,7 @@ class ZombieReport implements Countable
$result = []; $result = [];
foreach ($items as $item) { foreach ($items as $item) {
$row = []; $row = [];
$row[] = $item['user_id']; $row[] = $item['id'];
$row[] = $item['official_code']; $row[] = $item['official_code'];
$row[] = $item['firstname']; $row[] = $item['firstname'];
$row[] = $item['lastname']; $row[] = $item['lastname'];

Loading…
Cancel
Save