1
|
|
|
<?php |
|
|
|
|
2
|
|
|
|
3
|
|
|
namespace PhpOffice\PhpSpreadsheet\Chart\Renderer; |
4
|
|
|
|
5
|
|
|
use PhpOffice\PhpSpreadsheet\Chart\Chart; |
6
|
|
|
use PhpOffice\PhpSpreadsheet\Style\NumberFormat; |
7
|
|
|
|
8
|
2 |
|
require_once __DIR__ . '/Polyfill.php'; |
9
|
|
|
|
10
|
|
|
class JpGraph implements IRenderer |
11
|
|
|
{ |
12
|
|
|
private static $width = 640; |
13
|
|
|
|
14
|
|
|
private static $height = 480; |
15
|
|
|
|
16
|
|
|
private static $colourSet = [ |
17
|
|
|
'mediumpurple1', 'palegreen3', 'gold1', 'cadetblue1', |
18
|
|
|
'darkmagenta', 'coral', 'dodgerblue3', 'eggplant', |
19
|
|
|
'mediumblue', 'magenta', 'sandybrown', 'cyan', |
20
|
|
|
'firebrick1', 'forestgreen', 'deeppink4', 'darkolivegreen', |
21
|
|
|
'goldenrod2', |
22
|
|
|
]; |
23
|
|
|
|
24
|
|
|
private static $markSet; |
25
|
|
|
|
26
|
|
|
private $chart; |
27
|
|
|
|
28
|
|
|
private $graph; |
29
|
|
|
|
30
|
|
|
private static $plotColour = 0; |
31
|
|
|
|
32
|
|
|
private static $plotMark = 0; |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* Create a new jpgraph. |
36
|
|
|
* |
37
|
|
|
* @param Chart $chart |
38
|
|
|
*/ |
39
|
1 |
|
public function __construct(Chart $chart) |
40
|
|
|
{ |
41
|
1 |
|
self::init(); |
42
|
1 |
|
$this->graph = null; |
43
|
1 |
|
$this->chart = $chart; |
44
|
1 |
|
} |
45
|
|
|
|
46
|
1 |
|
private static function init() |
47
|
|
|
{ |
48
|
1 |
|
static $loaded = false; |
49
|
1 |
|
if ($loaded) { |
50
|
1 |
|
return; |
51
|
|
|
} |
52
|
|
|
|
53
|
1 |
|
\JpGraph\JpGraph::load(); |
54
|
1 |
|
\JpGraph\JpGraph::module('bar'); |
55
|
1 |
|
\JpGraph\JpGraph::module('contour'); |
56
|
1 |
|
\JpGraph\JpGraph::module('line'); |
57
|
1 |
|
\JpGraph\JpGraph::module('pie'); |
58
|
1 |
|
\JpGraph\JpGraph::module('pie3d'); |
59
|
1 |
|
\JpGraph\JpGraph::module('radar'); |
60
|
1 |
|
\JpGraph\JpGraph::module('regstat'); |
61
|
1 |
|
\JpGraph\JpGraph::module('scatter'); |
62
|
1 |
|
\JpGraph\JpGraph::module('stock'); |
63
|
|
|
|
64
|
1 |
|
self::$markSet = [ |
65
|
1 |
|
'diamond' => MARK_DIAMOND, |
66
|
1 |
|
'square' => MARK_SQUARE, |
67
|
1 |
|
'triangle' => MARK_UTRIANGLE, |
68
|
1 |
|
'x' => MARK_X, |
69
|
1 |
|
'star' => MARK_STAR, |
70
|
1 |
|
'dot' => MARK_FILLEDCIRCLE, |
71
|
1 |
|
'dash' => MARK_DTRIANGLE, |
72
|
1 |
|
'circle' => MARK_CIRCLE, |
73
|
1 |
|
'plus' => MARK_CROSS, |
74
|
|
|
]; |
75
|
|
|
|
76
|
1 |
|
$loaded = true; |
77
|
1 |
|
} |
78
|
|
|
|
79
|
1 |
|
private function formatPointMarker($seriesPlot, $markerID) |
80
|
|
|
{ |
81
|
1 |
|
$plotMarkKeys = array_keys(self::$markSet); |
82
|
1 |
|
if ($markerID === null) { |
83
|
|
|
// Use default plot marker (next marker in the series) |
84
|
1 |
|
self::$plotMark %= count(self::$markSet); |
85
|
1 |
|
$seriesPlot->mark->SetType(self::$markSet[$plotMarkKeys[self::$plotMark++]]); |
86
|
1 |
|
} elseif ($markerID !== 'none') { |
87
|
|
|
// Use specified plot marker (if it exists) |
88
|
1 |
|
if (isset(self::$markSet[$markerID])) { |
89
|
1 |
|
$seriesPlot->mark->SetType(self::$markSet[$markerID]); |
90
|
|
|
} else { |
91
|
|
|
// If the specified plot marker doesn't exist, use default plot marker (next marker in the series) |
92
|
|
|
self::$plotMark %= count(self::$markSet); |
93
|
1 |
|
$seriesPlot->mark->SetType(self::$markSet[$plotMarkKeys[self::$plotMark++]]); |
94
|
|
|
} |
95
|
|
|
} else { |
96
|
|
|
// Hide plot marker |
97
|
1 |
|
$seriesPlot->mark->Hide(); |
98
|
|
|
} |
99
|
1 |
|
$seriesPlot->mark->SetColor(self::$colourSet[self::$plotColour]); |
100
|
1 |
|
$seriesPlot->mark->SetFillColor(self::$colourSet[self::$plotColour]); |
101
|
1 |
|
$seriesPlot->SetColor(self::$colourSet[self::$plotColour++]); |
102
|
|
|
|
103
|
1 |
|
return $seriesPlot; |
104
|
|
|
} |
105
|
|
|
|
106
|
1 |
|
private function formatDataSetLabels($groupID, $datasetLabels, $labelCount, $rotation = '') |
|
|
|
|
107
|
|
|
{ |
108
|
1 |
|
$datasetLabelFormatCode = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getFormatCode(); |
109
|
1 |
|
if ($datasetLabelFormatCode !== null) { |
110
|
|
|
// Retrieve any label formatting code |
111
|
1 |
|
$datasetLabelFormatCode = stripslashes($datasetLabelFormatCode); |
112
|
|
|
} |
113
|
|
|
|
114
|
1 |
|
$testCurrentIndex = 0; |
115
|
1 |
|
foreach ($datasetLabels as $i => $datasetLabel) { |
116
|
1 |
|
if (is_array($datasetLabel)) { |
117
|
1 |
|
if ($rotation == 'bar') { |
118
|
1 |
|
$datasetLabels[$i] = implode(' ', $datasetLabel); |
119
|
|
|
} else { |
120
|
1 |
|
$datasetLabel = array_reverse($datasetLabel); |
121
|
1 |
|
$datasetLabels[$i] = implode("\n", $datasetLabel); |
122
|
|
|
} |
123
|
|
|
} else { |
124
|
|
|
// Format labels according to any formatting code |
125
|
1 |
|
if ($datasetLabelFormatCode !== null) { |
126
|
1 |
|
$datasetLabels[$i] = NumberFormat::toFormattedString($datasetLabel, $datasetLabelFormatCode); |
127
|
|
|
} |
128
|
|
|
} |
129
|
1 |
|
++$testCurrentIndex; |
130
|
|
|
} |
131
|
|
|
|
132
|
1 |
|
return $datasetLabels; |
133
|
|
|
} |
134
|
|
|
|
135
|
1 |
|
private function percentageSumCalculation($groupID, $seriesCount) |
136
|
|
|
{ |
137
|
|
|
// Adjust our values to a percentage value across all series in the group |
138
|
1 |
|
for ($i = 0; $i < $seriesCount; ++$i) { |
139
|
1 |
|
if ($i == 0) { |
140
|
1 |
|
$sumValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); |
141
|
|
|
} else { |
142
|
1 |
|
$nextValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); |
143
|
1 |
|
foreach ($nextValues as $k => $value) { |
144
|
1 |
|
if (isset($sumValues[$k])) { |
145
|
1 |
|
$sumValues[$k] += $value; |
146
|
|
|
} else { |
147
|
1 |
|
$sumValues[$k] = $value; |
|
|
|
|
148
|
|
|
} |
149
|
|
|
} |
150
|
|
|
} |
151
|
|
|
} |
152
|
|
|
|
153
|
1 |
|
return $sumValues; |
154
|
|
|
} |
155
|
|
|
|
156
|
1 |
|
private function percentageAdjustValues($dataValues, $sumValues) |
157
|
|
|
{ |
158
|
1 |
|
foreach ($dataValues as $k => $dataValue) { |
159
|
1 |
|
$dataValues[$k] = $dataValue / $sumValues[$k] * 100; |
160
|
|
|
} |
161
|
|
|
|
162
|
1 |
|
return $dataValues; |
163
|
|
|
} |
164
|
|
|
|
165
|
1 |
|
private function getCaption($captionElement) |
166
|
|
|
{ |
167
|
|
|
// Read any caption |
168
|
1 |
|
$caption = ($captionElement !== null) ? $captionElement->getCaption() : null; |
169
|
|
|
// Test if we have a title caption to display |
170
|
1 |
|
if ($caption !== null) { |
171
|
|
|
// If we do, it could be a plain string or an array |
172
|
1 |
|
if (is_array($caption)) { |
173
|
|
|
// Implode an array to a plain string |
174
|
1 |
|
$caption = implode('', $caption); |
175
|
|
|
} |
176
|
|
|
} |
177
|
|
|
|
178
|
1 |
|
return $caption; |
179
|
|
|
} |
180
|
|
|
|
181
|
1 |
|
private function renderTitle() |
182
|
|
|
{ |
183
|
1 |
|
$title = $this->getCaption($this->chart->getTitle()); |
184
|
1 |
|
if ($title !== null) { |
185
|
1 |
|
$this->graph->title->Set($title); |
186
|
|
|
} |
187
|
1 |
|
} |
188
|
|
|
|
189
|
1 |
|
private function renderLegend() |
190
|
|
|
{ |
191
|
1 |
|
$legend = $this->chart->getLegend(); |
192
|
1 |
|
if ($legend !== null) { |
193
|
1 |
|
$legendPosition = $legend->getPosition(); |
194
|
|
|
switch ($legendPosition) { |
195
|
1 |
|
case 'r': |
196
|
1 |
|
$this->graph->legend->SetPos(0.01, 0.5, 'right', 'center'); // right |
197
|
1 |
|
$this->graph->legend->SetColumns(1); |
198
|
|
|
|
199
|
1 |
|
break; |
200
|
|
|
case 'l': |
201
|
|
|
$this->graph->legend->SetPos(0.01, 0.5, 'left', 'center'); // left |
202
|
|
|
$this->graph->legend->SetColumns(1); |
203
|
|
|
|
204
|
|
|
break; |
205
|
|
|
case 't': |
206
|
|
|
$this->graph->legend->SetPos(0.5, 0.01, 'center', 'top'); // top |
207
|
|
|
break; |
208
|
|
|
case 'b': |
209
|
|
|
$this->graph->legend->SetPos(0.5, 0.99, 'center', 'bottom'); // bottom |
210
|
|
|
break; |
211
|
|
|
default: |
212
|
|
|
$this->graph->legend->SetPos(0.01, 0.01, 'right', 'top'); // top-right |
213
|
|
|
$this->graph->legend->SetColumns(1); |
214
|
|
|
|
215
|
1 |
|
break; |
216
|
|
|
} |
217
|
|
|
} else { |
218
|
1 |
|
$this->graph->legend->Hide(); |
219
|
|
|
} |
220
|
1 |
|
} |
221
|
|
|
|
222
|
1 |
|
private function renderCartesianPlotArea($type = 'textlin') |
223
|
|
|
{ |
224
|
1 |
|
$this->graph = new \Graph(self::$width, self::$height); |
225
|
1 |
|
$this->graph->SetScale($type); |
226
|
|
|
|
227
|
1 |
|
$this->renderTitle(); |
228
|
|
|
|
229
|
|
|
// Rotate for bar rather than column chart |
230
|
1 |
|
$rotation = $this->chart->getPlotArea()->getPlotGroupByIndex(0)->getPlotDirection(); |
231
|
1 |
|
$reverse = ($rotation == 'bar') ? true : false; |
232
|
|
|
|
233
|
1 |
|
$xAxisLabel = $this->chart->getXAxisLabel(); |
234
|
1 |
|
if ($xAxisLabel !== null) { |
235
|
1 |
|
$title = $this->getCaption($xAxisLabel); |
236
|
1 |
|
if ($title !== null) { |
237
|
1 |
|
$this->graph->xaxis->SetTitle($title, 'center'); |
238
|
1 |
|
$this->graph->xaxis->title->SetMargin(35); |
239
|
1 |
|
if ($reverse) { |
240
|
|
|
$this->graph->xaxis->title->SetAngle(90); |
241
|
|
|
$this->graph->xaxis->title->SetMargin(90); |
242
|
|
|
} |
243
|
|
|
} |
244
|
|
|
} |
245
|
|
|
|
246
|
1 |
|
$yAxisLabel = $this->chart->getYAxisLabel(); |
247
|
1 |
|
if ($yAxisLabel !== null) { |
248
|
1 |
|
$title = $this->getCaption($yAxisLabel); |
249
|
1 |
|
if ($title !== null) { |
250
|
1 |
|
$this->graph->yaxis->SetTitle($title, 'center'); |
251
|
1 |
|
if ($reverse) { |
252
|
|
|
$this->graph->yaxis->title->SetAngle(0); |
253
|
|
|
$this->graph->yaxis->title->SetMargin(-55); |
254
|
|
|
} |
255
|
|
|
} |
256
|
|
|
} |
257
|
1 |
|
} |
258
|
|
|
|
259
|
1 |
|
private function renderPiePlotArea() |
260
|
|
|
{ |
261
|
1 |
|
$this->graph = new \PieGraph(self::$width, self::$height); |
262
|
|
|
|
263
|
1 |
|
$this->renderTitle(); |
264
|
1 |
|
} |
265
|
|
|
|
266
|
1 |
|
private function renderRadarPlotArea() |
267
|
|
|
{ |
268
|
1 |
|
$this->graph = new \RadarGraph(self::$width, self::$height); |
269
|
1 |
|
$this->graph->SetScale('lin'); |
270
|
|
|
|
271
|
1 |
|
$this->renderTitle(); |
272
|
1 |
|
} |
273
|
|
|
|
274
|
1 |
|
private function renderPlotLine($groupID, $filled = false, $combination = false, $dimensions = '2d') |
|
|
|
|
275
|
|
|
{ |
276
|
1 |
|
$grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping(); |
277
|
|
|
|
278
|
1 |
|
$labelCount = count($this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount()); |
279
|
1 |
View Code Duplication |
if ($labelCount > 0) { |
|
|
|
|
280
|
1 |
|
$datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues(); |
281
|
1 |
|
$datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount); |
282
|
1 |
|
$this->graph->xaxis->SetTickLabels($datasetLabels); |
283
|
|
|
} |
284
|
|
|
|
285
|
1 |
|
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); |
286
|
1 |
|
$seriesPlots = []; |
287
|
1 |
|
if ($grouping == 'percentStacked') { |
288
|
1 |
|
$sumValues = $this->percentageSumCalculation($groupID, $seriesCount); |
289
|
|
|
} |
290
|
|
|
|
291
|
|
|
// Loop through each data series in turn |
292
|
1 |
|
for ($i = 0; $i < $seriesCount; ++$i) { |
293
|
1 |
|
$dataValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); |
294
|
1 |
|
$marker = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker(); |
295
|
|
|
|
296
|
1 |
|
if ($grouping == 'percentStacked') { |
297
|
1 |
|
$dataValues = $this->percentageAdjustValues($dataValues, $sumValues); |
|
|
|
|
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
// Fill in any missing values in the $dataValues array |
301
|
1 |
|
$testCurrentIndex = 0; |
302
|
1 |
View Code Duplication |
foreach ($dataValues as $k => $dataValue) { |
|
|
|
|
303
|
1 |
|
while ($k != $testCurrentIndex) { |
304
|
|
|
$dataValues[$testCurrentIndex] = null; |
305
|
|
|
++$testCurrentIndex; |
306
|
|
|
} |
307
|
1 |
|
++$testCurrentIndex; |
308
|
|
|
} |
309
|
|
|
|
310
|
1 |
|
$seriesPlot = new \LinePlot($dataValues); |
311
|
1 |
|
if ($combination) { |
312
|
|
|
$seriesPlot->SetBarCenter(); |
313
|
|
|
} |
314
|
|
|
|
315
|
1 |
|
if ($filled) { |
316
|
1 |
|
$seriesPlot->SetFilled(true); |
317
|
1 |
|
$seriesPlot->SetColor('black'); |
318
|
1 |
|
$seriesPlot->SetFillColor(self::$colourSet[self::$plotColour++]); |
319
|
|
|
} else { |
320
|
|
|
// Set the appropriate plot marker |
321
|
1 |
|
$this->formatPointMarker($seriesPlot, $marker); |
322
|
|
|
} |
323
|
1 |
|
$dataLabel = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue(); |
324
|
1 |
|
$seriesPlot->SetLegend($dataLabel); |
325
|
|
|
|
326
|
1 |
|
$seriesPlots[] = $seriesPlot; |
327
|
|
|
} |
328
|
|
|
|
329
|
1 |
|
if ($grouping == 'standard') { |
330
|
1 |
|
$groupPlot = $seriesPlots; |
331
|
|
|
} else { |
332
|
1 |
|
$groupPlot = new \AccLinePlot($seriesPlots); |
333
|
|
|
} |
334
|
1 |
|
$this->graph->Add($groupPlot); |
335
|
1 |
|
} |
336
|
|
|
|
337
|
1 |
|
private function renderPlotBar($groupID, $dimensions = '2d') |
338
|
|
|
{ |
339
|
1 |
|
$rotation = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotDirection(); |
340
|
|
|
// Rotate for bar rather than column chart |
341
|
1 |
|
if (($groupID == 0) && ($rotation == 'bar')) { |
342
|
1 |
|
$this->graph->Set90AndMargin(); |
343
|
|
|
} |
344
|
1 |
|
$grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping(); |
345
|
|
|
|
346
|
1 |
|
$labelCount = count($this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount()); |
347
|
1 |
|
if ($labelCount > 0) { |
348
|
1 |
|
$datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues(); |
349
|
1 |
|
$datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount, $rotation); |
350
|
|
|
// Rotate for bar rather than column chart |
351
|
1 |
|
if ($rotation == 'bar') { |
352
|
1 |
|
$datasetLabels = array_reverse($datasetLabels); |
353
|
1 |
|
$this->graph->yaxis->SetPos('max'); |
354
|
1 |
|
$this->graph->yaxis->SetLabelAlign('center', 'top'); |
355
|
1 |
|
$this->graph->yaxis->SetLabelSide(SIDE_RIGHT); |
356
|
|
|
} |
357
|
1 |
|
$this->graph->xaxis->SetTickLabels($datasetLabels); |
358
|
|
|
} |
359
|
|
|
|
360
|
1 |
|
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); |
361
|
1 |
|
$seriesPlots = []; |
362
|
1 |
|
if ($grouping == 'percentStacked') { |
363
|
1 |
|
$sumValues = $this->percentageSumCalculation($groupID, $seriesCount); |
364
|
|
|
} |
365
|
|
|
|
366
|
|
|
// Loop through each data series in turn |
367
|
1 |
|
for ($j = 0; $j < $seriesCount; ++$j) { |
368
|
1 |
|
$dataValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($j)->getDataValues(); |
369
|
1 |
|
if ($grouping == 'percentStacked') { |
370
|
1 |
|
$dataValues = $this->percentageAdjustValues($dataValues, $sumValues); |
|
|
|
|
371
|
|
|
} |
372
|
|
|
|
373
|
|
|
// Fill in any missing values in the $dataValues array |
374
|
1 |
|
$testCurrentIndex = 0; |
375
|
1 |
View Code Duplication |
foreach ($dataValues as $k => $dataValue) { |
|
|
|
|
376
|
1 |
|
while ($k != $testCurrentIndex) { |
377
|
|
|
$dataValues[$testCurrentIndex] = null; |
378
|
|
|
++$testCurrentIndex; |
379
|
|
|
} |
380
|
1 |
|
++$testCurrentIndex; |
381
|
|
|
} |
382
|
|
|
|
383
|
|
|
// Reverse the $dataValues order for bar rather than column chart |
384
|
1 |
|
if ($rotation == 'bar') { |
385
|
1 |
|
$dataValues = array_reverse($dataValues); |
386
|
|
|
} |
387
|
1 |
|
$seriesPlot = new \BarPlot($dataValues); |
388
|
1 |
|
$seriesPlot->SetColor('black'); |
389
|
1 |
|
$seriesPlot->SetFillColor(self::$colourSet[self::$plotColour++]); |
390
|
1 |
|
if ($dimensions == '3d') { |
391
|
1 |
|
$seriesPlot->SetShadow(); |
392
|
|
|
} |
393
|
1 |
|
if (!$this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($j)) { |
394
|
1 |
|
$dataLabel = ''; |
395
|
|
|
} else { |
396
|
1 |
|
$dataLabel = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($j)->getDataValue(); |
397
|
|
|
} |
398
|
1 |
|
$seriesPlot->SetLegend($dataLabel); |
399
|
|
|
|
400
|
1 |
|
$seriesPlots[] = $seriesPlot; |
401
|
|
|
} |
402
|
|
|
// Reverse the plot order for bar rather than column chart |
403
|
1 |
|
if (($rotation == 'bar') && (!($grouping == 'percentStacked'))) { |
404
|
1 |
|
$seriesPlots = array_reverse($seriesPlots); |
405
|
|
|
} |
406
|
|
|
|
407
|
1 |
|
if ($grouping == 'clustered') { |
408
|
1 |
|
$groupPlot = new \GroupBarPlot($seriesPlots); |
409
|
1 |
|
} elseif ($grouping == 'standard') { |
410
|
|
|
$groupPlot = new \GroupBarPlot($seriesPlots); |
411
|
|
|
} else { |
412
|
1 |
|
$groupPlot = new \AccBarPlot($seriesPlots); |
413
|
1 |
|
if ($dimensions == '3d') { |
414
|
1 |
|
$groupPlot->SetShadow(); |
415
|
|
|
} |
416
|
|
|
} |
417
|
|
|
|
418
|
1 |
|
$this->graph->Add($groupPlot); |
419
|
1 |
|
} |
420
|
|
|
|
421
|
1 |
|
private function renderPlotScatter($groupID, $bubble) |
422
|
|
|
{ |
423
|
1 |
|
$grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping(); |
|
|
|
|
424
|
1 |
|
$scatterStyle = $bubbleSize = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle(); |
425
|
|
|
|
426
|
1 |
|
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); |
427
|
1 |
|
$seriesPlots = []; |
|
|
|
|
428
|
|
|
|
429
|
|
|
// Loop through each data series in turn |
430
|
1 |
|
for ($i = 0; $i < $seriesCount; ++$i) { |
431
|
1 |
|
$dataValuesY = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues(); |
432
|
1 |
|
$dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); |
433
|
|
|
|
434
|
1 |
|
foreach ($dataValuesY as $k => $dataValueY) { |
435
|
1 |
|
$dataValuesY[$k] = $k; |
436
|
|
|
} |
437
|
|
|
|
438
|
1 |
|
$seriesPlot = new \ScatterPlot($dataValuesX, $dataValuesY); |
|
|
|
|
439
|
1 |
|
if ($scatterStyle == 'lineMarker') { |
440
|
1 |
|
$seriesPlot->SetLinkPoints(); |
441
|
1 |
|
$seriesPlot->link->SetColor(self::$colourSet[self::$plotColour]); |
442
|
1 |
|
} elseif ($scatterStyle == 'smoothMarker') { |
443
|
1 |
|
$spline = new \Spline($dataValuesY, $dataValuesX); |
444
|
1 |
|
list($splineDataY, $splineDataX) = $spline->Get(count($dataValuesX) * self::$width / 20); |
445
|
1 |
|
$lplot = new \LinePlot($splineDataX, $splineDataY); |
|
|
|
|
446
|
1 |
|
$lplot->SetColor(self::$colourSet[self::$plotColour]); |
447
|
|
|
|
448
|
1 |
|
$this->graph->Add($lplot); |
449
|
|
|
} |
450
|
|
|
|
451
|
1 |
|
if ($bubble) { |
452
|
1 |
|
$this->formatPointMarker($seriesPlot, 'dot'); |
453
|
1 |
|
$seriesPlot->mark->SetColor('black'); |
454
|
1 |
|
$seriesPlot->mark->SetSize($bubbleSize); |
455
|
|
|
} else { |
456
|
1 |
|
$marker = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker(); |
457
|
1 |
|
$this->formatPointMarker($seriesPlot, $marker); |
458
|
|
|
} |
459
|
1 |
|
$dataLabel = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue(); |
460
|
1 |
|
$seriesPlot->SetLegend($dataLabel); |
461
|
|
|
|
462
|
1 |
|
$this->graph->Add($seriesPlot); |
463
|
|
|
} |
464
|
1 |
|
} |
465
|
|
|
|
466
|
1 |
|
private function renderPlotRadar($groupID) |
467
|
|
|
{ |
468
|
1 |
|
$radarStyle = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle(); |
469
|
|
|
|
470
|
1 |
|
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); |
471
|
1 |
|
$seriesPlots = []; |
|
|
|
|
472
|
|
|
|
473
|
|
|
// Loop through each data series in turn |
474
|
1 |
|
for ($i = 0; $i < $seriesCount; ++$i) { |
475
|
1 |
|
$dataValuesY = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues(); |
476
|
1 |
|
$dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); |
477
|
1 |
|
$marker = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker(); |
478
|
|
|
|
479
|
1 |
|
$dataValues = []; |
480
|
1 |
|
foreach ($dataValuesY as $k => $dataValueY) { |
481
|
1 |
|
$dataValues[$k] = implode(' ', array_reverse($dataValueY)); |
482
|
|
|
} |
483
|
1 |
|
$tmp = array_shift($dataValues); |
484
|
1 |
|
$dataValues[] = $tmp; |
485
|
1 |
|
$tmp = array_shift($dataValuesX); |
486
|
1 |
|
$dataValuesX[] = $tmp; |
487
|
|
|
|
488
|
1 |
|
$this->graph->SetTitles(array_reverse($dataValues)); |
|
|
|
|
489
|
|
|
|
490
|
1 |
|
$seriesPlot = new \RadarPlot(array_reverse($dataValuesX)); |
491
|
|
|
|
492
|
1 |
|
$dataLabel = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue(); |
493
|
1 |
|
$seriesPlot->SetColor(self::$colourSet[self::$plotColour++]); |
494
|
1 |
|
if ($radarStyle == 'filled') { |
495
|
1 |
|
$seriesPlot->SetFillColor(self::$colourSet[self::$plotColour]); |
496
|
|
|
} |
497
|
1 |
|
$this->formatPointMarker($seriesPlot, $marker); |
498
|
1 |
|
$seriesPlot->SetLegend($dataLabel); |
499
|
|
|
|
500
|
1 |
|
$this->graph->Add($seriesPlot); |
501
|
|
|
} |
502
|
1 |
|
} |
503
|
|
|
|
504
|
1 |
|
private function renderPlotContour($groupID) |
505
|
|
|
{ |
506
|
1 |
|
$contourStyle = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle(); |
|
|
|
|
507
|
|
|
|
508
|
1 |
|
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); |
509
|
1 |
|
$seriesPlots = []; |
|
|
|
|
510
|
|
|
|
511
|
1 |
|
$dataValues = []; |
512
|
|
|
// Loop through each data series in turn |
513
|
1 |
|
for ($i = 0; $i < $seriesCount; ++$i) { |
514
|
1 |
|
$dataValuesY = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues(); |
|
|
|
|
515
|
1 |
|
$dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues(); |
516
|
|
|
|
517
|
1 |
|
$dataValues[$i] = $dataValuesX; |
518
|
|
|
} |
519
|
1 |
|
$seriesPlot = new \ContourPlot($dataValues); |
520
|
|
|
|
521
|
1 |
|
$this->graph->Add($seriesPlot); |
522
|
1 |
|
} |
523
|
|
|
|
524
|
1 |
|
private function renderPlotStock($groupID) |
525
|
|
|
{ |
526
|
1 |
|
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); |
527
|
1 |
|
$plotOrder = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotOrder(); |
528
|
|
|
|
529
|
1 |
|
$dataValues = []; |
530
|
|
|
// Loop through each data series in turn and build the plot arrays |
531
|
1 |
|
foreach ($plotOrder as $i => $v) { |
532
|
1 |
|
$dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($v)->getDataValues(); |
533
|
1 |
|
foreach ($dataValuesX as $j => $dataValueX) { |
534
|
1 |
|
$dataValues[$plotOrder[$i]][$j] = $dataValueX; |
535
|
|
|
} |
536
|
|
|
} |
537
|
1 |
|
if (empty($dataValues)) { |
538
|
|
|
return; |
539
|
|
|
} |
540
|
|
|
|
541
|
1 |
|
$dataValuesPlot = []; |
542
|
|
|
// Flatten the plot arrays to a single dimensional array to work with jpgraph |
543
|
1 |
|
for ($j = 0; $j < count($dataValues[0]); ++$j) { |
|
|
|
|
544
|
1 |
|
for ($i = 0; $i < $seriesCount; ++$i) { |
545
|
1 |
|
$dataValuesPlot[] = $dataValues[$i][$j]; |
546
|
|
|
} |
547
|
|
|
} |
548
|
|
|
|
549
|
|
|
// Set the x-axis labels |
550
|
1 |
|
$labelCount = count($this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount()); |
551
|
1 |
View Code Duplication |
if ($labelCount > 0) { |
|
|
|
|
552
|
1 |
|
$datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues(); |
553
|
1 |
|
$datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount); |
554
|
1 |
|
$this->graph->xaxis->SetTickLabels($datasetLabels); |
555
|
|
|
} |
556
|
|
|
|
557
|
1 |
|
$seriesPlot = new \StockPlot($dataValuesPlot); |
558
|
1 |
|
$seriesPlot->SetWidth(20); |
559
|
|
|
|
560
|
1 |
|
$this->graph->Add($seriesPlot); |
561
|
1 |
|
} |
562
|
|
|
|
563
|
1 |
View Code Duplication |
private function renderAreaChart($groupCount, $dimensions = '2d') |
|
|
|
|
564
|
|
|
{ |
565
|
1 |
|
$this->renderCartesianPlotArea(); |
566
|
|
|
|
567
|
1 |
|
for ($i = 0; $i < $groupCount; ++$i) { |
568
|
1 |
|
$this->renderPlotLine($i, true, false, $dimensions); |
569
|
|
|
} |
570
|
1 |
|
} |
571
|
|
|
|
572
|
1 |
View Code Duplication |
private function renderLineChart($groupCount, $dimensions = '2d') |
|
|
|
|
573
|
|
|
{ |
574
|
1 |
|
$this->renderCartesianPlotArea(); |
575
|
|
|
|
576
|
1 |
|
for ($i = 0; $i < $groupCount; ++$i) { |
577
|
1 |
|
$this->renderPlotLine($i, false, false, $dimensions); |
578
|
|
|
} |
579
|
1 |
|
} |
580
|
|
|
|
581
|
1 |
View Code Duplication |
private function renderBarChart($groupCount, $dimensions = '2d') |
|
|
|
|
582
|
|
|
{ |
583
|
1 |
|
$this->renderCartesianPlotArea(); |
584
|
|
|
|
585
|
1 |
|
for ($i = 0; $i < $groupCount; ++$i) { |
586
|
1 |
|
$this->renderPlotBar($i, $dimensions); |
587
|
|
|
} |
588
|
1 |
|
} |
589
|
|
|
|
590
|
1 |
View Code Duplication |
private function renderScatterChart($groupCount) |
|
|
|
|
591
|
|
|
{ |
592
|
1 |
|
$this->renderCartesianPlotArea('linlin'); |
593
|
|
|
|
594
|
1 |
|
for ($i = 0; $i < $groupCount; ++$i) { |
595
|
1 |
|
$this->renderPlotScatter($i, false); |
596
|
|
|
} |
597
|
1 |
|
} |
598
|
|
|
|
599
|
1 |
View Code Duplication |
private function renderBubbleChart($groupCount) |
|
|
|
|
600
|
|
|
{ |
601
|
1 |
|
$this->renderCartesianPlotArea('linlin'); |
602
|
|
|
|
603
|
1 |
|
for ($i = 0; $i < $groupCount; ++$i) { |
604
|
1 |
|
$this->renderPlotScatter($i, true); |
605
|
|
|
} |
606
|
1 |
|
} |
607
|
|
|
|
608
|
1 |
|
private function renderPieChart($groupCount, $dimensions = '2d', $doughnut = false, $multiplePlots = false) |
609
|
|
|
{ |
610
|
1 |
|
$this->renderPiePlotArea(); |
611
|
|
|
|
612
|
1 |
|
$iLimit = ($multiplePlots) ? $groupCount : 1; |
613
|
1 |
|
for ($groupID = 0; $groupID < $iLimit; ++$groupID) { |
614
|
1 |
|
$grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping(); |
|
|
|
|
615
|
1 |
|
$exploded = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle(); |
616
|
1 |
|
if ($groupID == 0) { |
617
|
1 |
|
$labelCount = count($this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount()); |
618
|
1 |
View Code Duplication |
if ($labelCount > 0) { |
|
|
|
|
619
|
1 |
|
$datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues(); |
620
|
1 |
|
$datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount); |
621
|
|
|
} |
622
|
|
|
} |
623
|
|
|
|
624
|
1 |
|
$seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount(); |
625
|
1 |
|
$seriesPlots = []; |
|
|
|
|
626
|
|
|
// For pie charts, we only display the first series: doughnut charts generally display all series |
627
|
1 |
|
$jLimit = ($multiplePlots) ? $seriesCount : 1; |
628
|
|
|
// Loop through each data series in turn |
629
|
1 |
|
for ($j = 0; $j < $jLimit; ++$j) { |
630
|
1 |
|
$dataValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($j)->getDataValues(); |
631
|
|
|
|
632
|
|
|
// Fill in any missing values in the $dataValues array |
633
|
1 |
|
$testCurrentIndex = 0; |
634
|
1 |
View Code Duplication |
foreach ($dataValues as $k => $dataValue) { |
|
|
|
|
635
|
1 |
|
while ($k != $testCurrentIndex) { |
636
|
|
|
$dataValues[$testCurrentIndex] = null; |
637
|
|
|
++$testCurrentIndex; |
638
|
|
|
} |
639
|
1 |
|
++$testCurrentIndex; |
640
|
|
|
} |
641
|
|
|
|
642
|
1 |
|
if ($dimensions == '3d') { |
643
|
1 |
|
$seriesPlot = new \PiePlot3D($dataValues); |
644
|
|
|
} else { |
645
|
1 |
|
if ($doughnut) { |
646
|
1 |
|
$seriesPlot = new \PiePlotC($dataValues); |
647
|
|
|
} else { |
648
|
1 |
|
$seriesPlot = new \PiePlot($dataValues); |
649
|
|
|
} |
650
|
|
|
} |
651
|
|
|
|
652
|
1 |
|
if ($multiplePlots) { |
653
|
1 |
|
$seriesPlot->SetSize(($jLimit - $j) / ($jLimit * 4)); |
654
|
|
|
} |
655
|
|
|
|
656
|
1 |
|
if ($doughnut) { |
657
|
1 |
|
$seriesPlot->SetMidColor('white'); |
658
|
|
|
} |
659
|
|
|
|
660
|
1 |
|
$seriesPlot->SetColor(self::$colourSet[self::$plotColour++]); |
661
|
1 |
|
if (count($datasetLabels) > 0) { |
662
|
1 |
|
$seriesPlot->SetLabels(array_fill(0, count($datasetLabels), '')); |
|
|
|
|
663
|
|
|
} |
664
|
1 |
|
if ($dimensions != '3d') { |
665
|
1 |
|
$seriesPlot->SetGuideLines(false); |
666
|
|
|
} |
667
|
1 |
|
if ($j == 0) { |
668
|
1 |
|
if ($exploded) { |
669
|
1 |
|
$seriesPlot->ExplodeAll(); |
670
|
|
|
} |
671
|
1 |
|
$seriesPlot->SetLegends($datasetLabels); |
672
|
|
|
} |
673
|
|
|
|
674
|
1 |
|
$this->graph->Add($seriesPlot); |
675
|
|
|
} |
676
|
|
|
} |
677
|
1 |
|
} |
678
|
|
|
|
679
|
1 |
|
private function renderRadarChart($groupCount) |
680
|
|
|
{ |
681
|
1 |
|
$this->renderRadarPlotArea(); |
682
|
|
|
|
683
|
1 |
|
for ($groupID = 0; $groupID < $groupCount; ++$groupID) { |
684
|
1 |
|
$this->renderPlotRadar($groupID); |
685
|
|
|
} |
686
|
1 |
|
} |
687
|
|
|
|
688
|
1 |
|
private function renderStockChart($groupCount) |
689
|
|
|
{ |
690
|
1 |
|
$this->renderCartesianPlotArea('intint'); |
691
|
|
|
|
692
|
1 |
|
for ($groupID = 0; $groupID < $groupCount; ++$groupID) { |
693
|
1 |
|
$this->renderPlotStock($groupID); |
694
|
|
|
} |
695
|
1 |
|
} |
696
|
|
|
|
697
|
1 |
|
private function renderContourChart($groupCount, $dimensions) |
|
|
|
|
698
|
|
|
{ |
699
|
1 |
|
$this->renderCartesianPlotArea('intint'); |
700
|
|
|
|
701
|
1 |
|
for ($i = 0; $i < $groupCount; ++$i) { |
702
|
1 |
|
$this->renderPlotContour($i); |
703
|
|
|
} |
704
|
1 |
|
} |
705
|
|
|
|
706
|
1 |
|
private function renderCombinationChart($groupCount, $dimensions, $outputDestination) |
|
|
|
|
707
|
|
|
{ |
708
|
1 |
|
$this->renderCartesianPlotArea(); |
709
|
|
|
|
710
|
1 |
|
for ($i = 0; $i < $groupCount; ++$i) { |
711
|
1 |
|
$dimensions = null; |
712
|
1 |
|
$chartType = $this->chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotType(); |
713
|
|
|
switch ($chartType) { |
714
|
1 |
|
case 'area3DChart': |
715
|
|
|
$dimensions = '3d'; |
716
|
|
|
// no break |
717
|
1 |
|
case 'areaChart': |
718
|
|
|
$this->renderPlotLine($i, true, true, $dimensions); |
719
|
|
|
|
720
|
|
|
break; |
721
|
1 |
|
case 'bar3DChart': |
722
|
|
|
$dimensions = '3d'; |
723
|
|
|
// no break |
724
|
1 |
|
case 'barChart': |
725
|
1 |
|
$this->renderPlotBar($i, $dimensions); |
726
|
|
|
|
727
|
1 |
|
break; |
728
|
1 |
|
case 'line3DChart': |
729
|
|
|
$dimensions = '3d'; |
730
|
|
|
// no break |
731
|
1 |
|
case 'lineChart': |
732
|
|
|
$this->renderPlotLine($i, false, true, $dimensions); |
733
|
|
|
|
734
|
|
|
break; |
735
|
1 |
|
case 'scatterChart': |
736
|
|
|
$this->renderPlotScatter($i, false); |
737
|
|
|
|
738
|
|
|
break; |
739
|
1 |
|
case 'bubbleChart': |
740
|
|
|
$this->renderPlotScatter($i, true); |
741
|
|
|
|
742
|
|
|
break; |
743
|
|
|
default: |
744
|
1 |
|
$this->graph = null; |
745
|
|
|
|
746
|
1 |
|
return false; |
747
|
|
|
} |
748
|
|
|
} |
749
|
|
|
|
750
|
|
|
$this->renderLegend(); |
751
|
|
|
|
752
|
|
|
$this->graph->Stroke($outputDestination); |
753
|
|
|
|
754
|
|
|
return true; |
755
|
|
|
} |
756
|
|
|
|
757
|
1 |
|
public function render($outputDestination) |
758
|
|
|
{ |
759
|
1 |
|
self::$plotColour = 0; |
760
|
|
|
|
761
|
1 |
|
$groupCount = $this->chart->getPlotArea()->getPlotGroupCount(); |
762
|
|
|
|
763
|
1 |
|
$dimensions = null; |
764
|
1 |
|
if ($groupCount == 1) { |
765
|
1 |
|
$chartType = $this->chart->getPlotArea()->getPlotGroupByIndex(0)->getPlotType(); |
766
|
|
|
} else { |
767
|
1 |
|
$chartTypes = []; |
768
|
1 |
|
for ($i = 0; $i < $groupCount; ++$i) { |
769
|
1 |
|
$chartTypes[] = $this->chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotType(); |
770
|
|
|
} |
771
|
1 |
|
$chartTypes = array_unique($chartTypes); |
772
|
1 |
|
if (count($chartTypes) == 1) { |
773
|
|
|
$chartType = array_pop($chartTypes); |
774
|
1 |
|
} elseif (count($chartTypes) == 0) { |
775
|
|
|
echo 'Chart is not yet implemented<br />'; |
776
|
|
|
|
777
|
|
|
return false; |
778
|
|
|
} else { |
779
|
1 |
|
return $this->renderCombinationChart($groupCount, $dimensions, $outputDestination); |
780
|
|
|
} |
781
|
|
|
} |
782
|
|
|
|
783
|
|
|
switch ($chartType) { |
784
|
1 |
|
case 'area3DChart': |
785
|
1 |
|
$dimensions = '3d'; |
786
|
|
|
// no break |
787
|
1 |
|
case 'areaChart': |
788
|
1 |
|
$this->renderAreaChart($groupCount, $dimensions); |
789
|
|
|
|
790
|
1 |
|
break; |
791
|
1 |
|
case 'bar3DChart': |
792
|
1 |
|
$dimensions = '3d'; |
793
|
|
|
// no break |
794
|
1 |
|
case 'barChart': |
795
|
1 |
|
$this->renderBarChart($groupCount, $dimensions); |
796
|
|
|
|
797
|
1 |
|
break; |
798
|
1 |
|
case 'line3DChart': |
799
|
1 |
|
$dimensions = '3d'; |
800
|
|
|
// no break |
801
|
1 |
|
case 'lineChart': |
802
|
1 |
|
$this->renderLineChart($groupCount, $dimensions); |
803
|
|
|
|
804
|
1 |
|
break; |
805
|
1 |
|
case 'pie3DChart': |
806
|
1 |
|
$dimensions = '3d'; |
807
|
|
|
// no break |
808
|
1 |
|
case 'pieChart': |
809
|
1 |
|
$this->renderPieChart($groupCount, $dimensions, false, false); |
810
|
|
|
|
811
|
1 |
|
break; |
812
|
1 |
|
case 'doughnut3DChart': |
813
|
|
|
$dimensions = '3d'; |
814
|
|
|
// no break |
815
|
1 |
|
case 'doughnutChart': |
816
|
1 |
|
$this->renderPieChart($groupCount, $dimensions, true, true); |
817
|
|
|
|
818
|
1 |
|
break; |
819
|
1 |
|
case 'scatterChart': |
820
|
1 |
|
$this->renderScatterChart($groupCount); |
821
|
|
|
|
822
|
1 |
|
break; |
823
|
1 |
|
case 'bubbleChart': |
824
|
1 |
|
$this->renderBubbleChart($groupCount); |
825
|
|
|
|
826
|
1 |
|
break; |
827
|
1 |
|
case 'radarChart': |
828
|
1 |
|
$this->renderRadarChart($groupCount); |
829
|
|
|
|
830
|
1 |
|
break; |
831
|
1 |
|
case 'surface3DChart': |
832
|
1 |
|
$dimensions = '3d'; |
833
|
|
|
// no break |
834
|
1 |
|
case 'surfaceChart': |
835
|
1 |
|
$this->renderContourChart($groupCount, $dimensions); |
836
|
|
|
|
837
|
1 |
|
break; |
838
|
1 |
|
case 'stockChart': |
839
|
1 |
|
$this->renderStockChart($groupCount); |
840
|
|
|
|
841
|
1 |
|
break; |
842
|
|
|
default: |
843
|
|
|
echo $chartType . ' is not yet implemented<br />'; |
844
|
|
|
|
845
|
|
|
return false; |
846
|
|
|
} |
847
|
1 |
|
$this->renderLegend(); |
848
|
|
|
|
849
|
1 |
|
$this->graph->Stroke($outputDestination); |
850
|
|
|
|
851
|
1 |
|
return true; |
852
|
|
|
} |
853
|
|
|
} |
854
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.