Passed
Push — master ( 8f5e6a...061d3e )
by Felipe
03:26
created

PiePlot3D   D

Complexity

Total Complexity 182

Size/Duplication

Total Lines 967
Duplicated Lines 16.44 %

Coupling/Cohesion

Components 3
Dependencies 3

Importance

Changes 0
Metric Value
dl 159
loc 967
rs 4.4444
c 0
b 0
f 0
wmc 182
lcom 3
cbo 3

20 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 10 10 1
A SetLegends() 0 4 1
A SetSliceColors() 0 4 1
A Legend() 0 5 1
A SetCSIMTargets() 0 6 1
A SetEdge() 0 5 1
A SetAngle() 0 9 3
C Add3DSliceToCSIM() 20 58 11
A SetLabels() 0 5 1
A SetLabelMargin() 0 4 1
A ShowLabelHint() 0 4 1
A SetLabelHintColor() 0 4 1
A SetHeight() 0 4 1
B NormAngle() 0 23 6
D Pie3DSlice() 79 202 24
A SetStartAngle() 0 7 3
F Pie3D() 18 332 67
C StrokeFullSliceFrame() 4 58 16
F Stroke() 19 95 21
F StrokeLabels() 9 79 20

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like PiePlot3D often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use PiePlot3D, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace Amenadiel\JpGraph\Plot;
3
4
use Amenadiel\JpGraph\Text;
5
6
/*=======================================================================
7
// File:        JPGRAPH_PIE3D.PHP
8
// Description: 3D Pie plot extension for JpGraph
9
// Created:     2001-03-24
10
// Ver:         $Id: jpgraph_pie3d.php 1329 2009-06-20 19:23:30Z ljp $
11
//
12
// Copyright (c) Asial Corporation. All rights reserved.
13
//========================================================================
14
 */
15
16
//===================================================
17
// CLASS PiePlot3D
18
// Description: Plots a 3D pie with a specified projection
19
// angle between 20 and 70 degrees.
20
//===================================================
21
class PiePlot3D extends PiePlot
22
{
23
    private $labelhintcolor = "red";
24
    private $showlabelhint = true;
25
    private $angle          = 50;
26
    private $edgecolor      = "";
27
    private $edgeweight      = 1;
28
    private $iThickness     = false;
29
30
    //---------------
31
    // CONSTRUCTOR
32 View Code Duplication
    public function __construct($data)
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...
33
    {
34
        $this->radius = 0.5;
35
        $this->data   = $data;
36
        $this->title  = new Text\Text("");
37
        $this->title->SetFont(FF_FONT1, FS_BOLD);
38
        $this->value = new DisplayValue();
39
        $this->value->Show();
40
        $this->value->SetFormat('%.0f%%');
41
    }
42
43
    //---------------
44
    // PUBLIC METHODS
45
46
    // Set label arrays
47
    public function SetLegends($aLegend)
48
    {
49
        $this->legends = array_reverse(array_slice($aLegend, 0, count($this->data)));
50
    }
51
52
    public function SetSliceColors($aColors)
53
    {
54
        $this->setslicecolors = $aColors;
55
    }
56
57
    public function Legend($aGraph)
58
    {
59
        parent::Legend($aGraph);
60
        $aGraph->legend->txtcol = array_reverse($aGraph->legend->txtcol);
61
    }
62
63
    public function SetCSIMTargets($aTargets, $aAlts = '', $aWinTargets = '')
64
    {
65
        $this->csimtargets    = $aTargets;
66
        $this->csimwintargets = $aWinTargets;
67
        $this->csimalts       = $aAlts;
68
    }
69
70
    // Should the slices be separated by a line? If color is specified as "" no line
71
    // will be used to separate pie slices.
72
    public function SetEdge($aColor = 'black', $aWeight = 1)
73
    {
74
        $this->edgecolor  = $aColor;
75
        $this->edgeweight = $aWeight;
76
    }
77
78
    // Specify projection angle for 3D in degrees
79
    // Must be between 20 and 70 degrees
80
    public function SetAngle($a)
81
    {
82
        if ($a < 5 || $a > 90) {
83
            Util\JpGraphError::RaiseL(14002);
84
            //("PiePlot3D::SetAngle() 3D Pie projection angle must be between 5 and 85 degrees.");
85
        } else {
86
            $this->angle = $a;
87
        }
88
    }
89
90
    public function Add3DSliceToCSIM($i, $xc, $yc, $height, $width, $thick, $sa, $ea)
91
    {
92
        //Slice number, ellipse centre (x,y), height, width, start angle, end angle
93
94
        $sa *= M_PI / 180;
95
        $ea *= M_PI / 180;
96
97
        //add coordinates of the centre to the map
98
        $coords = "$xc, $yc";
99
100
        //add coordinates of the first point on the arc to the map
101
        $xp = floor($width * cos($sa) / 2 + $xc);
102
        $yp = floor($yc - $height * sin($sa) / 2);
103
        $coords .= ", $xp, $yp";
104
105
        //If on the front half, add the thickness offset
106 View Code Duplication
        if ($sa >= M_PI && $sa <= 2 * M_PI * 1.01) {
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...
107
            $yp = floor($yp + $thick);
108
            $coords .= ", $xp, $yp";
109
        }
110
111
        //add coordinates every 0.2 radians
112
        $a = $sa + 0.2;
113
        while ($a < $ea) {
114
            $xp = floor($width * cos($a) / 2 + $xc);
115
            if ($a >= M_PI && $a <= 2 * M_PI * 1.01) {
116
                $yp = floor($yc - ($height * sin($a) / 2) + $thick);
117
            } else {
118
                $yp = floor($yc - $height * sin($a) / 2);
119
            }
120
            $coords .= ", $xp, $yp";
121
            $a += 0.2;
122
        }
123
124
        //Add the last point on the arc
125
        $xp = floor($width * cos($ea) / 2 + $xc);
126
        $yp = floor($yc - $height * sin($ea) / 2);
127
128 View Code Duplication
        if ($ea >= M_PI && $ea <= 2 * M_PI * 1.01) {
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...
129
            $coords .= ", $xp, " . floor($yp + $thick);
130
        }
131
        $coords .= ", $xp, $yp";
132
        $alt = '';
0 ignored issues
show
Unused Code introduced by
$alt 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...
133
134 View Code Duplication
        if (!empty($this->csimtargets[$i])) {
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...
135
            $this->csimareas .= "<area shape=\"poly\" coords=\"$coords\" href=\"" . $this->csimtargets[$i] . "\"";
136
137
            if (!empty($this->csimwintargets[$i])) {
138
                $this->csimareas .= " target=\"" . $this->csimwintargets[$i] . "\" ";
139
            }
140
141
            if (!empty($this->csimalts[$i])) {
142
                $tmp = sprintf($this->csimalts[$i], $this->data[$i]);
143
                $this->csimareas .= "alt=\"$tmp\" title=\"$tmp\" ";
144
            }
145
            $this->csimareas .= " />\n";
146
        }
147
    }
148
149
    public function SetLabels($aLabels, $aLblPosAdj = "auto")
150
    {
151
        $this->labels       = $aLabels;
152
        $this->ilabelposadj = $aLblPosAdj;
0 ignored issues
show
Documentation Bug introduced by
The property $ilabelposadj was declared of type integer, but $aLblPosAdj is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
153
    }
154
155
    // Distance from the pie to the labels
156
    public function SetLabelMargin($m)
157
    {
158
        $this->value->SetMargin($m);
159
    }
160
161
    // Show a thin line from the pie to the label for a specific slice
162
    public function ShowLabelHint($f = true)
163
    {
164
        $this->showlabelhint = $f;
165
    }
166
167
    // Set color of hint line to label for each slice
168
    public function SetLabelHintColor($c)
169
    {
170
        $this->labelhintcolor = $c;
171
    }
172
173
    public function SetHeight($aHeight)
174
    {
175
        $this->iThickness = $aHeight;
176
    }
177
178
    // Normalize Angle between 0-360
179
    public function NormAngle($a)
180
    {
181
        // Normalize anle to 0 to 2M_PI
182
        //
183
        if ($a > 0) {
184
            while ($a > 360) {
185
                $a -= 360;
186
            }
187
        } else {
188
            while ($a < 0) {
189
                $a += 360;
190
            }
191
        }
192
        if ($a < 0) {
193
            $a = 360 + $a;
194
        }
195
196
        if ($a == 360) {
197
            $a = 0;
198
        }
199
200
        return $a;
201
    }
202
203
    // Draw one 3D pie slice at position ($xc,$yc) with height $z
204
    public function Pie3DSlice($img, $xc, $yc, $w, $h, $sa, $ea, $z, $fillcolor, $shadow = 0.65)
205
    {
206
207
        // Due to the way the 3D Pie algorithm works we are
208
        // guaranteed that any slice we get into this method
209
        // belongs to either the left or right side of the
210
        // pie ellipse. Hence, no slice will cross 90 or 270
211
        // point.
212
        if (($sa < 90 && $ea > 90) || (($sa > 90 && $sa < 270) && $ea > 270)) {
213
            Util\JpGraphError::RaiseL(14003); //('Internal assertion failed. Pie3D::Pie3DSlice');
214
            exit(1);
0 ignored issues
show
Coding Style Compatibility introduced by
The method Pie3DSlice() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
215
        }
216
217
        $p[] = array();
0 ignored issues
show
Coding Style Comprehensibility introduced by
$p was never initialized. Although not strictly required by PHP, it is generally a good practice to add $p = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
218
219
        // Setup pre-calculated values
220
        $rsa   = $sa / 180 * M_PI; // to Rad
221
        $rea   = $ea / 180 * M_PI; // to Rad
222
        $sinsa = sin($rsa);
223
        $cossa = cos($rsa);
224
        $sinea = sin($rea);
225
        $cosea = cos($rea);
226
227
        // p[] is the points for the overall slice and
228
        // pt[] is the points for the top pie
229
230
        // Angular step when approximating the arc with a polygon train.
231
        $step = 0.05;
232
233
        if ($sa >= 270) {
234
            if ($ea > 360 || ($ea > 0 && $ea <= 90)) {
235
                if ($ea > 0 && $ea <= 90) {
236
                    // Adjust angle to simplify conditions in loops
237
                    $rea += 2 * M_PI;
238
                }
239
240
                $p = array($xc, $yc, $xc, $yc + $z,
241
                    $xc + $w * $cossa, $z + $yc - $h * $sinsa);
242
                $pt = array($xc, $yc, $xc + $w * $cossa, $yc - $h * $sinsa);
243
244 View Code Duplication
                for ($a = $rsa; $a < 2 * M_PI; $a += $step) {
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...
245
                    $tca  = cos($a);
246
                    $tsa  = sin($a);
247
                    $p[]  = $xc + $w * $tca;
248
                    $p[]  = $z + $yc - $h * $tsa;
249
                    $pt[] = $xc + $w * $tca;
250
                    $pt[] = $yc - $h * $tsa;
251
                }
252
253
                $pt[] = $xc + $w;
254
                $pt[] = $yc;
255
256
                $p[] = $xc + $w;
257
                $p[] = $z + $yc;
258
                $p[] = $xc + $w;
259
                $p[] = $yc;
260
                $p[] = $xc;
261
                $p[] = $yc;
262
263 View Code Duplication
                for ($a = 2 * M_PI + $step; $a < $rea; $a += $step) {
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...
264
                    $pt[] = $xc + $w * cos($a);
265
                    $pt[] = $yc - $h * sin($a);
266
                }
267
268
                $pt[] = $xc + $w * $cosea;
269
                $pt[] = $yc - $h * $sinea;
270
                $pt[] = $xc;
271
                $pt[] = $yc;
272
            } else {
273
                $p = array($xc, $yc, $xc, $yc + $z,
274
                    $xc + $w * $cossa, $z + $yc - $h * $sinsa);
275
                $pt = array($xc, $yc, $xc + $w * $cossa, $yc - $h * $sinsa);
276
277
                $rea = $rea == 0.0 ? 2 * M_PI : $rea;
278 View Code Duplication
                for ($a = $rsa; $a < $rea; $a += $step) {
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...
279
                    $tca  = cos($a);
280
                    $tsa  = sin($a);
281
                    $p[]  = $xc + $w * $tca;
282
                    $p[]  = $z + $yc - $h * $tsa;
283
                    $pt[] = $xc + $w * $tca;
284
                    $pt[] = $yc - $h * $tsa;
285
                }
286
287
                $pt[] = $xc + $w * $cosea;
288
                $pt[] = $yc - $h * $sinea;
289
                $pt[] = $xc;
290
                $pt[] = $yc;
291
292
                $p[] = $xc + $w * $cosea;
293
                $p[] = $z + $yc - $h * $sinea;
294
                $p[] = $xc + $w * $cosea;
295
                $p[] = $yc - $h * $sinea;
296
                $p[] = $xc;
297
                $p[] = $yc;
298
            }
299
        } elseif ($sa >= 180) {
300
            $p  = array($xc, $yc, $xc, $yc + $z, $xc + $w * $cosea, $z + $yc - $h * $sinea);
301
            $pt = array($xc, $yc, $xc + $w * $cosea, $yc - $h * $sinea);
302
303 View Code Duplication
            for ($a = $rea; $a > $rsa; $a -= $step) {
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...
304
                $tca  = cos($a);
305
                $tsa  = sin($a);
306
                $p[]  = $xc + $w * $tca;
307
                $p[]  = $z + $yc - $h * $tsa;
308
                $pt[] = $xc + $w * $tca;
309
                $pt[] = $yc - $h * $tsa;
310
            }
311
312
            $pt[] = $xc + $w * $cossa;
313
            $pt[] = $yc - $h * $sinsa;
314
            $pt[] = $xc;
315
            $pt[] = $yc;
316
317
            $p[] = $xc + $w * $cossa;
318
            $p[] = $z + $yc - $h * $sinsa;
319
            $p[] = $xc + $w * $cossa;
320
            $p[] = $yc - $h * $sinsa;
321
            $p[] = $xc;
322
            $p[] = $yc;
323
        } elseif ($sa >= 90) {
324
            if ($ea > 180) {
325
                $p  = array($xc, $yc, $xc, $yc + $z, $xc + $w * $cosea, $z + $yc - $h * $sinea);
326
                $pt = array($xc, $yc, $xc + $w * $cosea, $yc - $h * $sinea);
327
328 View Code Duplication
                for ($a = $rea; $a > M_PI; $a -= $step) {
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...
329
                    $tca  = cos($a);
330
                    $tsa  = sin($a);
331
                    $p[]  = $xc + $w * $tca;
332
                    $p[]  = $z + $yc - $h * $tsa;
333
                    $pt[] = $xc + $w * $tca;
334
                    $pt[] = $yc - $h * $tsa;
335
                }
336
337
                $p[] = $xc - $w;
338
                $p[] = $z + $yc;
339
                $p[] = $xc - $w;
340
                $p[] = $yc;
341
                $p[] = $xc;
342
                $p[] = $yc;
343
344
                $pt[] = $xc - $w;
345
                $pt[] = $z + $yc;
346
                $pt[] = $xc - $w;
347
                $pt[] = $yc;
348
349 View Code Duplication
                for ($a = M_PI - $step; $a > $rsa; $a -= $step) {
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...
350
                    $pt[] = $xc + $w * cos($a);
351
                    $pt[] = $yc - $h * sin($a);
352
                }
353
354
                $pt[] = $xc + $w * $cossa;
355
                $pt[] = $yc - $h * $sinsa;
356
                $pt[] = $xc;
357
                $pt[] = $yc;
358 View Code Duplication
            } else {
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...
359
                // $sa >= 90 && $ea <= 180
360
                $p = array($xc, $yc, $xc, $yc + $z,
361
                    $xc + $w * $cosea, $z + $yc - $h * $sinea,
362
                    $xc + $w * $cosea, $yc - $h * $sinea,
363
                    $xc, $yc);
364
365
                $pt = array($xc, $yc, $xc + $w * $cosea, $yc - $h * $sinea);
366
367
                for ($a = $rea; $a > $rsa; $a -= $step) {
368
                    $pt[] = $xc + $w * cos($a);
369
                    $pt[] = $yc - $h * sin($a);
370
                }
371
372
                $pt[] = $xc + $w * $cossa;
373
                $pt[] = $yc - $h * $sinsa;
374
                $pt[] = $xc;
375
                $pt[] = $yc;
376
            }
377 View Code Duplication
        } else {
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...
378
            // sa > 0 && ea < 90
379
380
            $p = array($xc, $yc, $xc, $yc + $z,
381
                $xc + $w * $cossa, $z + $yc - $h * $sinsa,
382
                $xc + $w * $cossa, $yc - $h * $sinsa,
383
                $xc, $yc);
384
385
            $pt = array($xc, $yc, $xc + $w * $cossa, $yc - $h * $sinsa);
386
387
            for ($a = $rsa; $a < $rea; $a += $step) {
388
                $pt[] = $xc + $w * cos($a);
389
                $pt[] = $yc - $h * sin($a);
390
            }
391
392
            $pt[] = $xc + $w * $cosea;
393
            $pt[] = $yc - $h * $sinea;
394
            $pt[] = $xc;
395
            $pt[] = $yc;
396
        }
397
398
        $img->PushColor($fillcolor . ":" . $shadow);
399
        $img->FilledPolygon($p);
400
        $img->PopColor();
401
402
        $img->PushColor($fillcolor);
403
        $img->FilledPolygon($pt);
404
        $img->PopColor();
405
    }
406
407
    public function SetStartAngle($aStart)
408
    {
409
        if ($aStart < 0 || $aStart > 360) {
410
            Util\JpGraphError::RaiseL(14004); //('Slice start angle must be between 0 and 360 degrees.');
411
        }
412
        $this->startangle = $aStart;
413
    }
414
415
    // Draw a 3D Pie
416
    public function Pie3D($aaoption, $img, $data, $colors, $xc, $yc, $d, $angle, $z,
417
        $shadow = 0.65, $startangle = 0, $edgecolor = "", $edgeweight = 1)
418
    {
419
420
        //---------------------------------------------------------------------------
421
        // As usual the algorithm get more complicated than I originally
422
        // envisioned. I believe that this is as simple as it is possible
423
        // to do it with the features I want. It's a good exercise to start
424
        // thinking on how to do this to convince your self that all this
425
        // is really needed for the general case.
426
        //
427
        // The algorithm two draw 3D pies without "real 3D" is done in
428
        // two steps.
429
        // First imagine the pie cut in half through a thought line between
430
        // 12'a clock and 6'a clock. It now easy to imagine that we can plot
431
        // the individual slices for each half by starting with the topmost
432
        // pie slice and continue down to 6'a clock.
433
        //
434
        // In the algortithm this is done in three principal steps
435
        // Step 1. Do the knife cut to ensure by splitting slices that extends
436
        // over the cut line. This is done by splitting the original slices into
437
        // upto 3 subslices.
438
        // Step 2. Find the top slice for each half
439
        // Step 3. Draw the slices from top to bottom
440
        //
441
        // The thing that slightly complicates this scheme with all the
442
        // angle comparisons below is that we can have an arbitrary start
443
        // angle so we must take into account the different equivalence classes.
444
        // For the same reason we must walk through the angle array in a
445
        // modulo fashion.
446
        //
447
        // Limitations of algorithm:
448
        // * A small exploded slice which crosses the 270 degree point
449
        //   will get slightly nagged close to the center due to the fact that
450
        //   we print the slices in Z-order and that the slice left part
451
        //   get printed first and might get slightly nagged by a larger
452
        //   slice on the right side just before the right part of the small
453
        //   slice. Not a major problem though.
454
        //---------------------------------------------------------------------------
455
456
        // Determine the height of the ellippse which gives an
457
        // indication of the inclination angle
458
        $h   = ($angle / 90.0) * $d;
459
        $sum = 0;
460
        for ($i = 0; $i < count($data); ++$i) {
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...
461
            $sum += $data[$i];
462
        }
463
464
        // Special optimization
465
        if ($sum == 0) {
466
            return;
467
        }
468
469
        if ($this->labeltype == 2) {
470
            $this->adjusted_data = $this->AdjPercentage($data);
471
        }
472
473
        // Setup the start
474
        $accsum = 0;
0 ignored issues
show
Unused Code introduced by
$accsum 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...
475
        $a      = $startangle;
476
        $a      = $this->NormAngle($a);
477
478
        //
479
        // Step 1 . Split all slices that crosses 90 or 270
480
        //
481
        $idx        = 0;
482
        $adjexplode = array();
483
        $numcolors  = count($colors);
484
        for ($i = 0; $i < count($data); ++$i, ++$idx) {
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...
485
            $da = $data[$i] / $sum * 360;
486
487
            if (empty($this->explode_radius[$i])) {
488
                $this->explode_radius[$i] = 0;
489
            }
490
491
            $expscale = 1;
492
            if ($aaoption == 1) {
493
                $expscale = 2;
494
            }
495
496
            $la      = $a + $da / 2;
497
            $explode = array($xc + $this->explode_radius[$i] * cos($la * M_PI / 180) * $expscale,
498
                $yc - $this->explode_radius[$i] * sin($la * M_PI / 180) * ($h / $d) * $expscale);
499
            $adjexplode[$idx]   = $explode;
500
            $labeldata[$i]      = array($la, $explode[0], $explode[1]);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$labeldata was never initialized. Although not strictly required by PHP, it is generally a good practice to add $labeldata = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
501
            $originalangles[$i] = array($a, $a + $da);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$originalangles was never initialized. Although not strictly required by PHP, it is generally a good practice to add $originalangles = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
502
503
            $ne = $this->NormAngle($a + $da);
504
            if ($da <= 180) {
505
                // If the slice size is <= 90 it can at maximum cut across
506
                // one boundary (either 90 or 270) where it needs to be split
507
                $split = -1; // no split
508
                if (($da <= 90 && ($a <= 90 && $ne > 90)) ||
509
                    (($da <= 180 && $da > 90) && (($a < 90 || $a >= 270) && $ne > 90))) {
510
                    $split = 90;
511
                } elseif (($da <= 90 && ($a <= 270 && $ne > 270)) ||
512
                    (($da <= 180 && $da > 90) && ($a >= 90 && $a < 270 && ($a + $da) > 270))) {
513
                    $split = 270;
514
                }
515
                if ($split > 0) {
516
                    // split in two
517
                    $angles[$idx]     = array($a, $split);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$angles was never initialized. Although not strictly required by PHP, it is generally a good practice to add $angles = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
518
                    $adjcolors[$idx]  = $colors[$i % $numcolors];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$adjcolors was never initialized. Although not strictly required by PHP, it is generally a good practice to add $adjcolors = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
519
                    $adjexplode[$idx] = $explode;
520
                    $angles[++$idx]   = array($split, $ne);
0 ignored issues
show
Bug introduced by
The variable $angles 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...
521
                    $adjcolors[$idx]  = $colors[$i % $numcolors];
0 ignored issues
show
Bug introduced by
The variable $adjcolors 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...
522
                    $adjexplode[$idx] = $explode;
523 View Code Duplication
                } else {
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...
524
                    // no split
525
                    $angles[$idx]     = array($a, $ne);
526
                    $adjcolors[$idx]  = $colors[$i % $numcolors];
527
                    $adjexplode[$idx] = $explode;
528
                }
529
            } else {
530
                // da>180
531
                // Slice may, depending on position, cross one or two
532
                // bonudaries
533
534
                if ($a < 90) {
535
                    $split = 90;
536
                } elseif ($a <= 270) {
537
                    $split = 270;
538
                } else {
539
                    $split = 90;
540
                }
541
542
                $angles[$idx]     = array($a, $split);
543
                $adjcolors[$idx]  = $colors[$i % $numcolors];
544
                $adjexplode[$idx] = $explode;
545
                //if( $a+$da > 360-$split ) {
1 ignored issue
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
546
                // For slices larger than 270 degrees we might cross
547
                // another boundary as well. This means that we must
548
                // split the slice further. The comparison gets a little
549
                // bit complicated since we must take into accound that
550
                // a pie might have a startangle >0 and hence a slice might
551
                // wrap around the 0 angle.
552
                // Three cases:
553
                //  a) Slice starts before 90 and hence gets a split=90, but
554
                //     we must also check if we need to split at 270
555
                //  b) Slice starts after 90 but before 270 and slices
556
                //     crosses 90 (after a wrap around of 0)
557
                //  c) If start is > 270 (hence the firstr split is at 90)
558
                //     and the slice is so large that it goes all the way
559
                //     around 270.
560
                if (($a < 90 && ($a + $da > 270)) || ($a > 90 && $a <= 270 && ($a + $da > 360 + 90)) || ($a > 270 && $this->NormAngle($a + $da) > 270)) {
561
                    $angles[++$idx]   = array($split, 360 - $split);
562
                    $adjcolors[$idx]  = $colors[$i % $numcolors];
563
                    $adjexplode[$idx] = $explode;
564
                    $angles[++$idx]   = array(360 - $split, $ne);
565
                    $adjcolors[$idx]  = $colors[$i % $numcolors];
566
                    $adjexplode[$idx] = $explode;
567 View Code Duplication
                } else {
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...
568
                    // Just a simple split to the previous decided
569
                    // angle.
570
                    $angles[++$idx]   = array($split, $ne);
571
                    $adjcolors[$idx]  = $colors[$i % $numcolors];
572
                    $adjexplode[$idx] = $explode;
573
                }
574
            }
575
            $a += $da;
576
            $a = $this->NormAngle($a);
577
        }
578
579
        // Total number of slices
580
        $n = count($angles);
581
582
        for ($i = 0; $i < $n; ++$i) {
583
            list($dbgs, $dbge) = $angles[$i];
0 ignored issues
show
Unused Code introduced by
The assignment to $dbgs is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
Unused Code introduced by
The assignment to $dbge is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
584
        }
585
586
        //
587
        // Step 2. Find start index (first pie that starts in upper left quadrant)
588
        //
589
        $minval = $angles[0][0];
590
        $min    = 0;
591
        for ($i = 0; $i < $n; ++$i) {
592
            if ($angles[$i][0] < $minval) {
593
                $minval = $angles[$i][0];
594
                $min    = $i;
595
            }
596
        }
597
        $j   = $min;
598
        $cnt = 0;
599
        while ($angles[$j][1] <= 90) {
600
            $j++;
601
            if ($j >= $n) {
602
                $j = 0;
603
            }
604
            if ($cnt > $n) {
605
                Util\JpGraphError::RaiseL(14005);
606
                //("Pie3D Internal error (#1). Trying to wrap twice when looking for start index");
607
            }
608
            ++$cnt;
609
        }
610
        $start = $j;
611
612
        //
613
        // Step 3. Print slices in z-order
614
        //
615
        $cnt = 0;
616
617
        // First stroke all the slices between 90 and 270 (left half circle)
618
        // counterclockwise
619
620
        while ($angles[$j][0] < 270 && $aaoption !== 2) {
621
            list($x, $y) = $adjexplode[$j];
622
623
            $this->Pie3DSlice($img, $x, $y, $d, $h, $angles[$j][0], $angles[$j][1],
624
                $z, $adjcolors[$j], $shadow);
625
626
            $last = array($x, $y, $j);
627
628
            $j++;
629
            if ($j >= $n) {
630
                $j = 0;
631
            }
632
633
            if ($cnt > $n) {
634
                Util\JpGraphError::RaiseL(14006);
635
                //("Pie3D Internal Error: Z-Sorting algorithm for 3D Pies is not working properly (2). Trying to wrap twice while stroking.");
636
            }
637
            ++$cnt;
638
        }
639
640
        $slice_left = $n - $cnt;
641
        $j          = $start - 1;
642
        if ($j < 0) {
643
            $j = $n - 1;
644
        }
645
646
        $cnt = 0;
647
648
        // The stroke all slices from 90 to -90 (right half circle)
649
        // clockwise
650
        while ($cnt < $slice_left && $aaoption !== 2) {
651
            list($x, $y) = $adjexplode[$j];
652
653
            $this->Pie3DSlice($img, $x, $y, $d, $h, $angles[$j][0], $angles[$j][1],
654
                $z, $adjcolors[$j], $shadow);
655
            $j--;
656
            if ($cnt > $n) {
657
                Util\JpGraphError::RaiseL(14006);
658
                //("Pie3D Internal Error: Z-Sorting algorithm for 3D Pies is not working properly (2). Trying to wrap twice while stroking.");
659
            }
660
            if ($j < 0) {
661
                $j = $n - 1;
662
            }
663
664
            $cnt++;
665
        }
666
667
        // Now do a special thing. Stroke the last slice on the left
668
        // halfcircle one more time.  This is needed in the case where
669
        // the slice close to 270 have been exploded. In that case the
670
        // part of the slice close to the center of the pie might be
671
        // slightly nagged.
672
        if ($aaoption !== 2) {
673
            $this->Pie3DSlice($img, $last[0], $last[1], $d, $h, $angles[$last[2]][0],
0 ignored issues
show
Bug introduced by
The variable $last 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...
674
                $angles[$last[2]][1], $z, $adjcolors[$last[2]], $shadow);
675
        }
676
677
        if ($aaoption !== 1) {
678
            // Now print possible labels and add csim
679
            $this->value->ApplyFont($img);
680
            $margin = $img->GetFontHeight() / 2 + $this->value->margin;
681
            for ($i = 0; $i < count($data); ++$i) {
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...
682
                $la = $labeldata[$i][0];
0 ignored issues
show
Bug introduced by
The variable $labeldata 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...
683
                $x  = $labeldata[$i][1] + cos($la * M_PI / 180) * ($d + $margin) * $this->ilabelposadj;
684
                $y  = $labeldata[$i][2] - sin($la * M_PI / 180) * ($h + $margin) * $this->ilabelposadj;
685
                if ($this->ilabelposadj >= 1.0) {
686
                    if ($la > 180 && $la < 360) {
687
                        $y += $z;
688
                    }
689
                }
690
                if ($this->labeltype == 0) {
691 View Code Duplication
                    if ($sum > 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...
692
                        $l = 100 * $data[$i] / $sum;
693
                    } else {
694
                        $l = 0;
695
                    }
696
                } elseif ($this->labeltype == 1) {
697
                    $l = $data[$i];
698
                } else {
699
                    $l = $this->adjusted_data[$i];
700
                }
701
                if (isset($this->labels[$i]) && is_string($this->labels[$i])) {
702
                    $l = sprintf($this->labels[$i], $l);
703
                }
704
705
                $this->StrokeLabels($l, $img, $labeldata[$i][0] * M_PI / 180, $x, $y, $z);
706
707
                $this->Add3DSliceToCSIM($i, $labeldata[$i][1], $labeldata[$i][2], $h * 2, $d * 2, $z,
708
                    $originalangles[$i][0], $originalangles[$i][1]);
0 ignored issues
show
Bug introduced by
The variable $originalangles 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...
709
            }
710
        }
711
712
        //
713
        // Finally add potential lines in pie
714
        //
715
716
        if ($edgecolor == "" || $aaoption !== 0) {
717
            return;
718
        }
719
720
        $accsum = 0;
0 ignored issues
show
Unused Code introduced by
$accsum 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...
721
        $a      = $startangle;
722
        $a      = $this->NormAngle($a);
723
724
        $a *= M_PI / 180.0;
725
726
        $idx = 0;
0 ignored issues
show
Unused Code introduced by
$idx 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...
727
        $img->PushColor($edgecolor);
728
        $img->SetLineWeight($edgeweight);
729
730
        $fulledge = true;
731
        for ($i = 0; $i < count($data) && $fulledge; ++$i) {
732
            if (empty($this->explode_radius[$i])) {
733
                $this->explode_radius[$i] = 0;
734
            }
735
            if ($this->explode_radius[$i] > 0) {
736
                $fulledge = false;
737
            }
738
        }
739
740
        for ($i = 0; $i < count($data); ++$i, ++$idx) {
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...
741
            $da = $data[$i] / $sum * 2 * M_PI;
742
            $this->StrokeFullSliceFrame($img, $xc, $yc, $a, $a + $da, $d, $h, $z, $edgecolor,
743
                $this->explode_radius[$i], $fulledge);
744
            $a += $da;
745
        }
746
        $img->PopColor();
747
    }
748
749
    public function StrokeFullSliceFrame($img, $xc, $yc, $sa, $ea, $w, $h, $z, $edgecolor, $exploderadius, $fulledge)
750
    {
751
        $step = 0.02;
752
753
        if ($exploderadius > 0) {
754
            $la = ($sa + $ea) / 2;
755
            $xc += $exploderadius * cos($la);
756
            $yc -= $exploderadius * sin($la) * ($h / $w);
757
        }
758
759
        $p = array($xc, $yc, $xc + $w * cos($sa), $yc - $h * sin($sa));
760
761
        for ($a = $sa; $a < $ea; $a += $step) {
762
            $p[] = $xc + $w * cos($a);
763
            $p[] = $yc - $h * sin($a);
764
        }
765
766
        $p[] = $xc + $w * cos($ea);
767
        $p[] = $yc - $h * sin($ea);
768
        $p[] = $xc;
769
        $p[] = $yc;
770
771
        $img->SetColor($edgecolor);
772
        $img->Polygon($p);
773
774
        // Unfortunately we can't really draw the full edge around the whole of
775
        // of the slice if any of the slices are exploded. The reason is that
776
        // this algorithm is to simply. There are cases where the edges will
777
        // "overwrite" other slices when they have been exploded.
778
        // Doing the full, proper 3D hidden lines stiff is actually quite
779
        // tricky. So for exploded pies we only draw the top edge. Not perfect
780
        // but the "real" solution is much more complicated.
781
        if ($fulledge && !($sa > 0 && $sa < M_PI && $ea < M_PI)) {
782
            if ($sa < M_PI && $ea > M_PI) {
783
                $sa = M_PI;
784
            }
785
786
            if ($sa < 2 * M_PI && (($ea >= 2 * M_PI) || ($ea > 0 && $ea < $sa))) {
787
                $ea = 2 * M_PI;
788
            }
789
790
            if ($sa >= M_PI && $ea <= 2 * M_PI) {
791
                $p = array($xc + $w * cos($sa), $yc - $h * sin($sa),
792
                    $xc + $w * cos($sa), $z + $yc - $h * sin($sa));
793
794 View Code Duplication
                for ($a = $sa + $step; $a < $ea; $a += $step) {
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...
795
                    $p[] = $xc + $w * cos($a);
796
                    $p[] = $z + $yc - $h * sin($a);
797
                }
798
                $p[] = $xc + $w * cos($ea);
799
                $p[] = $z + $yc - $h * sin($ea);
800
                $p[] = $xc + $w * cos($ea);
801
                $p[] = $yc - $h * sin($ea);
802
                $img->SetColor($edgecolor);
803
                $img->Polygon($p);
804
            }
805
        }
806
    }
807
808
    public function Stroke($img, $aaoption = 0)
809
    {
810
        $n = count($this->data);
811
812
        // If user hasn't set the colors use the theme array
813
        if ($this->setslicecolors == null) {
814
            $colors = array_keys($img->rgb->rgb_table);
815
            sort($colors);
816
            $idx_a = $this->themearr[$this->theme];
817
            $ca    = array();
818
            $m     = count($idx_a);
819
            for ($i = 0; $i < $m; ++$i) {
820
                $ca[$i] = $colors[$idx_a[$i]];
821
            }
822
            $ca = array_reverse(array_slice($ca, 0, $n));
823
        } else {
824
            $ca = $this->setslicecolors;
825
        }
826
827 View Code Duplication
        if ($this->posx <= 1 && $this->posx > 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...
828
            $xc = round($this->posx * $img->width);
829
        } else {
830
            $xc = $this->posx;
831
        }
832
833 View Code Duplication
        if ($this->posy <= 1 && $this->posy > 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...
834
            $yc = round($this->posy * $img->height);
835
        } else {
836
            $yc = $this->posy;
837
        }
838
839
        if ($this->radius <= 1) {
840
            $width = floor($this->radius * min($img->width, $img->height));
841
            // Make sure that the pie doesn't overflow the image border
842
            // The 0.9 factor is simply an extra margin to leave some space
843
            // between the pie an the border of the image.
844
            $width = min($width, min($xc * 0.9, ($yc * 90 / $this->angle - $width / 4) * 0.9));
845
        } else {
846
            $width = $this->radius * ($aaoption === 1 ? 2 : 1);
847
        }
848
849
        // Add a sanity check for width
850
        if ($width < 1) {
851
            Util\JpGraphError::RaiseL(14007); //("Width for 3D Pie is 0. Specify a size > 0");
852
        }
853
854
        // Establish a thickness. By default the thickness is a fifth of the
855
        // pie slice width (=pie radius) but since the perspective depends
856
        // on the inclination angle we use some heuristics to make the edge
857
        // slightly thicker the less the angle.
858
859
        // Has user specified an absolute thickness? In that case use
860
        // that instead
861
862
        if ($this->iThickness) {
863
            $thick = $this->iThickness;
864
            $thick *= ($aaoption === 1 ? 2 : 1);
865
        } else {
866
            $thick = $width / 12;
867
        }
868
        $a = $this->angle;
869
870
        if ($a <= 30) {
871
            $thick *= 1.6;
872
        } elseif ($a <= 40) {
873
            $thick *= 1.4;
874
        } elseif ($a <= 50) {
875
            $thick *= 1.2;
876
        } elseif ($a <= 60) {
877
            $thick *= 1.0;
878
        } elseif ($a <= 70) {
879
            $thick *= 0.8;
880
        } elseif ($a <= 80) {
881
            $thick *= 0.7;
882
        } else {
883
            $thick *= 0.6;
884
        }
885
886
        $thick = floor($thick);
887
888 View Code Duplication
        if ($this->explode_all) {
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...
889
            for ($i = 0; $i < $n; ++$i) {
890
                $this->explode_radius[$i] = $this->explode_r;
891
            }
892
        }
893
894
        $this->Pie3D($aaoption, $img, $this->data, $ca, $xc, $yc, $width, $this->angle,
895
            $thick, 0.65, $this->startangle, $this->edgecolor, $this->edgeweight);
896
897
        // Adjust title position
898 View Code Duplication
        if ($aaoption != 1) {
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...
899
            $this->title->SetPos($xc, $yc - $this->title->GetFontHeight($img) - $width / 2 - $this->title->margin, "center", "bottom");
0 ignored issues
show
Bug introduced by
The property margin does not seem to exist. Did you mean _margin?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
900
            $this->title->Stroke($img);
901
        }
902
    }
903
904
    //---------------
905
    // PRIVATE METHODS
906
907
    // Position the labels of each slice
908
    public function StrokeLabels($label, $img, $a, $xp, $yp, $z)
0 ignored issues
show
Unused Code introduced by
The parameter $z 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...
909
    {
910
        $this->value->halign = "left";
911
        $this->value->valign = "top";
912
913
        // Position the axis title.
914
        // dx, dy is the offset from the top left corner of the bounding box that sorrounds the text
915
        // that intersects with the extension of the corresponding axis. The code looks a little
916
        // bit messy but this is really the only way of having a reasonable position of the
917
        // axis titles.
918
        $this->value->ApplyFont($img);
919
        $h = $img->GetTextHeight($label);
920
        // For numeric values the format of the display value
921
        // must be taken into account
922 View Code Duplication
        if (is_numeric($label)) {
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...
923
            if ($label >= 0) {
924
                $w = $img->GetTextWidth(sprintf($this->value->format, $label));
925
            } else {
926
                $w = $img->GetTextWidth(sprintf($this->value->negformat, $label));
927
            }
928
        } else {
929
            $w = $img->GetTextWidth($label);
930
        }
931
932
        while ($a > 2 * M_PI) {
933
            $a -= 2 * M_PI;
934
        }
935
936
        if ($a >= 7 * M_PI / 4 || $a <= M_PI / 4) {
937
            $dx = 0;
938
        }
939
940
        if ($a >= M_PI / 4 && $a <= 3 * M_PI / 4) {
941
            $dx = ($a - M_PI / 4) * 2 / M_PI;
942
        }
943
944
        if ($a >= 3 * M_PI / 4 && $a <= 5 * M_PI / 4) {
945
            $dx = 1;
946
        }
947
948
        if ($a >= 5 * M_PI / 4 && $a <= 7 * M_PI / 4) {
949
            $dx = (1 - ($a - M_PI * 5 / 4) * 2 / M_PI);
950
        }
951
952
        if ($a >= 7 * M_PI / 4) {
953
            $dy = (($a - M_PI) - 3 * M_PI / 4) * 2 / M_PI;
954
        }
955
956
        if ($a <= M_PI / 4) {
957
            $dy = (1 - $a * 2 / M_PI);
958
        }
959
960
        if ($a >= M_PI / 4 && $a <= 3 * M_PI / 4) {
961
            $dy = 1;
962
        }
963
964
        if ($a >= 3 * M_PI / 4 && $a <= 5 * M_PI / 4) {
965
            $dy = (1 - ($a - 3 * M_PI / 4) * 2 / M_PI);
966
        }
967
968
        if ($a >= 5 * M_PI / 4 && $a <= 7 * M_PI / 4) {
969
            $dy = 0;
970
        }
971
972
        $x = round($xp - $dx * $w);
0 ignored issues
show
Bug introduced by
The variable $dx 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...
973
        $y = round($yp - $dy * $h);
0 ignored issues
show
Bug introduced by
The variable $dy 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...
974
975
        // Mark anchor point for debugging
976
        /*
1 ignored issue
show
Unused Code Comprehensibility introduced by
78% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
977
        $img->SetColor('red');
978
        $img->Line($xp-10,$yp,$xp+10,$yp);
979
        $img->Line($xp,$yp-10,$xp,$yp+10);
980
         */
981
982
        $oldmargin           = $this->value->margin;
983
        $this->value->margin = 0;
984
        $this->value->Stroke($img, $label, $x, $y);
985
        $this->value->margin = $oldmargin;
986
    }
987
} // Class
988
989
/* EOF */
990