diff --git a/composer.json b/composer.json
index 1d4caaf729..1ed2adea4c 100755
--- a/composer.json
+++ b/composer.json
@@ -181,7 +181,8 @@
"symfony/flex": true,
"dealerdirect/phpcodesniffer-composer-installer": true,
"symfony/runtime": true
- }
+ },
+ "process-timeout": 900
},
"require-dev": {
"behat/behat": "^3.10",
diff --git a/public/main/admin/statistics/index.php b/public/main/admin/statistics/index.php
index 602e99ee84..b5d62d9667 100644
--- a/public/main/admin/statistics/index.php
+++ b/public/main/admin/statistics/index.php
@@ -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[] .= '';
+ $htmlHeadXtra[] .= '';
+ $htmlHeadXtra[] .= '';
+ $htmlHeadXtra[] .= '';
+ $htmlHeadXtra[] .= '';
+ $htmlHeadXtra[] .= '';
+ if (api_get_current_access_url_id() === 1) {
+ $htmlHeadXtra[] .= '';
+ }
+ $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);
diff --git a/public/main/inc/ajax/statistics.ajax.php b/public/main/inc/ajax/statistics.ajax.php
index 83ba57dcf2..7504b8dbdf 100644
--- a/public/main/inc/ajax/statistics.ajax.php
+++ b/public/main/inc/ajax/statistics.ajax.php
@@ -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′',
+ $sessionsDuration5PreQuarter['0'],
+ $sessionsDuration4PreQuarter['0'],
+ $sessionsDuration3PreQuarter['0'],
+ $sessionsDuration2PreQuarter['0'],
+ $sessionsDuration1PreQuarter['0'],
+ $percentIncrementSessionDuration0,
+ $sessionsDurationCurrentQuarter['0'],
+ ];
+ $rows[] = [
+ '6-10′',
+ $sessionsDuration5PreQuarter['5'],
+ $sessionsDuration4PreQuarter['5'],
+ $sessionsDuration3PreQuarter['5'],
+ $sessionsDuration2PreQuarter['5'],
+ $sessionsDuration1PreQuarter['5'],
+ $percentIncrementSessionDuration5,
+ $sessionsDurationCurrentQuarter['5'],
+ ];
+ $rows[] = [
+ '11-15′',
+ $sessionsDuration5PreQuarter['10'],
+ $sessionsDuration4PreQuarter['10'],
+ $sessionsDuration3PreQuarter['10'],
+ $sessionsDuration2PreQuarter['10'],
+ $sessionsDuration1PreQuarter['10'],
+ $percentIncrementSessionDuration10,
+ $sessionsDurationCurrentQuarter['10'],
+ ];
+ $rows[] = [
+ '16-30′',
+ $sessionsDuration5PreQuarter['15'],
+ $sessionsDuration4PreQuarter['15'],
+ $sessionsDuration3PreQuarter['15'],
+ $sessionsDuration2PreQuarter['15'],
+ $sessionsDuration1PreQuarter['15'],
+ $percentIncrementSessionDuration15,
+ $sessionsDurationCurrentQuarter['15'],
+ ];
+ $rows[] = [
+ '31-60′',
+ $sessionsDuration5PreQuarter['30'],
+ $sessionsDuration4PreQuarter['30'],
+ $sessionsDuration3PreQuarter['30'],
+ $sessionsDuration2PreQuarter['30'],
+ $sessionsDuration1PreQuarter['30'],
+ $percentIncrementSessionDuration30,
+ $sessionsDurationCurrentQuarter['30'],
+ ];
+ $rows[] = [
+ '60-∞′',
+ $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;
}
diff --git a/public/main/inc/lib/api.lib.php b/public/main/inc/lib/api.lib.php
index 46b8aeb33b..971bfd81a8 100644
--- a/public/main/inc/lib/api.lib.php
+++ b/public/main/inc/lib/api.lib.php
@@ -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;
+}
diff --git a/public/main/inc/lib/internationalization.lib.php b/public/main/inc/lib/internationalization.lib.php
index 04a822126c..4424f9add0 100644
--- a/public/main/inc/lib/internationalization.lib.php
+++ b/public/main/inc/lib/internationalization.lib.php
@@ -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),
+ ];
+}
diff --git a/public/main/inc/lib/statistics.lib.php b/public/main/inc/lib/statistics.lib.php
index 4e31d1c097..d7c8589a5c 100644
--- a/public/main/inc/lib/statistics.lib.php
+++ b/public/main/inc/lib/statistics.lib.php
@@ -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;
+ }
}
diff --git a/public/main/inc/lib/tracking.lib.php b/public/main/inc/lib/tracking.lib.php
index 8373faa687..5649073551 100644
--- a/public/main/inc/lib/tracking.lib.php
+++ b/public/main/inc/lib/tracking.lib.php
@@ -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;
+ }
}
diff --git a/public/main/inc/lib/usermanager.lib.php b/public/main/inc/lib/usermanager.lib.php
index a25621e931..0b126ae8ec 100644
--- a/public/main/inc/lib/usermanager.lib.php
+++ b/public/main/inc/lib/usermanager.lib.php
@@ -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;
+ }
+
}
diff --git a/public/plugin/dashboard/block_global_info/block_global_info.class.php b/public/plugin/dashboard/block_global_info/block_global_info.class.php
index b66e3408a2..f874722542 100644
--- a/public/plugin/dashboard/block_global_info/block_global_info.class.php
+++ b/public/plugin/dashboard/block_global_info/block_global_info.class.php
@@ -122,11 +122,11 @@ class BlockGlobalInfo extends Block
[get_lang('Number of active users'), ''.Statistics::countUsers(null, null, null, true).''],
// Check number of courses
[get_lang('Total number of courses'), ''.Statistics::countCourses().''],
- [get_lang('Number of public courses'), ''.Statistics::countCoursesByVisibility(COURSE_VISIBILITY_OPEN_WORLD).''],
- [get_lang('Number of open courses'), ''.Statistics::countCoursesByVisibility(COURSE_VISIBILITY_OPEN_PLATFORM).''],
- [get_lang('Number of private courses'), ''.Statistics::countCoursesByVisibility(COURSE_VISIBILITY_REGISTERED).''],
- [get_lang('Number of closed courses'), ''.Statistics::countCoursesByVisibility(COURSE_VISIBILITY_CLOSED).''],
- [get_lang('Number of hidden courses'), ''.Statistics::countCoursesByVisibility(COURSE_VISIBILITY_HIDDEN).''],
+ [get_lang('Number of public courses'), ''.Statistics::countCoursesByVisibility([COURSE_VISIBILITY_OPEN_WORLD]).''],
+ [get_lang('Number of open courses'), ''.Statistics::countCoursesByVisibility([COURSE_VISIBILITY_OPEN_PLATFORM]).''],
+ [get_lang('Number of private courses'), ''.Statistics::countCoursesByVisibility([COURSE_VISIBILITY_REGISTERED]).''],
+ [get_lang('Number of closed courses'), ''.Statistics::countCoursesByVisibility([COURSE_VISIBILITY_CLOSED]).''],
+ [get_lang('Number of hidden courses'), ''.Statistics::countCoursesByVisibility([COURSE_VISIBILITY_HIDDEN]).''],
];
}
}