From 6aa5eb02d4ada1374b965e616cf7f467cb5e8bd1 Mon Sep 17 00:00:00 2001 From: Thorsten Rinne Date: Mon, 25 Nov 2024 17:54:19 +0100 Subject: [PATCH] refactor: migrated sessions page to controller (#3257) --- phpmyfaq/admin/assets/src/api/statistics.js | 42 ++++ phpmyfaq/admin/assets/src/index.js | 4 + .../admin/assets/src/statistics/sessions.js | 40 ++- phpmyfaq/admin/header.php | 3 +- phpmyfaq/admin/index.php | 7 - phpmyfaq/admin/statistics.sessions.day.php | 62 ----- phpmyfaq/admin/statistics.sessions.php | 112 --------- .../admin/statistics/sessions.day.twig | 58 +++-- .../templates/admin/statistics/sessions.twig | 233 +++++++++--------- phpmyfaq/src/admin-api-routes.php | 16 +- phpmyfaq/src/admin-routes.php | 11 + .../AbstractAdministrationController.php | 7 +- .../Administration/Api/SessionController.php | 9 +- .../Api/StatisticsController.php | 48 ++++ .../StatisticsSessionsController.php | 103 ++++++++ .../src/phpMyFAQ/Helper/StatisticsHelper.php | 3 + phpmyfaq/src/services.php | 14 ++ 17 files changed, 437 insertions(+), 335 deletions(-) delete mode 100644 phpmyfaq/admin/statistics.sessions.day.php delete mode 100644 phpmyfaq/admin/statistics.sessions.php create mode 100644 phpmyfaq/src/phpMyFAQ/Controller/Administration/StatisticsSessionsController.php diff --git a/phpmyfaq/admin/assets/src/api/statistics.js b/phpmyfaq/admin/assets/src/api/statistics.js index f5e3805d43..314f337426 100644 --- a/phpmyfaq/admin/assets/src/api/statistics.js +++ b/phpmyfaq/admin/assets/src/api/statistics.js @@ -75,3 +75,45 @@ export const clearRatings = async (csrfToken) => { console.error(error); } }; +export const clearVisits = async (csrfToken) => { + try { + const response = await fetch(`./api/statistics/visits/clear`, { + method: 'DELETE', + cache: 'no-cache', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + csrfToken: csrfToken, + }), + redirect: 'follow', + referrerPolicy: 'no-referrer', + }); + + return await response.json(); + } catch (error) { + console.error(error); + } +}; + +export const deleteSessions = async (csrfToken, month) => { + try { + const response = await fetch(`./api/statistics/sessions`, { + method: 'DELETE', + cache: 'no-cache', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + csrfToken: csrfToken, + month: month, + }), + redirect: 'follow', + referrerPolicy: 'no-referrer', + }); + + return await response.json(); + } catch (error) { + console.error(error); + } +}; diff --git a/phpmyfaq/admin/assets/src/index.js b/phpmyfaq/admin/assets/src/index.js index 611da0fd4a..41b0029dee 100644 --- a/phpmyfaq/admin/assets/src/index.js +++ b/phpmyfaq/admin/assets/src/index.js @@ -16,8 +16,10 @@ import { getLatestVersion, renderVisitorCharts, renderTopTenCharts, handleVerificationModal } from './dashboard'; import { handleClearRatings, + handleClearVisits, handleCreateReport, handleDeleteAdminLog, + handleDeleteSessions, handleSessions, handleStatistics, } from './statistics'; @@ -131,6 +133,8 @@ document.addEventListener('DOMContentLoaded', async () => { handleCreateReport(); handleTruncateSearchTerms(); handleClearRatings(); + handleClearVisits(); + handleDeleteSessions(); // Configuration → FAQ configuration await handleConfiguration(); diff --git a/phpmyfaq/admin/assets/src/statistics/sessions.js b/phpmyfaq/admin/assets/src/statistics/sessions.js index 3001d20aff..b978d51b1b 100644 --- a/phpmyfaq/admin/assets/src/statistics/sessions.js +++ b/phpmyfaq/admin/assets/src/statistics/sessions.js @@ -13,7 +13,8 @@ * @since 2024-01-14 */ -import { pushErrorNotification } from '../utils'; +import { pushErrorNotification, pushNotification } from '../utils'; +import { clearVisits, deleteSessions } from '../api/index.js'; export const handleSessions = () => { const firstHour = document.getElementById('firstHour'); @@ -67,3 +68,40 @@ export const handleSessions = () => { }); } }; + +export const handleClearVisits = () => { + const buttonClearRatings = document.getElementById('pmf-admin-clear-visits'); + + if (buttonClearRatings) { + buttonClearRatings.addEventListener('click', async (event) => { + event.preventDefault(); + const csrf = event.target.getAttribute('data-pmf-csrf'); + const response = await clearVisits(csrf); + + if (response.success) { + pushNotification(response.success); + } else { + pushErrorNotification(response.error); + } + }); + } +}; + +export const handleDeleteSessions = () => { + const buttonClearRatings = document.getElementById('pmf-admin-delete-sessions'); + + if (buttonClearRatings) { + buttonClearRatings.addEventListener('click', async (event) => { + event.preventDefault(); + const csrf = document.getElementById('pmf-csrf-token').value; + const month = document.getElementById('month').value; + const response = await deleteSessions(csrf, month); + + if (response.success) { + pushNotification(response.success); + } else { + pushErrorNotification(response.error); + } + }); + } +}; diff --git a/phpmyfaq/admin/header.php b/phpmyfaq/admin/header.php index dc6a829b53..a0491c1c22 100644 --- a/phpmyfaq/admin/header.php +++ b/phpmyfaq/admin/header.php @@ -112,7 +112,8 @@ $secLevelEntries['statistics'] .= $adminHelper->addMenuEntry( PermissionType::STATISTICS_VIEWLOGS->value, 'viewsessions', - 'ad_menu_session' + 'ad_menu_session', + 'statistics/sessions' ); $secLevelEntries['statistics'] .= $adminHelper->addMenuEntry( PermissionType::STATISTICS_ADMINLOG->value, diff --git a/phpmyfaq/admin/index.php b/phpmyfaq/admin/index.php index 9c9a5b4e2b..23f0745a80 100755 --- a/phpmyfaq/admin/index.php +++ b/phpmyfaq/admin/index.php @@ -318,13 +318,6 @@ case 'adminlog': require 'statistics.admin-log.php'; break; - case 'viewsessions': - case 'clear-visits': - require 'statistics.sessions.php'; - break; - case 'sessionbrowse': - require 'statistics.sessions.day.php'; - break; case 'viewsession': require 'statistics.show.php'; break; diff --git a/phpmyfaq/admin/statistics.sessions.day.php b/phpmyfaq/admin/statistics.sessions.day.php deleted file mode 100644 index c7d1d5bda1..0000000000 --- a/phpmyfaq/admin/statistics.sessions.day.php +++ /dev/null @@ -1,62 +0,0 @@ - - * @copyright 2003-2024 phpMyFAQ Team - * @license https://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0 - * @link https://www.phpmyfaq.de - * @since 2003-02-24 - */ - -use phpMyFAQ\Date; -use phpMyFAQ\Enums\PermissionType; -use phpMyFAQ\Filter; -use phpMyFAQ\Template\TwigWrapper; -use phpMyFAQ\Translation; -use phpMyFAQ\User\CurrentUser; -use Symfony\Component\HttpFoundation\Request; -use Twig\Extension\CoreExtension; - -if (!defined('IS_VALID_PHPMYFAQ')) { - http_response_code(400); - exit(); -} - -$faqConfig = $container->get('phpmyfaq.configuration'); -$user = CurrentUser::getCurrentUser($faqConfig); -$request = Request::createFromGlobals(); - -if ($user->perm->hasPermission($user->getUserId(), PermissionType::STATISTICS_VIEWLOGS->value)) { - $perPage = 50; - $day = Filter::filterVar($request->request->get('day'), FILTER_VALIDATE_INT); - $firstHour = strtotime('midnight', $day); - $lastHour = strtotime('tomorrow', $firstHour) - 1; - - $session = $container->get('phpmyfaq.admin.session'); - $sessionData = $session->getSessionsByDate($firstHour, $lastHour); - $date = new Date($faqConfig); - - $twig = new TwigWrapper(PMF_ROOT_DIR . '/assets/templates'); - $twig->getExtension(CoreExtension::class)->setDateFormat('Y-m-d H:i', '%d days'); - $template = $twig->loadTemplate('@admin/statistics/sessions.day.twig'); - - $templateVars = [ - 'adminHeaderSessionsPerDay' => Translation::get('ad_sess_session'), - 'currentDay' => date('Y-m-d', $day), - 'msgIpAddress' => Translation::get('ad_sess_ip'), - 'msgSessionDate' => Translation::get('ad_sess_s_date'), - 'msgSession' => Translation::get('ad_sess_session'), - 'sessionData' => $sessionData, - ]; - - echo $template->render($templateVars); -} else { - require __DIR__ . '/no-permission.php'; -} diff --git a/phpmyfaq/admin/statistics.sessions.php b/phpmyfaq/admin/statistics.sessions.php deleted file mode 100644 index 8f8a07e4c2..0000000000 --- a/phpmyfaq/admin/statistics.sessions.php +++ /dev/null @@ -1,112 +0,0 @@ - - * @author Matteo Scaramuccia - * @copyright 2003-2024 phpMyFAQ Team - * @license https://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0 - * @link https://www.phpmyfaq.de - * @since 2003-02-24 - */ - -use phpMyFAQ\Date; -use phpMyFAQ\Enums\PermissionType; -use phpMyFAQ\Filter; -use phpMyFAQ\Helper\StatisticsHelper; -use phpMyFAQ\Session\Token; -use phpMyFAQ\Template\TwigWrapper; -use phpMyFAQ\Translation; -use phpMyFAQ\User\CurrentUser; -use Symfony\Component\HttpFoundation\Request; - -if (!defined('IS_VALID_PHPMYFAQ')) { - http_response_code(400); - exit(); -} - -$faqConfig = $container->get('phpmyfaq.configuration'); -$user = CurrentUser::getCurrentUser($faqConfig); -$request = Request::createFromGlobals(); - -if ($user->perm->hasPermission($user->getUserId(), PermissionType::STATISTICS_VIEWLOGS->value)) { - $session = $container->get('phpmyfaq.admin.session'); - $date = new Date($faqConfig); - $visits = $container->get('phpmyfaq.visits'); - $statisticsHelper = new StatisticsHelper($session, $visits, $date); - - $stats = $statisticsHelper->getTrackingFilesStatistics(); - $visitsPerDay = $session->getNumberOfSessions(); - - $twig = new TwigWrapper(PMF_ROOT_DIR . '/assets/templates'); - $template = $twig->loadTemplate('@admin/statistics/sessions.twig'); - - $statdelete = Filter::filterVar($request->request->get('statdelete'), FILTER_SANITIZE_SPECIAL_CHARS); - $month = Filter::filterVar($request->request->get('month'), FILTER_SANITIZE_SPECIAL_CHARS); - $csrfTokenFromPost = Filter::filterVar($request->request->get('csrf'), FILTER_SANITIZE_SPECIAL_CHARS); - $csrfTokenFromGet = Filter::filterVar($request->query->get('csrf'), FILTER_SANITIZE_SPECIAL_CHARS); - - if (!Token::getInstance($container->get('session'))->verifyToken('sessions', $csrfTokenFromPost)) { - $statdelete = null; - } - - if (!Token::getInstance($container->get('session'))->verifyToken('clear-visits', $csrfTokenFromGet)) { - $clearVisits = false; - } else { - $clearVisits = true; - } - - // Delete sessions and session files - if ($statdelete == 'delete' && $month !== '') { - $hasMessage = $statisticsHelper->deleteTrackingFiles($month); - $message = Translation::get('ad_adminlog_delete_success'); - } - - // Reset all visits and sessions - if ('clear-visits' === $action && $clearVisits) { - $hasMessage = $statisticsHelper->clearAllVisits(); - $message = Translation::get('ad_reset_visits_success'); - } - - $templateVars = [ - 'adminHeaderSessions' => Translation::get('ad_stat_sess'), - 'csrfTokenClearVisits' => Token::getInstance($container->get('session'))->getTokenString('clear-visits'), - 'msgClearVisits' => Translation::get('ad_clear_all_visits'), - 'hasMessage' => $hasMessage ?? false, - 'message' => $message ?? '', - 'msgDays' => Translation::get('ad_stat_days'), - 'numberOfDays' => $stats->numberOfDays, - 'msgVisits' => Translation::get('ad_stat_vis'), - 'numberOfVisits' => $visitsPerDay, - 'msgVisitsPerDay' => Translation::get('ad_stat_vpd'), - 'visitsPerDay' => ($stats->numberOfDays != 0) ? round(($visitsPerDay / $stats->numberOfDays), 2) : 0, - 'msgFirstDate' => Translation::get('ad_stat_fien'), - 'firstDate' => $statisticsHelper->getFirstTrackingDate($stats->firstDate), - 'msgLastDate' => Translation::get('ad_stat_laen'), - 'lastDate' => $statisticsHelper->getLastTrackingDate($stats->lastDate), - 'msgSessionBrowse' => Translation::get('ad_stat_browse'), - 'renderedDaySelector' => $statisticsHelper->renderDaySelector(), - 'buttonOkay' => Translation::get('ad_stat_ok'), - 'msgSessionManagement' => Translation::get('ad_stat_management'), - 'csrfTokenSessions' => Token::getInstance($container->get('session'))->getTokenInput('sessions'), - 'msgChooseMonth' => Translation::get('ad_stat_choose'), - 'renderedMonthSelector' => $statisticsHelper->renderMonthSelector(), - 'buttonDeleteMonth' => Translation::get('ad_stat_delete'), - 'msgExportSessions' => Translation::get('msgExportSessions'), - 'msgExportSessionsAsCSV' => Translation::get('msgExportSessionsAsCSV'), - 'csrfTokenExport' => Token::getInstance($container->get('session'))->getTokenString('export-sessions'), - 'dateToday' => date('Y-m-d'), - 'msgExportSessionsFrom' => Translation::get('msgExportSessionsFrom'), - 'msgExportSessionsTo' => Translation::get('msgExportSessionsTo'), - 'datePickerMinDate' => date('Y-m-d', $stats->firstDate), - ]; - - echo $template->render($templateVars); -} else { - require __DIR__ . '/no-permission.php'; -} diff --git a/phpmyfaq/assets/templates/admin/statistics/sessions.day.twig b/phpmyfaq/assets/templates/admin/statistics/sessions.day.twig index a7cdf80ed2..c5c7897899 100644 --- a/phpmyfaq/assets/templates/admin/statistics/sessions.day.twig +++ b/phpmyfaq/assets/templates/admin/statistics/sessions.day.twig @@ -1,29 +1,33 @@ -
-

- - {{ adminHeaderSessionsPerDay }} {{ currentDay }} -

-
+{% extends '@admin/index.twig' %} -
-
- - - - - - - - - - {% for sid, data in sessionData %} - - - - - - {% endfor %} - -
{{ msgIpAddress }}{{ msgSessionDate }}{{ msgSession }}
{{ data.ip }}{{ data.time | date }}{{ sid }}
+{% block content %} +
+

+ + {{ adminHeaderSessionsPerDay }} {{ currentDay }} +

-
+ +
+
+ + + + + + + + + + {% for sid, data in sessionData %} + + + + + + {% endfor %} + +
{{ msgIpAddress }}{{ msgSessionDate }}{{ msgSession }}
{{ data.ip }}{{ data.time | date }}{{ sid }}
+
+
+{% endblock %} diff --git a/phpmyfaq/assets/templates/admin/statistics/sessions.twig b/phpmyfaq/assets/templates/admin/statistics/sessions.twig index 74a0897798..9339b1154e 100644 --- a/phpmyfaq/assets/templates/admin/statistics/sessions.twig +++ b/phpmyfaq/assets/templates/admin/statistics/sessions.twig @@ -1,134 +1,131 @@ -
-

- {{ adminHeaderSessions }} -

-
-
- - {{ msgClearVisits }} - +{% extends '@admin/index.twig' %} + +{% block content %} +
+

+ {{ adminHeaderSessions }} +

+
+
+ +
-
-{% if hasMessage %} -