Passed
Push — develop ( 6088f5...4e8e0d )
by Adrien
35:10 queued 29:41
created

JpGraph::renderCombinationChart()   B

Complexity

Conditions 10
Paths 39

Size

Total Lines 49
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 18.374

Importance

Changes 0
Metric Value
cc 10
eloc 32
nc 39
nop 3
dl 0
loc 49
ccs 18
cts 32
cp 0.5625
crap 18.374
rs 7.6666
c 0
b 0
f 0

How to fix   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 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
        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 = '')
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

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

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

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

660
                    $seriesPlot->/** @scrutinizer ignore-call */ 
661
                                 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 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

660
                    $seriesPlot->/** @scrutinizer ignore-call */ 
661
                                 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...
661
                }
662
663 1
                $seriesPlot->SetColor(self::$colourSet[self::$plotColour++]);
664 1
                if (count($datasetLabels) > 0) {
665 1
                    $seriesPlot->SetLabels(array_fill(0, count($datasetLabels), ''));
666
                }
667 1
                if ($dimensions != '3d') {
668 1
                    $seriesPlot->SetGuideLines(false);
669
                }
670 1
                if ($j == 0) {
671 1
                    if ($exploded) {
672 1
                        $seriesPlot->ExplodeAll();
673
                    }
674 1
                    $seriesPlot->SetLegends($datasetLabels);
675
                }
676
677 1
                $this->graph->Add($seriesPlot);
678
            }
679
        }
680 1
    }
681
682 1
    private function renderRadarChart($groupCount)
683
    {
684 1
        $this->renderRadarPlotArea();
685
686 1
        for ($groupID = 0; $groupID < $groupCount; ++$groupID) {
687 1
            $this->renderPlotRadar($groupID);
688
        }
689 1
    }
690
691 1
    private function renderStockChart($groupCount)
692
    {
693 1
        $this->renderCartesianPlotArea('intint');
694
695 1
        for ($groupID = 0; $groupID < $groupCount; ++$groupID) {
696 1
            $this->renderPlotStock($groupID);
697
        }
698 1
    }
699
700 1
    private function renderContourChart($groupCount, $dimensions)
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

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

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...
701
    {
702 1
        $this->renderCartesianPlotArea('intint');
703
704 1
        for ($i = 0; $i < $groupCount; ++$i) {
705 1
            $this->renderPlotContour($i);
706
        }
707 1
    }
708
709 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

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