Skip to content

Commit

Permalink
Merge branch 'MDL-67752-master-userstats' of git://github.com/mudrd8m…
Browse files Browse the repository at this point in the history
…z/moodle
  • Loading branch information
stronk7 committed Mar 11, 2020
2 parents a17bdbd + 4e907e7 commit 0b698cb
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 18 deletions.
73 changes: 55 additions & 18 deletions course/lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -2612,31 +2612,68 @@ function update_course($data, $editoroptions = NULL) {
}

/**
* Average number of participants
* @return integer
* Calculate the average number of enrolled participants per course.
*
* This is intended for statistics purposes during the site registration. Only visible courses are taken into account.
* Front page enrolments are excluded.
*
* @param bool $onlyactive Consider only active enrolments in enabled plugins and obey the enrolment time restrictions.
* @param int $lastloginsince If specified, count only users who logged in after this timestamp.
* @return float
*/
function average_number_of_participants() {
global $DB, $SITE;
function average_number_of_participants(bool $onlyactive = false, int $lastloginsince = null): float {
global $DB;

//count total of enrolments for visible course (except front page)
$sql = 'SELECT COUNT(*) FROM (
SELECT DISTINCT ue.userid, e.courseid
FROM {user_enrolments} ue, {enrol} e, {course} c
WHERE ue.enrolid = e.id
AND e.courseid <> :siteid
AND c.id = e.courseid
AND c.visible = 1) total';
$params = array('siteid' => $SITE->id);
$enrolmenttotal = $DB->count_records_sql($sql, $params);
$params = [
'siteid' => SITEID,
];

$sql = "SELECT DISTINCT ue.userid, e.courseid
FROM {user_enrolments} ue
JOIN {enrol} e ON e.id = ue.enrolid
JOIN {course} c ON c.id = e.courseid ";

//count total of visible courses (minus front page)
$coursetotal = $DB->count_records('course', array('visible' => 1));
$coursetotal = $coursetotal - 1 ;
if ($onlyactive || $lastloginsince) {
$sql .= "JOIN {user} u ON u.id = ue.userid ";
}

$sql .= "WHERE e.courseid <> :siteid
AND c.visible = 1 ";

if ($onlyactive) {
$sql .= "AND ue.status = :active
AND e.status = :enabled
AND ue.timestart < :now1
AND (ue.timeend = 0 OR ue.timeend > :now2) ";

// Same as in the enrollib - the rounding should help caching in the database.
$now = round(time(), -2);

$params += [
'active' => ENROL_USER_ACTIVE,
'enabled' => ENROL_INSTANCE_ENABLED,
'now1' => $now,
'now2' => $now,
];
}

if ($lastloginsince) {
$sql .= "AND u.lastlogin > :lastlogin ";
$params['lastlogin'] = $lastloginsince;
}

$sql = "SELECT COUNT(*)
FROM ($sql) total";

$enrolmenttotal = $DB->count_records_sql($sql, $params);

// Get the number of visible courses (exclude the front page).
$coursetotal = $DB->count_records('course', ['visible' => 1]);
$coursetotal = $coursetotal - 1;

//average of enrolment
if (empty($coursetotal)) {
$participantaverage = 0;

} else {
$participantaverage = $enrolmenttotal / $coursetotal;
}
Expand Down
74 changes: 74 additions & 0 deletions course/tests/courselib_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -6945,4 +6945,78 @@ public function test_course_allowed_module() {
// Manager has permissions.
$this->assertTrue(course_allowed_module($course, 'assign', $manager));
}

/**
* Test the {@link average_number_of_participants()} function.
*/
public function test_average_number_of_participants() {
global $DB;
$this->resetAfterTest(true);

$generator = $this->getDataGenerator();
$now = time();

// If there are no courses, expect zero number of participants per course.
$this->assertEquals(0, average_number_of_participants());

$c1 = $generator->create_course();
$c2 = $generator->create_course();

// If there are no users, expect zero number of participants per course.
$this->assertEquals(0, average_number_of_participants());

$t1 = $generator->create_user(['lastlogin' => $now]);
$s1 = $generator->create_user(['lastlogin' => $now]);
$s2 = $generator->create_user(['lastlogin' => $now - WEEKSECS]);
$s3 = $generator->create_user(['lastlogin' => $now - WEEKSECS]);
$s4 = $generator->create_user(['lastlogin' => $now - YEARSECS]);

// We have courses, we have users, but no enrolments yet.
$this->assertEquals(0, average_number_of_participants());

// Front page enrolments are ignored.
$generator->enrol_user($t1->id, SITEID, 'teacher');
$this->assertEquals(0, average_number_of_participants());

// The teacher enrolled into one of the two courses.
$generator->enrol_user($t1->id, $c1->id, 'editingteacher');
$this->assertEquals(0.5, average_number_of_participants());

// The teacher enrolled into both courses.
$generator->enrol_user($t1->id, $c2->id, 'editingteacher');
$this->assertEquals(1, average_number_of_participants());

// Student 1 enrolled in the Course 1 only.
$generator->enrol_user($s1->id, $c1->id, 'student');
$this->assertEquals(1.5, average_number_of_participants());

// Student 2 enrolled in both courses, but the enrolment in the Course 2 not active yet (enrolment starts in the future).
$generator->enrol_user($s2->id, $c1->id, 'student');
$generator->enrol_user($s2->id, $c2->id, 'student', 'manual', $now + WEEKSECS);
$this->assertEquals(2.5, average_number_of_participants());
$this->assertEquals(2, average_number_of_participants(true));

// Student 3 enrolled in the Course 1, but the enrolment already expired.
$generator->enrol_user($s3->id, $c1->id, 'student', 'manual', 0, $now - YEARSECS);
$this->assertEquals(3, average_number_of_participants());
$this->assertEquals(2, average_number_of_participants(true));

// Student 4 enrolled in both courses, but the enrolment has been suspended.
$generator->enrol_user($s4->id, $c1->id, 'student', 'manual', 0, 0, ENROL_USER_SUSPENDED);
$generator->enrol_user($s4->id, $c2->id, 'student', 'manual', $now - DAYSECS, $now + YEARSECS, ENROL_USER_SUSPENDED);
$this->assertEquals(4, average_number_of_participants());
$this->assertEquals(2, average_number_of_participants(true));

// Consider only t1 and s1 who logged in recently.
$this->assertEquals(1.5, average_number_of_participants(false, $now - DAYSECS));

// Consider only t1, s1, s2 and s3 who logged in in recent weeks.
$this->assertEquals(3, average_number_of_participants(false, $now - 4 * WEEKSECS));

// Hidden courses are excluded from stats.
$DB->set_field('course', 'visible', 0, ['id' => $c1->id]);
$this->assertEquals(3, average_number_of_participants());
$this->assertEquals(1, average_number_of_participants(true));
}

}
2 changes: 2 additions & 0 deletions lang/en/hub.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['activeparticipantnumberaverage'] = 'Average number of recently active participants ({$a})';
$string['activeusersnumber'] = 'Number of recently active users ({$a})';
$string['analyticsactions'] = 'Number of actions taken on generated predictions ({$a})';
$string['analyticsactionsnotuseful'] = 'Number of actions marking a prediction as not useful ({$a})';
$string['analyticsenabledmodels'] = 'Number of enabled prediction models ({$a})';
Expand Down
7 changes: 7 additions & 0 deletions lib/classes/hub/registration.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ class registration {
],
// Analytics stats added in Moodle 3.7.
2019022200 => ['analyticsenabledmodels', 'analyticspredictions', 'analyticsactions', 'analyticsactionsnotuseful'],
// Active users stats added in Moodle 3.9.
2020022600 => ['activeusers', 'activeparticipantnumberaverage'],
];

/** @var Site privacy: not displayed */
Expand Down Expand Up @@ -168,13 +170,15 @@ public static function get_site_info($defaults = []) {
// Statistical data.
$siteinfo['courses'] = $DB->count_records('course') - 1;
$siteinfo['users'] = $DB->count_records('user', array('deleted' => 0));
$siteinfo['activeusers'] = $DB->count_records_select('user', 'deleted = ? AND lastlogin > ?', [0, time() - DAYSECS * 30]);
$siteinfo['enrolments'] = $DB->count_records('role_assignments');
$siteinfo['posts'] = $DB->count_records('forum_posts');
$siteinfo['questions'] = $DB->count_records('question');
$siteinfo['resources'] = $DB->count_records('resource');
$siteinfo['badges'] = $DB->count_records_select('badge', 'status <> ' . BADGE_STATUS_ARCHIVED);
$siteinfo['issuedbadges'] = $DB->count_records('badge_issued');
$siteinfo['participantnumberaverage'] = average_number_of_participants();
$siteinfo['activeparticipantnumberaverage'] = average_number_of_participants(true, time() - DAYSECS * 30);
$siteinfo['modulenumberaverage'] = average_number_of_courses_modules();

// Version and url.
Expand Down Expand Up @@ -229,6 +233,7 @@ public static function get_stats_summary($siteinfo) {
'moodlerelease' => get_string('sitereleasenum', 'hub', $moodlerelease),
'courses' => get_string('coursesnumber', 'hub', $siteinfo['courses']),
'users' => get_string('usersnumber', 'hub', $siteinfo['users']),
'activeusers' => get_string('activeusersnumber', 'hub', $siteinfo['activeusers']),
'enrolments' => get_string('roleassignmentsnumber', 'hub', $siteinfo['enrolments']),
'posts' => get_string('postsnumber', 'hub', $siteinfo['posts']),
'questions' => get_string('questionsnumber', 'hub', $siteinfo['questions']),
Expand All @@ -237,6 +242,8 @@ public static function get_stats_summary($siteinfo) {
'issuedbadges' => get_string('issuedbadgesnumber', 'hub', $siteinfo['issuedbadges']),
'participantnumberaverage' => get_string('participantnumberaverage', 'hub',
format_float($siteinfo['participantnumberaverage'], 2)),
'activeparticipantnumberaverage' => get_string('activeparticipantnumberaverage', 'hub',
format_float($siteinfo['activeparticipantnumberaverage'], 2)),
'modulenumberaverage' => get_string('modulenumberaverage', 'hub',
format_float($siteinfo['modulenumberaverage'], 2)),
'mobileservicesenabled' => get_string('mobileservicesenabled', 'hub', $mobileservicesenabled),
Expand Down

0 comments on commit 0b698cb

Please sign in to comment.