Skip to content

Commit dabec80

Browse files
Statistics: Add report for subscriptions/unsubscriptions by day - refs #7683
1 parent b77b0d2 commit dabec80

File tree

2 files changed

+129
-0
lines changed

2 files changed

+129
-0
lines changed

public/main/admin/statistics/index.php

+80
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@
351351
'report=users_active' => get_lang('Users statistics'),
352352
'report=users_online' => get_lang('Users online'),
353353
'report=new_user_registrations' => get_lang('New users registrations'),
354+
'report=subscription_by_day' => get_lang('Course/Session subscriptions by day'),
354355
],
355356
get_lang('System') => [
356357
'report=activities' => get_lang('Important activities'),
@@ -370,6 +371,85 @@
370371
$content = '';
371372

372373
switch ($report) {
374+
case 'subscription_by_day':
375+
$form = new FormValidator('subscription_by_day', 'get', api_get_self());
376+
$form->addDateRangePicker('daterange', get_lang('Date range'), true, [
377+
'format' => 'YYYY-MM-DD',
378+
'timePicker' => 'false',
379+
'validate_format' => 'Y-m-d'
380+
]);
381+
$form->addHidden('report', 'subscription_by_day');
382+
$form->addButtonSearch(get_lang('Search'));
383+
$validated = $form->validate() || isset($_REQUEST['daterange']);
384+
385+
if ($validated) {
386+
$values = $form->getSubmitValues();
387+
$dateStart = Security::remove_XSS($values['daterange_start']);
388+
$dateEnd = Security::remove_XSS($values['daterange_end']);
389+
390+
$dates = [];
391+
$period = new DatePeriod(
392+
new DateTime($dateStart),
393+
new DateInterval('P1D'),
394+
(new DateTime($dateEnd))->modify('+1 day')
395+
);
396+
foreach ($period as $date) {
397+
$key = $date->format('Y-m-d');
398+
$dates[$key] = [
399+
'subscriptions' => 0,
400+
'unsubscriptions' => 0,
401+
];
402+
}
403+
404+
$subscriptions = Statistics::getSubscriptionsByDay($dateStart, $dateEnd);
405+
foreach ($subscriptions as $item) {
406+
$dates[$item['date']]['subscriptions'] = $item['count'];
407+
}
408+
409+
$unsubscriptions = Statistics::getUnsubscriptionsByDay($dateStart, $dateEnd);
410+
foreach ($unsubscriptions as $item) {
411+
$dates[$item['date']]['unsubscriptions'] = $item['count'];
412+
}
413+
414+
$labels = array_keys($dates);
415+
$subscriptionsData = array_map(fn($v) => $v['subscriptions'] ?? 0, $dates);
416+
$unsubscriptionsData = array_map(fn($v) => $v['unsubscriptions'] ?? 0, $dates);
417+
418+
$chartData = [
419+
'labels' => $labels,
420+
'datasets' => [
421+
['label' => get_lang('Subscriptions'), 'data' => $subscriptionsData],
422+
['label' => get_lang('Unsubscriptions'), 'data' => $unsubscriptionsData],
423+
]
424+
];
425+
426+
$htmlHeadXtra[] = Statistics::getJSChartTemplateWithData(
427+
$chartData,
428+
'bar',
429+
'title: { text: "'.get_lang('Subscriptions vs Unsubscriptions by day').'", display: true }',
430+
'subscriptions_chart',
431+
true
432+
);
433+
434+
$content .= '<canvas id="subscriptions_chart"></canvas>';
435+
$table = new HTML_Table(['class' => 'table table-hover table-striped table-bordered data_table']);
436+
437+
$table->setHeaderContents(0, 0, get_lang('Date'));
438+
$table->setHeaderContents(0, 1, get_lang('Subscriptions'));
439+
$table->setHeaderContents(0, 2, get_lang('Unsubscriptions'));
440+
441+
$row = 1;
442+
foreach ($dates as $date => $values) {
443+
$table->setCellContents($row, 0, $date);
444+
$table->setCellContents($row, 1, $values['subscriptions'] ?? 0);
445+
$table->setCellContents($row, 2, $values['unsubscriptions'] ?? 0);
446+
$row++;
447+
}
448+
$content .= $table->toHtml();
449+
}
450+
451+
$content = $form->returnForm() . $content;
452+
break;
373453
case 'session_by_date':
374454
$sessions = [];
375455
if ($validated) {

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

+49
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Chamilo\CoreBundle\Entity\UserRelUser;
88
use Chamilo\CoreBundle\Component\Utils\ActionIcon;
99
use Chamilo\CoreBundle\Framework\Container;
10+
use Doctrine\DBAL\ParameterType;
1011

1112
/**
1213
* This class provides some functions for statistics.
@@ -1895,4 +1896,52 @@ public static function getSessionsByDuration(string $dateFrom, string $dateUntil
18951896
}
18961897
return $results;
18971898
}
1899+
1900+
/**
1901+
* Returns the number of user subscriptions grouped by day.
1902+
*/
1903+
public static function getSubscriptionsByDay(string $startDate, string $endDate): array
1904+
{
1905+
$conn = Database::getManager()->getConnection();
1906+
$sql = "
1907+
SELECT DATE(default_date) AS date, COUNT(default_id) AS count
1908+
FROM track_e_default
1909+
WHERE default_event_type = :eventType
1910+
AND default_date BETWEEN :start AND :end
1911+
GROUP BY DATE(default_date)
1912+
ORDER BY DATE(default_date)
1913+
";
1914+
1915+
return $conn->executeQuery($sql, [
1916+
'eventType' => 'user_subscribed',
1917+
'start' => $startDate.' 00:00:00',
1918+
'end' => $endDate.' 23:59:59',
1919+
])->fetchAllAssociative();
1920+
}
1921+
1922+
/**
1923+
* Returns the number of user unsubscriptions grouped by day.
1924+
*/
1925+
public static function getUnsubscriptionsByDay(string $startDate, string $endDate): array
1926+
{
1927+
$conn = Database::getManager()->getConnection();
1928+
$sql = "
1929+
SELECT DATE(default_date) AS date, COUNT(default_id) AS count
1930+
FROM track_e_default
1931+
WHERE default_event_type IN (:eventType1, :eventType2)
1932+
AND default_date BETWEEN :start AND :end
1933+
GROUP BY DATE(default_date)
1934+
ORDER BY DATE(default_date)
1935+
";
1936+
1937+
return $conn->executeQuery($sql, [
1938+
'eventType1' => 'user_unsubscribed',
1939+
'eventType2' => 'session_user_deleted',
1940+
'start' => $startDate.' 00:00:00',
1941+
'end' => $endDate.' 23:59:59',
1942+
], [
1943+
'eventType1' => ParameterType::STRING,
1944+
'eventType2' => ParameterType::STRING,
1945+
])->fetchAllAssociative();
1946+
}
18981947
}

0 commit comments

Comments
 (0)