From 5246cf25dccffc4aab2a2050852a2b767864213d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chlo=C3=A9=20Zermatten?= Date: Fri, 30 Aug 2024 12:44:59 +0100 Subject: [PATCH 01/16] refactor: define abstract methods these methods contain section-specific code. While they likely could be refactored to take in arrays and process these programmatically, allowing some of the logic to be abstracted, this goes beyond the scope of this initial refactor which only seeks to abstract the methods that are shared amongst all usage graphs classes, and for which the implementations are strongly similar. --- code/web/services/Admin/AbstractUsageGraphs.php | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 code/web/services/Admin/AbstractUsageGraphs.php diff --git a/code/web/services/Admin/AbstractUsageGraphs.php b/code/web/services/Admin/AbstractUsageGraphs.php new file mode 100644 index 0000000000..8cbfe71dd4 --- /dev/null +++ b/code/web/services/Admin/AbstractUsageGraphs.php @@ -0,0 +1,10 @@ + Date: Fri, 30 Aug 2024 12:55:30 +0100 Subject: [PATCH 02/16] refactor: extract launchGraph() the launch() method must be implemented on children of Admin_Admin, taking no parameter, and returning void. Since its logic is the same for every usagegraph class, with the exception of the section name, I extracted it into UsageGraphs_UsageGraphs::launchGraph($section), leaving launch() the responsibility to assign the section name. --- .../services/Admin/AbstractUsageGraphs.php | 26 ++++++++++++++++++ code/web/services/Admin/UsageGraphs.php | 27 ++++--------------- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/code/web/services/Admin/AbstractUsageGraphs.php b/code/web/services/Admin/AbstractUsageGraphs.php index 8cbfe71dd4..bfa0112a9e 100644 --- a/code/web/services/Admin/AbstractUsageGraphs.php +++ b/code/web/services/Admin/AbstractUsageGraphs.php @@ -7,4 +7,30 @@ abstract function getBreadcrumbs(): array; abstract function getActiveAdminSection(): string; abstract protected function assignGraphSpecificTitle(string $stat): void; abstract protected function getAndSetInterfaceDataSeries(string $stat, string $instanceName): void; + + // methods shared amongst all usagegraph classes + protected function launchGraph(string $sectionName): void { + global $interface; + + $stat = $_REQUEST['stat']; + if (!empty($_REQUEST['instance'])) { + $instanceName = $_REQUEST['instance']; + } else { + $instanceName = ''; + } + $sectionTitle = $sectionName . ' ' . 'Usage Graph'; + + $interface->assign('stat', $stat); + $interface->assign('section', $sectionName); + $interface->assign('graphTitle', $sectionTitle); + $interface->assign('showCSVExportButton', true); + $interface->assign('propName', 'exportToCSV'); + + $this->assignGraphSpecificTitle($stat); + $this->getAndSetInterfaceDataSeries($stat, $instanceName); + + $graphTitle = $interface->getVariable('graphTitle'); + $this->display('usage-graph.tpl', $graphTitle); + } + } \ No newline at end of file diff --git a/code/web/services/Admin/UsageGraphs.php b/code/web/services/Admin/UsageGraphs.php index 89eaf25eb9..23dea064c6 100644 --- a/code/web/services/Admin/UsageGraphs.php +++ b/code/web/services/Admin/UsageGraphs.php @@ -1,30 +1,13 @@ assign('section', 'Admin'); - $interface->assign('showCSVExportButton', true); - $interface->assign('graphTitle', $title); - $this->assignGraphSpecificTitle($stat); - $this->getAndSetInterfaceDataSeries($stat, $instanceName); - $interface->assign('stat', $stat); - $interface->assign('propName', 'exportToCSV'); - $title = $interface->getVariable('graphTitle'); - $this->display('usage-graph.tpl', $title); +class Admin_UsageGraphs extends Admin_AbstractUsageGraphs { + function launch(): void { + $this->launchGraph('Admin'); // could refactor to extract the section name ('Admin') from the URL within UsageGraphs_UsageGraphs::launch() itself } + function getBreadcrumbs(): array { $breadcrumbs = []; $breadcrumbs[] = new Breadcrumb('/Admin/Home', 'Administration Home'); From 43eb01f40d3741097451395e64780090280a2aaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chlo=C3=A9=20Zermatten?= Date: Fri, 30 Aug 2024 12:58:50 +0100 Subject: [PATCH 03/16] refactor: move canView() to UsageGraphs_UsageGraphs since the permissions required to view admin usage graphs are the same no matter the section, canView() can be moved to the abstract UsageGraphs_UsageGraphs class to be used as is by all usagegraph classes --- code/web/services/Admin/AbstractUsageGraphs.php | 7 +++++++ code/web/services/Admin/UsageGraphs.php | 6 ------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/code/web/services/Admin/AbstractUsageGraphs.php b/code/web/services/Admin/AbstractUsageGraphs.php index bfa0112a9e..2dac30a432 100644 --- a/code/web/services/Admin/AbstractUsageGraphs.php +++ b/code/web/services/Admin/AbstractUsageGraphs.php @@ -33,4 +33,11 @@ protected function launchGraph(string $sectionName): void { $this->display('usage-graph.tpl', $graphTitle); } + public function canView(): bool { + return UserAccount::userHasPermission([ + 'View Dashboards', + 'View System Reports', + ]); + } + } \ No newline at end of file diff --git a/code/web/services/Admin/UsageGraphs.php b/code/web/services/Admin/UsageGraphs.php index 23dea064c6..ac6804c151 100644 --- a/code/web/services/Admin/UsageGraphs.php +++ b/code/web/services/Admin/UsageGraphs.php @@ -21,12 +21,6 @@ function getActiveAdminSection(): string { return 'system_reports'; } - function canView(): bool { - return UserAccount::userHasPermission([ - 'View Dashboards', - 'View System Reports', - ]); - } public function buildCSV() { global $interface; From ae88c2e34bc557a29b3c7c8e74390e6594d75301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chlo=C3=A9=20Zermatten?= Date: Fri, 30 Aug 2024 13:05:54 +0100 Subject: [PATCH 04/16] feat: move buildCSV() to UsageGraphs_UsageGraphs The buildCSV() method is shared amongst all usagegraphs classes and can therefore be added to the abstract UsageGraphs_UsageGraphs class, provided that it is amended to take in a string as a parameter with the name of the section (eg. 'Admin') --- code/web/services/Admin/AJAX.php | 1 + .../services/Admin/AbstractUsageGraphs.php | 44 ++++++++++++++++++ code/web/services/Admin/UsageGraphs.php | 45 ------------------- 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/code/web/services/Admin/AJAX.php b/code/web/services/Admin/AJAX.php index 57071fd580..59b4c11394 100644 --- a/code/web/services/Admin/AJAX.php +++ b/code/web/services/Admin/AJAX.php @@ -1679,5 +1679,6 @@ public function exportUsageData() { require_once ROOT_DIR . '/services/Admin/UsageGraphs.php'; $aspenUsageGraph = new Admin_UsageGraphs(); $aspenUsageGraph->buildCSV(); + } } \ No newline at end of file diff --git a/code/web/services/Admin/AbstractUsageGraphs.php b/code/web/services/Admin/AbstractUsageGraphs.php index 2dac30a432..299e72703d 100644 --- a/code/web/services/Admin/AbstractUsageGraphs.php +++ b/code/web/services/Admin/AbstractUsageGraphs.php @@ -40,4 +40,48 @@ public function canView(): bool { ]); } + public function buildCSV(string $section): void { + global $interface; + + $stat = $_REQUEST['stat']; + if (!empty($_REQUEST['instance'])) { + $instanceName = $_REQUEST['instance']; + } else { + $instanceName = ''; + } + $this->getAndSetInterfaceDataSeries($stat, $instanceName); + $dataSeries = $interface->getVariable('dataSeries'); + + $filename = "{$section}UsageData_{$stat}.csv"; + header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); + header("Cache-Control: no-store, no-cache, must-revalidate"); + header("Cache-Control: post-check=0, pre-check=0", false); + header("Pragma: no-cache"); + header('Content-Type: text/csv; charset=utf-8'); + header("Content-Disposition: attachment;filename={$filename}"); + $fp = fopen('php://output', 'w'); + $graphTitles = array_keys($dataSeries); + $numGraphTitles = count($dataSeries); + + // builds the header for each section of the table in the CSV - column headers: Dates, and the title of the graph + for($i = 0; $i < $numGraphTitles; $i++) { + $dataSerie = $dataSeries[$graphTitles[$i]]; + $numRows = count($dataSerie['data']); + $dates = array_keys($dataSerie['data']); + $header = ['Dates', $graphTitles[$i]]; + fputcsv($fp, $header); + + // builds each subsequent data row - aka the column value + if (empty($numRows)) { + fputcsv($fp, ['no data found']); + } + for($j = 0; $j < $numRows; $j++) { + $date = $dates[$j]; + $value = $dataSerie['data'][$date]; + $row = [$date, $value]; + fputcsv($fp, $row); + } + } + exit(); + } } \ No newline at end of file diff --git a/code/web/services/Admin/UsageGraphs.php b/code/web/services/Admin/UsageGraphs.php index ac6804c151..7dbfbb68e8 100644 --- a/code/web/services/Admin/UsageGraphs.php +++ b/code/web/services/Admin/UsageGraphs.php @@ -21,51 +21,6 @@ function getActiveAdminSection(): string { return 'system_reports'; } - - public function buildCSV() { - global $interface; - - $stat = $_REQUEST['stat']; - if (!empty($_REQUEST['instance'])) { - $instanceName = $_REQUEST['instance']; - } else { - $instanceName = ''; - } - $this->getAndSetInterfaceDataSeries($stat, $instanceName); - $dataSeries = $interface->getVariable('dataSeries'); - - $filename = "AspenUsageData_{$stat}.csv"; - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); - header("Cache-Control: no-store, no-cache, must-revalidate"); - header("Cache-Control: post-check=0, pre-check=0", false); - header("Pragma: no-cache"); - header('Content-Type: text/csv; charset=utf-8'); - header("Content-Disposition: attachment;filename={$filename}"); - $fp = fopen('php://output', 'w'); - $graphTitles = array_keys($dataSeries); - $numGraphTitles = count($dataSeries); - - // builds the header for each section of the table in the CSV - column headers: Dates, and the title of the graph - for($i = 0; $i < $numGraphTitles; $i++) { - $dataSerie = $dataSeries[$graphTitles[$i]]; - $numRows = count($dataSerie['data']); - $dates = array_keys($dataSerie['data']); - $header = ['Dates', $graphTitles[$i]]; - fputcsv($fp, $header); - - if( empty($numRows)) { - fputcsv($fp, ['no data found!']); - } - // builds each subsequent data row - aka the column value - for($j = 0; $j < $numRows; $j++) { - $date = $dates[$j]; - $value = $dataSerie['data'][$date]; - $row = [$date, $value]; - fputcsv($fp, $row); - } - } - exit(); - } private function getAndSetInterfaceDataSeries($stat, $instanceName) { global $interface; global $enabledModules; From e7afb3f1212815fa0f1df8512319e7f71d025978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chlo=C3=A9=20Zermatten?= Date: Fri, 30 Aug 2024 13:12:20 +0100 Subject: [PATCH 05/16] fix: methods types match abstract method definition types --- code/web/services/Admin/UsageGraphs.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/web/services/Admin/UsageGraphs.php b/code/web/services/Admin/UsageGraphs.php index 7dbfbb68e8..d5130b1ef4 100644 --- a/code/web/services/Admin/UsageGraphs.php +++ b/code/web/services/Admin/UsageGraphs.php @@ -21,7 +21,7 @@ function getActiveAdminSection(): string { return 'system_reports'; } - private function getAndSetInterfaceDataSeries($stat, $instanceName) { + protected function getAndSetInterfaceDataSeries($stat, $instanceName): void { global $interface; global $enabledModules; global $library; @@ -322,7 +322,7 @@ private function getAndSetInterfaceDataSeries($stat, $instanceName) { $interface->assign('translateColumnLabels', false); } - private function assignGraphSpecificTitle($stat) { + protected function assignGraphSpecificTitle(string $stat): void { global $interface; $title = $interface->getVariable('graphTitle'); switch ($stat) { From 2806f28ebcbabb20151fb1380907d5073932b27e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chlo=C3=A9=20Zermatten?= Date: Mon, 16 Sep 2024 16:27:53 +0100 Subject: [PATCH 06/16] feat: handle subsections Certain dashboards (SideLoads and Open Archives come to mind) are made up of various subsections for each of which the datastructure is repeated. These subsections can correspond to collection, profiles, etc. So that users are fully aware of what data they are looking at, this update the launchGraph() and buildCSV() methods to ensure that the name of these subSection is taken into account. --- .../services/Admin/AbstractUsageGraphs.php | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/code/web/services/Admin/AbstractUsageGraphs.php b/code/web/services/Admin/AbstractUsageGraphs.php index 299e72703d..5fb6dc73f5 100644 --- a/code/web/services/Admin/AbstractUsageGraphs.php +++ b/code/web/services/Admin/AbstractUsageGraphs.php @@ -18,10 +18,18 @@ protected function launchGraph(string $sectionName): void { } else { $instanceName = ''; } - $sectionTitle = $sectionName . ' ' . 'Usage Graph'; + + // includes dashboard subsection name in title if relevant + $subSectionName = $_REQUEST['subSection']; + $sectionTitle = $sectionName; + if (!empty($subSectionName)) { + $sectionTitle .= ': ' . $subSectionName; + } + $sectionTitle .= ' Usage Graph'; $interface->assign('stat', $stat); $interface->assign('section', $sectionName); + $interface->assign('subSection', $subSectionName); $interface->assign('graphTitle', $sectionTitle); $interface->assign('showCSVExportButton', true); $interface->assign('propName', 'exportToCSV'); @@ -52,7 +60,15 @@ public function buildCSV(string $section): void { $this->getAndSetInterfaceDataSeries($stat, $instanceName); $dataSeries = $interface->getVariable('dataSeries'); - $filename = "{$section}UsageData_{$stat}.csv"; + // ensures csv filename contains dashboard subsection name if relevant + $subSectionName = str_replace(' ', '_', $_REQUEST['subSection']); + $filename = $section . '_'; + if (!empty($subSectionName)) { + $filename .= $subSectionName . '_'; + } + $filename .= 'UsageData_' . $stat . '.csv'; + + // sets up the csv file header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); @@ -60,11 +76,13 @@ public function buildCSV(string $section): void { header('Content-Type: text/csv; charset=utf-8'); header("Content-Disposition: attachment;filename={$filename}"); $fp = fopen('php://output', 'w'); + + // builds the file content $graphTitles = array_keys($dataSeries); $numGraphTitles = count($dataSeries); - // builds the header for each section of the table in the CSV - column headers: Dates, and the title of the graph for($i = 0; $i < $numGraphTitles; $i++) { + // builds the header for each section of the table in the CSV - column headers: Dates, and the title of the graph $dataSerie = $dataSeries[$graphTitles[$i]]; $numRows = count($dataSerie['data']); $dates = array_keys($dataSerie['data']); From 35b28945b4077c4a5924aebc39db78c70b62bcd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chlo=C3=A9=20Zermatten?= Date: Mon, 16 Sep 2024 16:33:02 +0100 Subject: [PATCH 07/16] refactor: all graphs display Admin/usage-graph.tpl --- code/web/services/Admin/AbstractUsageGraphs.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/web/services/Admin/AbstractUsageGraphs.php b/code/web/services/Admin/AbstractUsageGraphs.php index 5fb6dc73f5..3726e746c7 100644 --- a/code/web/services/Admin/AbstractUsageGraphs.php +++ b/code/web/services/Admin/AbstractUsageGraphs.php @@ -38,7 +38,7 @@ protected function launchGraph(string $sectionName): void { $this->getAndSetInterfaceDataSeries($stat, $instanceName); $graphTitle = $interface->getVariable('graphTitle'); - $this->display('usage-graph.tpl', $graphTitle); + $this->display('../Admin/usage-graph.tpl', $graphTitle); } public function canView(): bool { From c0abbd3208b37c27d5feb67a325a3fb2edbb0c88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chlo=C3=A9=20Zermatten?= Date: Wed, 18 Sep 2024 11:23:05 +0100 Subject: [PATCH 08/16] refactor: Admin_UsageGraphs uses Graphing Utils --- code/web/services/Admin/UsageGraphs.php | 133 ++++-------------------- 1 file changed, 23 insertions(+), 110 deletions(-) diff --git a/code/web/services/Admin/UsageGraphs.php b/code/web/services/Admin/UsageGraphs.php index d5130b1ef4..6fdb7723f9 100644 --- a/code/web/services/Admin/UsageGraphs.php +++ b/code/web/services/Admin/UsageGraphs.php @@ -2,6 +2,7 @@ require_once ROOT_DIR . '/services/Admin/AbstractUsageGraphs.php'; require_once ROOT_DIR . '/sys/SystemLogging/AspenUsage.php'; +require_once ROOT_DIR . '/sys/Utils/GraphingUtils.php'; class Admin_UsageGraphs extends Admin_AbstractUsageGraphs { function launch(): void { @@ -40,183 +41,95 @@ protected function getAndSetInterfaceDataSeries($stat, $instanceName): void { //General Usage Stats if ($stat == 'pageViews' || $stat == 'generalUsage') { - $dataSeries['Page Views'] = [ - 'borderColor' => 'rgba(255, 99, 132, 1)', - 'backgroundColor' => 'rgba(255, 99, 132, 0.2)', - 'data' => [], - ]; + $dataSeries['Page Views'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userUsage->selectAdd('SUM(pageViews) as sumPageViews'); } if ($stat == 'authenticatedPageViews' || $stat == 'generalUsage') { - $dataSeries['Authenticated Page Views'] = [ - 'borderColor' => 'rgba(255, 159, 64, 1)', - 'backgroundColor' => 'rgba(255, 159, 64, 0.2)', - 'data' => [], - ]; + $dataSeries['Authenticated Page Views'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userUsage->selectAdd('SUM(pageViewsByAuthenticatedUsers) as sumPageViewsByAuthenticatedUsers'); } if ($stat == 'sessionsStarted' || $stat == 'generalUsage') { - $dataSeries['Sessions Started'] = [ - 'borderColor' => 'rgba(0, 255, 55, 1)', - 'backgroundColor' => 'rgba(0, 255, 55, 0.2)', - 'data' => [], - ]; + $dataSeries['Sessions Started'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userUsage->selectAdd('SUM(sessionsStarted) as sumSessionsStarted'); } if ($stat == 'pageViewsByBots' || $stat == 'generalUsage') { - $dataSeries['Page Views By Bots'] = [ - 'borderColor' => 'rgba(154, 75, 244, 1)', - 'backgroundColor' => 'rgba(154, 75, 244, 0.2)', - 'data' => [], - ]; + $dataSeries['Page Views By Bots'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userUsage->selectAdd('SUM(pageViewsByBots) as sumPageViewsByBots'); } if ($stat == 'asyncRequests' || $stat == 'generalUsage') { - $dataSeries['Asynchronous Requests'] = [ - 'borderColor' => 'rgba(54, 162, 235, 1)', - 'backgroundColor' => 'rgba(54, 162, 235, 0.2)', - 'data' => [], - ]; + $dataSeries['Asynchronous Requests'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userUsage->selectAdd('SUM(ajaxRequests) as sumAjaxRequests'); } if ($stat == 'coversRequested' || $stat == 'generalUsage') { - $dataSeries['Covers Requested'] = [ - 'borderColor' => 'rgba(255, 206, 86, 1)', - 'backgroundColor' => 'rgba(255, 206, 86, 0.2)', - 'data' => [], - ]; + $dataSeries['Covers Requested'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userUsage->selectAdd('SUM(coverViews) as sumCoverViews'); } //Search Stats if ($stat == 'groupedWorksSearches' || $stat == 'searches') { - $dataSeries['Grouped Work Searches'] = [ - 'borderColor' => 'rgba(255, 99, 132, 1)', - 'backgroundColor' => 'rgba(255, 99, 132, 0.2)', - 'data' => [], - ]; + $dataSeries['Grouped Work Searches'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userUsage->selectAdd('SUM(groupedWorkSearches) as sumGroupedWorkSearches'); } if ($stat == 'listSearches' || $stat == 'searches') { - $dataSeries['List Searches'] = [ - 'borderColor' => 'rgba(54, 162, 235, 1)', - 'backgroundColor' => 'rgba(54, 162, 235, 0.2)', - 'data' => [], - ]; + $dataSeries['List Searches'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userUsage->selectAdd('SUM(userListSearches) as sumUserListSearches'); } if (array_key_exists('EBSCO EDS', $enabledModules) && ($stat == 'edsSearches' || $stat == 'searches')) { - $dataSeries['EDS Searches'] = [ - 'borderColor' => 'rgba(255, 206, 86, 1)', - 'backgroundColor' => 'rgba(255, 206, 86, 0.2)', - 'data' => [], - ]; + $dataSeries['EDS Searches'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userUsage->selectAdd('SUM(ebscoEdsSearches) as sumEbscoEdsSearches'); } if (array_key_exists('EBSCOhost', $enabledModules) && ($stat == 'ebscohostSearches' || $stat == 'searches')) { - $dataSeries['EBSCOhost Searches'] = [ - 'borderColor' => 'rgba(255, 206, 86, 1)', - 'backgroundColor' => 'rgba(255, 206, 86, 0.2)', - 'data' => [], - ]; + $dataSeries['EBSCOhost Searches'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userUsage->selectAdd('SUM(ebscohostSearches) as sumEbscohostSearches'); } if (array_key_exists('Events', $enabledModules) && ($stat == 'eventSearches' || $stat == 'searches')) { - $dataSeries['Events Searches'] = [ - 'borderColor' => 'rgba(75, 192, 192, 1)', - 'backgroundColor' => 'rgba(75, 192, 192, 0.2)', - 'data' => [], - ]; + $dataSeries['Events Searches'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userUsage->selectAdd('SUM(eventsSearches) as sumEventsSearches'); } if ((array_key_exists('Web Indexer', $enabledModules) || array_key_exists('Web Builder', $enabledModules)) && ($stat == 'websiteSearches' || $stat == 'searches')) { - $dataSeries['Website Searches'] = [ - 'borderColor' => 'rgba(153, 102, 255, 1)', - 'backgroundColor' => 'rgba(153, 102, 255, 0.2)', - 'data' => [], - ]; + $dataSeries['Website Searches'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userUsage->selectAdd('SUM(websiteSearches) as sumWebsiteSearches'); } if (array_key_exists('Open Archives', $enabledModules) && ($stat == 'openArchivesSearches' || $stat == 'searches')) { - $dataSeries['Open Archives Searches'] = [ - 'borderColor' => 'rgba(255, 159, 64, 1)', - 'backgroundColor' => 'rgba(255, 159, 64, 0.2)', - 'data' => [], - ]; + $dataSeries['Open Archives Searches'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userUsage->selectAdd('SUM(openArchivesSearches) as sumOpenArchivesSearches'); } if ($library->enableGenealogy && ($stat == 'genealogySearches' || $stat == 'searches')) { - $dataSeries['Genealogy Searches'] = [ - 'borderColor' => 'rgba(154, 75, 244, 1)', - 'backgroundColor' => 'rgba(2154, 75, 244, 0.2)', - 'data' => [], - ]; + $dataSeries['Genealogy Searches'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userUsage->selectAdd('SUM(genealogySearches) as sumGenealogySearches'); } //Exceptions if ($stat == 'blockedPages' || $stat == 'exceptionsReport') { - $dataSeries['Blocked Pages'] = [ - 'borderColor' => 'rgba(255, 99, 132, 1)', - 'backgroundColor' => 'rgba(255, 99, 132, 0.2)', - 'data' => [], - ]; + $dataSeries['Blocked Pages'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userUsage->selectAdd('SUM(blockedRequests) as sumBlockedRequests'); } if ($stat == 'blockedApiRequests' || $stat == 'exceptionsReport') { - $dataSeries['Blocked API Requests'] = [ - 'borderColor' => 'rgba(255, 159, 64, 1)', - 'backgroundColor' => 'rgba(255, 159, 64, 0.2)', - 'data' => [], - ]; + $dataSeries['Blocked API Requests'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userUsage->selectAdd('SUM(blockedApiRequests) as sumBlockedApiRequests'); } if ($stat == 'errors' || $stat == 'exceptionsReport') { - $dataSeries['Errors'] = [ - 'borderColor' => 'rgba(154, 75, 244, 1)', - 'backgroundColor' => 'rgba(154, 75, 244, 0.2)', - 'data' => [], - ]; + $dataSeries['Errors'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userUsage->selectAdd('SUM(pagesWithErrors) as sumPagesWithErrors'); } if ($stat == 'searchesWithErrors' || $stat == 'exceptionsReport') { - $dataSeries['Searches with Errors'] = [ - 'borderColor' => 'rgba(154, 10, 120, 1)', - 'backgroundColor' => 'rgba(154, 10, 120, 0.2)', - 'data' => [], - ]; + $dataSeries['Searches with Errors'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userUsage->selectAdd('SUM(searchesWithErrors) as sumSearchesWithErrors'); } if ($stat == 'timedOutSearches' || $stat == 'exceptionsReport') { - $dataSeries['Timed Out Searches'] = [ - 'borderColor' => 'rgba(120, 10 244, 1)', - 'backgroundColor' => 'rgba(120, 10, 244, 0.2)', - 'data' => [], - ]; + $dataSeries['Timed Out Searches'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userUsage->selectAdd('SUM(timedOutSearches) as sumTimedOutSearches'); } if ($stat == 'timedOutSearchesWithHighLoad' || $stat == 'exceptionsReport') { - $dataSeries['Timed Out Searches Under High Load'] = [ - 'borderColor' => 'rgba(10, 120, 244, 1)', - 'backgroundColor' => 'rgba(10, 120, 244, 0.2)', - 'data' => [], - ]; + $dataSeries['Timed Out Searches Under High Load'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userUsage->selectAdd('SUM(timedOutSearchesWithHighLoad) as sumTimedOutSearchesWithHighLoad'); } if ($stat == 'emailsSent' || $stat == 'emailSending') { - $dataSeries['Emails Sent'] = [ - 'borderColor' => 'rgba(120, 10 244, 1)', - 'backgroundColor' => 'rgba(120, 10, 244, 0.2)', - 'data' => [], - ]; + $dataSeries['Emails Sent'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userUsage->selectAdd('SUM(emailsSent) as sumEmailsSent'); } if ($stat == 'failedEmails' || $stat == 'emailSending') { - $dataSeries['Failed Emails'] = [ - 'borderColor' => 'rgba(154, 10, 120, 1)', - 'backgroundColor' => 'rgba(154, 10, 120, 0.2)', - 'data' => [], - ]; + $dataSeries['Failed Emails'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userUsage->selectAdd('SUM(emailsFailed) as sumFailedEmails'); } From 3406e4ee612b5779920ef42a4ede6344639f6adf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chlo=C3=A9=20Zermatten?= Date: Wed, 18 Sep 2024 11:24:32 +0100 Subject: [PATCH 09/16] refactor: Summon_UsageGraphs extends Abstract_UsageGraphs --- code/web/services/Summon/AJAX.php | 2 +- code/web/services/Summon/UsageGraphs.php | 96 +++--------------------- 2 files changed, 12 insertions(+), 86 deletions(-) diff --git a/code/web/services/Summon/AJAX.php b/code/web/services/Summon/AJAX.php index 04402bc309..d6d65f4664 100644 --- a/code/web/services/Summon/AJAX.php +++ b/code/web/services/Summon/AJAX.php @@ -4,6 +4,6 @@ class Summon_AJAX extends JSON_Action { public function exportUsageData() { require_once ROOT_DIR . '/services/Summon/UsageGraphs.php'; $summonUsageGraph = new Summon_UsageGraphs(); - $summonUsageGraph->buildCSV(); + $summonUsageGraph->buildCSV('Summon'); } } \ No newline at end of file diff --git a/code/web/services/Summon/UsageGraphs.php b/code/web/services/Summon/UsageGraphs.php index 9fe882d614..71644f84a5 100644 --- a/code/web/services/Summon/UsageGraphs.php +++ b/code/web/services/Summon/UsageGraphs.php @@ -1,28 +1,14 @@ assign('graphTitle', $title); - $interface->assign('section', 'Summon'); - $interface->assign('showCSVExportButton', true); - $this->assignGraphSpecificTitle($stat); - $this->getAndSetInterfaceDataSeries($stat, $instanceName); - $interface->assign('stat', $stat); - $this->display('../Admin/usage-graph.tpl', $title); +class Summon_UsageGraphs extends Admin_AbstractUsageGraphs { + function launch(): void { + $this->launchGraph('Summon'); } function getActiveAdminSection(): string { @@ -45,51 +31,7 @@ function getBreadcrumbs(): array { return $breadcrumbs; } - // note that this will only handle tables with one stat (as is needed for Summon usage data) - // to see a version that handle multpile stats, see the Admin/UsageGraphs.php implementation - public function buildCSV() { - global $interface; - $stat = $_REQUEST['stat']; - if (!empty($_REQUEST['instance'])) { - $instanceName = $_REQUEST['instance']; - } else { - $instanceName = ''; - } - $this->getAndSetInterfaceDataSeries($stat, $instanceName); - $dataSeries = $interface->getVariable('dataSeries'); - - $filename = "SummonUsageData_{$stat}.csv"; - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); - header("Cache-Control: no-store, no-cache, must-revalidate"); - header("Cache-Control: post-check=0, pre-check=0", false); - header("Pragma: no-cache"); - header('Content-Type: text/csv; charset=utf-8'); - header("Content-Disposition: attachment;filename={$filename}"); - $fp = fopen('php://output', 'w'); - - // builds the first row of the table in the CSV - column headers: Dates, and the title of the graph - fputcsv($fp, ['Dates', $stat]); - - // builds each subsequent data row - aka the column value - foreach ($dataSeries as $dataSerie) { - $data = $dataSerie['data']; - $numRows = count($data); - $dates = array_keys($data); - - if( empty($numRows)) { - fputcsv($fp, ['no data found!']); - } - for($i = 0; $i < $numRows; $i++) { - $date = $dates[$i]; - $value = $data[$date]; - $row = [$date, $value]; - fputcsv($fp, $row); - } - } - exit(); - } - - private function getAndSetInterfaceDataSeries($stat, $instanceName) { + protected function getAndSetInterfaceDataSeries($stat, $instanceName): void { global $interface; $dataSeries = []; $columnLabels = []; @@ -106,11 +48,7 @@ private function getAndSetInterfaceDataSeries($stat, $instanceName) { $userSummonUsage->selectAdd('month'); $userSummonUsage->orderBy('year, month'); - $dataSeries['Active Users'] = [ - 'borderColor' => 'rgba(255, 99, 132, 1)', - 'backgroundColor' => 'rgba(255, 99, 132, 0.2)', - 'data' => [], - ]; + $dataSeries['Active Users'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userSummonUsage->selectAdd('COUNT(DISTINCT userId) as activeUsers'); // Collects results @@ -140,27 +78,15 @@ private function getAndSetInterfaceDataSeries($stat, $instanceName) { $summonRecordUsage->orderBy('year, month'); if ($stat == 'numRecordsViewed') { - $dataSeries['Number of Records Viewed'] = [ - 'borderColor' => 'rgba(255, 99, 132, 1)', - 'backgroundColor' => 'rgba(255, 99, 132, 0.2)', - 'data' => [], - ]; + $dataSeries['Number of Records Viewed'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $summonRecordUsage ->selectAdd('SUM(IF(timesViewedInSearch>0,1,0)) as numRecordsViewed'); } if ($stat == 'numRecordsClicked') { - $dataSeries['Number of Records Clicked'] = [ - 'borderColor' => 'rgba(255, 99, 132, 1)', - 'backgroundColor' => 'rgba(255, 99, 132, 0.2)', - 'data' => [], - ]; + $dataSeries['Number of Records Clicked'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $summonRecordUsage ->selectAdd('SUM(IF(timesUsed>0,1,0)) as numRecordsUsed'); } if ($stat == 'totalClicks') { - $dataSeries['Total Clicks'] = [ - 'borderColor' => 'rgba(255, 99, 132, 1)', - 'backgroundColor' => 'rgba(255, 99, 132, 0.2)', - 'data' => [], - ]; + $dataSeries['Total Clicks'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $summonRecordUsage ->selectAdd('SUM(timesUsed) as numClicks'); } // Collect results @@ -189,7 +115,7 @@ private function getAndSetInterfaceDataSeries($stat, $instanceName) { $interface->assign('translateColumnLabels', false); } - private function assignGraphSpecificTitle($stat) { + protected function assignGraphSpecificTitle($stat): void { global $interface; $title = $interface->getVariable('graphTitle'); switch ($stat) { From 7c15a6ae300770078a84a991d28f00de217e6ca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chlo=C3=A9=20Zermatten?= Date: Wed, 18 Sep 2024 11:25:35 +0100 Subject: [PATCH 10/16] refactor: ILS_UsageGraphs extends Abstract_UsageGraphs --- code/web/services/ILS/AJAX.php | 4 +- code/web/services/ILS/UsageGraphs.php | 138 ++++---------------------- 2 files changed, 20 insertions(+), 122 deletions(-) diff --git a/code/web/services/ILS/AJAX.php b/code/web/services/ILS/AJAX.php index a0c67d2695..594f670335 100644 --- a/code/web/services/ILS/AJAX.php +++ b/code/web/services/ILS/AJAX.php @@ -1,9 +1,9 @@ buildCSV(); + $ILSUsageGraph->buildCSV('ILS'); } } \ No newline at end of file diff --git a/code/web/services/ILS/UsageGraphs.php b/code/web/services/ILS/UsageGraphs.php index 05c1b78fc2..4105551650 100644 --- a/code/web/services/ILS/UsageGraphs.php +++ b/code/web/services/ILS/UsageGraphs.php @@ -1,28 +1,14 @@ assign('graphTitle', $title); - $interface->assign('section', 'ILS'); - $interface->assign('showCSVExportButton', true); - $this->assignGraphSpecificTitle($stat); - $this->getAndSetInterfaceDataSeries($stat, $instanceName); - $interface->assign('stat', $stat); - $this->display('../Admin/usage-graph.tpl', $title); +class ILS_UsageGraphs extends Admin_AbstractUsageGraphs { + function launch(): void { + $this->launchGraph('ILS'); } function getBreadcrumbs(): array { @@ -45,51 +31,7 @@ function canView(): bool { ]); } - // note that this will only handle tables with one stat (as is needed for Summon usage data) - // to see a version that handle multpile stats, see the Admin/UsageGraphs.php implementation - public function buildCSV() { - global $interface; - $stat = $_REQUEST['stat']; - if (!empty($_REQUEST['instance'])) { - $instanceName = $_REQUEST['instance']; - } else { - $instanceName = ''; - } - $this->getAndSetInterfaceDataSeries($stat, $instanceName); - $dataSeries = $interface->getVariable('dataSeries'); - - $filename = "ILSUsageData_{$stat}.csv"; - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); - header("Cache-Control: no-store, no-cache, must-revalidate"); - header("Cache-Control: post-check=0, pre-check=0", false); - header("Pragma: no-cache"); - header('Content-Type: text/csv; charset=utf-8'); - header("Content-Disposition: attachment;filename={$filename}"); - $fp = fopen('php://output', 'w'); - - // builds the first row of the table in the CSV - column headers: Dates, and the title of the graph - fputcsv($fp, ['Dates', $stat]); - - // builds each subsequent data row - aka the column value - foreach ($dataSeries as $dataSerie) { - $data = $dataSerie['data']; - $numRows = count($data); - $dates = array_keys($data); - - if( empty($numRows)) { - fputcsv($fp, ['no data found!']); - } - for($i = 0; $i < $numRows; $i++) { - $date = $dates[$i]; - $value = $data[$date]; - $row = [$date, $value]; - fputcsv($fp, $row); - } - } - exit(); - } - - private function getAndSetInterfaceDataSeries($stat, $instanceName) { + protected function getAndSetInterfaceDataSeries($stat, $instanceName): void { global $interface; $dataSeries = []; $columnLabels = []; @@ -114,51 +56,27 @@ private function getAndSetInterfaceDataSeries($stat, $instanceName) { $userILSUsage->orderBy('year, month'); if ($stat == 'userLogins') { - $dataSeries['User Logins'] = [ - 'borderColor' => 'rgba(255, 99, 132, 1)', - 'backgroundColor' => 'rgba(255, 99, 132, 0.2)', - 'data' => [], - ]; + $dataSeries['User Logins'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userILSUsage->selectAdd('SUM(usageCount) as sumUserLogins'); } if ($stat == 'selfRegistrations') { - $dataSeries['Self Registrations'] = [ - 'borderColor' => 'rgba(255, 159, 64, 1)', - 'backgroundColor' => 'rgba(255, 159, 64, 0.2)', - 'data' => [], - ]; + $dataSeries['Self Registrations'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userILSUsage->selectAdd('SUM(selfRegistrationCount) as sumSelfRegistrations'); } if ($stat == 'usersWithPdfDownloads') { - $dataSeries['Users Who Downloaded At Least One PDF'] = [ - 'borderColor' => 'rgba(255, 206, 86, 1)', - 'backgroundColor' => 'rgba(255, 206, 86, 0.2)', - 'data' => [], - ]; + $dataSeries['Users Who Downloaded At Least One PDF'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userILSUsage->selectAdd('SUM(IF(pdfDownloadCount>0,1,0)) as usersWithPdfDownloads'); } if ($stat == 'usersWithPdfViews') { - $dataSeries['Users Who Viewed At Least One PDF'] = [ - 'borderColor' => 'rgba(255, 206, 86, 1)', - 'backgroundColor' => 'rgba(255, 206, 86, 0.2)', - 'data' => [], - ]; + $dataSeries['Users Who Viewed At Least One PDF'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userILSUsage->selectAdd('SUM(IF(pdfViewCount>0,1,0)) as usersWithPdfViews'); } if ($stat == 'usersWithSupplementalFileDownloads') { - $dataSeries['Users Who Downloaded At Least One Supplemental File'] = [ - 'borderColor' => 'rgba(255, 206, 86, 1)', - 'backgroundColor' => 'rgba(255, 206, 86, 0.2)', - 'data' => [], - ]; + $dataSeries['Users Who Downloaded At Least One Supplemental File'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userILSUsage->selectAdd('SUM(IF(supplementalFileDownloadCount>0,1,0)) as usersWithSupplementalFileDownloads'); } if ($stat == 'usersWithHolds') { - $dataSeries['Users Who Placed At Least One Hold'] = [ - 'borderColor' => 'rgba(0, 255, 55, 1)', - 'backgroundColor' => 'rgba(0, 255, 55, 0.2)', - 'data' => [], - ]; + $dataSeries['Users Who Placed At Least One Hold'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $userILSUsage->selectAdd('SUM(IF(usageCount>0,1,0)) as usersWithHolds'); } @@ -214,43 +132,23 @@ private function getAndSetInterfaceDataSeries($stat, $instanceName) { $recordILSUsage->orderBy('year, month'); if ($stat == 'pdfsDownloaded') { - $dataSeries['PDFs Downloaded'] = [ - 'borderColor' => 'rgba(255, 206, 86, 1)', - 'backgroundColor' => 'rgba(255, 206, 86, 0.2)', - 'data' => [], - ]; + $dataSeries['PDFs Downloaded'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $recordILSUsage->selectAdd('SUM(pdfDownloadCount) as sumPdfsDownloaded'); } if ($stat == 'pdfsViewed') { - $dataSeries['PDFs Viewed'] = [ - 'borderColor' => 'rgba(255, 206, 86, 1)', - 'backgroundColor' => 'rgba(255, 206, 86, 0.2)', - 'data' => [], - ]; + $dataSeries['PDFs Viewed'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $recordILSUsage->selectAdd('SUM(pdfViewCount) as sumPdfsViewed'); } if ($stat == 'supplementalFilesDownloaded') { - $dataSeries['Supplemental Files Downloaded'] = [ - 'borderColor' => 'rgba(255, 206, 86, 1)', - 'backgroundColor' => 'rgba(255, 206, 86, 0.2)', - 'data' => [], - ]; + $dataSeries['Supplemental Files Downloaded'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $recordILSUsage->selectAdd('SUM(supplementalFileDownloadCount) as sumSupplementalFilesDownloaded'); } if ($stat == 'recordsHeld') { - $dataSeries['Records Held'] = [ - 'borderColor' => 'rgba(154, 75, 244, 1)', - 'backgroundColor' => 'rgba(154, 75, 244, 0.2)', - 'data' => [], - ]; + $dataSeries['Records Held'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $recordILSUsage->selectAdd('SUM(IF(timesUsed>0,1,0)) as numRecordsUsed'); } if ($stat == 'totalHolds') { - $dataSeries['Total Holds'] = [ - 'borderColor' => 'rgba(54, 162, 235, 1)', - 'backgroundColor' => 'rgba(54, 162, 235, 0.2)', - 'data' => [], - ]; + $dataSeries['Total Holds'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $recordILSUsage->selectAdd('SUM(timesUsed) as totalHolds'); } @@ -288,7 +186,7 @@ private function getAndSetInterfaceDataSeries($stat, $instanceName) { $interface->assign('translateColumnLabels', false); } - private function assignGraphSpecificTitle($stat) { + protected function assignGraphSpecificTitle($stat): void { global $interface; $title = $interface->getVariable('graphTitle'); switch ($stat) { From 49042d1b3c224c993b0ecc5f4e46654068c62e6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chlo=C3=A9=20Zermatten?= Date: Wed, 18 Sep 2024 11:26:35 +0100 Subject: [PATCH 11/16] refactor: Admin_APIUsageGraphs extends Abstract_UsageGraphs --- code/web/services/API/UsageGraphs.php | 72 ++++----------------------- 1 file changed, 10 insertions(+), 62 deletions(-) diff --git a/code/web/services/API/UsageGraphs.php b/code/web/services/API/UsageGraphs.php index bd0b93307d..5fc4046654 100644 --- a/code/web/services/API/UsageGraphs.php +++ b/code/web/services/API/UsageGraphs.php @@ -1,12 +1,11 @@ getVariable('graphTitle'); $this->display('../Admin/usage-graph.tpl', $title); } - function getBreadcrumbs(): array - { + function getBreadcrumbs(): array { $breadcrumbs = []; $breadcrumbs[] = new Breadcrumb('/Admin/Home', 'Administration Home'); $breadcrumbs[] = new Breadcrumb('/Admin/Home#system_reports', 'System Reports'); @@ -37,63 +35,18 @@ function getBreadcrumbs(): array return $breadcrumbs; } - function getActiveAdminSection(): string - { + function getActiveAdminSection(): string { return 'system_reports'; } - function canView(): bool - { + function canView(): bool { return UserAccount::userHasPermission([ 'View Dashboards', 'View System Reports', ]); } - // note that this will only handle tables with one stat (as is needed for Summon usage data) - // to see a version that handle multpile stats, see the Admin/UsageGraphs.php implementation - public function buildCSV() { - global $interface; - $stat = $_REQUEST['stat']; - if (!empty($_REQUEST['instance'])) { - $instanceName = $_REQUEST['instance']; - } else { - $instanceName = ''; - } - $this->getAndSetInterfaceDataSeries($stat, $instanceName); - $dataSeries = $interface->getVariable('dataSeries'); - - $filename = "AspenAPIUsageData_{$stat}.csv"; - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); - header("Cache-Control: no-store, no-cache, must-revalidate"); - header("Cache-Control: post-check=0, pre-check=0", false); - header("Pragma: no-cache"); - header('Content-Type: text/csv; charset=utf-8'); - header("Content-Disposition: attachment;filename={$filename}"); - $fp = fopen('php://output', 'w'); - - // builds the first row of the table in the CSV - column headers: Dates, and the title of the graph - fputcsv($fp, ['Dates', $stat]); - - // builds each subsequent data row - aka the column value - foreach ($dataSeries as $dataSerie) { - $data = $dataSerie['data']; - $numRows = count($data); - $dates = array_keys($data); - - if( empty($numRows)) { - fputcsv($fp, ['no data found!']); - } - for($i = 0; $i < $numRows; $i++) { - $date = $dates[$i]; - $value = $data[$date]; - $row = [$date, $value]; - fputcsv($fp, $row); - } - } - exit(); - } - private function getAndSetInterfaceDataSeries($stat, $instanceName) { + protected function getAndSetInterfaceDataSeries($stat, $instanceName): void { global $interface; $dataSeries = []; @@ -108,11 +61,7 @@ private function getAndSetInterfaceDataSeries($stat, $instanceName) { $usage->selectAdd('year'); $usage->selectAdd('month'); $usage->orderBy('year, month'); - $dataSeries[$stat] = [ - 'borderColor' => 'rgba(255, 99, 132, 1)', - 'backgroundColor' => 'rgba(255, 99, 132, 0.2)', - 'data' => [], - ]; + $dataSeries[$stat] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $usage->selectAdd('SUM(numCalls) as numCalls'); //Collect results @@ -130,8 +79,7 @@ private function getAndSetInterfaceDataSeries($stat, $instanceName) { $interface->assign('translateColumnLabels', false); } - private function assignGraphSpecificTitle($stat) - { + protected function assignGraphSpecificTitle($stat): void { global $interface; $title = 'Aspen Discovery API Usage Graph'; $title .= " - $stat"; From 2169c1fc42c13a9466ca49c337b8819753862bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chlo=C3=A9=20Zermatten?= Date: Wed, 18 Sep 2024 11:27:20 +0100 Subject: [PATCH 12/16] refactor: Axis360_APIUsageGraphs (Boundless) extends Abstract_UsageGraphs --- code/web/services/Axis360/AJAX.php | 4 +- code/web/services/Axis360/UsageGraphs.php | 74 ++--------------------- 2 files changed, 8 insertions(+), 70 deletions(-) diff --git a/code/web/services/Axis360/AJAX.php b/code/web/services/Axis360/AJAX.php index a049409115..7dab8490a8 100644 --- a/code/web/services/Axis360/AJAX.php +++ b/code/web/services/Axis360/AJAX.php @@ -489,9 +489,9 @@ function getLargeCover() { ]; } - public function exportUsageData() { + public function exportUsageData(): void { require_once ROOT_DIR . '/services/Axis360/UsageGraphs.php'; $axis360UsageGraph = new Axis360_UsageGraphs(); - $axis360UsageGraph->buildCSV(); + $axis360UsageGraph->buildCSV('Boundless'); } } \ No newline at end of file diff --git a/code/web/services/Axis360/UsageGraphs.php b/code/web/services/Axis360/UsageGraphs.php index 2636a6141f..a27efa397f 100644 --- a/code/web/services/Axis360/UsageGraphs.php +++ b/code/web/services/Axis360/UsageGraphs.php @@ -1,31 +1,14 @@ assign('graphTitle', $title); - $this->assignGraphSpecificTitle($stat); - $this->getAndSetInterfaceDataSeries($stat, $instanceName); - $interface->assign('stat', $stat); - $interface->assign('propName', 'exportToCSV'); - $interface->assign('showCSVExportButton', true); - $interface->assign('section', 'Axis360'); - - $this->display('../Admin/usage-graph.tpl', $title); +class Axis360_UsageGraphs extends Admin_AbstractUsageGraphs { + function launch(): void { + $this->launchGraph('Boundless'); } function getBreadcrumbs(): array { @@ -48,52 +31,7 @@ function canView(): bool { ]); } - public function buildCSV() { - global $interface; - - $stat = $_REQUEST['stat']; - if (!empty($_REQUEST['instance'])) { - $instanceName = $_REQUEST['instance']; - } else { - $instanceName = ''; - } - $this->getAndSetInterfaceDataSeries($stat, $instanceName); - $dataSeries = $interface->getVariable('dataSeries'); - - $filename = "BoundlessUsageData_{$stat}.csv"; - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); - header("Cache-Control: no-store, no-cache, must-revalidate"); - header("Cache-Control: post-check=0, pre-check=0", false); - header("Pragma: no-cache"); - header('Content-Type: text/csv; charset=utf-8'); - header("Content-Disposition: attachment;filename={$filename}"); - $fp = fopen('php://output', 'w'); - $graphTitles = array_keys($dataSeries); - $numGraphTitles = count($dataSeries); - - // builds the header for each section of the table in the CSV - column headers: Dates, and the title of the graph - for($i = 0; $i < $numGraphTitles; $i++) { - $dataSerie = $dataSeries[$graphTitles[$i]]; - $numRows = count($dataSerie['data']); - $dates = array_keys($dataSerie['data']); - $header = ['Dates', $graphTitles[$i]]; - fputcsv($fp, $header); - - if( empty($numRows)) { - fputcsv($fp, ['no data found!']); - } - // builds each subsequent data row - aka the column value - for($j = 0; $j < $numRows; $j++) { - $date = $dates[$j]; - $value = $dataSerie['data'][$date]; - $row = [$date, $value]; - fputcsv($fp, $row); - } - } - exit(); - } - - private function getAndSetInterfaceDataSeries($stat, $instanceName) { + protected function getAndSetInterfaceDataSeries($stat, $instanceName): void { global $interface; $dataSeries = []; $columnLabels = []; @@ -270,7 +208,7 @@ private function getAndSetInterfaceDataSeries($stat, $instanceName) { $interface->assign('translateColumnLabels', false); } - private function assignGraphSpecificTitle($stat) { + protected function assignGraphSpecificTitle($stat): void { global $interface; $title = $interface->getVariable('graphTitle'); switch ($stat) { From 36dc044cbadfb7af6d22d0d849063db963693920 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chlo=C3=A9=20Zermatten?= Date: Wed, 18 Sep 2024 11:28:23 +0100 Subject: [PATCH 13/16] refactor: MaterialsRequest_UsageGraphs extends Abstract_UsageGraphs --- .../responsive/MaterialsRequest/dashboard.tpl | 2 +- code/web/services/MaterialsRequest/AJAX.php | 6 + code/web/services/MaterialsRequest/Graph.php | 160 ------------------ .../services/MaterialsRequest/UsageGraphs.php | 100 +++++++++++ 4 files changed, 107 insertions(+), 161 deletions(-) delete mode 100644 code/web/services/MaterialsRequest/Graph.php create mode 100644 code/web/services/MaterialsRequest/UsageGraphs.php diff --git a/code/web/interface/themes/responsive/MaterialsRequest/dashboard.tpl b/code/web/interface/themes/responsive/MaterialsRequest/dashboard.tpl index 1dc87976c2..a1b0d76f73 100644 --- a/code/web/interface/themes/responsive/MaterialsRequest/dashboard.tpl +++ b/code/web/interface/themes/responsive/MaterialsRequest/dashboard.tpl @@ -7,7 +7,7 @@
-

{$statusStats.label}

{* No translation needed *} +

{$statusStats.label}

{* No translation needed *}
diff --git a/code/web/services/MaterialsRequest/AJAX.php b/code/web/services/MaterialsRequest/AJAX.php index 3dfddfe241..ee5f48cc9d 100644 --- a/code/web/services/MaterialsRequest/AJAX.php +++ b/code/web/services/MaterialsRequest/AJAX.php @@ -497,4 +497,10 @@ function selectHoldCandidate() : array { function getBreadcrumbs(): array { return []; } + + public function exportUsageData(): void { + require_once ROOT_DIR . '/services/MaterialsRequest/UsageGraphs.php'; + $MaterialsRequestUsageGraph = new MaterialsRequest_UsageGraphs(); + $MaterialsRequestUsageGraph->buildCSV('MaterialsRequest'); + } } \ No newline at end of file diff --git a/code/web/services/MaterialsRequest/Graph.php b/code/web/services/MaterialsRequest/Graph.php deleted file mode 100644 index 8580123c04..0000000000 --- a/code/web/services/MaterialsRequest/Graph.php +++ /dev/null @@ -1,160 +0,0 @@ -assign('curStatus', $status); - - $dataSeries = []; - $columnLabels = []; - - $userHomeLibrary = Library::getPatronHomeLibrary(); - if (is_null($userHomeLibrary)) { - //User does not have a home library, this is likely an admin account. Use the active library - global $library; - $userHomeLibrary = $library; - } - $libraryId = $userHomeLibrary->libraryId; - - $thisStatus = new MaterialsRequestStatus(); - $thisStatus->id = $status; - $thisStatus->libraryId = $libraryId; - $thisStatus->find(); - while ($thisStatus->fetch()) { - $title = 'Materials Request Usage Graph - ' . $thisStatus->description; - $materialsRequestUsage = new MaterialsRequestUsage(); - $materialsRequestUsage->groupBy('year, month'); - $materialsRequestUsage->selectAdd(); - $materialsRequestUsage->statusId = $status; - $materialsRequestUsage->selectAdd('year'); - $materialsRequestUsage->selectAdd('month'); - $materialsRequestUsage->selectAdd('SUM(numUsed) as numUsed'); - $materialsRequestUsage->orderBy('year, month'); - - $dataSeries[$thisStatus->description] = [ - 'borderColor' => 'rgba(255, 99, 132, 1)', - 'backgroundColor' => 'rgba(255, 99, 132, 0.2)', - 'data' => [], - ]; - - //Collect results - $materialsRequestUsage->find(); - - while ($materialsRequestUsage->fetch()) { - $curPeriod = "{$materialsRequestUsage->month}-{$materialsRequestUsage->year}"; - $columnLabels[] = $curPeriod; - $dataSeries[$thisStatus->description]['data'][$curPeriod] = $materialsRequestUsage->numUsed; - } - } - $interface->assign('columnLabels', $columnLabels); - $interface->assign('dataSeries', $dataSeries); - $interface->assign('graphTitle', $title); - $interface->assign('translateDataSeries', true); - $interface->assign('translateColumnLabels', false); - - //Check to see if we are exporting to Excel - if (isset($_REQUEST['exportToExcel'])) { - $this->exportToExcel(); - } - - $this->display('graph.tpl', $title); - } - - public function getAllPeriods() { - $usage = new MaterialsRequestUsage(); - $usage->selectAdd(null); - $usage->selectAdd('DISTINCT year, month'); - $usage->find(); - - $stats = []; - while ($usage->fetch()) { - $stats[$usage->month . '-' . $usage->year]['year'] = $usage->year; - $stats[$usage->month . '-' . $usage->year]['month'] = $usage->month; - } - return $stats; - } - - function exportToExcel() { - $status = $_REQUEST['status']; - - $periods = $this->getAllPeriods(); - - header('Content-Type: text/csv; charset=utf-8'); - header('Content-Disposition: attachment;filename="MaterialsRequestGraphReport.csv"'); - header('Cache-Control: max-age=0'); - $fp = fopen('php://output', 'w'); - - $header= ['Date', 'Requests Pending']; - fputcsv($fp, $header); - - $userHomeLibrary = Library::getPatronHomeLibrary(); - if (is_null($userHomeLibrary)) { - //User does not have a home library, this is likely an admin account. Use the active library - global $library; - $userHomeLibrary = $library; - } - $libraryId = $userHomeLibrary->libraryId; - - $thisStatus = new MaterialsRequestStatus(); - $thisStatus->libraryId = $libraryId; - $thisStatus->find(); - - foreach ($periods as $period) { - $materialsRequestUsage = new MaterialsRequestUsage(); - $materialsRequestUsage->year = $period['year']; - $materialsRequestUsage->month = $period['month']; - $materialsRequestUsage->statusId = $status; - $materialsRequestUsage->find(); - - $row = []; - $date = "{$materialsRequestUsage->month}-{$materialsRequestUsage->year}"; - $row[] = $date; - - $thisStatus = new MaterialsRequestStatus(); - $thisStatus->libraryId = $libraryId; - $thisStatus->find(); - - $materialsRequestUsage = new MaterialsRequestUsage(); - $materialsRequestUsage->year = $period['year']; - $materialsRequestUsage->month = $period['month']; - $materialsRequestUsage->statusId = $thisStatus->id; - - if ($materialsRequestUsage->find(true)){ //if we find a match on year, month, and id/statusId - $row[] = $materialsRequestUsage->numUsed ?? 0; - }else{ - $row[] = 0; - } - fputcsv($fp, $row); - } - exit; - } - - function getBreadcrumbs(): array { - $breadcrumbs = []; - $breadcrumbs[] = new Breadcrumb('/Admin/Home', 'Administration Home'); - $breadcrumbs[] = new Breadcrumb('/Admin/Home#materialsrequest', 'Materials Request'); - $breadcrumbs[] = new Breadcrumb('/MaterialsRequest/Dashboard', 'Usage Dashboard'); - $breadcrumbs[] = new Breadcrumb('', 'Usage Graph'); - return $breadcrumbs; - } - - function getActiveAdminSection(): string { - return 'materials_request'; - } - - function canView(): bool { - return UserAccount::userHasPermission([ - 'View Dashboards', - 'View System Reports', - ]); - } -} \ No newline at end of file diff --git a/code/web/services/MaterialsRequest/UsageGraphs.php b/code/web/services/MaterialsRequest/UsageGraphs.php new file mode 100644 index 0000000000..d51c9448ed --- /dev/null +++ b/code/web/services/MaterialsRequest/UsageGraphs.php @@ -0,0 +1,100 @@ +launchGraph('MaterialsRequest'); + } + + public function getAllPeriods() { + $usage = new MaterialsRequestUsage(); + $usage->selectAdd(null); + $usage->selectAdd('DISTINCT year, month'); + $usage->find(); + + $stats = []; + while ($usage->fetch()) { + $stats[$usage->month . '-' . $usage->year]['year'] = $usage->year; + $stats[$usage->month . '-' . $usage->year]['month'] = $usage->month; + } + return $stats; + } + + function getBreadcrumbs(): array { + $breadcrumbs = []; + $breadcrumbs[] = new Breadcrumb('/Admin/Home', 'Administration Home'); + $breadcrumbs[] = new Breadcrumb('/Admin/Home#materialsrequest', 'Materials Request'); + $breadcrumbs[] = new Breadcrumb('/MaterialsRequest/Dashboard', 'Usage Dashboard'); + $breadcrumbs[] = new Breadcrumb('', 'Usage Graph'); + return $breadcrumbs; + } + + function getActiveAdminSection(): string { + return 'materials_request'; + } + + function canView(): bool { + return UserAccount::userHasPermission([ + 'View Dashboards', + 'View System Reports', + ]); + } + + protected function assignGraphSpecificTitle($stat): void {} //unnecessary as achieved programmatically in getAndSetInterfaceDataSeries + + private function getMaterialsRequestStatusDescription($status, $libraryId) { + $thisStatus = new MaterialsRequestStatus(); + $thisStatus->id = $status; + $thisStatus->libraryId = $libraryId; + $thisStatus->find(); + return $thisStatus->fetch()->description; + } + + protected function getAndSetInterfaceDataSeries($stat, $instanceName): void { + global $interface; + + $status = $_REQUEST['stat']; + $interface->assign('curStatus', $status); + $dataSeries = []; + + $userHomeLibrary = Library::getPatronHomeLibrary(); + if (is_null($userHomeLibrary)) { + //User does not have a home library, this is likely an admin account. Use the active library + global $library; + $userHomeLibrary = $library; + } + $libraryId = $userHomeLibrary->libraryId; + $statusDescription = $this->getMaterialsRequestStatusDescription($status, $libraryId); + + $title = 'Materials Request Usage Graph - ' . $statusDescription; + $materialsRequestUsage = new MaterialsRequestUsage(); + $materialsRequestUsage->groupBy('year, month'); + $materialsRequestUsage->selectAdd(); + $materialsRequestUsage->statusId = $status; + $materialsRequestUsage->selectAdd('year'); + $materialsRequestUsage->selectAdd('month'); + $materialsRequestUsage->selectAdd('SUM(numUsed) as numUsed'); + $materialsRequestUsage->orderBy('year, month'); + + $dataSeries[$statusDescription] = GraphingUtils::getDataSeriesArray(count($dataSeries)); + + //Collect results + $materialsRequestUsage->find(); + + while ($materialsRequestUsage->fetch()) { + $curPeriod = "{$materialsRequestUsage->month}-{$materialsRequestUsage->year}"; + $columnLabels[] = $curPeriod; + $dataSeries[$statusDescription]['data'][$curPeriod] = $materialsRequestUsage->numUsed; + } + + $interface->assign('columnLabels', $columnLabels); + $interface->assign('dataSeries', $dataSeries); + $interface->assign('graphTitle', $title); + $interface->assign('translateDataSeries', true); + $interface->assign('translateColumnLabels', false); + } +} \ No newline at end of file From 7d7762af0ffc0c40342dc85b52f26554f9d23fec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chlo=C3=A9=20Zermatten?= Date: Wed, 18 Sep 2024 11:29:38 +0100 Subject: [PATCH 14/16] refactor: SideLoads_UsageGraphs extends Abstract_UsageGraphs --- code/web/services/SideLoads/AJAX.php | 2 +- code/web/services/SideLoads/UsageGraphs.php | 99 +++------------------ 2 files changed, 14 insertions(+), 87 deletions(-) diff --git a/code/web/services/SideLoads/AJAX.php b/code/web/services/SideLoads/AJAX.php index 5f638f58d6..b04f9ae905 100644 --- a/code/web/services/SideLoads/AJAX.php +++ b/code/web/services/SideLoads/AJAX.php @@ -49,6 +49,6 @@ public function deleteMarc() { public function exportUsageData() { require_once ROOT_DIR . '/services/SideLoads/UsageGraphs.php'; $aspenUsageGraph = new SideLoads_UsageGraphs(); - $aspenUsageGraph->buildCSV(); + $aspenUsageGraph->buildCSV('SideLoads'); } } \ No newline at end of file diff --git a/code/web/services/SideLoads/UsageGraphs.php b/code/web/services/SideLoads/UsageGraphs.php index 4d64f41707..7d0701e5bb 100644 --- a/code/web/services/SideLoads/UsageGraphs.php +++ b/code/web/services/SideLoads/UsageGraphs.php @@ -1,35 +1,14 @@ assign('graphTitle', $title); - $this->assignGraphSpecificTitle($stat); - - $profileName= $_REQUEST['profileName']; - $sideloadId = $this->getSideloadIdBySideLoadName($profileName); - $this->getAndSetInterfaceDataSeries($stat, $instanceName, $sideloadId); - $interface->assign('profileName', $profileName); - $interface->assign('stat', $stat); - $interface->assign('propName', 'exportToCSV'); - $interface->assign('showCSVExportButton', true); - $interface->assign('section', 'SideLoads'); - - $title = $interface->getVariable('graphTitle'); - $this->display('../Admin/usage-graph.tpl', $title); +class SideLoads_UsageGraphs extends Admin_AbstractUsageGraphs { + function launch(): void { + $this->launchGraph('SideLoads'); } function getBreadcrumbs(): array { @@ -52,60 +31,13 @@ function canView(): bool { ]); } - // note that this will only handle tables with one stat (as is needed for Summon usage data) - // to see a version that handle multpile stats, see the Admin/UsageGraphs.php implementation - public function buildCSV() { - global $interface; - $stat = $_REQUEST['stat']; - if (!empty($_REQUEST['instance'])) { - $instanceName = $_REQUEST['instance']; - } else { - $instanceName = ''; - } - - $profileName= $_REQUEST['profileName']; - $sideloadId = $this->getSideloadIdBySideLoadName($profileName); - $this->getAndSetInterfaceDataSeries($stat, $instanceName, $sideloadId); - $dataSeries = $interface->getVariable('dataSeries'); - - $filename = "SideLoadsUsageData_{$stat}.csv"; - header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); - header("Cache-Control: no-store, no-cache, must-revalidate"); - header("Cache-Control: post-check=0, pre-check=0", false); - header("Pragma: no-cache"); - header('Content-Type: text/csv; charset=utf-8'); - header("Content-Disposition: attachment;filename={$filename}"); - $fp = fopen('php://output', 'w'); - - // builds the first row of the table in the CSV - column headers: Dates, and the title of the graph - fputcsv($fp, ['Dates', $stat]); - - // builds each subsequent data row - aka the column value - foreach ($dataSeries as $dataSerie) { - $data = $dataSerie['data']; - $numRows = count($data); - $dates = array_keys($data); - - if( empty($numRows)) { - fputcsv($fp, ['no data found!']); - } - for($i = 0; $i < $numRows; $i++) { - $date = $dates[$i]; - $value = $data[$date]; - $row = [$date, $value]; - fputcsv($fp, $row); - } - } - exit(); - } - /* The only unique identifier available to determine for which sideload to fetch data is the sideload's name as $profileName. It is used here to find the sideloads' id as only this exists on the sideload usage tables */ - private function getSideloadIdBySideLoadName($name) { + private function getSideloadIdBySideLoadName($name): int { $sideload = new SideLoad(); $sideload->whereAdd('name = "' . $name .'"'); $sideload->selectAdd(); @@ -113,13 +45,16 @@ private function getSideloadIdBySideLoadName($name) { return $sideload->fetch()->id; } - private function getAndSetInterfaceDataSeries($stat, $instanceName, $sideloadId) { + protected function getAndSetInterfaceDataSeries($stat, $instanceName): void { global $interface; $dataSeries = []; $columnLabels = []; $usage = []; + $profileName= $_REQUEST['subSection']; + $sideloadId = $this->getSideloadIdBySideLoadName($profileName); + // for the graph displaying data retrieved from the user_sideload_usage table if ($stat == 'activeUsers') { $usage = new UserSideLoadUsage(); @@ -133,11 +68,7 @@ private function getAndSetInterfaceDataSeries($stat, $instanceName, $sideloadId) $usage->selectAdd('month'); $usage->orderBy('year, month'); - $dataSeries['Active Users'] = [ - 'borderColor' => 'rgba(255, 99, 132, 1)', - 'backgroundColor' => 'rgba(255, 99, 132, 0.2)', - 'data' => [], - ]; + $dataSeries['Active Users'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $usage->selectAdd('COUNT(id) as numUsers'); } @@ -155,11 +86,7 @@ private function getAndSetInterfaceDataSeries($stat, $instanceName, $sideloadId) $usage->selectAdd('month'); $usage->orderBy('year, month'); - $dataSeries['Records Accessed Online'] = [ - 'borderColor' => 'rgba(255, 99, 132, 1)', - 'backgroundColor' => 'rgba(255, 99, 132, 0.2)', - 'data' => [], - ]; + $dataSeries['Records Accessed Online'] = GraphingUtils::getDataSeriesArray(count($dataSeries)); $usage->selectAdd('SUM(IF(timesUsed>0,1,0)) as numRecordsUsed'); } @@ -184,7 +111,7 @@ private function getAndSetInterfaceDataSeries($stat, $instanceName, $sideloadId) $interface->assign('translateColumnLabels', false); } - private function assignGraphSpecificTitle($stat) { + protected function assignGraphSpecificTitle($stat): void { global $interface; $title = $interface->getVariable('graphTitle'); if ($stat == 'activeUsers') { From c60eed2bbe6d96c1eaa570e689b0831913794f3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chlo=C3=A9=20Zermatten?= Date: Tue, 24 Sep 2024 10:30:10 +0100 Subject: [PATCH 15/16] refactor: remove redundant empty usage-graph.tpl file --- code/web/interface/themes/responsive/SideLoads/usage-graph.tpl | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 code/web/interface/themes/responsive/SideLoads/usage-graph.tpl diff --git a/code/web/interface/themes/responsive/SideLoads/usage-graph.tpl b/code/web/interface/themes/responsive/SideLoads/usage-graph.tpl deleted file mode 100644 index e69de29bb2..0000000000 From 1efe8b430488fe7baf6874d17952ad09cb6e4ede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chlo=C3=A9=20Zermatten?= Date: Fri, 20 Dec 2024 15:56:57 +0000 Subject: [PATCH 16/16] refactor: API_UsageGraphs implements AbstractUsageGraphs --- code/web/services/API/UsageGraphs.php | 28 ++------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/code/web/services/API/UsageGraphs.php b/code/web/services/API/UsageGraphs.php index 5fc4046654..50f66b8b5d 100644 --- a/code/web/services/API/UsageGraphs.php +++ b/code/web/services/API/UsageGraphs.php @@ -6,26 +6,9 @@ class API_UsageGraphs extends Admin_AbstractUsageGraphs { function launch(): void { - global $interface; - - $stat = $_REQUEST['stat']; - if (!empty($_REQUEST['instance'])) { - $instanceName = $_REQUEST['instance']; - } else { - $instanceName = ''; - } - - $title = 'Aspen Discovery API Usage Graph'; - $interface->assign('section', 'API'); - $interface->assign('showCSVExportButton', true); - $interface->assign('graphTitle', $title); - $this->assignGraphSpecificTitle($stat); - $this->getAndSetInterfaceDataSeries($stat, $instanceName); - $interface->assign('stat', $stat); - $interface->assign('propName', 'exportToCSV'); - $title = $interface->getVariable('graphTitle'); - $this->display('../Admin/usage-graph.tpl', $title); + $this->launchGraph('API'); } + function getBreadcrumbs(): array { $breadcrumbs = []; $breadcrumbs[] = new Breadcrumb('/Admin/Home', 'Administration Home'); @@ -39,13 +22,6 @@ function getActiveAdminSection(): string { return 'system_reports'; } - function canView(): bool { - return UserAccount::userHasPermission([ - 'View Dashboards', - 'View System Reports', - ]); - } - protected function getAndSetInterfaceDataSeries($stat, $instanceName): void { global $interface;