Files
dokuwiki-plugin-statdisplay/helper/graph.php
2022-12-07 13:54:29 +01:00

315 lines
9.5 KiB
PHP

<?php
/**
* statdisplay plugin graph helper component
*
* @author Andreas Gohr <gohr@cosmocode.de>
* @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
*/
class helper_plugin_statdisplay_graph extends DokuWiki_Plugin
{
/** @var helper_plugin_statdisplay_log */
private $log = null;
/**
* Outputs a Graph image
*
* @param string $command
* @param string $from
* @param string $to
* @return void
*/
public function sendgraph($command, $from = '', $to = '')
{
require dirname(__FILE__) . '/../pchart/pData.php';
require dirname(__FILE__) . '/../pchart/pChart.php';
require dirname(__FILE__) . '/../pchart/GDCanvas.php';
require dirname(__FILE__) . '/../pchart/PieChart.php';
$this->log = plugin_load('helper', 'statdisplay_log');
header('Content-Type: image/png');
switch ($command) {
case 'all':
$this->summary();
break;
case 'month by day':
$this->monthby('day', $from);
break;
case 'month by hour':
$this->monthby('hour', $from);
break;
case 'traffic by day':
$this->trafficby('day', $from);
break;
case 'traffic by hour':
$this->trafficby('hour', $from);
break;
case 'traffic by user':
$this->userdownloads($from);
break;
default:
$this->nograph('No such graph: ' . $command);
break;
}
}
/**
* Show all the access data
*
* @param string $from
* @param string $to
* @return void
*/
private function summary($from = '', $to = '')
{
$times = array();
$hits = array();
$pages = array();
$media = array();
$visitors = array();
foreach ($this->log->logdata as $month => $data) {
if ($month[0] == '_') continue;
if ($from && $month < $from) continue;
if ($to && $month > $to) break;
$times[] = $month;
$pages[] = $data['page']['all']['count'] ?? 0;
$media[] = $data['media']['all']['count'] ?? 0;
$hits[] = $data['hits']['all']['count'] ?? 0;
$visitors[] = $data['hits']['all']['visitor'] ?? 0;
}
$title = $this->getLang('t_summary');
$this->accessgraph(
$title,
$times,
array(
$this->getLang('hits'),
$this->getLang('pages'),
$this->getLang('media'),
$this->getLang('visitors'),
),
array($hits, $pages, $media, $visitors)
);
}
/**
* Show month access by day or hour
*
* @param string $by either day or hour
* @param string $date
*/
private function monthby($by, $date = '')
{
if (!$date) $date = date('Y-m');
$data = $this->log->logdata[$date];
$times = array();
$hits = array();
$pages = array();
$media = array();
$visitors = array();
$keys = array_keys((array)$data['hits'][$by]);
sort($keys);
foreach ($keys as $idx) {
$times[] = $idx;
$pages[] = $data['page'][$by][$idx]['count'];
$media[] = $data['media'][$by][$idx]['count'];
$hits[] = $data['hits'][$by][$idx]['count'];
$visitors[] = $data['hits'][$by][$idx]['visitor'];
}
$title = sprintf($this->getLang('t_' . $by), $date);
$this->accessgraph(
$title,
$times,
array(
$this->getLang('hits'),
$this->getLang('pages'),
$this->getLang('media'),
$this->getLang('visitors'),
),
array($hits, $pages, $media, $visitors)
);
}
/**
* Show month traffic by day or hour
*
* @param string $by either day or hour
* @param string $date
*/
private function trafficby($by, $date = '')
{
if (!$date) $date = date('Y-m');
$data = $this->log->logdata[$date];
$times = array();
$hits = array();
$pages = array();
$media = array();
foreach (array_keys((array)$data['hits'][$by]) as $idx) {
$times[] = $idx;
$pages[] = $data['page'][$by][$idx]['bytes'] / 1024;
$media[] = $data['media'][$by][$idx]['bytes'] / 1024;
$hits[] = $data['hits'][$by][$idx]['bytes'] / 1024;
}
$title = 'Traffic';
$this->accessgraph(
$title,
$times,
array(
$this->getLang('all'),
$this->getLang('pages'),
$this->getLang('media'),
),
array($hits, $pages, $media)
);
}
/**
* @param string $date month to display
*/
private function userdownloads($date)
{
$usertraffic = $this->log->usertraffic($date);
if (!$usertraffic) $this->nograph($this->getLang('t_usertraffic') . ': no data');
$usertraffic = array_map(function ($in) {
return $in / 1024 / 1024;
}, $usertraffic);
// get work day average
if (count($usertraffic)) {
$avg = $this->log->avg($usertraffic);
// $avg = $avg / 7 *5; //work day average
} else {
$avg = 0;
}
arsort($usertraffic); // highest first
// limit number of users shown
$maxusers = 10;
if (count($usertraffic) > $maxusers + 1) {
$others = array_slice($usertraffic, $maxusers);
$usertraffic = array_slice($usertraffic, 0, $maxusers);
$other = 0;
foreach ($others as $user => $traffic) {
$other += $traffic;
}
$usertraffic[sprintf($this->getLang('others'), count($others))] = $other;
}
// prepare the graph datasets
$DataSet = new pData();
$DataSet->addPoints(array_values($usertraffic), "traffic");
// setup axis
$DataSet->AddPoints(array_keys($usertraffic), 'names');
$DataSet->AddAllSeries();
$DataSet->SetAbscissaLabelSeries('names');
$DataSet->removeSeries('names');
$DataSet->removeSeriesName('names');
// create the bar graph
$Canvas = new GDCanvas(600, 300, false);
$Chart = new pChart(600, 300, $Canvas);
$Chart->setFontProperties(dirname(__FILE__) . '/../pchart/Fonts/DroidSans.ttf', 8);
$Chart->setGraphArea(50, 40, 600, 200);
$Chart->drawScale(
$DataSet, new ScaleStyle(SCALE_NORMAL, new Color(127)),
45, 1, true
);
$Chart->drawBarGraph($DataSet->GetData(), $DataSet->GetDataDescription());
//$Chart->drawLegend(500, 40, $DataSet->GetDataDescription(), new Color(250));
$Chart->drawTreshold($avg, new Color(128, 0, 0));
$Chart->setFontProperties(dirname(__FILE__) . '/../pchart/Fonts/DroidSans.ttf', 12);
$Chart->drawTitle(10, 10, $this->getLang('t_usertraffic') . ' (MB)', new Color(0), 590, 30);
$Chart->Render(null);
}
/**
* Draws a line or bargraph depending on the number of data points
*
* @param string $title the graph's title
* @param array $axis the axis points
* @param array $labels the labels for the datasets
* @param array $datasets any number of data arrays
*/
private function accessgraph($title, $axis, $labels, $datasets)
{
if (!count($axis)) {
$this->nograph($title . ': no data');
return;
}
// add the data and labels
$DataSet = new pData();
foreach ($datasets as $num => $set) {
$DataSet->AddPoints($set, "series$num");
$DataSet->SetSeriesName($labels[$num], "series$num");
}
// setup axis
$DataSet->AddPoints($axis, 'times');
$DataSet->AddAllSeries();
$DataSet->SetAbscissaLabelSeries('times');
$DataSet->removeSeries('times');
$DataSet->removeSeriesName('times');
$Canvas = new GDCanvas(600, 300, false);
$Chart = new pChart(600, 300, $Canvas);
$usebargraph = (count($axis) < 10);
$Chart->setFontProperties(dirname(__FILE__) . '/../pchart/Fonts/DroidSans.ttf', 8);
$Chart->setGraphArea(50, 40, 500, 200);
$Chart->drawScale(
$DataSet, new ScaleStyle(SCALE_NORMAL, new Color(127)),
45, 1, $usebargraph
);
if ($usebargraph) {
$Chart->drawBarGraph($DataSet->GetData(), $DataSet->GetDataDescription());
} else {
$Chart->drawLineGraph($DataSet->GetData(), $DataSet->GetDataDescription());
}
$Chart->drawLegend(500, 40, $DataSet->GetDataDescription(), new Color(250));
$Chart->setFontProperties(dirname(__FILE__) . '/../pchart/Fonts/DroidSans.ttf', 12);
$Chart->drawTitle(10, 10, $title, new Color(0), 590, 30);
$Chart->Render(null);
}
/**
* Just creates a message
*
* @param $title
*/
private function nograph($title)
{
$Canvas = new GDCanvas(300, 40, false);
$Chart = new pChart(300, 40, $Canvas);
$Chart->setFontProperties(dirname(__FILE__) . '/../pchart/Fonts/DroidSans.ttf', 10);
$Chart->drawTitle(0, 0, $title, new Color(128, 0, 0), 300, 40);
$Chart->Render(null);
exit;
}
}