Skip to content

Commit fcef975

Browse files
Statistics: Include tracking of users of a course who are not subscribed - refs #5958
1 parent ae259f4 commit fcef975

File tree

2 files changed

+116
-0
lines changed

2 files changed

+116
-0
lines changed

public/main/admin/statistics/index.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,49 @@
785785
}
786786
// courses for each course category
787787
$content .= Statistics::printStats(get_lang('Courses'), $courses);
788+
789+
$content .= '
790+
<button class="btn btn--info mb-3" onclick="toggleNonRegisteredUsers()">
791+
'.get_lang('Show/Hide users active in open courses (not enrolled)').'
792+
</button>
793+
794+
<div id="non-registered-users-block" style="display: none; margin-top: 10px;">
795+
';
796+
797+
$sessionId = api_get_session_id();
798+
$userList = Statistics::getUsersWithActivityButNotRegistered($sessionId);
799+
800+
if (!empty($userList)) {
801+
$content .= Display::page_subheader2(get_lang('Users active in open courses (not enrolled)'));
802+
$content .= Display::tag('p', get_lang('The following users have accessed one or more courses without being officially registered. They generated activity in open courses but are not listed in the course subscription tables.'));
803+
$table = new HTML_Table(['class' => 'table table-hover table-striped data_table']);
804+
$table->setHeaderContents(0, 0, get_lang('Name'));
805+
$table->setHeaderContents(0, 1, get_lang('Course'));
806+
$table->setHeaderContents(0, 2, get_lang('Last access'));
807+
$row = 1;
808+
foreach ($userList as $user) {
809+
$name = Display::tag('strong', $user['firstname'].' '.$user['lastname']);
810+
$course = Display::tag('em', $user['courseTitle'].' ('.$user['courseCode'].')');
811+
$access = Security::remove_XSS($user['lastAccess']);
812+
813+
$table->setCellContents($row, 0, $name);
814+
$table->setCellContents($row, 1, $course);
815+
$table->setCellContents($row, 2, $access);
816+
$row++;
817+
}
818+
$content .= $table->toHtml();
819+
} else {
820+
$content .= Display::tag('p', get_lang('No users found with activity in open courses without enrollment.'));
821+
}
822+
$content .= '</div>';
823+
$content .= '
824+
<script>
825+
function toggleNonRegisteredUsers() {
826+
const block = document.getElementById("non-registered-users-block");
827+
block.style.display = block.style.display === "none" ? "block" : "none";
828+
}
829+
</script>';
830+
788831
break;
789832
case 'tools':
790833
$content .= '<canvas class="col-md-12" id="canvas" height="300px" style="margin-bottom: 20px"></canvas>';

public/main/inc/lib/statistics.lib.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22
/* For licensing terms, see /license.txt */
33

44
use Chamilo\CoreBundle\Component\Utils\ChamiloApi;
5+
use Chamilo\CoreBundle\Entity\CourseRelUser;
56
use Chamilo\CoreBundle\Entity\MessageRelUser;
67
use Chamilo\CoreBundle\Entity\ResourceLink;
8+
use Chamilo\CoreBundle\Entity\TrackEAccess;
9+
use Chamilo\CoreBundle\Entity\Course;
10+
use Chamilo\CoreBundle\Entity\User;
711
use Chamilo\CoreBundle\Entity\UserRelUser;
812
use Chamilo\CoreBundle\Component\Utils\ActionIcon;
913
use Chamilo\CoreBundle\Framework\Container;
@@ -1944,4 +1948,73 @@ public static function getUnsubscriptionsByDay(string $startDate, string $endDat
19441948
'eventType2' => ParameterType::STRING,
19451949
])->fetchAllAssociative();
19461950
}
1951+
1952+
/**
1953+
* Returns users who have activity in open courses without being officially enrolled.
1954+
*/
1955+
public static function getUsersWithActivityButNotRegistered(int $sessionId = 0): array
1956+
{
1957+
$em = Database::getManager();
1958+
1959+
$qb = $em->createQueryBuilder();
1960+
$qb->select('t.accessUserId AS userId, t.cId AS courseId, MAX(t.accessDate) AS lastAccess')
1961+
->from(TrackEAccess::class, 't')
1962+
->where('t.accessUserId IS NOT NULL')
1963+
->andWhere('t.cId IS NOT NULL')
1964+
->groupBy('t.accessUserId, t.cId');
1965+
1966+
if ($sessionId > 0) {
1967+
$qb->andWhere('t.sessionId = :sessionId')
1968+
->setParameter('sessionId', $sessionId);
1969+
}
1970+
1971+
$results = $qb->getQuery()->getArrayResult();
1972+
1973+
$nonRegistered = [];
1974+
1975+
foreach ($results as $row) {
1976+
$userId = $row['userId'];
1977+
$courseId = $row['courseId'];
1978+
1979+
$course = $em->getRepository(Course::class)->find($courseId);
1980+
if (!$course) {
1981+
continue;
1982+
}
1983+
1984+
if (!\in_array($course->getVisibility(), [Course::OPEN_PLATFORM, Course::OPEN_WORLD], true)) {
1985+
continue;
1986+
}
1987+
1988+
$isRegistered = $em->createQueryBuilder()
1989+
->select('1')
1990+
->from(CourseRelUser::class, 'cu')
1991+
->where('cu.user = :userId AND cu.course = :courseId')
1992+
->setParameter('userId', $userId)
1993+
->setParameter('courseId', $courseId);
1994+
1995+
if ($sessionId > 0) {
1996+
$isRegistered->andWhere('cu.session = :sessionId')
1997+
->setParameter('sessionId', $sessionId);
1998+
}
1999+
2000+
if (empty($isRegistered->getQuery()->getResult())) {
2001+
$user = $em->getRepository(User::class)->find($userId);
2002+
if (!$user) {
2003+
continue;
2004+
}
2005+
2006+
$nonRegistered[] = [
2007+
'id' => $user->getId(),
2008+
'firstname' => $user->getFirstname(),
2009+
'lastname' => $user->getLastname(),
2010+
'email' => $user->getEmail(),
2011+
'courseTitle' => $course->getTitle(),
2012+
'courseCode' => $course->getCode(),
2013+
'lastAccess' => $row['lastAccess'] ? (new \DateTime($row['lastAccess']))->format('Y-m-d H:i:s') : '',
2014+
];
2015+
}
2016+
}
2017+
2018+
return $nonRegistered;
2019+
}
19472020
}

0 commit comments

Comments
 (0)