Download plugins/ImageGraph/StaticGraph.php from Leon4gr45/matomo: direct link, hf CLI and curl.
- Browser
- Download file 11.4 kB
-
https://huggingface.co/spaces/Leon4gr45/matomo/resolve/main/plugins/ImageGraph/StaticGraph.php
- Command line
-
hf download hf://spaces/Leon4gr45/matomo/plugins/ImageGraph/StaticGraph.php
-
curl -L -o StaticGraph.php https://huggingface.co/spaces/Leon4gr45/matomo/resolve/main/plugins/ImageGraph/StaticGraph.php
11.4 kB
| /** | |
| * Matomo - free/libre analytics platform | |
| * | |
| * @link https://matomo.org | |
| * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later | |
| */ | |
| namespace Piwik\Plugins\ImageGraph; | |
| use CpChart\Data; | |
| use CpChart\Image; | |
| use Piwik\Container\StaticContainer; | |
| use Piwik\NumberFormatter; | |
| use Piwik\Piwik; | |
| use Piwik\BaseFactory; | |
| /** | |
| * The StaticGraph abstract class is used as a base class for different types of static graphs. | |
| * | |
| */ | |
| abstract class StaticGraph extends BaseFactory | |
| { | |
| public const GRAPH_TYPE_BASIC_LINE = "evolution"; | |
| public const GRAPH_TYPE_VERTICAL_BAR = "verticalBar"; | |
| public const GRAPH_TYPE_HORIZONTAL_BAR = "horizontalBar"; | |
| public const GRAPH_TYPE_3D_PIE = "3dPie"; | |
| public const GRAPH_TYPE_BASIC_PIE = "pie"; | |
| private static $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', | |
| ); | |
| public const ABSCISSA_SERIE_NAME = 'ABSCISSA'; | |
| private $aliasedGraph; | |
| /** | |
| * @var Image | |
| */ | |
| protected $pImage; | |
| /** | |
| * @var Data | |
| */ | |
| 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(); | |
| protected static function getClassNameFromClassId($graphType) | |
| { | |
| $className = self::$availableStaticGraphTypes[$graphType]; | |
| $className = __NAMESPACE__ . "\\StaticGraph\\" . $className; | |
| return $className; | |
| } | |
| protected static function getInvalidClassIdExceptionMessage($graphType) | |
| { | |
| return Piwik::translate( | |
| 'General_ExceptionInvalidStaticGraphType', | |
| array($graphType, implode(', ', self::getAvailableStaticGraphTypes())) | |
| ); | |
| } | |
| public static function getAvailableStaticGraphTypes() | |
| { | |
| return array_keys(self::$availableStaticGraphTypes); | |
| } | |
| public static function fixWhitespaceNonUnifont($value) | |
| { | |
| if (!is_string($value)) { | |
| return $value; | |
| } | |
| return strtr( | |
| $value, | |
| [ | |
| // thin space | |
| "\xE2\x80\x89" => ' ', | |
| // narrow non-break-space | |
| "\xE2\x80\xAF" => "\xC2\xA0", | |
| ] | |
| ); | |
| } | |
| /** | |
| * 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 = StaticContainer::get('path.tmp') . '/assets/' . $filename; | |
| @chmod($outputFilename, 0600); | |
| @unlink($outputFilename); | |
| return $outputFilename; | |
| } | |
| protected function initpData() | |
| { | |
| $this->pData = new Data(); | |
| foreach ($this->ordinateSeries as $column => $data) { | |
| $this->pData->addPoints($data, $column); | |
| if (isset($this->ordinateLabels[$column])) { | |
| $this->pData->setSerieDescription($column, $this->ordinateLabels[$column]); | |
| } | |
| if (isset($this->ordinateLogos[$column])) { | |
| $ordinateLogo = $this->createResizedImageCopyIfNeeded($this->ordinateLogos[$column]); | |
| $this->pData->setSeriePicture($column, $ordinateLogo); | |
| } | |
| } | |
| // Fix whitespace if not using unifont | |
| $abscissaSeries = $this->abscissaSeries; | |
| $formatMethodName = 'formatYAxis'; | |
| if (false === strpos($this->font, API::UNICODE_FONT)) { | |
| $abscissaSeries = array_map([$this, 'fixWhitespaceNonUnifont'], $abscissaSeries); | |
| $formatMethodName = 'formatYAxisNonUnifont'; | |
| } | |
| $this->pData->setAxisDisplay(0, AXIS_FORMAT_CUSTOM, '\\Piwik\\Plugins\\ImageGraph\\' . $formatMethodName); | |
| $this->pData->addPoints($abscissaSeries, self::ABSCISSA_SERIE_NAME); | |
| $this->pData->setAbscissa(self::ABSCISSA_SERIE_NAME); | |
| } | |
| protected function createResizedImageCopyIfNeeded($image) | |
| { | |
| $size = getimagesize($image); | |
| if ($size[0] <= 16 && $size[1] <= 16) { | |
| return $image; // use original image if size fits | |
| } | |
| $ratio = $size[0] / $size[1]; | |
| if ($ratio > 1) { | |
| $width = 16; | |
| $height = 16 / $ratio; | |
| } else { | |
| $width = 16 * $ratio; | |
| $height = 16; | |
| } | |
| $newImage = self::getOutputPath(md5($image) . '.png'); | |
| $src = imagecreatefromstring(file_get_contents($image)); | |
| $dst = imagecreatetruecolor($width, $height); | |
| imagesavealpha($dst, true); | |
| $color = imagecolorallocatealpha($dst, 0, 0, 0, 127); | |
| imagefill($dst, 0, 0, $color); | |
| imagecopyresampled($dst, $src, 0, 0, 0, 0, $width, $height, $size[0], $size[1]); | |
| imagedestroy($src); | |
| imagepng($dst, $newImage); | |
| imagedestroy($dst); | |
| return $newImage; | |
| } | |
| protected function initpImage() | |
| { | |
| $this->pImage = new Image($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 $data) { | |
| foreach ($data as $value) { | |
| [$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 []; | |
| } | |
| } | |
| } | |
| /** | |
| * Global format method - unifont | |
| * | |
| * required to format y axis values using CpChart internal format callbacks | |
| * @param $value | |
| * @return mixed | |
| */ | |
| function formatYAxis($value) | |
| { | |
| return NumberFormatter::getInstance()->format($value); | |
| } | |
| /** | |
| * Global format method - non-unifont | |
| * | |
| * required to format y axis values using CpChart internal format callbacks | |
| * @param $value | |
| * @return mixed | |
| */ | |
| function formatYAxisNonUnifont($value) | |
| { | |
| return StaticGraph::fixWhitespaceNonUnifont( | |
| NumberFormatter::getInstance()->format($value) | |
| ); | |
| } | |