questlab/www/analytics/plugins/ImageGraph/StaticGraph.php

355 lines
9.2 KiB
PHP

<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*
*/
namespace Piwik\Plugins\ImageGraph;
use Exception;
use pData;
use pImage;
use Piwik\Loader;
use Piwik\Piwik;
use Piwik\SettingsPiwik;
require_once PIWIK_INCLUDE_PATH . "/libs/pChart2.1.3/class/pDraw.class.php";
require_once PIWIK_INCLUDE_PATH . "/libs/pChart2.1.3/class/pImage.class.php";
require_once PIWIK_INCLUDE_PATH . "/libs/pChart2.1.3/class/pData.class.php";
/**
* The StaticGraph abstract class is used as a base class for different types of static graphs.
*
*/
abstract class StaticGraph
{
const GRAPH_TYPE_BASIC_LINE = "evolution";
const GRAPH_TYPE_VERTICAL_BAR = "verticalBar";
const GRAPH_TYPE_HORIZONTAL_BAR = "horizontalBar";
const GRAPH_TYPE_3D_PIE = "3dPie";
const GRAPH_TYPE_BASIC_PIE = "pie";
static private $availableStaticGraphTypes = array(
self::GRAPH_TYPE_BASIC_LINE => 'Evolution',
self::GRAPH_TYPE_VERTICAL_BAR => 'VerticalBar',
self::GRAPH_TYPE_HORIZONTAL_BAR => 'HorizontalBar',
self::GRAPH_TYPE_BASIC_PIE => 'Pie',
self::GRAPH_TYPE_3D_PIE => 'Pie3D',
);
const ABSCISSA_SERIE_NAME = 'ABSCISSA';
private $aliasedGraph;
/**
* @var pImage
*/
protected $pImage;
/**
* @var pData
*/
protected $pData;
protected $ordinateLabels;
protected $showLegend;
protected $abscissaSeries;
protected $abscissaLogos;
protected $ordinateSeries;
protected $ordinateLogos;
protected $colors;
protected $font;
protected $fontSize;
protected $textColor;
protected $backgroundColor;
protected $gridColor;
protected $legendFontSize;
protected $width;
protected $height;
protected $forceSkippedLabels = false;
abstract protected function getDefaultColors();
abstract public function renderGraph();
/**
* Return the StaticGraph according to the static graph type $graphType
*
* @throws Exception If the static graph type is unknown
* @param string $graphType
* @return \Piwik\Plugins\ImageGraph\StaticGraph
*/
public static function factory($graphType)
{
if (isset(self::$availableStaticGraphTypes[$graphType])) {
$className = self::$availableStaticGraphTypes[$graphType];
$className = __NAMESPACE__ . "\\StaticGraph\\" . $className;
Loader::loadClass($className);
return new $className;
} else {
throw new Exception(
Piwik::translate(
'General_ExceptionInvalidStaticGraphType',
array($graphType, implode(', ', self::getAvailableStaticGraphTypes()))
)
);
}
}
public static function getAvailableStaticGraphTypes()
{
return array_keys(self::$availableStaticGraphTypes);
}
/**
* Save rendering to disk
*
* @param string $filename without path
* @return string path of file
*/
public function sendToDisk($filename)
{
$filePath = self::getOutputPath($filename);
$this->pImage->Render($filePath);
return $filePath;
}
/**
* @return resource rendered static graph
*/
public function getRenderedImage()
{
return $this->pImage->Picture;
}
/**
* Output rendering to browser
*/
public function sendToBrowser()
{
$this->pImage->stroke();
}
public function setWidth($width)
{
$this->width = $width;
}
public function setHeight($height)
{
$this->height = $height;
}
public function setFontSize($fontSize)
{
if (!is_numeric($fontSize)) {
$fontSize = API::DEFAULT_FONT_SIZE;
}
$this->fontSize = $fontSize;
}
public function setLegendFontSize($legendFontSize)
{
$this->legendFontSize = $legendFontSize;
}
public function setFont($font)
{
$this->font = $font;
}
public function setTextColor($textColor)
{
$this->textColor = self::hex2rgb($textColor);
}
public function setBackgroundColor($backgroundColor)
{
$this->backgroundColor = self::hex2rgb($backgroundColor);
}
public function setGridColor($gridColor)
{
$this->gridColor = self::hex2rgb($gridColor);
}
public function setOrdinateSeries($ordinateSeries)
{
$this->ordinateSeries = $ordinateSeries;
}
public function setOrdinateLogos($ordinateLogos)
{
$this->ordinateLogos = $ordinateLogos;
}
public function setAbscissaLogos($abscissaLogos)
{
$this->abscissaLogos = $abscissaLogos;
}
public function setAbscissaSeries($abscissaSeries)
{
$this->abscissaSeries = $abscissaSeries;
}
public function setShowLegend($showLegend)
{
$this->showLegend = $showLegend;
}
public function setForceSkippedLabels($forceSkippedLabels)
{
$this->forceSkippedLabels = $forceSkippedLabels;
}
public function setOrdinateLabels($ordinateLabels)
{
$this->ordinateLabels = $ordinateLabels;
}
public function setAliasedGraph($aliasedGraph)
{
$this->aliasedGraph = $aliasedGraph;
}
public function setColors($colors)
{
$i = 0;
foreach ($this->getDefaultColors() as $colorKey => $defaultColor) {
if (isset($colors[$i]) && $this->hex2rgb($colors[$i])) {
$hexColor = $colors[$i];
} else {
$hexColor = $defaultColor;
}
$this->colors[$colorKey] = $this->hex2rgb($hexColor);
$i++;
}
}
/**
* Return $filename with temp directory and delete file
*
* @static
* @param $filename
* @return string path of file in temp directory
*/
protected static function getOutputPath($filename)
{
$outputFilename = PIWIK_USER_PATH . '/tmp/assets/' . $filename;
$outputFilename = SettingsPiwik::rewriteTmpPathWithHostname($outputFilename);
@chmod($outputFilename, 0600);
@unlink($outputFilename);
return $outputFilename;
}
protected function initpData()
{
$this->pData = new pData();
foreach ($this->ordinateSeries as $column => $data) {
$this->pData->addPoints($data, $column);
$this->pData->setSerieDescription($column, $this->ordinateLabels[$column]);
if (isset($this->ordinateLogos[$column])) {
$ordinateLogo = $this->ordinateLogos[$column];
$this->pData->setSeriePicture($column, $ordinateLogo);
}
}
$this->pData->addPoints($this->abscissaSeries, self::ABSCISSA_SERIE_NAME);
$this->pData->setAbscissa(self::ABSCISSA_SERIE_NAME);
}
protected function initpImage()
{
$this->pImage = new pImage($this->width, $this->height, $this->pData);
$this->pImage->Antialias = $this->aliasedGraph;
$this->pImage->setFontProperties(
array_merge(
array(
'FontName' => $this->font,
'FontSize' => $this->fontSize,
),
$this->textColor
)
);
}
protected function getTextWidthHeight($text, $fontSize = false)
{
if (!$fontSize) {
$fontSize = $this->fontSize;
}
if (!$this->pImage) {
$this->initpImage();
}
// could not find a way to get pixel perfect width & height info using imageftbbox
$textInfo = $this->pImage->drawText(
0, 0, $text,
array(
'Alpha' => 0,
'FontSize' => $fontSize,
'FontName' => $this->font
)
);
return array($textInfo[1]['X'] + 1, $textInfo[0]['Y'] - $textInfo[2]['Y']);
}
protected function getMaximumTextWidthHeight($values)
{
if (array_values($values) === $values) {
$values = array('' => $values);
}
$maxWidth = 0;
$maxHeight = 0;
foreach ($values as $column => $data) {
foreach ($data as $value) {
list($valueWidth, $valueHeight) = $this->getTextWidthHeight($value);
if ($valueWidth > $maxWidth) {
$maxWidth = $valueWidth;
}
if ($valueHeight > $maxHeight) {
$maxHeight = $valueHeight;
}
}
}
return array($maxWidth, $maxHeight);
}
protected function drawBackground()
{
$this->pImage->drawFilledRectangle(
0,
0,
$this->width,
$this->height,
array_merge(array('Alpha' => 100), $this->backgroundColor)
);
}
private static function hex2rgb($hexColor)
{
if (preg_match('/([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/', $hexColor, $matches)) {
return array(
'R' => hexdec($matches[1]),
'G' => hexdec($matches[2]),
'B' => hexdec($matches[3])
);
} else {
return false;
}
}
}