Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Admin: Add course/session report with links to tools - refs #2034 #6037

Merged
merged 4 commits into from
Mar 22, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Admin: Add course/session report with links to tools - refs #2034
christianbeeznest committed Jan 18, 2025
commit 3f27434fc863b28484edb184d96c63612ed0fbc5
61 changes: 61 additions & 0 deletions public/main/admin/statistics/index.php
Original file line number Diff line number Diff line change
@@ -334,6 +334,7 @@
get_lang('Courses') => [
'report=courses' => get_lang('Courses'),
'report=tools' => get_lang('Tools access'),
'report=tool_usage' => get_lang('Tool Usage Report'),
'report=courselastvisit' => get_lang('Latest access'),
'report=coursebylanguage' => get_lang('Number of courses by language'),
],
@@ -708,6 +709,66 @@
$content .= '<canvas class="col-md-12" id="canvas" height="300px" style="margin-bottom: 20px"></canvas>';
$content .= Statistics::printToolStats();
break;
case 'tool_usage':
$courseTools = Statistics::getAvailableTools();

if (empty($courseTools)) {
$content .= '<div class="alert alert-info">'.get_lang('No tools available for this report').'</div>';
break;
}

$form = new FormValidator('tool_usage', 'get');
$form->addHeader(get_lang('Tool Usage Report'));
$form->addSelect(
'tool_ids',
get_lang('Select Tools'),
$courseTools,
['multiple' => true, 'required' => true]
);
$form->addButtonSearch(get_lang('Generate Report'));
$form->addHidden('report', 'tool_usage');

$content .= $form->returnForm();

if ($form->validate()) {
$values = $form->getSubmitValues();
$toolIds = $values['tool_ids'];
$reportData = Statistics::getToolUsageReportByTools($toolIds);

$table = new HTML_Table(['class' => 'table table-hover table-striped data_table stats_table']);
$headers = [
get_lang('Tool'),
get_lang('Session'),
get_lang('Course'),
get_lang('Items Count'),
get_lang('Last Updated'),
];
$row = 0;

foreach ($headers as $index => $header) {
$table->setHeaderContents($row, $index, $header);
}
$row++;

foreach ($reportData as $data) {
$linkHtml = $data['link'] !== '-'
? sprintf(
'<a href="%s" class="text-blue-500 underline hover:text-blue-700" target="_self">%s</a>',
$data['link'],
htmlspecialchars($data['tool_name'])
)
: htmlspecialchars($data['tool_name']);

$table->setCellContents($row, 0, $linkHtml);
$table->setCellContents($row, 1, htmlspecialchars($data['session_name']));
$table->setCellContents($row, 2, htmlspecialchars($data['course_name']));
$table->setCellContents($row, 3, (int) $data['resource_count']);
$table->setCellContents($row, 4, htmlspecialchars($data['last_updated']));
$row++;
}
$content .= $table->toHtml();
}
break;
case 'coursebylanguage':
$content .= '<canvas class="col-md-12" id="canvas" height="300px" style="margin-bottom: 20px"></canvas>';
$result = Statistics::printCourseByLanguageStats();
24 changes: 24 additions & 0 deletions public/main/inc/lib/statistics.lib.php
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@

use Chamilo\CoreBundle\Component\Utils\ChamiloApi;
use Chamilo\CoreBundle\Entity\MessageRelUser;
use Chamilo\CoreBundle\Entity\ResourceLink;
use Chamilo\CoreBundle\Entity\UserRelUser;
use Chamilo\CoreBundle\Component\Utils\ActionIcon;

@@ -1665,4 +1666,27 @@ public static function groupByMonth(array $registrations): array

return $groupedData;
}

/**
* Retrieves the available tools using the repository.
*/
public static function getAvailableTools(): array
{
$em = Database::getManager();
$repo = $em->getRepository(ResourceLink::class);

return $repo->getAvailableTools();
}

/**
* Generates a report of tool usage based on the provided tool IDs.
*/
public static function getToolUsageReportByTools(array $toolIds): array
{
$em = Database::getManager();
$repo = $em->getRepository(ResourceLink::class);

return $repo->getToolUsageReportByTools($toolIds);
}

}
115 changes: 115 additions & 0 deletions src/CoreBundle/Repository/ResourceLinkRepository.php
Original file line number Diff line number Diff line change
@@ -18,6 +18,23 @@

class ResourceLinkRepository extends SortableRepository
{
private array $toolList = [
'course_description' => '/main/course_description/index.php',
'document' => '/resources/document/%resource_node_id%/',
'learnpath' => '/main/lp/lp_controller.php',
'link' => '/resources/links/%resource_node_id%/',
'quiz' => '/main/exercise/exercise.php',
'announcement' => '/main/announcements/announcements.php',
'glossary' => '/resources/glossary/%resource_node_id%/',
'attendance' => '/main/attendance/index.php',
'course_progress' => '/main/course_progress/index.php',
'agenda' => '/resources/ccalendarevent',
'forum' => '/main/forum/index.php',
'student_publication' => '/resources/assignment/%resource_node_id%',
'survey' => '/main/survey/survey_list.php',
'notebook' => '/main/notebook/index.php',
];

public function __construct(EntityManagerInterface $em)
{
parent::__construct($em, $em->getClassMetadata(ResourceLink::class));
@@ -50,4 +67,102 @@ public function removeByResourceInContext(
$this->remove($link);
}
}

/**
* Retrieves the list of available tools filtered by a predefined tool list.
*
* @return array The list of tools with their IDs and titles.
*/
public function getAvailableTools(): array
{
$queryBuilder = $this->_em->createQueryBuilder();
$queryBuilder
->select('DISTINCT t.id, t.title')
->from('ChamiloCoreBundle:ResourceLink', 'rl')
->innerJoin('ChamiloCoreBundle:ResourceType', 'rt', 'WITH', 'rt.id = rl.resourceTypeGroup')
->innerJoin('ChamiloCoreBundle:Tool', 't', 'WITH', 't.id = rt.tool')
->where('rl.course IS NOT NULL')
->andWhere('t.title IN (:toolList)')
->setParameter('toolList', array_keys($this->toolList));

$result = $queryBuilder->getQuery()->getArrayResult();

$tools = [];
foreach ($result as $row) {
$tools[$row['id']] = ucfirst(str_replace('_', ' ', $row['title']));
}

return $tools;
}

/**
* Retrieves a usage report of tools with dynamic links.
*
* @return array The tool usage data including counts, last update timestamps, and dynamic links.
*/
public function getToolUsageReportByTools(array $toolIds): array
{
$queryBuilder = $this->_em->createQueryBuilder();

$queryBuilder
->select(
'COUNT(rl.id) AS resource_count',
'IDENTITY(rl.course) AS course_id',
'IDENTITY(rl.session) AS session_id',
'IDENTITY(c.resourceNode) AS course_resource_node_id',
't.title AS tool_name',
'c.title AS course_name',
's.title AS session_name',
'MAX(rl.updatedAt) AS last_updated'
)
->from('ChamiloCoreBundle:ResourceLink', 'rl')
->innerJoin('ChamiloCoreBundle:ResourceType', 'rt', 'WITH', 'rt.id = rl.resourceTypeGroup')
->innerJoin('ChamiloCoreBundle:Tool', 't', 'WITH', 't.id = rt.tool')
->innerJoin('ChamiloCoreBundle:Course', 'c', 'WITH', 'c.id = rl.course')
->leftJoin('ChamiloCoreBundle:Session', 's', 'WITH', 's.id = rl.session')
->where($queryBuilder->expr()->in('t.id', ':toolIds'))
->groupBy('rl.course, rl.session, t.title')
->orderBy('t.title', 'ASC')
->addOrderBy('c.title', 'ASC')
->addOrderBy('s.title', 'ASC')
->setParameter('toolIds', $toolIds);

$result = $queryBuilder->getQuery()->getArrayResult();

return array_map(function ($row) {
$toolName = $row['tool_name'];
$baseLink = $this->toolList[$toolName] ?? null;

if ($baseLink) {
$link = str_replace(
['%resource_node_id%'],
[$row['course_resource_node_id']],
$baseLink
);

$queryParams = [
'cid' => $row['course_id'],
];

if (!empty($row['session_id'])) {
$queryParams['sid'] = $row['session_id'];
}

$link .= '?' . http_build_query($queryParams);
} else {
$link = '-';
}

return [
'tool_name' => $toolName,
'session_id' => $row['session_id'],
'session_name' => $row['session_name'] ?: '-',
'course_id' => $row['course_id'],
'course_name' => $row['course_name'],
'resource_count' => (int)$row['resource_count'],
'last_updated' => $row['last_updated'] ?: '-',
'link' => $link,
];
}, $result);
}
}