Skip to content

Commit e0cdd85

Browse files
committed
feat: rewritten statistics main page for Twig (#2791)
1 parent 3654994 commit e0cdd85

File tree

3 files changed

+185
-142
lines changed

3 files changed

+185
-142
lines changed

phpmyfaq/admin/statistics.sessions.php

Lines changed: 40 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@
1616
*/
1717

1818
use phpMyFAQ\Component\Alert;
19+
use phpMyFAQ\Configuration;
1920
use phpMyFAQ\Date;
2021
use phpMyFAQ\Filter;
2122
use phpMyFAQ\Helper\StatisticsHelper;
2223
use phpMyFAQ\Session;
2324
use phpMyFAQ\Session\Token;
25+
use phpMyFAQ\Template\TwigWrapper;
2426
use phpMyFAQ\Translation;
27+
use phpMyFAQ\User\CurrentUser;
2528
use phpMyFAQ\Visits;
2629
use Symfony\Component\HttpFoundation\Request;
2730

@@ -30,33 +33,21 @@
3033
exit();
3134
}
3235

36+
$faqConfig = Configuration::getConfigurationInstance();
37+
$user = CurrentUser::getCurrentUser($faqConfig);
3338
$request = Request::createFromGlobals();
3439

35-
?>
36-
37-
<div
38-
class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
39-
<h1 class="h2">
40-
<i aria-hidden="true" class="bi bi-list-ol"></i> <?= Translation::get('ad_stat_sess') ?>
41-
</h1>
42-
<div class="btn-toolbar mb-2 mb-md-0">
43-
<div class="btn-group mr-2">
44-
<a class="btn btn-outline-danger"
45-
href="?action=clear-visits&csrf=<?= Token::getInstance()->getTokenString('clear-visits') ?>">
46-
<i aria-hidden="true" class="bi bi-trash"></i> <?= Translation::get('ad_clear_all_visits') ?>
47-
</a>
48-
</div>
49-
</div>
50-
</div>
51-
52-
<?php
5340
if ($user->perm->hasPermission($user->getUserId(), 'viewlog')) {
5441
$session = new Session($faqConfig);
5542
$date = new Date($faqConfig);
5643
$visits = new Visits($faqConfig);
5744
$statisticsHelper = new StatisticsHelper($session, $visits, $date);
5845

5946
$stats = $statisticsHelper->getTrackingFilesStatistics();
47+
$visitsPerDay = $session->getNumberOfSessions();
48+
49+
$twig = new TwigWrapper(PMF_ROOT_DIR . '/assets/templates');
50+
$template = $twig->loadTemplate('./admin/statistics/sessions.twig');
6051

6152
$statdelete = Filter::filterVar($request->request->get('statdelete'), FILTER_SANITIZE_SPECIAL_CHARS);
6253
$month = Filter::filterVar($request->request->get('month'), FILTER_SANITIZE_SPECIAL_CHARS);
@@ -75,135 +66,44 @@ class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-cente
7566

7667
// Delete sessions and session files
7768
if ($statdelete == 'delete' && $month !== '') {
78-
$statisticsHelper->deleteTrackingFiles($month);
79-
80-
echo Alert::success('ad_adminlog_delete_success');
69+
$hasMessage = $statisticsHelper->deleteTrackingFiles($month);
70+
$message = Translation::get('ad_adminlog_delete_success');
8171
}
8272

8373
// Reset all visits and sessions
8474
if ('clear-visits' === $action && $clearVisits) {
85-
$statisticsHelper->clearAllVisits();
86-
87-
echo Alert::success('ad_reset_visits_success');
75+
$hasMessage = $statisticsHelper->clearAllVisits();
76+
$message = Translation::get('ad_reset_visits_success');
8877
}
89-
?>
90-
<div class="row">
91-
<div class="col-6">
92-
<div class="card shadow">
93-
<div class="card-body">
94-
<table class="table table-striped align-middle">
95-
<tr>
96-
<td><?= Translation::get('ad_stat_days') ?>:</td>
97-
<td><?= $stats->numberOfDays ?></td>
98-
</tr>
99-
<tr>
100-
<td><?= Translation::get('ad_stat_vis'); ?>:</td>
101-
<td><?= $numberOfSessions = $session->getNumberOfSessions() ?></td>
102-
</tr>
103-
<tr>
104-
<td><?= Translation::get('ad_stat_vpd') ?>:</td>
105-
<td><?= ($stats->numberOfDays != 0) ? round(
106-
($numberOfSessions / $stats->numberOfDays),
107-
2
108-
) : 0 ?></td>
109-
</tr>
110-
<tr>
111-
<td><?= Translation::get('ad_stat_fien') ?>:</td>
112-
<td>
113-
<?= $statisticsHelper->getFirstTrackingDate($stats->firstDate) ?>
114-
</td>
115-
</tr>
116-
<tr>
117-
<td><?= Translation::get('ad_stat_laen') ?>:</td>
118-
<td><?= $statisticsHelper->getLastTrackingDate($stats->lastDate) ?></td>
119-
</tr>
120-
<tr>
121-
<td><?= Translation::get('ad_stat_browse') ?>:</td>
122-
<td class="col-lg-10">
123-
<form action="?action=sessionbrowse" method="post" accept-charset="utf-8"
124-
class="row row-cols-lg-auto g-3 align-items-center">
125-
<div class="mr-2">
126-
<label for="day" class="d-none"><?= Translation::get(
127-
'ad_stat_browse'
128-
) ?></label>
129-
<select name="day" id="day" class="form-select">
130-
<?php
131-
foreach ($statisticsHelper->getAllTrackingDates() as $trackingDate) {
132-
printf('<option value="%d"', $trackingDate);
133-
if (
134-
date('Y-m-d', $trackingDate) == date(
135-
'Y-m-d',
136-
$request->server->get('REQUEST_TIME')
137-
)
138-
) {
139-
echo ' selected="selected"';
140-
}
141-
echo '>';
142-
echo $date->format(date('Y-m-d H:i', $trackingDate));
143-
echo "</option>\n";
144-
}
145-
?>
146-
</select>
147-
</div>
148-
<button class="btn btn-primary" type="submit" name="statbrowse">
149-
<?= Translation::get('ad_stat_ok') ?>
150-
</button>
151-
</form>
152-
</td>
153-
</tr>
154-
</table>
155-
</div>
156-
</div>
157-
</div>
158-
159-
<div class="col-6">
160-
<div class="card shadow">
161-
<h5 class="card-header py-3">
162-
<?= Translation::get('ad_stat_management') ?>
163-
</h5>
164-
<div class="card-body">
165-
<form action="?action=viewsessions" method="post"
166-
class="row row-cols-lg-auto g-3 align-items-center">
167-
<input type="hidden" name="statdelete" value="delete">
168-
<div class="col-12">
169-
<?= Token::getInstance()->getTokenInput('sessions') ?>
17078

171-
<label class="form-label" for="month"><?= Translation::get('ad_stat_choose') ?>:</label>
172-
<select name="month" id="month" class="form-select">
173-
<?php
174-
$oldValue = mktime(0, 0, 0, 1, 1, 1970);
175-
$isFirstDate = true;
176-
foreach ($statisticsHelper->getAllTrackingDates() as $trackingDate) {
177-
if (date('Y-m', $oldValue) != date('Y-m', $trackingDate)) {
178-
// The filename format is: trackingDDMMYYYY
179-
// e.g.: tracking02042006
180-
printf('<option value="%s"', date('mY', $trackingDate));
181-
// Select the oldest month
182-
if ($isFirstDate) {
183-
echo ' selected';
184-
$isFirstDate = false;
185-
}
186-
echo '>';
187-
echo date('Y-m', $trackingDate);
188-
echo "</option>\n";
189-
$oldValue = $trackingDate;
190-
}
191-
}
192-
?>
193-
</select>
194-
</div>
195-
<div class="col-12">
196-
<button class="btn btn-primary" type="submit">
197-
<?= Translation::get('ad_stat_delete') ?>
198-
</button>
199-
</div>
200-
</form>
201-
</div>
202-
</div>
203-
</div>
204-
</div>
79+
$templateVars = [
80+
'adminHeaderSessions' => Translation::get('ad_stat_sess'),
81+
'csrfTokenClearVisits' => Token::getInstance()->getTokenString('clear-visits'),
82+
'msgClearVisits' => Translation::get('ad_clear_all_visits'),
83+
'hasMessage' => $hasMessage ?? false,
84+
'message' => $message ?? '',
85+
'msgDays' => Translation::get('ad_stat_days'),
86+
'numberOfDays' => $stats->numberOfDays,
87+
'msgVisits' => Translation::get('ad_stat_vis'),
88+
'numberOfVisits' => $visitsPerDay,
89+
'msgVisitsPerDay' => Translation::get('ad_stat_vpd'),
90+
'visitsPerDay' => ($stats->numberOfDays != 0) ? round(($visitsPerDay / $stats->numberOfDays), 2) : 0,
91+
'msgFirstDate' => Translation::get('ad_stat_fien'),
92+
'firstDate' => $statisticsHelper->getFirstTrackingDate($stats->firstDate),
93+
'msgLastDate' => Translation::get('ad_stat_laen'),
94+
'lastDate' => $statisticsHelper->getLastTrackingDate($stats->lastDate),
95+
'msgSessionBrowse' => Translation::get('ad_stat_browse'),
96+
'renderedDaySelector' => $statisticsHelper->renderDaySelector(),
97+
'buttonOkay' => Translation::get('ad_stat_ok'),
98+
'msgSessionManagement' => Translation::get('ad_stat_management'),
99+
'csrfTokenSessions' => Token::getInstance()->getTokenInput('sessions'),
100+
'msgChooseMonth' => Translation::get('ad_stat_choose'),
101+
'renderedMonthSelector' => $statisticsHelper->renderMonthSelector(),
102+
'buttonDeleteMonth' => Translation::get('ad_stat_delete'),
103+
];
104+
105+
echo $template->render($templateVars);
205106

206-
<?php
207107
} else {
208108
echo Alert::danger('err_NotAuth');
209109
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<div
2+
class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
3+
<h1 class="h2">
4+
<i aria-hidden="true" class="bi bi-list-ol"></i> {{ adminHeaderSessions }}
5+
</h1>
6+
<div class="btn-toolbar mb-2 mb-md-0">
7+
<div class="btn-group mr-2">
8+
<a class="btn btn-outline-danger" href="?action=clear-visits&csrf={{ csrfTokenClearVisits }}">
9+
<i aria-hidden="true" class="bi bi-trash"></i> {{ msgClearVisits }}
10+
</a>
11+
</div>
12+
</div>
13+
</div>
14+
15+
{% if hasMessage %}
16+
<div class="alert alert-success" role="alert">
17+
{{ message }}
18+
</div>
19+
{% endif %}
20+
21+
<div class="row mb-3">
22+
<div class="col-6">
23+
<div class="card shadow">
24+
<h5 class="card-header py-3">
25+
{{ adminHeaderSessions }}
26+
</h5>
27+
<div class="card-body">
28+
<table class="table table-striped align-middle">
29+
<tr>
30+
<th class="w-50">{{ msgDays }}</th>
31+
<td class="w-50">{{ numberOfDays }}</td>
32+
</tr>
33+
<tr>
34+
<th>{{ msgVisits }}</th>
35+
<td>{{ numberOfVisits }}</td>
36+
</tr>
37+
<tr>
38+
<th>{{ msgVisitsPerDay }}</th>
39+
<td>{{ visitsPerDay }}</td>
40+
</tr>
41+
<tr>
42+
<th>{{ msgFirstDate }}</th>
43+
<td>{{ firstDate }}</td>
44+
</tr>
45+
<tr>
46+
<th>{{ msgLastDate }}</th>
47+
<td>{{ lastDate }}</td>
48+
</tr>
49+
<tr>
50+
<th>{{ msgSessionBrowse }}</th>
51+
<td class="col-lg-10">
52+
<form action="?action=sessionbrowse" method="post" accept-charset="utf-8"
53+
class="row row-cols-lg-auto g-3 align-items-center">
54+
<div class="mr-2">
55+
<label for="day" class="d-none">
56+
{{ msgSessionBrowse }}
57+
</label>
58+
<select name="day" id="day" class="form-select">
59+
{{ renderedDaySelector | raw }}
60+
</select>
61+
</div>
62+
<button class="btn btn-primary" type="submit" name="statbrowse">
63+
{{ buttonOkay }}
64+
</button>
65+
</form>
66+
</td>
67+
</tr>
68+
</table>
69+
</div>
70+
</div>
71+
</div>
72+
<div class="col-6">
73+
<!-- Chart has to be implemented :-) -->
74+
</div>
75+
</div>
76+
77+
<div class="row">
78+
<div class="col-6">
79+
<div class="card shadow">
80+
<h5 class="card-header py-3">
81+
{{ msgSessionManagement }}
82+
</h5>
83+
<div class="card-body">
84+
<form action="?action=viewsessions" method="post"
85+
class="row row-cols-lg-auto g-3 align-items-center">
86+
<input type="hidden" name="statdelete" value="delete">
87+
{{ csrfTokenSessions | raw }}
88+
<div class="col-12">
89+
<label class="visually-hidden" for="month">
90+
{{ msgChooseMonth }}
91+
</label>
92+
<select name="month" id="month" class="form-select">
93+
{{ renderedMonthSelector | raw }}
94+
</select>
95+
</div>
96+
<div class="col-12">
97+
<button class="btn btn-primary" type="submit">
98+
{{ buttonDeleteMonth }}
99+
</button>
100+
</div>
101+
</form>
102+
</div>
103+
</div>
104+
</div>
105+
</div>

phpmyfaq/src/phpMyFAQ/Helper/StatisticsHelper.php

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
namespace phpMyFAQ\Helper;
1919

20+
use phpDocumentor\Reflection\Types\This;
2021
use phpMyFAQ\Date;
2122
use phpMyFAQ\Session;
2223
use phpMyFAQ\Translation;
@@ -93,9 +94,9 @@ public function getLastTrackingDate(int $lastDate): string
9394
$date = $request->server->get('REQUEST_TIME');
9495
}
9596

96-
return $this->date->format(date('Y-m-d H:i', $date)) . '<br>';
97+
return $this->date->format(date('Y-m-d H:i', $date));
9798
} else {
98-
return Translation::get('ad_sess_noentry') . '<br>';
99+
return Translation::get('ad_sess_noentry');
99100
}
100101
}
101102

@@ -159,4 +160,41 @@ public function clearAllVisits(): bool
159160
// Delete sessions
160161
return $this->session->deleteAllSessions();
161162
}
163+
164+
public function renderMonthSelector(): string
165+
{
166+
$oldValue = mktime(0, 0, 0, 1, 1, 1970);
167+
$renderedHtml = sprintf('<option value="" selected>%s</option>', Translation::get('ad_stat_choose'));
168+
foreach ($this->getAllTrackingDates() as $trackingDate) {
169+
if (date('Y-m', $oldValue) != date('Y-m', $trackingDate)) {
170+
// The filename format is: trackingDDMMYYYY
171+
// e.g.: tracking02042006
172+
$renderedHtml .= sprintf(
173+
'<option value="%s">%s</option>',
174+
date('mY', $trackingDate),
175+
date('Y-m', $trackingDate)
176+
);
177+
$oldValue = $trackingDate;
178+
}
179+
}
180+
181+
return $renderedHtml;
182+
}
183+
184+
public function renderDaySelector(): string
185+
{
186+
$request = Request::createFromGlobals();
187+
$renderedHtml = '';
188+
foreach ($this->getAllTrackingDates() as $trackingDate) {
189+
$renderedHtml .= sprintf('<option value="%d"', $trackingDate);
190+
if (date('Y-m-d', $trackingDate) == date('Y-m-d', $request->server->get('REQUEST_TIME'))) {
191+
$renderedHtml .= ' selected';
192+
}
193+
$renderedHtml .= '>';
194+
$renderedHtml .= $this->date->format(date('Y-m-d H:i', $trackingDate));
195+
$renderedHtml .= "</option>\n";
196+
}
197+
198+
return $renderedHtml;
199+
}
162200
}

0 commit comments

Comments
 (0)