Failed Conditions
Push — master ( a2bb82...a189d9 )
by Adrien
10:27 queued 01:00
created

JpGraph::renderPlotLine()   C

Complexity

Conditions 10
Paths 200

Size

Total Lines 63
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 35
CRAP Score 10.049

Importance

Changes 0
Metric Value
cc 10
eloc 40
nc 200
nop 4
dl 0
loc 63
ccs 35
cts 38
cp 0.9211
crap 10.049
rs 6.8333
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Chart\Renderer;
4
5
use AccBarPlot;
6
use AccLinePlot;
7
use BarPlot;
8
use ContourPlot;
9
use Graph;
10
use GroupBarPlot;
11
use LinePlot;
12
use PhpOffice\PhpSpreadsheet\Chart\Chart;
13
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
14
use PieGraph;
15
use PiePlot;
16
use PiePlot3D;
17
use PiePlotC;
18
use RadarGraph;
19
use RadarPlot;
20
use ScatterPlot;
21
use Spline;
22
use StockPlot;
23
24
class JpGraph implements IRenderer
25
{
26
    private static $width = 640;
27
28
    private static $height = 480;
29
30
    private static $colourSet = [
31
        'mediumpurple1', 'palegreen3', 'gold1', 'cadetblue1',
32
        'darkmagenta', 'coral', 'dodgerblue3', 'eggplant',
33
        'mediumblue', 'magenta', 'sandybrown', 'cyan',
34
        'firebrick1', 'forestgreen', 'deeppink4', 'darkolivegreen',
35
        'goldenrod2',
36
    ];
37
38
    private static $markSet;
39
40
    private $chart;
41
42
    private $graph;
43
44
    private static $plotColour = 0;
45
46
    private static $plotMark = 0;
47
48
    /**
49
     * Create a new jpgraph.
50
     */
51 1
    public function __construct(Chart $chart)
52
    {
53 1
        self::init();
54 1
        $this->graph = null;
55 1
        $this->chart = $chart;
56 1
    }
57
58 1
    private static function init(): void
59
    {
60 1
        static $loaded = false;
61 1
        if ($loaded) {
62 1
            return;
63
        }
64
65 1
        \JpGraph\JpGraph::load();
66 1
        \JpGraph\JpGraph::module('bar');
67 1
        \JpGraph\JpGraph::module('contour');
68 1
        \JpGraph\JpGraph::module('line');
69 1
        \JpGraph\JpGraph::module('pie');
70 1
        \JpGraph\JpGraph::module('pie3d');
71 1
        \JpGraph\JpGraph::module('radar');
72 1
        \JpGraph\JpGraph::module('regstat');
73 1
        \JpGraph\JpGraph::module('scatter');
74 1
        \JpGraph\JpGraph::module('stock');
75
76 1
        self::$markSet = [
77 1
            'diamond' => MARK_DIAMOND,
78 1
            'square' => MARK_SQUARE,
79 1
            'triangle' => MARK_UTRIANGLE,
80 1
            'x' => MARK_X,
81 1
            'star' => MARK_STAR,
82 1
            'dot' => MARK_FILLEDCIRCLE,
83 1
            'dash' => MARK_DTRIANGLE,
84 1
            'circle' => MARK_CIRCLE,
85 1
            'plus' => MARK_CROSS,
86
        ];
87
88 1
        $loaded = true;
89 1
    }
90
91 1
    private function formatPointMarker($seriesPlot, $markerID)
92
    {
93 1
        $plotMarkKeys = array_keys(self::$markSet);
94 1
        if ($markerID === null) {
95
            //    Use default plot marker (next marker in the series)
96 1
            self::$plotMark %= count(self::$markSet);
97 1
            $seriesPlot->mark->SetType(self::$markSet[$plotMarkKeys[self::$plotMark++]]);
98 1
        } elseif ($markerID !== 'none') {
99
            //    Use specified plot marker (if it exists)
100 1
            if (isset(self::$markSet[$markerID])) {
101 1
                $seriesPlot->mark->SetType(self::$markSet[$markerID]);
102
            } else {
103
                //    If the specified plot marker doesn't exist, use default plot marker (next marker in the series)
104
                self::$plotMark %= count(self::$markSet);
105 1
                $seriesPlot->mark->SetType(self::$markSet[$plotMarkKeys[self::$plotMark++]]);
106
            }
107
        } else {
108
            //    Hide plot marker
109 1
            $seriesPlot->mark->Hide();
110
        }
111 1
        $seriesPlot->mark->SetColor(self::$colourSet[self::$plotColour]);
112 1
        $seriesPlot->mark->SetFillColor(self::$colourSet[self::$plotColour]);
113 1
        $seriesPlot->SetColor(self::$colourSet[self::$plotColour++]);
114
115 1
        return $seriesPlot;
116
    }
117
118 1
    private function formatDataSetLabels($groupID, $datasetLabels, $labelCount, $rotation = '')
0 ignored issues
show
Unused Code introduced by
The parameter $labelCount is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

118
    private function formatDataSetLabels($groupID, $datasetLabels, /** @scrutinizer ignore-unused */ $labelCount, $rotation = '')

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
119
    {
120 1
        $datasetLabelFormatCode = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getFormatCode();
121 1
        if ($datasetLabelFormatCode !== null) {
0 ignored issues
show
introduced by
The condition $datasetLabelFormatCode !== null is always true.
Loading history...
122
            //    Retrieve any label formatting code
123 1
            $datasetLabelFormatCode = stripslashes($datasetLabelFormatCode);
124
        }
125
126 1
        $testCurrentIndex = 0;
127 1
        foreach ($datasetLabels as $i => $datasetLabel) {
128 1
            if (is_array($datasetLabel)) {
129 1
                if ($rotation == 'bar') {
130 1
                    $datasetLabels[$i] = implode(' ', $datasetLabel);
131
                } else {
132 1
                    $datasetLabel = array_reverse($datasetLabel);
133 1
                    $datasetLabels[$i] = implode("\n", $datasetLabel);
134
                }
135
            } else {
136
                //    Format labels according to any formatting code
137 1
                if ($datasetLabelFormatCode !== null) {
138 1
                    $datasetLabels[$i] = NumberFormat::toFormattedString($datasetLabel, $datasetLabelFormatCode);
139
                }
140
            }
141 1
            ++$testCurrentIndex;
142
        }
143
144 1
        return $datasetLabels;
145
    }
146
147 1
    private function percentageSumCalculation($groupID, $seriesCount)
148
    {
149 1
        $sumValues = [];
150
        //    Adjust our values to a percentage value across all series in the group
151 1
        for ($i = 0; $i < $seriesCount; ++$i) {
152 1
            if ($i == 0) {
153 1
                $sumValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
154
            } else {
155 1
                $nextValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
156 1
                foreach ($nextValues as $k => $value) {
157 1
                    if (isset($sumValues[$k])) {
158 1
                        $sumValues[$k] += $value;
159
                    } else {
160
                        $sumValues[$k] = $value;
161
                    }
162
                }
163
            }
164
        }
165
166 1
        return $sumValues;
167
    }
168
169 1
    private function percentageAdjustValues($dataValues, $sumValues)
170
    {
171 1
        foreach ($dataValues as $k => $dataValue) {
172 1
            $dataValues[$k] = $dataValue / $sumValues[$k] * 100;
173
        }
174
175 1
        return $dataValues;
176
    }
177
178 1
    private function getCaption($captionElement)
179
    {
180
        //    Read any caption
181 1
        $caption = ($captionElement !== null) ? $captionElement->getCaption() : null;
182
        //    Test if we have a title caption to display
183 1
        if ($caption !== null) {
184
            //    If we do, it could be a plain string or an array
185 1
            if (is_array($caption)) {
186
                //    Implode an array to a plain string
187 1
                $caption = implode('', $caption);
188
            }
189
        }
190
191 1
        return $caption;
192
    }
193
194 1
    private function renderTitle(): void
195
    {
196 1
        $title = $this->getCaption($this->chart->getTitle());
197 1
        if ($title !== null) {
198 1
            $this->graph->title->Set($title);
199
        }
200 1
    }
201
202 1
    private function renderLegend(): void
203
    {
204 1
        $legend = $this->chart->getLegend();
205 1
        if ($legend !== null) {
206 1
            $legendPosition = $legend->getPosition();
207
            switch ($legendPosition) {
208 1
                case 'r':
209 1
                    $this->graph->legend->SetPos(0.01, 0.5, 'right', 'center'); //    right
210 1
                    $this->graph->legend->SetColumns(1);
211
212 1
                    break;
213
                case 'l':
214
                    $this->graph->legend->SetPos(0.01, 0.5, 'left', 'center'); //    left
215
                    $this->graph->legend->SetColumns(1);
216
217
                    break;
218
                case 't':
219
                    $this->graph->legend->SetPos(0.5, 0.01, 'center', 'top'); //    top
220
221
                    break;
222
                case 'b':
223
                    $this->graph->legend->SetPos(0.5, 0.99, 'center', 'bottom'); //    bottom
224
225
                    break;
226
                default:
227
                    $this->graph->legend->SetPos(0.01, 0.01, 'right', 'top'); //    top-right
228
                    $this->graph->legend->SetColumns(1);
229
230 1
                    break;
231
            }
232
        } else {
233 1
            $this->graph->legend->Hide();
234
        }
235 1
    }
236
237 1
    private function renderCartesianPlotArea($type = 'textlin'): void
238
    {
239 1
        $this->graph = new Graph(self::$width, self::$height);
240 1
        $this->graph->SetScale($type);
241
242 1
        $this->renderTitle();
243
244
        //    Rotate for bar rather than column chart
245 1
        $rotation = $this->chart->getPlotArea()->getPlotGroupByIndex(0)->getPlotDirection();
246 1
        $reverse = $rotation == 'bar';
247
248 1
        $xAxisLabel = $this->chart->getXAxisLabel();
249 1
        if ($xAxisLabel !== null) {
250 1
            $title = $this->getCaption($xAxisLabel);
251 1
            if ($title !== null) {
252 1
                $this->graph->xaxis->SetTitle($title, 'center');
253 1
                $this->graph->xaxis->title->SetMargin(35);
254 1
                if ($reverse) {
255
                    $this->graph->xaxis->title->SetAngle(90);
256
                    $this->graph->xaxis->title->SetMargin(90);
257
                }
258
            }
259
        }
260
261 1
        $yAxisLabel = $this->chart->getYAxisLabel();
262 1
        if ($yAxisLabel !== null) {
263 1
            $title = $this->getCaption($yAxisLabel);
264 1
            if ($title !== null) {
265 1
                $this->graph->yaxis->SetTitle($title, 'center');
266 1
                if ($reverse) {
267
                    $this->graph->yaxis->title->SetAngle(0);
268
                    $this->graph->yaxis->title->SetMargin(-55);
269
                }
270
            }
271
        }
272 1
    }
273
274 1
    private function renderPiePlotArea(): void
275
    {
276 1
        $this->graph = new PieGraph(self::$width, self::$height);
277
278 1
        $this->renderTitle();
279 1
    }
280
281 1
    private function renderRadarPlotArea(): void
282
    {
283 1
        $this->graph = new RadarGraph(self::$width, self::$height);
284 1
        $this->graph->SetScale('lin');
285
286 1
        $this->renderTitle();
287 1
    }
288
289 1
    private function renderPlotLine($groupID, $filled = false, $combination = false, $dimensions = '2d'): void
0 ignored issues
show
Unused Code introduced by
The parameter $dimensions is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

289
    private function renderPlotLine($groupID, $filled = false, $combination = false, /** @scrutinizer ignore-unused */ $dimensions = '2d'): void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
290
    {
291 1
        $grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping();
292
293 1
        $labelCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount();
294 1
        if ($labelCount > 0) {
295 1
            $datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
296 1
            $datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount);
297 1
            $this->graph->xaxis->SetTickLabels($datasetLabels);
298
        }
299
300 1
        $seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
301 1
        $seriesPlots = [];
302 1
        if ($grouping == 'percentStacked') {
303 1
            $sumValues = $this->percentageSumCalculation($groupID, $seriesCount);
304
        } else {
305 1
            $sumValues = [];
306
        }
307
308
        //    Loop through each data series in turn
309 1
        for ($i = 0; $i < $seriesCount; ++$i) {
310 1
            $dataValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
311 1
            $marker = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker();
312
313 1
            if ($grouping == 'percentStacked') {
314 1
                $dataValues = $this->percentageAdjustValues($dataValues, $sumValues);
315
            }
316
317
            //    Fill in any missing values in the $dataValues array
318 1
            $testCurrentIndex = 0;
319 1
            foreach ($dataValues as $k => $dataValue) {
320 1
                while ($k != $testCurrentIndex) {
321
                    $dataValues[$testCurrentIndex] = null;
322
                    ++$testCurrentIndex;
323
                }
324 1
                ++$testCurrentIndex;
325
            }
326
327 1
            $seriesPlot = new LinePlot($dataValues);
328 1
            if ($combination) {
329
                $seriesPlot->SetBarCenter();
330
            }
331
332 1
            if ($filled) {
333 1
                $seriesPlot->SetFilled(true);
334 1
                $seriesPlot->SetColor('black');
335 1
                $seriesPlot->SetFillColor(self::$colourSet[self::$plotColour++]);
336
            } else {
337
                //    Set the appropriate plot marker
338 1
                $this->formatPointMarker($seriesPlot, $marker);
339
            }
340 1
            $dataLabel = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue();
341 1
            $seriesPlot->SetLegend($dataLabel);
342
343 1
            $seriesPlots[] = $seriesPlot;
344
        }
345
346 1
        if ($grouping == 'standard') {
347 1
            $groupPlot = $seriesPlots;
348
        } else {
349 1
            $groupPlot = new AccLinePlot($seriesPlots);
350
        }
351 1
        $this->graph->Add($groupPlot);
352 1
    }
353
354 1
    private function renderPlotBar($groupID, $dimensions = '2d'): void
355
    {
356 1
        $rotation = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotDirection();
357
        //    Rotate for bar rather than column chart
358 1
        if (($groupID == 0) && ($rotation == 'bar')) {
359 1
            $this->graph->Set90AndMargin();
360
        }
361 1
        $grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping();
362
363 1
        $labelCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount();
364 1
        if ($labelCount > 0) {
365 1
            $datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
366 1
            $datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount, $rotation);
367
            //    Rotate for bar rather than column chart
368 1
            if ($rotation == 'bar') {
369 1
                $datasetLabels = array_reverse($datasetLabels);
370 1
                $this->graph->yaxis->SetPos('max');
371 1
                $this->graph->yaxis->SetLabelAlign('center', 'top');
372 1
                $this->graph->yaxis->SetLabelSide(SIDE_RIGHT);
373
            }
374 1
            $this->graph->xaxis->SetTickLabels($datasetLabels);
375
        }
376
377 1
        $seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
378 1
        $seriesPlots = [];
379 1
        if ($grouping == 'percentStacked') {
380 1
            $sumValues = $this->percentageSumCalculation($groupID, $seriesCount);
381
        } else {
382 1
            $sumValues = [];
383
        }
384
385
        //    Loop through each data series in turn
386 1
        for ($j = 0; $j < $seriesCount; ++$j) {
387 1
            $dataValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($j)->getDataValues();
388 1
            if ($grouping == 'percentStacked') {
389 1
                $dataValues = $this->percentageAdjustValues($dataValues, $sumValues);
390
            }
391
392
            //    Fill in any missing values in the $dataValues array
393 1
            $testCurrentIndex = 0;
394 1
            foreach ($dataValues as $k => $dataValue) {
395 1
                while ($k != $testCurrentIndex) {
396
                    $dataValues[$testCurrentIndex] = null;
397
                    ++$testCurrentIndex;
398
                }
399 1
                ++$testCurrentIndex;
400
            }
401
402
            //    Reverse the $dataValues order for bar rather than column chart
403 1
            if ($rotation == 'bar') {
404 1
                $dataValues = array_reverse($dataValues);
405
            }
406 1
            $seriesPlot = new BarPlot($dataValues);
407 1
            $seriesPlot->SetColor('black');
408 1
            $seriesPlot->SetFillColor(self::$colourSet[self::$plotColour++]);
409 1
            if ($dimensions == '3d') {
410 1
                $seriesPlot->SetShadow();
411
            }
412 1
            if (!$this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($j)) {
413 1
                $dataLabel = '';
414
            } else {
415 1
                $dataLabel = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($j)->getDataValue();
416
            }
417 1
            $seriesPlot->SetLegend($dataLabel);
418
419 1
            $seriesPlots[] = $seriesPlot;
420
        }
421
        //    Reverse the plot order for bar rather than column chart
422 1
        if (($rotation == 'bar') && ($grouping != 'percentStacked')) {
423 1
            $seriesPlots = array_reverse($seriesPlots);
424
        }
425
426 1
        if ($grouping == 'clustered') {
427 1
            $groupPlot = new GroupBarPlot($seriesPlots);
428 1
        } elseif ($grouping == 'standard') {
429
            $groupPlot = new GroupBarPlot($seriesPlots);
430
        } else {
431 1
            $groupPlot = new AccBarPlot($seriesPlots);
432 1
            if ($dimensions == '3d') {
433 1
                $groupPlot->SetShadow();
434
            }
435
        }
436
437 1
        $this->graph->Add($groupPlot);
438 1
    }
439
440 1
    private function renderPlotScatter($groupID, $bubble): void
441
    {
442 1
        $grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping();
0 ignored issues
show
Unused Code introduced by
The assignment to $grouping is dead and can be removed.
Loading history...
443 1
        $scatterStyle = $bubbleSize = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
444
445 1
        $seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
446 1
        $seriesPlots = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $seriesPlots is dead and can be removed.
Loading history...
447
448
        //    Loop through each data series in turn
449 1
        for ($i = 0; $i < $seriesCount; ++$i) {
450 1
            $dataValuesY = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues();
451 1
            $dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
452
453 1
            foreach ($dataValuesY as $k => $dataValueY) {
454 1
                $dataValuesY[$k] = $k;
455
            }
456
457 1
            $seriesPlot = new ScatterPlot($dataValuesX, $dataValuesY);
458 1
            if ($scatterStyle == 'lineMarker') {
459 1
                $seriesPlot->SetLinkPoints();
460 1
                $seriesPlot->link->SetColor(self::$colourSet[self::$plotColour]);
461 1
            } elseif ($scatterStyle == 'smoothMarker') {
462 1
                $spline = new Spline($dataValuesY, $dataValuesX);
463 1
                [$splineDataY, $splineDataX] = $spline->Get(count($dataValuesX) * self::$width / 20);
464 1
                $lplot = new LinePlot($splineDataX, $splineDataY);
465 1
                $lplot->SetColor(self::$colourSet[self::$plotColour]);
466
467 1
                $this->graph->Add($lplot);
468
            }
469
470 1
            if ($bubble) {
471 1
                $this->formatPointMarker($seriesPlot, 'dot');
472 1
                $seriesPlot->mark->SetColor('black');
473 1
                $seriesPlot->mark->SetSize($bubbleSize);
474
            } else {
475 1
                $marker = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker();
476 1
                $this->formatPointMarker($seriesPlot, $marker);
477
            }
478 1
            $dataLabel = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue();
479 1
            $seriesPlot->SetLegend($dataLabel);
480
481 1
            $this->graph->Add($seriesPlot);
482
        }
483 1
    }
484
485 1
    private function renderPlotRadar($groupID): void
486
    {
487 1
        $radarStyle = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
488
489 1
        $seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
490 1
        $seriesPlots = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $seriesPlots is dead and can be removed.
Loading history...
491
492
        //    Loop through each data series in turn
493 1
        for ($i = 0; $i < $seriesCount; ++$i) {
494 1
            $dataValuesY = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues();
495 1
            $dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
496 1
            $marker = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getPointMarker();
497
498 1
            $dataValues = [];
499 1
            foreach ($dataValuesY as $k => $dataValueY) {
500 1
                $dataValues[$k] = implode(' ', array_reverse($dataValueY));
501
            }
502 1
            $tmp = array_shift($dataValues);
503 1
            $dataValues[] = $tmp;
504 1
            $tmp = array_shift($dataValuesX);
505 1
            $dataValuesX[] = $tmp;
506
507 1
            $this->graph->SetTitles(array_reverse($dataValues));
508
509 1
            $seriesPlot = new RadarPlot(array_reverse($dataValuesX));
510
511 1
            $dataLabel = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue();
512 1
            $seriesPlot->SetColor(self::$colourSet[self::$plotColour++]);
513 1
            if ($radarStyle == 'filled') {
514 1
                $seriesPlot->SetFillColor(self::$colourSet[self::$plotColour]);
515
            }
516 1
            $this->formatPointMarker($seriesPlot, $marker);
517 1
            $seriesPlot->SetLegend($dataLabel);
518
519 1
            $this->graph->Add($seriesPlot);
520
        }
521 1
    }
522
523 1
    private function renderPlotContour($groupID): void
524
    {
525 1
        $contourStyle = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
0 ignored issues
show
Unused Code introduced by
The assignment to $contourStyle is dead and can be removed.
Loading history...
526
527 1
        $seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
528 1
        $seriesPlots = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $seriesPlots is dead and can be removed.
Loading history...
529
530 1
        $dataValues = [];
531
        //    Loop through each data series in turn
532 1
        for ($i = 0; $i < $seriesCount; ++$i) {
533 1
            $dataValuesY = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex($i)->getDataValues();
0 ignored issues
show
Unused Code introduced by
The assignment to $dataValuesY is dead and can be removed.
Loading history...
534 1
            $dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($i)->getDataValues();
535
536 1
            $dataValues[$i] = $dataValuesX;
537
        }
538 1
        $seriesPlot = new ContourPlot($dataValues);
539
540 1
        $this->graph->Add($seriesPlot);
541 1
    }
542
543 1
    private function renderPlotStock($groupID): void
544
    {
545 1
        $seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
546 1
        $plotOrder = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotOrder();
547
548 1
        $dataValues = [];
549
        //    Loop through each data series in turn and build the plot arrays
550 1
        foreach ($plotOrder as $i => $v) {
551 1
            $dataValuesX = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($v)->getDataValues();
552 1
            foreach ($dataValuesX as $j => $dataValueX) {
553 1
                $dataValues[$plotOrder[$i]][$j] = $dataValueX;
554
            }
555
        }
556 1
        if (empty($dataValues)) {
557
            return;
558
        }
559
560 1
        $dataValuesPlot = [];
561
        // Flatten the plot arrays to a single dimensional array to work with jpgraph
562 1
        $jMax = count($dataValues[0]);
563 1
        for ($j = 0; $j < $jMax; ++$j) {
564 1
            for ($i = 0; $i < $seriesCount; ++$i) {
565 1
                $dataValuesPlot[] = $dataValues[$i][$j];
566
            }
567
        }
568
569
        // Set the x-axis labels
570 1
        $labelCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount();
571 1
        if ($labelCount > 0) {
572 1
            $datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
573 1
            $datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount);
574 1
            $this->graph->xaxis->SetTickLabels($datasetLabels);
575
        }
576
577 1
        $seriesPlot = new StockPlot($dataValuesPlot);
578 1
        $seriesPlot->SetWidth(20);
579
580 1
        $this->graph->Add($seriesPlot);
581 1
    }
582
583 1
    private function renderAreaChart($groupCount, $dimensions = '2d'): void
584
    {
585 1
        $this->renderCartesianPlotArea();
586
587 1
        for ($i = 0; $i < $groupCount; ++$i) {
588 1
            $this->renderPlotLine($i, true, false, $dimensions);
589
        }
590 1
    }
591
592 1
    private function renderLineChart($groupCount, $dimensions = '2d'): void
593
    {
594 1
        $this->renderCartesianPlotArea();
595
596 1
        for ($i = 0; $i < $groupCount; ++$i) {
597 1
            $this->renderPlotLine($i, false, false, $dimensions);
598
        }
599 1
    }
600
601 1
    private function renderBarChart($groupCount, $dimensions = '2d'): void
602
    {
603 1
        $this->renderCartesianPlotArea();
604
605 1
        for ($i = 0; $i < $groupCount; ++$i) {
606 1
            $this->renderPlotBar($i, $dimensions);
607
        }
608 1
    }
609
610 1
    private function renderScatterChart($groupCount): void
611
    {
612 1
        $this->renderCartesianPlotArea('linlin');
613
614 1
        for ($i = 0; $i < $groupCount; ++$i) {
615 1
            $this->renderPlotScatter($i, false);
616
        }
617 1
    }
618
619 1
    private function renderBubbleChart($groupCount): void
620
    {
621 1
        $this->renderCartesianPlotArea('linlin');
622
623 1
        for ($i = 0; $i < $groupCount; ++$i) {
624 1
            $this->renderPlotScatter($i, true);
625
        }
626 1
    }
627
628 1
    private function renderPieChart($groupCount, $dimensions = '2d', $doughnut = false, $multiplePlots = false): void
629
    {
630 1
        $this->renderPiePlotArea();
631
632 1
        $iLimit = ($multiplePlots) ? $groupCount : 1;
633 1
        for ($groupID = 0; $groupID < $iLimit; ++$groupID) {
634 1
            $grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping();
0 ignored issues
show
Unused Code introduced by
The assignment to $grouping is dead and can be removed.
Loading history...
635 1
            $exploded = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
636 1
            $datasetLabels = [];
637 1
            if ($groupID == 0) {
638 1
                $labelCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount();
639 1
                if ($labelCount > 0) {
640 1
                    $datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
641 1
                    $datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount);
642
                }
643
            }
644
645 1
            $seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
646 1
            $seriesPlots = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $seriesPlots is dead and can be removed.
Loading history...
647
            //    For pie charts, we only display the first series: doughnut charts generally display all series
648 1
            $jLimit = ($multiplePlots) ? $seriesCount : 1;
649
            //    Loop through each data series in turn
650 1
            for ($j = 0; $j < $jLimit; ++$j) {
651 1
                $dataValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($j)->getDataValues();
652
653
                //    Fill in any missing values in the $dataValues array
654 1
                $testCurrentIndex = 0;
655 1
                foreach ($dataValues as $k => $dataValue) {
656 1
                    while ($k != $testCurrentIndex) {
657
                        $dataValues[$testCurrentIndex] = null;
658
                        ++$testCurrentIndex;
659
                    }
660 1
                    ++$testCurrentIndex;
661
                }
662
663 1
                if ($dimensions == '3d') {
664 1
                    $seriesPlot = new PiePlot3D($dataValues);
665
                } else {
666 1
                    if ($doughnut) {
667 1
                        $seriesPlot = new PiePlotC($dataValues);
668
                    } else {
669 1
                        $seriesPlot = new PiePlot($dataValues);
670
                    }
671
                }
672
673 1
                if ($multiplePlots) {
674 1
                    $seriesPlot->SetSize(($jLimit - $j) / ($jLimit * 4));
675
                }
676
677 1
                if ($doughnut) {
678 1
                    $seriesPlot->SetMidColor('white');
0 ignored issues
show
Bug introduced by
The method SetMidColor() does not exist on PiePlot. Did you maybe mean SetColor()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

678
                    $seriesPlot->/** @scrutinizer ignore-call */ 
679
                                 SetMidColor('white');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method SetMidColor() does not exist on PiePlot3D. Did you maybe mean SetColor()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

678
                    $seriesPlot->/** @scrutinizer ignore-call */ 
679
                                 SetMidColor('white');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
679
                }
680
681 1
                $seriesPlot->SetColor(self::$colourSet[self::$plotColour++]);
682 1
                if (count($datasetLabels) > 0) {
683 1
                    $seriesPlot->SetLabels(array_fill(0, count($datasetLabels), ''));
684
                }
685 1
                if ($dimensions != '3d') {
686 1
                    $seriesPlot->SetGuideLines(false);
687
                }
688 1
                if ($j == 0) {
689 1
                    if ($exploded) {
690 1
                        $seriesPlot->ExplodeAll();
691
                    }
692 1
                    $seriesPlot->SetLegends($datasetLabels);
693
                }
694
695 1
                $this->graph->Add($seriesPlot);
696
            }
697
        }
698 1
    }
699
700 1
    private function renderRadarChart($groupCount): void
701
    {
702 1
        $this->renderRadarPlotArea();
703
704 1
        for ($groupID = 0; $groupID < $groupCount; ++$groupID) {
705 1
            $this->renderPlotRadar($groupID);
706
        }
707 1
    }
708
709 1
    private function renderStockChart($groupCount): void
710
    {
711 1
        $this->renderCartesianPlotArea('intint');
712
713 1
        for ($groupID = 0; $groupID < $groupCount; ++$groupID) {
714 1
            $this->renderPlotStock($groupID);
715
        }
716 1
    }
717
718 1
    private function renderContourChart($groupCount, $dimensions): void
0 ignored issues
show
Unused Code introduced by
The parameter $dimensions is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

718
    private function renderContourChart($groupCount, /** @scrutinizer ignore-unused */ $dimensions): void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
719
    {
720 1
        $this->renderCartesianPlotArea('intint');
721
722 1
        for ($i = 0; $i < $groupCount; ++$i) {
723 1
            $this->renderPlotContour($i);
724
        }
725 1
    }
726
727 1
    private function renderCombinationChart($groupCount, $dimensions, $outputDestination)
0 ignored issues
show
Unused Code introduced by
The parameter $dimensions is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

727
    private function renderCombinationChart($groupCount, /** @scrutinizer ignore-unused */ $dimensions, $outputDestination)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
728
    {
729 1
        $this->renderCartesianPlotArea();
730
731 1
        for ($i = 0; $i < $groupCount; ++$i) {
732 1
            $dimensions = null;
733 1
            $chartType = $this->chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotType();
734
            switch ($chartType) {
735 1
                case 'area3DChart':
736
                    $dimensions = '3d';
737
                // no break
738 1
                case 'areaChart':
739
                    $this->renderPlotLine($i, true, true, $dimensions);
740
741
                    break;
742 1
                case 'bar3DChart':
743
                    $dimensions = '3d';
744
                // no break
745 1
                case 'barChart':
746 1
                    $this->renderPlotBar($i, $dimensions);
747
748 1
                    break;
749 1
                case 'line3DChart':
750
                    $dimensions = '3d';
751
                // no break
752 1
                case 'lineChart':
753
                    $this->renderPlotLine($i, false, true, $dimensions);
754
755
                    break;
756 1
                case 'scatterChart':
757
                    $this->renderPlotScatter($i, false);
758
759
                    break;
760 1
                case 'bubbleChart':
761
                    $this->renderPlotScatter($i, true);
762
763
                    break;
764
                default:
765 1
                    $this->graph = null;
766
767 1
                    return false;
768
            }
769
        }
770
771
        $this->renderLegend();
772
773
        $this->graph->Stroke($outputDestination);
774
775
        return true;
776
    }
777
778 1
    public function render($outputDestination)
779
    {
780 1
        self::$plotColour = 0;
781
782 1
        $groupCount = $this->chart->getPlotArea()->getPlotGroupCount();
783
784 1
        $dimensions = null;
785 1
        if ($groupCount == 1) {
0 ignored issues
show
introduced by
The condition $groupCount == 1 is always false.
Loading history...
786 1
            $chartType = $this->chart->getPlotArea()->getPlotGroupByIndex(0)->getPlotType();
787
        } else {
788 1
            $chartTypes = [];
789 1
            for ($i = 0; $i < $groupCount; ++$i) {
790 1
                $chartTypes[] = $this->chart->getPlotArea()->getPlotGroupByIndex($i)->getPlotType();
791
            }
792 1
            $chartTypes = array_unique($chartTypes);
793 1
            if (count($chartTypes) == 1) {
794
                $chartType = array_pop($chartTypes);
795 1
            } elseif (count($chartTypes) == 0) {
796
                echo 'Chart is not yet implemented<br />';
797
798
                return false;
799
            } else {
800 1
                return $this->renderCombinationChart($groupCount, $dimensions, $outputDestination);
801
            }
802
        }
803
804
        switch ($chartType) {
805 1
            case 'area3DChart':
806 1
                $dimensions = '3d';
807
            // no break
808 1
            case 'areaChart':
809 1
                $this->renderAreaChart($groupCount, $dimensions);
810
811 1
                break;
812 1
            case 'bar3DChart':
813 1
                $dimensions = '3d';
814
            // no break
815 1
            case 'barChart':
816 1
                $this->renderBarChart($groupCount, $dimensions);
817
818 1
                break;
819 1
            case 'line3DChart':
820 1
                $dimensions = '3d';
821
            // no break
822 1
            case 'lineChart':
823 1
                $this->renderLineChart($groupCount, $dimensions);
824
825 1
                break;
826 1
            case 'pie3DChart':
827 1
                $dimensions = '3d';
828
            // no break
829 1
            case 'pieChart':
830 1
                $this->renderPieChart($groupCount, $dimensions, false, false);
831
832 1
                break;
833 1
            case 'doughnut3DChart':
834
                $dimensions = '3d';
835
            // no break
836 1
            case 'doughnutChart':
837 1
                $this->renderPieChart($groupCount, $dimensions, true, true);
838
839 1
                break;
840 1
            case 'scatterChart':
841 1
                $this->renderScatterChart($groupCount);
842
843 1
                break;
844 1
            case 'bubbleChart':
845 1
                $this->renderBubbleChart($groupCount);
846
847 1
                break;
848 1
            case 'radarChart':
849 1
                $this->renderRadarChart($groupCount);
850
851 1
                break;
852 1
            case 'surface3DChart':
853 1
                $dimensions = '3d';
854
            // no break
855 1
            case 'surfaceChart':
856 1
                $this->renderContourChart($groupCount, $dimensions);
857
858 1
                break;
859 1
            case 'stockChart':
860 1
                $this->renderStockChart($groupCount);
861
862 1
                break;
863
            default:
864
                echo $chartType . ' is not yet implemented<br />';
865
866
                return false;
867
        }
868 1
        $this->renderLegend();
869
870 1
        $this->graph->Stroke($outputDestination);
871
872 1
        return true;
873
    }
874
}
875