PDF rausgenommen
This commit is contained in:
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\Plugins\ImageGraph\StaticGraph;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class Evolution extends GridGraph
|
||||
{
|
||||
|
||||
public function renderGraph()
|
||||
{
|
||||
$this->initGridChart(
|
||||
$displayVerticalGridLines = true,
|
||||
$bulletType = LEGEND_FAMILY_LINE,
|
||||
$horizontalGraph = false,
|
||||
$showTicks = true,
|
||||
$verticalLegend = true
|
||||
);
|
||||
|
||||
$this->pImage->drawLineChart();
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\Plugins\ImageGraph\StaticGraph;
|
||||
|
||||
use CpChart\Chart\Data;
|
||||
use Piwik\Plugins\ImageGraph\StaticGraph;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class Exception extends StaticGraph
|
||||
{
|
||||
const MESSAGE_RIGHT_MARGIN = 5;
|
||||
|
||||
/**
|
||||
* @var \Exception
|
||||
*/
|
||||
private $exception;
|
||||
|
||||
public function setException(\Exception $exception)
|
||||
{
|
||||
$this->exception = $exception;
|
||||
}
|
||||
|
||||
protected function getDefaultColors()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function setWidth($width)
|
||||
{
|
||||
if (empty($width)) {
|
||||
$width = 450;
|
||||
}
|
||||
parent::setWidth($width);
|
||||
}
|
||||
|
||||
public function setHeight($height)
|
||||
{
|
||||
if (empty($height)) {
|
||||
$height = 300;
|
||||
}
|
||||
parent::setHeight($height);
|
||||
}
|
||||
|
||||
public function renderGraph()
|
||||
{
|
||||
$this->pData = new Data();
|
||||
|
||||
$message = $this->exception->getMessage();
|
||||
list($textWidth, $textHeight) = $this->getTextWidthHeight($message);
|
||||
|
||||
if ($this->width == null) {
|
||||
$this->width = $textWidth + self::MESSAGE_RIGHT_MARGIN;
|
||||
}
|
||||
|
||||
if ($this->height == null) {
|
||||
$this->height = $textHeight;
|
||||
}
|
||||
|
||||
$this->initpImage();
|
||||
|
||||
$this->drawBackground();
|
||||
|
||||
$this->pImage->drawText(
|
||||
0,
|
||||
$textHeight,
|
||||
$message,
|
||||
$this->textColor
|
||||
);
|
||||
}
|
||||
}
|
485
msd2/tracking/piwik/plugins/ImageGraph/StaticGraph/GridGraph.php
Normal file
485
msd2/tracking/piwik/plugins/ImageGraph/StaticGraph/GridGraph.php
Normal file
@ -0,0 +1,485 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\Plugins\ImageGraph\StaticGraph;
|
||||
|
||||
use Piwik\Plugins\ImageGraph\StaticGraph;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
abstract class GridGraph extends StaticGraph
|
||||
{
|
||||
const GRAPHIC_COLOR_KEY = 'GRAPHIC_COLOR';
|
||||
|
||||
const TRUNCATION_TEXT = '...';
|
||||
|
||||
const DEFAULT_TICK_ALPHA = 20;
|
||||
const DEFAULT_SERIE_WEIGHT = 0.5;
|
||||
const LEFT_GRID_MARGIN = 4;
|
||||
const BOTTOM_GRID_MARGIN = 10;
|
||||
const TOP_GRID_MARGIN_HORIZONTAL_GRAPH = 1;
|
||||
const RIGHT_GRID_MARGIN_HORIZONTAL_GRAPH = 4;
|
||||
const OUTER_TICK_WIDTH = 5;
|
||||
const INNER_TICK_WIDTH = 0;
|
||||
const LABEL_SPACE_VERTICAL_GRAPH = 7;
|
||||
|
||||
const HORIZONTAL_LEGEND_TOP_MARGIN = 5;
|
||||
const HORIZONTAL_LEGEND_LEFT_MARGIN = 10;
|
||||
const HORIZONTAL_LEGEND_BOTTOM_MARGIN = 10;
|
||||
const VERTICAL_LEGEND_TOP_MARGIN = 8;
|
||||
const VERTICAL_LEGEND_LEFT_MARGIN = 6;
|
||||
const VERTICAL_LEGEND_MAX_WIDTH_PCT = 0.70;
|
||||
const LEGEND_LINE_BULLET_WIDTH = 14;
|
||||
const LEGEND_BOX_BULLET_WIDTH = 5;
|
||||
const LEGEND_BULLET_RIGHT_PADDING = 5;
|
||||
const LEGEND_ITEM_HORIZONTAL_INTERSTICE = 6;
|
||||
const LEGEND_ITEM_VERTICAL_INTERSTICE_OFFSET = 4;
|
||||
const LEGEND_SHADOW_OPACITY = 25;
|
||||
const LEGEND_VERTICAL_SHADOW_PADDING = 3;
|
||||
const LEGEND_HORIZONTAL_SHADOW_PADDING = 2;
|
||||
const PCHART_HARD_CODED_VERTICAL_LEGEND_INTERSTICE = 5;
|
||||
|
||||
protected function getDefaultColors()
|
||||
{
|
||||
return array(
|
||||
self::GRAPHIC_COLOR_KEY . '1' => '5170AE',
|
||||
self::GRAPHIC_COLOR_KEY . '2' => 'F29007',
|
||||
self::GRAPHIC_COLOR_KEY . '3' => 'CC3399',
|
||||
self::GRAPHIC_COLOR_KEY . '4' => '9933CC',
|
||||
self::GRAPHIC_COLOR_KEY . '5' => '80A033',
|
||||
self::GRAPHIC_COLOR_KEY . '6' => '246AD2'
|
||||
);
|
||||
}
|
||||
|
||||
protected function initGridChart(
|
||||
$displayVerticalGridLines,
|
||||
$bulletType,
|
||||
$horizontalGraph,
|
||||
$showTicks,
|
||||
$verticalLegend
|
||||
)
|
||||
{
|
||||
$this->initpData();
|
||||
|
||||
$colorIndex = 1;
|
||||
foreach ($this->ordinateSeries as $column => $data) {
|
||||
$this->pData->setSerieWeight($column, self::DEFAULT_SERIE_WEIGHT);
|
||||
$graphicColor = $this->colors[self::GRAPHIC_COLOR_KEY . $colorIndex++];
|
||||
$this->pData->setPalette($column, $graphicColor);
|
||||
}
|
||||
|
||||
$this->initpImage();
|
||||
|
||||
// graph area coordinates
|
||||
$topLeftXValue = $this->getGridLeftMargin($horizontalGraph, $withLabel = true);
|
||||
$topLeftYValue = $this->getGridTopMargin($horizontalGraph, $verticalLegend);
|
||||
$bottomRightXValue = $this->width - $this->getGridRightMargin($horizontalGraph);
|
||||
$bottomRightYValue = $this->getGraphBottom($horizontalGraph);
|
||||
|
||||
$this->drawBackground();
|
||||
|
||||
$this->pImage->setGraphArea(
|
||||
$topLeftXValue,
|
||||
$topLeftYValue,
|
||||
$bottomRightXValue,
|
||||
$bottomRightYValue
|
||||
);
|
||||
|
||||
// determine how many labels need to be skipped
|
||||
$skippedLabels = 0;
|
||||
if (!$horizontalGraph) {
|
||||
list($abscissaMaxWidth, $abscissaMaxHeight) = $this->getMaximumTextWidthHeight($this->abscissaSeries);
|
||||
$graphWidth = $bottomRightXValue - $topLeftXValue;
|
||||
$maxNumOfLabels = floor($graphWidth / ($abscissaMaxWidth + self::LABEL_SPACE_VERTICAL_GRAPH));
|
||||
|
||||
$abscissaSeriesCount = count($this->abscissaSeries);
|
||||
if ($maxNumOfLabels < $abscissaSeriesCount) {
|
||||
for ($candidateSkippedLabels = 1; $candidateSkippedLabels < $abscissaSeriesCount; $candidateSkippedLabels++) {
|
||||
$numberOfSegments = $abscissaSeriesCount / ($candidateSkippedLabels + 1);
|
||||
$numberOfCompleteSegments = floor($numberOfSegments);
|
||||
|
||||
$numberOfLabels = $numberOfCompleteSegments;
|
||||
if ($numberOfSegments > $numberOfCompleteSegments) {
|
||||
$numberOfLabels++;
|
||||
}
|
||||
|
||||
if ($numberOfLabels <= $maxNumOfLabels) {
|
||||
$skippedLabels = $candidateSkippedLabels;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->forceSkippedLabels
|
||||
&& $skippedLabels
|
||||
&& $skippedLabels < $this->forceSkippedLabels
|
||||
&& $abscissaSeriesCount > $this->forceSkippedLabels + 1
|
||||
) {
|
||||
$skippedLabels = $this->forceSkippedLabels;
|
||||
}
|
||||
}
|
||||
|
||||
$ordinateAxisLength =
|
||||
$horizontalGraph ? $bottomRightXValue - $topLeftXValue : $this->getGraphHeight($horizontalGraph, $verticalLegend);
|
||||
|
||||
$maxOrdinateValue = 0;
|
||||
foreach ($this->ordinateSeries as $column => $data) {
|
||||
$currentMax = $this->pData->getMax($column);
|
||||
|
||||
if ($currentMax > $maxOrdinateValue) {
|
||||
$maxOrdinateValue = $currentMax;
|
||||
}
|
||||
}
|
||||
|
||||
// rounding top scale value to the next multiple of 10
|
||||
if ($maxOrdinateValue > 10) {
|
||||
$modTen = $maxOrdinateValue % 10;
|
||||
if ($modTen) $maxOrdinateValue += 10 - $modTen;
|
||||
}
|
||||
|
||||
$gridColor = $this->gridColor;
|
||||
$this->pImage->drawScale(
|
||||
array(
|
||||
'Mode' => SCALE_MODE_MANUAL,
|
||||
'GridTicks' => 0,
|
||||
'LabelSkip' => $skippedLabels,
|
||||
'DrawXLines' => $displayVerticalGridLines,
|
||||
'Factors' => array(ceil($maxOrdinateValue / 2)),
|
||||
'MinDivHeight' => $ordinateAxisLength / 2,
|
||||
'AxisAlpha' => 0,
|
||||
'SkippedAxisAlpha' => 0,
|
||||
'TickAlpha' => $showTicks ? self::DEFAULT_TICK_ALPHA : 0,
|
||||
'InnerTickWidth' => self::INNER_TICK_WIDTH,
|
||||
'OuterTickWidth' => self::OUTER_TICK_WIDTH,
|
||||
'GridR' => $gridColor['R'],
|
||||
'GridG' => $gridColor['G'],
|
||||
'GridB' => $gridColor['B'],
|
||||
'GridAlpha' => 100,
|
||||
'ManualScale' => array(
|
||||
0 => array(
|
||||
'Min' => 0,
|
||||
'Max' => $maxOrdinateValue
|
||||
)
|
||||
),
|
||||
'Pos' => $horizontalGraph ? SCALE_POS_TOPBOTTOM : SCALE_POS_LEFTRIGHT,
|
||||
)
|
||||
);
|
||||
|
||||
if ($this->showLegend) {
|
||||
switch ($bulletType) {
|
||||
case LEGEND_FAMILY_LINE:
|
||||
$bulletWidth = self::LEGEND_LINE_BULLET_WIDTH;
|
||||
|
||||
// measured using a picture editing software
|
||||
$iconOffsetAboveLabelSymmetryAxis = -2;
|
||||
break;
|
||||
|
||||
case LEGEND_FAMILY_BOX:
|
||||
$bulletWidth = self::LEGEND_BOX_BULLET_WIDTH;
|
||||
|
||||
// measured using a picture editing software
|
||||
$iconOffsetAboveLabelSymmetryAxis = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
// pChart requires two coordinates to draw the legend $legendTopLeftXValue & $legendTopLeftYValue
|
||||
// $legendTopLeftXValue = legend's left padding
|
||||
$legendTopLeftXValue = $topLeftXValue + ($verticalLegend ? self::VERTICAL_LEGEND_LEFT_MARGIN : self::HORIZONTAL_LEGEND_LEFT_MARGIN);
|
||||
|
||||
// $legendTopLeftYValue = y coordinate of the top edge of the legend's icons
|
||||
// Caution :
|
||||
// - pChart will silently add some value (see $paddingAddedByPChart) to $legendTopLeftYValue depending on multiple criteria
|
||||
// - pChart will not take into account the size of the text. Setting $legendTopLeftYValue = 0 will crop the legend's labels
|
||||
// The following section of code determines the value of $legendTopLeftYValue while taking into account the following paremeters :
|
||||
// - whether legend items have icons
|
||||
// - whether icons are bigger than the legend's labels
|
||||
// - how much colored shadow padding is required
|
||||
list($maxLogoWidth, $maxLogoHeight) = self::getMaxLogoSize(array_values($this->ordinateLogos));
|
||||
if ($maxLogoHeight >= $this->legendFontSize) {
|
||||
$heightOfTextAboveBulletTop = 0;
|
||||
$paddingCreatedByLogo = $maxLogoHeight - $this->legendFontSize;
|
||||
$effectiveShadowPadding = $paddingCreatedByLogo < self::LEGEND_VERTICAL_SHADOW_PADDING * 2 ? self::LEGEND_VERTICAL_SHADOW_PADDING - ($paddingCreatedByLogo / 2) : 0;
|
||||
} else {
|
||||
if ($maxLogoHeight) {
|
||||
// measured using a picture editing software
|
||||
$iconOffsetAboveLabelSymmetryAxis = 5;
|
||||
}
|
||||
$heightOfTextAboveBulletTop = $this->legendFontSize / 2 - $iconOffsetAboveLabelSymmetryAxis;
|
||||
$effectiveShadowPadding = self::LEGEND_VERTICAL_SHADOW_PADDING;
|
||||
}
|
||||
|
||||
$effectiveLegendItemVerticalInterstice = $this->legendFontSize + self::LEGEND_ITEM_VERTICAL_INTERSTICE_OFFSET;
|
||||
$effectiveLegendItemHorizontalInterstice = self::LEGEND_ITEM_HORIZONTAL_INTERSTICE + self::LEGEND_HORIZONTAL_SHADOW_PADDING;
|
||||
|
||||
$legendTopMargin = $verticalLegend ? self::VERTICAL_LEGEND_TOP_MARGIN : self::HORIZONTAL_LEGEND_TOP_MARGIN;
|
||||
$requiredPaddingAboveItemBullet = $legendTopMargin + $heightOfTextAboveBulletTop + $effectiveShadowPadding;
|
||||
|
||||
$paddingAddedByPChart = 0;
|
||||
if ($verticalLegend) {
|
||||
if ($maxLogoHeight) {
|
||||
// see line 1691 of pDraw.class.php
|
||||
if ($maxLogoHeight < $effectiveLegendItemVerticalInterstice) {
|
||||
$paddingAddedByPChart = ($effectiveLegendItemVerticalInterstice / 2) - ($maxLogoHeight / 2);
|
||||
}
|
||||
} else {
|
||||
// see line 1711 of pDraw.class.php ($Y+$IconAreaHeight/2)
|
||||
$paddingAddedByPChart = $effectiveLegendItemVerticalInterstice / 2;
|
||||
}
|
||||
}
|
||||
|
||||
$legendTopLeftYValue = $paddingAddedByPChart < $requiredPaddingAboveItemBullet ? $requiredPaddingAboveItemBullet - $paddingAddedByPChart : 0;
|
||||
|
||||
// add colored background to each legend item
|
||||
if (count($this->ordinateLabels) > 1) {
|
||||
$currentPosition = $verticalLegend ? $legendTopMargin : $legendTopLeftXValue;
|
||||
$colorIndex = 1;
|
||||
foreach ($this->ordinateLabels as $metricCode => &$label) {
|
||||
$color = $this->colors[self::GRAPHIC_COLOR_KEY . $colorIndex++];
|
||||
|
||||
$paddedBulletWidth = $bulletWidth;
|
||||
if (isset($this->ordinateLogos[$metricCode])) {
|
||||
$paddedBulletWidth = $maxLogoWidth;
|
||||
}
|
||||
$paddedBulletWidth += self::LEGEND_BULLET_RIGHT_PADDING;
|
||||
|
||||
// truncate labels if required
|
||||
if ($verticalLegend) {
|
||||
$label = $this->truncateLabel($label, ($this->width * self::VERTICAL_LEGEND_MAX_WIDTH_PCT) - $legendTopLeftXValue - $paddedBulletWidth, $this->legendFontSize);
|
||||
$this->pData->setSerieDescription($metricCode, $label);
|
||||
}
|
||||
|
||||
$rectangleTopLeftXValue = ($verticalLegend ? $legendTopLeftXValue : $currentPosition) + $paddedBulletWidth - self::LEGEND_HORIZONTAL_SHADOW_PADDING;
|
||||
$rectangleTopLeftYValue = $verticalLegend ? $currentPosition : $legendTopMargin;
|
||||
|
||||
list($labelWidth, $labelHeight) = $this->getTextWidthHeight($label, $this->legendFontSize);
|
||||
$legendItemWidth = $paddedBulletWidth + $labelWidth + $effectiveLegendItemHorizontalInterstice;
|
||||
$rectangleBottomRightXValue = $rectangleTopLeftXValue + $labelWidth + (self::LEGEND_HORIZONTAL_SHADOW_PADDING * 2);
|
||||
|
||||
$legendItemHeight = max($maxLogoHeight, $this->legendFontSize) + ($effectiveShadowPadding * 2);
|
||||
$rectangleBottomRightYValue = $rectangleTopLeftYValue + $legendItemHeight;
|
||||
|
||||
$this->pImage->drawFilledRectangle(
|
||||
$rectangleTopLeftXValue,
|
||||
$rectangleTopLeftYValue,
|
||||
$rectangleBottomRightXValue,
|
||||
$rectangleBottomRightYValue,
|
||||
array(
|
||||
'Alpha' => self::LEGEND_SHADOW_OPACITY,
|
||||
'R' => $color['R'],
|
||||
'G' => $color['G'],
|
||||
'B' => $color['B'],
|
||||
)
|
||||
);
|
||||
|
||||
if ($verticalLegend) {
|
||||
$currentPositionIncrement = max($maxLogoHeight, $effectiveLegendItemVerticalInterstice, $this->legendFontSize) + self::PCHART_HARD_CODED_VERTICAL_LEGEND_INTERSTICE;
|
||||
} else {
|
||||
$currentPositionIncrement = $legendItemWidth;
|
||||
}
|
||||
|
||||
$currentPosition += $currentPositionIncrement;
|
||||
}
|
||||
}
|
||||
|
||||
// draw legend
|
||||
$legendColor = $this->textColor;
|
||||
$this->pImage->drawLegend(
|
||||
$legendTopLeftXValue,
|
||||
$legendTopLeftYValue,
|
||||
array(
|
||||
'Style' => LEGEND_NOBORDER,
|
||||
'FontSize' => $this->legendFontSize,
|
||||
'BoxWidth' => $bulletWidth,
|
||||
'XSpacing' => $effectiveLegendItemHorizontalInterstice, // not effective when vertical
|
||||
'Mode' => $verticalLegend ? LEGEND_VERTICAL : LEGEND_HORIZONTAL,
|
||||
'BoxHeight' => $verticalLegend ? $effectiveLegendItemVerticalInterstice : null,
|
||||
'Family' => $bulletType,
|
||||
'FontR' => $legendColor['R'],
|
||||
'FontG' => $legendColor['G'],
|
||||
'FontB' => $legendColor['B'],
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected static function getMaxLogoSize($logoPaths)
|
||||
{
|
||||
$maxLogoWidth = 0;
|
||||
$maxLogoHeight = 0;
|
||||
foreach ($logoPaths as $logoPath) {
|
||||
list($logoWidth, $logoHeight) = self::getLogoSize($logoPath);
|
||||
|
||||
if ($logoWidth > $maxLogoWidth) {
|
||||
$maxLogoWidth = $logoWidth;
|
||||
}
|
||||
if ($logoHeight > $maxLogoHeight) {
|
||||
$maxLogoHeight = $logoHeight;
|
||||
}
|
||||
}
|
||||
|
||||
return array($maxLogoWidth, $maxLogoHeight);
|
||||
}
|
||||
|
||||
protected static function getLogoSize($logoPath)
|
||||
{
|
||||
$pathInfo = getimagesize($logoPath);
|
||||
return array($pathInfo[0], $pathInfo[1]);
|
||||
}
|
||||
|
||||
protected function getGridLeftMargin($horizontalGraph, $withLabel)
|
||||
{
|
||||
$gridLeftMargin = self::LEFT_GRID_MARGIN + self::OUTER_TICK_WIDTH;
|
||||
|
||||
if ($withLabel) {
|
||||
list($maxTextWidth, $maxTextHeight) = $this->getMaximumTextWidthHeight($horizontalGraph ? $this->abscissaSeries : $this->ordinateSeries);
|
||||
$gridLeftMargin += $maxTextWidth;
|
||||
}
|
||||
|
||||
return $gridLeftMargin;
|
||||
}
|
||||
|
||||
protected function getGridTopMargin($horizontalGraph, $verticalLegend)
|
||||
{
|
||||
list($ordinateMaxWidth, $ordinateMaxHeight) = $this->getMaximumTextWidthHeight($this->ordinateSeries);
|
||||
|
||||
if ($horizontalGraph) {
|
||||
$topMargin = $ordinateMaxHeight + self::TOP_GRID_MARGIN_HORIZONTAL_GRAPH + self::OUTER_TICK_WIDTH;
|
||||
} else {
|
||||
$topMargin = $ordinateMaxHeight / 2;
|
||||
}
|
||||
|
||||
if ($this->showLegend && !$verticalLegend) {
|
||||
$topMargin += $this->getHorizontalLegendHeight();
|
||||
}
|
||||
|
||||
return $topMargin;
|
||||
}
|
||||
|
||||
private function getHorizontalLegendHeight()
|
||||
{
|
||||
list($maxMetricLegendWidth, $maxMetricLegendHeight) =
|
||||
$this->getMaximumTextWidthHeight(array_values($this->ordinateLabels), $this->legendFontSize);
|
||||
|
||||
return $maxMetricLegendHeight + self::HORIZONTAL_LEGEND_BOTTOM_MARGIN + self::HORIZONTAL_LEGEND_TOP_MARGIN;
|
||||
}
|
||||
|
||||
protected function getGraphHeight($horizontalGraph, $verticalLegend)
|
||||
{
|
||||
return $this->getGraphBottom($horizontalGraph) - $this->getGridTopMargin($horizontalGraph, $verticalLegend);
|
||||
}
|
||||
|
||||
private function getGridBottomMargin($horizontalGraph)
|
||||
{
|
||||
$gridBottomMargin = self::BOTTOM_GRID_MARGIN;
|
||||
if (!$horizontalGraph) {
|
||||
list($abscissaMaxWidth, $abscissaMaxHeight) = $this->getMaximumTextWidthHeight($this->abscissaSeries);
|
||||
$gridBottomMargin += $abscissaMaxHeight;
|
||||
}
|
||||
return $gridBottomMargin;
|
||||
}
|
||||
|
||||
protected function getGridRightMargin($horizontalGraph)
|
||||
{
|
||||
if ($horizontalGraph) {
|
||||
// in horizontal graphs, metric values are displayed on the far right of the bar
|
||||
list($ordinateMaxWidth, $ordinateMaxHeight) = $this->getMaximumTextWidthHeight($this->ordinateSeries);
|
||||
return self::RIGHT_GRID_MARGIN_HORIZONTAL_GRAPH + $ordinateMaxWidth;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected function getGraphBottom($horizontalGraph)
|
||||
{
|
||||
return $this->height - $this->getGridBottomMargin($horizontalGraph);
|
||||
}
|
||||
|
||||
protected function truncateLabel($label, $labelWidthLimit, $fontSize = false)
|
||||
{
|
||||
list($truncationTextWidth, $truncationTextHeight) = $this->getTextWidthHeight(self::TRUNCATION_TEXT, $fontSize);
|
||||
list($labelWidth, $labelHeight) = $this->getTextWidthHeight($label, $fontSize);
|
||||
|
||||
if ($labelWidth > $labelWidthLimit) {
|
||||
$averageCharWidth = $labelWidth / strlen($label);
|
||||
$charsToKeep = floor(($labelWidthLimit - $truncationTextWidth) / $averageCharWidth);
|
||||
$label = substr($label, 0, $charsToKeep) . self::TRUNCATION_TEXT;
|
||||
}
|
||||
return $label;
|
||||
}
|
||||
// display min & max values
|
||||
// can not currently be used because pChart's label design is not flexible enough
|
||||
// e.g: it is not possible to remove the box border & the square icon
|
||||
// it would require modifying pChart code base which we try to avoid
|
||||
// see https://github.com/piwik/piwik/issues/3396
|
||||
// protected function displayMinMaxValues()
|
||||
// {
|
||||
// if ($displayMinMax)
|
||||
// {
|
||||
// // when plotting multiple metrics, display min & max on both series
|
||||
// // to fix: in vertical bars, labels are hidden when multiple metrics are plotted, hence the restriction on count($this->ordinateSeries) == 1
|
||||
// if ($this->multipleMetrics && count($this->ordinateSeries) == 1)
|
||||
// {
|
||||
// $colorIndex = 1;
|
||||
// foreach($this->ordinateSeries as $column => $data)
|
||||
// {
|
||||
// $color = $this->colors[self::GRAPHIC_COLOR_KEY . $colorIndex++];
|
||||
//
|
||||
// $this->pImage->writeLabel(
|
||||
// $column,
|
||||
// self::locateMinMaxValue($data),
|
||||
// $Format = array(
|
||||
// 'NoTitle' => true,
|
||||
// 'DrawPoint' => false,
|
||||
// 'DrawSerieColor' => true,
|
||||
// 'TitleMode' => LABEL_TITLE_NOBACKGROUND,
|
||||
// 'GradientStartR' => $color['R'],
|
||||
// 'GradientStartG' => $color['G'],
|
||||
// 'GradientStartB' => $color['B'],
|
||||
// 'GradientEndR' => 255,
|
||||
// 'GradientEndG' => 255,
|
||||
// 'GradientEndB' => 255,
|
||||
// 'BoxWidth' => 0,
|
||||
// 'VerticalMargin' => 9,
|
||||
// 'HorizontalMargin' => 7,
|
||||
// )
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // display only one min & max label
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// protected static function locateMinMaxValue($data)
|
||||
// {
|
||||
// $firstValue = $data[0];
|
||||
// $minValue = $firstValue;
|
||||
// $minValueIndex = 0;
|
||||
// $maxValue = $firstValue;
|
||||
// $maxValueIndex = 0;
|
||||
// foreach($data as $index => $value)
|
||||
// {
|
||||
// if ($value > $maxValue)
|
||||
// {
|
||||
// $maxValue = $value;
|
||||
// $maxValueIndex = $index;
|
||||
// }
|
||||
//
|
||||
// if ($value < $minValue)
|
||||
// {
|
||||
// $minValue = $value;
|
||||
// $minValueIndex = $index;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return array($minValueIndex, $maxValueIndex);
|
||||
// }
|
||||
}
|
@ -0,0 +1,187 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\Plugins\ImageGraph\StaticGraph;
|
||||
use Piwik\Piwik;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class HorizontalBar extends GridGraph
|
||||
{
|
||||
const INTERLEAVE = 0.30;
|
||||
const PADDING_CHARS = ' ';
|
||||
const LEGEND_SQUARE_WIDTH = 11;
|
||||
const MIN_SPACE_BETWEEN_HORIZONTAL_VALUES = 5;
|
||||
const LOGO_MIN_RIGHT_MARGIN = 3;
|
||||
|
||||
public function renderGraph()
|
||||
{
|
||||
$verticalLegend = false;
|
||||
|
||||
// create resized copies of logo to match maximum width / height
|
||||
foreach ($this->abscissaLogos as &$logoPath) {
|
||||
$logoPath = $this->createResizedImageCopyIfNeeded($logoPath);
|
||||
list($logoWidth, $logoHeight) = self::getLogoSize($logoPath);
|
||||
$logoPathToHeight[$logoPath] = $logoHeight;
|
||||
}
|
||||
|
||||
// determine the maximum logo width & height
|
||||
list($maxLogoWidth, $maxLogoHeight) = self::getMaxLogoSize($this->abscissaLogos);
|
||||
|
||||
// truncate report
|
||||
$graphHeight = $this->getGraphBottom($horizontalGraph = true) - $this->getGridTopMargin($horizontalGraph = true, $verticalLegend);
|
||||
|
||||
list($abscissaMaxWidth, $abscissaMaxHeight) = $this->getMaximumTextWidthHeight($this->abscissaSeries);
|
||||
list($ordinateMaxWidth, $ordinateMaxHeight) = $this->getMaximumTextWidthHeight($this->ordinateSeries);
|
||||
|
||||
$numberOfSeries = count($this->ordinateSeries);
|
||||
$ordinateMaxHeight = $ordinateMaxHeight * $numberOfSeries;
|
||||
|
||||
$textMaxHeight = $abscissaMaxHeight > $ordinateMaxHeight ? $abscissaMaxHeight : $ordinateMaxHeight;
|
||||
|
||||
$minLineWidth = ($textMaxHeight > $maxLogoHeight ? $textMaxHeight : $maxLogoHeight) + (self::MIN_SPACE_BETWEEN_HORIZONTAL_VALUES * $numberOfSeries);
|
||||
$maxNumOfValues = floor($graphHeight / $minLineWidth);
|
||||
$abscissaSeriesCount = count($this->abscissaSeries);
|
||||
|
||||
if ($maxNumOfValues < $abscissaSeriesCount - 1) {
|
||||
$sumOfOthers = array();
|
||||
$truncatedOrdinateSeries = array();
|
||||
$truncatedAbscissaLogos = array();
|
||||
$truncatedAbscissaSeries = array();
|
||||
foreach ($this->ordinateSeries as $column => $data) {
|
||||
$truncatedOrdinateSeries[$column] = array();
|
||||
$sumOfOthers[$column] = 0;
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
for (; $i < $maxNumOfValues; $i++) {
|
||||
foreach ($this->ordinateSeries as $column => $data) {
|
||||
$truncatedOrdinateSeries[$column][] = $data[$i];
|
||||
}
|
||||
|
||||
$truncatedAbscissaLogos[] = isset($this->abscissaLogos[$i]) ? $this->abscissaLogos[$i] : null;
|
||||
$truncatedAbscissaSeries[] = $this->abscissaSeries[$i];
|
||||
}
|
||||
|
||||
for (; $i < $abscissaSeriesCount; $i++) {
|
||||
foreach ($this->ordinateSeries as $column => $data) {
|
||||
$sumOfOthers[$column] += $data[$i];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->ordinateSeries as $column => $data) {
|
||||
$truncatedOrdinateSeries[$column][] = $sumOfOthers[$column];
|
||||
}
|
||||
|
||||
$truncatedAbscissaSeries[] = Piwik::translate('General_Others');
|
||||
$this->abscissaSeries = $truncatedAbscissaSeries;
|
||||
$this->ordinateSeries = $truncatedOrdinateSeries;
|
||||
$this->abscissaLogos = $truncatedAbscissaLogos;
|
||||
}
|
||||
|
||||
// blank characters are used to pad labels so the logo can be displayed
|
||||
$paddingText = '';
|
||||
$paddingWidth = 0;
|
||||
if ($maxLogoWidth > 0) {
|
||||
while ($paddingWidth < $maxLogoWidth + self::LOGO_MIN_RIGHT_MARGIN) {
|
||||
$paddingText .= self::PADDING_CHARS;
|
||||
list($paddingWidth, $paddingHeight) = $this->getTextWidthHeight($paddingText);
|
||||
}
|
||||
}
|
||||
|
||||
// determine the maximum label width according to the minimum comfortable graph size
|
||||
$gridRightMargin = $this->getGridRightMargin($horizontalGraph = true);
|
||||
$minGraphSize = ($this->width - $gridRightMargin) / 2;
|
||||
|
||||
$metricLegendWidth = 0;
|
||||
foreach ($this->ordinateLabels as $column => $label) {
|
||||
list($textWidth, $textHeight) = $this->getTextWidthHeight($label);
|
||||
$metricLegendWidth += $textWidth;
|
||||
}
|
||||
|
||||
$legendWidth = $metricLegendWidth + ((self::HORIZONTAL_LEGEND_LEFT_MARGIN + self::LEGEND_SQUARE_WIDTH) * $numberOfSeries);
|
||||
if ($this->showLegend) {
|
||||
if ($legendWidth > $minGraphSize) {
|
||||
$minGraphSize = $legendWidth;
|
||||
}
|
||||
}
|
||||
|
||||
$gridLeftMarginWithoutLabels = $this->getGridLeftMargin($horizontalGraph = true, $withLabel = false);
|
||||
$labelWidthLimit =
|
||||
$this->width
|
||||
- $gridLeftMarginWithoutLabels
|
||||
- $gridRightMargin
|
||||
- $paddingWidth
|
||||
- $minGraphSize;
|
||||
|
||||
// truncate labels if needed
|
||||
foreach ($this->abscissaSeries as &$label) {
|
||||
$label = $this->truncateLabel($label, $labelWidthLimit);
|
||||
}
|
||||
|
||||
$gridLeftMarginBeforePadding = $this->getGridLeftMargin($horizontalGraph = true, $withLabel = true);
|
||||
|
||||
// pad labels for logo space
|
||||
foreach ($this->abscissaSeries as &$label) {
|
||||
$label .= $paddingText;
|
||||
}
|
||||
|
||||
$this->initGridChart(
|
||||
$displayVerticalGridLines = false,
|
||||
$bulletType = LEGEND_FAMILY_BOX,
|
||||
$horizontalGraph = true,
|
||||
$showTicks = false,
|
||||
$verticalLegend
|
||||
);
|
||||
|
||||
$valueColor = $this->textColor;
|
||||
$this->pImage->drawBarChart(
|
||||
array(
|
||||
'DisplayValues' => true,
|
||||
'Interleave' => self::INTERLEAVE,
|
||||
'DisplayR' => $valueColor['R'],
|
||||
'DisplayG' => $valueColor['G'],
|
||||
'DisplayB' => $valueColor['B'],
|
||||
)
|
||||
);
|
||||
|
||||
// // display icons
|
||||
$graphData = $this->pData->getData();
|
||||
$numberOfRows = count($this->abscissaSeries);
|
||||
$logoInterleave = $this->getGraphHeight(true, $verticalLegend) / $numberOfRows;
|
||||
for ($i = 0; $i < $numberOfRows; $i++) {
|
||||
if (isset($this->abscissaLogos[$i])) {
|
||||
$currentLogoPath = $this->abscissaLogos[$i];
|
||||
|
||||
if (isset($logoPathToHeight[$currentLogoPath])) {
|
||||
$logoHeight = $logoPathToHeight[$currentLogoPath];
|
||||
|
||||
$pathInfo = pathinfo($currentLogoPath);
|
||||
$logoExtension = strtoupper($pathInfo['extension']);
|
||||
$drawingFunction = 'drawFrom' . $logoExtension;
|
||||
|
||||
$logoYPosition =
|
||||
($logoInterleave * $i)
|
||||
+ $this->getGridTopMargin(true, $verticalLegend)
|
||||
+ $graphData['Axis'][1]['Margin']
|
||||
- $logoHeight / 2
|
||||
+ 1;
|
||||
|
||||
if (method_exists($this->pImage, $drawingFunction)) {
|
||||
$this->pImage->$drawingFunction(
|
||||
$gridLeftMarginBeforePadding,
|
||||
$logoYPosition,
|
||||
$currentLogoPath
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
26
msd2/tracking/piwik/plugins/ImageGraph/StaticGraph/Pie.php
Normal file
26
msd2/tracking/piwik/plugins/ImageGraph/StaticGraph/Pie.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\Plugins\ImageGraph\StaticGraph;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class Pie extends PieGraph
|
||||
{
|
||||
public function renderGraph()
|
||||
{
|
||||
$this->initPieGraph(false);
|
||||
|
||||
$this->pieChart->draw2DPie(
|
||||
$this->xPosition,
|
||||
$this->yPosition,
|
||||
$this->pieConfig
|
||||
);
|
||||
}
|
||||
}
|
27
msd2/tracking/piwik/plugins/ImageGraph/StaticGraph/Pie3D.php
Normal file
27
msd2/tracking/piwik/plugins/ImageGraph/StaticGraph/Pie3D.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Piwik\Plugins\ImageGraph\StaticGraph;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class Pie3D extends PieGraph
|
||||
{
|
||||
public function renderGraph()
|
||||
{
|
||||
$this->initPieGraph(true);
|
||||
|
||||
$this->pieChart->draw3DPie(
|
||||
$this->xPosition,
|
||||
$this->yPosition,
|
||||
$this->pieConfig
|
||||
);
|
||||
}
|
||||
}
|
126
msd2/tracking/piwik/plugins/ImageGraph/StaticGraph/PieGraph.php
Normal file
126
msd2/tracking/piwik/plugins/ImageGraph/StaticGraph/PieGraph.php
Normal file
@ -0,0 +1,126 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Piwik\Plugins\ImageGraph\StaticGraph;
|
||||
|
||||
use CpChart\Chart\Pie;
|
||||
use Piwik\Plugins\ImageGraph\StaticGraph;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
abstract class PieGraph extends StaticGraph
|
||||
{
|
||||
const RADIUS_MARGIN = 40;
|
||||
const PIE_RIGHT_MARGIN = 20;
|
||||
const SECTOR_GAP = 2.5;
|
||||
|
||||
const SLICE_COLOR_KEY = "SLICE_COLOR";
|
||||
|
||||
/**
|
||||
* @var Pie
|
||||
*/
|
||||
protected $pieChart;
|
||||
protected $xPosition;
|
||||
protected $yPosition;
|
||||
protected $pieConfig;
|
||||
|
||||
protected function getDefaultColors()
|
||||
{
|
||||
return array(
|
||||
self::SLICE_COLOR_KEY . '1' => '3C5A69',
|
||||
self::SLICE_COLOR_KEY . '2' => '679BB5',
|
||||
self::SLICE_COLOR_KEY . '3' => '695A3C',
|
||||
self::SLICE_COLOR_KEY . '4' => 'B58E67',
|
||||
self::SLICE_COLOR_KEY . '5' => '8AA68A',
|
||||
self::SLICE_COLOR_KEY . '6' => 'A4D2A6',
|
||||
);
|
||||
}
|
||||
|
||||
protected function initPieGraph($showLegend)
|
||||
{
|
||||
$this->truncateSmallValues();
|
||||
$this->initpData();
|
||||
$this->initpImage();
|
||||
|
||||
if ($this->height > $this->width) {
|
||||
$radius = ($this->width / 2) - self::RADIUS_MARGIN;
|
||||
} else {
|
||||
$radius = ($this->height / 2) - self::RADIUS_MARGIN;
|
||||
}
|
||||
|
||||
$this->pieChart = new Pie($this->pImage, $this->pData);
|
||||
|
||||
$numberOfSlices = count($this->abscissaSeries);
|
||||
$numberOfAvailableColors = count($this->colors);
|
||||
for ($i = 0; $i < $numberOfSlices; $i++) {
|
||||
$this->pieChart->setSliceColor($i, $this->colors[self::SLICE_COLOR_KEY . (($i % $numberOfAvailableColors) + 1)]);
|
||||
}
|
||||
|
||||
// max abscissa label width is used to set the pie right margin
|
||||
list($abscissaMaxWidth, $abscissaMaxHeight) = $this->getMaximumTextWidthHeight($this->abscissaSeries);
|
||||
|
||||
$this->xPosition = $this->width - $radius - $abscissaMaxWidth - self::PIE_RIGHT_MARGIN;
|
||||
$this->yPosition = $this->height / 2;
|
||||
|
||||
if ($showLegend) {
|
||||
$this->pieChart->drawPieLegend(15, 40, array("Alpha" => 20));
|
||||
}
|
||||
|
||||
$this->pieConfig =
|
||||
array(
|
||||
'Radius' => $radius,
|
||||
'DrawLabels' => true,
|
||||
'DataGapAngle' => self::SECTOR_GAP,
|
||||
'DataGapRadius' => self::SECTOR_GAP,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* this method logic is close to Piwik's core filter_truncate.
|
||||
* it uses a threshold to determine if an abscissa value should be drawn on the PIE
|
||||
* discarded abscissa values are summed in the 'other' abscissa value
|
||||
*
|
||||
* if this process is not perform, CpChart will draw pie slices that are too small to see
|
||||
*/
|
||||
private function truncateSmallValues()
|
||||
{
|
||||
$metricColumns = array_keys($this->ordinateSeries);
|
||||
$metricColumn = $metricColumns[0];
|
||||
|
||||
$ordinateValuesSum = 0;
|
||||
foreach ($this->ordinateSeries[$metricColumn] as $ordinateValue) {
|
||||
$ordinateValuesSum += $ordinateValue;
|
||||
}
|
||||
|
||||
$truncatedOrdinateSeries[$metricColumn] = array();
|
||||
$truncatedAbscissaSeries = array();
|
||||
$smallValuesSum = 0;
|
||||
|
||||
$ordinateValuesCount = count($this->ordinateSeries[$metricColumn]);
|
||||
for ($i = 0; $i < $ordinateValuesCount - 1; $i++) {
|
||||
$ordinateValue = $this->ordinateSeries[$metricColumn][$i];
|
||||
if ($ordinateValue / $ordinateValuesSum > 0.01) {
|
||||
$truncatedOrdinateSeries[$metricColumn][] = $ordinateValue;
|
||||
$truncatedAbscissaSeries[] = $this->abscissaSeries[$i];
|
||||
} else {
|
||||
$smallValuesSum += $ordinateValue;
|
||||
}
|
||||
}
|
||||
|
||||
$smallValuesSum += $this->ordinateSeries[$metricColumn][$ordinateValuesCount - 1];
|
||||
if (($smallValuesSum / $ordinateValuesSum) > 0.01) {
|
||||
$truncatedOrdinateSeries[$metricColumn][] = $smallValuesSum;
|
||||
$truncatedAbscissaSeries[] = end($this->abscissaSeries);
|
||||
}
|
||||
|
||||
$this->ordinateSeries = $truncatedOrdinateSeries;
|
||||
$this->abscissaSeries = $truncatedAbscissaSeries;
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\Plugins\ImageGraph\StaticGraph;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class VerticalBar extends GridGraph
|
||||
{
|
||||
const INTERLEAVE = 0.10;
|
||||
|
||||
public function renderGraph()
|
||||
{
|
||||
$this->initGridChart(
|
||||
$displayVerticalGridLines = false,
|
||||
$bulletType = LEGEND_FAMILY_BOX,
|
||||
$horizontalGraph = false,
|
||||
$showTicks = true,
|
||||
$verticalLegend = false
|
||||
);
|
||||
|
||||
$this->pImage->drawBarChart(
|
||||
array(
|
||||
'Interleave' => self::INTERLEAVE,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user