Merge branch 'master' of github.com:chamilo/chamilo-lms

pull/6055/head
Angel Fernando Quiroz Campos 8 months ago
commit 3cd611664b
No known key found for this signature in database
GPG Key ID: B284841AE3E562CD
  1. 3
      composer.json
  2. 153
      public/main/admin/statistics/index.php
  3. 654
      public/main/inc/ajax/statistics.ajax.php
  4. 17
      public/main/inc/lib/api.lib.php
  5. 55
      public/main/inc/lib/internationalization.lib.php
  6. 215
      public/main/inc/lib/statistics.lib.php
  7. 55
      public/main/inc/lib/tracking.lib.php
  8. 139
      public/main/inc/lib/usermanager.lib.php
  9. 10
      public/plugin/dashboard/block_global_info/block_global_info.class.php

@ -181,7 +181,8 @@
"symfony/flex": true,
"dealerdirect/phpcodesniffer-composer-installer": true,
"symfony/runtime": true
}
},
"process-timeout": 900
},
"require-dev": {
"behat/behat": "^3.10",

@ -352,16 +352,17 @@ $tools = [
'report=new_user_registrations' => get_lang('New users registrations'),
],
get_lang('System') => [
'report=activities' => get_lang('ImportantActivities'),
'report=user_session' => get_lang('PortalUserSessionStats'),
'report=activities' => get_lang('Important activities'),
'report=user_session' => get_lang('Portal user session stats'),
'report=quarterly_report' => get_lang('Quarterly report'),
],
get_lang('Social') => [
'report=messagereceived' => get_lang('MessagesReceived'),
'report=messagesent' => get_lang('MessagesSent'),
'report=friends' => get_lang('CountFriends'),
'report=messagereceived' => get_lang('Number of messages received'),
'report=messagesent' => get_lang('Number of messages sent'),
'report=friends' => get_lang('Contacts count'),
],
get_lang('Session') => [
'report=session_by_date' => get_lang('SessionsByDate'),
'report=session_by_date' => get_lang('Sessions by date'),
],
];
@ -1665,6 +1666,146 @@ switch ($report) {
case 'logins_by_date':
$content .= Statistics::printLoginsByDate();
break;
case 'quarterly_report':
global $htmlHeadXtra;
$ajaxPath = api_get_path(WEB_AJAX_PATH);
$waitIcon = Display::getMdiIcon('clock-time-four', 'ch-tool-icon-disabled', null, ICON_SIZE_SMALL, false);
$htmlHeadXtra[] .= '<script>
function loadReportQuarterlyUsers () {
$("#tracking-report-quarterly-users")
.html(\'<p>'.$waitIcon.'</p>\')
.load("'.$ajaxPath.'statistics.ajax.php?a=report_quarterly_users'.'");
}</script>';
$htmlHeadXtra[] .= '<script>
function loadReportQuarterlyCourses () {
$("#tracking-report-quarterly-courses")
.html(\'<p>'.$waitIcon.'</p>\')
.load("'.$ajaxPath.'statistics.ajax.php?a=report_quarterly_courses'.'");
}</script>';
$htmlHeadXtra[] .= '<script>
function loadReportQuarterlyHoursOfTraining () {
$("#tracking-report-quarterly-hours-of-training")
.html(\'<p>'.$waitIcon.'</p>\')
.load("'.$ajaxPath.'statistics.ajax.php?a=report_quarterly_hours_of_training'.'");
}</script>';
$htmlHeadXtra[] .= '<script>
function loadReportQuarterlyCertificatesGenerated () {
$("#tracking-report-quarterly-number-of-certificates-generated")
.html(\'<p>'.$waitIcon.'</p>\')
.load("'.$ajaxPath.'statistics.ajax.php?a=report_quarterly_number_of_certificates_generated'.'");
}</script>';
$htmlHeadXtra[] .= '<script>
function loadReportQuarterlySessionsByDuration () {
$("#tracking-report-quarterly-sessions-by-duration")
.html(\'<p>'.$waitIcon.'</p>\')
.load("'.$ajaxPath.'statistics.ajax.php?a=report_quarterly_sessions_by_duration'.'");
}</script>';
$htmlHeadXtra[] .= '<script>
function loadReportQuarterlyCoursesAndSessions () {
$("#tracking-report-quarterly-courses-and-sessions")
.html(\'<p>'.$waitIcon.'</p>\')
.load("'.$ajaxPath.'statistics.ajax.php?a=report_quarterly_courses_and_sessions'.'");
}</script>';
if (api_get_current_access_url_id() === 1) {
$htmlHeadXtra[] .= '<script>
function loadReportQuarterlyTotalDiskUsage () {
$("#tracking-report-quarterly-total-disk-usage")
.html(\'<p>'.$waitIcon.'</p>\')
.load("'.$ajaxPath.'statistics.ajax.php?a=report_quarterly_total_disk_usage'.'");
}</script>';
}
$content .= Display::tag('H4', get_lang('Number of users registered and connected'), ['style' => 'margin-bottom: 25px;']);
$content .= Display::url(
get_lang('Show'),
'javascript://',
['onclick' => 'loadReportQuarterlyUsers();', 'class' => 'btn btn-default']
);
$content .= Display::div('', ['id' => 'tracking-report-quarterly-users', 'style' => 'margin: 30px;']);
$content .= Display::tag('H4', get_lang('Number of existing and available courses'), ['style' => 'margin-bottom: 25px;']);
$content .= Display::url(
get_lang('Show'),
'javascript://',
['onclick' => 'loadReportQuarterlyCourses();', 'class' => 'btn btn-default']
);
$content .= Display::div('', ['id' => 'tracking-report-quarterly-courses', 'style' => 'margin: 30px;']);
$content .= Display::tag('H4', get_lang('Hours of training'), ['style' => 'margin-bottom: 25px;']);
$content .= Display::url(
get_lang('Show'),
'javascript://',
['onclick' => 'loadReportQuarterlyHoursOfTraining();', 'class' => 'btn btn-default']
);
$content .= Display::div(
'',
[
'id' => 'tracking-report-quarterly-hours-of-training',
'style' => 'margin: 30px;',
]
);
$content .= Display::tag(
'H4',
get_lang('Number of certificates generated'),
['style' => 'margin-bottom: 25px;']
);
$content .= Display::url(
get_lang('Show'),
'javascript://',
['onclick' => 'loadReportQuarterlyCertificatesGenerated();', 'class' => 'btn btn-default']
);
$content .= Display::div(
'',
['id' => 'tracking-report-quarterly-number-of-certificates-generated', 'style' => 'margin: 30px;']
);
$content .= Display::tag(
'H4',
get_lang('Number of sessions per duration'),
['style' => 'margin-bottom: 25px;']
);
$content .= Display::url(
get_lang('Show'),
'javascript://',
['onclick' => 'loadReportQuarterlySessionsByDuration();', 'class' => 'btn btn-default']
);
$content .= Display::div(
'',
['id' => 'tracking-report-quarterly-sessions-by-duration', 'style' => 'margin: 30px;']
);
$content .= Display::tag(
'H4',
get_lang('Number of courses, sessions and subscribed users'),
['style' => 'margin-bottom: 25px;']
);
$content .= Display::url(
get_lang('Show'),
'javascript://',
['onclick' => 'loadReportQuarterlyCoursesAndSessions();', 'class' => 'btn btn-default']
);
$content .= Display::div(
'',
[
'id' => 'tracking-report-quarterly-courses-and-sessions',
'style' => 'margin: 30px;',
]
);
if (api_get_current_access_url_id() === 1) {
$content .= Display::tag(
'H4',
get_lang('Total disk usage'),
['style' => 'margin-bottom: 25px;']
);
$content .= Display::url(
get_lang('Show'),
'javascript://',
['onclick' => 'loadReportQuarterlyTotalDiskUsage();', 'class' => 'btn btn-default']
);
$content .= Display::div(
'',
[
'id' => 'tracking-report-quarterly-total-disk-usage',
'style' => 'margin: 30px;',
]
);
}
break;
}
Display::display_header($tool_name);

@ -644,7 +644,7 @@ switch ($action) {
$all = [];
while ($row = Database::fetch_array($result)) {
$categoryData = SessionManager::get_session_category($row['session_category_id']);
$label = get_lang('NoCategory');
$label = get_lang('Without category');
if ($categoryData) {
$label = $categoryData['name'];
}
@ -759,4 +759,656 @@ switch ($action) {
header('Content-type: application/json');
echo json_encode($list);
break;
case 'report_quarterly_users':
$currentQuarterDates = getQuarterDates();
$pre1QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-3 month')
->format('Y-m-d')
);
$pre2QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-6 month')
->format('Y-m-d')
);
$pre3QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-9 month')
->format('Y-m-d')
);
$pre4QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-12 month')
->format('Y-m-d')
);
$pre5QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-15 month')
->format('Y-m-d')
);
// Make de headers for the table
$headers = [
'',
$pre5QuarterDates['quarter_title'],
$pre4QuarterDates['quarter_title'],
$pre3QuarterDates['quarter_title'],
$pre2QuarterDates['quarter_title'],
$pre1QuarterDates['quarter_title'],
get_lang('YoY'),
$currentQuarterDates['quarter_title'].'*',
];
// Get the data for the number of user registered row (2)
$countUsersTotal = UserManager::get_number_of_users(
null,
null,
null
);
$countUsersPre1Quarter = UserManager::get_number_of_users(
null,
null,
null,
null,
$pre1QuarterDates['quarter_end']
);
$countUsersPre2Quarter = UserManager::get_number_of_users(
null,
null,
null,
null,
$pre2QuarterDates['quarter_end']
);
$countUsersPre3Quarter = UserManager::get_number_of_users(
null,
null,
null,
null,
$pre3QuarterDates['quarter_end']
);
$countUsersPre4Quarter = UserManager::get_number_of_users(
null,
null,
null,
null,
$pre4QuarterDates['quarter_end']
);
$countUsersPre5Quarter = UserManager::get_number_of_users(
null,
null,
null,
null,
$pre5QuarterDates['quarter_end']
);
// Calculate percent for first row
$percentIncrementUsersRegistered = api_calculate_increment_percent(
$countUsersPre1Quarter,
$countUsersPre5Quarter
);
// Get the data for number of users connected row (3)
$countUsersConnectedCurrentQuarter = count(
Statistics::getLoginsByDate(
$currentQuarterDates['quarter_start'],
$currentQuarterDates['quarter_end']
)
);
$countUsersConnectedPre1Quarter = count(
Statistics::getLoginsByDate(
$pre1QuarterDates['quarter_start'],
$pre1QuarterDates['quarter_end']
)
);
$countUsersConnectedPre2Quarter = count(
Statistics::getLoginsByDate(
$pre2QuarterDates['quarter_start'],
$pre2QuarterDates['quarter_end']
)
);
$countUsersConnectedPre3Quarter = count(
Statistics::getLoginsByDate(
$pre3QuarterDates['quarter_start'],
$pre3QuarterDates['quarter_end']
)
);
$countUsersConnectedPre4Quarter = count(
Statistics::getLoginsByDate(
$pre4QuarterDates['quarter_start'],
$pre4QuarterDates['quarter_end']
)
);
$countUsersConnectedPre5Quarter = count(
Statistics::getLoginsByDate(
$pre5QuarterDates['quarter_start'],
$pre5QuarterDates['quarter_end']
)
);
// Calculate percent for second row
$percentIncrementUsersConnected = api_calculate_increment_percent(
$countUsersConnectedPre1Quarter,
$countUsersConnectedPre5Quarter
);
//Make de rows with the recollected data
$rows = [];
$rows[] = [
get_lang('Number of users registered (total)'),
$countUsersPre5Quarter,
$countUsersPre4Quarter,
$countUsersPre3Quarter,
$countUsersPre2Quarter,
$countUsersPre1Quarter,
$percentIncrementUsersRegistered,
$countUsersTotal,
];
//todo comprobacion + -
$rows[] = [
get_lang('Number of users registered (new vs previous quarter)'),
'-',
'+'.($countUsersPre1Quarter - $countUsersPre2Quarter),
'+'.($countUsersPre2Quarter - $countUsersPre3Quarter),
'+'.($countUsersPre3Quarter - $countUsersPre4Quarter),
'+'.($countUsersPre4Quarter - $countUsersPre5Quarter),
'-',
'+'.($countUsersTotal - $countUsersPre1Quarter),
];
$rows[] = [
get_lang('Number of users who connected'),
$countUsersConnectedPre5Quarter,
$countUsersConnectedPre4Quarter,
$countUsersConnectedPre3Quarter,
$countUsersConnectedPre2Quarter,
$countUsersConnectedPre1Quarter,
$percentIncrementUsersConnected,
$countUsersConnectedCurrentQuarter,
];
echo Display::table($headers, $rows, []);
echo Display::label(get_lang('*: Current quarter, incomplete data'), 'warning');
break;
case 'report_quarterly_courses':
$currentQuarterDates = getQuarterDates();
$pre1QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-3 month')
->format('Y-m-d')
);
$pre2QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-6 month')
->format('Y-m-d')
);
$pre3QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-9 month')
->format('Y-m-d')
);
$pre4QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-12 month')
->format('Y-m-d')
);
$pre5QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-15 month')
->format('Y-m-d')
);
// Make the headers for the table
$headers = [
'',
$pre5QuarterDates['quarter_title'],
$pre4QuarterDates['quarter_title'],
$pre3QuarterDates['quarter_title'],
$pre2QuarterDates['quarter_title'],
$pre1QuarterDates['quarter_title'],
get_lang('YoY'),
$currentQuarterDates['quarter_title'].'*',
];
// Get the data for the rows
$countCoursesCurrentQuarter = Statistics::countCourses(null, null, null);
$countCoursesPre1Quarter = Statistics::countCourses(null, null, $pre1QuarterDates['quarter_end']);
$countCoursesPre2Quarter = Statistics::countCourses(null, null, $pre2QuarterDates['quarter_end']);
$countCoursesPre3Quarter = Statistics::countCourses(null, null, $pre3QuarterDates['quarter_end']);
$countCoursesPre4Quarter = Statistics::countCourses(null, null, $pre4QuarterDates['quarter_end']);
$countCoursesPre5Quarter = Statistics::countCourses(null, null, $pre5QuarterDates['quarter_end']);
$auxArrayVisibilities = [
COURSE_VISIBILITY_OPEN_WORLD,
COURSE_VISIBILITY_OPEN_PLATFORM,
COURSE_VISIBILITY_REGISTERED,
];
$countCoursesAvailableCurrentQuarter = Statistics::countCoursesByVisibility($auxArrayVisibilities);
$countCoursesAvailablePre1Quarter = Statistics::countCoursesByVisibility(
$auxArrayVisibilities,
null,
$pre1QuarterDates['quarter_end']
);
$countCoursesAvailablePre2Quarter = Statistics::countCoursesByVisibility(
$auxArrayVisibilities,
null,
$pre2QuarterDates['quarter_end']
);
$countCoursesAvailablePre3Quarter = Statistics::countCoursesByVisibility(
$auxArrayVisibilities,
null,
$pre3QuarterDates['quarter_end']
);
$countCoursesAvailablePre4Quarter = Statistics::countCoursesByVisibility(
$auxArrayVisibilities,
null,
$pre4QuarterDates['quarter_end']
);
$countCoursesAvailablePre5Quarter = Statistics::countCoursesByVisibility(
$auxArrayVisibilities,
null,
$pre5QuarterDates['quarter_end']
);
// Calculate percents for first row
$percentIncrementCourses = api_calculate_increment_percent(
$countCoursesPre1Quarter,
$countCoursesPre5Quarter
);
// Calculate percents for second row
$percentIncrementUsersRegistered = api_calculate_increment_percent(
$countCoursesAvailablePre1Quarter,
$countCoursesAvailablePre5Quarter
);
//Make the rows with the recollected data
$rows = [];
$rows[] = [
get_lang('Number of existing courses (total)'),
$countCoursesPre5Quarter,
$countCoursesPre4Quarter,
$countCoursesPre3Quarter,
$countCoursesPre2Quarter,
$countCoursesPre1Quarter,
$percentIncrementCourses,
$countCoursesCurrentQuarter,
];
$rows[] = [
get_lang('Number of available courses (not closed or hidden, total)'),
$countCoursesAvailablePre5Quarter,
$countCoursesAvailablePre4Quarter,
$countCoursesAvailablePre3Quarter,
$countCoursesAvailablePre2Quarter,
$countCoursesAvailablePre1Quarter,
$percentIncrementUsersRegistered,
$countCoursesAvailableCurrentQuarter,
];
echo Display::table($headers, $rows, []);
echo Display::label(get_lang('*: Current quarter, incomplete data'), 'warning');
break;
case 'report_quarterly_hours_of_training':
$currentQuarterDates = getQuarterDates();
$pre1QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-3 month')
->format('Y-m-d')
);
$pre2QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-6 month')
->format('Y-m-d')
);
$pre3QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-9 month')
->format('Y-m-d')
);
$pre4QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-12 month')
->format('Y-m-d')
);
$pre5QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-15 month')
->format('Y-m-d')
);
// Make the headers for the table
$headers = [
'',
$pre5QuarterDates['quarter_title'],
$pre4QuarterDates['quarter_title'],
$pre3QuarterDates['quarter_title'],
$pre2QuarterDates['quarter_title'],
$pre1QuarterDates['quarter_title'],
get_lang('YoY'),
$currentQuarterDates['quarter_title'].'*',
];
// Get data for the row
$timeSpentCoursesCurrentQuarter = Tracking::getTotalTimeSpentInCourses(
$currentQuarterDates['quarter_start'],
$currentQuarterDates['quarter_end']
);
$timeSpentCourses1PreQuarter = Tracking::getTotalTimeSpentInCourses(
$pre1QuarterDates['quarter_start'],
$pre1QuarterDates['quarter_end']
);
$timeSpentCourses2PreQuarter = Tracking::getTotalTimeSpentInCourses(
$pre2QuarterDates['quarter_start'],
$pre2QuarterDates['quarter_end']
);
$timeSpentCourses3PreQuarter = Tracking::getTotalTimeSpentInCourses(
$pre3QuarterDates['quarter_start'],
$pre3QuarterDates['quarter_end']
);
$timeSpentCourses4PreQuarter = Tracking::getTotalTimeSpentInCourses(
$pre4QuarterDates['quarter_start'],
$pre4QuarterDates['quarter_end']
);
$timeSpentCourses5PreQuarter = Tracking::getTotalTimeSpentInCourses(
$pre5QuarterDates['quarter_start'],
$pre5QuarterDates['quarter_end']
);
// Calculate percent for the row
$percentIncrementTimeSpent = api_calculate_increment_percent(
$timeSpentCourses1PreQuarter,
$timeSpentCourses5PreQuarter
);
//Make the row with the recollected data
$rows = [];
$rows[] = [
get_lang('Number of hours of training followed (total)'),
$timeSpentCourses5PreQuarter,
$timeSpentCourses4PreQuarter,
$timeSpentCourses3PreQuarter,
$timeSpentCourses2PreQuarter,
$timeSpentCourses1PreQuarter,
$percentIncrementTimeSpent,
$timeSpentCoursesCurrentQuarter,
];
echo Display::table($headers, $rows, []);
echo Display::label(get_lang('*: Current quarter, incomplete data'), 'warning');
break;
case 'report_quarterly_number_of_certificates_generated':
$currentQuarterDates = getQuarterDates();
$pre1QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-3 month')
->format('Y-m-d')
);
$pre2QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-6 month')
->format('Y-m-d')
);
$pre3QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-9 month')
->format('Y-m-d')
);
$pre4QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-12 month')
->format('Y-m-d')
);
$pre5QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-15 month')
->format('Y-m-d')
);
// Make the headers for the table
$headers = [
'',
$pre5QuarterDates['quarter_title'],
$pre4QuarterDates['quarter_title'],
$pre3QuarterDates['quarter_title'],
$pre2QuarterDates['quarter_title'],
$pre1QuarterDates['quarter_title'],
get_lang('YoY'),
$currentQuarterDates['quarter_title'].'*',
];
// Get data for the row
$certificateGeneratedCurrentQuarter = Statistics::countCertificatesByQuarter(
null,
$currentQuarterDates['quarter_end']
);
$certificateGenerated1PreQuarter = Statistics::countCertificatesByQuarter(
null,
$pre1QuarterDates['quarter_end']
);
$certificateGenerated2PreQuarter = Statistics::countCertificatesByQuarter(
null,
$pre2QuarterDates['quarter_end']
);
$certificateGenerated3PreQuarter = Statistics::countCertificatesByQuarter(
null,
$pre3QuarterDates['quarter_end']
);
$certificateGenerated4PreQuarter = Statistics::countCertificatesByQuarter(
null,
$pre4QuarterDates['quarter_end']
);
$certificateGenerated5PreQuarter = Statistics::countCertificatesByQuarter(
null,
$pre5QuarterDates['quarter_end']
);
// Calculate percent for the row
$percentIncrementCertificateGenerated = api_calculate_increment_percent(
$certificateGenerated1PreQuarter,
$certificateGenerated5PreQuarter
);
//Make the row with the recollected data
$rows = [];
$rows[] = [
get_lang('Number of certificates generated'),
$certificateGenerated5PreQuarter,
$certificateGenerated4PreQuarter,
$certificateGenerated3PreQuarter,
$certificateGenerated2PreQuarter,
$certificateGenerated1PreQuarter,
$percentIncrementCertificateGenerated,
$certificateGeneratedCurrentQuarter,
];
echo Display::table($headers, $rows, []);
echo Display::label(get_lang('*: Current quarter, incomplete data'), 'warning');
break;
case "report_quarterly_sessions_by_duration":
$currentQuarterDates = getQuarterDates();
$pre1QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-3 month')
->format('Y-m-d')
);
$pre2QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-6 month')
->format('Y-m-d')
);
$pre3QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-9 month')
->format('Y-m-d')
);
$pre4QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-12 month')
->format('Y-m-d')
);
$pre5QuarterDates = getQuarterDates(
date_create($currentQuarterDates['quarter_start'])
->modify('-15 month')
->format('Y-m-d')
);
// Make the headers for the table
$headers = [
get_lang('Sessions per duration (by quarter)'),
$pre5QuarterDates['quarter_title'],
$pre4QuarterDates['quarter_title'],
$pre3QuarterDates['quarter_title'],
$pre2QuarterDates['quarter_title'],
$pre1QuarterDates['quarter_title'],
get_lang('YoY'),
$currentQuarterDates['quarter_title'].'*',
];
// Get the data for the rows
$sessionsDurationCurrentQuarter = Statistics::getSessionsByDuration(
$currentQuarterDates['quarter_start'],
$currentQuarterDates['quarter_end']
);
$sessionsDuration1PreQuarter = Statistics::getSessionsByDuration(
$pre1QuarterDates['quarter_start'],
$pre1QuarterDates['quarter_end']
);
$sessionsDuration2PreQuarter = Statistics::getSessionsByDuration(
$pre2QuarterDates['quarter_start'],
$pre2QuarterDates['quarter_end']
);
$sessionsDuration3PreQuarter = Statistics::getSessionsByDuration(
$pre3QuarterDates['quarter_start'],
$pre3QuarterDates['quarter_end']
);
$sessionsDuration4PreQuarter = Statistics::getSessionsByDuration(
$pre4QuarterDates['quarter_start'],
$pre4QuarterDates['quarter_end']
);
$sessionsDuration5PreQuarter = Statistics::getSessionsByDuration(
$pre5QuarterDates['quarter_start'],
$pre5QuarterDates['quarter_end']
);
// Calculate percent for the rows
$percentIncrementSessionDuration0 = api_calculate_increment_percent(
$sessionsDuration1PreQuarter['0'],
$sessionsDuration5PreQuarter['0']
);
$percentIncrementSessionDuration5 = api_calculate_increment_percent(
$sessionsDuration1PreQuarter['5'],
$sessionsDuration5PreQuarter['5']
);
$percentIncrementSessionDuration10 = api_calculate_increment_percent(
$sessionsDuration1PreQuarter['10'],
$sessionsDuration5PreQuarter['10']
);
$percentIncrementSessionDuration15 = api_calculate_increment_percent(
$sessionsDuration1PreQuarter['15'],
$sessionsDuration5PreQuarter['15']
);
$percentIncrementSessionDuration30 = api_calculate_increment_percent(
$sessionsDuration1PreQuarter['30'],
$sessionsDuration5PreQuarter['30']
);
$percentIncrementSessionDuration60 = api_calculate_increment_percent(
$sessionsDuration1PreQuarter['60'],
$sessionsDuration5PreQuarter['60']
);
//Make the rows with the recollected data
$rows = [];
$rows[] = [
'0-5&#8242;',
$sessionsDuration5PreQuarter['0'],
$sessionsDuration4PreQuarter['0'],
$sessionsDuration3PreQuarter['0'],
$sessionsDuration2PreQuarter['0'],
$sessionsDuration1PreQuarter['0'],
$percentIncrementSessionDuration0,
$sessionsDurationCurrentQuarter['0'],
];
$rows[] = [
'6-10&#8242;',
$sessionsDuration5PreQuarter['5'],
$sessionsDuration4PreQuarter['5'],
$sessionsDuration3PreQuarter['5'],
$sessionsDuration2PreQuarter['5'],
$sessionsDuration1PreQuarter['5'],
$percentIncrementSessionDuration5,
$sessionsDurationCurrentQuarter['5'],
];
$rows[] = [
'11-15&#8242;',
$sessionsDuration5PreQuarter['10'],
$sessionsDuration4PreQuarter['10'],
$sessionsDuration3PreQuarter['10'],
$sessionsDuration2PreQuarter['10'],
$sessionsDuration1PreQuarter['10'],
$percentIncrementSessionDuration10,
$sessionsDurationCurrentQuarter['10'],
];
$rows[] = [
'16-30&#8242;',
$sessionsDuration5PreQuarter['15'],
$sessionsDuration4PreQuarter['15'],
$sessionsDuration3PreQuarter['15'],
$sessionsDuration2PreQuarter['15'],
$sessionsDuration1PreQuarter['15'],
$percentIncrementSessionDuration15,
$sessionsDurationCurrentQuarter['15'],
];
$rows[] = [
'31-60&#8242;',
$sessionsDuration5PreQuarter['30'],
$sessionsDuration4PreQuarter['30'],
$sessionsDuration3PreQuarter['30'],
$sessionsDuration2PreQuarter['30'],
$sessionsDuration1PreQuarter['30'],
$percentIncrementSessionDuration30,
$sessionsDurationCurrentQuarter['30'],
];
$rows[] = [
'60-&#8734;&#8242;',
$sessionsDuration5PreQuarter['60'],
$sessionsDuration4PreQuarter['60'],
$sessionsDuration3PreQuarter['60'],
$sessionsDuration2PreQuarter['60'],
$sessionsDuration1PreQuarter['60'],
$percentIncrementSessionDuration60,
$sessionsDurationCurrentQuarter['60'],
];
echo Display::table($headers, $rows, []);
echo Display::label(get_lang('*: Current quarter, incomplete data'), 'warning');
break;
case "report_quarterly_courses_and_sessions":
// Make the headers for the tables
$headers = [
[
get_lang('List of course codes'),
get_lang('Number of subscribed users').'*',
get_lang('Number of users who finished the course (as defined in gradebook)'),
],
[
get_lang('List of course codes and sessions'),
get_lang('Number of subscribed users').'*',
get_lang('Number of users who finished the course (as defined in gradebook)'),
],
];
// Get the data fot the first table
$courses = UserManager::countUsersWhoFinishedCourses();
//Make the rows for first table
$rows = [];
foreach ($courses as $course => $data) {
$course_url = api_get_path(WEB_CODE_PATH).'course_home/course_home.php?cidReq='.$course;
$rows[] = [
Display::url($course, $course_url, ['target' => SESSION_LINK_TARGET]),
$data['subscribed'],
$data['finished'],
];
}
echo Display::table($headers[0], $rows, []);
//Get the data for the second table (with sessions)
$courses = UserManager::countUsersWhoFinishedCoursesInSessions();
//Make the rows for second table
$rows = [];
foreach ($courses as $course => $data) {
$rows[] = [
$course,
$data['subscribed'],
$data['finished'],
];
}
echo Display::tag('br', '', ['style' => 'margin-top: 25px;']);
echo Display::table($headers[1], $rows, []);
echo Display::tag('br', '', ['style' => 'margin-top: 25px;']);
echo Display::label(get_lang('*: All users, including inactive, are included'), 'warning');
break;
case "report_quarterly_total_disk_usage":
$accessUrlId = api_get_current_access_url_id();
if (api_is_windows_os()) {
$message = get_lang('The space used on disk cannot be measured properly on Windows-based systems.');
} else {
$dir = api_get_path(SYS_PATH);
$du = exec('du -sh '.$dir, $err);
list($size, $none) = explode("\t", $du);
unset($none);
$limit = 0;
if (isset($_configuration[$accessUrlId]['hosting_limit_disk_space'])) {
$limit = $_configuration[$accessUrlId]['hosting_limit_disk_space'];
}
$message = sprintf(get_lang('Total space used by portal %s limit is %s MB'), $size, $limit);
}
echo Display::tag('H5', $message, ['style' => 'margin-bottom: 25px;']);
break;
}

@ -7553,3 +7553,20 @@ function api_get_permission(string $permissionSlug, array $roles): bool
return $permissionService->hasPermission($permissionSlug, $roles);
}
/**
* Calculate the percentage of change between two numbers.
*
* @param int $newValue
* @param int $oldValue
* @return string
*/
function api_calculate_increment_percent(int $newValue, int $oldValue): string
{
if ($oldValue <= 0) {
$result = " - ";
} else {
$result = ' '.round(100 * (($newValue / $oldValue) - 1), 2).' %';
}
return $result;
}

@ -2013,3 +2013,58 @@ function api_get_human_date_time($date, $showTime = true, $humanForm = false)
}
}
}
/**
* Return an array with the start and end dates of a quarter (as in 3 months period).
* If no DateTime is not sent, use the current date.
*
* @param string|null $date (optional) The date or null.
*
* @return array E.G.: ['quarter_start' => '2022-10-11',
* 'quarter_end' => '2022-12-31',
* 'quarter_title' => 'Q4 2022']
*/
function getQuarterDates(string $date = null): array
{
if (empty($date)) {
$date = api_get_utc_datetime();
}
if (strlen($date > 10)) {
$date = substr($date, 0, 10);
}
$month = substr($date, 5, 2);
$year = substr($date, 0, 4);
switch ($month) {
case $month >= 1 && $month <= 3:
$start = "$year-01-01";
$end = "$year-03-31";
$quarter = 1;
break;
case $month >= 4 && $month <= 6:
$start = "$year-04-01";
$end = "$year-06-30";
$quarter = 2;
break;
case $month >= 7 && $month <= 9:
$start = "$year-07-01";
$end = "$year-09-30";
$quarter = 3;
break;
case $month >= 10 && $month <= 12:
$start = "$year-10-01";
$end = "$year-12-31";
$quarter = 4;
break;
default:
// Should never happen
$start = "$year-01-01";
$end = "$year-03-31";
$quarter = 1;
break;
}
return [
'quarter_start' => $start,
'quarter_end' => $end,
'quarter_title' => sprintf(get_lang('Q%s %s'), $quarter, $year),
];
}

@ -5,6 +5,7 @@ use Chamilo\CoreBundle\Component\Utils\ChamiloApi;
use Chamilo\CoreBundle\Entity\MessageRelUser;
use Chamilo\CoreBundle\Entity\UserRelUser;
use Chamilo\CoreBundle\Component\Utils\ActionIcon;
use Chamilo\CoreBundle\ServiceHelper\AccessUrlHelper;
/**
* This class provides some functions for statistics.
@ -37,42 +38,44 @@ class Statistics
/**
* Count courses.
*
* @param string $categoryCode Code of a course category.
* Default: count all courses.
* @param string|null $categoryCode Code of a course category.
* Default: count all courses.
* @param string|null $dateFrom dateFrom
* @param string|null $dateUntil dateUntil
*
* @return int Number of courses counted
* @throws \Doctrine\DBAL\Exception
*/
public static function countCourses($categoryCode = null)
public static function countCourses(string $categoryCode = null, string $dateFrom = null, string $dateUntil = null): int
{
$course_table = Database::get_main_table(TABLE_MAIN_COURSE);
$tblCourseCategory = Database::get_main_table(TABLE_MAIN_CATEGORY);
$access_url_rel_course_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
$courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
$accessUrlRelCourseTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
$urlId = api_get_current_access_url_id();
$categoryJoin = '';
$categoryCondition = '';
if (!empty($categoryCode)) {
//$categoryJoin = " LEFT JOIN $tblCourseCategory course_category ON course.category_id = course_category.id ";
//$categoryCondition = " course_category.code = '".Database::escape_string($categoryCode)."' ";
}
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$sql = "SELECT COUNT(*) AS number
FROM ".$course_table." as c, $access_url_rel_course_table as u
$categoryJoin
WHERE u.c_id = c.id AND access_url_id='".$urlId."'";
FROM ".$courseTable." AS c, $accessUrlRelCourseTable AS u
WHERE u.c_id = c.id AND $accessUrlRelCourseTable='".$urlId."'";
if (isset($categoryCode)) {
$sql .= " AND $categoryCondition";
$sql .= " AND category_code = '".Database::escape_string($categoryCode)."'";
}
} else {
$sql = "SELECT COUNT(*) AS number
FROM $course_table $categoryJoin";
FROM $courseTable AS c
WHERE 1 = 1";
if (isset($categoryCode)) {
$sql .= " WHERE $categoryCondition";
$sql .= " WHERE c.category_code = '".Database::escape_string($categoryCode)."'";
}
}
if (!empty($dateFrom)) {
$dateFrom = api_get_utc_datetime("$dateFrom 00:00:00");
$sql .= " AND c.creation_date >= '$dateFrom' ";
}
if (!empty($dateUntil)) {
$dateUntil = api_get_utc_datetime("$dateUntil 23:59:59");
$sql .= " AND c.creation_date <= '$dateUntil' ";
}
$res = Database::query($sql);
$obj = Database::fetch_object($res);
@ -82,30 +85,52 @@ class Statistics
/**
* Count courses by visibility.
*
* @param int $visibility visibility (0 = closed, 1 = private, 2 = open, 3 = public) all courses
* @param array|null $visibility visibility (0 = closed, 1 = private, 2 = open, 3 = public) all courses
* @param string|null $dateFrom dateFrom
* @param string|null $dateUntil dateUntil
*
* @return int Number of courses counted
* @throws \Doctrine\DBAL\Exception
*/
public static function countCoursesByVisibility($visibility = null)
public static function countCoursesByVisibility(
array $visibility = null,
string $dateFrom = null,
string $dateUntil = null
): int
{
if (!isset($visibility)) {
if (empty($visibility)) {
return 0;
} else {
$visibilityString = '';
$auxArrayVisibility = [];
if (!is_array($visibility)) {
$visibility = [$visibility];
}
foreach ($visibility as $item) {
$auxArrayVisibility[] = (int) $item;
}
$visibilityString = implode(',', $auxArrayVisibility);
}
$course_table = Database::get_main_table(TABLE_MAIN_COURSE);
$access_url_rel_course_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
$courseTable = Database::get_main_table(TABLE_MAIN_COURSE);
$accessUrlRelCourseTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
$urlId = api_get_current_access_url_id();
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$sql = "SELECT COUNT(*) AS number
FROM $course_table as c, $access_url_rel_course_table as u
WHERE u.c_id = c.id AND access_url_id='".$urlId."'";
if (isset($visibility)) {
$sql .= " AND visibility = ".intval($visibility);
}
FROM $courseTable AS c, $accessUrlRelCourseTable AS u
WHERE u.c_id = c.id AND u.access_url_id='".$urlId."'";
} else {
$sql = "SELECT COUNT(*) AS number FROM $course_table ";
if (isset($visibility)) {
$sql .= " WHERE visibility = ".intval($visibility);
}
$sql = "SELECT COUNT(*) AS number
FROM $courseTable AS c
WHERE 1 = 1";
}
$sql .= " AND visibility IN ($visibilityString) ";
if (!empty($dateFrom)) {
$dateFrom = api_get_utc_datetime("$dateFrom 00:00:00");
$sql .= " AND c.creation_date >= '$dateFrom' ";
}
if (!empty($dateUntil)) {
$dateUntil = api_get_utc_datetime("$dateUntil 23:59:59");
$sql .= " AND c.creation_date <= '$dateUntil' ";
}
$res = Database::query($sql);
$obj = Database::fetch_object($res);
@ -149,7 +174,7 @@ class Statistics
$where = implode(' AND ', $conditions);
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$sql = "SELECT COUNT(DISTINCT(u.id)) AS number
FROM $user_table as u
INNER JOIN $access_url_rel_user_table as url ON u.id = url.user_id
@ -203,7 +228,7 @@ class Statistics
$urlId = api_get_current_access_url_id();
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$sql = "SELECT DISTINCT(t.c_id) FROM $table t , $access_url_rel_course_table a
WHERE
t.c_id = a.c_id AND
@ -232,7 +257,7 @@ class Statistics
$table_user = Database::get_main_table(TABLE_MAIN_USER);
$access_url_rel_user_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
$urlId = api_get_current_access_url_id();
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$sql = "SELECT count(default_id) AS total_number_of_items
FROM $track_e_default, $table_user user, $access_url_rel_user_table url
WHERE user.active <> ".USER_SOFT_DELETED." AND
@ -298,7 +323,7 @@ class Statistics
$direction = 'DESC';
}
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$sql = "SELECT
default_event_type as col0,
default_value_type as col1,
@ -522,7 +547,7 @@ class Statistics
$where_url = null;
$now = api_get_utc_datetime();
$where_url_last = ' WHERE login_date > DATE_SUB("'.$now.'",INTERVAL 1 %s)';
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$table_url = ", $access_url_rel_user_table";
$where_url = " WHERE login_user_id=user_id AND access_url_id='".$urlId."'";
$where_url_last = ' AND login_date > DATE_SUB("'.$now.'",INTERVAL 1 %s)';
@ -622,7 +647,7 @@ class Statistics
$urlId = api_get_current_access_url_id();
$table_url = '';
$where_url = '';
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$table_url = ", $access_url_rel_user_table";
$where_url = " AND login_user_id=user_id AND access_url_id='".$urlId."'";
}
@ -712,7 +737,7 @@ class Statistics
$urlId = api_get_current_access_url_id();
$table_url = '';
$where_url = '';
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$table_url = ", $access_url_rel_user_table";
$where_url = " AND login_user_id=user_id AND access_url_id='".$urlId."'";
}
@ -778,7 +803,7 @@ class Statistics
foreach ($tools as $tool) {
$tool_names[$tool] = get_lang(ucfirst($tool), '');
}
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$sql = "SELECT access_tool, count( access_id ) AS number_of_logins
FROM $table t , $access_url_rel_course_table a
WHERE
@ -827,7 +852,7 @@ class Statistics
$table = Database::get_main_table(TABLE_MAIN_COURSE);
$access_url_rel_course_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
$urlId = api_get_current_access_url_id();
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$sql = "SELECT course_language, count( c.code ) AS number_of_courses
FROM $table as c, $access_url_rel_course_table as u
WHERE u.c_id = c.id AND access_url_id='".$urlId."'
@ -858,7 +883,7 @@ class Statistics
$url_condition = null;
$url_condition2 = null;
$table = null;
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$url_condition = ", $access_url_rel_user_table as url WHERE url.user_id=u.id AND access_url_id='".$urlId."'";
$url_condition2 = " AND url.user_id=u.id AND access_url_id='".$urlId."'";
$table = ", $access_url_rel_user_table as url ";
@ -971,7 +996,7 @@ class Statistics
$values = $form->exportValues();
$date_diff = $values['date_diff'];
$table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LASTACCESS);
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$sql = "SELECT * FROM $table t , $access_url_rel_course_table a
WHERE
c_id = a.c_id AND
@ -1050,7 +1075,7 @@ class Statistics
break;
}
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$sql = "SELECT u.lastname, u.firstname, u.username, COUNT(DISTINCT m.id) AS count_message
FROM $messageTable m
INNER JOIN $messageRelUserTable mru ON $joinCondition
@ -1095,7 +1120,7 @@ class Statistics
$access_url_rel_user_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
$urlId = api_get_current_access_url_id();
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$sql = "SELECT lastname, firstname, username, COUNT(friend_user_id) AS count_friend
FROM $access_url_rel_user_table as url, $user_friend_table uf
LEFT JOIN $user_table u
@ -1135,7 +1160,7 @@ class Statistics
$access_url_rel_user_table = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
$urlId = api_get_current_access_url_id();
$total = self::countUsers();
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$table_url = ", $access_url_rel_user_table";
$where_url = " AND login_user_id=user_id AND access_url_id='".$urlId."'";
} else {
@ -1516,7 +1541,7 @@ class Statistics
*
* @return array
*/
private static function getLoginsByDate($startDate, $endDate)
public static function getLoginsByDate(string $startDate, string $endDate): array
{
$startDate = api_get_utc_datetime("$startDate 00:00:00");
$endDate = api_get_utc_datetime("$endDate 23:59:59");
@ -1530,7 +1555,7 @@ class Statistics
$urlJoin = '';
$urlWhere = '';
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$tblUrlUser = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
$urlJoin = "INNER JOIN $tblUrlUser au ON u.id = au.user_id";
@ -1665,4 +1690,88 @@ class Statistics
return $groupedData;
}
/**
* Return de number of certificates generated.
* This function is resource intensive.
* @throws \Doctrine\DBAL\Exception
* @throws Exception
*/
public static function countCertificatesByQuarter(string $dateFrom = null, string $dateUntil = null): int
{
$tableGradebookCertificate = Database::get_main_table(TABLE_MAIN_GRADEBOOK_CERTIFICATE);
$condition = "";
if (!empty($dateFrom) && !empty($dateUntil)) {
$dateFrom = api_get_utc_datetime("$dateFrom 00:00:00");
$dateUntil = api_get_utc_datetime("$dateUntil 23:59:59");
$condition = "WHERE (created_at BETWEEN '$dateFrom' AND '$dateUntil')";
} elseif (!empty($dateFrom)) {
$dateFrom = api_get_utc_datetime("$dateFrom 00:00:00");
$condition = "WHERE created_at >= '$dateFrom'";
} elseif (!empty($dateUntil)) {
$dateUntil = api_get_utc_datetime("$dateUntil 23:59:59");
$condition = "WHERE created_at <= '$dateUntil'";
}
$sql = "
SELECT count(*) AS count
FROM $tableGradebookCertificate
$condition
";
$response = Database::query($sql);
$obj = Database::fetch_object($response);
return $obj->count;
}
/**
* Get the number of logins by dates.
* This function is resource intensive.
* @throws Exception
*/
public static function getSessionsByDuration(string $dateFrom, string $dateUntil): array
{
$results = [
'0' => 0,
'5' => 0,
'10' => 0,
'15' => 0,
'30' => 0,
'60' => 0,
];
if (!empty($dateFrom) && !empty($dateUntil)) {
$table = Database::get_main_table(TABLE_STATISTIC_TRACK_E_LOGIN);
$accessUrlRelUserTable = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
$urlId = api_get_current_access_url_id();
$tableUrl = '';
$whereUrl = '';
$dateFrom = api_get_utc_datetime("$dateFrom 00:00:00");
$dateUntil = api_get_utc_datetime("$dateUntil 23:59:59");
if (AccessUrlHelper::isMultiple()) {
$tableUrl = ", $accessUrlRelUserTable";
$whereUrl = " AND login_user_id = user_id AND access_url_id = $urlId";
}
$sql = "SELECT login_id, TIMESTAMPDIFF(SECOND, login_date, logout_date) AS duration
FROM $table $tableUrl
WHERE login_date >= '$dateFrom'
AND logout_date <= '$dateUntil'
$whereUrl
";
$res = Database::query($sql);
while ($session = Database::fetch_array($res)) {
if ($session['duration'] > 3600) {
$results['60']++;
} elseif ($session['duration'] > 1800) {
$results['30']++;
} elseif ($session['duration'] > 900) {
$results['15']++;
} elseif ($session['duration'] > 600) {
$results['10']++;
} elseif ($session['duration'] > 300) {
$results['5']++;
} else {
$results['0']++;
}
}
}
return $results;
}
}

@ -20,6 +20,7 @@ use CpChart\Image as pImage;
use ExtraField as ExtraFieldModel;
use Chamilo\CoreBundle\Component\Utils\ActionIcon;
use Chamilo\CoreBundle\Component\Utils\StateIcon;
use Chamilo\CoreBundle\ServiceHelper\AccessUrlHelper;
/**
* Class Tracking.
@ -1745,7 +1746,7 @@ class Tracking
$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()) {
if (AccessUrlHelper::isMultiple()) {
$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'";
@ -1827,7 +1828,7 @@ class Tracking
$url_table = null;
$url_condition = null;
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$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'";
@ -3599,7 +3600,7 @@ class Tracking
$tbl_session_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
$tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
$accessUrlEnabled = api_is_multiple_url_enabled();
$accessUrlEnabled = AccessUrlHelper::isMultiple();
$access_url_id = $accessUrlEnabled ? api_get_current_access_url_id() : -1;
$students = [];
@ -3754,7 +3755,7 @@ class Tracking
ON (c.id = sc.c_id)
WHERE sc.user_id = '.$coach_id.' AND sc.status = '.SessionEntity::COURSE_COACH;
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$access_url_id = api_get_current_access_url_id();
if (-1 != $access_url_id) {
$sql = 'SELECT DISTINCT c.code
@ -3792,7 +3793,7 @@ class Tracking
INNER JOIN $tbl_course as course
ON course.id = session_course.c_id";
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$tbl_course_rel_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_COURSE);
$access_url_id = api_get_current_access_url_id();
if (-1 != $access_url_id) {
@ -3815,11 +3816,11 @@ class Tracking
if (!empty($sessionId)) {
$sql .= ' WHERE session_course.session_id='.$sessionId;
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$sql .= ' AND access_url_id = '.$access_url_id;
}
} else {
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$sql .= ' WHERE access_url_id = '.$access_url_id;
}
}
@ -4596,7 +4597,7 @@ class Tracking
$session_id = (int) $session_id;
$urlId = api_get_current_access_url_id();
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$sql = "SELECT c.id, c.code, title
FROM $tbl_course_user cu
INNER JOIN $tbl_course c
@ -4643,7 +4644,7 @@ class Tracking
}
// Get the list of sessions where the user is subscribed as student
if (api_is_multiple_url_enabled()) {
if (AccessUrlHelper::isMultiple()) {
$sql = "SELECT DISTINCT c.code, s.id as session_id, s.title
FROM $tbl_session_course_user cu
INNER JOIN $tbl_access_rel_session a
@ -8134,4 +8135,40 @@ class Tracking
return $exeDate;
}
/**
* Return the total time spent in courses (no the total in platform).
*
* @return int
* @throws \Doctrine\DBAL\Exception
*/
public static function getTotalTimeSpentInCourses(
string $dateFrom = '',
string $dateUntil = ''
): int {
$tableTrackLogin = Database::get_main_table(TABLE_STATISTIC_TRACK_E_COURSE_ACCESS);
$tableUrlRelUser = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
$tableUrl = null;
$urlCondition = null;
$conditionTime = null;
if (AccessUrlHelper::isMultiple()) {
$accessUrlId = api_get_current_access_url_id();
$tableUrl = ", ".$tableUrlRelUser." as url_users";
$urlCondition = " AND u.user_id = url_users.user_id AND access_url_id = $accessUrlId";
}
if (!empty($dateFrom) && !empty($dateUntil)) {
$dateFrom = Database::escape_string($dateFrom);
$dateUntil = Database::escape_string($dateUntil);
$conditionTime = " (login_course_date >= '$dateFrom' AND logout_course_date <= '$dateUntil' ) ";
}
$sql = "SELECT SUM(TIMESTAMPDIFF(HOUR, login_course_date, logout_course_date)) diff
FROM $tableTrackLogin u $tableUrl
WHERE $conditionTime $urlCondition";
$rs = Database::query($sql);
$row = Database::fetch_array($rs, 'ASSOC');
$diff = $row['diff'];
if ($diff >= 0 and !empty($diff)) {
return $diff;
}
return 0;
}
}

@ -3368,27 +3368,33 @@ class UserManager
/**
* Get the total count of users.
*
* @param int $status Status of users to be counted
* @param int $access_url_id Access URL ID (optional)
* @param int $active
* @param ?int $status Status of users to be counted
* @param ?int $access_url_id Access URL ID (optional)
* @param ?int $active
*
* @return mixed Number of users or false on error
* @throws \Doctrine\DBAL\Exception
*/
public static function get_number_of_users($status = 0, $access_url_id = 1, $active = null)
{
$t_u = Database::get_main_table(TABLE_MAIN_USER);
$t_a = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
public static function get_number_of_users(
?int $status = 0,
?int $access_url_id = 1,
?int $active = null,
?string $dateFrom = null,
?string $dateUntil = null
): mixed {
$tableUser = Database::get_main_table(TABLE_MAIN_USER);
$tableAccessUrlRelUser = Database::get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
if (api_is_multiple_url_enabled()) {
$sql = "SELECT count(u.id)
FROM $t_u u
INNER JOIN $t_a url_user
FROM $tableUser u
INNER JOIN $tableAccessUrlRelUser url_user
ON (u.id = url_user.user_id)
WHERE url_user.access_url_id = $access_url_id
";
} else {
$sql = "SELECT count(u.id)
FROM $t_u u
FROM $tableUser u
WHERE 1 = 1 ";
}
@ -3397,11 +3403,20 @@ class UserManager
$sql .= " AND u.status = $status ";
}
if (null !== $active) {
if (isset($active)) {
$active = (int) $active;
$sql .= " AND u.active = $active ";
}
if (!empty($dateFrom)) {
$dateFrom = api_get_utc_datetime("$dateFrom 00:00:00");
$sql .= " AND u.registration_date >= '$dateFrom' ";
}
if (!empty($dateUntil)) {
$dateUntil = api_get_utc_datetime("$dateUntil 23:59:59");
$sql .= " AND u.registration_date <= '$dateUntil' ";
}
$res = Database::query($sql);
if (1 === Database::num_rows($res)) {
return (int) Database::result($res, 0, 0);
@ -6066,4 +6081,106 @@ SQL;
return $url;
}
/**
* Count users in courses and if they have certificate.
* This function is resource intensive.
*
* @return array
* @throws Exception
* @throws \Doctrine\DBAL\Exception
*/
public static function countUsersWhoFinishedCourses()
{
$courses = [];
$currentAccessUrlId = api_get_current_access_url_id();
$sql = "SELECT course.code, cru.user_id
FROM course_rel_user cru
JOIN course ON cru.c_id = course.id
JOIN access_url_rel_user auru on cru.user_id = auru.user_id
JOIN access_url_rel_course ON course.id = access_url_rel_course.c_id
WHERE access_url_rel_course.access_url_id = $currentAccessUrlId
ORDER BY course.code
";
$res = Database::query($sql);
if (Database::num_rows($res) > 0) {
while ($row = Database::fetch_array($res)) {
if (!isset($courses[$row['code']])) {
$courses[$row['code']] = [
'subscribed' => 0,
'finished' => 0,
];
}
$courses[$row['code']]['subscribed']++;
$entityManager = Database::getManager();
$repository = $entityManager->getRepository('ChamiloCoreBundle:GradebookCategory');
//todo check when have more than 1 gradebook
/** @var \Chamilo\CoreBundle\Entity\GradebookCategory $gradebook */
$gradebook = $repository->findOneBy(['courseCode' => $row['code']]);
if (!empty($gradebook)) {
$finished = 0;
$gb = Category::createCategoryObjectFromEntity($gradebook);
$finished = $gb->is_certificate_available($row['user_id']);
if (!empty($finished)) {
$courses[$row['code']]['finished']++;
}
}
}
}
return $courses;
}
/**
* Count users in sessions and if they have certificate.
* This function is resource intensive.
*
* @return array
* @throws Exception
* @throws \Doctrine\DBAL\Exception
*/
public static function countUsersWhoFinishedCoursesInSessions()
{
$coursesInSessions = [];
$currentAccessUrlId = api_get_current_access_url_id();
$sql = "SELECT course.code, srcru.session_id, srcru.user_id, session.title
FROM session_rel_course_rel_user srcru
JOIN course ON srcru.c_id = course.id
JOIN access_url_rel_session aurs on srcru.session_id = aurs.session_id
JOIN session ON srcru.session_id = session.id
WHERE aurs.access_url_id = $currentAccessUrlId
ORDER BY course.code, session.title
";
$res = Database::query($sql);
if (Database::num_rows($res) > 0) {
while ($row = Database::fetch_array($res)) {
$index = $row['code'].' ('.$row['title'].')';
if (!isset($coursesInSessions[$index])) {
$coursesInSessions[$index] = [
'subscribed' => 0,
'finished' => 0,
];
}
$coursesInSessions[$index]['subscribed']++;
$entityManager = Database::getManager();
$repository = $entityManager->getRepository('ChamiloCoreBundle:GradebookCategory');
/** @var \Chamilo\CoreBundle\Entity\GradebookCategory $gradebook */
$gradebook = $repository->findOneBy(
[
'courseCode' => $row['code'],
'sessionId' => $row['session_id'],
]
);
if (!empty($gradebook)) {
$finished = 0;
$gb = Category::createCategoryObjectFromEntity($gradebook);
$finished = $gb->is_certificate_available($row['user_id']);
if (!empty($finished)) {
$coursesInSessions[$index]['finished']++;
}
}
}
}
return $coursesInSessions;
}
}

@ -122,11 +122,11 @@ class BlockGlobalInfo extends Block
[get_lang('Number of active users'), '<a href="'.$path.'admin/user_list.php?keyword_firstname=&amp;keyword_lastname=&amp;keyword_username=&amp;keyword_email=&amp;keyword_officialcode=&amp;keyword_status=%25&amp;keyword_active=1&amp;submit=&amp;_qf__advanced_search=">'.Statistics::countUsers(null, null, null, true).'</a>'],
// Check number of courses
[get_lang('Total number of courses'), '<a href="'.$path.'admin/course_list.php">'.Statistics::countCourses().'</a>'],
[get_lang('Number of public courses'), '<a href="'.$path.'admin/course_list.php?keyword_code=&amp;keyword_title=&amp;keyword_language=%25&amp;keyword_category=&amp;keyword_visibility='.COURSE_VISIBILITY_OPEN_WORLD.'&amp;keyword_subscribe=%25&amp;keyword_unsubscribe=%25&amp;submit=&amp;_qf__advanced_course_search=">'.Statistics::countCoursesByVisibility(COURSE_VISIBILITY_OPEN_WORLD).'</a>'],
[get_lang('Number of open courses'), '<a href="'.$path.'admin/course_list.php?keyword_code=&amp;keyword_title=&amp;keyword_language=%25&amp;keyword_category=&amp;keyword_visibility='.COURSE_VISIBILITY_OPEN_PLATFORM.'&amp;keyword_subscribe=%25&amp;keyword_unsubscribe=%25&amp;submit=&amp;_qf__advanced_course_search=">'.Statistics::countCoursesByVisibility(COURSE_VISIBILITY_OPEN_PLATFORM).'</a>'],
[get_lang('Number of private courses'), '<a href="'.$path.'admin/course_list.php?keyword_code=&amp;keyword_title=&amp;keyword_language=%25&amp;keyword_category=&amp;keyword_visibility='.COURSE_VISIBILITY_REGISTERED.'&amp;keyword_subscribe=%25&amp;keyword_unsubscribe=%25&amp;submit=&amp;_qf__advanced_course_search=">'.Statistics::countCoursesByVisibility(COURSE_VISIBILITY_REGISTERED).'</a>'],
[get_lang('Number of closed courses'), '<a href="'.$path.'admin/course_list.php?keyword_code=&amp;keyword_title=&amp;keyword_language=%25&amp;keyword_category=&amp;keyword_visibility='.COURSE_VISIBILITY_CLOSED.'&amp;keyword_subscribe=%25&amp;keyword_unsubscribe=%25&amp;submit=&amp;_qf__advanced_course_search=">'.Statistics::countCoursesByVisibility(COURSE_VISIBILITY_CLOSED).'</a>'],
[get_lang('Number of hidden courses'), '<a href="'.$path.'admin/course_list.php?keyword_code=&amp;keyword_title=&amp;keyword_language=%25&amp;keyword_category=&amp;keyword_visibility='.COURSE_VISIBILITY_HIDDEN.'&amp;keyword_subscribe=%25&amp;keyword_unsubscribe=%25&amp;submit=&amp;_qf__advanced_course_search=">'.Statistics::countCoursesByVisibility(COURSE_VISIBILITY_HIDDEN).'</a>'],
[get_lang('Number of public courses'), '<a href="'.$path.'admin/course_list.php?keyword_code=&amp;keyword_title=&amp;keyword_language=%25&amp;keyword_category=&amp;keyword_visibility='.COURSE_VISIBILITY_OPEN_WORLD.'&amp;keyword_subscribe=%25&amp;keyword_unsubscribe=%25&amp;submit=&amp;_qf__advanced_course_search=">'.Statistics::countCoursesByVisibility([COURSE_VISIBILITY_OPEN_WORLD]).'</a>'],
[get_lang('Number of open courses'), '<a href="'.$path.'admin/course_list.php?keyword_code=&amp;keyword_title=&amp;keyword_language=%25&amp;keyword_category=&amp;keyword_visibility='.COURSE_VISIBILITY_OPEN_PLATFORM.'&amp;keyword_subscribe=%25&amp;keyword_unsubscribe=%25&amp;submit=&amp;_qf__advanced_course_search=">'.Statistics::countCoursesByVisibility([COURSE_VISIBILITY_OPEN_PLATFORM]).'</a>'],
[get_lang('Number of private courses'), '<a href="'.$path.'admin/course_list.php?keyword_code=&amp;keyword_title=&amp;keyword_language=%25&amp;keyword_category=&amp;keyword_visibility='.COURSE_VISIBILITY_REGISTERED.'&amp;keyword_subscribe=%25&amp;keyword_unsubscribe=%25&amp;submit=&amp;_qf__advanced_course_search=">'.Statistics::countCoursesByVisibility([COURSE_VISIBILITY_REGISTERED]).'</a>'],
[get_lang('Number of closed courses'), '<a href="'.$path.'admin/course_list.php?keyword_code=&amp;keyword_title=&amp;keyword_language=%25&amp;keyword_category=&amp;keyword_visibility='.COURSE_VISIBILITY_CLOSED.'&amp;keyword_subscribe=%25&amp;keyword_unsubscribe=%25&amp;submit=&amp;_qf__advanced_course_search=">'.Statistics::countCoursesByVisibility([COURSE_VISIBILITY_CLOSED]).'</a>'],
[get_lang('Number of hidden courses'), '<a href="'.$path.'admin/course_list.php?keyword_code=&amp;keyword_title=&amp;keyword_language=%25&amp;keyword_category=&amp;keyword_visibility='.COURSE_VISIBILITY_HIDDEN.'&amp;keyword_subscribe=%25&amp;keyword_unsubscribe=%25&amp;submit=&amp;_qf__advanced_course_search=">'.Statistics::countCoursesByVisibility([COURSE_VISIBILITY_HIDDEN]).'</a>'],
];
}
}

Loading…
Cancel
Save