Completed
Push — develop ( 782b4e...557e80 )
by Adrien
43:38
created

JpGraph::renderLegend()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 32
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 11.1115

Importance

Changes 0
Metric Value
cc 6
eloc 25
nc 6
nop 0
dl 0
loc 32
ccs 11
cts 23
cp 0.4783
crap 11.1115
rs 8.439
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 1
        self::$markSet = [
65 1
            'diamond' => MARK_DIAMOND,
66 1
            'square' => MARK_SQUARE,
67 1
            'triangle' => MARK_UTRIANGLE,
68 1
            'x' => MARK_X,
69 1
            'star' => MARK_STAR,
70 1
            'dot' => MARK_FILLEDCIRCLE,
71 1
            'dash' => MARK_DTRIANGLE,
72 1
            'circle' => MARK_CIRCLE,
73 1
            'plus' => MARK_CROSS,
74
        ];
75
76 1
        $loaded = true;
77 1
    }
78
79 1
    private function formatPointMarker($seriesPlot, $markerID)
80
    {
81 1
        $plotMarkKeys = array_keys(self::$markSet);
82 1
        if ($markerID === null) {
83
            //    Use default plot marker (next marker in the series)
84 1
            self::$plotMark %= count(self::$markSet);
85 1
            $seriesPlot->mark->SetType(self::$markSet[$plotMarkKeys[self::$plotMark++]]);
86 1
        } elseif ($markerID !== 'none') {
87
            //    Use specified plot marker (if it exists)
88 1
            if (isset(self::$markSet[$markerID])) {
89 1
                $seriesPlot->mark->SetType(self::$markSet[$markerID]);
90
            } else {
91
                //    If the specified plot marker doesn't exist, use default plot marker (next marker in the series)
92
                self::$plotMark %= count(self::$markSet);
93 1
                $seriesPlot->mark->SetType(self::$markSet[$plotMarkKeys[self::$plotMark++]]);
94
            }
95
        } else {
96
            //    Hide plot marker
97 1
            $seriesPlot->mark->Hide();
98
        }
99 1
        $seriesPlot->mark->SetColor(self::$colourSet[self::$plotColour]);
100 1
        $seriesPlot->mark->SetFillColor(self::$colourSet[self::$plotColour]);
101 1
        $seriesPlot->SetColor(self::$colourSet[self::$plotColour++]);
102
103 1
        return $seriesPlot;
104
    }
105
106 1
    private function formatDataSetLabels($groupID, $datasetLabels, $labelCount, $rotation = '')
0 ignored issues
show
Unused Code introduced by
The parameter $labelCount is not used and could be removed.

This check looks from 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) {
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;
0 ignored issues
show
Bug introduced by
The variable $sumValues does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

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

This check looks from 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());
279 1 View Code Duplication
        if ($labelCount > 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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
Bug introduced by
The variable $sumValues does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
298
            }
299
300
            //    Fill in any missing values in the $dataValues array
301 1
            $testCurrentIndex = 0;
302 1 View Code Duplication
            foreach ($dataValues as $k => $dataValue) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
303 1
                while ($k != $testCurrentIndex) {
304
                    $dataValues[$testCurrentIndex] = null;
305
                    ++$testCurrentIndex;
306
                }
307 1
                ++$testCurrentIndex;
308
            }
309
310 1
            $seriesPlot = new \LinePlot($dataValues);
311 1
            if ($combination) {
312
                $seriesPlot->SetBarCenter();
313
            }
314
315 1
            if ($filled) {
316 1
                $seriesPlot->SetFilled(true);
317 1
                $seriesPlot->SetColor('black');
318 1
                $seriesPlot->SetFillColor(self::$colourSet[self::$plotColour++]);
319
            } else {
320
                //    Set the appropriate plot marker
321 1
                $this->formatPointMarker($seriesPlot, $marker);
322
            }
323 1
            $dataLabel = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotLabelByIndex($i)->getDataValue();
324 1
            $seriesPlot->SetLegend($dataLabel);
325
326 1
            $seriesPlots[] = $seriesPlot;
327
        }
328
329 1
        if ($grouping == 'standard') {
330 1
            $groupPlot = $seriesPlots;
331
        } else {
332 1
            $groupPlot = new \AccLinePlot($seriesPlots);
333
        }
334 1
        $this->graph->Add($groupPlot);
335 1
    }
336
337 1
    private function renderPlotBar($groupID, $dimensions = '2d')
338
    {
339 1
        $rotation = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotDirection();
340
        //    Rotate for bar rather than column chart
341 1
        if (($groupID == 0) && ($rotation == 'bar')) {
342 1
            $this->graph->Set90AndMargin();
343
        }
344 1
        $grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping();
345
346 1
        $labelCount = count($this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount());
347 1
        if ($labelCount > 0) {
348 1
            $datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
349 1
            $datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount, $rotation);
350
            //    Rotate for bar rather than column chart
351 1
            if ($rotation == 'bar') {
352 1
                $datasetLabels = array_reverse($datasetLabels);
353 1
                $this->graph->yaxis->SetPos('max');
354 1
                $this->graph->yaxis->SetLabelAlign('center', 'top');
355 1
                $this->graph->yaxis->SetLabelSide(SIDE_RIGHT);
356
            }
357 1
            $this->graph->xaxis->SetTickLabels($datasetLabels);
358
        }
359
360 1
        $seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
361 1
        $seriesPlots = [];
362 1
        if ($grouping == 'percentStacked') {
363 1
            $sumValues = $this->percentageSumCalculation($groupID, $seriesCount);
364
        }
365
366
        //    Loop through each data series in turn
367 1
        for ($j = 0; $j < $seriesCount; ++$j) {
368 1
            $dataValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($j)->getDataValues();
369 1
            if ($grouping == 'percentStacked') {
370 1
                $dataValues = $this->percentageAdjustValues($dataValues, $sumValues);
0 ignored issues
show
Bug introduced by
The variable $sumValues does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
371
            }
372
373
            //    Fill in any missing values in the $dataValues array
374 1
            $testCurrentIndex = 0;
375 1 View Code Duplication
            foreach ($dataValues as $k => $dataValue) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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
$grouping is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

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
$seriesPlots is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

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);
0 ignored issues
show
Documentation introduced by
$dataValuesY is of type array, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
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);
0 ignored issues
show
Documentation introduced by
$splineDataY is of type array<integer|string,integer|double>, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
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
$seriesPlots is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

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));
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Graph as the method SetTitles() does only exist in the following sub-classes of Graph: RadarGraph. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
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
$contourStyle is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
507
508 1
        $seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
509 1
        $seriesPlots = [];
0 ignored issues
show
Unused Code introduced by
$seriesPlots is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

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
$dataValuesY is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

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
        for ($j = 0; $j < count($dataValues[0]); ++$j) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
544 1
            for ($i = 0; $i < $seriesCount; ++$i) {
545 1
                $dataValuesPlot[] = $dataValues[$i][$j];
546
            }
547
        }
548
549
        // Set the x-axis labels
550 1
        $labelCount = count($this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount());
551 1 View Code Duplication
        if ($labelCount > 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
552 1
            $datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
553 1
            $datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount);
554 1
            $this->graph->xaxis->SetTickLabels($datasetLabels);
555
        }
556
557 1
        $seriesPlot = new \StockPlot($dataValuesPlot);
558 1
        $seriesPlot->SetWidth(20);
559
560 1
        $this->graph->Add($seriesPlot);
561 1
    }
562
563 1 View Code Duplication
    private function renderAreaChart($groupCount, $dimensions = '2d')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
564
    {
565 1
        $this->renderCartesianPlotArea();
566
567 1
        for ($i = 0; $i < $groupCount; ++$i) {
568 1
            $this->renderPlotLine($i, true, false, $dimensions);
569
        }
570 1
    }
571
572 1 View Code Duplication
    private function renderLineChart($groupCount, $dimensions = '2d')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
573
    {
574 1
        $this->renderCartesianPlotArea();
575
576 1
        for ($i = 0; $i < $groupCount; ++$i) {
577 1
            $this->renderPlotLine($i, false, false, $dimensions);
578
        }
579 1
    }
580
581 1 View Code Duplication
    private function renderBarChart($groupCount, $dimensions = '2d')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
582
    {
583 1
        $this->renderCartesianPlotArea();
584
585 1
        for ($i = 0; $i < $groupCount; ++$i) {
586 1
            $this->renderPlotBar($i, $dimensions);
587
        }
588 1
    }
589
590 1 View Code Duplication
    private function renderScatterChart($groupCount)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
591
    {
592 1
        $this->renderCartesianPlotArea('linlin');
593
594 1
        for ($i = 0; $i < $groupCount; ++$i) {
595 1
            $this->renderPlotScatter($i, false);
596
        }
597 1
    }
598
599 1 View Code Duplication
    private function renderBubbleChart($groupCount)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
600
    {
601 1
        $this->renderCartesianPlotArea('linlin');
602
603 1
        for ($i = 0; $i < $groupCount; ++$i) {
604 1
            $this->renderPlotScatter($i, true);
605
        }
606 1
    }
607
608 1
    private function renderPieChart($groupCount, $dimensions = '2d', $doughnut = false, $multiplePlots = false)
609
    {
610 1
        $this->renderPiePlotArea();
611
612 1
        $iLimit = ($multiplePlots) ? $groupCount : 1;
613 1
        for ($groupID = 0; $groupID < $iLimit; ++$groupID) {
614 1
            $grouping = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotGrouping();
0 ignored issues
show
Unused Code introduced by
$grouping is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
615 1
            $exploded = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotStyle();
616 1
            if ($groupID == 0) {
617 1
                $labelCount = count($this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex(0)->getPointCount());
618 1 View Code Duplication
                if ($labelCount > 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
619 1
                    $datasetLabels = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotCategoryByIndex(0)->getDataValues();
620 1
                    $datasetLabels = $this->formatDataSetLabels($groupID, $datasetLabels, $labelCount);
621
                }
622
            }
623
624 1
            $seriesCount = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotSeriesCount();
625 1
            $seriesPlots = [];
0 ignored issues
show
Unused Code introduced by
$seriesPlots is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
626
            //    For pie charts, we only display the first series: doughnut charts generally display all series
627 1
            $jLimit = ($multiplePlots) ? $seriesCount : 1;
628
            //    Loop through each data series in turn
629 1
            for ($j = 0; $j < $jLimit; ++$j) {
630 1
                $dataValues = $this->chart->getPlotArea()->getPlotGroupByIndex($groupID)->getPlotValuesByIndex($j)->getDataValues();
631
632
                //    Fill in any missing values in the $dataValues array
633 1
                $testCurrentIndex = 0;
634 1 View Code Duplication
                foreach ($dataValues as $k => $dataValue) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
635 1
                    while ($k != $testCurrentIndex) {
636
                        $dataValues[$testCurrentIndex] = null;
637
                        ++$testCurrentIndex;
638
                    }
639 1
                    ++$testCurrentIndex;
640
                }
641
642 1
                if ($dimensions == '3d') {
643 1
                    $seriesPlot = new \PiePlot3D($dataValues);
644
                } else {
645 1
                    if ($doughnut) {
646 1
                        $seriesPlot = new \PiePlotC($dataValues);
647
                    } else {
648 1
                        $seriesPlot = new \PiePlot($dataValues);
649
                    }
650
                }
651
652 1
                if ($multiplePlots) {
653 1
                    $seriesPlot->SetSize(($jLimit - $j) / ($jLimit * 4));
654
                }
655
656 1
                if ($doughnut) {
657 1
                    $seriesPlot->SetMidColor('white');
658
                }
659
660 1
                $seriesPlot->SetColor(self::$colourSet[self::$plotColour++]);
661 1
                if (count($datasetLabels) > 0) {
662 1
                    $seriesPlot->SetLabels(array_fill(0, count($datasetLabels), ''));
0 ignored issues
show
Bug introduced by
The variable $datasetLabels does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
663
                }
664 1
                if ($dimensions != '3d') {
665 1
                    $seriesPlot->SetGuideLines(false);
666
                }
667 1
                if ($j == 0) {
668 1
                    if ($exploded) {
669 1
                        $seriesPlot->ExplodeAll();
670
                    }
671 1
                    $seriesPlot->SetLegends($datasetLabels);
672
                }
673
674 1
                $this->graph->Add($seriesPlot);
675
            }
676
        }
677 1
    }
678
679 1
    private function renderRadarChart($groupCount)
680
    {
681 1
        $this->renderRadarPlotArea();
682
683 1
        for ($groupID = 0; $groupID < $groupCount; ++$groupID) {
684 1
            $this->renderPlotRadar($groupID);
685
        }
686 1
    }
687
688 1
    private function renderStockChart($groupCount)
689
    {
690 1
        $this->renderCartesianPlotArea('intint');
691
692 1
        for ($groupID = 0; $groupID < $groupCount; ++$groupID) {
693 1
            $this->renderPlotStock($groupID);
694
        }
695 1
    }
696
697 1
    private function renderContourChart($groupCount, $dimensions)
0 ignored issues
show
Unused Code introduced by
The parameter $dimensions is not used and could be removed.

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

Loading history...
698
    {
699 1
        $this->renderCartesianPlotArea('intint');
700
701 1
        for ($i = 0; $i < $groupCount; ++$i) {
702 1
            $this->renderPlotContour($i);
703
        }
704 1
    }
705
706 1
    private function renderCombinationChart($groupCount, $dimensions, $outputDestination)
0 ignored issues
show
Unused Code introduced by
The parameter $dimensions is not used and could be removed.

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

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