PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 4.13.5
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v4.13.5
5.12.0 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 4 years ago
Sparkline.php
224 lines
1 <?php
2 /**
3 * Matomo - free/libre analytics platform
4 *
5 * @link https://matomo.org
6 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
7 *
8 */
9
10 namespace Piwik\Visualization;
11
12 use Piwik\Common;
13 use Piwik\Piwik;
14 use Piwik\View\ViewInterface;
15
16 /**
17 * Renders a sparkline image given a PHP data array.
18 * Using the Sparkline PHP Graphing Library sparkline.org
19 */
20 class Sparkline implements ViewInterface
21 {
22 const DEFAULT_WIDTH = 200;
23 const DEFAULT_HEIGHT = 50;
24 const MAX_WIDTH = 1000;
25 const MAX_HEIGHT = 1000;
26
27
28 /**
29 * Width of the sparkline
30 * @var int
31 */
32 protected $_width = self::DEFAULT_WIDTH;
33 /**
34 * Height of sparkline
35 * @var int
36 */
37 protected $_height = self::DEFAULT_HEIGHT;
38 private $serieses = array();
39 /**
40 * @var \Davaxi\Sparkline
41 */
42 private $sparkline;
43
44 /**
45 * Array with format: array( x, y, z, ... )
46 * @param array $data,...
47 */
48 public function setValues()
49 {
50 $this->serieses = func_get_args();
51 }
52
53 public function addSeries(array $values)
54 {
55 $this->serieses[] = $values;
56 }
57
58 public function main()
59 {
60 try {
61 $sparkline = new \Davaxi\Sparkline();
62 } catch (\Exception $exception) {
63 // Ignore GD not installed exception
64 return;
65 }
66
67
68 $thousandSeparator = Piwik::translate('Intl_NumberSymbolGroup');
69 $decimalSeparator = Piwik::translate('Intl_NumberSymbolDecimal');
70
71 $sparkline->setData(); // remove default series
72 foreach ($this->serieses as $seriesIndex => $series) {
73 $values = [];
74 $hasFloat = false;
75
76 foreach ($series as $value) {
77 // replace localized decimal separator
78 $value = str_replace($thousandSeparator, '', $value);
79 $value = str_replace($decimalSeparator, '.', $value);
80
81 // sanitize value
82 $value = filter_var($value, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION | FILTER_FLAG_ALLOW_SCIENTIFIC);
83
84 if (empty($value) || !is_numeric($value)) {
85 $value = 0;
86 }
87
88 $values[] = $value;
89
90 if (is_float($value + 0)) { // coerce to int/float type before checking
91 $hasFloat = true;
92 }
93 }
94
95 // the sparkline lib used converts everything to integers (see the FormatTrait.php file) which means float
96 // numbers that are close to 1.0 or 0.0 will get floored. this can happen in the average page generation time
97 // report, and cause some values which are, eg, around ~.9 to appear as 0 in the sparkline. to workaround this, we
98 // scale the values.
99 if ($hasFloat) {
100 $values = array_map(function ($x) {
101 return $x * 1000.0;
102 }, $values);
103 }
104
105 $sparkline->addSeries($values);
106 $this->setSparklineColors($sparkline, $seriesIndex);
107 }
108
109 $sparkline->setWidth($this->getWidth());
110 $sparkline->setHeight($this->getHeight());
111 $sparkline->setLineThickness(1);
112 $sparkline->setPadding('5');
113
114 $this->sparkline = $sparkline;
115 }
116
117 /**
118 * Returns the width of the sparkline
119 * @return int
120 */
121 public function getWidth() {
122 return $this->_width;
123 }
124
125 /**
126 * Sets the width of the sparkline
127 * @param int $width
128 */
129 public function setWidth($width) {
130 if (!is_numeric($width) || $width <= 0) {
131 return;
132 }
133 if ($width > self::MAX_WIDTH) {
134 $this->_width = self::MAX_WIDTH;
135 } else {
136 $this->_width = (int)$width;
137 }
138 }
139
140 /**
141 * Returns the height of the sparkline
142 * @return int
143 */
144 public function getHeight() {
145 return $this->_height;
146 }
147
148 /**
149 * Sets the height of the sparkline
150 * @param int $height
151 */
152 public function setHeight($height) {
153 if (!is_numeric($height) || $height <= 0) {
154 return;
155 }
156 if ($height > self::MAX_HEIGHT) {
157 $this->_height = self::MAX_HEIGHT;
158 } else {
159 $this->_height = (int)$height;
160 }
161 }
162
163 /**
164 * Sets the sparkline colors
165 *
166 * @param \Davaxi\Sparkline $sparkline
167 */
168 private function setSparklineColors($sparkline, $seriesIndex) {
169 $colors = Common::getRequestVar('colors', false, 'json');
170
171 $defaultColors = array(
172 'backgroundColor' => '#ffffff',
173 'lineColor' => '#162C4A',
174 'minPointColor' => '#ff7f7f',
175 'maxPointColor' => '#75BF7C',
176 'lastPointColor' => '#55AAFF',
177 'fillColor' => '#ffffff'
178 );
179
180 if (empty($colors)) {
181 $colors = $defaultColors; //set default color, if no color passed
182 } else {
183 $colors = array_merge($defaultColors, $colors); //set default color key, if no key set.
184 }
185
186 if (strtolower($colors['backgroundColor']) !== '#ffffff') {
187 $sparkline->setBackgroundColorHex($colors['backgroundColor']);
188 } else {
189 $sparkline->deactivateBackgroundColor();
190 }
191
192 if (is_array($colors['lineColor'])) {
193 $sparkline->setLineColorHex($colors['lineColor'][$seriesIndex] ?? $defaultColors['lineColor'], $seriesIndex);
194
195 // set point colors to same as line colors so they can be better differentiated
196 $colors['minPointColor'] = $colors['maxPointColor'] = $colors['lastPointColor'] = $colors['lineColor'][$seriesIndex] ?? $defaultColors['lineColor'];
197 } else {
198 $sparkline->setLineColorHex($colors['lineColor']);
199 }
200
201 if (strtolower($colors['fillColor'] !== "#ffffff")) {
202 $sparkline->setFillColorHex($colors['fillColor']);
203 } else {
204 $sparkline->deactivateFillColor();
205 }
206 if (strtolower($colors['minPointColor'] !== "#ffffff")) {
207 $sparkline->addPoint("minimum", 5, $colors['minPointColor'], $seriesIndex);
208 }
209 if (strtolower($colors['maxPointColor'] !== "#ffffff")) {
210 $sparkline->addPoint("maximum", 5, $colors['maxPointColor'], $seriesIndex);
211 }
212 if (strtolower($colors['lastPointColor'] !== "#ffffff")) {
213 $sparkline->addPoint("last", 5, $colors['lastPointColor'], $seriesIndex);
214 }
215 }
216
217 public function render() {
218 if ($this->sparkline instanceof \Davaxi\Sparkline) {
219 $this->sparkline->display();
220 $this->sparkline->destroy();
221 }
222 }
223 }
224