PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / trunk
Matomo Analytics – Powerful, Privacy-First Insights for WordPress vtrunk
5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / core / Visualization / Sparkline.php
matomo / app / core / Visualization Last commit date
Sparkline.php 1 year ago
Sparkline.php
202 lines
1 <?php
2
3 /**
4 * Matomo - free/libre analytics platform
5 *
6 * @link https://matomo.org
7 * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
8 */
9 namespace Piwik\Visualization;
10
11 use Piwik\Common;
12 use Piwik\Piwik;
13 use Piwik\View\ViewInterface;
14 /**
15 * Renders a sparkline image given a PHP data array.
16 * Using the Sparkline PHP Graphing Library sparkline.org
17 */
18 class Sparkline implements ViewInterface
19 {
20 public const DEFAULT_WIDTH = 200;
21 public const DEFAULT_HEIGHT = 50;
22 public const MAX_WIDTH = 1000;
23 public const MAX_HEIGHT = 1000;
24 /**
25 * Width of the sparkline
26 * @var int
27 */
28 protected $width = self::DEFAULT_WIDTH;
29 /**
30 * Height of sparkline
31 * @var int
32 */
33 protected $height = self::DEFAULT_HEIGHT;
34 private $serieses = [];
35 /**
36 * @var \Davaxi\Sparkline
37 */
38 private $sparkline;
39 /**
40 * Array with format: array( x, y, z, ... )
41 * @param array ...$data
42 */
43 public function setValues(...$data)
44 {
45 $this->serieses = $data;
46 }
47 public function addSeries(array $values)
48 {
49 $this->serieses[] = $values;
50 }
51 public function main()
52 {
53 try {
54 $sparkline = new \Davaxi\Sparkline();
55 } catch (\Exception $exception) {
56 // Ignore GD not installed exception
57 return;
58 }
59 $thousandSeparator = Piwik::translate('Intl_NumberSymbolGroup');
60 $decimalSeparator = Piwik::translate('Intl_NumberSymbolDecimal');
61 $sparkline->setData();
62 // remove default series
63 foreach ($this->serieses as $seriesIndex => $series) {
64 $values = [];
65 $hasFloat = \false;
66 foreach ($series as $value) {
67 // replace localized decimal separator
68 $value = str_replace($thousandSeparator, '', $value);
69 $value = str_replace($decimalSeparator, '.', $value);
70 // sanitize value
71 $value = filter_var($value, \FILTER_SANITIZE_NUMBER_FLOAT, \FILTER_FLAG_ALLOW_FRACTION | \FILTER_FLAG_ALLOW_SCIENTIFIC);
72 if (empty($value) || !is_numeric($value)) {
73 $value = 0;
74 }
75 $values[] = $value;
76 if (is_float($value + 0)) {
77 // coerce to int/float type before checking
78 $hasFloat = \true;
79 }
80 }
81 // the sparkline lib used converts everything to integers (see the FormatTrait.php file) which means float
82 // numbers that are close to 1.0 or 0.0 will get floored. this can happen in the average page generation time
83 // report, and cause some values which are, eg, around ~.9 to appear as 0 in the sparkline. to workaround this, we
84 // scale the values.
85 if ($hasFloat) {
86 $values = array_map(function ($x) {
87 return $x * 1000.0;
88 }, $values);
89 }
90 $sparkline->addSeries($values);
91 $this->setSparklineColors($sparkline, $seriesIndex);
92 }
93 $sparkline->setWidth($this->getWidth());
94 $sparkline->setHeight($this->getHeight());
95 $sparkline->setLineThickness(1);
96 $sparkline->setPadding('5');
97 $this->sparkline = $sparkline;
98 }
99 /**
100 * Returns the width of the sparkline
101 * @return int
102 */
103 public function getWidth()
104 {
105 return $this->width;
106 }
107 /**
108 * Sets the width of the sparkline
109 * @param int $width
110 */
111 public function setWidth($width)
112 {
113 if (!is_numeric($width) || $width <= 0) {
114 return;
115 }
116 if ($width > self::MAX_WIDTH) {
117 $this->width = self::MAX_WIDTH;
118 } else {
119 $this->width = (int) $width;
120 }
121 }
122 /**
123 * Returns the height of the sparkline
124 * @return int
125 */
126 public function getHeight()
127 {
128 return $this->height;
129 }
130 /**
131 * Sets the height of the sparkline
132 * @param int $height
133 */
134 public function setHeight($height)
135 {
136 if (!is_numeric($height) || $height <= 0) {
137 return;
138 }
139 if ($height > self::MAX_HEIGHT) {
140 $this->height = self::MAX_HEIGHT;
141 } else {
142 $this->height = (int) $height;
143 }
144 }
145 /**
146 * Sets the sparkline colors
147 *
148 * @param \Davaxi\Sparkline $sparkline
149 */
150 private function setSparklineColors($sparkline, $seriesIndex)
151 {
152 $colors = Common::getRequestVar('colors', \false, 'json');
153 $defaultColors = array('backgroundColor' => '#ffffff', 'lineColor' => '#162C4A', 'minPointColor' => '#ff7f7f', 'maxPointColor' => '#75BF7C', 'lastPointColor' => '#55AAFF', 'fillColor' => '#ffffff');
154 if (empty($colors) || !is_array($colors)) {
155 $colors = $defaultColors;
156 //set default color, if no color passed
157 } else {
158 $colors = array_merge($defaultColors, $colors);
159 //set default color key, if no key set.
160 }
161 if (strtolower($colors['backgroundColor']) !== '#ffffff') {
162 $sparkline->setBackgroundColorHex($colors['backgroundColor']);
163 } else {
164 $sparkline->deactivateBackgroundColor();
165 }
166 if (is_array($colors['lineColor'])) {
167 $sparkline->setLineColorHex($colors['lineColor'][$seriesIndex] ?? $defaultColors['lineColor'], $seriesIndex);
168 // set point colors to same as line colors so they can be better differentiated
169 $colors['minPointColor'] = $colors['maxPointColor'] = $colors['lastPointColor'] = $colors['lineColor'][$seriesIndex] ?? $defaultColors['lineColor'];
170 } else {
171 $sparkline->setLineColorHex($colors['lineColor']);
172 }
173 if (strtolower($colors['fillColor'] !== "#ffffff")) {
174 $sparkline->setFillColorHex($colors['fillColor']);
175 } else {
176 $sparkline->deactivateFillColor();
177 }
178 if (strtolower($colors['minPointColor'] !== "#ffffff")) {
179 $sparkline->addPoint("minimum", 5, $colors['minPointColor'], $seriesIndex);
180 }
181 if (strtolower($colors['maxPointColor'] !== "#ffffff")) {
182 $sparkline->addPoint("maximum", 5, $colors['maxPointColor'], $seriesIndex);
183 }
184 if (strtolower($colors['lastPointColor'] !== "#ffffff")) {
185 $sparkline->addPoint("last", 5, $colors['lastPointColor'], $seriesIndex);
186 }
187 }
188 public function render()
189 {
190 if (!$this->sparkline instanceof \Davaxi\Sparkline) {
191 return;
192 }
193 if (0 === $this->sparkline->getSeriesCount()) {
194 // ensure to have at least one series & point in sparkline to avoid possible php notices/errors
195 // a sparkline will then be displayed with a zero line
196 $this->sparkline->addSeries([0]);
197 }
198 $this->sparkline->display();
199 $this->sparkline->destroy();
200 }
201 }
202