Failed Conditions
Push — develop ( a6bb49...7a4cbd )
by Adrien
36:15
created

JpGraph::renderTitle()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 5
ccs 4
cts 4
cp 1
crap 2
rs 10
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 10 and the first side effect is on line 8.

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.

Loading history...
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
        //    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;
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...
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')
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

274
    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...
275
    {
276 1
        $grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping();
277
278 1
        $labelCount = count($this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount());
0 ignored issues
show
Bug introduced by
$this->chart->getPlotAre...dex(0)->getPointCount() of type integer is incompatible with the type Countable|array expected by parameter $var of count(). ( Ignorable by Annotation )

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

278
        $labelCount = count(/** @scrutinizer ignore-type */ $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount());
Loading history...
279 1
        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);
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...
298
            }
299
300
            //    Fill in any missing values in the $dataValues array
301 1
            $testCurrentIndex = 0;
302 1
            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());
0 ignored issues
show
Bug introduced by
$this->chart->getPlotAre...dex(0)->getPointCount() of type integer is incompatible with the type Countable|array expected by parameter $var of count(). ( Ignorable by Annotation )

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

346
        $labelCount = count(/** @scrutinizer ignore-type */ $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount());
Loading history...
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);
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...
371
            }
372
373
            //    Fill in any missing values in the $dataValues array
374 1
            $testCurrentIndex = 0;
375 1
            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();
0 ignored issues
show
Unused Code introduced by
The assignment to $grouping is dead and can be removed.
Loading history...
424 1
        $scatterStyle = $bubbleSize = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
425
426 1
        $seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
427 1
        $seriesPlots = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $seriesPlots is dead and can be removed.
Loading history...
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 = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $seriesPlots is dead and can be removed.
Loading history...
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();
0 ignored issues
show
Unused Code introduced by
The assignment to $contourStyle is dead and can be removed.
Loading history...
507
508 1
        $seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
509 1
        $seriesPlots = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $seriesPlots is dead and can be removed.
Loading history...
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();
0 ignored issues
show
Unused Code introduced by
The assignment to $dataValuesY is dead and can be removed.
Loading history...
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
        $jMax = count($dataValues[0]);
544 1
        for ($j = 0; $j < $jMax; ++$j) {
545 1
            for ($i = 0; $i < $seriesCount; ++$i) {
546 1
                $dataValuesPlot[] = $dataValues[$i][$j];
547
            }
548
        }
549
550
        // Set the x-axis labels
551 1
        $labelCount = count($this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount());
0 ignored issues
show
Bug introduced by
$this->chart->getPlotAre...dex(0)->getPointCount() of type integer is incompatible with the type Countable|array expected by parameter $var of count(). ( Ignorable by Annotation )

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

551
        $labelCount = count(/** @scrutinizer ignore-type */ $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount());
Loading history...
552 1
        if ($labelCount > 0) {
553 1
            $datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
554 1
            $datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount);
555 1
            $this->graph->xaxis->SetTickLabels($datasetLabels);
556
        }
557
558 1
        $seriesPlot = new \StockPlot($dataValuesPlot);
559 1
        $seriesPlot->SetWidth(20);
560
561 1
        $this->graph->Add($seriesPlot);
562 1
    }
563
564 1
    private function renderAreaChart($groupCount, $dimensions = '2d')
565
    {
566 1
        $this->renderCartesianPlotArea();
567
568 1
        for ($i = 0; $i < $groupCount; ++$i) {
569 1
            $this->renderPlotLine($i, true, false, $dimensions);
570
        }
571 1
    }
572
573 1
    private function renderLineChart($groupCount, $dimensions = '2d')
574
    {
575 1
        $this->renderCartesianPlotArea();
576
577 1
        for ($i = 0; $i < $groupCount; ++$i) {
578 1
            $this->renderPlotLine($i, false, false, $dimensions);
579
        }
580 1
    }
581
582 1
    private function renderBarChart($groupCount, $dimensions = '2d')
583
    {
584 1
        $this->renderCartesianPlotArea();
585
586 1
        for ($i = 0; $i < $groupCount; ++$i) {
587 1
            $this->renderPlotBar($i, $dimensions);
588
        }
589 1
    }
590
591 1
    private function renderScatterChart($groupCount)
592
    {
593 1
        $this->renderCartesianPlotArea('linlin');
594
595 1
        for ($i = 0; $i < $groupCount; ++$i) {
596 1
            $this->renderPlotScatter($i, false);
597
        }
598 1
    }
599
600 1
    private function renderBubbleChart($groupCount)
601
    {
602 1
        $this->renderCartesianPlotArea('linlin');
603
604 1
        for ($i = 0; $i < $groupCount; ++$i) {
605 1
            $this->renderPlotScatter($i, true);
606
        }
607 1
    }
608
609 1
    private function renderPieChart($groupCount, $dimensions = '2d', $doughnut = false, $multiplePlots = false)
610
    {
611 1
        $this->renderPiePlotArea();
612
613 1
        $iLimit = ($multiplePlots) ? $groupCount : 1;
614 1
        for ($groupID = 0; $groupID < $iLimit; ++$groupID) {
615 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...
616 1
            $exploded = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
617 1
            if ($groupID == 0) {
618 1
                $labelCount = count($this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount());
0 ignored issues
show
Bug introduced by
$this->chart->getPlotAre...dex(0)->getPointCount() of type integer is incompatible with the type Countable|array expected by parameter $var of count(). ( Ignorable by Annotation )

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

618
                $labelCount = count(/** @scrutinizer ignore-type */ $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount());
Loading history...
619 1
                if ($labelCount > 0) {
620 1
                    $datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
621 1
                    $datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount);
622
                }
623
            }
624
625 1
            $seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
626 1
            $seriesPlots = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $seriesPlots is dead and can be removed.
Loading history...
627
            //    For pie charts, we only display the first series: doughnut charts generally display all series
628 1
            $jLimit = ($multiplePlots) ? $seriesCount : 1;
629
            //    Loop through each data series in turn
630 1
            for ($j = 0; $j < $jLimit; ++$j) {
631 1
                $dataValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($j)->getDataValues();
632
633
                //    Fill in any missing values in the $dataValues array
634 1
                $testCurrentIndex = 0;
635 1
                foreach ($dataValues as $k => $dataValue) {
636 1
                    while ($k != $testCurrentIndex) {
637
                        $dataValues[$testCurrentIndex] = null;
638
                        ++$testCurrentIndex;
639
                    }
640 1
                    ++$testCurrentIndex;
641
                }
642
643 1
                if ($dimensions == '3d') {
644 1
                    $seriesPlot = new \PiePlot3D($dataValues);
645
                } else {
646 1
                    if ($doughnut) {
647 1
                        $seriesPlot = new \PiePlotC($dataValues);
648
                    } else {
649 1
                        $seriesPlot = new \PiePlot($dataValues);
650
                    }
651
                }
652
653 1
                if ($multiplePlots) {
654 1
                    $seriesPlot->SetSize(($jLimit - $j) / ($jLimit * 4));
655
                }
656
657 1
                if ($doughnut) {
658 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

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

658
                    $seriesPlot->/** @scrutinizer ignore-call */ 
659
                                 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...
659
                }
660
661 1
                $seriesPlot->SetColor(self::$colourSet[self::$plotColour++]);
662 1
                if (count($datasetLabels) > 0) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $datasetLabels does not seem to be defined for all execution paths leading up to this point.
Loading history...
663 1
                    $seriesPlot->SetLabels(array_fill(0, count($datasetLabels), ''));
664
                }
665 1
                if ($dimensions != '3d') {
666 1
                    $seriesPlot->SetGuideLines(false);
667
                }
668 1
                if ($j == 0) {
669 1
                    if ($exploded) {
670 1
                        $seriesPlot->ExplodeAll();
671
                    }
672 1
                    $seriesPlot->SetLegends($datasetLabels);
673
                }
674
675 1
                $this->graph->Add($seriesPlot);
676
            }
677
        }
678 1
    }
679
680 1
    private function renderRadarChart($groupCount)
681
    {
682 1
        $this->renderRadarPlotArea();
683
684 1
        for ($groupID = 0; $groupID < $groupCount; ++$groupID) {
685 1
            $this->renderPlotRadar($groupID);
686
        }
687 1
    }
688
689 1
    private function renderStockChart($groupCount)
690
    {
691 1
        $this->renderCartesianPlotArea('intint');
692
693 1
        for ($groupID = 0; $groupID < $groupCount; ++$groupID) {
694 1
            $this->renderPlotStock($groupID);
695
        }
696 1
    }
697
698 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

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

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