Test Failed
Push — CI ( 0f01dd...c95a04 )
by Adam
55:13
created

pDraw::drawStepChart()   F

Complexity

Conditions 80
Paths > 20000

Size

Total Lines 167
Code Lines 104

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 167
rs 2
cc 80
eloc 104
nc 429496.7295
nop 1

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
 /*
3
     pDraw - class extension with drawing methods
4
5
     Version     : 2.1.4
6
     Made by     : Jean-Damien POGOLOTTI
7
     Last Update : 19/01/2014
8
9
     This file can be distributed under the license you can find at :
10
11
                       http://www.pchart.net/license
12
13
     You can find the whole class documentation on the pChart web site.
14
 */
15
16
 define("DIRECTION_VERTICAL"		, 690001);
17
 define("DIRECTION_HORIZONTAL"		, 690002);
18
19
 define("SCALE_POS_LEFTRIGHT"		, 690101);
20
 define("SCALE_POS_TOPBOTTOM"		, 690102);
21
22
 define("SCALE_MODE_FLOATING"		, 690201);
23
 define("SCALE_MODE_START0"		, 690202);
24
 define("SCALE_MODE_ADDALL"		, 690203);
25
 define("SCALE_MODE_ADDALL_START0"	, 690204);
26
 define("SCALE_MODE_MANUAL"		, 690205);
27
28
 define("SCALE_SKIP_NONE"		, 690301);
29
 define("SCALE_SKIP_SAME"		, 690302);
30
 define("SCALE_SKIP_NUMBERS"		, 690303);
31
32
 define("TEXT_ALIGN_TOPLEFT"		, 690401);
33
 define("TEXT_ALIGN_TOPMIDDLE"		, 690402);
34
 define("TEXT_ALIGN_TOPRIGHT"		, 690403);
35
 define("TEXT_ALIGN_MIDDLELEFT"		, 690404);
36
 define("TEXT_ALIGN_MIDDLEMIDDLE"	, 690405);
37
 define("TEXT_ALIGN_MIDDLERIGHT"	, 690406);
38
 define("TEXT_ALIGN_BOTTOMLEFT"		, 690407);
39
 define("TEXT_ALIGN_BOTTOMMIDDLE"	, 690408);
40
 define("TEXT_ALIGN_BOTTOMRIGHT"	, 690409);
41
42
 define("POSITION_TOP"                  , 690501);
43
 define("POSITION_BOTTOM"               , 690502);
44
45
 define("LABEL_POS_LEFT"		, 690601);
46
 define("LABEL_POS_CENTER"		, 690602);
47
 define("LABEL_POS_RIGHT"		, 690603);
48
 define("LABEL_POS_TOP"			, 690604);
49
 define("LABEL_POS_BOTTOM"		, 690605);
50
 define("LABEL_POS_INSIDE"		, 690606);
51
 define("LABEL_POS_OUTSIDE"		, 690607);
52
53
 define("ORIENTATION_HORIZONTAL"	, 690701);
54
 define("ORIENTATION_VERTICAL"		, 690702);
55
 define("ORIENTATION_AUTO"		, 690703);
56
57
 define("LEGEND_NOBORDER"		, 690800);
58
 define("LEGEND_BOX"			, 690801);
59
 define("LEGEND_ROUND"			, 690802);
60
61
 define("LEGEND_VERTICAL"		, 690901);
62
 define("LEGEND_HORIZONTAL"		, 690902);
63
64
 define("LEGEND_FAMILY_BOX"		, 691051);
65
 define("LEGEND_FAMILY_CIRCLE"		, 691052);
66
 define("LEGEND_FAMILY_LINE"		, 691053);
67
68
 define("DISPLAY_AUTO"			, 691001);
69
 define("DISPLAY_MANUAL"		, 691002);
70
71
 define("LABELING_ALL"			, 691011);
72
 define("LABELING_DIFFERENT"		, 691012);
73
74
 define("BOUND_MIN"			, 691021);
75
 define("BOUND_MAX"			, 691022);
76
 define("BOUND_BOTH"			, 691023);
77
78
 define("BOUND_LABEL_POS_TOP"		, 691031);
79
 define("BOUND_LABEL_POS_BOTTOM"	, 691032);
80
 define("BOUND_LABEL_POS_AUTO"		, 691033);
81
82
 define("CAPTION_LEFT_TOP"		, 691041);
83
 define("CAPTION_RIGHT_BOTTOM"		, 691042);
84
85
 define("GRADIENT_SIMPLE"		, 691051);
86
 define("GRADIENT_EFFECT_CAN"		, 691052);
87
88
 define("LABEL_TITLE_NOBACKGROUND"	, 691061);
89
 define("LABEL_TITLE_BACKGROUND"	, 691062);
90
91
 define("LABEL_POINT_NONE"		, 691071);
92
 define("LABEL_POINT_CIRCLE"		, 691072);
93
 define("LABEL_POINT_BOX"		, 691073);
94
95
 define("ZONE_NAME_ANGLE_AUTO"		, 691081);
96
97
 define("PI"		, 3.14159265);
98
 define("ALL"		, 69);
99
 define("NONE"		, 31);
100
 define("AUTO"		, 690000);
101
 define("OUT_OF_SIGHT"	, -10000000000000);
102
103
 class pDraw
104
  {
105
   /* Returns the number of drawable series */
106
   function countDrawableSeries()
107
    {
108
     $Results = 0;
109
     $Data = $this->DataSet->getData();
110
111
     foreach($Data["Series"] as $SerieName => $Serie)
112
      { if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] ) { $Results++; } }
113
114
     return($Results);
115
    }
116
117
   /* Fix box coordinates */
118
   function fixBoxCoordinates($Xa,$Ya,$Xb,$Yb)
119
    {
120
     $X1 = min($Xa,$Xb); $Y1 = min($Ya,$Yb);
121
     $X2 = max($Xa,$Xb); $Y2 = max($Ya,$Yb);
122
123
     return(array($X1,$Y1,$X2,$Y2));
124
    }
125
126
   /* Draw a polygon */
127
   function drawPolygon($Points,$Format="")
128
    {
129
     $R			= isset($Format["R"]) ? $Format["R"] : 0;
130
     $G			= isset($Format["G"]) ? $Format["G"] : 0;
131
     $B			= isset($Format["B"]) ? $Format["B"] : 0;
132
     $Alpha		= isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
133
     $NoFill		= isset($Format["NoFill"]) ? $Format["NoFill"] : FALSE;
134
     $NoBorder		= isset($Format["NoBorder"]) ? $Format["NoBorder"] : FALSE;
135
     $BorderR		= isset($Format["BorderR"]) ? $Format["BorderR"] : $R;
136
     $BorderG		= isset($Format["BorderG"]) ? $Format["BorderG"] : $G;
137
     $BorderB		= isset($Format["BorderB"]) ? $Format["BorderB"] : $B;
138
     $BorderAlpha 	= isset($Format["Alpha"]) ? $Format["Alpha"] : $Alpha / 2;
139
     $Surrounding	= isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL;
140
     $SkipX		= isset($Format["SkipX"]) ? $Format["SkipX"] : OUT_OF_SIGHT;
141
     $SkipY		= isset($Format["SkipY"]) ? $Format["SkipY"] : OUT_OF_SIGHT;
142
143
     /* Calling the ImageFilledPolygon() function over the $Points array will round it */ 	
0 ignored issues
show
Coding Style introduced by
There is some trailing whitespace on this line which should be avoided as per coding-style.
Loading history...
144
     $Backup = $Points;
145
146
     if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; }
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $Surrounding of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
147
148
     if ( $SkipX != OUT_OF_SIGHT ) { $SkipX = floor($SkipX); }
149
     if ( $SkipY != OUT_OF_SIGHT ) { $SkipY = floor($SkipY); }
150
151
     $RestoreShadow = $this->Shadow;
152
     if ( !$NoFill )
153
      {
154
       if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 )
155
        {
156
         $this->Shadow = FALSE;
157
         for($i=0;$i<=count($Points)-1;$i=$i+2)
158
          { $Shadow[] = $Points[$i] + $this->ShadowX; $Shadow[] = $Points[$i+1] + $this->ShadowY; }
159
         $this->drawPolygon($Shadow,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa,"NoBorder"=>TRUE));
160
        }
161
162
       $FillColor = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha);
163
164
       if ( count($Points) >= 6 )
165
        { ImageFilledPolygon($this->Picture,$Points,count($Points)/2,$FillColor); }
166
      }
167
168
     if ( !$NoBorder )
169
      {
170
       $Points = $Backup;
171
172
       if ( $NoFill )
173
        $BorderSettings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha);
174
       else
175
        $BorderSettings = array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha);
176
177
       for($i=0;$i<=count($Points)-1;$i=$i+2)
178
        {
179
         if ( isset($Points[$i+2]) )
180
          {
181
           if ( !($Points[$i] == $Points[$i+2] && $Points[$i] == $SkipX ) && !($Points[$i+1] == $Points[$i+3] && $Points[$i+1] == $SkipY ) )
182
            $this->drawLine($Points[$i],$Points[$i+1],$Points[$i+2],$Points[$i+3],$BorderSettings);
183
          }
184
         else
185
          {
186
           if ( !($Points[$i] == $Points[0] && $Points[$i] == $SkipX ) && !($Points[$i+1] == $Points[1] && $Points[$i+1] == $SkipY ) )
187
            $this->drawLine($Points[$i],$Points[$i+1],$Points[0],$Points[1],$BorderSettings);
188
          }
189
        }
190
      }
191
192
     $this->Shadow = $RestoreShadow;
193
    }
194
195
   /* Apply AALias correction to the rounded box boundaries */
196
   function offsetCorrection($Value,$Mode)
197
    {
198
     $Value = round($Value,1);
199
200
     if ( $Value == 0 && $Mode == 1 ) { return(.9); }
201
     if ( $Value == 0 ) { return(0); }
202
203
     if ( $Mode == 1) 
204
      { if ( $Value == 1 ) { return(.9); }; if ( $Value == .1 ) { return(.9); }; if ( $Value == .2 ) { return(.8); }; if ( $Value == .3 ) { return(.8); }; if ( $Value == .4 ) { return(.7); }; if ( $Value == .5 ) { return(.5); }; if ( $Value == .6 ) { return(.8); }; if ( $Value == .7 ) { return(.7); }; if ( $Value == .8 ) { return(.6); }; if ( $Value == .9 ) { return(.9); }; }
205
206
     if ( $Mode == 2) 
207
      { if ( $Value == 1 ) { return(.9); }; if ( $Value == .1 ) { return(.1); }; if ( $Value == .2 ) { return(.2); }; if ( $Value == .3 ) { return(.3); }; if ( $Value == .4 ) { return(.4); }; if ( $Value == .5 ) { return(.5); }; if ( $Value == .6 ) { return(.8); }; if ( $Value == .7 ) { return(.7); }; if ( $Value == .8 ) { return(.8); }; if ( $Value == .9 ) { return(.9); }; }
208
209
     if ( $Mode == 3) 
210
      { if ( $Value == 1 ) { return(.1); }; if ( $Value == .1 ) { return(.1); }; if ( $Value == .2 ) { return(.2); }; if ( $Value == .3 ) { return(.3); }; if ( $Value == .4 ) { return(.4); }; if ( $Value == .5 ) { return(.9); }; if ( $Value == .6 ) { return(.6); }; if ( $Value == .7 ) { return(.7); }; if ( $Value == .8 ) { return(.4); }; if ( $Value == .9 ) { return(.5); }; }
211
212
     if ( $Mode == 4) 
213
      { if ( $Value == 1 ) { return(-1); }; if ( $Value == .1 ) { return(.1); }; if ( $Value == .2 ) { return(.2); }; if ( $Value == .3 ) { return(.3); }; if ( $Value == .4 ) { return(.1); }; if ( $Value == .5 ) { return(-.1); }; if ( $Value == .6 ) { return(.8); }; if ( $Value == .7 ) { return(.1); }; if ( $Value == .8 ) { return(.1); }; if ( $Value == .9 ) { return(.1); }; }
214
    }
215
216
   /* Draw a rectangle with rounded corners */
217
   function drawRoundedRectangle($X1,$Y1,$X2,$Y2,$Radius,$Format="")
218
    {
219
     $R	    = isset($Format["R"]) ? $Format["R"] : 0;
220
     $G	    = isset($Format["G"]) ? $Format["G"] : 0;
221
     $B	    = isset($Format["B"]) ? $Format["B"] : 0;
222
     $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
223
224
     list($X1,$Y1,$X2,$Y2) = $this->fixBoxCoordinates($X1,$Y1,$X2,$Y2);
225
226
     if ( $X2 - $X1 < $Radius ) { $Radius = floor((($X2-$X1))/2); }
227
     if ( $Y2 - $Y1 < $Radius ) { $Radius = floor((($Y2-$Y1))/2); }
228
229
     $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"NoBorder"=>TRUE);
230
231
     if ( $Radius <= 0 ) { $this->drawRectangle($X1,$Y1,$X2,$Y2,$Color); return(0); }
232
233
     if ( $this->Antialias )
234
      {
235
       $this->drawLine($X1+$Radius,$Y1,$X2-$Radius,$Y1,$Color);
236
       $this->drawLine($X2,$Y1+$Radius,$X2,$Y2-$Radius,$Color);
237
       $this->drawLine($X2-$Radius,$Y2,$X1+$Radius,$Y2,$Color);
238
       $this->drawLine($X1,$Y1+$Radius,$X1,$Y2-$Radius,$Color);
239
      }
240
     else
241
      {
242
       $Color = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha);
243
       imageline($this->Picture,$X1+$Radius,$Y1,$X2-$Radius,$Y1,$Color);
244
       imageline($this->Picture,$X2,$Y1+$Radius,$X2,$Y2-$Radius,$Color);
245
       imageline($this->Picture,$X2-$Radius,$Y2,$X1+$Radius,$Y2,$Color);
246
       imageline($this->Picture,$X1,$Y1+$Radius,$X1,$Y2-$Radius,$Color);
247
      }
248
249
     $Step = 360 / (2 * PI * $Radius);
250
     for($i=0;$i<=90;$i=$i+$Step)
251
      {
252
       $X = cos(($i+180)*PI/180) * $Radius + $X1 + $Radius;
253
       $Y = sin(($i+180)*PI/180) * $Radius + $Y1 + $Radius;
254
       $this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
255
256
       $X = cos(($i+90)*PI/180) * $Radius + $X1 + $Radius;
257
       $Y = sin(($i+90)*PI/180) * $Radius + $Y2 - $Radius;
258
       $this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
259
260
       $X = cos($i*PI/180) * $Radius + $X2 - $Radius;
261
       $Y = sin($i*PI/180) * $Radius + $Y2 - $Radius;
262
       $this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
263
264
       $X = cos(($i+270)*PI/180) * $Radius + $X2 - $Radius;
265
       $Y = sin(($i+270)*PI/180) * $Radius + $Y1 + $Radius;
266
       $this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
267
      }
268
    }
269
270
   /* Draw a rectangle with rounded corners */
271
   function drawRoundedFilledRectangle($X1,$Y1,$X2,$Y2,$Radius,$Format="")
272
    {
273
     $R			= isset($Format["R"]) ? $Format["R"] : 0;
274
     $G			= isset($Format["G"]) ? $Format["G"] : 0;
275
     $B			= isset($Format["B"]) ? $Format["B"] : 0;
276
     $BorderR		= isset($Format["BorderR"]) ? $Format["BorderR"] : -1;
277
     $BorderG		= isset($Format["BorderG"]) ? $Format["BorderG"] : -1;
278
     $BorderB		= isset($Format["BorderB"]) ? $Format["BorderB"] : -1;
279
     $Alpha		= isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
280
     $Surrounding	= isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL;
281
282
     /* Temporary fix for AA issue */
283
     $Y1 = floor($Y1); $Y2 = floor($Y2); $X1 = floor($X1); $X2 = floor($X2);
284
285
     if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; }
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $Surrounding of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
286
     if ( $BorderR == -1 ) { $BorderR = $R; $BorderG = $G; $BorderB = $B; }
287
288
     list($X1,$Y1,$X2,$Y2) = $this->fixBoxCoordinates($X1,$Y1,$X2,$Y2);
289
290
     if ( $X2 - $X1 < $Radius*2 ) { $Radius = floor((($X2-$X1))/4); }
291
     if ( $Y2 - $Y1 < $Radius*2 ) { $Radius = floor((($Y2-$Y1))/4); }
292
293
     $RestoreShadow = $this->Shadow;
294
     if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 )
295
      {
296
       $this->Shadow = FALSE;
297
       $this->drawRoundedFilledRectangle($X1+$this->ShadowX,$Y1+$this->ShadowY,$X2+$this->ShadowX,$Y2+$this->ShadowY,$Radius,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa));
298
      }
299
300
     $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"NoBorder"=>TRUE);
301
302
     if ( $Radius <= 0 ) { $this->drawFilledRectangle($X1,$Y1,$X2,$Y2,$Color); return(0); }
303
304
     $YTop    = $Y1+$Radius;
305
     $YBottom = $Y2-$Radius;
306
307
     $Step = 360 / (2 * PI * $Radius);
308
     $Positions = ""; $Radius--; $MinY = ""; $MaxY = "";
309
     for($i=0;$i<=90;$i=$i+$Step)
310
      {
311
       $Xp1 = cos(($i+180)*PI/180) * $Radius + $X1 + $Radius;
312
       $Xp2 = cos(((90-$i)+270)*PI/180) * $Radius + $X2 - $Radius;
313
       $Yp  = floor(sin(($i+180)*PI/180) * $Radius + $YTop);
314
       if ( $MinY == "" || $Yp > $MinY ) { $MinY = $Yp; }
315
316
       if ( $Xp1 <= floor($X1) )  { $Xp1++; }
317
       if ( $Xp2 >= floor($X2) )  { $Xp2--; }
318
       $Xp1++;
319
320
       if ( !isset($Positions[$Yp]) )
321
        { $Positions[$Yp]["X1"] = $Xp1; $Positions[$Yp]["X2"] = $Xp2; }
322
       else
323
        { $Positions[$Yp]["X1"] = ($Positions[$Yp]["X1"]+$Xp1)/2; $Positions[$Yp]["X2"] = ($Positions[$Yp]["X2"]+$Xp2)/2; }
324
325
       $Xp1 = cos(($i+90)*PI/180) * $Radius + $X1 + $Radius;
326
       $Xp2 = cos((90-$i)*PI/180) * $Radius + $X2 - $Radius;
327
       $Yp  = floor(sin(($i+90)*PI/180) * $Radius + $YBottom);
328
       if ( $MaxY == "" || $Yp < $MaxY ) { $MaxY = $Yp; }
329
330
       if ( $Xp1 <= floor($X1) ) { $Xp1++; }
331
       if ( $Xp2 >= floor($X2) ) { $Xp2--; }
332
       $Xp1++;
333
334
       if ( !isset($Positions[$Yp]) )
335
        { $Positions[$Yp]["X1"] = $Xp1; $Positions[$Yp]["X2"] = $Xp2; }
336
       else
337
        { $Positions[$Yp]["X1"] = ($Positions[$Yp]["X1"]+$Xp1)/2; $Positions[$Yp]["X2"] = ($Positions[$Yp]["X2"]+$Xp2)/2; }
338
      }
339
340
     $ManualColor  = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha);
341
     foreach($Positions as $Yp => $Bounds)
0 ignored issues
show
Bug introduced by
The expression $Positions of type string is not traversable.
Loading history...
342
      {
343
       $X1 = $Bounds["X1"]; $X1Dec = $this->getFirstDecimal($X1); if ( $X1Dec != 0 ) { $X1 = floor($X1)+1; }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getFirstDecimal() does only exist in the following sub-classes of pDraw: pImage. 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...
344
       $X2 = $Bounds["X2"]; $X2Dec = $this->getFirstDecimal($X2); if ( $X2Dec != 0 ) { $X2 = floor($X2)-1; }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getFirstDecimal() does only exist in the following sub-classes of pDraw: pImage. 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...
345
       imageline($this->Picture,$X1,$Yp,$X2,$Yp,$ManualColor);
346
      }
347
     $this->drawFilledRectangle($X1,$MinY+1,floor($X2),$MaxY-1,$Color);
348
349
     $Radius++;
350
     $this->drawRoundedRectangle($X1,$Y1,$X2+1,$Y2-1,$Radius,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha));
351
352
     $this->Shadow = $RestoreShadow;
353
    }
354
355
   /* Draw a rectangle with rounded corners */
356
   function drawRoundedFilledRectangle_deprecated($X1,$Y1,$X2,$Y2,$Radius,$Format="")
357
    {
358
     $R			= isset($Format["R"]) ? $Format["R"] : 0;
359
     $G			= isset($Format["G"]) ? $Format["G"] : 0;
360
     $B			= isset($Format["B"]) ? $Format["B"] : 0;
361
     $BorderR		= isset($Format["BorderR"]) ? $Format["BorderR"] : -1;
362
     $BorderG		= isset($Format["BorderG"]) ? $Format["BorderG"] : -1;
363
     $BorderB		= isset($Format["BorderB"]) ? $Format["BorderB"] : -1;
364
     $Alpha		= isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
365
     $Surrounding	= isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL;
366
367
     if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; }
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $Surrounding of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
368
     if ( $BorderR == -1 ) { $BorderR = $R; $BorderG = $G; $BorderB = $B; }
369
370
     list($X1,$Y1,$X2,$Y2) = $this->fixBoxCoordinates($X1,$Y1,$X2,$Y2);
371
372
     if ( $X2 - $X1 < $Radius ) { $Radius = floor((($X2-$X1)+2)/2); }
373
     if ( $Y2 - $Y1 < $Radius ) { $Radius = floor((($Y2-$Y1)+2)/2); }
374
375
     $RestoreShadow = $this->Shadow;
376
     if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 )
377
      {
378
       $this->Shadow = FALSE;
379
       $this->drawRoundedFilledRectangle($X1+$this->ShadowX,$Y1+$this->ShadowY,$X2+$this->ShadowX,$Y2+$this->ShadowY,$Radius,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa));
380
      }
381
382
     if ( $this->getFirstDecimal($X2) >= 5 )  { $XOffset2 = 1; } else { $XOffset2 = 0; }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getFirstDecimal() does only exist in the following sub-classes of pDraw: pImage. 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...
383
     if ( $this->getFirstDecimal($X1) <= 5 )  { $XOffset1 = 1; } else { $XOffset1 = 0; }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getFirstDecimal() does only exist in the following sub-classes of pDraw: pImage. 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...
384
385
     if ( !$this->Antialias ) { $XOffset1 = 1; $XOffset2 = 1; }
386
387
     $YTop    = floor($Y1+$Radius);
388
     $YBottom = floor($Y2-$Radius);
389
390
     $this->drawFilledRectangle($X1-$XOffset1,$YTop,$X2+$XOffset2,$YBottom,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"NoBorder"=>TRUE));
391
392
     $Step = 360 / (2 * PI * $Radius);
393
     $Color  = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha);
394
     $Color2 = $this->allocateColor($this->Picture,255,0,0,$Alpha);
395
     $Drawn = "";
396
397
     if ( $Alpha < 100 )  { $Drawn[$YTop] = FALSE; }
398
     if ( $Alpha < 100 )  { $Drawn[$YBottom] = TRUE; }
399
     
400
     for($i=0;$i<=90;$i=$i+$Step)
401
      {
402
       $Xp1 = cos(($i+180)*PI/180) * $Radius + $X1 + $Radius;
403
       $Xp2 = cos(((90-$i)+270)*PI/180) * $Radius + $X2 - $Radius;
404
       $Yp  = sin(($i+180)*PI/180) * $Radius + $YTop;
405
406
       if ( $this->getFirstDecimal($Xp1) > 5 )  { $XOffset1 = 1; } else { $XOffset1 = 0; }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getFirstDecimal() does only exist in the following sub-classes of pDraw: pImage. 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...
407
       if ( $this->getFirstDecimal($Xp2) > 5 )  { $XOffset2 = 1; } else { $XOffset2 = 0; }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getFirstDecimal() does only exist in the following sub-classes of pDraw: pImage. 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...
408
       if ( $this->getFirstDecimal($Yp) > 5 )  { $YOffset = 1; } else { $YOffset = 0; }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getFirstDecimal() does only exist in the following sub-classes of pDraw: pImage. 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...
409
410
       if ( !isset($Drawn[$Yp+$YOffset]) || $Alpha == 100 )
411
        imageline($this->Picture,$Xp1+$XOffset1,$Yp+$YOffset,$Xp2+$XOffset2,$Yp+$YOffset,$Color);
412
413
       $Drawn[$Yp+$YOffset] = $Xp2;
414
415
       $Xp1 = cos(($i+90)*PI/180) * $Radius + $X1 + $Radius;
416
       $Xp2 = cos((90-$i)*PI/180) * $Radius + $X2 - $Radius;
417
       $Yp  = sin(($i+90)*PI/180) * $Radius + $YBottom;
418
419
       if ( $this->getFirstDecimal($Xp1) > 7 )  { $XOffset1 = 1; } else { $XOffset1 = 0; }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getFirstDecimal() does only exist in the following sub-classes of pDraw: pImage. 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...
420
       if ( $this->getFirstDecimal($Xp2) > 7 )  { $XOffset2 = 1; } else { $XOffset2 = 0; }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getFirstDecimal() does only exist in the following sub-classes of pDraw: pImage. 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...
421
       if ( $this->getFirstDecimal($Yp) > 5 )  { $YOffset = 1; } else { $YOffset = 0; }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getFirstDecimal() does only exist in the following sub-classes of pDraw: pImage. 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...
422
423
       if ( !isset($Drawn[$Yp+$YOffset]) || $Alpha == 100 )
424
        imageline($this->Picture,$Xp1+$XOffset1,$Yp+$YOffset,$Xp2+$XOffset2,$Yp+$YOffset,$Color);
425
426
       $Drawn[$Yp+$YOffset] = $Xp2;
427
      }
428
429
     $this->drawRoundedRectangle($X1,$Y1,$X2,$Y2,$Radius,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha));
430
431
     $this->Shadow = $RestoreShadow;
432
    }
433
434
   /* Draw a rectangle */
435
   function drawRectangle($X1,$Y1,$X2,$Y2,$Format="")
436
    {
437
     $R		= isset($Format["R"]) ? $Format["R"] : 0;
438
     $G		= isset($Format["G"]) ? $Format["G"] : 0;
439
     $B		= isset($Format["B"]) ? $Format["B"] : 0;
440
     $Alpha	= isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
441
     $Ticks	= isset($Format["Ticks"]) ? $Format["Ticks"] : NULL;
442
     $NoAngle	= isset($Format["NoAngle"]) ? $Format["NoAngle"] : FALSE;
443
444
     if ($X1 > $X2) { list($X1, $X2) = array($X2, $X1); }
445
     if ($Y1 > $Y2) { list($Y1, $Y2) = array($Y2, $Y1); }
446
447
     if ( $this->Antialias )
448
      {
449
       if ( $NoAngle )
450
        {
451
         $this->drawLine($X1+1,$Y1,$X2-1,$Y1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks));
452
         $this->drawLine($X2,$Y1+1,$X2,$Y2-1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks));
453
         $this->drawLine($X2-1,$Y2,$X1+1,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks));
454
         $this->drawLine($X1,$Y1+1,$X1,$Y2-1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks));
455
        }
456
       else
457
        {
458
         $this->drawLine($X1+1,$Y1,$X2-1,$Y1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks));
459
         $this->drawLine($X2,$Y1,$X2,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks));
460
         $this->drawLine($X2-1,$Y2,$X1+1,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks));
461
         $this->drawLine($X1,$Y1,$X1,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks));
462
        }
463
      }
464
     else
465
      {
466
       $Color = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha);
467
       imagerectangle($this->Picture,$X1,$Y1,$X2,$Y2,$Color);
468
      }
469
    }
470
471
   /* Draw a filled rectangle */
472
   function drawFilledRectangle($X1,$Y1,$X2,$Y2,$Format="")
473
    {
474
     $R			= isset($Format["R"]) ? $Format["R"] : 0;
475
     $G			= isset($Format["G"]) ? $Format["G"] : 0;
476
     $B			= isset($Format["B"]) ? $Format["B"] : 0;
477
     $Alpha		= isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
478
     $BorderR		= isset($Format["BorderR"]) ? $Format["BorderR"] : -1;
479
     $BorderG		= isset($Format["BorderG"]) ? $Format["BorderG"] : -1;
480
     $BorderB		= isset($Format["BorderB"]) ? $Format["BorderB"] : -1;
481
     $BorderAlpha	= isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : $Alpha;
482
     $Surrounding	= isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL;
483
     $Ticks		= isset($Format["Ticks"]) ? $Format["Ticks"] : NULL;
484
     $NoAngle		= isset($Format["NoAngle"]) ? $Format["NoAngle"] : NULL;
485
     $Dash		= isset($Format["Dash"]) ? $Format["Dash"] : FALSE;
486
     $DashStep		= isset($Format["DashStep"]) ? $Format["DashStep"] : 4;
487
     $DashR		= isset($Format["DashR"]) ? $Format["DashR"] : 0;
488
     $DashG		= isset($Format["DashG"]) ? $Format["DashG"] : 0;
489
     $DashB		= isset($Format["DashB"]) ? $Format["DashB"] : 0;
490
     $NoBorder		= isset($Format["NoBorder"]) ? $Format["NoBorder"] : FALSE;
491
492
     if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; }
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $Surrounding of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
493
494
     if ($X1 > $X2) { list($X1, $X2) = array($X2, $X1); }
495
     if ($Y1 > $Y2) { list($Y1, $Y2) = array($Y2, $Y1); }
496
497
     $RestoreShadow = $this->Shadow;
498
     if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 )
499
      {
500
       $this->Shadow = FALSE;
501
       $this->drawFilledRectangle($X1+$this->ShadowX,$Y1+$this->ShadowY,$X2+$this->ShadowX,$Y2+$this->ShadowY,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa,"Ticks"=>$Ticks,"NoAngle"=>$NoAngle));
502
      }
503
504
     $Color = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha);
505
     if ( $NoAngle )
506
      {
507
       imagefilledrectangle($this->Picture,ceil($X1)+1,ceil($Y1),floor($X2)-1,floor($Y2),$Color);
508
       imageline($this->Picture,ceil($X1),ceil($Y1)+1,ceil($X1),floor($Y2)-1,$Color);
509
       imageline($this->Picture,floor($X2),ceil($Y1)+1,floor($X2),floor($Y2)-1,$Color);
510
      }
511
     else
512
      imagefilledrectangle($this->Picture,ceil($X1),ceil($Y1),floor($X2),floor($Y2),$Color);
513
514
     if ( $Dash )
515
      {
516
       if ( $BorderR != -1 ) { $iX1=$X1+1; $iY1=$Y1+1; $iX2=$X2-1; $iY2=$Y2-1; } else { $iX1=$X1; $iY1=$Y1; $iX2=$X2; $iY2=$Y2; }
517
518
       $Color = $this->allocateColor($this->Picture,$DashR,$DashG,$DashB,$Alpha);
519
       $Y=$iY1-$DashStep;
520
       for($X=$iX1; $X<=$iX2+($iY2-$iY1); $X=$X+$DashStep)
521
        {
522
         $Y=$Y+$DashStep;
523
         if ( $X > $iX2 ) { $Xa = $X-($X-$iX2); $Ya = $iY1+($X-$iX2); } else { $Xa = $X; $Ya = $iY1; }
524
         if ( $Y > $iY2 ) { $Xb = $iX1+($Y-$iY2); $Yb = $Y-($Y-$iY2); } else { $Xb = $iX1; $Yb = $Y; }
525
         imageline($this->Picture,$Xa,$Ya,$Xb,$Yb,$Color);
526
        }
527
      }
528
529
     if ( $this->Antialias && !$NoBorder )
530
      {
531
       if ( $X1 < ceil($X1) )
532
        {
533
         $AlphaA = $Alpha * (ceil($X1) - $X1);
534
         $Color = $this->allocateColor($this->Picture,$R,$G,$B,$AlphaA);
535
         imageline($this->Picture,ceil($X1)-1,ceil($Y1),ceil($X1)-1,floor($Y2),$Color);
536
        }
537
538
       if ( $Y1 < ceil($Y1) )
539
        {
540
         $AlphaA = $Alpha * (ceil($Y1) - $Y1);
541
         $Color = $this->allocateColor($this->Picture,$R,$G,$B,$AlphaA);
542
         imageline($this->Picture,ceil($X1),ceil($Y1)-1,floor($X2),ceil($Y1)-1,$Color);
543
        }
544
545
       if ( $X2 > floor($X2) )
546
        {
547
         $AlphaA = $Alpha * (.5-($X2 - floor($X2)));
548
         $Color = $this->allocateColor($this->Picture,$R,$G,$B,$AlphaA);
549
         imageline($this->Picture,floor($X2)+1,ceil($Y1),floor($X2)+1,floor($Y2),$Color);
550
        } 
551
552
       if ( $Y2 > floor($Y2) )
553
        {
554
         $AlphaA = $Alpha * (.5-($Y2 - floor($Y2)));
555
         $Color = $this->allocateColor($this->Picture,$R,$G,$B,$AlphaA);
556
         imageline($this->Picture,ceil($X1),floor($Y2)+1,floor($X2),floor($Y2)+1,$Color);
557
        }
558
      }
559
560
     if ( $BorderR != -1 )
561
      $this->drawRectangle($X1,$Y1,$X2,$Y2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$Ticks,"NoAngle"=>$NoAngle));
562
563
     $this->Shadow = $RestoreShadow;
564
    }
565
566
   /* Draw a rectangular marker of the specified size */
567
   function drawRectangleMarker($X,$Y,$Format="")
568
    {
569
     $Size = isset($Format["Size"]) ? $Format["Size"] : 4;
570
571
     $HalfSize = floor($Size/2);
572
     $this->drawFilledRectangle($X-$HalfSize,$Y-$HalfSize,$X+$HalfSize,$Y+$HalfSize,$Format);
573
    }
574
575
   /* Drawn a spline based on the bezier function */
576
   function drawSpline($Coordinates,$Format="")
577
    {
578
     $R		= isset($Format["R"]) ? $Format["R"] : 0;
579
     $G		= isset($Format["G"]) ? $Format["G"] : 0;
580
     $B		= isset($Format["B"]) ? $Format["B"] : 0;
581
     $Alpha	= isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
582
     $Force	= isset($Format["Force"]) ? $Format["Force"] : 30;
583
     $Forces	= isset($Format["Forces"]) ? $Format["Forces"] : NULL;
584
     $ShowC	= isset($Format["ShowControl"]) ? $Format["ShowControl"] : FALSE;
585
     $Ticks	= isset($Format["Ticks"]) ? $Format["Ticks"] : NULL;
586
     $PathOnly	= isset($Format["PathOnly"]) ? $Format["PathOnly"] : FALSE;
587
     $Weight	= isset($Format["Weight"]) ? $Format["Weight"] : NULL;
588
589
     $Cpt = NULL; $Mode = NULL; $Result = "";
590
     for($i=1;$i<=count($Coordinates)-1;$i++)
591
      {
592
       $X1 = $Coordinates[$i-1][0]; $Y1 = $Coordinates[$i-1][1];
593
       $X2 = $Coordinates[$i][0];   $Y2 = $Coordinates[$i][1];
594
595
       if ( $Forces != NULL ) { $Force = $Forces[$i]; }
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $Forces of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
596
597
       /* First segment */
598
       if ( $i == 1 )
599
        { $Xv1 = $X1; $Yv1 = $Y1; }
600
       else
601
        {
602
         $Angle1 = $this->getAngle($XLast,$YLast,$X1,$Y1);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getAngle() does only exist in the following sub-classes of pDraw: pImage. 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...
603
         $Angle2 = $this->getAngle($X1,$Y1,$X2,$Y2);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getAngle() does only exist in the following sub-classes of pDraw: pImage. 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...
604
         $XOff = cos($Angle2 * PI / 180) * $Force + $X1;
605
         $YOff = sin($Angle2 * PI / 180) * $Force + $Y1;
606
607
         $Xv1 = cos($Angle1 * PI / 180) * $Force + $XOff;
608
         $Yv1 = sin($Angle1 * PI / 180) * $Force + $YOff;
609
        }
610
611
       /* Last segment */
612
       if ( $i == count($Coordinates)-1 )
613
        { $Xv2 = $X2; $Yv2 = $Y2; }
614
       else
615
        {
616
         $Angle1 = $this->getAngle($X2,$Y2,$Coordinates[$i+1][0],$Coordinates[$i+1][1]);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getAngle() does only exist in the following sub-classes of pDraw: pImage. 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...
617
         $Angle2 = $this->getAngle($X1,$Y1,$X2,$Y2);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getAngle() does only exist in the following sub-classes of pDraw: pImage. 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...
618
         $XOff = cos(($Angle2+180) * PI / 180) * $Force + $X2;
619
         $YOff = sin(($Angle2+180) * PI / 180) * $Force + $Y2;
620
621
         $Xv2 = cos(($Angle1+180) * PI / 180) * $Force + $XOff;
622
         $Yv2 = sin(($Angle1+180) * PI / 180) * $Force + $YOff;
623
        }
624
625
       $Path = $this->drawBezier($X1,$Y1,$X2,$Y2,$Xv1,$Yv1,$Xv2,$Yv2,$Format);
626
       if ($PathOnly) { $Result[] = $Path; }
627
628
       $XLast = $X1; $YLast = $Y1;
629
      }
630
631
     return($Result);
632
    }
633
634
   /* Draw a bezier curve with two controls points */
635
   function drawBezier($X1,$Y1,$X2,$Y2,$Xv1,$Yv1,$Xv2,$Yv2,$Format="")
636
    {
637
     $R		= isset($Format["R"]) ? $Format["R"] : 0;
638
     $G		= isset($Format["G"]) ? $Format["G"] : 0;
639
     $B		= isset($Format["B"]) ? $Format["B"] : 0;
640
     $Alpha	= isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
641
     $ShowC	= isset($Format["ShowControl"]) ? $Format["ShowControl"] : FALSE;
642
     $Segments	= isset($Format["Segments"]) ? $Format["Segments"] : NULL;
643
     $Ticks	= isset($Format["Ticks"]) ? $Format["Ticks"] : NULL;
644
     $NoDraw    = isset($Format["NoDraw"]) ? $Format["NoDraw"] : FALSE;
645
     $PathOnly  = isset($Format["PathOnly"]) ? $Format["PathOnly"] : FALSE;
646
     $Weight    = isset($Format["Weight"]) ? $Format["Weight"] : NULL;
647
     $DrawArrow		= isset($Format["DrawArrow"]) ? $Format["DrawArrow"] : FALSE;
648
     $ArrowSize		= isset($Format["ArrowSize"]) ? $Format["ArrowSize"] : 10;
649
     $ArrowRatio	= isset($Format["ArrowRatio"]) ? $Format["ArrowRatio"] : .5;
650
     $ArrowTwoHeads	= isset($Format["ArrowTwoHeads"]) ? $Format["ArrowTwoHeads"] : FALSE;
651
652
     if ( $Segments == NULL )
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $Segments of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
653
      {
654
       $Length    = $this->getLength($X1,$Y1,$X2,$Y2);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getLength() does only exist in the following sub-classes of pDraw: pImage. 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...
655
       $Precision = ($Length*125)/1000;
656
      }
657
     else
658
      $Precision = $Segments;
659
660
     $P[0]["X"] = $X1;  $P[0]["Y"] = $Y1;
661
     $P[1]["X"] = $Xv1; $P[1]["Y"] = $Yv1;
662
     $P[2]["X"] = $Xv2; $P[2]["Y"] = $Yv2;
663
     $P[3]["X"] = $X2;  $P[3]["Y"] = $Y2;
664
665
     /* Compute the bezier points */
666
     $Q = ""; $ID = 0; $Path = "";
667
     for($i=0;$i<=$Precision;$i=$i+1)
668
      {
669
       $u = $i / $Precision;
670
671
       $C    = "";
672
       $C[0] = (1 - $u) * (1 - $u) * (1 - $u);
673
       $C[1] = ($u * 3) * (1 - $u) * (1 - $u);
674
       $C[2] = 3 * $u * $u * (1 - $u);
675
       $C[3] = $u * $u * $u;
676
677
       for($j=0;$j<=3;$j++)
678
        {
679
         if ( !isset($Q[$ID]) ) { $Q[$ID] = ""; }
680
         if ( !isset($Q[$ID]["X"]) ) { $Q[$ID]["X"] = 0; }
681
         if ( !isset($Q[$ID]["Y"]) ) { $Q[$ID]["Y"] = 0; }
682
683
         $Q[$ID]["X"] = $Q[$ID]["X"] + $P[$j]["X"] * $C[$j];
684
         $Q[$ID]["Y"] = $Q[$ID]["Y"] + $P[$j]["Y"] * $C[$j];
685
        }
686
       $ID++;
687
      }        
688
     $Q[$ID]["X"] = $X2; $Q[$ID]["Y"] = $Y2;
689
690
     if ( !$NoDraw )
691
      {
692
       /* Display the control points */
693
       if ( $ShowC && !$PathOnly )
694
        {
695
         $Xv1 = floor($Xv1); $Yv1 = floor($Yv1); $Xv2 = floor($Xv2); $Yv2 = floor($Yv2);
696
697
         $this->drawLine($X1,$Y1,$X2,$Y2,array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>30));
698
699
         $MyMarkerSettings = array("R"=>255,"G"=>0,"B"=>0,"BorderR"=>255,"BorderB"=>255,"BorderG"=>255,"Size"=>4);
700
         $this->drawRectangleMarker($Xv1,$Yv1,$MyMarkerSettings);
701
         $this->drawText($Xv1+4,$Yv1,"v1");
702
         $MyMarkerSettings = array("R"=>0,"G"=>0,"B"=>255,"BorderR"=>255,"BorderB"=>255,"BorderG"=>255,"Size"=>4);
703
         $this->drawRectangleMarker($Xv2,$Yv2,$MyMarkerSettings);
704
         $this->drawText($Xv2+4,$Yv2,"v2");
705
        }
706
707
       /* Draw the bezier */
708
       $LastX = NULL; $LastY = NULL; $Cpt = NULL; $Mode = NULL; $ArrowS = NULL;
709
       foreach ($Q as $Key => $Point)
0 ignored issues
show
Bug introduced by
The expression $Q of type string is not traversable.
Loading history...
710
        {
711
         $X = $Point["X"]; $Y = $Point["Y"];
712
713
         /* Get the first segment */
714
         if ( $ArrowS == NULL && $LastX != NULL && $LastY != NULL )
715
          { $ArrowS["X2"] = $LastX; $ArrowS["Y2"] = $LastY; $ArrowS["X1"] = $X; $ArrowS["Y1"] = $Y; }
716
717
         if ( $LastX != NULL && $LastY != NULL && !$PathOnly)
718
          list($Cpt,$Mode) = $this->drawLine($LastX,$LastY,$X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Cpt"=>$Cpt,"Mode"=>$Mode,"Weight"=>$Weight));
719
720
         /* Get the last segment */
721
         $ArrowE["X1"] = $LastX; $ArrowE["Y1"] = $LastY; $ArrowE["X2"] = $X; $ArrowE["Y2"] = $Y;
722
723
         $LastX = $X; $LastY = $Y;
724
        }
725
726
       if ( $DrawArrow && !$PathOnly )
727
        {
728
         $ArrowSettings = array("FillR"=>$R,"FillG"=>$G,"FillB"=>$B,"Alpha"=>$Alpha,"Size"=>$ArrowSize,"Ratio"=>$ArrowRatio);
729
         if ( $ArrowTwoHeads )
730
          $this->drawArrow($ArrowS["X1"],$ArrowS["Y1"],$ArrowS["X2"],$ArrowS["Y2"],$ArrowSettings);
731
732
         $this->drawArrow($ArrowE["X1"],$ArrowE["Y1"],$ArrowE["X2"],$ArrowE["Y2"],$ArrowSettings);
733
        }
734
      }
735
     return($Q);
736
    }
737
738
   /* Draw a line between two points */
739
   function drawLine($X1,$Y1,$X2,$Y2,$Format="")
740
    {
741
     $R		= isset($Format["R"]) ? $Format["R"] : 0;
742
     $G		= isset($Format["G"]) ? $Format["G"] : 0;
743
     $B		= isset($Format["B"]) ? $Format["B"] : 0;
744
     $Alpha	= isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
745
     $Ticks	= isset($Format["Ticks"]) ? $Format["Ticks"] : NULL;
746
     $Cpt	= isset($Format["Cpt"]) ? $Format["Cpt"] : 1;
747
     $Mode	= isset($Format["Mode"]) ? $Format["Mode"] : 1;
748
     $Weight	= isset($Format["Weight"]) ? $Format["Weight"] : NULL;
749
     $Threshold	= isset($Format["Threshold"]) ? $Format["Threshold"] : NULL;
750
751
     if ( $this->Antialias == FALSE && $Ticks == NULL )
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $Ticks of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
752
      {
753
       if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 )
754
        {
755
         $ShadowColor = $this->allocateColor($this->Picture,$this->ShadowR,$this->ShadowG,$this->ShadowB,$this->Shadowa);
756
         imageline($this->Picture,$X1+$this->ShadowX,$Y1+$this->ShadowY,$X2+$this->ShadowX,$Y2+$this->ShadowY,$ShadowColor);
757
        }
758
759
       $Color = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha);
760
       imageline($this->Picture,$X1,$Y1,$X2,$Y2,$Color);
761
       return(0);
762
      }
763
764
     $Distance = sqrt(($X2-$X1)*($X2-$X1)+($Y2-$Y1)*($Y2-$Y1));  
765
     if ( $Distance == 0 ) { return(-1); }
766
767
     /* Derivative algorithm for overweighted lines, re-route to polygons primitives */
768
     if ( $Weight != NULL )
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $Weight of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
769
      {
770
       $Angle        = $this->getAngle($X1,$Y1,$X2,$Y2);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getAngle() does only exist in the following sub-classes of pDraw: pImage. 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...
771
       $PolySettings = array ("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"BorderAlpha"=>$Alpha);
772
773
       if ( $Ticks == NULL )
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $Ticks of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
774
        {
775
         $Points   = ""; 
776
         $Points[] = cos(deg2rad($Angle-90)) * $Weight + $X1; $Points[] = sin(deg2rad($Angle-90)) * $Weight + $Y1;
777
         $Points[] = cos(deg2rad($Angle+90)) * $Weight + $X1; $Points[] = sin(deg2rad($Angle+90)) * $Weight + $Y1;
778
         $Points[] = cos(deg2rad($Angle+90)) * $Weight + $X2; $Points[] = sin(deg2rad($Angle+90)) * $Weight + $Y2;
779
         $Points[] = cos(deg2rad($Angle-90)) * $Weight + $X2; $Points[] = sin(deg2rad($Angle-90)) * $Weight + $Y2;
780
781
         $this->drawPolygon($Points,$PolySettings);
782
        }
783
       else
784
        {
785
         for($i=0;$i<=$Distance;$i=$i+$Ticks*2)
786
          {
787
           $Xa = (($X2-$X1)/$Distance) * $i + $X1; $Ya = (($Y2-$Y1)/$Distance) * $i + $Y1;
788
           $Xb = (($X2-$X1)/$Distance) * ($i+$Ticks) + $X1; $Yb = (($Y2-$Y1)/$Distance) * ($i+$Ticks) + $Y1;
789
790
           $Points   = ""; 
791
           $Points[] = cos(deg2rad($Angle-90)) * $Weight + $Xa; $Points[] = sin(deg2rad($Angle-90)) * $Weight + $Ya;
792
           $Points[] = cos(deg2rad($Angle+90)) * $Weight + $Xa; $Points[] = sin(deg2rad($Angle+90)) * $Weight + $Ya;
793
           $Points[] = cos(deg2rad($Angle+90)) * $Weight + $Xb; $Points[] = sin(deg2rad($Angle+90)) * $Weight + $Yb;
794
           $Points[] = cos(deg2rad($Angle-90)) * $Weight + $Xb; $Points[] = sin(deg2rad($Angle-90)) * $Weight 	+ $Yb;
795
796
           $this->drawPolygon($Points,$PolySettings);
797
          }
798
        }
799
800
       return(1);
801
      }
802
803
     $XStep = ($X2-$X1) / $Distance;
804
     $YStep = ($Y2-$Y1) / $Distance;
805
806
     for($i=0;$i<=$Distance;$i++)
807
      {
808
       $X = $i * $XStep + $X1;
809
       $Y = $i * $YStep + $Y1;
810
811
       $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha);
812
813
       if ( $Threshold != NULL )
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $Threshold of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
814
        {
815
         foreach($Threshold as $Key => $Parameters)
0 ignored issues
show
Bug introduced by
The expression $Threshold of type string is not traversable.
Loading history...
816
          {
817
           if ( $Y <= $Parameters["MinX"] && $Y >= $Parameters["MaxX"])
818
            {
819
             if ( isset($Parameters["R"]) ) { $RT = $Parameters["R"]; } else { $RT = 0; }
820
             if ( isset($Parameters["G"]) ) { $GT = $Parameters["G"]; } else { $GT = 0; }
821
             if ( isset($Parameters["B"]) ) { $BT = $Parameters["B"]; } else { $BT = 0; }
822
             if ( isset($Parameters["Alpha"]) ) { $AlphaT = $Parameters["Alpha"]; } else { $AlphaT = 0; }
823
             $Color = array("R"=>$RT,"G"=>$GT,"B"=>$BT,"Alpha"=>$AlphaT);
824
            }
825
          }
826
        }
827
828
       if ( $Ticks != NULL )
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $Ticks of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
829
        {
830
         if ( $Cpt % $Ticks == 0 )
831
          { $Cpt = 0; if ( $Mode == 1 ) { $Mode = 0; } else { $Mode = 1; } }
832
833
         if ( $Mode == 1 )
834
          $this->drawAntialiasPixel($X,$Y,$Color);
835
836
         $Cpt++;
837
        }
838
       else
839
        $this->drawAntialiasPixel($X,$Y,$Color);
840
      }
841
842
     return(array($Cpt,$Mode));
843
    }
844
845
   /* Draw a circle */
846
   function drawCircle($Xc,$Yc,$Height,$Width,$Format="")
847
    {
848
     $R	    = isset($Format["R"]) ? $Format["R"] : 0;
849
     $G	    = isset($Format["G"]) ? $Format["G"] : 0;
850
     $B	    = isset($Format["B"]) ? $Format["B"] : 0;
851
     $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
852
     $Ticks = isset($Format["Ticks"]) ? $Format["Ticks"] : NULL;
853
854
     $Height	= abs($Height);
855
     $Width	= abs($Width);
856
857
     if ( $Height == 0 ) { $Height = 1; }
858
     if ( $Width == 0 )  { $Width = 1; }
859
     $Xc = floor($Xc); $Yc = floor($Yc);
860
861
     $RestoreShadow = $this->Shadow;
862
     if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 )
863
      {
864
       $this->Shadow = FALSE;
865
       $this->drawCircle($Xc+$this->ShadowX,$Yc+$this->ShadowY,$Height,$Width,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa,"Ticks"=>$Ticks));
866
      }
867
868
     if ( $Width == 0 ) { $Width = $Height; }
869
     if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; }
870
     if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; }
871
     if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; }
872
873
     $Step = 360 / (2 * PI * max($Width,$Height));
874
     $Mode = 1; $Cpt = 1;
875
     for($i=0;$i<=360;$i=$i+$Step)
876
      {
877
       $X = cos($i*PI/180) * $Height + $Xc;
878
       $Y = sin($i*PI/180) * $Width + $Yc;
879
880
       if ( $Ticks != NULL )
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $Ticks of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
881
        {
882
         if ( $Cpt % $Ticks == 0 )
883
          { $Cpt = 0; if ( $Mode == 1 ) { $Mode = 0; } else { $Mode = 1; } }
884
885
         if ( $Mode == 1 )
886
          $this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
887
888
         $Cpt++;
889
        }
890
       else
891
        $this->drawAntialiasPixel($X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
892
893
      }
894
     $this->Shadow = $RestoreShadow;
895
    }
896
897
   /* Draw a filled circle */
898
   function drawFilledCircle($X,$Y,$Radius,$Format="")
899
    {
900
     $R			= isset($Format["R"]) ? $Format["R"] : 0;
901
     $G			= isset($Format["G"]) ? $Format["G"] : 0;
902
     $B			= isset($Format["B"]) ? $Format["B"] : 0;
903
     $Alpha		= isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
904
     $BorderR		= isset($Format["BorderR"]) ? $Format["BorderR"] : -1;
905
     $BorderG		= isset($Format["BorderG"]) ? $Format["BorderG"] : -1;
906
     $BorderB		= isset($Format["BorderB"]) ? $Format["BorderB"] : -1;
907
     $BorderAlpha	= isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : $Alpha;
908
     $Ticks     	= isset($Format["Ticks"]) ? $Format["Ticks"] : NULL;
909
     $Surrounding 	= isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL;
910
911
     if ( $Radius == 0 ) { $Radius = 1; }
912
     if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; }
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $Surrounding of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
913
     $X = floor($X); $Y = floor($Y);
914
915
     $Radius = abs($Radius);
916
917
     $RestoreShadow = $this->Shadow;
918
     if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 )
919
      {
920
       $this->Shadow = FALSE;
921
       $this->drawFilledCircle($X+$this->ShadowX,$Y+$this->ShadowY,$Radius,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa,"Ticks"=>$Ticks));
922
      }
923
924
     $this->Mask  = "";
925
     $Color = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha);
926
     for ($i=0; $i<=$Radius*2; $i++)
927
      {
928
       $Slice  = sqrt($Radius * $Radius - ($Radius - $i) * ($Radius - $i));
929
       $XPos   = floor($Slice);
930
       $YPos   = $Y + $i - $Radius;
931
       $AAlias = $Slice - floor($Slice);
932
933
       $this->Mask[$X-$XPos][$YPos] = TRUE;
934
       $this->Mask[$X+$XPos][$YPos] = TRUE;
935
       imageline($this->Picture,$X-$XPos,$YPos,$X+$XPos,$YPos,$Color);
936
      }
937
     if ( $this->Antialias )
938
      $this->drawCircle($X,$Y,$Radius,$Radius,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks));
939
940
     $this->Mask = "";
941
942
     if ( $BorderR != -1 )
943
      $this->drawCircle($X,$Y,$Radius,$Radius,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$Ticks));
944
945
     $this->Shadow	= $RestoreShadow;
946
    }
947
948
   /* Write text */
949
   function drawText($X,$Y,$Text,$Format="")
950
    {
951
     $R			= isset($Format["R"]) ? $Format["R"] : $this->FontColorR;
952
     $G			= isset($Format["G"]) ? $Format["G"] : $this->FontColorG;
953
     $B			= isset($Format["B"]) ? $Format["B"] : $this->FontColorB;
954
     $Angle		= isset($Format["Angle"]) ? $Format["Angle"] : 0;
955
     $Align		= isset($Format["Align"]) ? $Format["Align"] : TEXT_ALIGN_BOTTOMLEFT;
956
     $Alpha		= isset($Format["Alpha"]) ? $Format["Alpha"] : $this->FontColorA;
957
     $FontName		= isset($Format["FontName"]) ? $Format["FontName"] : $this->FontName;
958
     $FontSize		= isset($Format["FontSize"]) ? $Format["FontSize"] : $this->FontSize;
959
     $ShowOrigine	= isset($Format["ShowOrigine"]) ? $Format["ShowOrigine"] : FALSE;
960
     $TOffset		= isset($Format["TOffset"]) ? $Format["TOffset"] : 2;
961
     $DrawBox		= isset($Format["DrawBox"]) ? $Format["DrawBox"] : FALSE;
962
     $DrawBoxBorder	= isset($Format["DrawBoxBorder"]) ? $Format["DrawBoxBorder"] : TRUE;
963
     $BorderOffset	= isset($Format["BorderOffset"]) ? $Format["BorderOffset"] : 6;
964
     $BoxRounded	= isset($Format["BoxRounded"]) ? $Format["BoxRounded"] : FALSE;
965
     $RoundedRadius	= isset($Format["RoundedRadius"]) ? $Format["RoundedRadius"] : 6;
966
     $BoxR		= isset($Format["BoxR"]) ? $Format["BoxR"] : 255;
967
     $BoxG		= isset($Format["BoxG"]) ? $Format["BoxG"] : 255;
968
     $BoxB		= isset($Format["BoxB"]) ? $Format["BoxB"] : 255;
969
     $BoxAlpha		= isset($Format["BoxAlpha"]) ? $Format["BoxAlpha"] : 50;
970
     $BoxSurrounding	= isset($Format["BoxSurrounding"]) ? $Format["BoxSurrounding"] : "";
971
     $BoxBorderR	= isset($Format["BoxR"]) ? $Format["BoxR"] : 0;
972
     $BoxBorderG	= isset($Format["BoxG"]) ? $Format["BoxG"] : 0;
973
     $BoxBorderB	= isset($Format["BoxB"]) ? $Format["BoxB"] : 0;
974
     $BoxBorderAlpha	= isset($Format["BoxAlpha"]) ? $Format["BoxAlpha"] : 50;
975
     $NoShadow		= isset($Format["NoShadow"]) ? $Format["NoShadow"] : FALSE;
976
977
     $Shadow = $this->Shadow;
978
     if ( $NoShadow ) { $this->Shadow = FALSE; }
979
980
     if ( $BoxSurrounding != "" ) { $BoxBorderR = $BoxR - $BoxSurrounding; $BoxBorderG = $BoxG - $BoxSurrounding; $BoxBorderB = $BoxB - $BoxSurrounding; $BoxBorderAlpha = $BoxAlpha; }
981
982
     if ( $ShowOrigine )
983
      {
984
       $MyMarkerSettings = array("R"=>255,"G"=>0,"B"=>0,"BorderR"=>255,"BorderB"=>255,"BorderG"=>255,"Size"=>4);
985
       $this->drawRectangleMarker($X,$Y,$MyMarkerSettings);
986
      }
987
988
     $TxtPos = $this->getTextBox($X,$Y,$FontName,$FontSize,$Angle,$Text);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getTextBox() does only exist in the following sub-classes of pDraw: pImage. 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...
989
990
     if ( $DrawBox && ($Angle == 0 || $Angle == 90 || $Angle == 180 || $Angle == 270))
991
      {
992
       $T[0]["X"]=0;$T[0]["Y"]=0;$T[1]["X"]=0;$T[1]["Y"]=0;$T[2]["X"]=0;$T[2]["Y"]=0;$T[3]["X"]=0;$T[3]["Y"]=0;
993
       if ( $Angle == 0 ) { $T[0]["X"]=-$TOffset;$T[0]["Y"]=$TOffset;$T[1]["X"]=$TOffset;$T[1]["Y"]=$TOffset;$T[2]["X"]=$TOffset;$T[2]["Y"]=-$TOffset;$T[3]["X"]=-$TOffset;$T[3]["Y"]=-$TOffset; }
994
995
       $X1 = min($TxtPos[0]["X"],$TxtPos[1]["X"],$TxtPos[2]["X"],$TxtPos[3]["X"]) - $BorderOffset + 3;
996
       $Y1 = min($TxtPos[0]["Y"],$TxtPos[1]["Y"],$TxtPos[2]["Y"],$TxtPos[3]["Y"]) - $BorderOffset;
997
       $X2 = max($TxtPos[0]["X"],$TxtPos[1]["X"],$TxtPos[2]["X"],$TxtPos[3]["X"]) + $BorderOffset + 3;
998
       $Y2 = max($TxtPos[0]["Y"],$TxtPos[1]["Y"],$TxtPos[2]["Y"],$TxtPos[3]["Y"]) + $BorderOffset - 3;
999
1000
       $X1 = $X1 - $TxtPos[$Align]["X"] + $X + $T[0]["X"];
1001
       $Y1 = $Y1 - $TxtPos[$Align]["Y"] + $Y + $T[0]["Y"];
1002
       $X2 = $X2 - $TxtPos[$Align]["X"] + $X + $T[0]["X"];
1003
       $Y2 = $Y2 - $TxtPos[$Align]["Y"] + $Y + $T[0]["Y"];
1004
1005
       $Settings = array("R"=>$BoxR,"G"=>$BoxG,"B"=>$BoxB,"Alpha"=>$BoxAlpha,"BorderR"=>$BoxBorderR,"BorderG"=>$BoxBorderG,"BorderB"=>$BoxBorderB,"BorderAlpha"=>$BoxBorderAlpha);
1006
1007
       if ( $BoxRounded )
1008
        { $this->drawRoundedFilledRectangle($X1,$Y1,$X2,$Y2,$RoundedRadius,$Settings); }
1009
       else
1010
        { $this->drawFilledRectangle($X1,$Y1,$X2,$Y2,$Settings); }
1011
      }
1012
1013
     $X = $X - $TxtPos[$Align]["X"] + $X;
1014
     $Y = $Y - $TxtPos[$Align]["Y"] + $Y;
1015
1016
     if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 )
1017
      {
1018
       $C_ShadowColor = $this->allocateColor($this->Picture,$this->ShadowR,$this->ShadowG,$this->ShadowB,$this->Shadowa);
1019
       imagettftext($this->Picture,$FontSize,$Angle,$X+$this->ShadowX,$Y+$this->ShadowY,$C_ShadowColor,$FontName,$Text);
1020
      }
1021
1022
     $C_TextColor = $this->AllocateColor($this->Picture,$R,$G,$B,$Alpha);
1023
     imagettftext($this->Picture,$FontSize,$Angle,$X,$Y,$C_TextColor,$FontName,$Text);
1024
1025
     $this->Shadow = $Shadow;
1026
1027
     return($TxtPos);
1028
    }
1029
1030
   /* Draw a gradient within a defined area */
1031
   function drawGradientArea($X1,$Y1,$X2,$Y2,$Direction,$Format="")
1032
    {
1033
     $StartR	= isset($Format["StartR"]) ? $Format["StartR"] : 90;
1034
     $StartG	= isset($Format["StartG"]) ? $Format["StartG"] : 90;
1035
     $StartB	= isset($Format["StartB"]) ? $Format["StartB"] : 90;
1036
     $EndR	= isset($Format["EndR"]) ? $Format["EndR"] : 0;
1037
     $EndG	= isset($Format["EndG"]) ? $Format["EndG"] : 0;
1038
     $EndB	= isset($Format["EndB"]) ? $Format["EndB"] : 0;
1039
     $Alpha	= isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
1040
     $Levels	= isset($Format["Levels"]) ? $Format["Levels"] : NULL;
1041
1042
     $Shadow = $this->Shadow;
1043
     $this->Shadow = FALSE;
1044
1045
     if ( $StartR == $EndR && $StartG == $EndG && $StartB == $EndB )
1046
      {
1047
       $this->drawFilledRectangle($X1,$Y1,$X2,$Y2,array("R"=>$StartR,"G"=>$StartG,"B"=>$StartB,"Alpha"=>$Alpha));
1048
       return(0);
1049
      }
1050
1051
     if ( $Levels != NULL )
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $Levels of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
1052
      { $EndR=$StartR+$Levels; $EndG=$StartG+$Levels; $EndB=$StartB+$Levels; }
1053
1054
     if ($X1 > $X2) { list($X1, $X2) = array($X2, $X1); }
1055
     if ($Y1 > $Y2) { list($Y1, $Y2) = array($Y2, $Y1); }
1056
1057
     if ( $Direction == DIRECTION_VERTICAL )   { $Width = abs($Y2-$Y1); }
1058
     if ( $Direction == DIRECTION_HORIZONTAL ) { $Width = abs($X2-$X1); }
1059
1060
     $Step     = max(abs($EndR-$StartR),abs($EndG-$StartG),abs($EndB-$StartB));
1061
     $StepSize = $Width/$Step;
1062
     $RStep    = ($EndR-$StartR)/$Step;
1063
     $GStep    = ($EndG-$StartG)/$Step;
1064
     $BStep    = ($EndB-$StartB)/$Step;
1065
1066
     $R=$StartR;$G=$StartG;$B=$StartB;
1067
     switch($Direction)
1068
      {
1069
       case DIRECTION_VERTICAL:
1070
        $StartY = $Y1; $EndY = floor($Y2)+1; $LastY2 = $StartY;
1071
        for($i=0;$i<=$Step;$i++)
1072
         {
1073
          $Y2 = floor($StartY + ($i * $StepSize));
1074
1075
          if ($Y2 > $EndY) { $Y2 = $EndY; }
1076
          if (($Y1 != $Y2 && $Y1 < $Y2) || $Y2 == $EndY)
1077
           {
1078
            $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha);
1079
            $this->drawFilledRectangle($X1,$Y1,$X2,$Y2,$Color);
1080
            $LastY2 = max($LastY2,$Y2);
1081
            $Y1 = $Y2+1;
1082
           }
1083
          $R = $R + $RStep; $G = $G + $GStep; $B = $B + $BStep;
1084
         }
1085
        if ( $LastY2 < $EndY && isset($Color)) { for ($i=$LastY2+1;$i<=$EndY;$i++) { $this->drawLine($X1,$i,$X2,$i,$Color); } }
1086
        break;
1087
1088
       case DIRECTION_HORIZONTAL:
1089
        $StartX = $X1; $EndX = $X2;
1090
        for($i=0;$i<=$Step;$i++)
1091
         {
1092
          $X2 = floor($StartX + ($i * $StepSize));
1093
1094
          if ($X2 > $EndX) { $X2 = $EndX; }
1095
          if (($X1 != $X2 && $X1 < $X2) || $X2 == $EndX)
1096
           {
1097
            $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha);
1098
            $this->drawFilledRectangle($X1,$Y1,$X2,$Y2,$Color);
1099
            $X1 = $X2+1;
1100
           }
1101
          $R = $R + $RStep; $G = $G + $GStep; $B = $B + $BStep; 
1102
         }
1103
        if ( $X2 < $EndX && isset($Color)) { $this->drawFilledRectangle($X2,$Y1,$EndX,$Y2,$Color); }
1104
        break;
1105
      }
1106
1107
     $this->Shadow = $Shadow;
1108
1109
    }
1110
1111
   /* Draw an aliased pixel */
1112
   function drawAntialiasPixel($X,$Y,$Format="")
1113
    {
1114
     $R     = isset($Format["R"]) ? $Format["R"] : 0;
1115
     $G     = isset($Format["G"]) ? $Format["G"] : 0;
1116
     $B     = isset($Format["B"]) ? $Format["B"] : 0;
1117
     $Alpha = isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
1118
1119
     if ( $X < 0 || $Y < 0 || $X >= $this->XSize || $Y >= $this->YSize )
1120
      return(-1);
1121
1122
     if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; }
1123
     if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; }
1124
     if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; }
1125
1126
     if ( !$this->Antialias )
1127
      {
1128
       if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 )
1129
        {
1130
         $ShadowColor = $this->allocateColor($this->Picture,$this->ShadowR,$this->ShadowG,$this->ShadowB,$this->Shadowa);
1131
         imagesetpixel($this->Picture,$X+$this->ShadowX,$Y+$this->ShadowY,$ShadowColor);
1132
        }
1133
1134
       $PlotColor = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha);
1135
       imagesetpixel($this->Picture,$X,$Y,$PlotColor);
1136
1137
       return(0);
1138
      }
1139
1140
     $Plot = "";
1141
     $Xi   = floor($X);
1142
     $Yi   = floor($Y);
1143
1144
     if ( $Xi == $X && $Yi == $Y)
1145
      {
1146
       if ( $Alpha == 100 )
1147
        $this->drawAlphaPixel($X,$Y,100,$R,$G,$B);
1148
       else
1149
        $this->drawAlphaPixel($X,$Y,$Alpha,$R,$G,$B);
1150
      }
1151
     else
1152
      {
1153
       $Alpha1 = (((1 - ($X - floor($X))) * (1 - ($Y - floor($Y))) * 100) / 100) * $Alpha;
1154
       if ( $Alpha1 > $this->AntialiasQuality ) { $this->drawAlphaPixel($Xi,$Yi,$Alpha1,$R,$G,$B); }
1155
1156
       $Alpha2 = ((($X - floor($X)) * (1 - ($Y - floor($Y))) * 100) / 100) * $Alpha;
1157
       if ( $Alpha2 > $this->AntialiasQuality ) { $this->drawAlphaPixel($Xi+1,$Yi,$Alpha2,$R,$G,$B); }
1158
1159
       $Alpha3 = (((1 - ($X - floor($X))) * ($Y - floor($Y)) * 100) / 100) * $Alpha;
1160
       if ( $Alpha3 > $this->AntialiasQuality ) { $this->drawAlphaPixel($Xi,$Yi+1,$Alpha3,$R,$G,$B); }
1161
1162
       $Alpha4 = ((($X - floor($X)) * ($Y - floor($Y)) * 100) / 100) * $Alpha;
1163
       if ( $Alpha4 > $this->AntialiasQuality ) { $this->drawAlphaPixel($Xi+1,$Yi+1,$Alpha4,$R,$G,$B); }
1164
      }
1165
    }
1166
1167
   /* Draw a semi-transparent pixel */
1168
   function drawAlphaPixel($X,$Y,$Alpha,$R,$G,$B)
1169
    {
1170
     if ( isset($this->Mask[$X])) { if ( isset($this->Mask[$X][$Y]) ) { return(0); } }
1171
1172
     if ( $X < 0 || $Y < 0 || $X >= $this->XSize || $Y >= $this->YSize )
1173
      return(-1);
1174
1175
     if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; }
1176
     if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; }
1177
     if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; }
1178
1179
     if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 )
1180
      {
1181
       $AlphaFactor = floor(($Alpha / 100) * $this->Shadowa);
1182
       $ShadowColor = $this->allocateColor($this->Picture,$this->ShadowR,$this->ShadowG,$this->ShadowB,$AlphaFactor);
1183
       imagesetpixel($this->Picture,$X+$this->ShadowX,$Y+$this->ShadowY,$ShadowColor);
1184
      }
1185
1186
     $C_Aliased = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha);
1187
     imagesetpixel($this->Picture,$X,$Y,$C_Aliased);
1188
    }
1189
1190
   /* Convert apha to base 10 */
1191
   function convertAlpha($AlphaValue)
1192
    { return((127/100)*(100-$AlphaValue)); }
1193
1194
   /* Allocate a color with transparency */
1195
   function allocateColor($Picture,$R,$G,$B,$Alpha=100)
1196
    {
1197
     if ( $R < 0 ) { $R = 0; } if ( $R > 255 ) { $R = 255; }
1198
     if ( $G < 0 ) { $G = 0; } if ( $G > 255 ) { $G = 255; }
1199
     if ( $B < 0 ) { $B = 0; } if ( $B > 255 ) { $B = 255; }
1200
     if ( $Alpha < 0 )  { $Alpha = 0; }
1201
     if ( $Alpha > 100) { $Alpha = 100; }
1202
1203
     $Alpha = $this->convertAlpha($Alpha);
1204
     return(imagecolorallocatealpha($Picture,$R,$G,$B,$Alpha));
1205
    }
1206
1207
   /* Load a PNG file and draw it over the chart */
1208
   function drawFromPNG($X,$Y,$FileName)
1209
    { $this->drawFromPicture(1,$FileName,$X,$Y); }
1210
1211
   /* Load a GIF file and draw it over the chart */
1212
   function drawFromGIF($X,$Y,$FileName)
1213
    { $this->drawFromPicture(2,$FileName,$X,$Y); }
1214
1215
   /* Load a JPEG file and draw it over the chart */
1216
   function drawFromJPG($X,$Y,$FileName)
1217
    { $this->drawFromPicture(3,$FileName,$X,$Y); }
1218
1219
   function getPicInfo($FileName)
1220
    {
1221
     $Infos  = getimagesize($FileName);
1222
     $Width  = $Infos[0];
1223
     $Height = $Infos[1];
1224
     $Type   = $Infos["mime"];
1225
1226
     if ( $Type == "image/png") { $Type = 1; }
1227
     if ( $Type == "image/gif") { $Type = 2; }
1228
     if ( $Type == "image/jpeg ") { $Type = 3; }
1229
1230
     return(array($Width,$Height,$Type));
1231
    }
1232
1233
   /* Generic loader function for external pictures */
1234
   function drawFromPicture($PicType,$FileName,$X,$Y)
1235
    {
1236
     if ( file_exists($FileName))
1237
      {
1238
       list($Width,$Height) = $this->getPicInfo($FileName);
1239
1240
       if ( $PicType == 1 )
1241
        { $Raster = imagecreatefrompng($FileName); }
1242
       elseif ( $PicType == 2 )
1243
        { $Raster = imagecreatefromgif($FileName); }
1244
       elseif ( $PicType == 3 )
1245
        { $Raster = imagecreatefromjpeg($FileName); }
1246
       else
1247
        { return(0); }
1248
1249
1250
       $RestoreShadow = $this->Shadow;
1251
       if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 )
1252
        {
1253
         $this->Shadow = FALSE;
1254
         if ( $PicType == 3 )
1255
          $this->drawFilledRectangle($X+$this->ShadowX,$Y+$this->ShadowY,$X+$Width+$this->ShadowX,$Y+$Height+$this->ShadowY,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa));
1256
         else
1257
          {
1258
           $TranparentID = imagecolortransparent($Raster);
1259
           for ($Xc=0;$Xc<=$Width-1;$Xc++)
1260
            {
1261
             for ($Yc=0;$Yc<=$Height-1;$Yc++)
1262
              {
1263
               $RGBa   = imagecolorat($Raster,$Xc,$Yc);
1264
               $Values = imagecolorsforindex($Raster,$RGBa);
1265
               if ( $Values["alpha"] < 120 )
1266
                {
1267
                 $AlphaFactor = floor(($this->Shadowa / 100) * ((100 / 127) * (127-$Values["alpha"])));
1268
                 $this->drawAlphaPixel($X+$Xc+$this->ShadowX,$Y+$Yc+$this->ShadowY,$AlphaFactor,$this->ShadowR,$this->ShadowG,$this->ShadowB);
1269
                }
1270
              }
1271
            }
1272
          }
1273
        }
1274
       $this->Shadow = $RestoreShadow;
1275
1276
       imagecopy($this->Picture,$Raster,$X,$Y,0,0,$Width,$Height);
1277
       imagedestroy($Raster);
1278
      }
1279
    }
1280
1281
   /* Draw an arrow */
1282
   function drawArrow($X1,$Y1,$X2,$Y2,$Format="")
1283
    {
1284
     $FillR	= isset($Format["FillR"]) ? $Format["FillR"] : 0;
1285
     $FillG	= isset($Format["FillG"]) ? $Format["FillG"] : 0;
1286
     $FillB	= isset($Format["FillB"]) ? $Format["FillB"] : 0;
1287
     $BorderR	= isset($Format["BorderR"]) ? $Format["BorderR"] : $FillR;
1288
     $BorderG	= isset($Format["BorderG"]) ? $Format["BorderG"] : $FillG;
1289
     $BorderB	= isset($Format["BorderB"]) ? $Format["BorderB"] : $FillB;
1290
     $Alpha	= isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
1291
     $Size	= isset($Format["Size"]) ? $Format["Size"] : 10;
1292
     $Ratio	= isset($Format["Ratio"]) ? $Format["Ratio"] : .5;
1293
     $TwoHeads	= isset($Format["TwoHeads"]) ? $Format["TwoHeads"] : FALSE;
1294
     $Ticks	= isset($Format["Ticks"]) ? $Format["Ticks"] : FALSE;
1295
1296
     /* Calculate the line angle */
1297
     $Angle = $this->getAngle($X1,$Y1,$X2,$Y2);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getAngle() does only exist in the following sub-classes of pDraw: pImage. 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...
1298
1299
     /* Override Shadow support, this will be managed internally */
1300
     $RestoreShadow = $this->Shadow;
1301
     if ( $this->Shadow && $this->ShadowX != 0 && $this->ShadowY != 0 )
1302
      {
1303
       $this->Shadow = FALSE;
1304
       $this->drawArrow($X1+$this->ShadowX,$Y1+$this->ShadowY,$X2+$this->ShadowX,$Y2+$this->ShadowY,array("FillR"=>$this->ShadowR,"FillG"=>$this->ShadowG,"FillB"=>$this->ShadowB,"Alpha"=>$this->Shadowa,"Size"=>$Size,"Ratio"=>$Ratio,"TwoHeads"=>$TwoHeads,"Ticks"=>$Ticks));
1305
      }
1306
1307
     /* Draw the 1st Head */
1308
     $TailX = cos(($Angle-180)*PI/180)*$Size+$X2;
1309
     $TailY = sin(($Angle-180)*PI/180)*$Size+$Y2;
1310
1311
     $Points	= "";
1312
     $Points[]  = $X2; $Points[]  = $Y2;
1313
     $Points[]	= cos(($Angle-90)*PI/180)*$Size*$Ratio+$TailX; $Points[] = sin(($Angle-90)*PI/180)*$Size*$Ratio+$TailY;
1314
     $Points[]	= cos(($Angle-270)*PI/180)*$Size*$Ratio+$TailX; $Points[] = sin(($Angle-270)*PI/180)*$Size*$Ratio+$TailY;
1315
     $Points[]  = $X2; $Points[]  = $Y2;
1316
1317
     /* Visual correction */
1318
     if ($Angle == 180 || $Angle == 360 ) { $Points[4] = $Points[2]; }
1319
     if ($Angle == 90 || $Angle == 270 ) { $Points[5] = $Points[3]; }
1320
1321
     $ArrowColor = $this->allocateColor($this->Picture,$FillR,$FillG,$FillB,$Alpha);
1322
     ImageFilledPolygon($this->Picture,$Points,4,$ArrowColor);
1323
1324
     $this->drawLine($Points[0],$Points[1],$Points[2],$Points[3],array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha));
1325
     $this->drawLine($Points[2],$Points[3],$Points[4],$Points[5],array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha));
1326
     $this->drawLine($Points[0],$Points[1],$Points[4],$Points[5],array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha));
1327
1328
     /* Draw the second head */
1329
     if ( $TwoHeads )
1330
      {
1331
       $Angle = $this->getAngle($X2,$Y2,$X1,$Y1);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getAngle() does only exist in the following sub-classes of pDraw: pImage. 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...
1332
1333
       $TailX2 = cos(($Angle-180)*PI/180)*$Size+$X1;
1334
       $TailY2 = sin(($Angle-180)*PI/180)*$Size+$Y1;
1335
1336
       $Points   = "";
1337
       $Points[] = $X1; $Points[]  = $Y1;
1338
       $Points[] = cos(($Angle-90)*PI/180)*$Size*$Ratio+$TailX2; $Points[] = sin(($Angle-90)*PI/180)*$Size*$Ratio+$TailY2;
1339
       $Points[] = cos(($Angle-270)*PI/180)*$Size*$Ratio+$TailX2; $Points[] = sin(($Angle-270)*PI/180)*$Size*$Ratio+$TailY2;
1340
       $Points[] = $X1; $Points[]  = $Y1;
1341
1342
       /* Visual correction */
1343
       if ($Angle == 180 || $Angle == 360 ) { $Points[4] = $Points[2]; }
1344
       if ($Angle == 90 || $Angle == 270 ) { $Points[5] = $Points[3]; }
1345
1346
       $ArrowColor = $this->allocateColor($this->Picture,$FillR,$FillG,$FillB,$Alpha);
1347
       ImageFilledPolygon($this->Picture,$Points,4,$ArrowColor);
1348
1349
       $this->drawLine($Points[0],$Points[1],$Points[2],$Points[3],array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha));
1350
       $this->drawLine($Points[2],$Points[3],$Points[4],$Points[5],array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha));
1351
       $this->drawLine($Points[0],$Points[1],$Points[4],$Points[5],array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha));
1352
1353
       $this->drawLine($TailX,$TailY,$TailX2,$TailY2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha,"Ticks"=>$Ticks));
1354
      }
1355
     else
1356
      $this->drawLine($X1,$Y1,$TailX,$TailY,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha,"Ticks"=>$Ticks));
1357
1358
     /* Re-enable shadows */
1359
     $this->Shadow = $RestoreShadow;
1360
    }
1361
1362
   /* Draw a label with associated arrow */
1363
   function drawArrowLabel($X1,$Y1,$Text,$Format="")
1364
    {
1365
     $FillR    = isset($Format["FillR"]) ? $Format["FillR"] : 0;
1366
     $FillG    = isset($Format["FillG"]) ? $Format["FillG"] : 0;
1367
     $FillB    = isset($Format["FillB"]) ? $Format["FillB"] : 0;
1368
     $BorderR  = isset($Format["BorderR"]) ? $Format["BorderR"] : $FillR;
1369
     $BorderG  = isset($Format["BorderG"]) ? $Format["BorderG"] : $FillG;
1370
     $BorderB  = isset($Format["BorderB"]) ? $Format["BorderB"] : $FillB;
1371
     $FontName = isset($Format["FontName"]) ? $Format["FontName"] : $this->FontName;
1372
     $FontSize = isset($Format["FontSize"]) ? $Format["FontSize"] : $this->FontSize;
1373
     $Alpha    = isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
1374
     $Length   = isset($Format["Length"]) ? $Format["Length"] : 50;
1375
     $Angle    = isset($Format["Angle"]) ? $Format["Angle"] : 315;
1376
     $Size     = isset($Format["Size"]) ? $Format["Size"] : 10;
1377
     $Position = isset($Format["Position"]) ? $Format["Position"] : POSITION_TOP;
1378
     $RoundPos = isset($Format["RoundPos"]) ? $Format["RoundPos"] : FALSE;
1379
     $Ticks    = isset($Format["Ticks"]) ? $Format["Ticks"] : NULL;
1380
1381
     $Angle = $Angle % 360;
1382
1383
     $X2 = sin(($Angle+180)*PI/180)*$Length+$X1;
1384
     $Y2 = cos(($Angle+180)*PI/180)*$Length+$Y1;
1385
1386
     if ( $RoundPos && $Angle > 0 && $Angle < 180 ) { $Y2 = ceil($Y2); }
1387
     if ( $RoundPos && $Angle > 180 ) { $Y2 = floor($Y2); }
1388
1389
     $this->drawArrow($X2,$Y2,$X1,$Y1,$Format);
1390
1391
     $Size	= imagettfbbox($FontSize,0,$FontName,$Text);
1392
     $TxtWidth	= max(abs($Size[2]-$Size[0]),abs($Size[0]-$Size[6]));
1393
     $TxtHeight	= max(abs($Size[1]-$Size[7]),abs($Size[3]-$Size[1]));
1394
1395
     if ( $Angle > 0 && $Angle < 180 )
1396
      {
1397
       $this->drawLine($X2,$Y2,$X2-$TxtWidth,$Y2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha,"Ticks"=>$Ticks));
1398
       if ( $Position == POSITION_TOP )
1399
        $this->drawText($X2,$Y2-2,$Text,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha,"Align"=>TEXT_ALIGN_BOTTOMRIGHT));
1400
       else
1401
        $this->drawText($X2,$Y2+4,$Text,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha,"Align"=>TEXT_ALIGN_TOPRIGHT));
1402
      }
1403
     else
1404
      {
1405
       $this->drawLine($X2,$Y2,$X2+$TxtWidth,$Y2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha,"Ticks"=>$Ticks));
1406
       if ( $Position == POSITION_TOP )
1407
        $this->drawText($X2,$Y2-2,$Text,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha));
1408
       else
1409
        $this->drawText($X2,$Y2+4,$Text,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$Alpha,"Align"=>TEXT_ALIGN_TOPLEFT));
1410
      }
1411
    }
1412
1413
   /* Draw a progress bar filled with specified % */
1414
   function drawProgress($X,$Y,$Percent,$Format="")
1415
    {
1416
     if ( $Percent > 100 ) { $Percent = 100; }
1417
     if ( $Percent < 0 ) { $Percent = 0; }
1418
1419
     $Width	= isset($Format["Width"]) ? $Format["Width"] : 200;
1420
     $Height	= isset($Format["Height"]) ? $Format["Height"] : 20;
1421
     $Orientation = isset($Format["Orientation"]) ? $Format["Orientation"] : ORIENTATION_HORIZONTAL;
1422
     $ShowLabel = isset($Format["ShowLabel"]) ? $Format["ShowLabel"] : FALSE;
1423
     $LabelPos	= isset($Format["LabelPos"]) ? $Format["LabelPos"] : LABEL_POS_INSIDE;
1424
     $Margin    = isset($Format["Margin"]) ? $Format["Margin"] : 10;
1425
     $R		= isset($Format["R"]) ? $Format["R"] : 130;
1426
     $G		= isset($Format["G"]) ? $Format["G"] : 130;
1427
     $B		= isset($Format["B"]) ? $Format["B"] : 130;
1428
     $RFade	= isset($Format["RFade"]) ? $Format["RFade"] : -1;
1429
     $GFade	= isset($Format["GFade"]) ? $Format["GFade"] : -1;
1430
     $BFade	= isset($Format["BFade"]) ? $Format["BFade"] : -1;
1431
     $BorderR	= isset($Format["BorderR"]) ? $Format["BorderR"] : $R;
1432
     $BorderG	= isset($Format["BorderG"]) ? $Format["BorderG"] : $G;
1433
     $BorderB	= isset($Format["BorderB"]) ? $Format["BorderB"] : $B;
1434
     $BoxBorderR = isset($Format["BoxBorderR"]) ? $Format["BoxBorderR"] : 0;
1435
     $BoxBorderG = isset($Format["BoxBorderG"]) ? $Format["BoxBorderG"] : 0;
1436
     $BoxBorderB = isset($Format["BoxBorderB"]) ? $Format["BoxBorderB"] : 0;
1437
     $BoxBackR	= isset($Format["BoxBackR"]) ? $Format["BoxBackR"] : 255;
1438
     $BoxBackG	= isset($Format["BoxBackG"]) ? $Format["BoxBackG"] : 255;
1439
     $BoxBackB	= isset($Format["BoxBackB"]) ? $Format["BoxBackB"] : 255;
1440
     $Alpha	= isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
1441
     $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL;
1442
     $BoxSurrounding = isset($Format["BoxSurrounding"]) ? $Format["BoxSurrounding"] : NULL;
1443
     $NoAngle	= isset($Format["NoAngle"]) ? $Format["NoAngle"] : FALSE;
1444
1445
     if ( $RFade != -1 && $GFade != -1 && $BFade != -1 )
1446
      {
1447
       $RFade = (($RFade-$R)/100)*$Percent+$R;
1448
       $GFade = (($GFade-$G)/100)*$Percent+$G;
1449
       $BFade = (($BFade-$B)/100)*$Percent+$B;
1450
      }
1451
1452
     if ( $Surrounding != NULL ) { $BorderR = $R + $Surrounding; $BorderG = $G + $Surrounding; $BorderB = $B + $Surrounding; }
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $Surrounding of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
1453
     if ( $BoxSurrounding != NULL ) { $BoxBorderR = $BoxBackR + $Surrounding; $BoxBorderG = $BoxBackG + $Surrounding; $BoxBorderB = $BoxBackB + $Surrounding; }
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $BoxSurrounding of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
1454
1455
     if ( $Orientation == ORIENTATION_VERTICAL )
1456
      {
1457
       $InnerHeight = (($Height-2)/100)*$Percent;
1458
       $this->drawFilledRectangle($X,$Y,$X+$Width,$Y-$Height,array("R"=>$BoxBackR,"G"=>$BoxBackG,"B"=>$BoxBackB,"BorderR"=>$BoxBorderR,"BorderG"=>$BoxBorderG,"BorderB"=>$BoxBorderB,"NoAngle"=>$NoAngle));
1459
1460
       $RestoreShadow = $this->Shadow; $this->Shadow  = FALSE;
1461
       if ( $RFade != -1 && $GFade != -1 && $BFade != -1 )
1462
        {
1463
         $GradientOptions = array("StartR"=>$RFade,"StartG"=>$GFade,"StartB"=>$BFade,"EndR"=>$R,"EndG"=>$G,"EndB"=>$B);
1464
         $this->drawGradientArea($X+1,$Y-1,$X+$Width-1,$Y-$InnerHeight,DIRECTION_VERTICAL,$GradientOptions);
1465
1466
         if ( $Surrounding )
1467
          $this->drawRectangle($X+1,$Y-1,$X+$Width-1,$Y-$InnerHeight,array("R"=>255,"G"=>255,"B"=>255,"Alpha"=>$Surrounding));
1468
        }
1469
       else
1470
        $this->drawFilledRectangle($X+1,$Y-1,$X+$Width-1,$Y-$InnerHeight,array("R"=>$R,"G"=>$G,"B"=>$B,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB));
1471
1472
       $this->Shadow = $RestoreShadow;
1473
1474
       if ( $ShowLabel && $LabelPos == LABEL_POS_BOTTOM )	{ $this->drawText($X+($Width/2),$Y+$Margin,$Percent."%",array("Align"=>TEXT_ALIGN_TOPMIDDLE)); }
1475
       if ( $ShowLabel && $LabelPos == LABEL_POS_TOP )		{ $this->drawText($X+($Width/2),$Y-$Height-$Margin,$Percent."%",array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); }
1476
       if ( $ShowLabel && $LabelPos == LABEL_POS_INSIDE )	{ $this->drawText($X+($Width/2),$Y-$InnerHeight-$Margin,$Percent."%",array("Align"=>TEXT_ALIGN_MIDDLELEFT,"Angle"=>90)); }
1477
       if ( $ShowLabel && $LabelPos == LABEL_POS_CENTER )	{ $this->drawText($X+($Width/2),$Y-($Height/2),$Percent."%",array("Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"Angle"=>90)); }
1478
      }
1479
     else
1480
      {
1481
       if ( $Percent == 100 )
1482
        $InnerWidth = $Width-1;
1483
       else
1484
        $InnerWidth = (($Width-2)/100)*$Percent;
1485
1486
       $this->drawFilledRectangle($X,$Y,$X+$Width,$Y+$Height,array("R"=>$BoxBackR,"G"=>$BoxBackG,"B"=>$BoxBackB,"BorderR"=>$BoxBorderR,"BorderG"=>$BoxBorderG,"BorderB"=>$BoxBorderB,"NoAngle"=>$NoAngle));
1487
1488
       $RestoreShadow = $this->Shadow; $this->Shadow  = FALSE;
1489
       if ( $RFade != -1 && $GFade != -1 && $BFade != -1 )
1490
        {
1491
         $GradientOptions = array("StartR"=>$R,"StartG"=>$G,"StartB"=>$B,"EndR"=>$RFade,"EndG"=>$GFade,"EndB"=>$BFade);
1492
         $this->drawGradientArea($X+1,$Y+1,$X+$InnerWidth,$Y+$Height-1,DIRECTION_HORIZONTAL,$GradientOptions);
1493
1494
         if ( $Surrounding )
1495
          $this->drawRectangle($X+1,$Y+1,$X+$InnerWidth,$Y+$Height-1,array("R"=>255,"G"=>255,"B"=>255,"Alpha"=>$Surrounding));
1496
        }
1497
       else
1498
        $this->drawFilledRectangle($X+1,$Y+1,$X+$InnerWidth,$Y+$Height-1,array("R"=>$R,"G"=>$G,"B"=>$B,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB));
1499
 
1500
       $this->Shadow = $RestoreShadow;
1501
1502
       if ( $ShowLabel && $LabelPos == LABEL_POS_LEFT )		{ $this->drawText($X-$Margin,$Y+($Height/2),$Percent."%",array("Align"=>TEXT_ALIGN_MIDDLERIGHT)); }
1503
       if ( $ShowLabel && $LabelPos == LABEL_POS_RIGHT )	{ $this->drawText($X+$Width+$Margin,$Y+($Height/2),$Percent."%",array("Align"=>TEXT_ALIGN_MIDDLELEFT)); }
1504
       if ( $ShowLabel && $LabelPos == LABEL_POS_CENTER )	{ $this->drawText($X+($Width/2),$Y+($Height/2),$Percent."%",array("Align"=>TEXT_ALIGN_MIDDLEMIDDLE)); }
1505
       if ( $ShowLabel && $LabelPos == LABEL_POS_INSIDE )	{ $this->drawText($X+$InnerWidth+$Margin,$Y+($Height/2),$Percent."%",array("Align"=>TEXT_ALIGN_MIDDLELEFT)); }
1506
      }
1507
    }
1508
1509
   /* Get the legend box size */
1510
   function getLegendSize($Format="")
1511
    {
1512
     $FontName		= isset($Format["FontName"]) ? $Format["FontName"] : $this->FontName;
1513
     $FontSize		= isset($Format["FontSize"]) ? $Format["FontSize"] : $this->FontSize;
1514
     $BoxSize		= isset($Format["BoxSize"]) ? $Format["BoxSize"] : 5;
1515
     $Margin		= isset($Format["Margin"]) ? $Format["Margin"] : 5;
1516
     $Style		= isset($Format["Style"]) ? $Format["Style"] : LEGEND_ROUND;
1517
     $Mode		= isset($Format["Mode"]) ? $Format["Mode"] : LEGEND_VERTICAL;
1518
     $BoxWidth		= isset($Format["BoxWidth"]) ? $Format["BoxWidth"] : 5;
1519
     $BoxHeight		= isset($Format["BoxHeight"]) ? $Format["BoxHeight"] : 5;
1520
     $IconAreaWidth	= isset($Format["IconAreaWidth"]) ? $Format["IconAreaWidth"] : $BoxWidth;
1521
     $IconAreaHeight	= isset($Format["IconAreaHeight"]) ? $Format["IconAreaHeight"] : $BoxHeight;
1522
     $XSpacing		= isset($Format["XSpacing"]) ? $Format["XSpacing"] : 5;
1523
1524
     $Data = $this->DataSet->getData();
1525
1526
     foreach($Data["Series"] as $SerieName => $Serie)
1527
      {
1528
       if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] && isset($Serie["Picture"]))
1529
        {
1530
         list($PicWidth,$PicHeight) = $this->getPicInfo($Serie["Picture"]);
1531
         if ( $IconAreaWidth < $PicWidth ) { $IconAreaWidth = $PicWidth; }
1532
         if ( $IconAreaHeight < $PicHeight ) { $IconAreaHeight = $PicHeight; }
1533
        }
1534
      }
1535
1536
     $YStep = max($this->FontSize,$IconAreaHeight) + 5;
1537
     $XStep = $IconAreaWidth + 5;
1538
     $XStep = $XSpacing;
1539
1540
     $X=100; $Y=100;
1541
1542
     $Boundaries = ""; $Boundaries["L"] = $X; $Boundaries["T"] = $Y; $Boundaries["R"] = 0; $Boundaries["B"] = 0; $vY = $Y; $vX = $X;
1543
     foreach($Data["Series"] as $SerieName => $Serie)
1544
      {
1545
       if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] )
1546
        {
1547
         if ( $Mode == LEGEND_VERTICAL )
1548
          {
1549
           $BoxArray = $this->getTextBox($vX+$IconAreaWidth+4,$vY+$IconAreaHeight/2,$FontName,$FontSize,0,$Serie["Description"]);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getTextBox() does only exist in the following sub-classes of pDraw: pImage. 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...
1550
1551
           if ( $Boundaries["T"] > $BoxArray[2]["Y"]+$IconAreaHeight/2 ) { $Boundaries["T"] = $BoxArray[2]["Y"]+$IconAreaHeight/2; }
1552
           if ( $Boundaries["R"] < $BoxArray[1]["X"]+2 ) { $Boundaries["R"] = $BoxArray[1]["X"]+2; }
1553
           if ( $Boundaries["B"] < $BoxArray[1]["Y"]+2+$IconAreaHeight/2 ) { $Boundaries["B"] = $BoxArray[1]["Y"]+2+$IconAreaHeight/2; }
1554
1555
           $Lines = preg_split("/\n/",$Serie["Description"]);
1556
           $vY = $vY + max($this->FontSize*count($Lines),$IconAreaHeight) + 5;
1557
          }
1558
         elseif ( $Mode == LEGEND_HORIZONTAL )
1559
          {
1560
           $Lines = preg_split("/\n/",$Serie["Description"]);
1561
           $Width = "";
1562
           foreach($Lines as $Key => $Value)
1563
            {
1564
             $BoxArray = $this->getTextBox($vX+$IconAreaWidth+6,$Y+$IconAreaHeight/2+(($this->FontSize+3)*$Key),$FontName,$FontSize,0,$Value);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getTextBox() does only exist in the following sub-classes of pDraw: pImage. 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...
1565
1566
             if ( $Boundaries["T"] > $BoxArray[2]["Y"]+$IconAreaHeight/2 ) { $Boundaries["T"] = $BoxArray[2]["Y"]+$IconAreaHeight/2; }
1567
             if ( $Boundaries["R"] < $BoxArray[1]["X"]+2 ) { $Boundaries["R"] = $BoxArray[1]["X"]+2; }
1568
             if ( $Boundaries["B"] < $BoxArray[1]["Y"]+2+$IconAreaHeight/2 ) { $Boundaries["B"] = $BoxArray[1]["Y"]+2+$IconAreaHeight/2; }
1569
1570
             $Width[] = $BoxArray[1]["X"];
1571
            }
1572
1573
           $vX=max($Width)+$XStep;
1574
          }
1575
        }
1576
      }
1577
     $vY=$vY-$YStep; $vX=$vX-$XStep;
1578
1579
     $TopOffset  = $Y - $Boundaries["T"];
1580
     if ( $Boundaries["B"]-($vY+$IconAreaHeight) < $TopOffset ) { $Boundaries["B"] = $vY+$IconAreaHeight+$TopOffset; }
1581
1582
     $Width  = ($Boundaries["R"]+$Margin) - ($Boundaries["L"]-$Margin);
1583
     $Height = ($Boundaries["B"]+$Margin) - ($Boundaries["T"]-$Margin);
1584
1585
     return(array("Width"=>$Width,"Height"=>$Height));
1586
    }
1587
1588
   /* Draw the legend of the active series */
1589
   function drawLegend($X,$Y,$Format="")
1590
    {
1591
     $Family	= isset($Format["Family"]) ? $Format["Family"] : LEGEND_FAMILY_BOX;
1592
     $FontName	= isset($Format["FontName"]) ? $Format["FontName"] : $this->FontName;
1593
     $FontSize	= isset($Format["FontSize"]) ? $Format["FontSize"] : $this->FontSize;
1594
     $FontR	= isset($Format["FontR"]) ? $Format["FontR"] : $this->FontColorR;
1595
     $FontG	= isset($Format["FontG"]) ? $Format["FontG"] : $this->FontColorG;
1596
     $FontB	= isset($Format["FontB"]) ? $Format["FontB"] : $this->FontColorB;
1597
     $BoxWidth	= isset($Format["BoxWidth"]) ? $Format["BoxWidth"] : 5;
1598
     $BoxHeight	= isset($Format["BoxHeight"]) ? $Format["BoxHeight"] : 5;
1599
     $IconAreaWidth	= isset($Format["IconAreaWidth"]) ? $Format["IconAreaWidth"] : $BoxWidth;
1600
     $IconAreaHeight	= isset($Format["IconAreaHeight"]) ? $Format["IconAreaHeight"] : $BoxHeight;
1601
     $XSpacing	= isset($Format["XSpacing"]) ? $Format["XSpacing"] : 5;
1602
     $Margin	= isset($Format["Margin"]) ? $Format["Margin"] : 5;
1603
     $R		= isset($Format["R"]) ? $Format["R"] : 200;
1604
     $G		= isset($Format["G"]) ? $Format["G"] : 200;
1605
     $B		= isset($Format["B"]) ? $Format["B"] : 200;
1606
     $Alpha	= isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
1607
     $BorderR	= isset($Format["BorderR"]) ? $Format["BorderR"] : 255;
1608
     $BorderG	= isset($Format["BorderG"]) ? $Format["BorderG"] : 255;
1609
     $BorderB	= isset($Format["BorderB"]) ? $Format["BorderB"] : 255;
1610
     $Surrounding = isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL;
1611
     $Style	= isset($Format["Style"]) ? $Format["Style"] : LEGEND_ROUND;
1612
     $Mode	= isset($Format["Mode"]) ? $Format["Mode"] : LEGEND_VERTICAL;
1613
1614
     if ( $Surrounding != NULL ) { $BorderR = $R + $Surrounding; $BorderG = $G + $Surrounding; $BorderB = $B + $Surrounding; }
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $Surrounding of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
1615
1616
     $Data = $this->DataSet->getData();
1617
1618
     foreach($Data["Series"] as $SerieName => $Serie)
1619
      {
1620
       if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] && isset($Serie["Picture"]))
1621
        {
1622
         list($PicWidth,$PicHeight) = $this->getPicInfo($Serie["Picture"]);
1623
         if ( $IconAreaWidth < $PicWidth ) { $IconAreaWidth = $PicWidth; }
1624
         if ( $IconAreaHeight < $PicHeight ) { $IconAreaHeight = $PicHeight; }
1625
        }
1626
      }
1627
1628
     $YStep = max($this->FontSize,$IconAreaHeight) + 5;
1629
     $XStep = $IconAreaWidth + 5;
1630
     $XStep = $XSpacing;
1631
1632
     $Boundaries = ""; $Boundaries["L"] = $X; $Boundaries["T"] = $Y; $Boundaries["R"] = 0; $Boundaries["B"] = 0; $vY = $Y; $vX = $X;
1633
     foreach($Data["Series"] as $SerieName => $Serie)
1634
      {
1635
       if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] )
1636
        {
1637
         if ( $Mode == LEGEND_VERTICAL )
1638
          {
1639
           $BoxArray = $this->getTextBox($vX+$IconAreaWidth+4,$vY+$IconAreaHeight/2,$FontName,$FontSize,0,$Serie["Description"]);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getTextBox() does only exist in the following sub-classes of pDraw: pImage. 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...
1640
1641
           if ( $Boundaries["T"] > $BoxArray[2]["Y"]+$IconAreaHeight/2 ) { $Boundaries["T"] = $BoxArray[2]["Y"]+$IconAreaHeight/2; }
1642
           if ( $Boundaries["R"] < $BoxArray[1]["X"]+2 ) { $Boundaries["R"] = $BoxArray[1]["X"]+2; }
1643
           if ( $Boundaries["B"] < $BoxArray[1]["Y"]+2+$IconAreaHeight/2 ) { $Boundaries["B"] = $BoxArray[1]["Y"]+2+$IconAreaHeight/2; }
1644
1645
           $Lines = preg_split("/\n/",$Serie["Description"]);
1646
           $vY = $vY + max($this->FontSize*count($Lines),$IconAreaHeight) + 5;
1647
          }
1648
         elseif ( $Mode == LEGEND_HORIZONTAL )
1649
          {
1650
           $Lines = preg_split("/\n/",$Serie["Description"]);
1651
           $Width = "";
1652
           foreach($Lines as $Key => $Value)
1653
            {
1654
             $BoxArray = $this->getTextBox($vX+$IconAreaWidth+6,$Y+$IconAreaHeight/2+(($this->FontSize+3)*$Key),$FontName,$FontSize,0,$Value);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getTextBox() does only exist in the following sub-classes of pDraw: pImage. 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...
1655
1656
             if ( $Boundaries["T"] > $BoxArray[2]["Y"]+$IconAreaHeight/2 ) { $Boundaries["T"] = $BoxArray[2]["Y"]+$IconAreaHeight/2; }
1657
             if ( $Boundaries["R"] < $BoxArray[1]["X"]+2 ) { $Boundaries["R"] = $BoxArray[1]["X"]+2; }
1658
             if ( $Boundaries["B"] < $BoxArray[1]["Y"]+2+$IconAreaHeight/2 ) { $Boundaries["B"] = $BoxArray[1]["Y"]+2+$IconAreaHeight/2; }
1659
1660
             $Width[] = $BoxArray[1]["X"];
1661
            }
1662
1663
           $vX=max($Width)+$XStep;
1664
          }
1665
        }
1666
      }
1667
     $vY=$vY-$YStep; $vX=$vX-$XStep;
1668
1669
     $TopOffset  = $Y - $Boundaries["T"];
1670
     if ( $Boundaries["B"]-($vY+$IconAreaHeight) < $TopOffset ) { $Boundaries["B"] = $vY+$IconAreaHeight+$TopOffset; }
1671
1672
     if ( $Style == LEGEND_ROUND )
1673
      $this->drawRoundedFilledRectangle($Boundaries["L"]-$Margin,$Boundaries["T"]-$Margin,$Boundaries["R"]+$Margin,$Boundaries["B"]+$Margin,$Margin,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB));
1674
     elseif ( $Style == LEGEND_BOX )
1675
      $this->drawFilledRectangle($Boundaries["L"]-$Margin,$Boundaries["T"]-$Margin,$Boundaries["R"]+$Margin,$Boundaries["B"]+$Margin,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB));
1676
1677
     $RestoreShadow = $this->Shadow; $this->Shadow = FALSE;
1678
     foreach($Data["Series"] as $SerieName => $Serie)
1679
      {
1680
       if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] )
1681
        {
1682
         $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"];
1683
         $Ticks = $Serie["Ticks"]; $Weight = $Serie["Weight"];
1684
1685
         if ( isset($Serie["Picture"]) )
1686
          {
1687
           $Picture = $Serie["Picture"];
1688
           list($PicWidth,$PicHeight) = $this->getPicInfo($Picture);
1689
           $PicX = $X+$IconAreaWidth/2; $PicY = $Y+$IconAreaHeight/2; 
1690
1691
           $this->drawFromPNG($PicX-$PicWidth/2,$PicY-$PicHeight/2,$Picture);
1692
          }
1693
         else
1694
          {
1695
           if ( $Family == LEGEND_FAMILY_BOX )
1696
            {
1697
             if ( $BoxWidth != $IconAreaWidth ) { $XOffset = floor(($IconAreaWidth-$BoxWidth)/2); } else { $XOffset = 0; }
1698
             if ( $BoxHeight != $IconAreaHeight ) { $YOffset = floor(($IconAreaHeight-$BoxHeight)/2); } else { $YOffset = 0; }
1699
1700
             $this->drawFilledRectangle($X+1+$XOffset,$Y+1+$YOffset,$X+$BoxWidth+$XOffset+1,$Y+$BoxHeight+1+$YOffset,array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>20));
1701
             $this->drawFilledRectangle($X+$XOffset,$Y+$YOffset,$X+$BoxWidth+$XOffset,$Y+$BoxHeight+$YOffset,array("R"=>$R,"G"=>$G,"B"=>$B,"Surrounding"=>20));
1702
            }
1703
           elseif ( $Family == LEGEND_FAMILY_CIRCLE )
1704
            {
1705
             $this->drawFilledCircle($X+1+$IconAreaWidth/2,$Y+1+$IconAreaHeight/2,min($IconAreaHeight/2,$IconAreaWidth/2),array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>20));
1706
             $this->drawFilledCircle($X+$IconAreaWidth/2,$Y+$IconAreaHeight/2,min($IconAreaHeight/2,$IconAreaWidth/2),array("R"=>$R,"G"=>$G,"B"=>$B,"Surrounding"=>20));
1707
            }
1708
           elseif ( $Family == LEGEND_FAMILY_LINE )
1709
            {
1710
             $this->drawLine($X+1,$Y+1+$IconAreaHeight/2,$X+1+$IconAreaWidth,$Y+1+$IconAreaHeight/2,array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>20,"Ticks"=>$Ticks,"Weight"=>$Weight));
1711
             $this->drawLine($X,$Y+$IconAreaHeight/2,$X+$IconAreaWidth,$Y+$IconAreaHeight/2,array("R"=>$R,"G"=>$G,"B"=>$B,"Ticks"=>$Ticks,"Weight"=>$Weight));
1712
            }
1713
          }
1714
1715
         if ( $Mode == LEGEND_VERTICAL )
1716
          {
1717
           $Lines = preg_split("/\n/",$Serie["Description"]);
1718
           foreach($Lines as $Key => $Value)
1719
            $this->drawText($X+$IconAreaWidth+4,$Y+$IconAreaHeight/2+(($this->FontSize+3)*$Key),$Value,array("R"=>$FontR,"G"=>$FontG,"B"=>$FontB,"Align"=>TEXT_ALIGN_MIDDLELEFT,"FontSize"=>$FontSize,"FontName"=>$FontName));
1720
1721
           $Y=$Y+max($this->FontSize*count($Lines),$IconAreaHeight) + 5;
1722
          }
1723
         elseif ( $Mode == LEGEND_HORIZONTAL )
1724
          {
1725
           $Lines = preg_split("/\n/",$Serie["Description"]);
1726
           $Width = "";
1727
           foreach($Lines as $Key => $Value)
1728
            {
1729
             $BoxArray = $this->drawText($X+$IconAreaWidth+4,$Y+$IconAreaHeight/2+(($this->FontSize+3)*$Key),$Value,array("R"=>$FontR,"G"=>$FontG,"B"=>$FontB,"Align"=>TEXT_ALIGN_MIDDLELEFT,"FontSize"=>$FontSize,"FontName"=>$FontName));
1730
             $Width[] = $BoxArray[1]["X"];
1731
            }
1732
           $X=max($Width)+2+$XStep;
1733
          }
1734
        }
1735
      }
1736
1737
1738
     $this->Shadow = $RestoreShadow;
1739
    }
1740
1741
   function drawScale($Format="")
1742
    {
1743
     $Pos		= isset($Format["Pos"]) ? $Format["Pos"] : SCALE_POS_LEFTRIGHT;
1744
     $Floating		= isset($Format["Floating"]) ? $Format["Floating"] : FALSE;
1745
     $Mode		= isset($Format["Mode"]) ? $Format["Mode"] : SCALE_MODE_FLOATING;
1746
     $RemoveXAxis	= isset($Format["RemoveXAxis"]) ? $Format["RemoveXAxis"] : FALSE;
1747
     $MinDivHeight	= isset($Format["MinDivHeight"]) ? $Format["MinDivHeight"] : 20;
1748
     $Factors		= isset($Format["Factors"]) ? $Format["Factors"] : array(1,2,5);
1749
     $ManualScale	= isset($Format["ManualScale"]) ? $Format["ManualScale"] : array("0"=>array("Min"=>-100,"Max"=>100));
1750
     $XMargin		= isset($Format["XMargin"]) ? $Format["XMargin"] : AUTO;
1751
     $YMargin		= isset($Format["YMargin"]) ? $Format["YMargin"] : 0;
1752
     $ScaleSpacing	= isset($Format["ScaleSpacing"]) ? $Format["ScaleSpacing"] : 15;
1753
     $InnerTickWidth	= isset($Format["InnerTickWidth"]) ? $Format["InnerTickWidth"] : 2;
1754
     $OuterTickWidth	= isset($Format["OuterTickWidth"]) ? $Format["OuterTickWidth"] : 2;
1755
     $DrawXLines	= isset($Format["DrawXLines"]) ? $Format["DrawXLines"] : TRUE;
1756
     $DrawYLines	= isset($Format["DrawYLines"]) ? $Format["DrawYLines"] : ALL;
1757
     $GridTicks		= isset($Format["GridTicks"]) ? $Format["GridTicks"] : 4;
1758
     $GridR		= isset($Format["GridR"]) ? $Format["GridR"] : 255;
1759
     $GridG		= isset($Format["GridG"]) ? $Format["GridG"] : 255;
1760
     $GridB		= isset($Format["GridB"]) ? $Format["GridB"] : 255;
1761
     $GridAlpha		= isset($Format["GridAlpha"]) ? $Format["GridAlpha"] : 40;
1762
     $AxisRo		= isset($Format["AxisR"]) ? $Format["AxisR"] : 0;
1763
     $AxisGo		= isset($Format["AxisG"]) ? $Format["AxisG"] : 0;
1764
     $AxisBo		= isset($Format["AxisB"]) ? $Format["AxisB"] : 0;
1765
     $AxisAlpha		= isset($Format["AxisAlpha"]) ? $Format["AxisAlpha"] : 100;
1766
     $TickRo		= isset($Format["TickR"]) ? $Format["TickR"] : 0;
1767
     $TickGo		= isset($Format["TickG"]) ? $Format["TickG"] : 0;
1768
     $TickBo		= isset($Format["TickB"]) ? $Format["TickB"] : 0;
1769
     $TickAlpha		= isset($Format["TickAlpha"]) ? $Format["TickAlpha"] : 100;
1770
     $DrawSubTicks	= isset($Format["DrawSubTicks"]) ? $Format["DrawSubTicks"] : FALSE;
1771
     $InnerSubTickWidth	= isset($Format["InnerSubTickWidth"]) ? $Format["InnerSubTickWidth"] : 0;
1772
     $OuterSubTickWidth	= isset($Format["OuterSubTickWidth"]) ? $Format["OuterSubTickWidth"] : 2;
1773
     $SubTickR		= isset($Format["SubTickR"]) ? $Format["SubTickR"] : 255;
1774
     $SubTickG		= isset($Format["SubTickG"]) ? $Format["SubTickG"] : 0;
1775
     $SubTickB		= isset($Format["SubTickB"]) ? $Format["SubTickB"] : 0;
1776
     $SubTickAlpha	= isset($Format["SubTickAlpha"]) ? $Format["SubTickAlpha"] : 100;
1777
     $AutoAxisLabels	= isset($Format["AutoAxisLabels"]) ? $Format["AutoAxisLabels"] : TRUE;
1778
     $XReleasePercent	= isset($Format["XReleasePercent"]) ? $Format["XReleasePercent"] : 1;
1779
     $DrawArrows	= isset($Format["DrawArrows"]) ? $Format["DrawArrows"] : FALSE;
1780
     $ArrowSize         = isset($Format["ArrowSize"]) ? $Format["ArrowSize"] : 8;
1781
     $CycleBackground	= isset($Format["CycleBackground"]) ? $Format["CycleBackground"] : FALSE;
1782
     $BackgroundR1	= isset($Format["BackgroundR1"]) ? $Format["BackgroundR1"] : 255;
1783
     $BackgroundG1	= isset($Format["BackgroundG1"]) ? $Format["BackgroundG1"] : 255;
1784
     $BackgroundB1	= isset($Format["BackgroundB1"]) ? $Format["BackgroundB1"] : 255;
1785
     $BackgroundAlpha1	= isset($Format["BackgroundAlpha1"]) ? $Format["BackgroundAlpha1"] : 20;
1786
     $BackgroundR2	= isset($Format["BackgroundR2"]) ? $Format["BackgroundR2"] : 230;
1787
     $BackgroundG2	= isset($Format["BackgroundG2"]) ? $Format["BackgroundG2"] : 230;
1788
     $BackgroundB2	= isset($Format["BackgroundB2"]) ? $Format["BackgroundB2"] : 230;
1789
     $BackgroundAlpha2	= isset($Format["BackgroundAlpha2"]) ? $Format["BackgroundAlpha2"] : 20;
1790
     $LabelingMethod	= isset($Format["LabelingMethod"]) ? $Format["LabelingMethod"] : LABELING_ALL;
1791
     $LabelSkip		= isset($Format["LabelSkip"]) ? $Format["LabelSkip"] : 0;
1792
     $LabelRotation	= isset($Format["LabelRotation"]) ? $Format["LabelRotation"] : 0;
1793
     $RemoveSkippedAxis	= isset($Format["RemoveSkippedAxis"]) ? $Format["RemoveSkippedAxis"] : FALSE;
1794
     $SkippedAxisTicks	= isset($Format["SkippedAxisTicks"]) ? $Format["SkippedAxisTicks"] : $GridTicks+2;
1795
     $SkippedAxisR	= isset($Format["SkippedAxisR"]) ? $Format["SkippedAxisR"] : $GridR;
1796
     $SkippedAxisG	= isset($Format["SkippedAxisG"]) ? $Format["SkippedAxisG"] : $GridG;
1797
     $SkippedAxisB	= isset($Format["SkippedAxisB"]) ? $Format["SkippedAxisB"] : $GridB;
1798
     $SkippedAxisAlpha	= isset($Format["SkippedAxisAlpha"]) ? $Format["SkippedAxisAlpha"] : $GridAlpha-30;
1799
     $SkippedTickR	= isset($Format["SkippedTickR"]) ? $Format["SkippedTickR"] : $TickRo;
1800
     $SkippedTickG	= isset($Format["SkippedTickG"]) ? $Format["SkippedTickG"] : $TickGo;
1801
     $SkippedTickB	= isset($Format["SkippedTicksB"]) ? $Format["SkippedTickB"] : $TickBo;
1802
     $SkippedTickAlpha	= isset($Format["SkippedTickAlpha"]) ? $Format["SkippedTickAlpha"] : $TickAlpha-80;
1803
     $SkippedInnerTickWidth	= isset($Format["SkippedInnerTickWidth"]) ? $Format["SkippedInnerTickWidth"] : 0;
1804
     $SkippedOuterTickWidth	= isset($Format["SkippedOuterTickWidth"]) ? $Format["SkippedOuterTickWidth"] : 2;
1805
1806
     /* Floating scale require X & Y margins to be set manually */
1807
     if ( $Floating && ( $XMargin == AUTO || $YMargin == 0 ) ) { $Floating = FALSE; }
1808
1809
     /* Skip a NOTICE event in case of an empty array */
1810
     if ( $DrawYLines == NONE || $DrawYLines == FALSE ) { $DrawYLines = array("zarma"=>"31"); }
1811
1812
     /* Define the color for the skipped elements */
1813
     $SkippedAxisColor = array("R"=>$SkippedAxisR,"G"=>$SkippedAxisG,"B"=>$SkippedAxisB,"Alpha"=>$SkippedAxisAlpha,"Ticks"=>$SkippedAxisTicks);
1814
     $SkippedTickColor = array("R"=>$SkippedTickR,"G"=>$SkippedTickG,"B"=>$SkippedTickB,"Alpha"=>$SkippedTickAlpha);
1815
1816
     $Data = $this->DataSet->getData();
1817
     if ( isset($Data["Abscissa"]) ) { $Abscissa = $Data["Abscissa"]; } else { $Abscissa = NULL; }
1818
1819
     /* Unset the abscissa axis, needed if we display multiple charts on the same picture */
1820
     if ( $Abscissa != NULL )
1821
      {
1822
       foreach($Data["Axis"] as $AxisID => $Parameters)
1823
        { if ($Parameters["Identity"] == AXIS_X) { unset($Data["Axis"][$AxisID]); } }
1824
      }
1825
1826
     /* Build the scale settings */
1827
     $GotXAxis = FALSE;
1828
     foreach($Data["Axis"] as $AxisID => $AxisParameter)
1829
      {
1830
       if ( $AxisParameter["Identity"] == AXIS_X ) { $GotXAxis = TRUE; }
1831
1832
       if ( $Pos == SCALE_POS_LEFTRIGHT && $AxisParameter["Identity"] == AXIS_Y)
1833
        { $Height = $this->GraphAreaY2-$this->GraphAreaY1 - $YMargin*2; }
1834
       elseif ( $Pos == SCALE_POS_LEFTRIGHT && $AxisParameter["Identity"] == AXIS_X)
1835
        { $Height = $this->GraphAreaX2-$this->GraphAreaX1; }
1836
       elseif ( $Pos == SCALE_POS_TOPBOTTOM && $AxisParameter["Identity"] == AXIS_Y)
1837
        { $Height = $this->GraphAreaX2-$this->GraphAreaX1 - $YMargin*2;; }
1838
       else
1839
        { $Height = $this->GraphAreaY2-$this->GraphAreaY1; }
1840
1841
       $AxisMin = ABSOLUTE_MAX; $AxisMax = OUT_OF_SIGHT;
1842
       if ( $Mode == SCALE_MODE_FLOATING || $Mode == SCALE_MODE_START0 )
1843
        {
1844
         foreach($Data["Series"] as $SerieID => $SerieParameter)
1845
          {
1846
           if ( $SerieParameter["Axis"] == $AxisID && $Data["Series"][$SerieID]["isDrawable"] && $Data["Abscissa"] != $SerieID)
1847
            {
1848
             $AxisMax = max($AxisMax,$Data["Series"][$SerieID]["Max"]);
1849
             $AxisMin = min($AxisMin,$Data["Series"][$SerieID]["Min"]);
1850
            }
1851
          }
1852
         $AutoMargin = (($AxisMax-$AxisMin)/100)*$XReleasePercent;
1853
1854
         $Data["Axis"][$AxisID]["Min"] = $AxisMin-$AutoMargin; $Data["Axis"][$AxisID]["Max"] = $AxisMax+$AutoMargin;
1855
         if ( $Mode == SCALE_MODE_START0 ) { $Data["Axis"][$AxisID]["Min"] = 0; }
1856
        }
1857
       elseif ( $Mode == SCALE_MODE_MANUAL )
1858
        {
1859
         if ( isset($ManualScale[$AxisID]["Min"]) && isset($ManualScale[$AxisID]["Max"]) )
1860
          {
1861
           $Data["Axis"][$AxisID]["Min"] = $ManualScale[$AxisID]["Min"];
1862
           $Data["Axis"][$AxisID]["Max"] = $ManualScale[$AxisID]["Max"];
1863
          }
1864
         else
1865
          { echo "Manual scale boundaries not set."; exit(); }
1866
        }
1867
       elseif ( $Mode == SCALE_MODE_ADDALL || $Mode == SCALE_MODE_ADDALL_START0 )
1868
        {
1869
         $Series = "";
1870
         foreach($Data["Series"] as $SerieID => $SerieParameter)
1871
          { if ( $SerieParameter["Axis"] == $AxisID && $SerieParameter["isDrawable"] && $Data["Abscissa"] != $SerieID ) { $Series[$SerieID] = count($Data["Series"][$SerieID]["Data"]); } }
1872
1873
         for ($ID=0;$ID<=max($Series)-1;$ID++)
1874
          {
1875
           $PointMin = 0; $PointMax = 0;
1876
           foreach($Series as $SerieID => $ValuesCount )
0 ignored issues
show
Bug introduced by
The expression $Series of type string is not traversable.
Loading history...
1877
            {
1878
             if (isset($Data["Series"][$SerieID]["Data"][$ID]) && $Data["Series"][$SerieID]["Data"][$ID] != NULL )
1879
              {
1880
               $Value = $Data["Series"][$SerieID]["Data"][$ID];
1881
               if ( $Value > 0 ) { $PointMax = $PointMax + $Value; } else { $PointMin = $PointMin + $Value; }
1882
              }
1883
            }
1884
           $AxisMax = max($AxisMax,$PointMax);
1885
           $AxisMin = min($AxisMin,$PointMin);
1886
          }
1887
         $AutoMargin = (($AxisMax-$AxisMin)/100)*$XReleasePercent;
1888
         $Data["Axis"][$AxisID]["Min"] = $AxisMin-$AutoMargin; $Data["Axis"][$AxisID]["Max"] = $AxisMax+$AutoMargin;
1889
        }
1890
       $MaxDivs = floor($Height/$MinDivHeight);
1891
1892
       if ( $Mode == SCALE_MODE_ADDALL_START0 ) { $Data["Axis"][$AxisID]["Min"] = 0; }
1893
1894
       $Scale   = $this->computeScale($Data["Axis"][$AxisID]["Min"],$Data["Axis"][$AxisID]["Max"],$MaxDivs,$Factors,$AxisID);
1895
1896
       $Data["Axis"][$AxisID]["Margin"]    = $AxisParameter["Identity"] == AXIS_X ? $XMargin : $YMargin;
1897
       $Data["Axis"][$AxisID]["ScaleMin"]  = $Scale["XMin"];
1898
       $Data["Axis"][$AxisID]["ScaleMax"]  = $Scale["XMax"];
1899
       $Data["Axis"][$AxisID]["Rows"]      = $Scale["Rows"];
1900
       $Data["Axis"][$AxisID]["RowHeight"] = $Scale["RowHeight"];
1901
1902
       if ( isset($Scale["Format"]) ) { $Data["Axis"][$AxisID]["Format"] = $Scale["Format"]; }
1903
1904
       if ( !isset($Data["Axis"][$AxisID]["Display"]) ) { $Data["Axis"][$AxisID]["Display"] = NULL; }
1905
       if ( !isset($Data["Axis"][$AxisID]["Format"]) )  { $Data["Axis"][$AxisID]["Format"] = NULL; }
1906
       if ( !isset($Data["Axis"][$AxisID]["Unit"]) )    { $Data["Axis"][$AxisID]["Unit"] = NULL; }
1907
      }
1908
1909
     /* Still no X axis */
1910
     if ( $GotXAxis == FALSE )
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
1911
      {
1912
       if ( $Abscissa != NULL )
1913
        {
1914
         $Points = count($Data["Series"][$Abscissa]["Data"]);
1915
         if ( $AutoAxisLabels )
1916
          $AxisName = isset($Data["Series"][$Abscissa]["Description"]) ? $Data["Series"][$Abscissa]["Description"] : NULL;
1917
         else
1918
          $AxisName = NULL;
1919
        }
1920
       else
1921
        {
1922
         $Points = 0;
1923
         $AxisName = isset($Data["XAxisName"]) ? $Data["XAxisName"] : NULL;
1924
         foreach($Data["Series"] as $SerieID => $SerieParameter)
1925
          { if ( $SerieParameter["isDrawable"] ) { $Points = max($Points,count($SerieParameter["Data"])); } }
1926
        }
1927
1928
       $AxisID = count($Data["Axis"]);
1929
       $Data["Axis"][$AxisID]["Identity"] = AXIS_X;
1930
       if ( $Pos == SCALE_POS_LEFTRIGHT ) { $Data["Axis"][$AxisID]["Position"] = AXIS_POSITION_BOTTOM; } else { $Data["Axis"][$AxisID]["Position"] = AXIS_POSITION_LEFT; }
1931
       if ( isset($Data["AbscissaName"]) ) { $Data["Axis"][$AxisID]["Name"] = $Data["AbscissaName"]; }
1932
       if ( $XMargin == AUTO )
1933
        {
1934
         if ( $Pos == SCALE_POS_LEFTRIGHT )
1935
          { $Height = $this->GraphAreaX2-$this->GraphAreaX1; }
1936
         else
1937
          { $Height = $this->GraphAreaY2-$this->GraphAreaY1; }
1938
1939
         if ( $Points == 1 )
1940
          $Data["Axis"][$AxisID]["Margin"] = $Height / 2;
1941
         else
1942
          $Data["Axis"][$AxisID]["Margin"] = ($Height/$Points) / 2;
1943
        }
1944
       else
1945
        { $Data["Axis"][$AxisID]["Margin"] = $XMargin; }
1946
       $Data["Axis"][$AxisID]["Rows"] = $Points-1;
1947
       if ( !isset($Data["Axis"][$AxisID]["Display"]) ) { $Data["Axis"][$AxisID]["Display"] = NULL; }
1948
       if ( !isset($Data["Axis"][$AxisID]["Format"]) )  { $Data["Axis"][$AxisID]["Format"] = NULL; }
1949
       if ( !isset($Data["Axis"][$AxisID]["Unit"]) )    { $Data["Axis"][$AxisID]["Unit"] = NULL; }
1950
      }
1951
1952
     /* Do we need to reverse the abscissa position? */
1953
     if ( $Pos != SCALE_POS_LEFTRIGHT )
1954
      {
1955
       if ( $Data["AbsicssaPosition"] == AXIS_POSITION_BOTTOM )
1956
        { $Data["AbsicssaPosition"] = AXIS_POSITION_LEFT; }
1957
       else
1958
        { $Data["AbsicssaPosition"] = AXIS_POSITION_RIGHT; }
1959
      }
1960
     $Data["Axis"][$AxisID]["Position"] = $Data["AbsicssaPosition"];
1961
1962
     $this->DataSet->saveOrientation($Pos);
1963
     $this->DataSet->saveAxisConfig($Data["Axis"]);
1964
     $this->DataSet->saveYMargin($YMargin);
1965
1966
     $FontColorRo = $this->FontColorR; $FontColorGo = $this->FontColorG; $FontColorBo = $this->FontColorB;
1967
1968
     $AxisPos["L"] = $this->GraphAreaX1; $AxisPos["R"] = $this->GraphAreaX2; $AxisPos["T"] = $this->GraphAreaY1; $AxisPos["B"] = $this->GraphAreaY2;
1969
     foreach($Data["Axis"] as $AxisID => $Parameters)
1970
      {
1971
       if ( isset($Parameters["Color"]) )
1972
        {
1973
         $AxisR = $Parameters["Color"]["R"]; $AxisG = $Parameters["Color"]["G"]; $AxisB = $Parameters["Color"]["B"];
1974
         $TickR = $Parameters["Color"]["R"]; $TickG = $Parameters["Color"]["G"]; $TickB = $Parameters["Color"]["B"];
1975
         $this->setFontProperties(array("R"=>$Parameters["Color"]["R"],"G"=>$Parameters["Color"]["G"],"B"=>$Parameters["Color"]["B"]));
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method setFontProperties() does only exist in the following sub-classes of pDraw: pImage. 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...
1976
        }
1977
       else
1978
        {
1979
         $AxisR = $AxisRo; $AxisG = $AxisGo; $AxisB = $AxisBo;
1980
         $TickR = $TickRo; $TickG = $TickGo; $TickB = $TickBo;
1981
         $this->setFontProperties(array("R"=>$FontColorRo,"G"=>$FontColorGo,"B"=>$FontColorBo));
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method setFontProperties() does only exist in the following sub-classes of pDraw: pImage. 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...
1982
        }
1983
1984
       $LastValue = "w00t"; $ID = 1;
1985
       if ( $Parameters["Identity"] == AXIS_X )
1986
        {
1987
         if ( $Pos == SCALE_POS_LEFTRIGHT )
1988
          {
1989
           if ( $Parameters["Position"] == AXIS_POSITION_BOTTOM )
1990
            {
1991
             if ( $LabelRotation == 0 )					{ $LabelAlign = TEXT_ALIGN_TOPMIDDLE; $YLabelOffset = 2; }
1992
             if ( $LabelRotation > 0 && $LabelRotation < 190 )		{ $LabelAlign = TEXT_ALIGN_MIDDLERIGHT; $YLabelOffset = 5; }
1993
             if ( $LabelRotation == 180 )				{ $LabelAlign = TEXT_ALIGN_BOTTOMMIDDLE; $YLabelOffset = 5; }
1994
             if ( $LabelRotation > 180 && $LabelRotation < 360 )	{ $LabelAlign = TEXT_ALIGN_MIDDLELEFT; $YLabelOffset = 2; }
1995
1996
             if ( !$RemoveXAxis )
1997
              {
1998
               if ( $Floating )
1999
                { $FloatingOffset = $YMargin; $this->drawLine($this->GraphAreaX1+$Parameters["Margin"],$AxisPos["B"],$this->GraphAreaX2-$Parameters["Margin"],$AxisPos["B"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); }
2000
               else
2001
                { $FloatingOffset = 0; $this->drawLine($this->GraphAreaX1,$AxisPos["B"],$this->GraphAreaX2,$AxisPos["B"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); }
2002
2003
               if ( $DrawArrows ) { $this->drawArrow($this->GraphAreaX2-$Parameters["Margin"],$AxisPos["B"],$this->GraphAreaX2+($ArrowSize*2),$AxisPos["B"],array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); }
2004
              }
2005
2006
             $Width = ($this->GraphAreaX2 - $this->GraphAreaX1) - $Parameters["Margin"]*2;
2007
2008
             if ($Parameters["Rows"] == 0 ) { $Step  = $Width; } else { $Step  = $Width / ($Parameters["Rows"]); }
2009
             
2010
             $MaxBottom = $AxisPos["B"];
2011
             for($i=0;$i<=$Parameters["Rows"];$i++)
2012
              {
2013
               $XPos  = $this->GraphAreaX1 + $Parameters["Margin"] + $Step*$i;
2014
               $YPos  = $AxisPos["B"];
2015
2016
               if ( $Abscissa != NULL )
2017
                { if ( isset($Data["Series"][$Abscissa]["Data"][$i]) ) { $Value = $this->scaleFormat($Data["Series"][$Abscissa]["Data"][$i],$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]); } else { $Value = ""; } }
2018
               else
2019
                {
2020
                 if ( isset($Parameters["ScaleMin"]) && isset ($Parameters["RowHeight"]) )
2021
                  $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]);
2022
                 else
2023
                  $Value = $i;
2024
                }
2025
2026
               $ID++; $Skipped = TRUE;
2027
               if ( $this->isValidLabel($Value,$LastValue,$LabelingMethod,$ID,$LabelSkip) && !$RemoveXAxis)
2028
                {
2029
                 $Bounds    = $this->drawText($XPos,$YPos+$OuterTickWidth+$YLabelOffset,$Value,array("Angle"=>$LabelRotation,"Align"=>$LabelAlign));
2030
                 $TxtBottom = $YPos+$OuterTickWidth+2+($Bounds[0]["Y"]-$Bounds[2]["Y"]);
2031
                 $MaxBottom = max($MaxBottom,$TxtBottom);
2032
                 $LastValue = $Value;
2033
                 $Skipped   = FALSE;
2034
                }
2035
2036
               if ( $RemoveXAxis ) { $Skipped   = FALSE; }
2037
2038
               if ( $Skipped )
2039
                {
2040
                 if ( $DrawXLines && !$RemoveSkippedAxis ) { $this->drawLine($XPos,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,$SkippedAxisColor); }
2041
                 if ( ($SkippedInnerTickWidth !=0 || $SkippedOuterTickWidth != 0) && !$RemoveXAxis && !$RemoveSkippedAxis) { $this->drawLine($XPos,$YPos-$SkippedInnerTickWidth,$XPos,$YPos+$SkippedOuterTickWidth,$SkippedTickColor); }
2042
                }
2043
               else
2044
                {
2045
                 if ( $DrawXLines && ($XPos != $this->GraphAreaX1 && $XPos != $this->GraphAreaX2) ) { $this->drawLine($XPos,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); }
2046
                 if ( ($InnerTickWidth !=0 || $OuterTickWidth != 0) && !$RemoveXAxis ) { $this->drawLine($XPos,$YPos-$InnerTickWidth,$XPos,$YPos+$OuterTickWidth,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); }
2047
                }
2048
              }
2049
2050
             if ( isset($Parameters["Name"]) && !$RemoveXAxis)
2051
              {
2052
               $YPos   = $MaxBottom+2;
2053
               $XPos   = $this->GraphAreaX1+($this->GraphAreaX2-$this->GraphAreaX1)/2;
2054
               $Bounds = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_TOPMIDDLE));
2055
               $MaxBottom = $Bounds[0]["Y"];
2056
2057
               $this->DataSet->Data["GraphArea"]["Y2"] = $MaxBottom + $this->FontSize;
2058
              }
2059
2060
             $AxisPos["B"] = $MaxBottom + $ScaleSpacing;
2061
            }
2062
           elseif ( $Parameters["Position"] == AXIS_POSITION_TOP )
2063
            {
2064
             if ( $LabelRotation == 0 )					{ $LabelAlign = TEXT_ALIGN_BOTTOMMIDDLE; $YLabelOffset = 2; }
2065
             if ( $LabelRotation > 0 && $LabelRotation < 190 )		{ $LabelAlign = TEXT_ALIGN_MIDDLELEFT; $YLabelOffset = 2; }
2066
             if ( $LabelRotation == 180 )				{ $LabelAlign = TEXT_ALIGN_TOPMIDDLE; $YLabelOffset = 5; }
2067
             if ( $LabelRotation > 180 && $LabelRotation < 360 )	{ $LabelAlign = TEXT_ALIGN_MIDDLERIGHT; $YLabelOffset = 5; }
2068
2069
             if ( !$RemoveXAxis )
2070
              {
2071
               if ( $Floating )
2072
                { $FloatingOffset = $YMargin; $this->drawLine($this->GraphAreaX1+$Parameters["Margin"],$AxisPos["T"],$this->GraphAreaX2-$Parameters["Margin"],$AxisPos["T"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); }
2073
               else
2074
                { $FloatingOffset = 0; $this->drawLine($this->GraphAreaX1,$AxisPos["T"],$this->GraphAreaX2,$AxisPos["T"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); }
2075
2076
               if ( $DrawArrows ) { $this->drawArrow($this->GraphAreaX2-$Parameters["Margin"],$AxisPos["T"],$this->GraphAreaX2+($ArrowSize*2),$AxisPos["T"],array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); }
2077
              }
2078
2079
             $Width = ($this->GraphAreaX2 - $this->GraphAreaX1) - $Parameters["Margin"]*2;
2080
2081
             if ($Parameters["Rows"] == 0 ) { $Step  = $Width; } else { $Step  = $Width / $Parameters["Rows"]; }
2082
             
2083
             $MinTop = $AxisPos["T"];
2084
             for($i=0;$i<=$Parameters["Rows"];$i++)
2085
              {
2086
               $XPos  = $this->GraphAreaX1 + $Parameters["Margin"] + $Step*$i;
2087
               $YPos  = $AxisPos["T"];
2088
2089
               if ( $Abscissa != NULL )
2090
                { if ( isset($Data["Series"][$Abscissa]["Data"][$i]) ) { $Value = $this->scaleFormat($Data["Series"][$Abscissa]["Data"][$i],$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]); } else { $Value = ""; } }
2091
               else
2092
                {
2093
                 if ( isset($Parameters["ScaleMin"]) && isset ($Parameters["RowHeight"]) )
2094
                  $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]);
2095
                 else
2096
                  $Value = $i;
2097
                }
2098
2099
               $ID++; $Skipped = TRUE;
2100
               if ( $this->isValidLabel($Value,$LastValue,$LabelingMethod,$ID,$LabelSkip) && !$RemoveXAxis)
2101
                {
2102
                 $Bounds = $this->drawText($XPos,$YPos-$OuterTickWidth-$YLabelOffset,$Value,array("Angle"=>$LabelRotation,"Align"=>$LabelAlign));
2103
                 $TxtBox = $YPos-$OuterTickWidth-2-($Bounds[0]["Y"]-$Bounds[2]["Y"]);
2104
                 $MinTop = min($MinTop,$TxtBox);
2105
                 $LastValue = $Value;
2106
                 $Skipped   = FALSE;
2107
                }
2108
2109
               if ( $RemoveXAxis ) { $Skipped   = FALSE; }
2110
2111
               if ( $Skipped )
2112
                {
2113
                 if ( $DrawXLines && !$RemoveSkippedAxis ) { $this->drawLine($XPos,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,$SkippedAxisColor); }
2114
                 if ( ($SkippedInnerTickWidth !=0 || $SkippedOuterTickWidth != 0) && !$RemoveXAxis && !$RemoveSkippedAxis ) { $this->drawLine($XPos,$YPos+$SkippedInnerTickWidth,$XPos,$YPos-$SkippedOuterTickWidth,$SkippedTickColor); }
2115
                }
2116
               else
2117
                {
2118
                 if ( $DrawXLines ) { $this->drawLine($XPos,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); }
2119
                 if ( ($InnerTickWidth !=0 || $OuterTickWidth != 0) && !$RemoveXAxis ) { $this->drawLine($XPos,$YPos+$InnerTickWidth,$XPos,$YPos-$OuterTickWidth,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); }
2120
                }
2121
2122
              }
2123
2124
             if ( isset($Parameters["Name"]) && !$RemoveXAxis )
2125
              {
2126
               $YPos   = $MinTop-2;
2127
               $XPos   = $this->GraphAreaX1+($this->GraphAreaX2-$this->GraphAreaX1)/2;
2128
               $Bounds = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE));
2129
               $MinTop = $Bounds[2]["Y"];
2130
2131
               $this->DataSet->Data["GraphArea"]["Y1"] = $MinTop;
2132
              }
2133
2134
             $AxisPos["T"] = $MinTop - $ScaleSpacing;
2135
            }
2136
          }
2137
         elseif ( $Pos == SCALE_POS_TOPBOTTOM )
2138
          {
2139
           if ( $Parameters["Position"] == AXIS_POSITION_LEFT )
2140
            {
2141
             if ( $LabelRotation == 0 )					{ $LabelAlign = TEXT_ALIGN_MIDDLERIGHT; $XLabelOffset = -2; }
2142
             if ( $LabelRotation > 0 && $LabelRotation < 190 )		{ $LabelAlign = TEXT_ALIGN_MIDDLERIGHT; $XLabelOffset = -6; }
2143
             if ( $LabelRotation == 180 )				{ $LabelAlign = TEXT_ALIGN_MIDDLELEFT; $XLabelOffset = -2; }
2144
             if ( $LabelRotation > 180 && $LabelRotation < 360 )	{ $LabelAlign = TEXT_ALIGN_MIDDLELEFT; $XLabelOffset = -5; }
2145
2146
             if ( !$RemoveXAxis )
2147
              {
2148
               if ( $Floating )
2149
                { $FloatingOffset = $YMargin; $this->drawLine($AxisPos["L"],$this->GraphAreaY1+$Parameters["Margin"],$AxisPos["L"],$this->GraphAreaY2-$Parameters["Margin"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); }
2150
               else
2151
                { $FloatingOffset = 0; $this->drawLine($AxisPos["L"],$this->GraphAreaY1,$AxisPos["L"],$this->GraphAreaY2,array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); }
2152
2153
               if ( $DrawArrows ) { $this->drawArrow($AxisPos["L"],$this->GraphAreaY2-$Parameters["Margin"],$AxisPos["L"],$this->GraphAreaY2+($ArrowSize*2),array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); }
2154
              }
2155
2156
             $Height = ($this->GraphAreaY2 - $this->GraphAreaY1) - $Parameters["Margin"]*2;
2157
2158
             if ($Parameters["Rows"] == 0 ) { $Step  = $Height; } else { $Step   = $Height / $Parameters["Rows"]; }
2159
2160
             $MinLeft = $AxisPos["L"];
2161
             for($i=0;$i<=$Parameters["Rows"];$i++)
2162
              {
2163
               $YPos  = $this->GraphAreaY1 + $Parameters["Margin"] + $Step*$i;
2164
               $XPos  = $AxisPos["L"];
2165
2166
               if ( $Abscissa != NULL )
2167
                { if ( isset($Data["Series"][$Abscissa]["Data"][$i]) ) { $Value = $this->scaleFormat($Data["Series"][$Abscissa]["Data"][$i],$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]); } else { $Value = ""; } }
2168
               else
2169
                {
2170
                 if ( isset($Parameters["ScaleMin"]) && isset ($Parameters["RowHeight"]) )
2171
                  $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]);
2172
                 else
2173
                  $Value = $i;
2174
                }
2175
2176
               $ID++; $Skipped = TRUE;
2177
               if ( $this->isValidLabel($Value,$LastValue,$LabelingMethod,$ID,$LabelSkip) && !$RemoveXAxis)
2178
                {
2179
                 $Bounds  = $this->drawText($XPos-$OuterTickWidth+$XLabelOffset,$YPos,$Value,array("Angle"=>$LabelRotation,"Align"=>$LabelAlign));
2180
                 $TxtBox  = $XPos-$OuterTickWidth-2-($Bounds[1]["X"]-$Bounds[0]["X"]);
2181
                 $MinLeft = min($MinLeft,$TxtBox);
2182
                 $LastValue = $Value;
2183
                 $Skipped   = FALSE;
2184
                }
2185
2186
               if ( $RemoveXAxis ) { $Skipped   = FALSE; }
2187
2188
               if ( $Skipped )
2189
                {
2190
                 if ( $DrawXLines && !$RemoveSkippedAxis ) { $this->drawLine($this->GraphAreaX1+$FloatingOffset,$YPos,$this->GraphAreaX2-$FloatingOffset,$YPos,$SkippedAxisColor); }
2191
                 if ( ($SkippedInnerTickWidth !=0 || $SkippedOuterTickWidth != 0) && !$RemoveXAxis && !$RemoveSkippedAxis ) { $this->drawLine($XPos-$SkippedOuterTickWidth,$YPos,$XPos+$SkippedInnerTickWidth,$YPos,$SkippedTickColor); }
2192
                }
2193
               else
2194
                {
2195
                 if ( $DrawXLines && ($YPos != $this->GraphAreaY1 && $YPos != $this->GraphAreaY2) ) { $this->drawLine($this->GraphAreaX1+$FloatingOffset,$YPos,$this->GraphAreaX2-$FloatingOffset,$YPos,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); }
2196
                 if ( ($InnerTickWidth !=0 || $OuterTickWidth != 0) && !$RemoveXAxis ) { $this->drawLine($XPos-$OuterTickWidth,$YPos,$XPos+$InnerTickWidth,$YPos,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); }
2197
                }
2198
2199
              }
2200
             if ( isset($Parameters["Name"]) && !$RemoveXAxis )
2201
              {
2202
               $XPos   = $MinLeft-2;
2203
               $YPos   = $this->GraphAreaY1+($this->GraphAreaY2-$this->GraphAreaY1)/2;
2204
               $Bounds = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE,"Angle"=>90));
2205
               $MinLeft = $Bounds[0]["X"];
2206
2207
               $this->DataSet->Data["GraphArea"]["X1"] = $MinLeft;
2208
              }
2209
2210
             $AxisPos["L"] = $MinLeft - $ScaleSpacing;
2211
            }
2212
           elseif ( $Parameters["Position"] == AXIS_POSITION_RIGHT )
2213
            {
2214
             if ( $LabelRotation == 0 )					{ $LabelAlign = TEXT_ALIGN_MIDDLELEFT; $XLabelOffset = 2; }
2215
             if ( $LabelRotation > 0 && $LabelRotation < 190 )		{ $LabelAlign = TEXT_ALIGN_MIDDLELEFT; $XLabelOffset = 6; }
2216
             if ( $LabelRotation == 180 )				{ $LabelAlign = TEXT_ALIGN_MIDDLERIGHT; $XLabelOffset = 5; }
2217
             if ( $LabelRotation > 180 && $LabelRotation < 360 )	{ $LabelAlign = TEXT_ALIGN_MIDDLERIGHT; $XLabelOffset = 7; }
2218
2219
             if ( !$RemoveXAxis )
2220
              {
2221
               if ( $Floating )
2222
                { $FloatingOffset = $YMargin; $this->drawLine($AxisPos["R"],$this->GraphAreaY1+$Parameters["Margin"],$AxisPos["R"],$this->GraphAreaY2-$Parameters["Margin"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); }
2223
               else
2224
                { $FloatingOffset = 0; $this->drawLine($AxisPos["R"],$this->GraphAreaY1,$AxisPos["R"],$this->GraphAreaY2,array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); }
2225
2226
               if ( $DrawArrows ) { $this->drawArrow($AxisPos["R"],$this->GraphAreaY2-$Parameters["Margin"],$AxisPos["R"],$this->GraphAreaY2+($ArrowSize*2),array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); }
2227
              }
2228
2229
             $Height = ($this->GraphAreaY2 - $this->GraphAreaY1) - $Parameters["Margin"]*2;
2230
2231
             if ($Parameters["Rows"] == 0 ) { $Step  = $Height; } else { $Step   = $Height / $Parameters["Rows"]; }
2232
             
2233
             $MaxRight = $AxisPos["R"];
2234
             for($i=0;$i<=$Parameters["Rows"];$i++)
2235
              {
2236
               $YPos  = $this->GraphAreaY1 + $Parameters["Margin"] + $Step*$i;
2237
               $XPos  = $AxisPos["R"];
2238
2239
               if ( $Abscissa != NULL )
2240
                { if ( isset($Data["Series"][$Abscissa]["Data"][$i]) ) { $Value = $this->scaleFormat($Data["Series"][$Abscissa]["Data"][$i],$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]); } else { $Value = ""; } }
2241
               else
2242
                {
2243
                 if ( isset($Parameters["ScaleMin"]) && isset ($Parameters["RowHeight"]) )
2244
                  $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Data["XAxisDisplay"],$Data["XAxisFormat"],$Data["XAxisUnit"]);
2245
                 else
2246
                  $Value = $i;
2247
                }
2248
2249
               $ID++; $Skipped = TRUE;
2250
               if ( $this->isValidLabel($Value,$LastValue,$LabelingMethod,$ID,$LabelSkip) && !$RemoveXAxis)
2251
                {
2252
                 $Bounds   = $this->drawText($XPos+$OuterTickWidth+$XLabelOffset,$YPos,$Value,array("Angle"=>$LabelRotation,"Align"=>$LabelAlign));
2253
                 $TxtBox   = $XPos+$OuterTickWidth+2+($Bounds[1]["X"]-$Bounds[0]["X"]);
2254
                 $MaxRight = max($MaxRight,$TxtBox);
2255
                 $LastValue = $Value;
2256
                 $Skipped   = FALSE;
2257
                }
2258
2259
               if ( $RemoveXAxis ) { $Skipped   = FALSE; }
2260
2261
               if ( $Skipped )
2262
                {
2263
                 if ( $DrawXLines && !$RemoveSkippedAxis ) { $this->drawLine($this->GraphAreaX1+$FloatingOffset,$YPos,$this->GraphAreaX2-$FloatingOffset,$YPos,$SkippedAxisColor); }
2264
                 if ( ($SkippedInnerTickWidth != 0 || $SkippedOuterTickWidth != 0) && !$RemoveXAxis && !$RemoveSkippedAxis ) { $this->drawLine($XPos+$SkippedOuterTickWidth,$YPos,$XPos-$SkippedInnerTickWidth,$YPos,$SkippedTickColor); }
2265
                }
2266
               else
2267
                {
2268
                 if ( $DrawXLines ) { $this->drawLine($this->GraphAreaX1+$FloatingOffset,$YPos,$this->GraphAreaX2-$FloatingOffset,$YPos,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); }
2269
                 if ( ($InnerTickWidth != 0 || $OuterTickWidth != 0) && !$RemoveXAxis ) { $this->drawLine($XPos+$OuterTickWidth,$YPos,$XPos-$InnerTickWidth,$YPos,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha)); }
2270
                }
2271
2272
              }
2273
2274
             if ( isset($Parameters["Name"]) && !$RemoveXAxis)
2275
              {
2276
               $XPos   = $MaxRight+4;
2277
               $YPos   = $this->GraphAreaY1+($this->GraphAreaY2-$this->GraphAreaY1)/2;
2278
               $Bounds = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE,"Angle"=>270));
2279
               $MaxRight = $Bounds[1]["X"];
2280
2281
               $this->DataSet->Data["GraphArea"]["X2"] = $MaxRight + $this->FontSize;
2282
              }
2283
2284
             $AxisPos["R"] = $MaxRight + $ScaleSpacing;
2285
            }
2286
          }
2287
        }
2288
2289
2290
2291
       if ( $Parameters["Identity"] == AXIS_Y )
2292
        {
2293
         if ( $Pos == SCALE_POS_LEFTRIGHT )
2294
          {
2295
           if ( $Parameters["Position"] == AXIS_POSITION_LEFT )
2296
            {
2297
2298
             if ( $Floating )
2299
              { $FloatingOffset = $XMargin; $this->drawLine($AxisPos["L"],$this->GraphAreaY1+$Parameters["Margin"],$AxisPos["L"],$this->GraphAreaY2-$Parameters["Margin"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); }
2300
             else
2301
              { $FloatingOffset = 0; $this->drawLine($AxisPos["L"],$this->GraphAreaY1,$AxisPos["L"],$this->GraphAreaY2,array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); }
2302
2303
             if ( $DrawArrows ) { $this->drawArrow($AxisPos["L"],$this->GraphAreaY1+$Parameters["Margin"],$AxisPos["L"],$this->GraphAreaY1-($ArrowSize*2),array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); }
2304
2305
             $Height = ($this->GraphAreaY2 - $this->GraphAreaY1) - $Parameters["Margin"]*2;
2306
             $Step   = $Height / $Parameters["Rows"]; $SubTicksSize = $Step /2; $MinLeft = $AxisPos["L"];
2307
             $LastY  = NULL;
2308
             for($i=0;$i<=$Parameters["Rows"];$i++)
2309
              {
2310
               $YPos  = $this->GraphAreaY2 - $Parameters["Margin"] - $Step*$i;
2311
               $XPos  = $AxisPos["L"];
2312
               $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Parameters["Display"],$Parameters["Format"],$Parameters["Unit"]);
2313
2314
               if ( $i%2 == 1 ) { $BGColor = array("R"=>$BackgroundR1,"G"=>$BackgroundG1,"B"=>$BackgroundB1,"Alpha"=>$BackgroundAlpha1); } else { $BGColor = array("R"=>$BackgroundR2,"G"=>$BackgroundG2,"B"=>$BackgroundB2,"Alpha"=>$BackgroundAlpha2); }
2315
               if ( $LastY != NULL && $CycleBackground && ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) )) { $this->drawFilledRectangle($this->GraphAreaX1+$FloatingOffset,$LastY,$this->GraphAreaX2-$FloatingOffset,$YPos,$BGColor); }
2316
2317
               if ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) ) { $this->drawLine($this->GraphAreaX1+$FloatingOffset,$YPos,$this->GraphAreaX2-$FloatingOffset,$YPos,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); }
2318
2319
               if ( $DrawSubTicks && $i != $Parameters["Rows"] )
2320
                $this->drawLine($XPos-$OuterSubTickWidth,$YPos-$SubTicksSize,$XPos+$InnerSubTickWidth,$YPos-$SubTicksSize,array("R"=>$SubTickR,"G"=>$SubTickG,"B"=>$SubTickB,"Alpha"=>$SubTickAlpha));
2321
2322
               $this->drawLine($XPos-$OuterTickWidth,$YPos,$XPos+$InnerTickWidth,$YPos,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha));
2323
               $Bounds  = $this->drawText($XPos-$OuterTickWidth-2,$YPos,$Value,array("Align"=>TEXT_ALIGN_MIDDLERIGHT));
2324
               $TxtLeft = $XPos-$OuterTickWidth-2-($Bounds[1]["X"]-$Bounds[0]["X"]);
2325
               $MinLeft = min($MinLeft,$TxtLeft);
2326
2327
               $LastY = $YPos;
2328
              }
2329
2330
             if ( isset($Parameters["Name"]) )
2331
              {
2332
               $XPos    = $MinLeft-2;
2333
               $YPos    = $this->GraphAreaY1+($this->GraphAreaY2-$this->GraphAreaY1)/2;
2334
               $Bounds  = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE,"Angle"=>90));
2335
               $MinLeft = $Bounds[2]["X"];
2336
2337
               $this->DataSet->Data["GraphArea"]["X1"] = $MinLeft;
2338
              }
2339
2340
             $AxisPos["L"] = $MinLeft - $ScaleSpacing;
2341
            }
2342
           elseif ( $Parameters["Position"] == AXIS_POSITION_RIGHT )
2343
            {
2344
             if ( $Floating )
2345
              { $FloatingOffset = $XMargin; $this->drawLine($AxisPos["R"],$this->GraphAreaY1+$Parameters["Margin"],$AxisPos["R"],$this->GraphAreaY2-$Parameters["Margin"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); }
2346
             else
2347
              { $FloatingOffset = 0; $this->drawLine($AxisPos["R"],$this->GraphAreaY1,$AxisPos["R"],$this->GraphAreaY2,array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); }
2348
2349
             if ( $DrawArrows ) { $this->drawArrow($AxisPos["R"],$this->GraphAreaY1+$Parameters["Margin"],$AxisPos["R"],$this->GraphAreaY1-($ArrowSize*2),array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); }
2350
2351
             $Height = ($this->GraphAreaY2 - $this->GraphAreaY1) - $Parameters["Margin"]*2;
2352
             $Step   = $Height / $Parameters["Rows"]; $SubTicksSize = $Step /2; $MaxLeft = $AxisPos["R"];
2353
             $LastY  = NULL;
2354
             for($i=0;$i<=$Parameters["Rows"];$i++)
2355
              {
2356
               $YPos  = $this->GraphAreaY2 - $Parameters["Margin"] - $Step*$i;
2357
               $XPos  = $AxisPos["R"];
2358
               $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Parameters["Display"],$Parameters["Format"],$Parameters["Unit"]);
2359
2360
               if ( $i%2 == 1 ) { $BGColor = array("R"=>$BackgroundR1,"G"=>$BackgroundG1,"B"=>$BackgroundB1,"Alpha"=>$BackgroundAlpha1); } else { $BGColor = array("R"=>$BackgroundR2,"G"=>$BackgroundG2,"B"=>$BackgroundB2,"Alpha"=>$BackgroundAlpha2); }
2361
               if ( $LastY != NULL && $CycleBackground  && ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) )) { $this->drawFilledRectangle($this->GraphAreaX1+$FloatingOffset,$LastY,$this->GraphAreaX2-$FloatingOffset,$YPos,$BGColor); }
2362
2363
               if ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) ) { $this->drawLine($this->GraphAreaX1+$FloatingOffset,$YPos,$this->GraphAreaX2-$FloatingOffset,$YPos,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); }
2364
2365
               if ( $DrawSubTicks && $i != $Parameters["Rows"] )
2366
                $this->drawLine($XPos-$OuterSubTickWidth,$YPos-$SubTicksSize,$XPos+$InnerSubTickWidth,$YPos-$SubTicksSize,array("R"=>$SubTickR,"G"=>$SubTickG,"B"=>$SubTickB,"Alpha"=>$SubTickAlpha));
2367
2368
               $this->drawLine($XPos-$InnerTickWidth,$YPos,$XPos+$OuterTickWidth,$YPos,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha));
2369
               $Bounds  = $this->drawText($XPos+$OuterTickWidth+2,$YPos,$Value,array("Align"=>TEXT_ALIGN_MIDDLELEFT));
2370
               $TxtLeft = $XPos+$OuterTickWidth+2+($Bounds[1]["X"]-$Bounds[0]["X"]);
2371
               $MaxLeft = max($MaxLeft,$TxtLeft);
2372
2373
               $LastY = $YPos;
2374
              }
2375
2376
             if ( isset($Parameters["Name"]) )
2377
              {
2378
               $XPos    = $MaxLeft+6;
2379
               $YPos    = $this->GraphAreaY1+($this->GraphAreaY2-$this->GraphAreaY1)/2;
2380
               $Bounds  = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE,"Angle"=>270));
2381
               $MaxLeft = $Bounds[2]["X"];
2382
2383
               $this->DataSet->Data["GraphArea"]["X2"] = $MaxLeft + $this->FontSize;
2384
              }
2385
             $AxisPos["R"] = $MaxLeft + $ScaleSpacing;
2386
            }
2387
          }
2388
         elseif ( $Pos == SCALE_POS_TOPBOTTOM )
2389
          {
2390
           if ( $Parameters["Position"] == AXIS_POSITION_TOP )
2391
            {
2392
             if ( $Floating )
2393
              { $FloatingOffset = $XMargin; $this->drawLine($this->GraphAreaX1+$Parameters["Margin"],$AxisPos["T"],$this->GraphAreaX2-$Parameters["Margin"],$AxisPos["T"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); }
2394
             else
2395
              { $FloatingOffset = 0; $this->drawLine($this->GraphAreaX1,$AxisPos["T"],$this->GraphAreaX2,$AxisPos["T"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); }
2396
2397
             if ( $DrawArrows ) { $this->drawArrow($this->GraphAreaX2-$Parameters["Margin"],$AxisPos["T"],$this->GraphAreaX2+($ArrowSize*2),$AxisPos["T"],array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); }
2398
2399
             $Width = ($this->GraphAreaX2 - $this->GraphAreaX1) - $Parameters["Margin"]*2;
2400
             $Step   = $Width / $Parameters["Rows"]; $SubTicksSize = $Step /2; $MinTop = $AxisPos["T"];
2401
             $LastX  = NULL;
2402
             for($i=0;$i<=$Parameters["Rows"];$i++)
2403
              {
2404
               $XPos  = $this->GraphAreaX1 + $Parameters["Margin"] + $Step*$i;
2405
               $YPos  = $AxisPos["T"];
2406
               $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Parameters["Display"],$Parameters["Format"],$Parameters["Unit"]);
2407
2408
               if ( $i%2 == 1 ) { $BGColor = array("R"=>$BackgroundR1,"G"=>$BackgroundG1,"B"=>$BackgroundB1,"Alpha"=>$BackgroundAlpha1); } else { $BGColor = array("R"=>$BackgroundR2,"G"=>$BackgroundG2,"B"=>$BackgroundB2,"Alpha"=>$BackgroundAlpha2); }
2409
               if ( $LastX != NULL && $CycleBackground  && ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) )) { $this->drawFilledRectangle($LastX,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,$BGColor); }
2410
2411
               if ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) ) { $this->drawLine($XPos,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); }
2412
2413
               if ( $DrawSubTicks && $i != $Parameters["Rows"] )
2414
                $this->drawLine($XPos+$SubTicksSize,$YPos-$OuterSubTickWidth,$XPos+$SubTicksSize,$YPos+$InnerSubTickWidth,array("R"=>$SubTickR,"G"=>$SubTickG,"B"=>$SubTickB,"Alpha"=>$SubTickAlpha));
2415
2416
               $this->drawLine($XPos,$YPos-$OuterTickWidth,$XPos,$YPos+$InnerTickWidth,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha));
2417
               $Bounds    = $this->drawText($XPos,$YPos-$OuterTickWidth-2,$Value,array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE));
2418
               $TxtHeight = $YPos-$OuterTickWidth-2-($Bounds[1]["Y"]-$Bounds[2]["Y"]);
2419
               $MinTop    = min($MinTop,$TxtHeight);
2420
2421
               $LastX = $XPos;
2422
              }
2423
2424
             if ( isset($Parameters["Name"]) )
2425
              {
2426
               $YPos   = $MinTop-2;
2427
               $XPos   = $this->GraphAreaX1+($this->GraphAreaX2-$this->GraphAreaX1)/2;
2428
               $Bounds = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_BOTTOMMIDDLE));
2429
               $MinTop = $Bounds[2]["Y"];
2430
2431
               $this->DataSet->Data["GraphArea"]["Y1"] = $MinTop;
2432
              }
2433
2434
             $AxisPos["T"] = $MinTop - $ScaleSpacing;
2435
            }
2436
           elseif ( $Parameters["Position"] == AXIS_POSITION_BOTTOM )
2437
            {
2438
             if ( $Floating )
2439
              { $FloatingOffset = $XMargin; $this->drawLine($this->GraphAreaX1+$Parameters["Margin"],$AxisPos["B"],$this->GraphAreaX2-$Parameters["Margin"],$AxisPos["B"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); }
2440
             else
2441
              { $FloatingOffset = 0; $this->drawLine($this->GraphAreaX1,$AxisPos["B"],$this->GraphAreaX2,$AxisPos["B"],array("R"=>$AxisR,"G"=>$AxisG,"B"=>$AxisB,"Alpha"=>$AxisAlpha)); }
2442
2443
             if ( $DrawArrows ) { $this->drawArrow($this->GraphAreaX2-$Parameters["Margin"],$AxisPos["B"],$this->GraphAreaX2+($ArrowSize*2),$AxisPos["B"],array("FillR"=>$AxisR,"FillG"=>$AxisG,"FillB"=>$AxisB,"Size"=>$ArrowSize)); }
2444
2445
             $Width = ($this->GraphAreaX2 - $this->GraphAreaX1) - $Parameters["Margin"]*2;
2446
             $Step   = $Width / $Parameters["Rows"]; $SubTicksSize = $Step /2; $MaxBottom = $AxisPos["B"];
2447
             $LastX  = NULL;
2448
             for($i=0;$i<=$Parameters["Rows"];$i++)
2449
              {
2450
               $XPos  = $this->GraphAreaX1 + $Parameters["Margin"] + $Step*$i;
2451
               $YPos  = $AxisPos["B"];
2452
               $Value = $this->scaleFormat($Parameters["ScaleMin"] + $Parameters["RowHeight"]*$i,$Parameters["Display"],$Parameters["Format"],$Parameters["Unit"]);
2453
2454
               if ( $i%2 == 1 ) { $BGColor = array("R"=>$BackgroundR1,"G"=>$BackgroundG1,"B"=>$BackgroundB1,"Alpha"=>$BackgroundAlpha1); } else { $BGColor = array("R"=>$BackgroundR2,"G"=>$BackgroundG2,"B"=>$BackgroundB2,"Alpha"=>$BackgroundAlpha2); }
2455
               if ( $LastX != NULL && $CycleBackground  && ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) )) { $this->drawFilledRectangle($LastX,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,$BGColor); }
2456
2457
               if ( $DrawYLines == ALL || in_array($AxisID,$DrawYLines) ) { $this->drawLine($XPos,$this->GraphAreaY1+$FloatingOffset,$XPos,$this->GraphAreaY2-$FloatingOffset,array("R"=>$GridR,"G"=>$GridG,"B"=>$GridB,"Alpha"=>$GridAlpha,"Ticks"=>$GridTicks)); }
2458
2459
               if ( $DrawSubTicks && $i != $Parameters["Rows"] )
2460
                $this->drawLine($XPos+$SubTicksSize,$YPos-$OuterSubTickWidth,$XPos+$SubTicksSize,$YPos+$InnerSubTickWidth,array("R"=>$SubTickR,"G"=>$SubTickG,"B"=>$SubTickB,"Alpha"=>$SubTickAlpha));
2461
2462
               $this->drawLine($XPos,$YPos-$OuterTickWidth,$XPos,$YPos+$InnerTickWidth,array("R"=>$TickR,"G"=>$TickG,"B"=>$TickB,"Alpha"=>$TickAlpha));
2463
               $Bounds    = $this->drawText($XPos,$YPos+$OuterTickWidth+2,$Value,array("Align"=>TEXT_ALIGN_TOPMIDDLE));
2464
               $TxtHeight = $YPos+$OuterTickWidth+2+($Bounds[1]["Y"]-$Bounds[2]["Y"]);
2465
               $MaxBottom = max($MaxBottom,$TxtHeight);
2466
2467
               $LastX = $XPos;
2468
              }
2469
2470
             if ( isset($Parameters["Name"]) )
2471
              {
2472
               $YPos   = $MaxBottom+2;
2473
               $XPos   = $this->GraphAreaX1+($this->GraphAreaX2-$this->GraphAreaX1)/2;
2474
               $Bounds = $this->drawText($XPos,$YPos,$Parameters["Name"],array("Align"=>TEXT_ALIGN_TOPMIDDLE));
2475
               $MaxBottom = $Bounds[0]["Y"];
2476
2477
               $this->DataSet->Data["GraphArea"]["Y2"] = $MaxBottom + $this->FontSize;
2478
              }
2479
2480
             $AxisPos["B"] = $MaxBottom + $ScaleSpacing;
2481
            }
2482
          }
2483
        }
2484
      }
2485
    }
2486
2487
   function isValidLabel($Value,$LastValue,$LabelingMethod,$ID,$LabelSkip)
2488
    {
2489
     if ( $LabelingMethod == LABELING_DIFFERENT && $Value != $LastValue ) { return(TRUE); }
2490
     if ( $LabelingMethod == LABELING_DIFFERENT && $Value == $LastValue ) { return(FALSE); }
2491
     if ( $LabelingMethod == LABELING_ALL && $LabelSkip == 0 ) { return(TRUE); }
2492
     if ( $LabelingMethod == LABELING_ALL && ($ID+$LabelSkip) % ($LabelSkip+1) != 1 ) { return(FALSE); }
2493
2494
     return(TRUE);
2495
    }
2496
2497
   /* Compute the scale, check for the best visual factors */
2498
   function computeScale($XMin,$XMax,$MaxDivs,$Factors,$AxisID=0)
2499
    {
2500
     /* Compute each factors */
2501
     $Results = "";
2502
     foreach ($Factors as $Key => $Factor)
2503
      $Results[$Factor] = $this->processScale($XMin,$XMax,$MaxDivs,array($Factor),$AxisID);
2504
2505
     /* Remove scales that are creating to much decimals */
2506
     $GoodScaleFactors = "";
2507
     foreach ($Results as $Key => $Result)
0 ignored issues
show
Bug introduced by
The expression $Results of type string is not traversable.
Loading history...
2508
      {
2509
       $Decimals = preg_split("/\./",$Result["RowHeight"]);
2510
       if ( (!isset($Decimals[1])) || (strlen($Decimals[1]) < 6) ) { $GoodScaleFactors[] = $Key; }
2511
      }
2512
2513
     /* Found no correct scale, shame,... returns the 1st one as default */
2514
     if ( $GoodScaleFactors == "" ) { return($Results[$Factors[0]]); }
2515
2516
     /* Find the factor that cause the maximum number of Rows */
2517
     $MaxRows = 0; $BestFactor = 0;
2518
     foreach($GoodScaleFactors as $Key => $Factor)
0 ignored issues
show
Bug introduced by
The expression $GoodScaleFactors of type string is not traversable.
Loading history...
2519
      { if ( $Results[$Factor]["Rows"] > $MaxRows ) { $MaxRows = $Results[$Factor]["Rows"]; $BestFactor = $Factor; } }
2520
2521
     /* Return the best visual scale */
2522
     return($Results[$BestFactor]);
2523
    }
2524
2525
   /* Compute the best matching scale based on size & factors */
2526
   function processScale($XMin,$XMax,$MaxDivs,$Factors,$AxisID)
2527
    {
2528
     $ScaleHeight = abs(ceil($XMax)-floor($XMin));
2529
2530
     if ( isset($this->DataSet->Data["Axis"][$AxisID]["Format"]) )
2531
      $Format = $this->DataSet->Data["Axis"][$AxisID]["Format"];
2532
     else
2533
      $Format = NULL;
2534
2535
     if ( isset($this->DataSet->Data["Axis"][$AxisID]["Display"]) )
2536
      $Mode = $this->DataSet->Data["Axis"][$AxisID]["Display"];
2537
     else
2538
      $Mode = AXIS_FORMAT_DEFAULT;
2539
2540
     $Scale = "";
2541
     if ( $XMin != $XMax )
2542
      {
2543
       $Found = FALSE; $Rescaled = FALSE; $Scaled10Factor = .0001; $Result = 0;
2544
       while(!$Found)
2545
        {
2546
         foreach($Factors as $Key => $Factor)
2547
          {
2548
           if ( !$Found )
2549
            {
2550
             if ( !($this->modulo($XMin,$Factor*$Scaled10Factor) == 0) || ($XMin != floor($XMin))) { $XMinRescaled = floor($XMin/($Factor*$Scaled10Factor))*$Factor*$Scaled10Factor; } else { $XMinRescaled = $XMin; }
2551
             if ( !($this->modulo($XMax,$Factor*$Scaled10Factor) == 0) || ($XMax != floor($XMax))) { $XMaxRescaled = floor($XMax/($Factor*$Scaled10Factor))*$Factor*$Scaled10Factor+($Factor*$Scaled10Factor); } else { $XMaxRescaled = $XMax; }
2552
             $ScaleHeightRescaled = abs($XMaxRescaled-$XMinRescaled);
2553
2554
             if ( !$Found && floor($ScaleHeightRescaled/($Factor*$Scaled10Factor)) <= $MaxDivs ) { $Found = TRUE; $Rescaled = TRUE; $Result = $Factor * $Scaled10Factor; }
2555
            }
2556
          }
2557
         $Scaled10Factor = $Scaled10Factor * 10;
2558
        }
2559
2560
       /* ReCall Min / Max / Height */
2561
       if ( $Rescaled ) { $XMin = $XMinRescaled; $XMax = $XMaxRescaled; $ScaleHeight = $ScaleHeightRescaled; }
2562
2563
       /* Compute rows size */
2564
       $Rows      = floor($ScaleHeight / $Result); if ( $Rows == 0 ) { $Rows = 1; }
2565
       $RowHeight = $ScaleHeight / $Rows;
2566
2567
       /* Return the results */
2568
       $Scale["Rows"] = $Rows; $Scale["RowHeight"] = $RowHeight; $Scale["XMin"] = $XMin;  $Scale["XMax"] = $XMax;
2569
2570
       /* Compute the needed decimals for the metric view to avoid repetition of the same X Axis labels */
2571
       if ( $Mode == AXIS_FORMAT_METRIC && $Format == NULL )
2572
        {
2573
         $Done = FALSE; $GoodDecimals = 0;
2574
         for($Decimals=0;$Decimals<=10;$Decimals++)
2575
          {
2576
           if ( !$Done )
2577
            {
2578
             $LastLabel = "zob"; $ScaleOK = TRUE;
2579
             for($i=0;$i<=$Rows;$i++)
2580
              {
2581
               $Value = $XMin + $i*$RowHeight;
2582
               $Label = $this->scaleFormat($Value,AXIS_FORMAT_METRIC,$Decimals);
2583
2584
               if ( $LastLabel == $Label ) { $ScaleOK = FALSE; }
2585
               $LastLabel = $Label;
2586
              }
2587
             if ( $ScaleOK ) { $Done = TRUE; $GoodDecimals = $Decimals; }
2588
            }
2589
          }
2590
2591
         $Scale["Format"] = $GoodDecimals;
2592
        }
2593
      }
2594
     else
2595
      {
2596
       /* If all values are the same we keep a +1/-1 scale */
2597
       $Rows = 2; $XMin = $XMax-1; $XMax = $XMax+1; $RowHeight = 1;
2598
2599
       /* Return the results */
2600
       $Scale["Rows"] = $Rows; $Scale["RowHeight"] = $RowHeight; $Scale["XMin"] = $XMin;  $Scale["XMax"] = $XMax;
2601
      }
2602
2603
     return($Scale);
2604
    }
2605
2606
   function modulo($Value1,$Value2)
2607
    {
2608
     if (floor($Value2) == 0) { return(0); }
2609
     if (floor($Value2) != 0) { return($Value1 % $Value2); }
2610
2611
     $MinValue = min($Value1,$Value2); $Factor = 10;
2612
     while ( floor($MinValue*$Factor) == 0 )
2613
      { $Factor = $Factor * 10; }
2614
2615
     return(($Value1*$Factor) % ($Value2*$Factor));
2616
    }
2617
2618
   /* Draw an X threshold */
2619
   function drawXThreshold($Value,$Format="")
2620
    {
2621
     $R			= isset($Format["R"]) ? $Format["R"] : 255;
2622
     $G			= isset($Format["G"]) ? $Format["G"] : 0;
2623
     $B			= isset($Format["B"]) ? $Format["B"] : 0;
2624
     $Alpha		= isset($Format["Alpha"]) ? $Format["Alpha"] : 50;
2625
     $Weight		= isset($Format["Weight"]) ? $Format["Weight"] : NULL;
2626
     $Ticks		= isset($Format["Ticks"]) ? $Format["Ticks"] : 6;
2627
     $Wide		= isset($Format["Wide"]) ? $Format["Wide"] : FALSE;
2628
     $WideFactor	= isset($Format["WideFactor"]) ? $Format["WideFactor"] : 5;
2629
     $WriteCaption	= isset($Format["WriteCaption"]) ? $Format["WriteCaption"] : FALSE;
2630
     $Caption		= isset($Format["Caption"]) ? $Format["Caption"] : NULL;
2631
     $CaptionAlign	= isset($Format["CaptionAlign"]) ? $Format["CaptionAlign"] : CAPTION_LEFT_TOP;
2632
     $CaptionOffset     = isset($Format["CaptionOffset"]) ? $Format["CaptionOffset"] : 5;
2633
     $CaptionR		= isset($Format["CaptionR"]) ? $Format["CaptionR"] : 255;
2634
     $CaptionG		= isset($Format["CaptionG"]) ? $Format["CaptionG"] : 255;
2635
     $CaptionB		= isset($Format["CaptionB"]) ? $Format["CaptionB"] : 255;
2636
     $CaptionAlpha	= isset($Format["CaptionAlpha"]) ? $Format["CaptionAlpha"] : 100;
2637
     $DrawBox		= isset($Format["DrawBox"]) ? $Format["DrawBox"] : TRUE;
2638
     $DrawBoxBorder	= isset($Format["DrawBoxBorder"]) ? $Format["DrawBoxBorder"] : FALSE;
2639
     $BorderOffset	= isset($Format["BorderOffset"]) ? $Format["BorderOffset"] : 3;
2640
     $BoxRounded	= isset($Format["BoxRounded"]) ? $Format["BoxRounded"] : TRUE;
2641
     $RoundedRadius	= isset($Format["RoundedRadius"]) ? $Format["RoundedRadius"] : 3;
2642
     $BoxR		= isset($Format["BoxR"]) ? $Format["BoxR"] : 0;
2643
     $BoxG		= isset($Format["BoxG"]) ? $Format["BoxG"] : 0;
2644
     $BoxB		= isset($Format["BoxB"]) ? $Format["BoxB"] : 0;
2645
     $BoxAlpha		= isset($Format["BoxAlpha"]) ? $Format["BoxAlpha"] : 30;
2646
     $BoxSurrounding	= isset($Format["BoxSurrounding"]) ? $Format["BoxSurrounding"] : "";
2647
     $BoxBorderR	= isset($Format["BoxBorderR"]) ? $Format["BoxBorderR"] : 255;
2648
     $BoxBorderG	= isset($Format["BoxBorderG"]) ? $Format["BoxBorderG"] : 255;
2649
     $BoxBorderB	= isset($Format["BoxBorderB"]) ? $Format["BoxBorderB"] : 255;
2650
     $BoxBorderAlpha	= isset($Format["BoxBorderAlpha"]) ? $Format["BoxBorderAlpha"] : 100;
2651
     $ValueIsLabel	= isset($Format["ValueIsLabel"]) ? $Format["ValueIsLabel"] : FALSE;
2652
2653
     $Data           = $this->DataSet->getData();
2654
     $AbscissaMargin = $this->getAbscissaMargin($Data);
2655
     $XScale         = $this->scaleGetXSettings();
2656
2657
     if ( is_array($Value) ) { foreach ($Value as $Key => $ID) { $this->drawXThreshold($ID,$Format); } return(0); }
2658
2659
     if ( $ValueIsLabel )
2660
      {
2661
       $Format["ValueIsLabel"] = FALSE;
2662
       foreach($Data["Series"][$Data["Abscissa"]]["Data"] as $Key => $SerieValue)
2663
        { if ( $SerieValue == $Value ) { $this->drawXThreshold($Key,$Format); } }
2664
2665
       return(0);
2666
      }
2667
2668
     $CaptionSettings = array("DrawBox"=>$DrawBox,"DrawBoxBorder"=>$DrawBoxBorder,"BorderOffset"=>$BorderOffset,"BoxRounded"=>$BoxRounded,"RoundedRadius"=>$RoundedRadius,
2669
                              "BoxR"=>$BoxR,"BoxG"=>$BoxG,"BoxB"=>$BoxB,"BoxAlpha"=>$BoxAlpha,"BoxSurrounding"=>$BoxSurrounding,
2670
                              "BoxBorderR"=>$BoxBorderR,"BoxBorderG"=>$BoxBorderG,"BoxBorderB"=>$BoxBorderB,"BoxBorderAlpha"=>$BoxBorderAlpha,
2671
                              "R"=>$CaptionR,"G"=>$CaptionG,"B"=>$CaptionB,"Alpha"=>$CaptionAlpha);
2672
2673
     if ( $Caption == NULL )
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $Caption of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
2674
      {
2675
       if ( isset($Data["Abscissa"]) )
2676
        {
2677
         if ( isset($Data["Series"][$Data["Abscissa"]]["Data"][$Value]) )
2678
          $Caption = $Data["Series"][$Data["Abscissa"]]["Data"][$Value];
2679
         else
2680
          $Caption = $Value;
2681
        }
2682
       else
2683
        $Caption = $Value;
2684
      }
2685
2686
     if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT )
2687
      {
2688
       $XStep = (($this->GraphAreaX2 - $this->GraphAreaX1) - $XScale[0] *2 ) / $XScale[1];
2689
       $XPos  = $this->GraphAreaX1 + $XScale[0] + $XStep * $Value;
2690
       $YPos1 = $this->GraphAreaY1 + $Data["YMargin"];
2691
       $YPos2 = $this->GraphAreaY2 - $Data["YMargin"];
2692
2693
       if ( $XPos >= $this->GraphAreaX1 + $AbscissaMargin && $XPos <= $this->GraphAreaX2 - $AbscissaMargin )
2694
        {
2695
         $this->drawLine($XPos,$YPos1,$XPos,$YPos2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight));
2696
2697
         if ( $Wide )
2698
          {
2699
           $this->drawLine($XPos-1,$YPos1,$XPos-1,$YPos2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks));
2700
           $this->drawLine($XPos+1,$YPos1,$XPos+1,$YPos2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks));
2701
          }
2702
2703
         if ( $WriteCaption )
2704
          {
2705
           if ( $CaptionAlign == CAPTION_LEFT_TOP )
2706
            { $Y = $YPos1 + $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_TOPMIDDLE; }
2707
           else 
2708
            { $Y = $YPos2 - $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_BOTTOMMIDDLE; }
2709
           
2710
           $this->drawText($XPos,$Y,$Caption,$CaptionSettings);
2711
          }
2712
2713
         return(array("X"=>$XPos));
2714
        }
2715
      }
2716
     elseif( $Data["Orientation"] == SCALE_POS_TOPBOTTOM )
2717
      {
2718
       $XStep = (($this->GraphAreaY2 - $this->GraphAreaY1) - $XScale[0] *2 ) / $XScale[1];
2719
       $XPos  = $this->GraphAreaY1 + $XScale[0] + $XStep * $Value;
2720
       $YPos1 = $this->GraphAreaX1 + $Data["YMargin"];
2721
       $YPos2 = $this->GraphAreaX2 - $Data["YMargin"];
2722
2723
       if ( $XPos >= $this->GraphAreaY1 + $AbscissaMargin && $XPos <= $this->GraphAreaY2 - $AbscissaMargin )
2724
        {
2725
         $this->drawLine($YPos1,$XPos,$YPos2,$XPos,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight));
2726
2727
         if ( $Wide )
2728
          {
2729
           $this->drawLine($YPos1,$XPos-1,$YPos2,$XPos-1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks));
2730
           $this->drawLine($YPos1,$XPos+1,$YPos2,$XPos+1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks));
2731
          }
2732
2733
         if ( $WriteCaption )
2734
          {
2735
           if ( $CaptionAlign == CAPTION_LEFT_TOP )
2736
            { $Y = $YPos1 + $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_MIDDLELEFT; }
2737
           else 
2738
            { $Y = $YPos2 - $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_MIDDLERIGHT; }
2739
           
2740
           $this->drawText($Y,$XPos,$Caption,$CaptionSettings);
2741
          }
2742
2743
         return(array("X"=>$XPos));
2744
        }
2745
      }
2746
    }
2747
2748
   /* Draw an X threshold area */
2749
   function drawXThresholdArea($Value1,$Value2,$Format="")
2750
    {
2751
     $R		= isset($Format["R"]) ? $Format["R"] : 255;
2752
     $G		= isset($Format["G"]) ? $Format["G"] : 0;
2753
     $B		= isset($Format["B"]) ? $Format["B"] : 0;
2754
     $Alpha	= isset($Format["Alpha"]) ? $Format["Alpha"] : 20;
2755
     $Border    = isset($Format["Border"]) ? $Format["Border"] : TRUE;
2756
     $BorderR   = isset($Format["BorderR"]) ? $Format["BorderR"] : $R;
2757
     $BorderG   = isset($Format["BorderG"]) ? $Format["BorderG"] : $G;
2758
     $BorderB   = isset($Format["BorderB"]) ? $Format["BorderB"] : $B;
2759
     $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : $Alpha + 20;
2760
     $BorderTicks = isset($Format["BorderTicks"]) ? $Format["BorderTicks"] : 2;
2761
     $AreaName 	= isset($Format["AreaName"]) ? $Format["AreaName"] : NULL;
2762
     $NameAngle	= isset($Format["NameAngle"]) ? $Format["NameAngle"] : ZONE_NAME_ANGLE_AUTO;
2763
     $NameR	= isset($Format["NameR"]) ? $Format["NameR"] : 255;
2764
     $NameG	= isset($Format["NameG"]) ? $Format["NameG"] : 255;
2765
     $NameB	= isset($Format["NameB"]) ? $Format["NameB"] : 255;
2766
     $NameAlpha	= isset($Format["NameAlpha"]) ? $Format["NameAlpha"] : 100;
2767
     $DisableShadowOnArea = isset($Format["DisableShadowOnArea"]) ? $Format["DisableShadowOnArea"] : TRUE;
2768
2769
     $RestoreShadow = $this->Shadow;
2770
     if ( $DisableShadowOnArea && $this->Shadow ) { $this->Shadow = FALSE; }
2771
2772
     if ($BorderAlpha >100) { $BorderAlpha = 100;}
2773
2774
     $Data           = $this->DataSet->getData();
2775
     $XScale         = $this->scaleGetXSettings();
2776
     $AbscissaMargin = $this->getAbscissaMargin($Data);
2777
2778
     if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT )
2779
      {
2780
       $XStep = (($this->GraphAreaX2 - $this->GraphAreaX1) - $XScale[0] *2 ) / $XScale[1];
2781
       $XPos1 = $this->GraphAreaX1 + $XScale[0] + $XStep * $Value1;
2782
       $XPos2 = $this->GraphAreaX1 + $XScale[0] + $XStep * $Value2;
2783
       $YPos1 = $this->GraphAreaY1 + $Data["YMargin"];
2784
       $YPos2 = $this->GraphAreaY2 - $Data["YMargin"];
2785
2786
       if ( $XPos1 < $this->GraphAreaX1 + $XScale[0] ) { $XPos1 = $this->GraphAreaX1 + $XScale[0]; }
2787
       if ( $XPos1 > $this->GraphAreaX2 - $XScale[0] ) { $XPos1 = $this->GraphAreaX2 - $XScale[0]; }
2788
       if ( $XPos2 < $this->GraphAreaX1 + $XScale[0] ) { $XPos2 = $this->GraphAreaX1 + $XScale[0]; }
2789
       if ( $XPos2 > $this->GraphAreaX2 - $XScale[0] ) { $XPos2 = $this->GraphAreaX2 - $XScale[0]; }
2790
2791
       $this->drawFilledRectangle($XPos1,$YPos1,$XPos2,$YPos2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
2792
2793
       if ( $Border )
2794
        {
2795
         $this->drawLine($XPos1,$YPos1,$XPos1,$YPos2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks));
2796
         $this->drawLine($XPos2,$YPos1,$XPos2,$YPos2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks));
2797
        }
2798
2799
       if ( $AreaName != NULL )
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $AreaName of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
2800
        {
2801
         $XPos = ($XPos2-$XPos1)/2 + $XPos1;
2802
         $YPos = ($YPos2-$YPos1)/2 + $YPos1;
2803
2804
         if ( $NameAngle == ZONE_NAME_ANGLE_AUTO )
2805
          {
2806
           $TxtPos   = $this->getTextBox($XPos,$YPos,$this->FontName,$this->FontSize,0,$AreaName);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getTextBox() does only exist in the following sub-classes of pDraw: pImage. 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...
2807
           $TxtWidth = $TxtPos[1]["X"] - $TxtPos[0]["X"];
2808
           if ( abs($XPos2 - $XPos1) > $TxtWidth ) { $NameAngle = 0; } else { $NameAngle = 90; }
2809
          }
2810
         $this->Shadow = $RestoreShadow;
2811
         $this->drawText($XPos,$YPos,$AreaName,array("R"=>$NameR,"G"=>$NameG,"B"=>$NameB,"Alpha"=>$NameAlpha,"Angle"=>$NameAngle,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE));
2812
         if ( $DisableShadowOnArea ) { $this->Shadow = FALSE; }
2813
        }
2814
2815
       $this->Shadow = $RestoreShadow;
2816
       return(array("X1"=>$XPos1,"X2"=>$XPos2));
2817
      }
2818
     elseif ( $Data["Orientation"] == SCALE_POS_TOPBOTTOM )
2819
      {
2820
       $XStep = (($this->GraphAreaY2 - $this->GraphAreaY1) - $XScale[0] *2 ) / $XScale[1];
2821
       $XPos1 = $this->GraphAreaY1 + $XScale[0] + $XStep * $Value1;
2822
       $XPos2 = $this->GraphAreaY1 + $XScale[0] + $XStep * $Value2;
2823
       $YPos1 = $this->GraphAreaX1 + $Data["YMargin"];
2824
       $YPos2 = $this->GraphAreaX2 - $Data["YMargin"];
2825
2826
       if ( $XPos1 < $this->GraphAreaY1 + $XScale[0] ) { $XPos1 = $this->GraphAreaY1 + $XScale[0]; }
2827
       if ( $XPos1 > $this->GraphAreaY2 - $XScale[0] ) { $XPos1 = $this->GraphAreaY2 - $XScale[0]; }
2828
       if ( $XPos2 < $this->GraphAreaY1 + $XScale[0] ) { $XPos2 = $this->GraphAreaY1 + $XScale[0]; }
2829
       if ( $XPos2 > $this->GraphAreaY2 - $XScale[0] ) { $XPos2 = $this->GraphAreaY2 - $XScale[0]; }
2830
2831
       $this->drawFilledRectangle($YPos1,$XPos1,$YPos2,$XPos2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
2832
2833
       if ( $Border )
2834
        {
2835
         $this->drawLine($YPos1,$XPos1,$YPos2,$XPos1,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks));
2836
         $this->drawLine($YPos1,$XPos2,$YPos2,$XPos2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks));
2837
        }
2838
2839
       if ( $AreaName != NULL )
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $AreaName of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
2840
        {
2841
         $XPos = ($XPos2-$XPos1)/2 + $XPos1;
2842
         $YPos = ($YPos2-$YPos1)/2 + $YPos1;
2843
2844
         $this->Shadow = $RestoreShadow;
2845
         $this->drawText($YPos,$XPos,$AreaName,array("R"=>$NameR,"G"=>$NameG,"B"=>$NameB,"Alpha"=>$NameAlpha,"Angle"=>0,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE));
2846
         if ( $DisableShadowOnArea ) { $this->Shadow = FALSE; }
2847
        }
2848
2849
       $this->Shadow = $RestoreShadow;
2850
       return(array("X1"=>$XPos1,"X2"=>$XPos2));
2851
      }
2852
    }
2853
2854
   /* Draw an Y threshold with the computed scale */
2855
   function drawThreshold($Value,$Format="")
2856
    {
2857
     $AxisID		= isset($Format["AxisID"]) ? $Format["AxisID"] : 0;
2858
     $R			= isset($Format["R"]) ? $Format["R"] : 255;
2859
     $G			= isset($Format["G"]) ? $Format["G"] : 0;
2860
     $B			= isset($Format["B"]) ? $Format["B"] : 0;
2861
     $Alpha		= isset($Format["Alpha"]) ? $Format["Alpha"] : 50;
2862
     $Weight		= isset($Format["Weight"]) ? $Format["Weight"] : NULL;
2863
     $Ticks		= isset($Format["Ticks"]) ? $Format["Ticks"] : 6;
2864
     $Wide		= isset($Format["Wide"]) ? $Format["Wide"] : FALSE;
2865
     $WideFactor	= isset($Format["WideFactor"]) ? $Format["WideFactor"] : 5;
2866
     $WriteCaption	= isset($Format["WriteCaption"]) ? $Format["WriteCaption"] : FALSE;
2867
     $Caption		= isset($Format["Caption"]) ? $Format["Caption"] : NULL;
2868
     $CaptionAlign	= isset($Format["CaptionAlign"]) ? $Format["CaptionAlign"] : CAPTION_LEFT_TOP;
2869
     $CaptionOffset     = isset($Format["CaptionOffset"]) ? $Format["CaptionOffset"] : 10;
2870
     $CaptionR		= isset($Format["CaptionR"]) ? $Format["CaptionR"] : 255;
2871
     $CaptionG		= isset($Format["CaptionG"]) ? $Format["CaptionG"] : 255;
2872
     $CaptionB		= isset($Format["CaptionB"]) ? $Format["CaptionB"] : 255;
2873
     $CaptionAlpha	= isset($Format["CaptionAlpha"]) ? $Format["CaptionAlpha"] : 100;
2874
     $DrawBox		= isset($Format["DrawBox"]) ? $Format["DrawBox"] : TRUE;
2875
     $DrawBoxBorder	= isset($Format["DrawBoxBorder"]) ? $Format["DrawBoxBorder"] : FALSE;
2876
     $BorderOffset	= isset($Format["BorderOffset"]) ? $Format["BorderOffset"] : 5;
2877
     $BoxRounded	= isset($Format["BoxRounded"]) ? $Format["BoxRounded"] : TRUE;
2878
     $RoundedRadius	= isset($Format["RoundedRadius"]) ? $Format["RoundedRadius"] : 3;
2879
     $BoxR		= isset($Format["BoxR"]) ? $Format["BoxR"] : 0;
2880
     $BoxG		= isset($Format["BoxG"]) ? $Format["BoxG"] : 0;
2881
     $BoxB		= isset($Format["BoxB"]) ? $Format["BoxB"] : 0;
2882
     $BoxAlpha		= isset($Format["BoxAlpha"]) ? $Format["BoxAlpha"] : 20;
2883
     $BoxSurrounding	= isset($Format["BoxSurrounding"]) ? $Format["BoxSurrounding"] : "";
2884
     $BoxBorderR	= isset($Format["BoxBorderR"]) ? $Format["BoxBorderR"] : 255;
2885
     $BoxBorderG	= isset($Format["BoxBorderG"]) ? $Format["BoxBorderG"] : 255;
2886
     $BoxBorderB	= isset($Format["BoxBorderB"]) ? $Format["BoxBorderB"] : 255;
2887
     $BoxBorderAlpha	= isset($Format["BoxBorderAlpha"]) ? $Format["BoxBorderAlpha"] : 100;
2888
     $NoMargin		= isset($Format["NoMargin"]) ? $Format["NoMargin"] : FALSE;
2889
2890
     if ( is_array($Value) ) { foreach ($Value as $Key => $ID) { $this->drawThreshold($ID,$Format); } return(0); }
2891
2892
     $CaptionSettings = array("DrawBox"=>$DrawBox,"DrawBoxBorder"=>$DrawBoxBorder,"BorderOffset"=>$BorderOffset,"BoxRounded"=>$BoxRounded,"RoundedRadius"=>$RoundedRadius,
2893
                              "BoxR"=>$BoxR,"BoxG"=>$BoxG,"BoxB"=>$BoxB,"BoxAlpha"=>$BoxAlpha,"BoxSurrounding"=>$BoxSurrounding,
2894
                              "BoxBorderR"=>$BoxBorderR,"BoxBorderG"=>$BoxBorderG,"BoxBorderB"=>$BoxBorderB,"BoxBorderAlpha"=>$BoxBorderAlpha,
2895
                              "R"=>$CaptionR,"G"=>$CaptionG,"B"=>$CaptionB,"Alpha"=>$CaptionAlpha);
2896
2897
     $Data           = $this->DataSet->getData();
2898
     $AbscissaMargin = $this->getAbscissaMargin($Data);
2899
2900
     if ( $NoMargin ) { $AbscissaMargin = 0; }
2901
     if ( !isset($Data["Axis"][$AxisID]) ) { return(-1); }
2902
     if ( $Caption == NULL ) { $Caption = $Value; }
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $Caption of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
2903
2904
     if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT )
2905
      {
2906
       $YPos = $this->scaleComputeY($Value,array("AxisID"=>$AxisID));
2907
       if ( $YPos >= $this->GraphAreaY1+$Data["Axis"][$AxisID]["Margin"] && $YPos <= $this->GraphAreaY2-$Data["Axis"][$AxisID]["Margin"] )
2908
        {
2909
         $X1 = $this->GraphAreaX1 + $AbscissaMargin;
2910
         $X2 = $this->GraphAreaX2 - $AbscissaMargin;
2911
2912
         $this->drawLine($X1,$YPos,$X2,$YPos,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight));
2913
2914
         if ( $Wide )
2915
          {
2916
           $this->drawLine($X1,$YPos-1,$X2,$YPos-1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks));
2917
           $this->drawLine($X1,$YPos+1,$X2,$YPos+1,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks));
2918
          }
2919
2920
         if ( $WriteCaption )
2921
          {
2922
           if ( $CaptionAlign == CAPTION_LEFT_TOP )
2923
            { $X = $X1 + $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_MIDDLELEFT; }
2924
           else 
2925
            { $X = $X2 - $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_MIDDLERIGHT; }
2926
           
2927
           $this->drawText($X,$YPos,$Caption,$CaptionSettings);
2928
          }
2929
        }
2930
2931
       return(array("Y"=>$YPos));
2932
      }
2933
2934
     if ( $Data["Orientation"] == SCALE_POS_TOPBOTTOM )
2935
      {
2936
       $XPos = $this->scaleComputeY($Value,array("AxisID"=>$AxisID));
2937
       if ( $XPos >= $this->GraphAreaX1+$Data["Axis"][$AxisID]["Margin"] && $XPos <= $this->GraphAreaX2-$Data["Axis"][$AxisID]["Margin"] )
2938
        {
2939
         $Y1 = $this->GraphAreaY1 + $AbscissaMargin;
2940
         $Y2 = $this->GraphAreaY2 - $AbscissaMargin;
2941
2942
         $this->drawLine($XPos,$Y1,$XPos,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight));
2943
2944
         if ( $Wide )
2945
          {
2946
           $this->drawLine($XPos-1,$Y1,$XPos-1,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks));
2947
           $this->drawLine($XPos+1,$Y1,$XPos+1,$Y2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/$WideFactor,"Ticks"=>$Ticks));
2948
          }
2949
2950
         if ( $WriteCaption )
2951
          {
2952
           if ( $CaptionAlign == CAPTION_LEFT_TOP )
2953
            { $Y = $Y1 + $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_TOPMIDDLE; }
2954
           else 
2955
            { $Y = $Y2 - $CaptionOffset; $CaptionSettings["Align"] = TEXT_ALIGN_BOTTOMMIDDLE; }
2956
2957
           $CaptionSettings["Align"] = TEXT_ALIGN_TOPMIDDLE;
2958
           $this->drawText($XPos,$Y,$Caption,$CaptionSettings);
2959
          }
2960
        }
2961
2962
       return(array("Y"=>$XPos));
2963
      }
2964
    }
2965
2966
   /* Draw a threshold with the computed scale */
2967
   function drawThresholdArea($Value1,$Value2,$Format="")
2968
    {
2969
     $AxisID	= isset($Format["AxisID"]) ? $Format["AxisID"] : 0;
2970
     $R		= isset($Format["R"]) ? $Format["R"] : 255;
2971
     $G		= isset($Format["G"]) ? $Format["G"] : 0;
2972
     $B		= isset($Format["B"]) ? $Format["B"] : 0;
2973
     $Alpha	= isset($Format["Alpha"]) ? $Format["Alpha"] : 20;
2974
     $Border    = isset($Format["Border"]) ? $Format["Border"] : TRUE;
2975
     $BorderR   = isset($Format["BorderR"]) ? $Format["BorderR"] : $R;
2976
     $BorderG   = isset($Format["BorderG"]) ? $Format["BorderG"] : $G;
2977
     $BorderB   = isset($Format["BorderB"]) ? $Format["BorderB"] : $B;
2978
     $BorderAlpha = isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : $Alpha + 20;
2979
     $BorderTicks = isset($Format["BorderTicks"]) ? $Format["BorderTicks"] : 2;
2980
     $AreaName 	= isset($Format["AreaName"]) ? $Format["AreaName"] : NULL;
2981
     $NameAngle	= isset($Format["NameAngle"]) ? $Format["NameAngle"] : ZONE_NAME_ANGLE_AUTO;
2982
     $NameR	= isset($Format["NameR"]) ? $Format["NameR"] : 255;
2983
     $NameG	= isset($Format["NameG"]) ? $Format["NameG"] : 255;
2984
     $NameB	= isset($Format["NameB"]) ? $Format["NameB"] : 255;
2985
     $NameAlpha	= isset($Format["NameAlpha"]) ? $Format["NameAlpha"] : 100;
2986
     $DisableShadowOnArea = isset($Format["DisableShadowOnArea"]) ? $Format["DisableShadowOnArea"] : TRUE;
2987
     $NoMargin	= isset($Format["NoMargin"]) ? $Format["NoMargin"] : FALSE;
2988
2989
     if ($Value1 > $Value2) { list($Value1, $Value2) = array($Value2, $Value1); }
2990
2991
     $RestoreShadow = $this->Shadow;
2992
     if ( $DisableShadowOnArea && $this->Shadow ) { $this->Shadow = FALSE; }
2993
2994
     if ($BorderAlpha >100) { $BorderAlpha = 100;}
2995
2996
     $Data           = $this->DataSet->getData();
2997
     $AbscissaMargin = $this->getAbscissaMargin($Data);
2998
2999
     if ( $NoMargin ) { $AbscissaMargin = 0; }
3000
     if ( !isset($Data["Axis"][$AxisID]) ) { return(-1); }
3001
3002
     if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT )
3003
      {
3004
       $XPos1 = $this->GraphAreaX1 + $AbscissaMargin;
3005
       $XPos2 = $this->GraphAreaX2 - $AbscissaMargin;
3006
       $YPos1 = $this->scaleComputeY($Value1,array("AxisID"=>$AxisID));
3007
       $YPos2 = $this->scaleComputeY($Value2,array("AxisID"=>$AxisID));
3008
3009
       if ( $YPos1 < $this->GraphAreaY1+$Data["Axis"][$AxisID]["Margin"] ) { $YPos1 = $this->GraphAreaY1+$Data["Axis"][$AxisID]["Margin"]; }
3010
       if ( $YPos1 > $this->GraphAreaY2-$Data["Axis"][$AxisID]["Margin"] ) { $YPos1 = $this->GraphAreaY2-$Data["Axis"][$AxisID]["Margin"]; }
3011
       if ( $YPos2 < $this->GraphAreaY1+$Data["Axis"][$AxisID]["Margin"] ) { $YPos2 = $this->GraphAreaY1+$Data["Axis"][$AxisID]["Margin"]; }
3012
       if ( $YPos2 > $this->GraphAreaY2-$Data["Axis"][$AxisID]["Margin"] ) { $YPos2 = $this->GraphAreaY2-$Data["Axis"][$AxisID]["Margin"]; }
3013
3014
       $this->drawFilledRectangle($XPos1,$YPos1,$XPos2,$YPos2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
3015
       if ( $Border )
3016
        {
3017
         $this->drawLine($XPos1,$YPos1,$XPos2,$YPos1,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks));
3018
         $this->drawLine($XPos1,$YPos2,$XPos2,$YPos2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks));
3019
        }
3020
3021
       if ( $AreaName != NULL )
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $AreaName of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
3022
        {
3023
         $XPos = ($XPos2-$XPos1)/2 + $XPos1;
3024
         $YPos = ($YPos2-$YPos1)/2 + $YPos1;
3025
         $this->Shadow = $RestoreShadow;
3026
         $this->drawText($XPos,$YPos,$AreaName,array("R"=>$NameR,"G"=>$NameG,"B"=>$NameB,"Alpha"=>$NameAlpha,"Angle"=>0,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE));
3027
         if ( $DisableShadowOnArea ) { $this->Shadow = FALSE; }
3028
        }
3029
3030
       $this->Shadow = $RestoreShadow;
3031
       return(array("Y1"=>$YPos1,"Y2"=>$YPos2));
3032
      }
3033
     elseif ( $Data["Orientation"] == SCALE_POS_TOPBOTTOM )
3034
      {
3035
       $YPos1 = $this->GraphAreaY1 + $AbscissaMargin;
3036
       $YPos2 = $this->GraphAreaY2 - $AbscissaMargin;
3037
       $XPos1 = $this->scaleComputeY($Value1,array("AxisID"=>$AxisID));
3038
       $XPos2 = $this->scaleComputeY($Value2,array("AxisID"=>$AxisID));
3039
3040
       if ( $XPos1 < $this->GraphAreaX1+$Data["Axis"][$AxisID]["Margin"] ) { $XPos1 = $this->GraphAreaX1+$Data["Axis"][$AxisID]["Margin"]; }
3041
       if ( $XPos1 > $this->GraphAreaX2-$Data["Axis"][$AxisID]["Margin"] ) { $XPos1 = $this->GraphAreaX2-$Data["Axis"][$AxisID]["Margin"]; }
3042
       if ( $XPos2 < $this->GraphAreaX1+$Data["Axis"][$AxisID]["Margin"] ) { $XPos2 = $this->GraphAreaX1+$Data["Axis"][$AxisID]["Margin"]; }
3043
       if ( $XPos2 > $this->GraphAreaX2-$Data["Axis"][$AxisID]["Margin"] ) { $XPos2 = $this->GraphAreaX2-$Data["Axis"][$AxisID]["Margin"]; }
3044
3045
       $this->drawFilledRectangle($XPos1,$YPos1,$XPos2,$YPos2,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
3046
       if ( $Border )
3047
        {
3048
         $this->drawLine($XPos1,$YPos1,$XPos1,$YPos2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks));
3049
         $this->drawLine($XPos2,$YPos1,$XPos2,$YPos2,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Ticks"=>$BorderTicks));
3050
        }
3051
3052
       if ( $AreaName != NULL )
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $AreaName of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
3053
        {
3054
         $XPos = ($YPos2-$YPos1)/2 + $YPos1;
3055
         $YPos = ($XPos2-$XPos1)/2 + $XPos1;
3056
3057
         if ( $NameAngle == ZONE_NAME_ANGLE_AUTO )
3058
          {
3059
           $TxtPos   = $this->getTextBox($XPos,$YPos,$this->FontName,$this->FontSize,0,$AreaName);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getTextBox() does only exist in the following sub-classes of pDraw: pImage. 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...
3060
           $TxtWidth = $TxtPos[1]["X"] - $TxtPos[0]["X"];
3061
           if ( abs($XPos2 - $XPos1) > $TxtWidth ) { $NameAngle = 0; } else { $NameAngle = 90; }
3062
          }
3063
         $this->Shadow = $RestoreShadow;
3064
         $this->drawText($YPos,$XPos,$AreaName,array("R"=>$NameR,"G"=>$NameG,"B"=>$NameB,"Alpha"=>$NameAlpha,"Angle"=>$NameAngle,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE));
3065
         if ( $DisableShadowOnArea ) { $this->Shadow = FALSE; }
3066
        }
3067
3068
       $this->Shadow = $RestoreShadow;
3069
       return(array("Y1"=>$XPos1,"Y2"=>$XPos2));
3070
      }
3071
    }
3072
3073
   function scaleGetXSettings()
3074
    {
3075
     $Data = $this->DataSet->getData();
3076
     foreach($Data["Axis"] as $AxisID => $Settings)
3077
      {
3078
       if ( $Settings["Identity"] == AXIS_X )
3079
        {
3080
         $Rows = $Settings["Rows"];
3081
3082
         return(array($Settings["Margin"],$Rows));
3083
        }
3084
      }
3085
    }
3086
3087
   function scaleComputeY($Values,$Option="",$ReturnOnly0Height=FALSE)
3088
    {
3089
     $AxisID	= isset($Option["AxisID"]) ? $Option["AxisID"] : 0;
3090
     $SerieName	= isset($Option["SerieName"]) ? $Option["SerieName"] : NULL;
3091
3092
     $Data = $this->DataSet->getData();
3093
     if ( !isset($Data["Axis"][$AxisID]) ) { return(-1); }
3094
3095
     if ( $SerieName != NULL ) { $AxisID = $Data["Series"][$SerieName]["Axis"]; }
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $SerieName of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
3096
     if ( !is_array($Values) ) { $tmp = $Values; $Values = ""; $Values[0] = $tmp; }
3097
3098
     $Result = "";
3099
     if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT )
3100
      {
3101
       $Height      = ($this->GraphAreaY2 - $this->GraphAreaY1) - $Data["Axis"][$AxisID]["Margin"]*2;
3102
       $ScaleHeight = $Data["Axis"][$AxisID]["ScaleMax"] - $Data["Axis"][$AxisID]["ScaleMin"];
3103
       $Step        = $Height / $ScaleHeight;
3104
3105
       if ( $ReturnOnly0Height )
3106
        { foreach($Values as $Key => $Value) { if ( $Value == VOID ) { $Result[] = VOID; } else { $Result[] = $Step * $Value; } } }
0 ignored issues
show
Bug introduced by
The expression $Values of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
3107
       else
3108
        { foreach($Values as $Key => $Value) { if ( $Value == VOID ) { $Result[] = VOID; } else { $Result[] = $this->GraphAreaY2 - $Data["Axis"][$AxisID]["Margin"] - ($Step * ($Value-$Data["Axis"][$AxisID]["ScaleMin"])); } } }
0 ignored issues
show
Bug introduced by
The expression $Values of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
3109
      }
3110
     else
3111
      {
3112
       $Width      = ($this->GraphAreaX2 - $this->GraphAreaX1) - $Data["Axis"][$AxisID]["Margin"]*2;
3113
       $ScaleWidth = $Data["Axis"][$AxisID]["ScaleMax"] - $Data["Axis"][$AxisID]["ScaleMin"];
3114
       $Step       = $Width / $ScaleWidth;
3115
3116
       if ( $ReturnOnly0Height )
3117
        { foreach($Values as $Key => $Value) { if ( $Value == VOID ) { $Result[] = VOID; } else { $Result[] = $Step * $Value; } } }
0 ignored issues
show
Bug introduced by
The expression $Values of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
3118
       else
3119
        { foreach($Values as $Key => $Value) { if ( $Value == VOID ) { $Result[] = VOID; } else { $Result[] = $this->GraphAreaX1 + $Data["Axis"][$AxisID]["Margin"] + ($Step * ($Value-$Data["Axis"][$AxisID]["ScaleMin"])); } } }
0 ignored issues
show
Bug introduced by
The expression $Values of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
3120
      }
3121
3122
     if ( count($Result) == 1 )
3123
      return($Result[0]);
3124
     else
3125
      return($Result);
3126
    }
3127
3128
   /* Format the axis values */
3129
   function scaleFormat($Value,$Mode=NULL,$Format=NULL,$Unit=NULL)
3130
    {
3131
     if ( $Value == VOID ) { return(""); }
3132
3133
     if ( $Mode == AXIS_FORMAT_TRAFFIC )
3134
      {
3135
       if ( $Value == 0 ) { return("0B"); }
3136
       $Units = array("B","KB","MB","GB","TB","PB");
3137
       $Sign = ""; if ( $Value < 0 ) { $Value = abs($Value); $Sign = "-"; }
3138
3139
       $Value = number_format($Value/pow(1024,($Scale=floor(log($Value,1024)))),2,",",".");
3140
       return($Sign.$Value." ".$Units[$Scale]);
3141
      }
3142
3143
     if ( $Mode == AXIS_FORMAT_CUSTOM )
3144
      { if ( function_exists($Format) ) { return(call_user_func($Format,$Value)); } }
3145
3146
     if ( $Mode == AXIS_FORMAT_DATE )
3147
      { if ( $Format == NULL ) { $Pattern = "d/m/Y"; } else { $Pattern = $Format; } return(gmdate($Pattern,$Value)); }
3148
3149
     if ( $Mode == AXIS_FORMAT_TIME )
3150
      { if ( $Format == NULL ) { $Pattern = "H:i:s"; } else { $Pattern = $Format; } return(gmdate($Pattern,$Value)); }
3151
3152
     if ( $Mode == AXIS_FORMAT_CURRENCY )
3153
      { return($Format.number_format($Value,2)); }
3154
3155
     if ( $Mode == AXIS_FORMAT_METRIC )
3156
      {
3157
       if (abs($Value) > 1000000000)
3158
        return(round($Value/1000000000,$Format)."g".$Unit);
3159
       if (abs($Value) > 1000000)
3160
        return(round($Value/1000000,$Format)."m".$Unit);
3161
       elseif (abs($Value) >= 1000)
3162
        return(round($Value/1000,$Format)."k".$Unit);
3163
       
3164
      }
3165
     return($Value.$Unit);
3166
    }
3167
3168
   /* Write Max value on a chart */
3169
   function writeBounds($Type=BOUND_BOTH,$Format=NULL)
3170
    {
3171
     $MaxLabelTxt	= isset($Format["MaxLabelTxt"]) ? $Format["MaxLabelTxt"] : "max=";
3172
     $MinLabelTxt	= isset($Format["MinLabelTxt"]) ? $Format["MinLabelTxt"] : "min=";
3173
     $Decimals		= isset($Format["Decimals"]) ? $Format["Decimals"] : 1;
3174
     $ExcludedSeries	= isset($Format["ExcludedSeries"]) ? $Format["ExcludedSeries"] : "";
3175
     $DisplayOffset	= isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 4;
3176
     $DisplayColor	= isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL;
3177
     $MaxDisplayR	= isset($Format["MaxDisplayR"]) ? $Format["MaxDisplayR"] : 0;
3178
     $MaxDisplayG	= isset($Format["MaxDisplayG"]) ? $Format["MaxDisplayG"] : 0;
3179
     $MaxDisplayB	= isset($Format["MaxDisplayB"]) ? $Format["MaxDisplayB"] : 0;
3180
     $MinDisplayR	= isset($Format["MinDisplayR"]) ? $Format["MinDisplayR"] : 255;
3181
     $MinDisplayG	= isset($Format["MinDisplayG"]) ? $Format["MinDisplayG"] : 255;
3182
     $MinDisplayB	= isset($Format["MinDisplayB"]) ? $Format["MinDisplayB"] : 255;
3183
     $MinLabelPos	= isset($Format["MinLabelPos"]) ? $Format["MinLabelPos"] : BOUND_LABEL_POS_AUTO;
3184
     $MaxLabelPos	= isset($Format["MaxLabelPos"]) ? $Format["MaxLabelPos"] : BOUND_LABEL_POS_AUTO;
3185
     $DrawBox		= isset($Format["DrawBox"]) ? $Format["DrawBox"] : TRUE;
3186
     $DrawBoxBorder	= isset($Format["DrawBoxBorder"]) ? $Format["DrawBoxBorder"] : FALSE;
3187
     $BorderOffset	= isset($Format["BorderOffset"]) ? $Format["BorderOffset"] : 5;
3188
     $BoxRounded	= isset($Format["BoxRounded"]) ? $Format["BoxRounded"] : TRUE;
3189
     $RoundedRadius	= isset($Format["RoundedRadius"]) ? $Format["RoundedRadius"] : 3;
3190
     $BoxR		= isset($Format["BoxR"]) ? $Format["BoxR"] : 0;
3191
     $BoxG		= isset($Format["BoxG"]) ? $Format["BoxG"] : 0;
3192
     $BoxB		= isset($Format["BoxB"]) ? $Format["BoxB"] : 0;
3193
     $BoxAlpha		= isset($Format["BoxAlpha"]) ? $Format["BoxAlpha"] : 20;
3194
     $BoxSurrounding	= isset($Format["BoxSurrounding"]) ? $Format["BoxSurrounding"] : "";
3195
     $BoxBorderR	= isset($Format["BoxBorderR"]) ? $Format["BoxBorderR"] : 255;
3196
     $BoxBorderG	= isset($Format["BoxBorderG"]) ? $Format["BoxBorderG"] : 255;
3197
     $BoxBorderB	= isset($Format["BoxBorderB"]) ? $Format["BoxBorderB"] : 255;
3198
     $BoxBorderAlpha	= isset($Format["BoxBorderAlpha"]) ? $Format["BoxBorderAlpha"] : 100;
3199
3200
     $CaptionSettings = array("DrawBox"=>$DrawBox,"DrawBoxBorder"=>$DrawBoxBorder,"BorderOffset"=>$BorderOffset,"BoxRounded"=>$BoxRounded,"RoundedRadius"=>$RoundedRadius,
3201
                              "BoxR"=>$BoxR,"BoxG"=>$BoxG,"BoxB"=>$BoxB,"BoxAlpha"=>$BoxAlpha,"BoxSurrounding"=>$BoxSurrounding,
3202
                              "BoxBorderR"=>$BoxBorderR,"BoxBorderG"=>$BoxBorderG,"BoxBorderB"=>$BoxBorderB,"BoxBorderAlpha"=>$BoxBorderAlpha);
3203
3204
     list($XMargin,$XDivs) = $this->scaleGetXSettings();
3205
3206
     $Data = $this->DataSet->getData();
3207
     foreach($Data["Series"] as $SerieName => $Serie)
3208
      {
3209
       if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] && !isset($ExcludedSeries[$SerieName]))
3210
        {
3211
         $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"];
3212
         if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; }
3213
3214
         $MinValue = $this->DataSet->getMin($SerieName);
3215
         $MaxValue = $this->DataSet->getMax($SerieName);
3216
3217
         $MinPos = VOID; $MaxPos = VOID;
3218
         foreach($Serie["Data"] as $Key => $Value)
3219
          { 
3220
           if ( $Value == $MinValue && $MinPos == VOID ) { $MinPos = $Key; }
3221
           if ( $Value == $MaxValue ) { $MaxPos = $Key; }
3222
          }
3223
3224
         $AxisID	= $Serie["Axis"];
3225
         $Mode		= $Data["Axis"][$AxisID]["Display"];
3226
         $Format	= $Data["Axis"][$AxisID]["Format"];
3227
         $Unit		= $Data["Axis"][$AxisID]["Unit"];
3228
3229
         $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"]));
3230
3231
         if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT )
3232
          {
3233
           $XStep       = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs;
3234
           $X           = $this->GraphAreaX1 + $XMargin;
3235
           $SerieOffset = isset($Serie["XOffset"]) ? $Serie["XOffset"] : 0;
3236
3237
           if ( $Type == BOUND_MAX || $Type == BOUND_BOTH )
3238
            {
3239
             if ( $MaxLabelPos == BOUND_LABEL_POS_TOP    || ( $MaxLabelPos ==  BOUND_LABEL_POS_AUTO && $MaxValue >= 0) ) { $YPos  = $PosArray[$MaxPos] - $DisplayOffset + 2; $Align = TEXT_ALIGN_BOTTOMMIDDLE; }
3240
             if ( $MaxLabelPos == BOUND_LABEL_POS_BOTTOM || ( $MaxLabelPos ==  BOUND_LABEL_POS_AUTO && $MaxValue < 0) ) { $YPos  = $PosArray[$MaxPos] + $DisplayOffset + 2; $Align = TEXT_ALIGN_TOPMIDDLE; }
3241
3242
             $XPos  = $X + $MaxPos*$XStep + $SerieOffset;
3243
             $Label = $MaxLabelTxt.$this->scaleFormat(round($MaxValue,$Decimals),$Mode,$Format,$Unit);
3244
3245
             $TxtPos  = $this->getTextBox($XPos,$YPos,$this->FontName,$this->FontSize,0,$Label);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getTextBox() does only exist in the following sub-classes of pDraw: pImage. 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...
3246
             $XOffset = 0; $YOffset = 0;
3247
             if ( $TxtPos[0]["X"] < $this->GraphAreaX1 ) { $XOffset = (($this->GraphAreaX1 - $TxtPos[0]["X"])/2); }
3248
             if ( $TxtPos[1]["X"] > $this->GraphAreaX2 ) { $XOffset = -(($TxtPos[1]["X"] - $this->GraphAreaX2)/2); }
3249
             if ( $TxtPos[2]["Y"] < $this->GraphAreaY1 ) { $YOffset = $this->GraphAreaY1 - $TxtPos[2]["Y"]; }
3250
             if ( $TxtPos[0]["Y"] > $this->GraphAreaY2 ) { $YOffset = -($TxtPos[0]["Y"] - $this->GraphAreaY2); }
3251
3252
             $CaptionSettings["R"] = $MaxDisplayR; $CaptionSettings["G"] = $MaxDisplayG;
3253
             $CaptionSettings["B"] = $MaxDisplayB; $CaptionSettings["Align"] = $Align;
3254
3255
             $this->drawText($XPos+$XOffset,$YPos+$YOffset,$Label,$CaptionSettings);
3256
            }
3257
3258
           if ( $Type == BOUND_MIN || $Type == BOUND_BOTH )
3259
            {
3260
             if ( $MinLabelPos == BOUND_LABEL_POS_TOP    || ( $MinLabelPos ==  BOUND_LABEL_POS_AUTO && $MinValue >= 0) ) { $YPos  = $PosArray[$MinPos] - $DisplayOffset + 2; $Align = TEXT_ALIGN_BOTTOMMIDDLE; }
3261
             if ( $MinLabelPos == BOUND_LABEL_POS_BOTTOM || ( $MinLabelPos ==  BOUND_LABEL_POS_AUTO && $MinValue < 0) ) { $YPos  = $PosArray[$MinPos] + $DisplayOffset + 2; $Align = TEXT_ALIGN_TOPMIDDLE; }
3262
3263
             $XPos  = $X + $MinPos*$XStep + $SerieOffset;
3264
             $Label = $MinLabelTxt.$this->scaleFormat(round($MinValue,$Decimals),$Mode,$Format,$Unit);
3265
3266
             $TxtPos  = $this->getTextBox($XPos,$YPos,$this->FontName,$this->FontSize,0,$Label);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getTextBox() does only exist in the following sub-classes of pDraw: pImage. 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...
3267
             $XOffset = 0; $YOffset = 0;
3268
             if ( $TxtPos[0]["X"] < $this->GraphAreaX1 ) { $XOffset = (($this->GraphAreaX1 - $TxtPos[0]["X"])/2); }
3269
             if ( $TxtPos[1]["X"] > $this->GraphAreaX2 ) { $XOffset = -(($TxtPos[1]["X"] - $this->GraphAreaX2)/2); }
3270
             if ( $TxtPos[2]["Y"] < $this->GraphAreaY1 ) { $YOffset = $this->GraphAreaY1 - $TxtPos[2]["Y"]; }
3271
             if ( $TxtPos[0]["Y"] > $this->GraphAreaY2 ) { $YOffset = -($TxtPos[0]["Y"] - $this->GraphAreaY2); }
3272
3273
             $CaptionSettings["R"] = $MinDisplayR; $CaptionSettings["G"] = $MinDisplayG;
3274
             $CaptionSettings["B"] = $MinDisplayB; $CaptionSettings["Align"] = $Align;
3275
3276
             $this->drawText($XPos+$XOffset,$YPos-$DisplayOffset+$YOffset,$Label,$CaptionSettings);
3277
            }
3278
          }
3279
         else
3280
          {
3281
           $XStep       = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs;
3282
           $X           = $this->GraphAreaY1 + $XMargin;
3283
           $SerieOffset = isset($Serie["XOffset"]) ? $Serie["XOffset"] : 0;
3284
3285
           if ( $Type == BOUND_MAX || $Type == BOUND_BOTH )
3286
            {
3287
             if ( $MaxLabelPos == BOUND_LABEL_POS_TOP    || ( $MaxLabelPos ==  BOUND_LABEL_POS_AUTO && $MaxValue >= 0) ) { $YPos  = $PosArray[$MaxPos] + $DisplayOffset + 2; $Align = TEXT_ALIGN_MIDDLELEFT; }
3288
             if ( $MaxLabelPos == BOUND_LABEL_POS_BOTTOM || ( $MaxLabelPos ==  BOUND_LABEL_POS_AUTO && $MaxValue < 0) ) { $YPos  = $PosArray[$MaxPos] - $DisplayOffset + 2; $Align = TEXT_ALIGN_MIDDLERIGHT; }
3289
3290
             $XPos  = $X + $MaxPos*$XStep + $SerieOffset;
3291
             $Label = $MaxLabelTxt.$this->scaleFormat($MaxValue,$Mode,$Format,$Unit);
3292
3293
             $TxtPos  = $this->getTextBox($YPos,$XPos,$this->FontName,$this->FontSize,0,$Label);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getTextBox() does only exist in the following sub-classes of pDraw: pImage. 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...
3294
             $XOffset = 0; $YOffset = 0;
3295
             if ( $TxtPos[0]["X"] < $this->GraphAreaX1 ) { $XOffset = $this->GraphAreaX1 - $TxtPos[0]["X"]; }
3296
             if ( $TxtPos[1]["X"] > $this->GraphAreaX2 ) { $XOffset = -($TxtPos[1]["X"] - $this->GraphAreaX2); }
3297
             if ( $TxtPos[2]["Y"] < $this->GraphAreaY1 ) { $YOffset = ($this->GraphAreaY1 - $TxtPos[2]["Y"])/2; }
3298
             if ( $TxtPos[0]["Y"] > $this->GraphAreaY2 ) { $YOffset = -(($TxtPos[0]["Y"] - $this->GraphAreaY2)/2);}
3299
3300
             $CaptionSettings["R"] = $MaxDisplayR; $CaptionSettings["G"] = $MaxDisplayG;
3301
             $CaptionSettings["B"] = $MaxDisplayB; $CaptionSettings["Align"] = $Align;
3302
3303
             $this->drawText($YPos+$XOffset,$XPos+$YOffset,$Label,$CaptionSettings);
3304
            }
3305
3306
           if ( $Type == BOUND_MIN || $Type == BOUND_BOTH )
3307
            {
3308
             if ( $MinLabelPos == BOUND_LABEL_POS_TOP    || ( $MinLabelPos ==  BOUND_LABEL_POS_AUTO && $MinValue >= 0) ) { $YPos  = $PosArray[$MinPos] + $DisplayOffset + 2; $Align = TEXT_ALIGN_MIDDLELEFT; }
3309
             if ( $MinLabelPos == BOUND_LABEL_POS_BOTTOM || ( $MinLabelPos ==  BOUND_LABEL_POS_AUTO && $MinValue < 0) ) { $YPos  = $PosArray[$MinPos] - $DisplayOffset + 2; $Align = TEXT_ALIGN_MIDDLERIGHT; }
3310
3311
             $XPos  = $X + $MinPos*$XStep + $SerieOffset;
3312
             $Label = $MinLabelTxt.$this->scaleFormat($MinValue,$Mode,$Format,$Unit);
3313
3314
             $TxtPos  = $this->getTextBox($YPos,$XPos,$this->FontName,$this->FontSize,0,$Label);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getTextBox() does only exist in the following sub-classes of pDraw: pImage. 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...
3315
             $XOffset = 0; $YOffset = 0;
3316
             if ( $TxtPos[0]["X"] < $this->GraphAreaX1 ) { $XOffset = $this->GraphAreaX1 - $TxtPos[0]["X"]; }
3317
             if ( $TxtPos[1]["X"] > $this->GraphAreaX2 ) { $XOffset = -($TxtPos[1]["X"] - $this->GraphAreaX2); }
3318
             if ( $TxtPos[2]["Y"] < $this->GraphAreaY1 ) { $YOffset = ($this->GraphAreaY1 - $TxtPos[2]["Y"])/2; }
3319
             if ( $TxtPos[0]["Y"] > $this->GraphAreaY2 ) { $YOffset = -(($TxtPos[0]["Y"] - $this->GraphAreaY2)/2);}
3320
3321
             $CaptionSettings["R"] = $MinDisplayR; $CaptionSettings["G"] = $MinDisplayG;
3322
             $CaptionSettings["B"] = $MinDisplayB; $CaptionSettings["Align"] = $Align;
3323
3324
             $this->drawText($YPos+$XOffset,$XPos+$YOffset,$Label,$CaptionSettings);
3325
            }
3326
          }
3327
        }
3328
      }
3329
    }
3330
3331
   /* Draw a plot chart */
3332
   function drawPlotChart($Format=NULL)
3333
    {
3334
     $PlotSize		= isset($Format["PlotSize"]) ? $Format["PlotSize"] : NULL;
3335
     $PlotBorder	= isset($Format["PlotBorder"]) ? $Format["PlotBorder"] : FALSE;
3336
     $BorderR		= isset($Format["BorderR"]) ? $Format["BorderR"] : 50;
3337
     $BorderG		= isset($Format["BorderG"]) ? $Format["BorderG"] : 50;
3338
     $BorderB		= isset($Format["BorderB"]) ? $Format["BorderB"] : 50;
3339
     $BorderAlpha	= isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : 30;
3340
     $BorderSize	= isset($Format["BorderSize"]) ? $Format["BorderSize"] : 2;
3341
     $Surrounding	= isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL;
3342
     $DisplayValues	= isset($Format["DisplayValues"]) ? $Format["DisplayValues"] : FALSE;
3343
     $DisplayOffset	= isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 4;
3344
     $DisplayColor	= isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL;
3345
     $DisplayR		= isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0;
3346
     $DisplayG		= isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0;
3347
     $DisplayB		= isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0;
3348
     $RecordImageMap	= isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE;
3349
3350
     $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR;
3351
3352
     $Data = $this->DataSet->getData();
3353
     list($XMargin,$XDivs) = $this->scaleGetXSettings();
3354
3355
     foreach($Data["Series"] as $SerieName => $Serie)
3356
      {
3357
       if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] )
3358
        {
3359
         if ( isset($Serie["Weight"]) ) { $SerieWeight = $Serie["Weight"] + 2; } else { $SerieWeight = 2; }
3360
         if ( $PlotSize != NULL ) { $SerieWeight = $PlotSize; }
3361
3362
         $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"];
3363
         if ( $Surrounding != NULL ) { $BorderR = $R + $Surrounding; $BorderG = $G + $Surrounding; $BorderB = $B + $Surrounding; }
3364
         if ( isset($Serie["Picture"]) )
3365
          { $Picture = $Serie["Picture"]; list($PicWidth,$PicHeight,$PicType) = $this->getPicInfo($Picture); }
3366
         else { $Picture = NULL; $PicOffset = 0; }
3367
3368
         if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; }
3369
3370
         $AxisID	= $Serie["Axis"];
3371
         $Shape		= $Serie["Shape"];
3372
         $Mode		= $Data["Axis"][$AxisID]["Display"];
3373
         $Format	= $Data["Axis"][$AxisID]["Format"];
3374
         $Unit		= $Data["Axis"][$AxisID]["Unit"];
3375
3376
         if (isset($Serie["Description"])) { $SerieDescription = $Serie["Description"]; } else { $SerieDescription = $SerieName; }
3377
3378
         $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"]));
3379
3380
         $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0;
3381
3382
         if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT )
3383
          {
3384
           if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; }
3385
           if ( $Picture != NULL ) { $PicOffset = $PicHeight / 2; $SerieWeight = 0; }
3386
           $X = $this->GraphAreaX1 + $XMargin;
3387
3388
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
3389
           foreach($PosArray as $Key => $Y)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
3390
            {
3391
             if ( $DisplayValues ) 
3392
              $this->drawText($X,$Y-$DisplayOffset-$SerieWeight-$BorderSize-$PicOffset,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE));
3393
3394
             if ( $Y != VOID )
3395
              {
3396
               if ( $RecordImageMap ) { $this->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".$SerieWeight,$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
3397
3398
               if ( $Picture != NULL )
3399
                { $this->drawFromPicture($PicType,$Picture,$X-$PicWidth/2,$Y-$PicHeight/2); }
3400
               else
3401
                { $this->drawShape($X,$Y,$Shape,$SerieWeight,$PlotBorder,$BorderSize,$R,$G,$B,$Alpha,$BorderR,$BorderG,$BorderB,$BorderAlpha); }
3402
              }
3403
             $X = $X + $XStep;
3404
            }
3405
          }
3406
         else
3407
          {
3408
           if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; }
3409
           if ( $Picture != NULL ) { $PicOffset = $PicWidth / 2; $SerieWeight = 0; }
3410
           $Y = $this->GraphAreaY1 + $XMargin;
3411
3412
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
3413
           foreach($PosArray as $Key => $X)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
3414
            {
3415
             if ( $DisplayValues ) 
3416
              $this->drawText($X+$DisplayOffset+$SerieWeight+$BorderSize+$PicOffset,$Y,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("Angle"=>270,"R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE));
3417
3418
             if ( $X != VOID )
3419
              {
3420
               if ( $RecordImageMap ) { $this->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".$SerieWeight,$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
3421
3422
               if ( $Picture != NULL )
3423
                { $this->drawFromPicture($PicType,$Picture,$X-$PicWidth/2,$Y-$PicHeight/2); }
3424
               else
3425
                { $this->drawShape($X,$Y,$Shape,$SerieWeight,$PlotBorder,$BorderSize,$R,$G,$B,$Alpha,$BorderR,$BorderG,$BorderB,$BorderAlpha); }
3426
              }
3427
             $Y = $Y + $YStep;
3428
            }
3429
          }
3430
        }
3431
      }
3432
    }
3433
3434
   /* Draw a spline chart */
3435
   function drawSplineChart($Format=NULL)
3436
    {
3437
     $BreakVoid		= isset($Format["BreakVoid"]) ? $Format["BreakVoid"] : TRUE;
3438
     $VoidTicks		= isset($Format["VoidTicks"]) ? $Format["VoidTicks"] : 4;
3439
     $BreakR		= isset($Format["BreakR"]) ? $Format["BreakR"] : NULL; // 234
3440
     $BreakG		= isset($Format["BreakG"]) ? $Format["BreakG"] : NULL; // 55
3441
     $BreakB		= isset($Format["BreakB"]) ? $Format["BreakB"] : NULL; // 26
3442
     $DisplayValues	= isset($Format["DisplayValues"]) ? $Format["DisplayValues"] : FALSE;
3443
     $DisplayOffset	= isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 2;
3444
     $DisplayColor	= isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL;
3445
     $DisplayR		= isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0;
3446
     $DisplayG		= isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0;
3447
     $DisplayB		= isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0;
3448
     $RecordImageMap	= isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE;
3449
     $ImageMapPlotSize  = isset($Format["ImageMapPlotSize"]) ? $Format["ImageMapPlotSize"] : 5;
3450
3451
     $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR;
3452
3453
     $Data = $this->DataSet->getData();
3454
     list($XMargin,$XDivs) = $this->scaleGetXSettings();
3455
     foreach($Data["Series"] as $SerieName => $Serie)
3456
      {
3457
       if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] )
3458
        {
3459
         $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; $Weight = $Serie["Weight"];
3460
3461
         if ( $BreakR == NULL )
3462
          $BreakSettings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$VoidTicks);
3463
         else
3464
          $BreakSettings = array("R"=>$BreakR,"G"=>$BreakG,"B"=>$BreakB,"Alpha"=>$Alpha,"Ticks"=>$VoidTicks,"Weight"=>$Weight);
3465
3466
         if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; }
3467
3468
         $AxisID	= $Serie["Axis"];
3469
         $Mode		= $Data["Axis"][$AxisID]["Display"];
3470
         $Format	= $Data["Axis"][$AxisID]["Format"];
3471
         $Unit		= $Data["Axis"][$AxisID]["Unit"];
3472
3473
         if (isset($Serie["Description"])) { $SerieDescription = $Serie["Description"]; } else { $SerieDescription = $SerieName; }
3474
3475
         $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"]));
3476
3477
         $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0;
3478
3479
         if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT )
3480
          {
3481
           if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; }
3482
           $X     = $this->GraphAreaX1 + $XMargin; $WayPoints = "";
3483
           $Force = $XStep / 5;
3484
3485
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
3486
           $LastGoodY = NULL; $LastGoodX = NULL; $LastX = 1; $LastY = 1;
3487
           foreach($PosArray as $Key => $Y)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
3488
            {
3489
             if ( $DisplayValues ) 
3490
              $this->drawText($X,$Y-$DisplayOffset,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE));
3491
	
3492
             if ( $RecordImageMap && $Y != VOID ) { $this->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".$ImageMapPlotSize,$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
3493
3494
             if ( $Y == VOID && $LastY != NULL )
3495
              { $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); $WayPoints = ""; }
3496
3497
             if ( $Y != VOID && $LastY == NULL && $LastGoodY != NULL && !$BreakVoid )
3498
              { $this->drawLine($LastGoodX,$LastGoodY,$X,$Y,$BreakSettings); }
3499
3500
             if ( $Y != VOID )
3501
              $WayPoints[] = array($X,$Y);
3502
3503
             if ( $Y != VOID ) { $LastGoodY = $Y; $LastGoodX = $X; }
3504
             if ( $Y == VOID ) { $Y = NULL; }
3505
3506
             $LastX = $X; $LastY = $Y;
3507
             $X = $X + $XStep;
3508
            }
3509
           $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight));
3510
          }
3511
         else
3512
          {
3513
           if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; }
3514
           $Y     = $this->GraphAreaY1 + $XMargin; $WayPoints = "";
3515
           $Force = $YStep / 5;
3516
3517
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
3518
           $LastGoodY = NULL; $LastGoodX = NULL; $LastX = 1; $LastY = 1;
3519
           foreach($PosArray as $Key => $X)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
3520
            {
3521
             if ( $DisplayValues ) 
3522
              $this->drawText($X+$DisplayOffset,$Y,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("Angle"=>270,"R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE));
3523
3524
             if ( $RecordImageMap && $X != VOID ) { $this->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".$ImageMapPlotSize,$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
3525
3526
             if ( $X == VOID && $LastX != NULL )
3527
              { $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight)); $WayPoints = ""; }
3528
3529
             if ( $X != VOID && $LastX == NULL && $LastGoodX != NULL && !$BreakVoid )
3530
              { $this->drawLine($LastGoodX,$LastGoodY,$X,$Y,$BreakSettings); }
3531
3532
             if ( $X != VOID )
3533
              $WayPoints[] = array($X,$Y);
3534
3535
             if ( $X != VOID ) { $LastGoodX = $X; $LastGoodY = $Y; }
3536
             if ( $X == VOID ) { $X = NULL; }
3537
3538
             $LastX = $X; $LastY = $Y;
3539
             $Y = $Y + $YStep;
3540
            }
3541
           $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight));
3542
          }
3543
        }
3544
      }
3545
    }
3546
3547
   /* Draw a filled spline chart */
3548
   function drawFilledSplineChart($Format=NULL)
3549
    {
3550
     $DisplayValues	= isset($Format["DisplayValues"]) ? $Format["DisplayValues"] : FALSE;
3551
     $DisplayOffset	= isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 2;
3552
     $DisplayColor	= isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL;
3553
     $DisplayR		= isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0;
3554
     $DisplayG		= isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0;
3555
     $DisplayB		= isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0;
3556
     $AroundZero	= isset($Format["AroundZero"]) ? $Format["AroundZero"] : TRUE;
3557
     $Threshold		= isset($Format["Threshold"]) ? $Format["Threshold"] : NULL;
3558
3559
     $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR;
3560
3561
     $Data = $this->DataSet->getData();
3562
     list($XMargin,$XDivs) = $this->scaleGetXSettings();
3563
     foreach($Data["Series"] as $SerieName => $Serie)
3564
      {
3565
       if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] )
3566
        {
3567
         $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"];
3568
         if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; }
3569
3570
         $AxisID	= $Serie["Axis"];
3571
         $Mode		= $Data["Axis"][$AxisID]["Display"];
3572
         $Format	= $Data["Axis"][$AxisID]["Format"];
3573
         $Unit		= $Data["Axis"][$AxisID]["Unit"];
3574
3575
         $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"]));
3576
         if ( $AroundZero ) { $YZero = $this->scaleComputeY(0,array("AxisID"=>$Serie["Axis"])); }
3577
3578
         if ( $Threshold != NULL )
3579
          {
3580
           foreach($Threshold as $Key => $Params)
3581
            {
3582
             $Threshold[$Key]["MinX"] = $this->scaleComputeY($Params["Min"],array("AxisID"=>$Serie["Axis"]));
3583
             $Threshold[$Key]["MaxX"] = $this->scaleComputeY($Params["Max"],array("AxisID"=>$Serie["Axis"]));
3584
            }
3585
          }
3586
3587
         $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0;
3588
3589
         if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT )
3590
          {
3591
           if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; }
3592
           $X     = $this->GraphAreaX1 + $XMargin; $WayPoints = "";
3593
           $Force = $XStep / 5;
3594
3595
           if ( !$AroundZero ) { $YZero = $this->GraphAreaY2-1; }
3596
           if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; }
3597
           if ( $YZero < $this->GraphAreaY1+1 ) { $YZero = $this->GraphAreaY1+1; }
3598
3599
           $LastX = ""; $LastY = "";
3600
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
3601
           foreach($PosArray as $Key => $Y)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
3602
            {
3603
             if ( $DisplayValues ) 
3604
              $this->drawText($X,$Y-$DisplayOffset,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE));
3605
3606
             if ( $Y == VOID )
3607
              {
3608
               $Area = $this->drawSpline($WayPoints,array("Force"=>$Force,"PathOnly"=>TRUE));
3609
3610
               if ( $Area != "" )
3611
                {
3612
                 foreach ($Area as $key => $Points)
0 ignored issues
show
Bug introduced by
The expression $Area of type string is not traversable.
Loading history...
3613
                  {
3614
                   $Corners = ""; $Corners[] = $Area[$key][0]["X"]; $Corners[] = $YZero;
3615
                   foreach($Points as $subKey => $Point)
3616
                    {
3617
                     if ( $subKey == count($Points)-1) { $Corners[] = $Point["X"]-1; } else { $Corners[] = $Point["X"]; }
3618
                     $Corners[] = $Point["Y"]+1;
3619
                    }
3620
                   $Corners[] = $Points[$subKey]["X"]-1; $Corners[] = $YZero;
3621
3622
                   $this->drawPolygonChart($Corners,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/2,"NoBorder"=>TRUE,"Threshold"=>$Threshold));
3623
                  }
3624
                 $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks));
3625
                }
3626
3627
               $WayPoints = "";
3628
              }
3629
             else
3630
              $WayPoints[] = array($X,$Y-.5); /* -.5 for AA visual fix */
3631
3632
             $X = $X + $XStep;
3633
            }
3634
           $Area = $this->drawSpline($WayPoints,array("Force"=>$Force,"PathOnly"=>TRUE));
3635
3636
           if ( $Area != "" )
3637
            {
3638
             foreach ($Area as $key => $Points)
0 ignored issues
show
Bug introduced by
The expression $Area of type string is not traversable.
Loading history...
3639
              {
3640
               $Corners = ""; $Corners[] = $Area[$key][0]["X"]; $Corners[] = $YZero;
3641
               foreach($Points as $subKey => $Point)
3642
                {
3643
                 if ( $subKey == count($Points)-1) { $Corners[] = $Point["X"]-1; } else { $Corners[] = $Point["X"]; }
3644
                 $Corners[] = $Point["Y"]+1;
3645
                }
3646
               $Corners[] = $Points[$subKey]["X"]-1; $Corners[] = $YZero;
3647
3648
               $this->drawPolygonChart($Corners,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/2,"NoBorder"=>TRUE,"Threshold"=>$Threshold));
3649
              }
3650
             $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks));
3651
            }
3652
          }
3653
         else
3654
          {
3655
           if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; }
3656
           $Y     = $this->GraphAreaY1 + $XMargin; $WayPoints = "";
3657
           $Force = $YStep / 5;
3658
3659
           if ( !$AroundZero ) { $YZero = $this->GraphAreaX1+1; }
3660
           if ( $YZero > $this->GraphAreaX2-1 ) { $YZero = $this->GraphAreaX2-1; }
3661
           if ( $YZero < $this->GraphAreaX1+1 ) { $YZero = $this->GraphAreaX1+1; }
3662
3663
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
3664
           foreach($PosArray as $Key => $X)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
3665
            {
3666
             if ( $DisplayValues ) 
3667
              $this->drawText($X+$DisplayOffset,$Y,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("Angle"=>270,"R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE));
3668
3669
             if ( $X == VOID )
3670
              {
3671
               $Area = $this->drawSpline($WayPoints,array("Force"=>$Force,"PathOnly"=>TRUE));
3672
3673
               if ( $Area != "" )
3674
                {
3675
                 foreach ($Area as $key => $Points)
0 ignored issues
show
Bug introduced by
The expression $Area of type string is not traversable.
Loading history...
3676
                  {
3677
                   $Corners = ""; $Corners[] = $YZero; $Corners[] = $Area[$key][0]["Y"];
3678
                   foreach($Points as $subKey => $Point)
3679
                    {
3680
                     if ( $subKey == count($Points)-1) { $Corners[] = $Point["X"]-1; } else { $Corners[] = $Point["X"]; }
3681
                     $Corners[] = $Point["Y"];
3682
                    }
3683
                   $Corners[] = $YZero; $Corners[] = $Points[$subKey]["Y"]-1;
3684
3685
                   $this->drawPolygonChart($Corners,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/2,"NoBorder"=>TRUE,"Threshold"=>$Threshold));
3686
                  }
3687
                 $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks));
3688
                }
3689
3690
               $WayPoints = "";
3691
              }
3692
             else
3693
              $WayPoints[] = array($X,$Y);
3694
3695
             $Y = $Y + $YStep;
3696
            }
3697
           $Area = $this->drawSpline($WayPoints,array("Force"=>$Force,"PathOnly"=>TRUE));
3698
3699
           if ( $Area != "" )
3700
            {
3701
             foreach ($Area as $key => $Points)
0 ignored issues
show
Bug introduced by
The expression $Area of type string is not traversable.
Loading history...
3702
              {
3703
               $Corners = ""; $Corners[] = $YZero; $Corners[] = $Area[$key][0]["Y"];
3704
               foreach($Points as $subKey => $Point)
3705
                {
3706
                 if ( $subKey == count($Points)-1) { $Corners[] = $Point["X"]-1; } else { $Corners[] = $Point["X"]; }
3707
                 $Corners[] = $Point["Y"];
3708
                }
3709
               $Corners[] = $YZero; $Corners[] = $Points[$subKey]["Y"]-1;
3710
3711
               $this->drawPolygonChart($Corners,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha/2,"NoBorder"=>TRUE,"Threshold"=>$Threshold));
3712
              }
3713
             $this->drawSpline($WayPoints,array("Force"=>$Force,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks));
3714
            }
3715
3716
          }
3717
        }
3718
      }
3719
    }
3720
3721
   /* Draw a line chart */
3722
   function drawLineChart($Format=NULL)
3723
    {
3724
     $BreakVoid		= isset($Format["BreakVoid"]) ? $Format["BreakVoid"] : TRUE;
3725
     $VoidTicks		= isset($Format["VoidTicks"]) ? $Format["VoidTicks"] : 4;
3726
     $BreakR		= isset($Format["BreakR"]) ? $Format["BreakR"] : NULL;
3727
     $BreakG		= isset($Format["BreakG"]) ? $Format["BreakG"] : NULL;
3728
     $BreakB		= isset($Format["BreakB"]) ? $Format["BreakB"] : NULL;
3729
     $DisplayValues	= isset($Format["DisplayValues"]) ? $Format["DisplayValues"] : FALSE;
3730
     $DisplayOffset	= isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 2;
3731
     $DisplayColor	= isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL;
3732
     $DisplayR		= isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0;
3733
     $DisplayG		= isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0;
3734
     $DisplayB		= isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0;
3735
     $RecordImageMap	= isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE;
3736
     $ImageMapPlotSize  = isset($Format["ImageMapPlotSize"]) ? $Format["ImageMapPlotSize"] : 5;
3737
     $ForceColor	= isset($Format["ForceColor"]) ? $Format["ForceColor"] : FALSE;
3738
     $ForceR		= isset($Format["ForceR"]) ? $Format["ForceR"] : 0;
3739
     $ForceG		= isset($Format["ForceG"]) ? $Format["ForceG"] : 0;
3740
     $ForceB		= isset($Format["ForceB"]) ? $Format["ForceB"] : 0;
3741
     $ForceAlpha	= isset($Format["ForceAlpha"]) ? $Format["ForceAlpha"] : 100;
3742
3743
     $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR;
3744
3745
     $Data = $this->DataSet->getData();
3746
     list($XMargin,$XDivs) = $this->scaleGetXSettings();
3747
     foreach($Data["Series"] as $SerieName => $Serie)
3748
      {
3749
       if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] )
3750
        {
3751
         $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; $Weight = $Serie["Weight"];
3752
3753
         if ( $ForceColor )
3754
          { $R = $ForceR; $G = $ForceG; $B = $ForceB; $Alpha = $ForceAlpha; }
3755
3756
         if ( $BreakR == NULL )
3757
          $BreakSettings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$VoidTicks,"Weight"=>$Weight);
3758
         else
3759
          $BreakSettings = array("R"=>$BreakR,"G"=>$BreakG,"B"=>$BreakB,"Alpha"=>$Alpha,"Ticks"=>$VoidTicks,"Weight"=>$Weight);
3760
3761
         if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; }
3762
3763
         $AxisID	= $Serie["Axis"];
3764
         $Mode		= $Data["Axis"][$AxisID]["Display"];
3765
         $Format	= $Data["Axis"][$AxisID]["Format"];
3766
         $Unit		= $Data["Axis"][$AxisID]["Unit"];
3767
3768
         if (isset($Serie["Description"])) { $SerieDescription = $Serie["Description"]; } else { $SerieDescription = $SerieName; }
3769
3770
         $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"]));
3771
3772
         $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0;
3773
3774
         if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT )
3775
          {
3776
           if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; }
3777
           $X = $this->GraphAreaX1 + $XMargin; $LastX = NULL; $LastY = NULL;
3778
3779
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
3780
           $LastGoodY = NULL; $LastGoodX = NULL;
3781
           foreach($PosArray as $Key => $Y)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
3782
            {
3783
             if ( $DisplayValues && $Serie["Data"][$Key] != VOID ) 
3784
              {
3785
               if ( $Serie["Data"][$Key] > 0 ) { $Align = TEXT_ALIGN_BOTTOMMIDDLE; $Offset = $DisplayOffset; } else { $Align = TEXT_ALIGN_TOPMIDDLE; $Offset = -$DisplayOffset; }
3786
               $this->drawText($X,$Y-$Offset-$Weight,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>$Align));
3787
              }
3788
3789
             if ( $RecordImageMap && $Y != VOID ) { $this->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".$ImageMapPlotSize,$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
3790
3791
             if ( $Y != VOID && $LastX != NULL && $LastY != NULL )
3792
              $this->drawLine($LastX,$LastY,$X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight));
3793
3794
             if ( $Y != VOID && $LastY == NULL && $LastGoodY != NULL && !$BreakVoid )
3795
              { $this->drawLine($LastGoodX,$LastGoodY,$X,$Y,$BreakSettings); $LastGoodY = NULL; }
3796
3797
             if ( $Y != VOID ) { $LastGoodY = $Y; $LastGoodX = $X; }
3798
             if ( $Y == VOID ) { $Y = NULL; }
3799
3800
             $LastX = $X; $LastY = $Y;
3801
             $X = $X + $XStep;
3802
            }
3803
          }
3804
         else
3805
          {
3806
           if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; }
3807
           $Y = $this->GraphAreaY1 + $XMargin; $LastX = NULL; $LastY = NULL;
3808
3809
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
3810
           $LastGoodY = NULL; $LastGoodX = NULL;
3811
           foreach($PosArray as $Key => $X)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
3812
            {
3813
             if ( $DisplayValues && $Serie["Data"][$Key] != VOID ) 
3814
              { $this->drawText($X+$DisplayOffset+$Weight,$Y,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("Angle"=>270,"R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_BOTTOMMIDDLE)); }
3815
3816
             if ( $RecordImageMap && $X != VOID ) { $this->addToImageMap("CIRCLE",floor($X).",".floor($Y).",".$ImageMapPlotSize,$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
3817
3818
             if ( $X != VOID && $LastX != NULL && $LastY != NULL )
3819
              $this->drawLine($LastX,$LastY,$X,$Y,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight));
3820
3821
             if ( $X != VOID && $LastX == NULL && $LastGoodY != NULL && !$BreakVoid )
3822
              { $this->drawLine($LastGoodX,$LastGoodY,$X,$Y,$BreakSettings); $LastGoodY = NULL; }
3823
3824
             if ( $X != VOID ) { $LastGoodY = $Y; $LastGoodX = $X; }
3825
             if ( $X == VOID ) { $X = NULL; }
3826
3827
             $LastX = $X; $LastY = $Y;
3828
             $Y = $Y + $YStep;
3829
            }
3830
          }
3831
        }
3832
      }
3833
    }
3834
3835
   /* Draw a line chart */
3836
   function drawZoneChart($SerieA,$SerieB,$Format=NULL)
3837
    {
3838
     $AxisID	= isset($Format["AxisID"]) ? $Format["AxisID"] : 0;
3839
     $LineR	= isset($Format["LineR"]) ? $Format["LineR"] : 150;
3840
     $LineG	= isset($Format["LineG"]) ? $Format["LineG"] : 150;
3841
     $LineB	= isset($Format["LineB"]) ? $Format["LineB"] : 150;
3842
     $LineAlpha	= isset($Format["LineAlpha"]) ? $Format["LineAlpha"] : 50;
3843
     $LineTicks	= isset($Format["LineTicks"]) ? $Format["LineTicks"] : 1;
3844
     $AreaR	= isset($Format["AreaR"]) ? $Format["AreaR"] : 150;
3845
     $AreaG	= isset($Format["AreaG"]) ? $Format["AreaG"] : 150;
3846
     $AreaB	= isset($Format["AreaB"]) ? $Format["AreaB"] : 150;
3847
     $AreaAlpha	= isset($Format["AreaAlpha"]) ? $Format["AreaAlpha"] : 5;
3848
3849
     $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR;
3850
3851
     $Data	 = $this->DataSet->getData();
3852
     if ( !isset($Data["Series"][$SerieA]["Data"]) || !isset($Data["Series"][$SerieB]["Data"]) ) { return(0); }
3853
     $SerieAData = $Data["Series"][$SerieA]["Data"];
3854
     $SerieBData = $Data["Series"][$SerieB]["Data"];
3855
3856
     list($XMargin,$XDivs) = $this->scaleGetXSettings();
3857
3858
     $Mode	= $Data["Axis"][$AxisID]["Display"];
3859
     $Format	= $Data["Axis"][$AxisID]["Format"];
3860
     $Unit	= $Data["Axis"][$AxisID]["Unit"];
3861
3862
     $PosArrayA = $this->scaleComputeY($SerieAData,array("AxisID"=>$AxisID));
3863
     $PosArrayB = $this->scaleComputeY($SerieBData,array("AxisID"=>$AxisID));
3864
     if ( count($PosArrayA) != count($PosArrayB) ) { return(0); }
3865
3866
     if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT )
3867
      {
3868
       if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; }
3869
       $X = $this->GraphAreaX1 + $XMargin; $LastX = NULL; $LastY = NULL;
3870
3871
       $LastX = NULL; $LastY1 = NULL; $LastY2 = NULL;
3872
       $BoundsA = ""; $BoundsB = "";
3873
       foreach($PosArrayA as $Key => $Y1)
0 ignored issues
show
Bug introduced by
The expression $PosArrayA of type integer|string is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
3874
        {
3875
         $Y2 = $PosArrayB[$Key];
3876
3877
         $BoundsA[] = $X; $BoundsA[] = $Y1;
3878
         $BoundsB[] = $X; $BoundsB[] = $Y2;
3879
3880
         $LastX = $X;
3881
         $LastY1 = $Y1; $LastY2 = $Y2;
3882
3883
         $X = $X + $XStep;
3884
        }
3885
       $Bounds = array_merge($BoundsA,$this->reversePlots($BoundsB));
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method reversePlots() does only exist in the following sub-classes of pDraw: pImage. 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...
3886
       $this->drawPolygonChart($Bounds,array("R"=>$AreaR,"G"=>$AreaG,"B"=>$AreaB,"Alpha"=>$AreaAlpha));
3887
3888
       for($i=0;$i<=count($BoundsA)-4;$i=$i+2)
3889
        {
3890
         $this->drawLine($BoundsA[$i],$BoundsA[$i+1],$BoundsA[$i+2],$BoundsA[$i+3],array("R"=>$LineR,"G"=>$LineG,"B"=>$LineB,"Alpha"=>$LineAlpha,"Ticks"=>$LineTicks));
3891
         $this->drawLine($BoundsB[$i],$BoundsB[$i+1],$BoundsB[$i+2],$BoundsB[$i+3],array("R"=>$LineR,"G"=>$LineG,"B"=>$LineB,"Alpha"=>$LineAlpha,"Ticks"=>$LineTicks));
3892
        }
3893
      }
3894
     else
3895
      {
3896
       if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; }
3897
       $Y = $this->GraphAreaY1 + $XMargin; $LastX = NULL; $LastY = NULL;
3898
3899
       $LastY = NULL; $LastX1 = NULL; $LastX2 = NULL;
3900
       $BoundsA = ""; $BoundsB = "";
3901
       foreach($PosArrayA as $Key => $X1)
0 ignored issues
show
Bug introduced by
The expression $PosArrayA of type integer|string is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
3902
        {
3903
         $X2 = $PosArrayB[$Key];
3904
3905
         $BoundsA[] = $X1; $BoundsA[] = $Y;
3906
         $BoundsB[] = $X2; $BoundsB[] = $Y;
3907
3908
         $LastY = $Y;
3909
         $LastX1 = $X1; $LastX2 = $X2;
3910
3911
         $Y = $Y + $YStep;
3912
        }
3913
       $Bounds = array_merge($BoundsA,$this->reversePlots($BoundsB));
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method reversePlots() does only exist in the following sub-classes of pDraw: pImage. 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...
3914
       $this->drawPolygonChart($Bounds,array("R"=>$AreaR,"G"=>$AreaG,"B"=>$AreaB,"Alpha"=>$AreaAlpha));
3915
3916
       for($i=0;$i<=count($BoundsA)-4;$i=$i+2)
3917
        {
3918
         $this->drawLine($BoundsA[$i],$BoundsA[$i+1],$BoundsA[$i+2],$BoundsA[$i+3],array("R"=>$LineR,"G"=>$LineG,"B"=>$LineB,"Alpha"=>$LineAlpha,"Ticks"=>$LineTicks));
3919
         $this->drawLine($BoundsB[$i],$BoundsB[$i+1],$BoundsB[$i+2],$BoundsB[$i+3],array("R"=>$LineR,"G"=>$LineG,"B"=>$LineB,"Alpha"=>$LineAlpha,"Ticks"=>$LineTicks));
3920
        }
3921
      }
3922
    }
3923
3924
   /* Draw a step chart */
3925
   function drawStepChart($Format=NULL)
3926
    {
3927
     $BreakVoid		= isset($Format["BreakVoid"]) ? $Format["BreakVoid"] : FALSE;
3928
     $ReCenter		= isset($Format["ReCenter"]) ? $Format["ReCenter"] : TRUE;
3929
     $VoidTicks		= isset($Format["VoidTicks"]) ? $Format["VoidTicks"] : 4;
3930
     $BreakR		= isset($Format["BreakR"]) ? $Format["BreakR"] : NULL;
3931
     $BreakG		= isset($Format["BreakG"]) ? $Format["BreakG"] : NULL;
3932
     $BreakB		= isset($Format["BreakB"]) ? $Format["BreakB"] : NULL;
3933
     $DisplayValues	= isset($Format["DisplayValues"]) ? $Format["DisplayValues"] :FALSE;
3934
     $DisplayOffset	= isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 2;
3935
     $DisplayColor	= isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL;
3936
     $DisplayR		= isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0;
3937
     $DisplayG		= isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0;
3938
     $DisplayB		= isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0;
3939
     $RecordImageMap	= isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE;
3940
     $ImageMapPlotSize  = isset($Format["ImageMapPlotSize"]) ? $Format["ImageMapPlotSize"] : 5;
3941
3942
     $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR;
3943
3944
     $Data = $this->DataSet->getData();
3945
     list($XMargin,$XDivs) = $this->scaleGetXSettings();
3946
     foreach($Data["Series"] as $SerieName => $Serie)
3947
      {
3948
       if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] )
3949
        {
3950
         $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; $Weight = $Serie["Weight"];
3951
3952
         if (isset($Serie["Description"])) { $SerieDescription = $Serie["Description"]; } else { $SerieDescription = $SerieName; }
3953
3954
         if ( $BreakR == NULL )
3955
          $BreakSettings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$VoidTicks,"Weight"=>$Weight);
3956
         else
3957
          $BreakSettings = array("R"=>$BreakR,"G"=>$BreakG,"B"=>$BreakB,"Alpha"=>$Alpha,"Ticks"=>$VoidTicks,"Weight"=>$Weight);
3958
3959
         if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; }
3960
3961
         $AxisID	= $Serie["Axis"];
3962
         $Mode		= $Data["Axis"][$AxisID]["Display"];
3963
         $Format	= $Data["Axis"][$AxisID]["Format"];
3964
         $Unit		= $Data["Axis"][$AxisID]["Unit"];
3965
         $Color		= array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight);
3966
3967
         $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"]));
3968
3969
         $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0;
3970
3971
         if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT )
3972
          {
3973
           if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; }
3974
           $X = $this->GraphAreaX1 + $XMargin; $LastX = NULL; $LastY = NULL;
3975
3976
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
3977
           $LastGoodY = NULL; $LastGoodX = NULL; $Init = FALSE;
3978
           foreach($PosArray as $Key => $Y)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
3979
            {
3980
             if ( $DisplayValues && $Serie["Data"][$Key] != VOID ) 
3981
              {
3982
               if ( $Y <= $LastY ) { $Align = TEXT_ALIGN_BOTTOMMIDDLE; $Offset = $DisplayOffset; } else { $Align = TEXT_ALIGN_TOPMIDDLE; $Offset = -$DisplayOffset; }
3983
               $this->drawText($X,$Y-$Offset-$Weight,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>$Align));
3984
              }
3985
3986
             if ( $Y != VOID && $LastX != NULL && $LastY != NULL )
3987
              {
3988
               $this->drawLine($LastX,$LastY,$X,$LastY,$Color);
3989
               $this->drawLine($X,$LastY,$X,$Y,$Color);
3990
               if ( $ReCenter && $X+$XStep < $this->GraphAreaX2 - $XMargin )
3991
                {
3992
                 $this->drawLine($X,$Y,$X+$XStep,$Y,$Color);
3993
                 if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X-$ImageMapPlotSize).",".floor($Y-$ImageMapPlotSize).",".floor($X+$XStep+$ImageMapPlotSize).",".floor($Y+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
3994
                }
3995
               else
3996
                { if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastX-$ImageMapPlotSize).",".floor($LastY-$ImageMapPlotSize).",".floor($X+$ImageMapPlotSize).",".floor($LastY+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); } }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
3997
              }
3998
3999
             if ( $Y != VOID && $LastY == NULL && $LastGoodY != NULL && !$BreakVoid )
4000
              { 
4001
               if ( $ReCenter )
4002
                {
4003
                 $this->drawLine($LastGoodX+$XStep,$LastGoodY,$X,$LastGoodY,$BreakSettings);
4004
                 if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastGoodX+$XStep-$ImageMapPlotSize).",".floor($LastGoodY-$ImageMapPlotSize).",".floor($X+$ImageMapPlotSize).",".floor($LastGoodY+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
4005
                }
4006
               else
4007
                {
4008
                 $this->drawLine($LastGoodX,$LastGoodY,$X,$LastGoodY,$BreakSettings);
4009
                 if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastGoodX-$ImageMapPlotSize).",".floor($LastGoodY-$ImageMapPlotSize).",".floor($X+$ImageMapPlotSize).",".floor($LastGoodY+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
4010
                }
4011
4012
               $this->drawLine($X,$LastGoodY,$X,$Y,$BreakSettings);
4013
               $LastGoodY = NULL;
4014
              }
4015
             elseif( !$BreakVoid && $LastGoodY == NULL && $Y != VOID )
4016
              {
4017
              $this->drawLine($this->GraphAreaX1 + $XMargin,$Y,$X,$Y,$BreakSettings);
4018
               if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($this->GraphAreaX1+$XMargin-$ImageMapPlotSize).",".floor($Y-$ImageMapPlotSize).",".floor($X+$ImageMapPlotSize).",".floor($Y+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
4019
              }
4020
4021
             if ( $Y != VOID ) { $LastGoodY = $Y; $LastGoodX = $X; }
4022
             if ( $Y == VOID ) { $Y = NULL; }
4023
4024
             if ( !$Init && $ReCenter ) { $X = $X - $XStep/2; $Init = TRUE; }
4025
             $LastX = $X; $LastY = $Y;
4026
             if ( $LastX < $this->GraphAreaX1 + $XMargin ) { $LastX = $this->GraphAreaX1 + $XMargin; }
4027
             $X = $X + $XStep;
4028
            }
4029
           if ( $ReCenter )
4030
            {
4031
             $this->drawLine($LastX,$LastY,$this->GraphAreaX2 - $XMargin,$LastY,$Color);
4032
             if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastX-$ImageMapPlotSize).",".floor($LastY-$ImageMapPlotSize).",".floor($this->GraphAreaX2-$XMargin+$ImageMapPlotSize).",".floor($LastY+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
4033
            }
4034
          }
4035
         else
4036
          {
4037
           if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; }
4038
           $Y = $this->GraphAreaY1 + $XMargin; $LastX = NULL; $LastY = NULL;
4039
4040
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
4041
           $LastGoodY = NULL; $LastGoodX = NULL; $Init = FALSE;
4042
           foreach($PosArray as $Key => $X)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
4043
            {
4044
             if ( $DisplayValues && $Serie["Data"][$Key] != VOID ) 
4045
              {
4046
               if ( $X >= $LastX ) { $Align = TEXT_ALIGN_MIDDLELEFT; $Offset = $DisplayOffset; } else { $Align = TEXT_ALIGN_MIDDLERIGHT; $Offset = -$DisplayOffset; }
4047
               $this->drawText($X+$Offset+$Weight,$Y,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>$Align));
4048
              }
4049
4050
             if ( $X != VOID && $LastX != NULL && $LastY != NULL )
4051
              {
4052
               $this->drawLine($LastX,$LastY,$LastX,$Y,$Color);
4053
               $this->drawLine($LastX,$Y,$X,$Y,$Color);
4054
4055
               if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastX-$ImageMapPlotSize).",".floor($LastY-$ImageMapPlotSize).",".floor($LastX+$XStep+$ImageMapPlotSize).",".floor($Y+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
4056
              }
4057
4058
             if ( $X != VOID && $LastX == NULL && $LastGoodY != NULL && !$BreakVoid )
4059
              {
4060
               $this->drawLine($LastGoodX,$LastGoodY,$LastGoodX,$LastGoodY+$YStep,$Color);
4061
               if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastGoodX-$ImageMapPlotSize).",".floor($LastGoodY-$ImageMapPlotSize).",".floor($LastGoodX+$ImageMapPlotSize).",".floor($LastGoodY+$YStep+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
4062
4063
               $this->drawLine($LastGoodX,$LastGoodY+$YStep,$LastGoodX,$Y,$BreakSettings);
4064
               if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastGoodX-$ImageMapPlotSize).",".floor($LastGoodY+$YStep-$ImageMapPlotSize).",".floor($LastGoodX+$ImageMapPlotSize).",".floor($YStep+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
4065
4066
               $this->drawLine($LastGoodX,$Y,$X,$Y,$BreakSettings);
4067
               $LastGoodY = NULL;
4068
              }
4069
             elseif ( $X != VOID && $LastGoodY == NULL && !$BreakVoid )
4070
              {
4071
               $this->drawLine($X,$this->GraphAreaY1 + $XMargin,$X,$Y,$BreakSettings);
4072
               if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X-$ImageMapPlotSize).",".floor($this->GraphAreaY1+$XMargin-$ImageMapPlotSize).",".floor($X+$ImageMapPlotSize).",".floor($Y+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
4073
              }
4074
4075
             if ( $X != VOID ) { $LastGoodY = $Y; $LastGoodX = $X; }
4076
             if ( $X == VOID ) { $X = NULL; }
4077
4078
             if ( !$Init && $ReCenter ) { $Y = $Y - $YStep/2; $Init = TRUE; }
4079
             $LastX = $X; $LastY = $Y;
4080
             if ( $LastY < $this->GraphAreaY1 + $XMargin ) { $LastY = $this->GraphAreaY1 + $XMargin; }
4081
             $Y = $Y + $YStep;
4082
            }
4083
           if ( $ReCenter )
4084
            {
4085
             $this->drawLine($LastX,$LastY,$LastX,$this->GraphAreaY2 - $XMargin,$Color);
4086
             if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($LastX-$ImageMapPlotSize).",".floor($LastY-$ImageMapPlotSize).",".floor($LastX+$ImageMapPlotSize).",".floor($this->GraphAreaY2-$XMargin+$ImageMapPlotSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
4087
            }
4088
          }
4089
        }
4090
      }
4091
    }
4092
4093
   /* Draw a step chart */
4094
   function drawFilledStepChart($Format=NULL)
4095
    {
4096
     $ReCenter		= isset($Format["ReCenter"]) ? $Format["ReCenter"] : TRUE;
4097
     $DisplayValues	= isset($Format["DisplayValues"]) ? $Format["DisplayValues"] :FALSE;
4098
     $DisplayOffset	= isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 2;
4099
     $DisplayColor	= isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL;
4100
     $ForceTransparency	= isset($Format["ForceTransparency"]) ? $Format["ForceTransparency"] : NULL;
4101
     $DisplayR		= isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0;
4102
     $DisplayG		= isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0;
4103
     $DisplayB		= isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0;
4104
     $AroundZero	= isset($Format["AroundZero"]) ? $Format["AroundZero"] : TRUE;
4105
4106
     $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR;
4107
4108
     $Data = $this->DataSet->getData();
4109
     list($XMargin,$XDivs) = $this->scaleGetXSettings();
4110
     foreach($Data["Series"] as $SerieName => $Serie)
4111
      {
4112
       if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] )
4113
        {
4114
         $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; $Weight = $Serie["Weight"];
4115
4116
         if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; }
4117
4118
         $AxisID	= $Serie["Axis"];
4119
         $Mode		= $Data["Axis"][$AxisID]["Display"];
4120
         $Format	= $Data["Axis"][$AxisID]["Format"];
4121
         $Unit		= $Data["Axis"][$AxisID]["Unit"];
4122
4123
         $Color		= array("R"=>$R,"G"=>$G,"B"=>$B);
4124
         if ( $ForceTransparency != NULL ) { $Color["Alpha"] = $ForceTransparency; } else { $Color["Alpha"] = $Alpha; }
4125
4126
         $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"]));
4127
         $YZero    = $this->scaleComputeY(0,array("AxisID"=>$Serie["Axis"]));
4128
4129
         $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0;
4130
4131
         if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT )
4132
          {
4133
           if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; }
4134
           if ( $YZero < $this->GraphAreaY1+1 ) { $YZero = $this->GraphAreaY1+1; }
4135
4136
           if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; }
4137
           $X = $this->GraphAreaX1 + $XMargin; $LastX = NULL; $LastY = NULL;
4138
4139
           if ( !$AroundZero ) { $YZero = $this->GraphAreaY2-1; }
4140
4141
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
4142
           $LastGoodY = NULL; $LastGoodX = NULL; $Points = ""; $Init = FALSE;
4143
           foreach($PosArray as $Key => $Y)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
4144
            {
4145
             if ( $Y == VOID && $LastX != NULL && $LastY != NULL && $Points !="" )
4146
              {
4147
               $Points[] = $LastX; $Points[] = $LastY;
4148
               $Points[] = $X; $Points[] = $LastY;
4149
               $Points[] = $X; $Points[] = $YZero;
4150
               $this->drawPolygon($Points,$Color);
4151
               $Points = "";
4152
              }
4153
4154
             if ( $Y != VOID && $LastX != NULL && $LastY != NULL )
4155
              {
4156
               if ( $Points == "") { $Points[] = $LastX; $Points[] = $YZero; }
4157
               $Points[] = $LastX; $Points[] = $LastY;
4158
               $Points[] = $X; $Points[] = $LastY;
4159
               $Points[] = $X; $Points[] = $Y;
4160
              }
4161
4162
             if ( $Y != VOID ) { $LastGoodY = $Y; $LastGoodX = $X; }
4163
             if ( $Y == VOID ) { $Y = NULL; }
4164
4165
             if ( !$Init && $ReCenter ) { $X = $X - $XStep/2; $Init = TRUE; }
4166
             $LastX = $X; $LastY = $Y;
4167
             if ( $LastX < $this->GraphAreaX1 + $XMargin ) { $LastX = $this->GraphAreaX1 + $XMargin; }
4168
             $X = $X + $XStep;
4169
            }
4170
4171
           if ( $ReCenter )
4172
            {
4173
             $Points[] = $LastX+$XStep/2; $Points[] = $LastY;
4174
             $Points[] = $LastX+$XStep/2; $Points[] = $YZero;
4175
            }
4176
           else
4177
            { $Points[] = $LastX; $Points[] = $YZero; }
4178
4179
           $this->drawPolygon($Points,$Color);
4180
          }
4181
         else
4182
          {
4183
           if ( $YZero < $this->GraphAreaX1+1 ) { $YZero = $this->GraphAreaX1+1; }
4184
           if ( $YZero > $this->GraphAreaX2-1 ) { $YZero = $this->GraphAreaX2-1; }
4185
4186
           if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; }
4187
           $Y = $this->GraphAreaY1 + $XMargin; $LastX = NULL; $LastY = NULL;
4188
4189
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
4190
           $LastGoodY = NULL; $LastGoodX = NULL; $Points = "";
4191
           foreach($PosArray as $Key => $X)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
4192
            {
4193
             if ( $X == VOID && $LastX != NULL && $LastY != NULL && $Points !="" )
4194
              {
4195
               $Points[] = $LastX; $Points[] = $LastY;
4196
               $Points[] = $LastX; $Points[] = $Y;
4197
               $Points[] = $YZero; $Points[] = $Y;
4198
               $this->drawPolygon($Points,$Color);
4199
               $Points = "";
4200
              }
4201
4202
             if ( $X != VOID && $LastX != NULL && $LastY != NULL )
4203
              {
4204
               if ( $Points == "") { $Points[] = $YZero; $Points[] = $LastY; }
4205
               $Points[] = $LastX; $Points[] = $LastY;
4206
               $Points[] = $LastX; $Points[] = $Y;
4207
               $Points[] = $X; $Points[] = $Y;
4208
              }
4209
4210
             if ( $X != VOID ) { $LastGoodY = $Y; $LastGoodX = $X; }
4211
             if ( $X == VOID ) { $X = NULL; }
4212
4213
             if ( $LastX == NULL && $ReCenter ) { $Y = $Y - $YStep/2; }
4214
             $LastX = $X; $LastY = $Y;
4215
             if ( $LastY < $this->GraphAreaY1 + $XMargin ) { $LastY = $this->GraphAreaY1 + $XMargin; }
4216
             $Y = $Y + $YStep;
4217
            }
4218
4219
           if ( $ReCenter )
4220
            {
4221
             $Points[] = $LastX; $Points[] = $LastY+$YStep/2;
4222
             $Points[] = $YZero; $Points[] = $LastY+$YStep/2;
4223
            }
4224
           else
4225
            { $Points[] = $YZero; $Points[] = $LastY; }
4226
4227
           $this->drawPolygon($Points,$Color);
4228
          }
4229
        }
4230
      }
4231
    }
4232
4233
   /* Draw an area chart */
4234
   function drawAreaChart($Format=NULL)
4235
    {
4236
     $DisplayValues	= isset($Format["DisplayValues"]) ? $Format["DisplayValues"] : FALSE;
4237
     $DisplayOffset	= isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 2;
4238
     $DisplayColor	= isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL;
4239
     $DisplayR		= isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0;
4240
     $DisplayG		= isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0;
4241
     $DisplayB		= isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0;
4242
     $ForceTransparency	= isset($Format["ForceTransparency"]) ? $Format["ForceTransparency"] : 25;
4243
     $AroundZero	= isset($Format["AroundZero"]) ? $Format["AroundZero"] : TRUE;
4244
     $Threshold		= isset($Format["Threshold"]) ? $Format["Threshold"] : NULL;
4245
4246
     $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR;
4247
4248
     $Data  = $this->DataSet->getData();
4249
     list($XMargin,$XDivs) = $this->scaleGetXSettings();
4250
4251
     foreach($Data["Series"] as $SerieName => $Serie)
4252
      {
4253
       if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] )
4254
        {
4255
         $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"];
4256
         if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; }
4257
4258
         $AxisID	= $Serie["Axis"];
4259
         $Mode		= $Data["Axis"][$AxisID]["Display"];
4260
         $Format	= $Data["Axis"][$AxisID]["Format"];
4261
         $Unit		= $Data["Axis"][$AxisID]["Unit"];
4262
4263
         $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"]));
4264
         $YZero    = $this->scaleComputeY(0,array("AxisID"=>$Serie["Axis"]));
4265
4266
         if ( $Threshold != NULL )
4267
          {
4268
           foreach($Threshold as $Key => $Params)
4269
            {
4270
             $Threshold[$Key]["MinX"] = $this->scaleComputeY($Params["Min"],array("AxisID"=>$Serie["Axis"]));
4271
             $Threshold[$Key]["MaxX"] = $this->scaleComputeY($Params["Max"],array("AxisID"=>$Serie["Axis"]));
4272
            }
4273
          }
4274
4275
         $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0;
4276
4277
         if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT )
4278
          {
4279
           if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; }
4280
4281
           $Areas = ""; $AreaID = 0; 
4282
           $Areas[$AreaID][] = $this->GraphAreaX1 + $XMargin;
4283
           if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaY2-1; }
4284
4285
           if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; }
4286
           $X = $this->GraphAreaX1 + $XMargin; $LastX = NULL; $LastY = NULL;
4287
4288
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
4289
           foreach($PosArray as $Key => $Y)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
4290
            {
4291
             if ( $DisplayValues && $Serie["Data"][$Key] != VOID )
4292
              {
4293
               if ( $Serie["Data"][$Key] > 0 ) { $Align = TEXT_ALIGN_BOTTOMMIDDLE; $Offset = $DisplayOffset; } else { $Align = TEXT_ALIGN_TOPMIDDLE; $Offset = -$DisplayOffset; }
4294
               $this->drawText($X,$Y-$Offset,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>$Align));
4295
              }
4296
4297
             if ( $Y == VOID && isset($Areas[$AreaID]) )
4298
              {
4299
               if($LastX == NULL)
4300
                { $Areas[$AreaID][] = $X; }
4301
               else
4302
                { $Areas[$AreaID][] = $LastX; }
4303
4304
               if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaY2-1; }
4305
               $AreaID++;
4306
              }
4307
             elseif ($Y != VOID)
4308
              {
4309
               if ( !isset($Areas[$AreaID]) )
4310
                {
4311
                 $Areas[$AreaID][] = $X;
4312
                 if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaY2-1; }
4313
                }
4314
4315
               $Areas[$AreaID][] = $X;
4316
               $Areas[$AreaID][] = $Y;
4317
              }
4318
4319
             $LastX = $X;
4320
             $X = $X + $XStep;
4321
            }
4322
           $Areas[$AreaID][] = $LastX;
4323
           if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaY2-1; }
4324
4325
           /* Handle shadows in the areas */
4326
           if ( $this->Shadow )
4327
            {
4328
             $ShadowArea = "";
4329
             foreach($Areas as $Key => $Points)
0 ignored issues
show
Bug introduced by
The expression $Areas of type string is not traversable.
Loading history...
4330
              {
4331
               $ShadowArea[$Key] = "";
4332
               foreach($Points as $Key2 => $Value)
4333
                {
4334
                 if ( $Key2 % 2 == 0 )
4335
                  { $ShadowArea[$Key][] = $Value + $this->ShadowX; }
4336
                 else
4337
                  { $ShadowArea[$Key][] = $Value + $this->ShadowY; }
4338
                }
4339
              }              
4340
4341
             foreach($ShadowArea as $Key => $Points)
0 ignored issues
show
Bug introduced by
The expression $ShadowArea of type string is not traversable.
Loading history...
4342
              $this->drawPolygonChart($Points,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa));
4343
            }
4344
4345
           $Alpha = $ForceTransparency != NULL ? $ForceTransparency : $Alpha;
4346
           $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Threshold"=>$Threshold);
4347
4348
           foreach($Areas as $Key => $Points)
0 ignored issues
show
Bug introduced by
The expression $Areas of type string is not traversable.
Loading history...
4349
            $this->drawPolygonChart($Points,$Color);
4350
          }
4351
         else
4352
          {
4353
           if ( $YZero < $this->GraphAreaX1+1 ) { $YZero = $this->GraphAreaX1+1; }
4354
           if ( $YZero > $this->GraphAreaX2-1 ) { $YZero = $this->GraphAreaX2-1; }
4355
4356
           $Areas = ""; $AreaID = 0; 
4357
           if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaX1+1; }
4358
           $Areas[$AreaID][] = $this->GraphAreaY1 + $XMargin;
4359
4360
           if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; }
4361
           $Y     = $this->GraphAreaY1 + $XMargin; $LastX = NULL; $LastY = NULL;
4362
4363
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
4364
           foreach($PosArray as $Key => $X)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
4365
            {
4366
             if ( $DisplayValues && $Serie["Data"][$Key] != VOID )
4367
              {
4368
               if ( $Serie["Data"][$Key] > 0 ) { $Align = TEXT_ALIGN_BOTTOMMIDDLE; $Offset = $DisplayOffset; } else { $Align = TEXT_ALIGN_TOPMIDDLE; $Offset = -$DisplayOffset; }
4369
               $this->drawText($X+$Offset,$Y,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("Angle"=>270,"R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>$Align));
4370
              }
4371
4372
             if ( $X == VOID && isset($Areas[$AreaID]) )
4373
              {
4374
               if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaX1+1; }
4375
4376
               if($LastY == NULL)
4377
                { $Areas[$AreaID][] = $Y; }
4378
               else
4379
                { $Areas[$AreaID][] = $LastY; }
4380
4381
               $AreaID++;
4382
              }
4383
             elseif ($X != VOID)
4384
              {
4385
               if ( !isset($Areas[$AreaID]) )
4386
                {
4387
                 if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaX1+1; }
4388
                 $Areas[$AreaID][] = $Y;
4389
                }
4390
4391
               $Areas[$AreaID][] = $X;
4392
               $Areas[$AreaID][] = $Y;
4393
              }
4394
4395
             $LastX = $X; $LastY = $Y;
4396
             $Y = $Y + $YStep;
4397
            }
4398
           if ( $AroundZero ) { $Areas[$AreaID][] = $YZero; } else { $Areas[$AreaID][] = $this->GraphAreaX1+1; }
4399
           $Areas[$AreaID][] = $LastY;
4400
4401
           /* Handle shadows in the areas */
4402
           if ( $this->Shadow )
4403
            {
4404
             $ShadowArea = "";
4405
             foreach($Areas as $Key => $Points)
0 ignored issues
show
Bug introduced by
The expression $Areas of type string is not traversable.
Loading history...
4406
              {
4407
               $ShadowArea[$Key] = "";
4408
               foreach($Points as $Key2 => $Value)
4409
                {
4410
                 if ( $Key2 % 2 == 0 )
4411
                  { $ShadowArea[$Key][] = $Value + $this->ShadowX; }
4412
                 else
4413
                  { $ShadowArea[$Key][] = $Value + $this->ShadowY; }
4414
                }
4415
              }              
4416
4417
             foreach($ShadowArea as $Key => $Points)
0 ignored issues
show
Bug introduced by
The expression $ShadowArea of type string is not traversable.
Loading history...
4418
              $this->drawPolygonChart($Points,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa));
4419
            }
4420
4421
           $Alpha = $ForceTransparency != NULL ? $ForceTransparency : $Alpha;
4422
           $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Threshold"=>$Threshold);
4423
4424
           foreach($Areas as $Key => $Points)
0 ignored issues
show
Bug introduced by
The expression $Areas of type string is not traversable.
Loading history...
4425
            $this->drawPolygonChart($Points,$Color);
4426
          }
4427
        }
4428
      }
4429
    }
4430
4431
4432
   /* Draw a bar chart */
4433
   function drawBarChart($Format=NULL)
4434
    {
4435
     $Floating0Serie	= isset($Format["Floating0Serie"]) ? $Format["Floating0Serie"] : NULL;
4436
     $Floating0Value	= isset($Format["Floating0Value"]) ? $Format["Floating0Value"] : NULL;
4437
     $Draw0Line		= isset($Format["Draw0Line"]) ? $Format["Draw0Line"] : FALSE;
4438
     $DisplayValues	= isset($Format["DisplayValues"]) ? $Format["DisplayValues"] : FALSE;
4439
     $DisplayOrientation = isset($Format["DisplayOrientation"]) ? $Format["DisplayOrientation"] : ORIENTATION_HORIZONTAL;
4440
     $DisplayOffset	= isset($Format["DisplayOffset"]) ? $Format["DisplayOffset"] : 2;
4441
     $DisplayColor	= isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL;
4442
     $DisplayFont	= isset($Format["DisplaySize"]) ? $Format["DisplaySize"] : $this->FontName;
4443
     $DisplaySize	= isset($Format["DisplaySize"]) ? $Format["DisplaySize"] : $this->FontSize;
4444
     $DisplayPos	= isset($Format["DisplayPos"]) ? $Format["DisplayPos"] : LABEL_POS_OUTSIDE;
4445
     $DisplayShadow	= isset($Format["DisplayShadow"]) ? $Format["DisplayShadow"] : TRUE;
4446
     $DisplayR		= isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0;
4447
     $DisplayG		= isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0;
4448
     $DisplayB		= isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0;
4449
     $AroundZero	= isset($Format["AroundZero"]) ? $Format["AroundZero"] : TRUE;
4450
     $Interleave	= isset($Format["Interleave"]) ? $Format["Interleave"] : .5;
4451
     $Rounded		= isset($Format["Rounded"]) ? $Format["Rounded"] : FALSE;
4452
     $RoundRadius	= isset($Format["RoundRadius"]) ? $Format["RoundRadius"] : 4;
4453
     $Surrounding	= isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL;
4454
     $BorderR		= isset($Format["BorderR"]) ? $Format["BorderR"] : -1;
4455
     $BorderG		= isset($Format["BorderG"]) ? $Format["BorderG"] : -1;
4456
     $BorderB		= isset($Format["BorderB"]) ? $Format["BorderB"] : -1;
4457
     $Gradient		= isset($Format["Gradient"]) ? $Format["Gradient"] : FALSE;
4458
     $GradientMode	= isset($Format["GradientMode"]) ? $Format["GradientMode"] : GRADIENT_SIMPLE;
4459
     $GradientAlpha	= isset($Format["GradientAlpha"]) ? $Format["GradientAlpha"] : 20;
4460
     $GradientStartR	= isset($Format["GradientStartR"]) ? $Format["GradientStartR"] : 255;
4461
     $GradientStartG	= isset($Format["GradientStartG"]) ? $Format["GradientStartG"] : 255;
4462
     $GradientStartB	= isset($Format["GradientStartB"]) ? $Format["GradientStartB"] : 255;
4463
     $GradientEndR	= isset($Format["GradientEndR"]) ? $Format["GradientEndR"] : 0;
4464
     $GradientEndG	= isset($Format["GradientEndG"]) ? $Format["GradientEndG"] : 0;
4465
     $GradientEndB	= isset($Format["GradientEndB"]) ? $Format["GradientEndB"] : 0;
4466
     $TxtMargin		= isset($Format["TxtMargin"]) ? $Format["TxtMargin"] : 6;
4467
     $OverrideColors	= isset($Format["OverrideColors"]) ? $Format["OverrideColors"] : NULL;
4468
     $OverrideSurrounding = isset($Format["OverrideSurrounding"]) ? $Format["OverrideSurrounding"] : 30;
4469
     $InnerSurrounding	= isset($Format["InnerSurrounding"]) ? $Format["InnerSurrounding"] : NULL;
4470
     $InnerBorderR	= isset($Format["InnerBorderR"]) ? $Format["InnerBorderR"] : -1;
4471
     $InnerBorderG	= isset($Format["InnerBorderG"]) ? $Format["InnerBorderG"] : -1;
4472
     $InnerBorderB	= isset($Format["InnerBorderB"]) ? $Format["InnerBorderB"] : -1;
4473
     $RecordImageMap	= isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE;
4474
4475
     $this->LastChartLayout = CHART_LAST_LAYOUT_REGULAR;
4476
4477
     $Data = $this->DataSet->getData();
4478
     list($XMargin,$XDivs) = $this->scaleGetXSettings();
4479
4480
     if ( $OverrideColors != NULL )
4481
      {
4482
       $OverrideColors = $this->validatePalette($OverrideColors,$OverrideSurrounding);
4483
       $this->DataSet->saveExtendedData("Palette",$OverrideColors);
4484
      }
4485
4486
     $RestoreShadow = $this->Shadow;
4487
4488
     $SeriesCount  = $this->countDrawableSeries();
4489
     $CurrentSerie = 0;
4490
     foreach($Data["Series"] as $SerieName => $Serie)
4491
      {
4492
       if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] )
4493
        {
4494
         $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"];
4495
         if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = $R; $DisplayG = $G; $DisplayB = $B; }
4496
         if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; }
4497
         if ( $InnerSurrounding != NULL ) { $InnerBorderR = $R+$InnerSurrounding; $InnerBorderG = $G+$InnerSurrounding; $InnerBorderB = $B+$InnerSurrounding; }
4498
         if ( $InnerBorderR == -1 ) { $InnerColor = NULL; } else { $InnerColor = array("R"=>$InnerBorderR,"G"=>$InnerBorderG,"B"=>$InnerBorderB); }
4499
         $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB);
4500
4501
         $AxisID	= $Serie["Axis"];
4502
         $Mode		= $Data["Axis"][$AxisID]["Display"];
4503
         $Format	= $Data["Axis"][$AxisID]["Format"];
4504
         $Unit		= $Data["Axis"][$AxisID]["Unit"];
4505
4506
         if (isset($Serie["Description"])) { $SerieDescription = $Serie["Description"]; } else { $SerieDescription = $SerieName; }
4507
4508
         $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"]));
4509
4510
         if ( $Floating0Value != NULL )
4511
          { $YZero = $this->scaleComputeY($Floating0Value,array("AxisID"=>$Serie["Axis"])); }
4512
         else
4513
          { $YZero = $this->scaleComputeY(0,array("AxisID"=>$Serie["Axis"])); }
4514
4515
         if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT )
4516
          {
4517
           if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; }
4518
           if ( $YZero < $this->GraphAreaY1+1 ) { $YZero = $this->GraphAreaY1+1; }
4519
4520
           if ( $XDivs == 0 ) { $XStep = 0; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; }
4521
           $X = $this->GraphAreaX1 + $XMargin;
4522
4523
           if ( $AroundZero ) { $Y1 = $YZero; } else { $Y1 = $this->GraphAreaY2-1; }
4524
           if ( $XDivs == 0 ) { $XSize = ($this->GraphAreaX2-$this->GraphAreaX1)/($SeriesCount+$Interleave); } else { $XSize   = ($XStep / ($SeriesCount+$Interleave) ); }
4525
4526
           $XOffset = -($XSize*$SeriesCount)/2 + $CurrentSerie * $XSize;
4527
           if ( $X + $XOffset <= $this->GraphAreaX1 ) { $XOffset = $this->GraphAreaX1 - $X + 1 ; }
4528
4529
           $this->DataSet->Data["Series"][$SerieName]["XOffset"] = $XOffset + $XSize / 2;
4530
4531
           if ( $Rounded || $BorderR != -1) { $XSpace = 1; } else { $XSpace = 0; }
4532
4533
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
4534
4535
           $ID = 0;
4536
           foreach($PosArray as $Key => $Y2)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
4537
            {
4538
             if ( $Floating0Serie != NULL )
4539
              {
4540
               if ( isset($Data["Series"][$Floating0Serie]["Data"][$Key]) )
4541
                { $Value = $Data["Series"][$Floating0Serie]["Data"][$Key]; }
4542
               else
4543
                { $Value = 0; }
4544
4545
               $YZero = $this->scaleComputeY($Value,array("AxisID"=>$Serie["Axis"]));
4546
               if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; }
4547
               if ( $YZero < $this->GraphAreaY1+1 ) { $YZero = $this->GraphAreaY1+1; }
4548
4549
               if ( $AroundZero ) { $Y1 = $YZero; } else { $Y1 = $this->GraphAreaY2-1; }
4550
              }
4551
4552
             if ( $OverrideColors != NULL )
4553
              { if ( isset($OverrideColors[$ID]) ) { $Color = array("R"=>$OverrideColors[$ID]["R"],"G"=>$OverrideColors[$ID]["G"],"B"=>$OverrideColors[$ID]["B"],"Alpha"=>$OverrideColors[$ID]["Alpha"],"BorderR"=>$OverrideColors[$ID]["BorderR"],"BorderG"=>$OverrideColors[$ID]["BorderG"],"BorderB"=>$OverrideColors[$ID]["BorderB"]); } else { $Color = $this->getRandomColor(); } }
4554
4555
             if ( $Y2 != VOID )
4556
              {
4557
               $BarHeight = $Y1 - $Y2;
4558
4559
               if ( $Serie["Data"][$Key] == 0 )
4560
                {
4561
                 $this->drawLine($X+$XOffset+$XSpace,$Y1,$X+$XOffset+$XSize-$XSpace,$Y1,$Color);
4562
                 if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X+$XOffset+$XSpace).",".floor($Y1-1).",".floor($X+$XOffset+$XSize-$XSpace).",".floor($Y1+1),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
4563
                }
4564
               else
4565
                {
4566
                 if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X+$XOffset+$XSpace).",".floor($Y1).",".floor($X+$XOffset+$XSize-$XSpace).",".floor($Y2),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
4567
4568
                 if ( $Rounded )
4569
                  $this->drawRoundedFilledRectangle($X+$XOffset+$XSpace,$Y1,$X+$XOffset+$XSize-$XSpace,$Y2,$RoundRadius,$Color);
4570
                 else
4571
                  {
4572
                   $this->drawFilledRectangle($X+$XOffset+$XSpace,$Y1,$X+$XOffset+$XSize-$XSpace,$Y2,$Color);
4573
4574
                   if ( $InnerColor != NULL ) { $this->drawRectangle($X+$XOffset+$XSpace+1,min($Y1,$Y2)+1,$X+$XOffset+$XSize-$XSpace-1,max($Y1,$Y2)-1,$InnerColor); }
4575
4576
                   if ( $Gradient )
4577
                    {
4578
                     $this->Shadow  = FALSE;
4579
4580
                     if ( $GradientMode == GRADIENT_SIMPLE )
4581
                      {
4582
                       if ( $Serie["Data"][$Key] >= 0 )
4583
                        $GradienColor = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha);
4584
                       else
4585
                        $GradienColor = array("StartR"=>$GradientEndR,"StartG"=>$GradientEndG,"StartB"=>$GradientEndB,"EndR"=>$GradientStartR,"EndG"=>$GradientStartG,"EndB"=>$GradientStartB,"Alpha"=>$GradientAlpha);
4586
4587
                       $this->drawGradientArea($X+$XOffset+$XSpace,$Y1,$X+$XOffset+$XSize-$XSpace,$Y2,DIRECTION_VERTICAL,$GradienColor);
4588
                      }
4589
                     elseif ( $GradientMode == GRADIENT_EFFECT_CAN )
4590
                      {
4591
                       $GradienColor1 = array("StartR"=>$GradientEndR,"StartG"=>$GradientEndG,"StartB"=>$GradientEndB,"EndR"=>$GradientStartR,"EndG"=>$GradientStartG,"EndB"=>$GradientStartB,"Alpha"=>$GradientAlpha);
4592
                       $GradienColor2 = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha);
4593
                       $XSpan = floor($XSize / 3);
4594
4595
                       $this->drawGradientArea($X+$XOffset+$XSpace,$Y1,$X+$XOffset+$XSpan-$XSpace,$Y2,DIRECTION_HORIZONTAL,$GradienColor1);
4596
                       $this->drawGradientArea($X+$XOffset+$XSpan+$XSpace,$Y1,$X+$XOffset+$XSize-$XSpace,$Y2,DIRECTION_HORIZONTAL,$GradienColor2);
4597
                      }
4598
                     $this->Shadow = $RestoreShadow;
4599
                    }
4600
                  }
4601
4602
                 if ( $Draw0Line )
4603
                  {
4604
                   $Line0Color = array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>20);
4605
4606
                   if ( abs($Y1 - $Y2) > 3 ) { $Line0Width = 3; } else { $Line0Width = 1; }
4607
                   if ( $Y1 - $Y2 < 0 ) { $Line0Width = -$Line0Width; }
4608
4609
                   $this->drawFilledRectangle($X+$XOffset+$XSpace,floor($Y1),$X+$XOffset+$XSize-$XSpace,floor($Y1)-$Line0Width,$Line0Color);
4610
                   $this->drawLine($X+$XOffset+$XSpace,floor($Y1),$X+$XOffset+$XSize-$XSpace,floor($Y1),$Line0Color);
4611
                  }
4612
                }
4613
4614
               if ( $DisplayValues && $Serie["Data"][$Key] != VOID )
4615
                {
4616
                 if ( $DisplayShadow ) { $this->Shadow = TRUE; }
4617
4618
                 $Caption    = $this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit);
4619
                 $TxtPos     = $this->getTextBox(0,0,$DisplayFont,$DisplaySize,90,$Caption);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getTextBox() does only exist in the following sub-classes of pDraw: pImage. 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...
4620
                 $TxtHeight  = $TxtPos[0]["Y"] - $TxtPos[1]["Y"] + $TxtMargin;
4621
4622
                 if ( $DisplayPos == LABEL_POS_INSIDE && abs($TxtHeight) < abs($BarHeight) )
4623
                  {
4624
                   $CenterX = (($X+$XOffset+$XSize-$XSpace)-($X+$XOffset+$XSpace))/2 + $X+$XOffset+$XSpace;
4625
                   $CenterY = ($Y2-$Y1)/2 + $Y1;
4626
4627
                   $this->drawText($CenterX,$CenterY,$Caption,array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontSize"=>$DisplaySize,"Angle"=>90));
4628
                  }
4629
                 else
4630
                  {
4631
                   if ( $Serie["Data"][$Key] >= 0 ) { $Align = TEXT_ALIGN_BOTTOMMIDDLE; $Offset = $DisplayOffset; } else { $Align = TEXT_ALIGN_TOPMIDDLE; $Offset = -$DisplayOffset; }
4632
                   $this->drawText($X+$XOffset+$XSize/2,$Y2-$Offset,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>$Align,"FontSize"=>$DisplaySize));
4633
                  }
4634
4635
                 $this->Shadow = $RestoreShadow;
4636
                }
4637
              }
4638
4639
             $X = $X + $XStep;
4640
             $ID++;
4641
            }
4642
          }
4643
         else
4644
          {
4645
           if ( $YZero < $this->GraphAreaX1+1 ) { $YZero = $this->GraphAreaX1+1; }
4646
           if ( $YZero > $this->GraphAreaX2-1 ) { $YZero = $this->GraphAreaX2-1; }
4647
4648
           if ( $XDivs == 0 ) { $YStep = 0; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; }
4649
           
4650
           $Y = $this->GraphAreaY1 + $XMargin;
4651
4652
           if ( $AroundZero ) { $X1 = $YZero; } else { $X1 = $this->GraphAreaX1+1; }
4653
           if ( $XDivs == 0 ) { $YSize = ($this->GraphAreaY2-$this->GraphAreaY1)/($SeriesCount+$Interleave); } else { $YSize   = ($YStep / ($SeriesCount+$Interleave) ); }
4654
           
4655
           $YOffset = -($YSize*$SeriesCount)/2 + $CurrentSerie * $YSize;
4656
           if ( $Y + $YOffset <= $this->GraphAreaY1 ) { $YOffset = $this->GraphAreaY1 - $Y + 1 ; }
4657
4658
           $this->DataSet->Data["Series"][$SerieName]["XOffset"] = $YOffset + $YSize / 2;
4659
4660
           if ( $Rounded || $BorderR != -1 ) { $YSpace = 1; } else { $YSpace = 0; }
4661
4662
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
4663
4664
           $ID = 0 ;
4665
           foreach($PosArray as $Key => $X2)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
4666
            {
4667
             if ( $Floating0Serie != NULL )
4668
              {
4669
               if ( isset($Data["Series"][$Floating0Serie]["Data"][$Key]) )
4670
                $Value = $Data["Series"][$Floating0Serie]["Data"][$Key];
4671
               else { $Value = 0; }
4672
4673
               $YZero = $this->scaleComputeY($Value,array("AxisID"=>$Serie["Axis"]));
4674
               if ( $YZero < $this->GraphAreaX1+1 ) { $YZero = $this->GraphAreaX1+1; }
4675
               if ( $YZero > $this->GraphAreaX2-1 ) { $YZero = $this->GraphAreaX2-1; }
4676
               if ( $AroundZero ) { $X1 = $YZero; } else { $X1 = $this->GraphAreaX1+1; }
4677
              }
4678
4679
             if ( $OverrideColors != NULL )
4680
              { if ( isset($OverrideColors[$ID]) ) { $Color = array("R"=>$OverrideColors[$ID]["R"],"G"=>$OverrideColors[$ID]["G"],"B"=>$OverrideColors[$ID]["B"],"Alpha"=>$OverrideColors[$ID]["Alpha"],"BorderR"=>$OverrideColors[$ID]["BorderR"],"BorderG"=>$OverrideColors[$ID]["BorderG"],"BorderB"=>$OverrideColors[$ID]["BorderB"]); } else { $Color = $this->getRandomColor(); } }
4681
4682
             if ( $X2 != VOID )
4683
              {
4684
               $BarWidth = $X2 - $X1;
4685
4686
               if ( $Serie["Data"][$Key] == 0 )
4687
                {
4688
                 $this->drawLine($X1,$Y+$YOffset+$YSpace,$X1,$Y+$YOffset+$YSize-$YSpace,$Color);
4689
                 if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X1-1).",".floor($Y+$YOffset+$YSpace).",".floor($X1+1).",".floor($Y+$YOffset+$YSize-$YSpace),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
4690
                }
4691
               else
4692
                {
4693
                 if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X1).",".floor($Y+$YOffset+$YSpace).",".floor($X2).",".floor($Y+$YOffset+$YSize-$YSpace),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
4694
4695
                 if ( $Rounded )
4696
                  $this->drawRoundedFilledRectangle($X1+1,$Y+$YOffset+$YSpace,$X2,$Y+$YOffset+$YSize-$YSpace,$RoundRadius,$Color);
4697
                 else
4698
                  {
4699
                   $this->drawFilledRectangle($X1,$Y+$YOffset+$YSpace,$X2,$Y+$YOffset+$YSize-$YSpace,$Color);
4700
4701
                   if ( $InnerColor != NULL ) { $this->drawRectangle(min($X1,$X2)+1,$Y+$YOffset+$YSpace+1,max($X1,$X2)-1,$Y+$YOffset+$YSize-$YSpace-1,$InnerColor); }
4702
4703
                   if ( $Gradient )
4704
                    {
4705
                     $this->Shadow  = FALSE;
4706
4707
                     if ( $GradientMode == GRADIENT_SIMPLE )
4708
                      {
4709
                       if ( $Serie["Data"][$Key] >= 0 )
4710
                        $GradienColor = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha);
4711
                       else
4712
                        $GradienColor = array("StartR"=>$GradientEndR,"StartG"=>$GradientEndG,"StartB"=>$GradientEndB,"EndR"=>$GradientStartR,"EndG"=>$GradientStartG,"EndB"=>$GradientStartB,"Alpha"=>$GradientAlpha);
4713
4714
                       $this->drawGradientArea($X1,$Y+$YOffset+$YSpace,$X2,$Y+$YOffset+$YSize-$YSpace,DIRECTION_HORIZONTAL,$GradienColor);
4715
                      }
4716
                     elseif ( $GradientMode == GRADIENT_EFFECT_CAN )
4717
                      {
4718
                       $GradienColor1 = array("StartR"=>$GradientEndR,"StartG"=>$GradientEndG,"StartB"=>$GradientEndB,"EndR"=>$GradientStartR,"EndG"=>$GradientStartG,"EndB"=>$GradientStartB,"Alpha"=>$GradientAlpha);
4719
                       $GradienColor2 = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha);
4720
                       $YSpan = floor($YSize / 3);
4721
4722
                       $this->drawGradientArea($X1,$Y+$YOffset+$YSpace,$X2,$Y+$YOffset+$YSpan-$YSpace,DIRECTION_VERTICAL,$GradienColor1);
4723
                       $this->drawGradientArea($X1,$Y+$YOffset+$YSpan,$X2,$Y+$YOffset+$YSize-$YSpace,DIRECTION_VERTICAL,$GradienColor2);
4724
                      }
4725
                     $this->Shadow = $RestoreShadow;
4726
                    }
4727
                  }
4728
4729
                 if ( $Draw0Line )
4730
                  {
4731
                   $Line0Color = array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>20);
4732
4733
                   if ( abs($X1 - $X2) > 3 ) { $Line0Width = 3; } else { $Line0Width = 1; }
4734
                   if ( $X2 - $X1 < 0 ) { $Line0Width = -$Line0Width; }
4735
4736
                   $this->drawFilledRectangle(floor($X1),$Y+$YOffset+$YSpace,floor($X1)+$Line0Width,$Y+$YOffset+$YSize-$YSpace,$Line0Color);
4737
                   $this->drawLine(floor($X1),$Y+$YOffset+$YSpace,floor($X1),$Y+$YOffset+$YSize-$YSpace,$Line0Color);
4738
                  }
4739
                }
4740
4741
               if ( $DisplayValues && $Serie["Data"][$Key] != VOID ) 
4742
                {
4743
                 if ( $DisplayShadow ) { $this->Shadow = TRUE; }
4744
4745
                 $Caption   = $this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit);
4746
                 $TxtPos    = $this->getTextBox(0,0,$DisplayFont,$DisplaySize,0,$Caption);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getTextBox() does only exist in the following sub-classes of pDraw: pImage. 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...
4747
                 $TxtWidth  = $TxtPos[1]["X"] - $TxtPos[0]["X"] + $TxtMargin;
4748
4749
                 if ( $DisplayPos == LABEL_POS_INSIDE && abs($TxtWidth) < abs($BarWidth) )
4750
                  {
4751
                   $CenterX = ($X2-$X1)/2 + $X1;
4752
                   $CenterY = (($Y+$YOffset+$YSize-$YSpace)-($Y+$YOffset+$YSpace))/2 + ($Y+$YOffset+$YSpace);
4753
4754
                   $this->drawText($CenterX,$CenterY,$Caption,array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontSize"=>$DisplaySize));
4755
                  }
4756
                 else
4757
                  {
4758
                   if ( $Serie["Data"][$Key] >= 0 ) { $Align = TEXT_ALIGN_MIDDLELEFT; $Offset = $DisplayOffset; } else { $Align = TEXT_ALIGN_MIDDLERIGHT; $Offset = -$DisplayOffset; }
4759
                   $this->drawText($X2+$Offset,$Y+$YOffset+$YSize/2,$Caption,array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>$Align,"FontSize"=>$DisplaySize));
4760
                  }
4761
4762
                 $this->Shadow = $RestoreShadow;
4763
                }
4764
              }
4765
             $Y = $Y + $YStep;
4766
             $ID++;
4767
            }
4768
          }
4769
         $CurrentSerie++;
4770
        }
4771
      }
4772
    }
4773
4774
   /* Draw a bar chart */
4775
   function drawStackedBarChart($Format=NULL)
4776
    {
4777
     $DisplayValues	= isset($Format["DisplayValues"]) ? $Format["DisplayValues"] : FALSE;
4778
     $DisplayOrientation = isset($Format["DisplayOrientation"]) ? $Format["DisplayOrientation"] : ORIENTATION_AUTO;
4779
     $DisplayRound      = isset($Format["DisplayRound"]) ? $Format["DisplayRound"] : 0;
4780
     $DisplayColor	= isset($Format["DisplayColor"]) ? $Format["DisplayColor"] : DISPLAY_MANUAL;
4781
     $DisplayFont	= isset($Format["DisplayFont"]) ? $Format["DisplayFont"] : $this->FontName;
4782
     $DisplaySize	= isset($Format["DisplaySize"]) ? $Format["DisplaySize"] : $this->FontSize;
4783
     $DisplayR		= isset($Format["DisplayR"]) ? $Format["DisplayR"] : 0;
4784
     $DisplayG		= isset($Format["DisplayG"]) ? $Format["DisplayG"] : 0;
4785
     $DisplayB		= isset($Format["DisplayB"]) ? $Format["DisplayB"] : 0;
4786
     $Interleave	= isset($Format["Interleave"]) ? $Format["Interleave"] : .5;
4787
     $Rounded		= isset($Format["Rounded"]) ? $Format["Rounded"] : FALSE;
4788
     $RoundRadius	= isset($Format["RoundRadius"]) ? $Format["RoundRadius"] : 4;
4789
     $Surrounding	= isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL;
4790
     $BorderR		= isset($Format["BorderR"]) ? $Format["BorderR"] : -1;
4791
     $BorderG		= isset($Format["BorderG"]) ? $Format["BorderG"] : -1;
4792
     $BorderB		= isset($Format["BorderB"]) ? $Format["BorderB"] : -1;
4793
     $Gradient		= isset($Format["Gradient"]) ? $Format["Gradient"] : FALSE;
4794
     $GradientMode	= isset($Format["GradientMode"]) ? $Format["GradientMode"] : GRADIENT_SIMPLE;
4795
     $GradientAlpha	= isset($Format["GradientAlpha"]) ? $Format["GradientAlpha"] : 20;
4796
     $GradientStartR	= isset($Format["GradientStartR"]) ? $Format["GradientStartR"] : 255;
4797
     $GradientStartG	= isset($Format["GradientStartG"]) ? $Format["GradientStartG"] : 255;
4798
     $GradientStartB	= isset($Format["GradientStartB"]) ? $Format["GradientStartB"] : 255;
4799
     $GradientEndR	= isset($Format["GradientEndR"]) ? $Format["GradientEndR"] : 0;
4800
     $GradientEndG	= isset($Format["GradientEndG"]) ? $Format["GradientEndG"] : 0;
4801
     $GradientEndB	= isset($Format["GradientEndB"]) ? $Format["GradientEndB"] : 0;
4802
     $InnerSurrounding	= isset($Format["InnerSurrounding"]) ? $Format["InnerSurrounding"] : NULL;
4803
     $InnerBorderR	= isset($Format["InnerBorderR"]) ? $Format["InnerBorderR"] : -1;
4804
     $InnerBorderG	= isset($Format["InnerBorderG"]) ? $Format["InnerBorderG"] : -1;
4805
     $InnerBorderB	= isset($Format["InnerBorderB"]) ? $Format["InnerBorderB"] : -1;
4806
     $RecordImageMap	= isset($Format["RecordImageMap"]) ? $Format["RecordImageMap"] : FALSE;
4807
     $FontFactor	= isset($Format["FontFactor"]) ? $Format["FontFactor"] : 8;
4808
4809
     $this->LastChartLayout = CHART_LAST_LAYOUT_STACKED;
4810
4811
     $Data = $this->DataSet->getData();
4812
     list($XMargin,$XDivs) = $this->scaleGetXSettings();
4813
4814
     $RestoreShadow = $this->Shadow;
4815
4816
     $LastX = ""; $LastY = "";
4817
     foreach($Data["Series"] as $SerieName => $Serie)
4818
      {
4819
       if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] )
4820
        {
4821
         $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"];
4822
         if ( $DisplayColor == DISPLAY_AUTO ) { $DisplayR = 255; $DisplayG = 255; $DisplayB = 255; }
4823
         if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; }
4824
         if ( $InnerSurrounding != NULL ) { $InnerBorderR = $R+$InnerSurrounding; $InnerBorderG = $G+$InnerSurrounding; $InnerBorderB = $B+$InnerSurrounding; }
4825
         if ( $InnerBorderR == -1 ) { $InnerColor = NULL; } else { $InnerColor = array("R"=>$InnerBorderR,"G"=>$InnerBorderG,"B"=>$InnerBorderB); }
4826
4827
         $AxisID	= $Serie["Axis"];
4828
         $Mode		= $Data["Axis"][$AxisID]["Display"];
4829
         $Format	= $Data["Axis"][$AxisID]["Format"];
4830
         $Unit		= $Data["Axis"][$AxisID]["Unit"];
4831
4832
         if (isset($Serie["Description"])) { $SerieDescription = $Serie["Description"]; } else { $SerieDescription = $SerieName; }
4833
4834
         $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"]),TRUE);
4835
         $YZero    = $this->scaleComputeY(0,array("AxisID"=>$Serie["Axis"]));
4836
4837
         $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0;
4838
4839
         $Color = array("TransCorner"=>TRUE,"R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"BorderR"=>$BorderR,"BorderG"=>$BorderG,"BorderB"=>$BorderB);
4840
4841
         if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT )
4842
          {
4843
           if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; }
4844
           if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; }
4845
4846
           if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; }
4847
           $X     = $this->GraphAreaX1 + $XMargin;
4848
4849
           $XSize   = ($XStep / (1+$Interleave) );
4850
           $XOffset = -($XSize/2);
4851
4852
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
4853
           foreach($PosArray as $Key => $Height)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
4854
            {
4855
             if ( $Height != VOID && $Serie["Data"][$Key] != 0 )
4856
              {
4857
               if ( $Serie["Data"][$Key] > 0 ) { $Pos = "+"; } else { $Pos = "-"; }
4858
4859
               if ( !isset($LastY[$Key] ) ) { $LastY[$Key] = ""; }
4860
               if ( !isset($LastY[$Key][$Pos] ) ) { $LastY[$Key][$Pos] = $YZero; }
4861
4862
               $Y1 = $LastY[$Key][$Pos];
4863
               $Y2 = $Y1 - $Height;
4864
4865
               if ( ($Rounded || $BorderR != -1) && ($Pos == "+" && $Y1 != $YZero) ) { $YSpaceUp = 1; } else { $YSpaceUp = 0; }
4866
               if ( ($Rounded || $BorderR != -1) && ($Pos == "-" && $Y1 != $YZero) ) { $YSpaceDown = 1; } else { $YSpaceDown = 0; }
4867
4868
               if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X+$XOffset).",".floor($Y1-$YSpaceUp+$YSpaceDown).",".floor($X+$XOffset+$XSize).",".floor($Y2),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
4869
4870
               if ( $Rounded )
4871
                $this->drawRoundedFilledRectangle($X+$XOffset,$Y1-$YSpaceUp+$YSpaceDown,$X+$XOffset+$XSize,$Y2,$RoundRadius,$Color);
4872
               else
4873
                {
4874
                 $this->drawFilledRectangle($X+$XOffset,$Y1-$YSpaceUp+$YSpaceDown,$X+$XOffset+$XSize,$Y2,$Color);
4875
4876
                 if ( $InnerColor != NULL ) { $RestoreShadow = $this->Shadow; $this->Shadow = FALSE; $this->drawRectangle(min($X+$XOffset+1,$X+$XOffset+$XSize),min($Y1-$YSpaceUp+$YSpaceDown,$Y2)+1,max($X+$XOffset+1,$X+$XOffset+$XSize)-1,max($Y1-$YSpaceUp+$YSpaceDown,$Y2)-1,$InnerColor); $this->Shadow = $RestoreShadow;}
4877
4878
                 if ( $Gradient )
4879
                  {
4880
                   $this->Shadow  = FALSE;
4881
4882
                   if ( $GradientMode == GRADIENT_SIMPLE )
4883
                    {
4884
                     $GradientColor = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha);
4885
                     $this->drawGradientArea($X+$XOffset,$Y1-1-$YSpaceUp+$YSpaceDown,$X+$XOffset+$XSize,$Y2+1,DIRECTION_VERTICAL,$GradientColor);
4886
                    }
4887
                   elseif ( $GradientMode == GRADIENT_EFFECT_CAN )
4888
                    {
4889
                     $GradientColor1 = array("StartR"=>$GradientEndR,"StartG"=>$GradientEndG,"StartB"=>$GradientEndB,"EndR"=>$GradientStartR,"EndG"=>$GradientStartG,"EndB"=>$GradientStartB,"Alpha"=>$GradientAlpha);
4890
                     $GradientColor2 = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha);
4891
                     $XSpan = floor($XSize / 3);
4892
4893
                     $this->drawGradientArea($X+$XOffset-.5,$Y1-.5-$YSpaceUp+$YSpaceDown,$X+$XOffset+$XSpan,$Y2+.5,DIRECTION_HORIZONTAL,$GradientColor1);
4894
                     $this->drawGradientArea($X+$XSpan+$XOffset-.5,$Y1-.5-$YSpaceUp+$YSpaceDown,$X+$XOffset+$XSize,$Y2+.5,DIRECTION_HORIZONTAL,$GradientColor2);
4895
                    }
4896
                   $this->Shadow = $RestoreShadow;
4897
                  }
4898
                }
4899
4900
               if ( $DisplayValues )
4901
                {
4902
                 $BarHeight = abs($Y2-$Y1)-2;
4903
                 $BarWidth  = $XSize+($XOffset/2)-$FontFactor;
4904
4905
                 $Caption   = $this->scaleFormat(round($Serie["Data"][$Key],$DisplayRound),$Mode,$Format,$Unit);
4906
                 $TxtPos    = $this->getTextBox(0,0,$DisplayFont,$DisplaySize,0,$Caption);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getTextBox() does only exist in the following sub-classes of pDraw: pImage. 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...
4907
                 $TxtHeight = abs($TxtPos[2]["Y"] - $TxtPos[0]["Y"]);
4908
                 $TxtWidth  = abs($TxtPos[1]["X"] - $TxtPos[0]["X"]);
4909
4910
                 $XCenter = ( ($X+$XOffset+$XSize) - ($X+$XOffset) ) / 2 + $X+$XOffset;
4911
                 $YCenter = ( ($Y2) - ($Y1-$YSpaceUp+$YSpaceDown) ) / 2 + $Y1-$YSpaceUp+$YSpaceDown;
4912
4913
                 $Done = FALSE;
4914
                 if ( $DisplayOrientation == ORIENTATION_HORIZONTAL || $DisplayOrientation == ORIENTATION_AUTO )
4915
                  {
4916
                   if ( $TxtHeight < $BarHeight && $TxtWidth < $BarWidth  )
4917
                    {
4918
                     $this->drawText($XCenter,$YCenter,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontSize"=>$DisplaySize,"FontName"=>$DisplayFont));
4919
                     $Done = TRUE;
4920
                    }
4921
                  }
4922
4923
                 if ( $DisplayOrientation == ORIENTATION_VERTICAL || ( $DisplayOrientation == ORIENTATION_AUTO && !$Done) )
4924
                  {
4925
                   if ( $TxtHeight < $BarWidth && $TxtWidth < $BarHeight  )
4926
                    $this->drawText($XCenter,$YCenter,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Angle"=>90,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontSize"=>$DisplaySize,"FontName"=>$DisplayFont));
4927
                  }
4928
                }
4929
4930
               $LastY[$Key][$Pos] = $Y2;
4931
              }
4932
4933
             $X = $X + $XStep;
4934
            }
4935
          }
4936
         else
4937
          {
4938
           if ( $YZero < $this->GraphAreaX1+1 ) { $YZero = $this->GraphAreaX1+1; }
4939
           if ( $YZero > $this->GraphAreaX2-1 ) { $YZero = $this->GraphAreaX2-1; }
4940
4941
           if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; }
4942
           $Y     = $this->GraphAreaY1 + $XMargin;
4943
4944
           $YSize   = $YStep / (1+$Interleave);
4945
           $YOffset = -($YSize/2);
4946
4947
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
4948
           foreach($PosArray as $Key => $Width)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
4949
            {
4950
             if ( $Width != VOID && $Serie["Data"][$Key] != 0 )
4951
              {
4952
               if ( $Serie["Data"][$Key] > 0 ) { $Pos = "+"; } else { $Pos = "-"; }
4953
4954
               if ( !isset($LastX[$Key] ) ) { $LastX[$Key] = ""; }
4955
               if ( !isset($LastX[$Key][$Pos] ) ) { $LastX[$Key][$Pos] = $YZero; }
4956
4957
               $X1 = $LastX[$Key][$Pos];
4958
               $X2 = $X1 + $Width;
4959
4960
               if ( ($Rounded || $BorderR != -1) && ($Pos == "+" && $X1 != $YZero) ) { $XSpaceLeft = 2; } else { $XSpaceLeft = 0; }
4961
               if ( ($Rounded || $BorderR != -1) && ($Pos == "-" && $X1 != $YZero) ) { $XSpaceRight = 2; } else { $XSpaceRight = 0; }
4962
4963
               if ( $RecordImageMap ) { $this->addToImageMap("RECT",floor($X1+$XSpaceLeft).",".floor($Y+$YOffset).",".floor($X2-$XSpaceRight).",".floor($Y+$YOffset+$YSize),$this->toHTMLColor($R,$G,$B),$SerieDescription,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit)); }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method toHTMLColor() does only exist in the following sub-classes of pDraw: pImage. 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...
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method addToImageMap() does only exist in the following sub-classes of pDraw: pImage. 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...
4964
4965
               if ( $Rounded )
4966
                $this->drawRoundedFilledRectangle($X1+$XSpaceLeft,$Y+$YOffset,$X2-$XSpaceRight,$Y+$YOffset+$YSize,$RoundRadius,$Color);
4967
               else
4968
                {
4969
                 $this->drawFilledRectangle($X1+$XSpaceLeft,$Y+$YOffset,$X2-$XSpaceRight,$Y+$YOffset+$YSize,$Color);
4970
4971
                 if ( $InnerColor != NULL ) { $RestoreShadow = $this->Shadow; $this->Shadow = FALSE; $this->drawRectangle(min($X1+$XSpaceLeft,$X2-$XSpaceRight)+1,min($Y+$YOffset,$Y+$YOffset+$YSize)+1,max($X1+$XSpaceLeft,$X2-$XSpaceRight)-1,max($Y+$YOffset,$Y+$YOffset+$YSize)-1,$InnerColor); $this->Shadow = $RestoreShadow;}
4972
4973
                 if ( $Gradient )
4974
                  {
4975
                   $this->Shadow  = FALSE;
4976
4977
                   if ( $GradientMode == GRADIENT_SIMPLE )
4978
                    {
4979
                     $GradientColor = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha);
4980
                     $this->drawGradientArea($X1+$XSpaceLeft,$Y+$YOffset,$X2-$XSpaceRight,$Y+$YOffset+$YSize,DIRECTION_HORIZONTAL,$GradientColor);
4981
                    }
4982
                   elseif ( $GradientMode == GRADIENT_EFFECT_CAN )
4983
                    {
4984
                     $GradientColor1 = array("StartR"=>$GradientEndR,"StartG"=>$GradientEndG,"StartB"=>$GradientEndB,"EndR"=>$GradientStartR,"EndG"=>$GradientStartG,"EndB"=>$GradientStartB,"Alpha"=>$GradientAlpha);
4985
                     $GradientColor2 = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$GradientAlpha);
4986
                     $YSpan = floor($YSize / 3);
4987
4988
                     $this->drawGradientArea($X1+$XSpaceLeft,$Y+$YOffset,$X2-$XSpaceRight,$Y+$YOffset+$YSpan,DIRECTION_VERTICAL,$GradientColor1);
4989
                     $this->drawGradientArea($X1+$XSpaceLeft,$Y+$YOffset+$YSpan,$X2-$XSpaceRight,$Y+$YOffset+$YSize,DIRECTION_VERTICAL,$GradientColor2);
4990
                    }
4991
                   $this->Shadow = $RestoreShadow;
4992
                  }
4993
                }
4994
4995
               if ( $DisplayValues )
4996
                {
4997
                 $BarWidth = abs($X2-$X1)-$FontFactor;
4998
                 $BarHeight = $YSize+($YOffset/2)-$FontFactor/2;
4999
                 $Caption   = $this->scaleFormat(round($Serie["Data"][$Key],$DisplayRound),$Mode,$Format,$Unit);
5000
                 $TxtPos    = $this->getTextBox(0,0,$DisplayFont,$DisplaySize,0,$Caption);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getTextBox() does only exist in the following sub-classes of pDraw: pImage. 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...
5001
                 $TxtHeight = abs($TxtPos[2]["Y"] - $TxtPos[0]["Y"]);
5002
                 $TxtWidth  = abs($TxtPos[1]["X"] - $TxtPos[0]["X"]);
5003
5004
                 $XCenter  = ( $X2 - $X1 ) / 2 + $X1;
5005
                 $YCenter  = ( ($Y+$YOffset+$YSize) - ($Y+$YOffset) ) / 2 + $Y+$YOffset;
5006
5007
                 $Done = FALSE;
5008
                 if ( $DisplayOrientation == ORIENTATION_HORIZONTAL || $DisplayOrientation == ORIENTATION_AUTO )
5009
                  {
5010
                   if ( $TxtHeight < $BarHeight && $TxtWidth < $BarWidth  )
5011
                    {
5012
                     $this->drawText($XCenter,$YCenter,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontSize"=>$DisplaySize,"FontName"=>$DisplayFont));
5013
                     $Done = TRUE;
5014
                    }
5015
                  }
5016
5017
                 if ( $DisplayOrientation == ORIENTATION_VERTICAL || ( $DisplayOrientation == ORIENTATION_AUTO && !$Done) )
5018
                  {
5019
                   if ( $TxtHeight < $BarWidth && $TxtWidth < $BarHeight  )
5020
                    $this->drawText($XCenter,$YCenter,$this->scaleFormat($Serie["Data"][$Key],$Mode,$Format,$Unit),array("R"=>$DisplayR,"G"=>$DisplayG,"B"=>$DisplayB,"Angle"=>90,"Align"=>TEXT_ALIGN_MIDDLEMIDDLE,"FontSize"=>$DisplaySize,"FontName"=>$DisplayFont));
5021
                  }
5022
                }
5023
5024
               $LastX[$Key][$Pos] = $X2;
5025
              }
5026
5027
             $Y = $Y + $YStep;
5028
            }
5029
          }
5030
        }
5031
      }
5032
    }
5033
5034
   /* Draw a stacked area chart */
5035
   function drawStackedAreaChart($Format=NULL)
5036
    {
5037
     $DrawLine		= isset($Format["DrawLine"]) ? $Format["DrawLine"] : FALSE;
5038
     $LineSurrounding	= isset($Format["LineSurrounding"]) ? $Format["LineSurrounding"] : NULL;
5039
     $LineR		= isset($Format["LineR"]) ? $Format["LineR"] : VOID;
5040
     $LineG		= isset($Format["LineG"]) ? $Format["LineG"] : VOID;
5041
     $LineB		= isset($Format["LineB"]) ? $Format["LineB"] : VOID;
5042
     $LineAlpha		= isset($Format["LineAlpha"]) ? $Format["LineAlpha"] : 100;
5043
     $DrawPlot		= isset($Format["DrawPlot"]) ? $Format["DrawPlot"] : FALSE;
5044
     $PlotRadius	= isset($Format["PlotRadius"]) ? $Format["PlotRadius"] : 2;
5045
     $PlotBorder	= isset($Format["PlotBorder"]) ? $Format["PlotBorder"] : 1;
5046
     $PlotBorderSurrounding = isset($Format["PlotBorderSurrounding"]) ? $Format["PlotBorderSurrounding"] : NULL;
5047
     $PlotBorderR	= isset($Format["PlotBorderR"]) ? $Format["PlotBorderR"] : 0;
5048
     $PlotBorderG	= isset($Format["PlotBorderG"]) ? $Format["PlotBorderG"] : 0;
5049
     $PlotBorderB	= isset($Format["PlotBorderB"]) ? $Format["PlotBorderB"] : 0;
5050
     $PlotBorderAlpha	= isset($Format["PlotBorderAlpha"]) ? $Format["PlotBorderAlpha"] : 50;
5051
     $ForceTransparency	= isset($Format["ForceTransparency"]) ? $Format["ForceTransparency"] : NULL;
5052
5053
     $this->LastChartLayout = CHART_LAST_LAYOUT_STACKED;
5054
5055
     $Data = $this->DataSet->getData();
5056
     list($XMargin,$XDivs) = $this->scaleGetXSettings();
5057
5058
     $RestoreShadow = $this->Shadow;
5059
     $this->Shadow  = FALSE;
5060
5061
     /* Build the offset data series */
5062
     $OffsetData    = "";
5063
     $OverallOffset = "";
5064
     $SerieOrder    = "";
5065
     foreach($Data["Series"] as $SerieName => $Serie)
5066
      {
5067
       if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] )
5068
        {
5069
         $SerieOrder[] = $SerieName;
5070
5071
         foreach($Serie["Data"] as $Key => $Value)
5072
          {
5073
           if ( $Value == VOID ) { $Value = 0; }
5074
           if ($Value >= 0) { $Sign = "+"; } else { $Sign = "-"; }
5075
           if ( !isset($OverallOffset[$Key]) || !isset($OverallOffset[$Key][$Sign]) ) { $OverallOffset[$Key][$Sign] = 0; }
5076
5077
           if ( $Sign == "+" )
5078
            { $Data["Series"][$SerieName]["Data"][$Key] = $Value + $OverallOffset[$Key][$Sign]; }
5079
           else
5080
            { $Data["Series"][$SerieName]["Data"][$Key] = $Value - $OverallOffset[$Key][$Sign]; }
5081
5082
           $OverallOffset[$Key][$Sign] = $OverallOffset[$Key][$Sign] + abs($Value);
5083
          }
5084
        } 
5085
      }
5086
     $SerieOrder = array_reverse($SerieOrder);
5087
5088
     $LastX = ""; $LastY = "";
5089
     foreach($SerieOrder as $Key => $SerieName)
5090
      {
5091
       $Serie = $Data["Series"][$SerieName];
5092
       if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] )
5093
        {
5094
         $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"];
5095
         if ( $ForceTransparency != NULL ) { $Alpha = $ForceTransparency; }
5096
5097
         $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha);
5098
5099
         if ( $LineSurrounding != NULL )
5100
          $LineColor = array("R"=>$R+$LineSurrounding,"G"=>$G+$LineSurrounding,"B"=>$B+$LineSurrounding,"Alpha"=>$Alpha);
5101
         elseif ( $LineR != VOID )
5102
          $LineColor = array("R"=>$LineR,"G"=>$LineG,"B"=>$LineB,"Alpha"=>$LineAlpha);
5103
         else
5104
          $LineColor = $Color;
5105
5106
         if ( $PlotBorderSurrounding != NULL )
5107
          $PlotBorderColor = array("R"=>$R+$PlotBorderSurrounding,"G"=>$G+$PlotBorderSurrounding,"B"=>$B+$PlotBorderSurrounding,"Alpha"=>$PlotBorderAlpha);
5108
         else
5109
          $PlotBorderColor = array("R"=>$PlotBorderR,"G"=>$PlotBorderG,"B"=>$PlotBorderB,"Alpha"=>$PlotBorderAlpha);
5110
5111
         $AxisID	= $Serie["Axis"];
5112
         $Mode		= $Data["Axis"][$AxisID]["Display"];
5113
         $Format	= $Data["Axis"][$AxisID]["Format"];
5114
         $Unit		= $Data["Axis"][$AxisID]["Unit"];
5115
5116
         $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"]),TRUE);
5117
         $YZero    = $this->scaleComputeY(0,array("AxisID"=>$Serie["Axis"]));
5118
5119
         $this->DataSet->Data["Series"][$SerieName]["XOffset"] = 0;
5120
5121
         if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT )
5122
          {
5123
           if ( $YZero < $this->GraphAreaY1+1 ) { $YZero = $this->GraphAreaY1+1; }
5124
           if ( $YZero > $this->GraphAreaY2-1 ) { $YZero = $this->GraphAreaY2-1; }
5125
5126
           if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; }
5127
           $X = $this->GraphAreaX1 + $XMargin;
5128
5129
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
5130
5131
           $Plots = ""; $Plots[] = $X; $Plots[] = $YZero;
5132
           foreach($PosArray as $Key => $Height)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
5133
            {
5134
             if ( $Height != VOID ) { $Plots[] = $X; $Plots[] = $YZero-$Height; }
5135
             $X = $X + $XStep;
5136
            }
5137
           $Plots[] = $X-$XStep; $Plots[] = $YZero;
5138
5139
           $this->drawPolygon($Plots,$Color);
5140
5141
           $this->Shadow = $RestoreShadow;
5142
           if ( $DrawLine ) { for($i=2; $i<=count($Plots)-6; $i=$i+2) { $this->drawLine($Plots[$i],$Plots[$i+1],$Plots[$i+2],$Plots[$i+3],$LineColor); } }
5143
           if ( $DrawPlot )
5144
            {
5145
             for($i=2; $i<=count($Plots)-4; $i=$i+2)
5146
              {
5147
               if ( $PlotBorder != 0 )
5148
                { $this->drawFilledCircle($Plots[$i],$Plots[$i+1],$PlotRadius+$PlotBorder,$PlotBorderColor); }
5149
5150
               $this->drawFilledCircle($Plots[$i],$Plots[$i+1],$PlotRadius,$Color);
5151
              }
5152
            }
5153
           $this->Shadow = FALSE;
5154
          }
5155
         elseif ( $Data["Orientation"] == SCALE_POS_TOPBOTTOM )
5156
          {
5157
           if ( $YZero < $this->GraphAreaX1+1 ) { $YZero = $this->GraphAreaX1+1; }
5158
           if ( $YZero > $this->GraphAreaX2-1 ) { $YZero = $this->GraphAreaX2-1; }
5159
5160
           if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; }
5161
           $Y = $this->GraphAreaY1 + $XMargin;
5162
5163
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
5164
5165
           $Plots = ""; $Plots[] = $YZero; $Plots[] = $Y;
5166
           foreach($PosArray as $Key => $Height)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
5167
            {
5168
             if ( $Height != VOID ) { $Plots[] = $YZero+$Height; $Plots[] = $Y; }
5169
             $Y = $Y + $YStep;
5170
            }
5171
           $Plots[] = $YZero; $Plots[] = $Y-$YStep;
5172
5173
           $this->drawPolygon($Plots,$Color);
5174
5175
           $this->Shadow = $RestoreShadow;
5176
           if ( $DrawLine ) { for($i=2; $i<=count($Plots)-6; $i=$i+2) { $this->drawLine($Plots[$i],$Plots[$i+1],$Plots[$i+2],$Plots[$i+3],$LineColor); } }
5177
           if ( $DrawPlot )
5178
            {
5179
             for($i=2; $i<=count($Plots)-4; $i=$i+2)
5180
              {
5181
               if ( $PlotBorder != 0 )
5182
                { $this->drawFilledCircle($Plots[$i],$Plots[$i+1],$PlotRadius+$PlotBorder,$PlotBorderColor); }
5183
5184
               $this->drawFilledCircle($Plots[$i],$Plots[$i+1],$PlotRadius,$Color);
5185
              }
5186
            }
5187
           $this->Shadow = FALSE;
5188
          }
5189
        }
5190
      }
5191
     $this->Shadow = $RestoreShadow;
5192
    }
5193
5194
   /* Returns a random color */
5195
   function getRandomColor($Alpha=100)
5196
    { return(array("R"=>rand(0,255),"G"=>rand(0,255),"B"=>rand(0,255),"Alpha"=>$Alpha)); }
5197
 
5198
   /* Validate a palette */
5199
   function validatePalette($Colors,$Surrounding=NULL)
5200
    {
5201
     $Result = "";
5202
5203
     if ( !is_array($Colors) ) { return($this->getRandomColor()); }
5204
5205
     foreach($Colors as $Key => $Values)
5206
      {
5207
       if ( isset($Values["R"]) ) { $Result[$Key]["R"] = $Values["R"]; } else { $Result[$Key]["R"] = rand(0,255); }
5208
       if ( isset($Values["G"]) ) { $Result[$Key]["G"] = $Values["G"]; } else { $Result[$Key]["G"] = rand(0,255); }
5209
       if ( isset($Values["B"]) ) { $Result[$Key]["B"] = $Values["B"]; } else { $Result[$Key]["B"] = rand(0,255); }
5210
       if ( isset($Values["Alpha"]) ) { $Result[$Key]["Alpha"] = $Values["Alpha"]; } else { $Result[$Key]["Alpha"] = 100; }
5211
5212
       if ( $Surrounding != NULL )
5213
        {
5214
         $Result[$Key]["BorderR"] = $Result[$Key]["R"] + $Surrounding;
5215
         $Result[$Key]["BorderG"] = $Result[$Key]["G"] + $Surrounding;
5216
         $Result[$Key]["BorderB"] = $Result[$Key]["B"] + $Surrounding;
5217
        }
5218
       else
5219
        {
5220
         if ( isset($Values["BorderR"]) )     { $Result[$Key]["BorderR"] = $Values["BorderR"]; } else { $Result[$Key]["BorderR"] = $Result[$Key]["R"]; }
5221
         if ( isset($Values["BorderG"]) )     { $Result[$Key]["BorderG"] = $Values["BorderG"]; } else { $Result[$Key]["BorderG"] = $Result[$Key]["G"]; }
5222
         if ( isset($Values["BorderB"]) )     { $Result[$Key]["BorderB"] = $Values["BorderB"]; } else { $Result[$Key]["BorderB"] = $Result[$Key]["B"]; }
5223
         if ( isset($Values["BorderAlpha"]) ) { $Result[$Key]["BorderAlpha"] = $Values["BorderAlpha"]; } else { $Result[$Key]["BorderAlpha"] = $Result[$Key]["Alpha"]; }
5224
        }
5225
      }
5226
5227
     return($Result);
5228
    }
5229
5230
   /* Draw the derivative chart associated to the data series */
5231
   function drawDerivative($Format=NULL)
5232
    {
5233
     $Offset		= isset($Format["Offset"]) ? $Format["Offset"] : 10;
5234
     $SerieSpacing	= isset($Format["SerieSpacing"]) ? $Format["SerieSpacing"] : 3;
5235
     $DerivativeHeight	= isset($Format["DerivativeHeight"]) ? $Format["DerivativeHeight"] : 4;
5236
     $ShadedSlopeBox	= isset($Format["ShadedSlopeBox"]) ? $Format["ShadedSlopeBox"] : FALSE;
5237
     $DrawBackground	= isset($Format["DrawBackground"]) ? $Format["DrawBackground"] : TRUE;
5238
     $BackgroundR	= isset($Format["BackgroundR"]) ? $Format["BackgroundR"] : 255;
5239
     $BackgroundG	= isset($Format["BackgroundG"]) ? $Format["BackgroundG"] : 255;
5240
     $BackgroundB	= isset($Format["BackgroundB"]) ? $Format["BackgroundB"] : 255;
5241
     $BackgroundAlpha	= isset($Format["BackgroundAlpha"]) ? $Format["BackgroundAlpha"] : 20;
5242
     $DrawBorder	= isset($Format["DrawBorder"]) ? $Format["DrawBorder"] : TRUE;
5243
     $BorderR		= isset($Format["BorderR"]) ? $Format["BorderR"] : 0;
5244
     $BorderG		= isset($Format["BorderG"]) ? $Format["BorderG"] : 0;
5245
     $BorderB		= isset($Format["BorderB"]) ? $Format["BorderB"] : 0;
5246
     $BorderAlpha	= isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : 100;
5247
     $Caption		= isset($Format["Caption"]) ? $Format["Caption"] : TRUE;
5248
     $CaptionHeight	= isset($Format["CaptionHeight"]) ? $Format["CaptionHeight"] : 10;
5249
     $CaptionWidth	= isset($Format["CaptionWidth"]) ? $Format["CaptionWidth"] : 20;
5250
     $CaptionMargin	= isset($Format["CaptionMargin"]) ? $Format["CaptionMargin"] : 4;
5251
     $CaptionLine	= isset($Format["CaptionLine"]) ? $Format["CaptionLine"] : FALSE;
5252
     $CaptionBox	= isset($Format["CaptionBox"]) ? $Format["CaptionBox"] : FALSE;
5253
     $CaptionBorderR	= isset($Format["CaptionBorderR"]) ? $Format["CaptionBorderR"] : 0;
5254
     $CaptionBorderG	= isset($Format["CaptionBorderG"]) ? $Format["CaptionBorderG"] : 0;
5255
     $CaptionBorderB	= isset($Format["CaptionBorderB"]) ? $Format["CaptionBorderB"] : 0;
5256
     $CaptionFillR	= isset($Format["CaptionFillR"]) ? $Format["CaptionFillR"] : 255;
5257
     $CaptionFillG	= isset($Format["CaptionFillG"]) ? $Format["CaptionFillG"] : 255;
5258
     $CaptionFillB	= isset($Format["CaptionFillB"]) ? $Format["CaptionFillB"] : 255;
5259
     $CaptionFillAlpha	= isset($Format["CaptionFillAlpha"]) ? $Format["CaptionFillAlpha"] : 80;
5260
     $PositiveSlopeStartR	= isset($Format["PositiveSlopeStartR"]) ? $Format["PositiveSlopeStartR"] : 184;
5261
     $PositiveSlopeStartG	= isset($Format["PositiveSlopeStartG"]) ? $Format["PositiveSlopeStartG"] : 234;
5262
     $PositiveSlopeStartB	= isset($Format["PositiveSlopeStartB"]) ? $Format["PositiveSlopeStartB"] : 88;
5263
     $PositiveSlopeEndR		= isset($Format["PositiveSlopeStartR"]) ? $Format["PositiveSlopeStartR"] : 239;
5264
     $PositiveSlopeEndG		= isset($Format["PositiveSlopeStartG"]) ? $Format["PositiveSlopeStartG"] : 31;
5265
     $PositiveSlopeEndB		= isset($Format["PositiveSlopeStartB"]) ? $Format["PositiveSlopeStartB"] : 36;
5266
     $NegativeSlopeStartR	= isset($Format["NegativeSlopeStartR"]) ? $Format["NegativeSlopeStartR"] : 184;
5267
     $NegativeSlopeStartG	= isset($Format["NegativeSlopeStartG"]) ? $Format["NegativeSlopeStartG"] : 234;
5268
     $NegativeSlopeStartB	= isset($Format["NegativeSlopeStartB"]) ? $Format["NegativeSlopeStartB"] : 88;
5269
     $NegativeSlopeEndR		= isset($Format["NegativeSlopeStartR"]) ? $Format["NegativeSlopeStartR"] : 67;
5270
     $NegativeSlopeEndG		= isset($Format["NegativeSlopeStartG"]) ? $Format["NegativeSlopeStartG"] : 124;
5271
     $NegativeSlopeEndB		= isset($Format["NegativeSlopeStartB"]) ? $Format["NegativeSlopeStartB"] : 227;
5272
5273
     $Data = $this->DataSet->getData();
5274
5275
     list($XMargin,$XDivs) = $this->scaleGetXSettings();
5276
5277
     if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT )
5278
      $YPos = $this->DataSet->Data["GraphArea"]["Y2"] + $Offset;
5279
     else
5280
      $XPos = $this->DataSet->Data["GraphArea"]["X2"] + $Offset;
5281
5282
     foreach($Data["Series"] as $SerieName => $Serie)
5283
      {
5284
       if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] )
5285
        {
5286
         $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; $Alpha = $Serie["Color"]["Alpha"]; $Ticks = $Serie["Ticks"]; $Weight = $Serie["Weight"];
5287
5288
         $AxisID   = $Serie["Axis"];
5289
         $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"]));
5290
5291
         if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT )
5292
          {
5293
           if ( $Caption )
5294
            {
5295
             if ( $CaptionLine ) 
5296
              {
5297
               $StartX = floor($this->GraphAreaX1-$CaptionWidth+$XMargin-$CaptionMargin);
5298
               $EndX   = floor($this->GraphAreaX1-$CaptionMargin+$XMargin);
5299
5300
               $CaptionSettings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight);
5301
               if ( $CaptionBox ) { $this->drawFilledRectangle($StartX,$YPos,$EndX,$YPos+$CaptionHeight,array("R"=>$CaptionFillR,"G"=>$CaptionFillG,"B"=>$CaptionFillB,"BorderR"=>$CaptionBorderR,"BorderG"=>$CaptionBorderG,"BorderB"=>$CaptionBorderB,"Alpha"=>$CaptionFillAlpha)); }
5302
               $this->drawLine($StartX+2,$YPos+($CaptionHeight/2),$EndX-2,$YPos+($CaptionHeight/2),$CaptionSettings);
5303
              }
5304
             else
5305
              $this->drawFilledRectangle($this->GraphAreaX1-$CaptionWidth+$XMargin-$CaptionMargin,$YPos,$this->GraphAreaX1-$CaptionMargin+$XMargin,$YPos+$CaptionHeight,array("R"=>$R,"G"=>$G,"B"=>$B,"BorderR"=>$CaptionBorderR,"BorderG"=>$CaptionBorderG,"BorderB"=>$CaptionBorderB));
5306
            }
5307
5308
           if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; }
5309
           $X = $this->GraphAreaX1 + $XMargin;
5310
5311
           $TopY    = $YPos + ($CaptionHeight/2) - ($DerivativeHeight/2);
5312
           $BottomY = $YPos + ($CaptionHeight/2) + ($DerivativeHeight/2);
5313
5314
           $StartX  = floor($this->GraphAreaX1+$XMargin);
5315
           $EndX    = floor($this->GraphAreaX2-$XMargin);
5316
5317
           if ( $DrawBackground ) { $this->drawFilledRectangle($StartX-1,$TopY-1,$EndX+1,$BottomY+1,array("R"=>$BackgroundR,"G"=>$BackgroundG,"B"=>$BackgroundB,"Alpha"=>$BackgroundAlpha)); }
5318
           if ( $DrawBorder ) { $this->drawRectangle($StartX-1,$TopY-1,$EndX+1,$BottomY+1,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha)); }
5319
5320
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
5321
5322
           $RestoreShadow = $this->Shadow;
5323
           $this->Shadow  = FALSE;
5324
5325
           /* Determine the Max slope index */
5326
           $LastX = NULL; $LastY = NULL; $MinSlope = 0; $MaxSlope = 1;
5327
           foreach($PosArray as $Key => $Y)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
5328
            {
5329
             if ( $Y != VOID && $LastX != NULL )
5330
              { $Slope = ($LastY - $Y); if ( $Slope > $MaxSlope ) { $MaxSlope = $Slope; } if ( $Slope < $MinSlope ) { $MinSlope = $Slope; } }
5331
5332
             if ( $Y == VOID )
5333
              { $LastX = NULL; $LastY = NULL; }
5334
             else
5335
              { $LastX = $X; $LastY = $Y; }
5336
            }
5337
5338
           $LastX = NULL; $LastY = NULL; $LastColor = NULL;
5339
           foreach($PosArray as $Key => $Y)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
5340
            {
5341
             if ( $Y != VOID && $LastY != NULL )
5342
              {
5343
               $Slope = ($LastY - $Y);
5344
5345
               if ( $Slope >= 0 )
5346
                {
5347
                 $SlopeIndex = (100 / $MaxSlope) * $Slope;
5348
                 $R = (($PositiveSlopeEndR - $PositiveSlopeStartR)/100)*$SlopeIndex+$PositiveSlopeStartR;
5349
                 $G = (($PositiveSlopeEndG - $PositiveSlopeStartG)/100)*$SlopeIndex+$PositiveSlopeStartG;
5350
                 $B = (($PositiveSlopeEndB - $PositiveSlopeStartB)/100)*$SlopeIndex+$PositiveSlopeStartB;
5351
                }
5352
               elseif ( $Slope < 0 )
5353
                {
5354
                 $SlopeIndex = (100 / abs($MinSlope)) * abs($Slope);
5355
                 $R = (($NegativeSlopeEndR - $NegativeSlopeStartR)/100)*$SlopeIndex+$NegativeSlopeStartR;
5356
                 $G = (($NegativeSlopeEndG - $NegativeSlopeStartG)/100)*$SlopeIndex+$NegativeSlopeStartG;
5357
                 $B = (($NegativeSlopeEndB - $NegativeSlopeStartB)/100)*$SlopeIndex+$NegativeSlopeStartB;
5358
                }
5359
5360
               $Color = array("R"=>$R,"G"=>$G,"B"=>$B);
5361
5362
               if ( $ShadedSlopeBox && $LastColor != NULL ) // && $Slope != 0
5363
                {
5364
                 $GradientSettings = array("StartR"=>$LastColor["R"],"StartG"=>$LastColor["G"],"StartB"=>$LastColor["B"],"EndR"=>$R,"EndG"=>$G,"EndB"=>$B);
5365
                 $this->drawGradientArea($LastX,$TopY,$X,$BottomY,DIRECTION_HORIZONTAL,$GradientSettings);
5366
                }
5367
               elseif ( !$ShadedSlopeBox || $LastColor == NULL ) // || $Slope == 0
5368
                $this->drawFilledRectangle(floor($LastX),$TopY,floor($X),$BottomY,$Color);
5369
5370
               $LastColor = $Color;
5371
              }
5372
5373
             if ( $Y == VOID )
5374
              { $LastY = NULL; }
5375
             else
5376
              { $LastX = $X; $LastY = $Y; }
5377
5378
             $X = $X + $XStep;
5379
            }
5380
5381
           $YPos = $YPos + $CaptionHeight + $SerieSpacing;
5382
          }
5383
         else
5384
          {
5385
           if ( $Caption )
5386
            {
5387
             $StartY = floor($this->GraphAreaY1-$CaptionWidth+$XMargin-$CaptionMargin);
5388
             $EndY   = floor($this->GraphAreaY1-$CaptionMargin+$XMargin);
5389
             if ( $CaptionLine ) 
5390
              {
5391
               $CaptionSettings = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks,"Weight"=>$Weight);
5392
               if ( $CaptionBox ) { $this->drawFilledRectangle($XPos,$StartY,$XPos+$CaptionHeight,$EndY,array("R"=>$CaptionFillR,"G"=>$CaptionFillG,"B"=>$CaptionFillB,"BorderR"=>$CaptionBorderR,"BorderG"=>$CaptionBorderG,"BorderB"=>$CaptionBorderB,"Alpha"=>$CaptionFillAlpha)); }
5393
               $this->drawLine($XPos+($CaptionHeight/2),$StartY+2,$XPos+($CaptionHeight/2),$EndY-2,$CaptionSettings);
5394
              }
5395
             else
5396
              $this->drawFilledRectangle($XPos,$StartY,$XPos+$CaptionHeight,$EndY,array("R"=>$R,"G"=>$G,"B"=>$B,"BorderR"=>$CaptionBorderR,"BorderG"=>$CaptionBorderG,"BorderB"=>$CaptionBorderB));
5397
            }
5398
5399
5400
           if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $XStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; }
5401
           $Y = $this->GraphAreaY1 + $XMargin;
5402
5403
           $TopX    = $XPos + ($CaptionHeight/2) - ($DerivativeHeight/2);
5404
           $BottomX = $XPos + ($CaptionHeight/2) + ($DerivativeHeight/2);
5405
5406
           $StartY  = floor($this->GraphAreaY1+$XMargin);
5407
           $EndY    = floor($this->GraphAreaY2-$XMargin);
5408
5409
           if ( $DrawBackground ) { $this->drawFilledRectangle($TopX-1,$StartY-1,$BottomX+1,$EndY+1,array("R"=>$BackgroundR,"G"=>$BackgroundG,"B"=>$BackgroundB,"Alpha"=>$BackgroundAlpha)); }
5410
           if ( $DrawBorder ) { $this->drawRectangle($TopX-1,$StartY-1,$BottomX+1,$EndY+1,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha)); }
5411
5412
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
5413
5414
           $RestoreShadow = $this->Shadow;
5415
           $this->Shadow  = FALSE;
5416
5417
           /* Determine the Max slope index */
5418
           $LastX = NULL; $LastY = NULL; $MinSlope = 0; $MaxSlope = 1;
5419
           foreach($PosArray as $Key => $X)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
5420
            {
5421
             if ( $X != VOID && $LastX != NULL )
5422
              { $Slope = ($X - $LastX); if ( $Slope > $MaxSlope ) { $MaxSlope = $Slope; } if ( $Slope < $MinSlope ) { $MinSlope = $Slope; } }
5423
5424
             if ( $X == VOID )
5425
              { $LastX = NULL; }
5426
             else
5427
              { $LastX = $X; }
5428
            }
5429
5430
           $LastX = NULL; $LastY = NULL; $LastColor = NULL;
5431
           foreach($PosArray as $Key => $X)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
5432
            {
5433
             if ( $X != VOID && $LastX != NULL )
5434
              {
5435
               $Slope = ($X - $LastX);
5436
5437
               if ( $Slope >= 0 )
5438
                {
5439
                 $SlopeIndex = (100 / $MaxSlope) * $Slope;
5440
                 $R = (($PositiveSlopeEndR - $PositiveSlopeStartR)/100)*$SlopeIndex+$PositiveSlopeStartR;
5441
                 $G = (($PositiveSlopeEndG - $PositiveSlopeStartG)/100)*$SlopeIndex+$PositiveSlopeStartG;
5442
                 $B = (($PositiveSlopeEndB - $PositiveSlopeStartB)/100)*$SlopeIndex+$PositiveSlopeStartB;
5443
                }
5444
               elseif ( $Slope < 0 )
5445
                {
5446
                 $SlopeIndex = (100 / abs($MinSlope)) * abs($Slope);
5447
                 $R = (($NegativeSlopeEndR - $NegativeSlopeStartR)/100)*$SlopeIndex+$NegativeSlopeStartR;
5448
                 $G = (($NegativeSlopeEndG - $NegativeSlopeStartG)/100)*$SlopeIndex+$NegativeSlopeStartG;
5449
                 $B = (($NegativeSlopeEndB - $NegativeSlopeStartB)/100)*$SlopeIndex+$NegativeSlopeStartB;
5450
                }
5451
5452
               $Color = array("R"=>$R,"G"=>$G,"B"=>$B);
5453
5454
               if ( $ShadedSlopeBox && $LastColor != NULL )
5455
                {
5456
                 $GradientSettings = array("StartR"=>$LastColor["R"],"StartG"=>$LastColor["G"],"StartB"=>$LastColor["B"],"EndR"=>$R,"EndG"=>$G,"EndB"=>$B);
5457
5458
                 $this->drawGradientArea($TopX,$LastY,$BottomX,$Y,DIRECTION_VERTICAL,$GradientSettings);
5459
                }
5460
               elseif ( !$ShadedSlopeBox || $LastColor == NULL ) 
5461
                $this->drawFilledRectangle($TopX,floor($LastY),$BottomX,floor($Y),$Color);
5462
5463
               $LastColor = $Color;
5464
              }
5465
5466
             if ( $X == VOID )
5467
              { $LastX = NULL; }
5468
             else
5469
              { $LastX = $X; $LastY = $Y; }
5470
5471
             $Y = $Y + $XStep;
5472
            }
5473
5474
           $XPos = $XPos + $CaptionHeight + $SerieSpacing;
5475
          }
5476
5477
         $this->Shadow = $RestoreShadow;
5478
        }
5479
      }
5480
    }
5481
5482
   /* Draw the line of best fit */
5483
   function drawBestFit($Format="")
5484
    {
5485
     $OverrideTicks	= isset($Format["Ticks"]) ? $Format["Ticks"] : NULL;
5486
     $OverrideR		= isset($Format["R"]) ? $Format["R"] : VOID;
5487
     $OverrideG		= isset($Format["G"]) ? $Format["G"] : VOID;
5488
     $OverrideB		= isset($Format["B"]) ? $Format["B"] : VOID;
5489
     $OverrideAlpha	= isset($Format["Alpha"]) ? $Format["Alpha"] : VOID;
5490
5491
     $Data = $this->DataSet->getData();
5492
     list($XMargin,$XDivs) = $this->scaleGetXSettings();
5493
5494
     foreach($Data["Series"] as $SerieName => $Serie)
5495
      {
5496
       if ( $Serie["isDrawable"] == TRUE && $SerieName != $Data["Abscissa"] )
5497
        {
5498
         if ( $OverrideR != VOID && $OverrideG != VOID && $OverrideB != VOID ) { $R = $OverrideR; $G = $OverrideG; $B = $OverrideB; } else { $R = $Serie["Color"]["R"]; $G = $Serie["Color"]["G"]; $B = $Serie["Color"]["B"]; }
5499
         if ( $OverrideTicks == NULL ) { $Ticks = $Serie["Ticks"]; } else { $Ticks = $OverrideTicks; }
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $OverrideTicks of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
5500
         if ( $OverrideAlpha == VOID ) { $Alpha = $Serie["Color"]["Alpha"]; } else { $Alpha = $OverrideAlpha; }
5501
5502
         $Color = array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha,"Ticks"=>$Ticks);
5503
5504
         $AxisID   = $Serie["Axis"];
5505
         $PosArray = $this->scaleComputeY($Serie["Data"],array("AxisID"=>$Serie["Axis"]));
5506
5507
         if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT )
5508
          {
5509
           if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; }
5510
           $X = $this->GraphAreaX1 + $XMargin;
5511
5512
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
5513
           $Sxy = 0; $Sx = 0; $Sy = 0; $Sxx = 0;
5514
           foreach($PosArray as $Key => $Y)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
5515
            {
5516
             if ( $Y != VOID )
5517
              {
5518
               $Sxy = $Sxy + $X*$Y;
5519
               $Sx  = $Sx + $X;
5520
               $Sy  = $Sy + $Y;
5521
               $Sxx = $Sxx + $X*$X;
5522
              }
5523
5524
             $X = $X + $XStep;
5525
            }
5526
           $n = count($this->DataSet->stripVOID($PosArray)); //$n = count($PosArray);
5527
           $M = (($n*$Sxy)-($Sx*$Sy)) / (($n*$Sxx)-($Sx*$Sx));
5528
           $B = (($Sy)-($M*$Sx))/($n);
5529
5530
           $X1 = $this->GraphAreaX1 + $XMargin;
5531
           $Y1 = $M * $X1 + $B;
5532
           $X2 = $this->GraphAreaX2 - $XMargin;
5533
           $Y2 = $M * $X2 + $B;
5534
5535
           if ( $Y1 < $this->GraphAreaY1 ) { $X1 = $X1 + ($this->GraphAreaY1-$Y1); $Y1 = $this->GraphAreaY1; }
5536
           if ( $Y1 > $this->GraphAreaY2 ) { $X1 = $X1 + ($Y1-$this->GraphAreaY2); $Y1 = $this->GraphAreaY2; }
5537
           if ( $Y2 < $this->GraphAreaY1 ) { $X2 = $X2 - ($this->GraphAreaY1-$Y2); $Y2 = $this->GraphAreaY1; }
5538
           if ( $Y2 > $this->GraphAreaY2 ) { $X2 = $X2 - ($Y2-$this->GraphAreaY2); $Y2 = $this->GraphAreaY2; }
5539
5540
           $this->drawLine($X1,$Y1,$X2,$Y2,$Color);
5541
          }
5542
         else
5543
          {
5544
           if ( $XDivs == 0 ) { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $YStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; }
5545
           $Y = $this->GraphAreaY1 + $XMargin;
5546
5547
           if ( !is_array($PosArray) ) { $Value = $PosArray; $PosArray = ""; $PosArray[0] = $Value; }
5548
           $Sxy = 0; $Sx = 0; $Sy = 0; $Sxx = 0;
5549
           foreach($PosArray as $Key => $X)
0 ignored issues
show
Bug introduced by
The expression $PosArray of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
5550
            {
5551
             if ( $X != VOID )
5552
              {
5553
               $Sxy = $Sxy + $X*$Y;
5554
               $Sx  = $Sx + $Y;
5555
               $Sy  = $Sy + $X;
5556
               $Sxx = $Sxx + $Y*$Y;
5557
              }
5558
5559
             $Y = $Y + $YStep;
5560
            }
5561
           $n = count($this->DataSet->stripVOID($PosArray)); //$n = count($PosArray);
5562
           $M = (($n*$Sxy)-($Sx*$Sy)) / (($n*$Sxx)-($Sx*$Sx));
5563
           $B = (($Sy)-($M*$Sx))/($n);
5564
5565
           $Y1 = $this->GraphAreaY1 + $XMargin;
5566
           $X1 = $M * $Y1 + $B;
5567
           $Y2 = $this->GraphAreaY2 - $XMargin;
5568
           $X2 = $M * $Y2 + $B;
5569
5570
           if ( $X1 < $this->GraphAreaX1 ) { $Y1 = $Y1 + ($this->GraphAreaX1-$X1); $X1 = $this->GraphAreaX1; }
5571
           if ( $X1 > $this->GraphAreaX2 ) { $Y1 = $Y1 + ($X1-$this->GraphAreaX2); $X1 = $this->GraphAreaX2; }
5572
           if ( $X2 < $this->GraphAreaX1 ) { $Y2 = $Y2 - ($this->GraphAreaY1-$X2); $X2 = $this->GraphAreaX1; }
5573
           if ( $X2 > $this->GraphAreaX2 ) { $Y2 = $Y2 - ($X2-$this->GraphAreaX2); $X2 = $this->GraphAreaX2; }
5574
5575
           $this->drawLine($X1,$Y1,$X2,$Y2,$Color);
5576
          }
5577
        }
5578
      }
5579
    }
5580
5581
   /* Write labels */
5582
   function writeLabel($SeriesName,$Indexes,$Format="")
5583
    {
5584
     $OverrideTitle	= isset($Format["OverrideTitle"]) ? $Format["OverrideTitle"] : NULL;
5585
     $ForceLabels	= isset($Format["ForceLabels"]) ? $Format["ForceLabels"] : NULL;
5586
     $DrawPoint		= isset($Format["DrawPoint"]) ? $Format["DrawPoint"] : LABEL_POINT_BOX;
5587
     $DrawVerticalLine	= isset($Format["DrawVerticalLine"]) ? $Format["DrawVerticalLine"] : FALSE;
5588
     $VerticalLineR	= isset($Format["VerticalLineR"]) ? $Format["VerticalLineR"] : 0;
5589
     $VerticalLineG	= isset($Format["VerticalLineG"]) ? $Format["VerticalLineG"] : 0;
5590
     $VerticalLineB	= isset($Format["VerticalLineB"]) ? $Format["VerticalLineB"] : 0;
5591
     $VerticalLineAlpha	= isset($Format["VerticalLineAlpha"]) ? $Format["VerticalLineAlpha"] : 40;
5592
     $VerticalLineTicks	= isset($Format["VerticalLineTicks"]) ? $Format["VerticalLineTicks"] : 2;
5593
5594
     $Data = $this->DataSet->getData();
5595
     list($XMargin,$XDivs) = $this->scaleGetXSettings();
5596
5597
     if ( !is_array($Indexes) )    { $Index = $Indexes; $Indexes = ""; $Indexes[] = $Index; }
5598
     if ( !is_array($SeriesName) ) { $SerieName = $SeriesName; $SeriesName = ""; $SeriesName[] = $SerieName; }
5599
     if ( $ForceLabels != NULL && !is_array($ForceLabels) ) { $ForceLabel = $ForceLabels; $ForceLabels = ""; $ForceLabels[] = $ForceLabel; }
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $ForceLabels of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
5600
5601
     foreach ($Indexes as $Key => $Index)
0 ignored issues
show
Bug introduced by
The expression $Indexes of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
5602
      {
5603
       $Series = "";
5604
5605
       if ( $Data["Orientation"] == SCALE_POS_LEFTRIGHT )
5606
        {
5607
         if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1)/4; } else { $XStep = ($this->GraphAreaX2-$this->GraphAreaX1-$XMargin*2)/$XDivs; }
5608
         $X = $this->GraphAreaX1 + $XMargin + $Index * $XStep;
5609
5610
         if ( $DrawVerticalLine ) { $this->drawLine($X,$this->GraphAreaY1+$Data["YMargin"],$X,$this->GraphAreaY2-$Data["YMargin"],array("R"=>$VerticalLineR,"G"=>$VerticalLineG,"B"=>$VerticalLineB,"Alpha"=>$VerticalLineAlpha,"Ticks"=>$VerticalLineTicks)); }
5611
5612
         $MinY = $this->GraphAreaY2;
5613
         foreach ($SeriesName as $iKey => $SerieName)
0 ignored issues
show
Bug introduced by
The expression $SeriesName of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
5614
          {
5615
           if ( isset($Data["Series"][$SerieName]["Data"][$Index]) )
5616
            {
5617
             $AxisID       = $Data["Series"][$SerieName]["Axis"];
5618
             $XAxisMode    = $Data["XAxisDisplay"];
5619
             $XAxisFormat  = $Data["XAxisFormat"];
5620
             $XAxisUnit    = $Data["XAxisUnit"];
5621
             $AxisMode     = $Data["Axis"][$AxisID]["Display"];
5622
             $AxisFormat   = $Data["Axis"][$AxisID]["Format"];
5623
             $AxisUnit     = $Data["Axis"][$AxisID]["Unit"];
5624
5625
             if ( isset($Data["Abscissa"]) && isset($Data["Series"][$Data["Abscissa"]]["Data"][$Index]) )
5626
              $XLabel = $this->scaleFormat($Data["Series"][$Data["Abscissa"]]["Data"][$Index],$XAxisMode,$XAxisFormat,$XAxisUnit);
5627
             else
5628
              $XLabel = "";
5629
5630
             if ( $OverrideTitle != NULL)
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $OverrideTitle of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
5631
              $Description = $OverrideTitle;
5632
             elseif ( count($SeriesName) == 1 )
5633
              {
5634
               $Description = $Data["Series"][$SerieName]["Description"]." - ".$XLabel;
5635
              }
5636
             elseif ( isset($Data["Abscissa"]) && isset($Data["Series"][$Data["Abscissa"]]["Data"][$Index]) )
5637
              $Description = $XLabel;
5638
5639
             $Serie = "";
5640
             $Serie["R"] = $Data["Series"][$SerieName]["Color"]["R"];
5641
             $Serie["G"] = $Data["Series"][$SerieName]["Color"]["G"];
5642
             $Serie["B"] = $Data["Series"][$SerieName]["Color"]["B"];
5643
             $Serie["Alpha"] = $Data["Series"][$SerieName]["Color"]["Alpha"];
5644
5645
             if ( count($SeriesName) == 1 && isset($Data["Series"][$SerieName]["XOffset"]) )
5646
              $SerieOffset = $Data["Series"][$SerieName]["XOffset"];
5647
             else
5648
              $SerieOffset = 0;
5649
5650
             $Value = $Data["Series"][$SerieName]["Data"][$Index];
5651
             if ( $Value == VOID ) { $Value = "NaN"; }
5652
5653
             if ( $ForceLabels != NULL )
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $ForceLabels of type string|null|array against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
5654
              $Caption = isset($ForceLabels[$Key]) ? $ForceLabels[$Key] : "Not set";
5655
             else
5656
              $Caption = $this->scaleFormat($Value,$AxisMode,$AxisFormat,$AxisUnit);
5657
5658
             if ( $this->LastChartLayout == CHART_LAST_LAYOUT_STACKED )
5659
              {
5660
               if ( $Value >=0 ) { $LookFor = "+"; } else { $LookFor = "-"; }
5661
5662
               $Value = 0; $Done = FALSE;
5663
               foreach($Data["Series"] as $Name => $SerieLookup)
5664
                {
5665
                 if ( $SerieLookup["isDrawable"] == TRUE && $Name != $Data["Abscissa"] && !$Done )
5666
                  {
5667
                   if ( isset($Data["Series"][$Name]["Data"][$Index]) && $Data["Series"][$Name]["Data"][$Index] != VOID )
5668
                    {
5669
                     if ($Data["Series"][$Name]["Data"][$Index] >= 0 && $LookFor == "+" ) { $Value = $Value + $Data["Series"][$Name]["Data"][$Index]; }
5670
                     if ($Data["Series"][$Name]["Data"][$Index] < 0 && $LookFor == "-" )  { $Value = $Value - $Data["Series"][$Name]["Data"][$Index]; }
5671
                     if ($Name == $SerieName ) { $Done = TRUE; }
5672
                    }
5673
                  }
5674
                }
5675
              }
5676
5677
             $X = floor($this->GraphAreaX1 + $XMargin + $Index * $XStep + $SerieOffset);
5678
             $Y = floor($this->scaleComputeY($Value,array("AxisID"=>$AxisID)));
5679
5680
             if ($Y < $MinY) { $MinY = $Y; }
5681
5682
             if ( $DrawPoint == LABEL_POINT_CIRCLE )
5683
              $this->drawFilledCircle($X,$Y,3,array("R"=>255,"G"=>255,"B"=>255,"BorderR"=>0,"BorderG"=>0,"BorderB"=>0));
5684
             elseif ( $DrawPoint == LABEL_POINT_BOX )
5685
              $this->drawFilledRectangle($X-2,$Y-2,$X+2,$Y+2,array("R"=>255,"G"=>255,"B"=>255,"BorderR"=>0,"BorderG"=>0,"BorderB"=>0));
5686
5687
             $Series[] = array("Format"=>$Serie,"Caption"=>$Caption);
5688
            }
5689
          }
5690
         $this->drawLabelBox($X,$MinY-3,$Description,$Series,$Format);
5691
5692
        }
5693
       else
5694
        {
5695
         if ( $XDivs == 0 ) { $XStep = ($this->GraphAreaY2-$this->GraphAreaY1)/4; } else { $XStep = ($this->GraphAreaY2-$this->GraphAreaY1-$XMargin*2)/$XDivs; }
5696
         $Y = $this->GraphAreaY1 + $XMargin + $Index * $XStep;
5697
5698
         if ( $DrawVerticalLine ) { $this->drawLine($this->GraphAreaX1+$Data["YMargin"],$Y,$this->GraphAreaX2-$Data["YMargin"],$Y,array("R"=>$VerticalLineR,"G"=>$VerticalLineG,"B"=>$VerticalLineB,"Alpha"=>$VerticalLineAlpha,"Ticks"=>$VerticalLineTicks)); }
5699
5700
         $MinX = $this->GraphAreaX2;
5701
         foreach ($SeriesName as $Key => $SerieName)
0 ignored issues
show
Bug introduced by
The expression $SeriesName of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
5702
          {
5703
           if ( isset($Data["Series"][$SerieName]["Data"][$Index]) )
5704
            {
5705
             $AxisID      = $Data["Series"][$SerieName]["Axis"];
5706
             $XAxisMode   = $Data["XAxisDisplay"];
5707
             $XAxisFormat = $Data["XAxisFormat"];
5708
             $XAxisUnit   = $Data["XAxisUnit"];
5709
             $AxisMode    = $Data["Axis"][$AxisID]["Display"];
5710
             $AxisFormat  = $Data["Axis"][$AxisID]["Format"];
5711
             $AxisUnit    = $Data["Axis"][$AxisID]["Unit"];
5712
5713
             if ( isset($Data["Abscissa"]) && isset($Data["Series"][$Data["Abscissa"]]["Data"][$Index]) )
5714
              $XLabel = $this->scaleFormat($Data["Series"][$Data["Abscissa"]]["Data"][$Index],$XAxisMode,$XAxisFormat,$XAxisUnit);
5715
             else
5716
              $XLabel = "";
5717
5718
             if ( $OverrideTitle != NULL)
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $OverrideTitle of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
5719
              $Description = $OverrideTitle;
5720
             elseif ( count($SeriesName) == 1 )
5721
              {
5722
               if ( isset($Data["Abscissa"]) && isset($Data["Series"][$Data["Abscissa"]]["Data"][$Index]) )
5723
                $Description = $Data["Series"][$SerieName]["Description"]." - ".$XLabel;
5724
              }
5725
             elseif ( isset($Data["Abscissa"]) && isset($Data["Series"][$Data["Abscissa"]]["Data"][$Index]) )
5726
              $Description = $XLabel;
5727
5728
             $Serie = "";
5729
             if ( isset($Data["Extended"]["Palette"][$Index] ) )
5730
              {
5731
               $Serie["R"] = $Data["Extended"]["Palette"][$Index]["R"];
5732
               $Serie["G"] = $Data["Extended"]["Palette"][$Index]["G"];
5733
               $Serie["B"] = $Data["Extended"]["Palette"][$Index]["B"];
5734
               $Serie["Alpha"] = $Data["Extended"]["Palette"][$Index]["Alpha"];
5735
              }
5736
             else
5737
              {
5738
               $Serie["R"] = $Data["Series"][$SerieName]["Color"]["R"];
5739
               $Serie["G"] = $Data["Series"][$SerieName]["Color"]["G"];
5740
               $Serie["B"] = $Data["Series"][$SerieName]["Color"]["B"];
5741
               $Serie["Alpha"] = $Data["Series"][$SerieName]["Color"]["Alpha"];
5742
              }
5743
5744
             if ( count($SeriesName) == 1 && isset($Data["Series"][$SerieName]["XOffset"]) )
5745
              $SerieOffset = $Data["Series"][$SerieName]["XOffset"];
5746
             else
5747
              $SerieOffset = 0;
5748
5749
             $Value = $Data["Series"][$SerieName]["Data"][$Index];
5750
             if ( $ForceLabels != NULL )
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $ForceLabels of type string|null|array against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
5751
              $Caption = isset($ForceLabels[$Key]) ? $ForceLabels[$Key] : "Not set";
5752
             else
5753
              $Caption = $this->scaleFormat($Value,$AxisMode,$AxisFormat,$AxisUnit);
5754
             if ( $Value == VOID ) { $Value = "NaN"; }
5755
5756
             if ( $this->LastChartLayout == CHART_LAST_LAYOUT_STACKED )
5757
              {
5758
               if ( $Value >=0 ) { $LookFor = "+"; } else { $LookFor = "-"; }
5759
5760
               $Value = 0; $Done = FALSE;
5761
               foreach($Data["Series"] as $Name => $SerieLookup)
5762
                {
5763
                 if ( $SerieLookup["isDrawable"] == TRUE && $Name != $Data["Abscissa"] && !$Done )
5764
                  {
5765
                   if ( isset($Data["Series"][$Name]["Data"][$Index]) && $Data["Series"][$Name]["Data"][$Index] != VOID )
5766
                    {
5767
                     if ($Data["Series"][$Name]["Data"][$Index] >= 0 && $LookFor == "+" ) { $Value = $Value + $Data["Series"][$Name]["Data"][$Index]; }
5768
                     if ($Data["Series"][$Name]["Data"][$Index] < 0 && $LookFor == "-" )  { $Value = $Value - $Data["Series"][$Name]["Data"][$Index]; }
5769
                     if ($Name == $SerieName ) { $Done = TRUE; }
5770
                    }
5771
                  }
5772
                }
5773
              }
5774
5775
             $X = floor($this->scaleComputeY($Value,array("AxisID"=>$AxisID)));
5776
             $Y = floor($this->GraphAreaY1 + $XMargin + $Index * $XStep + $SerieOffset);
5777
5778
             if ($X < $MinX) { $MinX = $X; }
5779
5780
             if ( $DrawPoint == LABEL_POINT_CIRCLE )
5781
              $this->drawFilledCircle($X,$Y,3,array("R"=>255,"G"=>255,"B"=>255,"BorderR"=>0,"BorderG"=>0,"BorderB"=>0));
5782
             elseif ( $DrawPoint == LABEL_POINT_BOX )
5783
              $this->drawFilledRectangle($X-2,$Y-2,$X+2,$Y+2,array("R"=>255,"G"=>255,"B"=>255,"BorderR"=>0,"BorderG"=>0,"BorderB"=>0));
5784
5785
             $Series[] = array("Format"=>$Serie,"Caption"=>$Caption);
5786
            }
5787
          }
5788
         $this->drawLabelBox($MinX,$Y-3,$Description,$Series,$Format);
5789
5790
        }
5791
      }
5792
    }
5793
5794
   /* Draw a label box */
5795
   function drawLabelBox($X,$Y,$Title,$Captions,$Format="")
5796
    {
5797
     $NoTitle			= isset($Format["NoTitle"]) ? $Format["NoTitle"] : NULL;
5798
     $BoxWidth			= isset($Format["BoxWidth"]) ? $Format["BoxWidth"] : 50;
5799
     $DrawSerieColor		= isset($Format["DrawSerieColor"]) ? $Format["DrawSerieColor"] : TRUE;
5800
     $SerieR			= isset($Format["SerieR"]) ? $Format["SerieR"] : NULL;
5801
     $SerieG			= isset($Format["SerieG"]) ? $Format["SerieG"] : NULL;
5802
     $SerieB			= isset($Format["SerieB"]) ? $Format["SerieB"] : NULL;
5803
     $SerieAlpha		= isset($Format["SerieAlpha"]) ? $Format["SerieAlpha"] : NULL;
5804
     $SerieBoxSize		= isset($Format["SerieBoxSize"]) ? $Format["SerieBoxSize"] : 6;
5805
     $SerieBoxSpacing		= isset($Format["SerieBoxSpacing"]) ? $Format["SerieBoxSpacing"] : 4;
5806
     $VerticalMargin		= isset($Format["VerticalMargin"]) ? $Format["VerticalMargin"] : 10;
5807
     $HorizontalMargin		= isset($Format["HorizontalMargin"]) ? $Format["HorizontalMargin"] : 8;
5808
     $R				= isset($Format["R"]) ? $Format["R"] : $this->FontColorR;
5809
     $G				= isset($Format["G"]) ? $Format["G"] : $this->FontColorG;
5810
     $B				= isset($Format["B"]) ? $Format["B"] : $this->FontColorB;
5811
     $Alpha			= isset($Format["Alpha"]) ? $Format["Alpha"] : $this->FontColorA;
5812
     $FontName			= isset($Format["FontName"]) ? $Format["FontName"] : $this->FontName;
5813
     $FontSize			= isset($Format["FontSize"]) ? $Format["FontSize"] : $this->FontSize;
5814
     $TitleMode			= isset($Format["TitleMode"]) ? $Format["TitleMode"] : LABEL_TITLE_NOBACKGROUND;
5815
     $TitleR			= isset($Format["TitleR"]) ? $Format["TitleR"] : $R;
5816
     $TitleG			= isset($Format["TitleG"]) ? $Format["TitleG"] : $G;
5817
     $TitleB			= isset($Format["TitleB"]) ? $Format["TitleB"] : $B;
5818
     $TitleAlpha		= isset($Format["TitleAlpha"]) ? $Format["TitleAlpha"] : 100;
5819
     $TitleBackgroundR		= isset($Format["TitleBackgroundR"]) ? $Format["TitleBackgroundR"] : 0;
5820
     $TitleBackgroundG		= isset($Format["TitleBackgroundG"]) ? $Format["TitleBackgroundG"] : 0;
5821
     $TitleBackgroundB		= isset($Format["TitleBackgroundB"]) ? $Format["TitleBackgroundB"] : 0;
5822
     $TitleBackgroundAlpha	= isset($Format["TitleBackgroundAlpha"]) ? $Format["TitleBackgroundAlpha"] : 100;
5823
     $GradientStartR		= isset($Format["GradientStartR"]) ? $Format["GradientStartR"] : 255;
5824
     $GradientStartG		= isset($Format["GradientStartG"]) ? $Format["GradientStartG"] : 255;
5825
     $GradientStartB		= isset($Format["GradientStartB"]) ? $Format["GradientStartB"] : 255;
5826
     $GradientEndR		= isset($Format["GradientEndR"]) ? $Format["GradientEndR"] : 220;
5827
     $GradientEndG		= isset($Format["GradientEndG"]) ? $Format["GradientEndG"] : 220;
5828
     $GradientEndB		= isset($Format["GradientEndB"]) ? $Format["GradientEndB"] : 220;
5829
     $BoxAlpha			= isset($Format["BoxAlpha"]) ? $Format["BoxAlpha"] : 100;
5830
5831
     if ( !$DrawSerieColor ) { $SerieBoxSize = 0; $SerieBoxSpacing = 0; }
5832
5833
     $TxtPos      = $this->getTextBox($X,$Y,$FontName,$FontSize,0,$Title);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getTextBox() does only exist in the following sub-classes of pDraw: pImage. 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...
5834
     $TitleWidth  = ($TxtPos[1]["X"] - $TxtPos[0]["X"])+$VerticalMargin*2;
5835
     $TitleHeight = ($TxtPos[0]["Y"] - $TxtPos[2]["Y"]);
5836
5837
     if ( $NoTitle ) { $TitleWidth = 0; $TitleHeight = 0; }
5838
5839
     $CaptionWidth = 0; $CaptionHeight = -$HorizontalMargin;
5840
     foreach($Captions as $Key =>$Caption)
5841
      {
5842
       $TxtPos        = $this->getTextBox($X,$Y,$FontName,$FontSize,0,$Caption["Caption"]);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getTextBox() does only exist in the following sub-classes of pDraw: pImage. 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...
5843
       $CaptionWidth  = max($CaptionWidth,($TxtPos[1]["X"] - $TxtPos[0]["X"])+$VerticalMargin*2);
5844
       $CaptionHeight = $CaptionHeight + max(($TxtPos[0]["Y"] - $TxtPos[2]["Y"]),($SerieBoxSize+2)) + $HorizontalMargin;
5845
      }
5846
5847
     if ( $CaptionHeight <= 5 ) { $CaptionHeight = $CaptionHeight + $HorizontalMargin/2; }
5848
5849
     if ( $DrawSerieColor ) { $CaptionWidth = $CaptionWidth + $SerieBoxSize + $SerieBoxSpacing; }
5850
5851
     $BoxWidth = max($BoxWidth,$TitleWidth,$CaptionWidth);
5852
5853
     $XMin = $X - 5 - floor(($BoxWidth-10) / 2);
5854
     $XMax = $X + 5 + floor(($BoxWidth-10) / 2);
5855
5856
     $RestoreShadow = $this->Shadow;
5857
     if ( $this->Shadow == TRUE )
5858
      {
5859
       $this->Shadow = FALSE;
5860
5861
       $Poly = "";
5862
       $Poly[] = $X+$this->ShadowX; $Poly[] = $Y+$this->ShadowX;
5863
       $Poly[] = $X+5+$this->ShadowX; $Poly[] = $Y-5+$this->ShadowX;
5864
       $Poly[] = $XMax+$this->ShadowX; $Poly[] = $Y-5+$this->ShadowX;
5865
5866
       if ( $NoTitle )
5867
        {
5868
         $Poly[] = $XMax+$this->ShadowX; $Poly[] = $Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*2+$this->ShadowX;
5869
         $Poly[] = $XMin+$this->ShadowX; $Poly[] = $Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*2+$this->ShadowX;
5870
        }
5871
       else
5872
        {
5873
         $Poly[] = $XMax+$this->ShadowX; $Poly[] = $Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3+$this->ShadowX;
5874
         $Poly[] = $XMin+$this->ShadowX; $Poly[] = $Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3+$this->ShadowX;
5875
        }
5876
5877
       $Poly[] = $XMin+$this->ShadowX; $Poly[] = $Y-5+$this->ShadowX;
5878
       $Poly[] = $X-5+$this->ShadowX; $Poly[] = $Y-5+$this->ShadowX;
5879
       $this->drawPolygon($Poly,array("R"=>$this->ShadowR,"G"=>$this->ShadowG,"B"=>$this->ShadowB,"Alpha"=>$this->Shadowa));
5880
      }
5881
5882
     /* Draw the background */
5883
     $GradientSettings = array("StartR"=>$GradientStartR,"StartG"=>$GradientStartG,"StartB"=>$GradientStartB,"EndR"=>$GradientEndR,"EndG"=>$GradientEndG,"EndB"=>$GradientEndB,"Alpha"=>$BoxAlpha);
5884
     if ( $NoTitle )
5885
      $this->drawGradientArea($XMin,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$XMax,$Y-6,DIRECTION_VERTICAL,$GradientSettings);
5886
     else
5887
      $this->drawGradientArea($XMin,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMax,$Y-6,DIRECTION_VERTICAL,$GradientSettings);
5888
     $Poly = ""; $Poly[] = $X; $Poly[] = $Y; $Poly[] = $X-5; $Poly[] = $Y-5; $Poly[] = $X+5; $Poly[] = $Y-5;
5889
     $this->drawPolygon($Poly,array("R"=>$GradientEndR,"G"=>$GradientEndG,"B"=>$GradientEndB,"Alpha"=>$BoxAlpha,"NoBorder"=>TRUE));
5890
5891
     /* Outer border */
5892
     $OuterBorderColor = $this->allocateColor($this->Picture,100,100,100,$BoxAlpha);
5893
     imageline($this->Picture,$XMin,$Y-5,$X-5,$Y-5,$OuterBorderColor);
5894
     imageline($this->Picture,$X,$Y,$X-5,$Y-5,$OuterBorderColor);
5895
     imageline($this->Picture,$X,$Y,$X+5,$Y-5,$OuterBorderColor);
5896
     imageline($this->Picture,$X+5,$Y-5,$XMax,$Y-5,$OuterBorderColor);
5897
     if ( $NoTitle )
5898
      {
5899
       imageline($this->Picture,$XMin,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$XMin,$Y-5,$OuterBorderColor);
5900
       imageline($this->Picture,$XMax,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$XMax,$Y-5,$OuterBorderColor);
5901
       imageline($this->Picture,$XMin,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$XMax,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$OuterBorderColor);
5902
      }
5903
     else
5904
      {
5905
       imageline($this->Picture,$XMin,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMin,$Y-5,$OuterBorderColor);
5906
       imageline($this->Picture,$XMax,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMax,$Y-5,$OuterBorderColor);
5907
       imageline($this->Picture,$XMin,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMax,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$OuterBorderColor);
5908
      }
5909
5910
     /* Inner border */
5911
     $InnerBorderColor = $this->allocateColor($this->Picture,255,255,255,$BoxAlpha);
5912
     imageline($this->Picture,$XMin+1,$Y-6,$X-5,$Y-6,$InnerBorderColor);
5913
     imageline($this->Picture,$X,$Y-1,$X-5,$Y-6,$InnerBorderColor);
5914
     imageline($this->Picture,$X,$Y-1,$X+5,$Y-6,$InnerBorderColor);
5915
     imageline($this->Picture,$X+5,$Y-6,$XMax-1,$Y-6,$InnerBorderColor);
5916
     if ( $NoTitle )
5917
      {
5918
       imageline($this->Picture,$XMin+1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$XMin+1,$Y-6,$InnerBorderColor);
5919
       imageline($this->Picture,$XMax-1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$XMax-1,$Y-6,$InnerBorderColor);
5920
       imageline($this->Picture,$XMin+1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$XMax-1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*2,$InnerBorderColor);
5921
      }
5922
     else
5923
      {
5924
       imageline($this->Picture,$XMin+1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMin+1,$Y-6,$InnerBorderColor);
5925
       imageline($this->Picture,$XMax-1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMax-1,$Y-6,$InnerBorderColor);
5926
       imageline($this->Picture,$XMin+1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMax-1,$Y-4-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$InnerBorderColor);
5927
      }
5928
5929
     /* Draw the separator line */
5930
     if ( $TitleMode == LABEL_TITLE_NOBACKGROUND && !$NoTitle )
5931
      {
5932
       $YPos    = $Y-7-$CaptionHeight-$HorizontalMargin-$HorizontalMargin/2;
5933
       $XMargin = $VerticalMargin / 2;
5934
       $this->drawLine($XMin+$XMargin,$YPos+1,$XMax-$XMargin,$YPos+1,array("R"=>$GradientEndR,"G"=>$GradientEndG,"B"=>$GradientEndB,"Alpha"=>$BoxAlpha));
5935
       $this->drawLine($XMin+$XMargin,$YPos,$XMax-$XMargin,$YPos,array("R"=>$GradientStartR,"G"=>$GradientStartG,"B"=>$GradientStartB,"Alpha"=>$BoxAlpha));
5936
      }
5937
     elseif ( $TitleMode == LABEL_TITLE_BACKGROUND )
5938
      {
5939
       $this->drawFilledRectangle($XMin,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin*3,$XMax,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin+$HorizontalMargin/2,array("R"=>$TitleBackgroundR,"G"=>$TitleBackgroundG,"B"=>$TitleBackgroundB,"Alpha"=>$BoxAlpha));
5940
       imageline($this->Picture,$XMin+1,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin+$HorizontalMargin/2+1,$XMax-1,$Y-5-$TitleHeight-$CaptionHeight-$HorizontalMargin+$HorizontalMargin/2+1,$InnerBorderColor);
5941
      }
5942
5943
     /* Write the description */
5944
     if ( !$NoTitle )
5945
      $this->drawText($XMin+$VerticalMargin,$Y-7-$CaptionHeight-$HorizontalMargin*2,$Title,array("Align"=>TEXT_ALIGN_BOTTOMLEFT,"R"=>$TitleR,"G"=>$TitleG,"B"=>$TitleB));
5946
5947
     /* Write the value */
5948
     $YPos = $Y-5-$HorizontalMargin; $XPos = $XMin+$VerticalMargin+$SerieBoxSize+$SerieBoxSpacing;
5949
     foreach($Captions as $Key => $Caption)
5950
      {
5951
       $CaptionTxt    = $Caption["Caption"];
5952
       $TxtPos        = $this->getTextBox($XPos,$YPos,$FontName,$FontSize,0,$CaptionTxt);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getTextBox() does only exist in the following sub-classes of pDraw: pImage. 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...
5953
       $CaptionHeight = ($TxtPos[0]["Y"] - $TxtPos[2]["Y"]);
5954
5955
       /* Write the serie color if needed */
5956
       if ( $DrawSerieColor )
5957
        {
5958
         $BoxSettings = array("R"=>$Caption["Format"]["R"],"G"=>$Caption["Format"]["G"],"B"=>$Caption["Format"]["B"],"Alpha"=>$Caption["Format"]["Alpha"],"BorderR"=>0,"BorderG"=>0,"BorderB"=>0);
5959
         $this->drawFilledRectangle($XMin+$VerticalMargin,$YPos-$SerieBoxSize,$XMin+$VerticalMargin+$SerieBoxSize,$YPos,$BoxSettings);
5960
        }
5961
5962
       $this->drawText($XPos,$YPos,$CaptionTxt,array("Align"=>TEXT_ALIGN_BOTTOMLEFT));
5963
5964
       $YPos = $YPos - $CaptionHeight - $HorizontalMargin;
5965
      }
5966
5967
     $this->Shadow = $RestoreShadow;
5968
    }
5969
5970
   /* Draw a basic shape */
5971
   function drawShape($X,$Y,$Shape,$PlotSize,$PlotBorder,$BorderSize,$R,$G,$B,$Alpha,$BorderR,$BorderG,$BorderB,$BorderAlpha)
5972
    {
5973
     if ( $Shape == SERIE_SHAPE_FILLEDCIRCLE )
5974
      {
5975
       if ( $PlotBorder ) { $this->drawFilledCircle($X,$Y,$PlotSize+$BorderSize,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha)); }
5976
       $this->drawFilledCircle($X,$Y,$PlotSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
5977
      }
5978
     elseif ( $Shape == SERIE_SHAPE_FILLEDSQUARE )
5979
      {
5980
       if ( $PlotBorder ) { $this->drawFilledRectangle($X-$PlotSize-$BorderSize,$Y-$PlotSize-$BorderSize,$X+$PlotSize+$BorderSize,$Y+$PlotSize+$BorderSize,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha)); }
5981
       $this->drawFilledRectangle($X-$PlotSize,$Y-$PlotSize,$X+$PlotSize,$Y+$PlotSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
5982
      }
5983
     elseif ( $Shape == SERIE_SHAPE_FILLEDTRIANGLE )
5984
      {
5985
       if ( $PlotBorder )
5986
        {
5987
         $Pos = ""; $Pos[]=$X; $Pos[]=$Y-$PlotSize-$BorderSize; $Pos[]=$X-$PlotSize-$BorderSize; $Pos[]=$Y+$PlotSize+$BorderSize; $Pos[]=$X+$PlotSize+$BorderSize; $Pos[]=$Y+$PlotSize+$BorderSize;
5988
         $this->drawPolygon($Pos,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha));
5989
        }
5990
5991
       $Pos = ""; $Pos[]=$X; $Pos[]=$Y-$PlotSize; $Pos[]=$X-$PlotSize; $Pos[]=$Y+$PlotSize; $Pos[]=$X+$PlotSize; $Pos[]=$Y+$PlotSize;
5992
       $this->drawPolygon($Pos,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
5993
      }
5994
     elseif ( $Shape == SERIE_SHAPE_TRIANGLE )
5995
      {
5996
       $this->drawLine($X,$Y-$PlotSize,$X-$PlotSize,$Y+$PlotSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
5997
       $this->drawLine($X-$PlotSize,$Y+$PlotSize,$X+$PlotSize,$Y+$PlotSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
5998
       $this->drawLine($X+$PlotSize,$Y+$PlotSize,$X,$Y-$PlotSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
5999
      }
6000
     elseif ( $Shape == SERIE_SHAPE_SQUARE )
6001
      $this->drawRectangle($X-$PlotSize,$Y-$PlotSize,$X+$PlotSize,$Y+$PlotSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
6002
     elseif ( $Shape == SERIE_SHAPE_CIRCLE )
6003
      $this->drawCircle($X,$Y,$PlotSize,$PlotSize,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
6004
     elseif ( $Shape == SERIE_SHAPE_DIAMOND )
6005
      {
6006
       $Pos = ""; $Pos[]=$X-$PlotSize; $Pos[]=$Y; $Pos[]=$X; $Pos[]=$Y-$PlotSize; $Pos[]=$X+$PlotSize; $Pos[]=$Y; $Pos[]=$X; $Pos[]=$Y+$PlotSize;
6007
       $this->drawPolygon($Pos,array("NoFill"=>TRUE,"BorderR"=>$R,"BorderG"=>$G,"BorderB"=>$B,"BorderAlpha"=>$Alpha));
6008
      }      
6009
     elseif ( $Shape == SERIE_SHAPE_FILLEDDIAMOND )
6010
      {
6011
       if ( $PlotBorder )
6012
        {
6013
         $Pos = ""; $Pos[]=$X-$PlotSize-$BorderSize; $Pos[]=$Y; $Pos[]=$X; $Pos[]=$Y-$PlotSize-$BorderSize; $Pos[]=$X+$PlotSize+$BorderSize; $Pos[]=$Y; $Pos[]=$X; $Pos[]=$Y+$PlotSize+$BorderSize;
6014
         $this->drawPolygon($Pos,array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha));
6015
        }
6016
6017
       $Pos = ""; $Pos[]=$X-$PlotSize; $Pos[]=$Y; $Pos[]=$X; $Pos[]=$Y-$PlotSize; $Pos[]=$X+$PlotSize; $Pos[]=$Y; $Pos[]=$X; $Pos[]=$Y+$PlotSize;
6018
       $this->drawPolygon($Pos,array("R"=>$R,"G"=>$G,"B"=>$B,"Alpha"=>$Alpha));
6019
      }      
6020
    }
6021
6022
   function drawPolygonChart($Points,$Format="")
6023
    {
6024
     $R			= isset($Format["R"]) ? $Format["R"] : 0;
6025
     $G			= isset($Format["G"]) ? $Format["G"] : 0;
6026
     $B			= isset($Format["B"]) ? $Format["B"] : 0;
6027
     $Alpha		= isset($Format["Alpha"]) ? $Format["Alpha"] : 100;
6028
     $NoFill		= isset($Format["NoFill"]) ? $Format["NoFill"] : FALSE;
6029
     $NoBorder		= isset($Format["NoBorder"]) ? $Format["NoBorder"] : FALSE;
6030
     $BorderR		= isset($Format["BorderR"]) ? $Format["BorderR"] : $R;
6031
     $BorderG		= isset($Format["BorderG"]) ? $Format["BorderG"] : $G;
6032
     $BorderB		= isset($Format["BorderB"]) ? $Format["BorderB"] : $B;
6033
     $BorderAlpha 	= isset($Format["BorderAlpha"]) ? $Format["BorderAlpha"] : $Alpha / 2;
6034
     $Surrounding	= isset($Format["Surrounding"]) ? $Format["Surrounding"] : NULL;
6035
     $Threshold         = isset($Format["Threshold"]) ? $Format["Threshold"] : NULL;
6036
6037
     if ( $Surrounding != NULL ) { $BorderR = $R+$Surrounding; $BorderG = $G+$Surrounding; $BorderB = $B+$Surrounding; }
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $Surrounding of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
6038
6039
     $RestoreShadow = $this->Shadow;
6040
     $this->Shadow = FALSE;
6041
6042
     $AllIntegers = TRUE;
6043
     for($i=0;$i<=count($Points)-2;$i=$i+2)
6044
      { if ( $this->getFirstDecimal($Points[$i+1]) != 0 ) { $AllIntegers = FALSE; } }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getFirstDecimal() does only exist in the following sub-classes of pDraw: pImage. 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...
6045
6046
     /* Convert polygon to segments */
6047
     $Segments = "";
6048
     for($i=2;$i<=count($Points)-2;$i=$i+2)
6049
      { $Segments[] = array("X1"=>$Points[$i-2],"Y1"=>$Points[$i-1],"X2"=>$Points[$i],"Y2"=>$Points[$i+1]); }
6050
     $Segments[] = array("X1"=>$Points[$i-2],"Y1"=>$Points[$i-1],"X2"=>$Points[0],"Y2"=>$Points[1]);
6051
6052
     /* Simplify straight lines */
6053
     $Result = ""; $inHorizon = FALSE; $LastX = VOID;
6054
     foreach($Segments as $Key => $Pos)
0 ignored issues
show
Bug introduced by
The expression $Segments of type string is not traversable.
Loading history...
6055
      {
6056
       if ( $Pos["Y1"] != $Pos["Y2"] )
6057
        {
6058
         if ( $inHorizon ) { $inHorizon = FALSE; $Result[] = array("X1"=>$LastX,"Y1"=>$Pos["Y1"],"X2"=>$Pos["X1"],"Y2"=>$Pos["Y1"]); }
6059
6060
         $Result[] = array("X1"=>$Pos["X1"],"Y1"=>$Pos["Y1"],"X2"=>$Pos["X2"],"Y2"=>$Pos["Y2"]);
6061
        }
6062
       else { if ( !$inHorizon ) { $inHorizon = TRUE; $LastX = $Pos["X1"];} }
6063
      }
6064
     $Segments = $Result;
6065
6066
     /* Do we have something to draw */
6067
     if ( $Segments == "" ) { return(0); }
6068
6069
     /* For segments debugging purpose */
6070
     //foreach($Segments as $Key => $Pos)
6071
     // echo $Pos["X1"].",".$Pos["Y1"].",".$Pos["X2"].",".$Pos["Y2"]."\r\n";
6072
6073
     /* Find out the min & max Y boundaries */
6074
     $MinY = OUT_OF_SIGHT; $MaxY = OUT_OF_SIGHT;
6075
     foreach($Segments as $Key => $Coords)
0 ignored issues
show
Bug introduced by
The expression $Segments of type string is not traversable.
Loading history...
6076
      {
6077
       if ( $MinY == OUT_OF_SIGHT || $MinY > min($Coords["Y1"],$Coords["Y2"]) ) { $MinY = min($Coords["Y1"],$Coords["Y2"]); }
6078
       if ( $MaxY == OUT_OF_SIGHT || $MaxY < max($Coords["Y1"],$Coords["Y2"]) ) { $MaxY = max($Coords["Y1"],$Coords["Y2"]); }
6079
      }
6080
6081
     if ( $AllIntegers ) { $YStep = 1; } else { $YStep = .5; }
6082
6083
     $MinY = floor($MinY); $MaxY = floor($MaxY);
6084
6085
     /* Scan each Y lines */
6086
     $DefaultColor = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha);
6087
     $DebugLine = 0; $DebugColor = $this->allocateColor($this->Picture,255,0,0,100);
6088
6089
     $MinY = floor($MinY); $MaxY = floor($MaxY); $YStep = 1; 
6090
6091
     if ( !$NoFill )
6092
      {
6093
       //if ( $DebugLine ) { $MinY = $DebugLine; $MaxY = $DebugLine; }
6094
       for($Y=$MinY;$Y<=$MaxY;$Y=$Y+$YStep)
6095
        {
6096
         $Intersections = ""; $LastSlope = NULL; $RestoreLast = "-";
6097
         foreach($Segments as $Key => $Coords)
0 ignored issues
show
Bug introduced by
The expression $Segments of type string is not traversable.
Loading history...
6098
          {
6099
           $X1 = $Coords["X1"]; $X2 = $Coords["X2"]; $Y1 = $Coords["Y1"]; $Y2 = $Coords["Y2"];
6100
6101
           if ( min($Y1,$Y2) <= $Y && max($Y1,$Y2) >= $Y )
6102
            {
6103
             if ( $Y1 == $Y2 )
6104
              { $X = $X1; }
6105
             else
6106
              { $X = $X1 + ( ($Y-$Y1)*$X2 - ($Y-$Y1)*$X1 ) / ($Y2-$Y1); }
6107
6108
             $X = floor($X);
6109
6110
             if ( $X2 == $X1 )
6111
              { $Slope = "!"; }
6112
             else
6113
              {
6114
               $SlopeC = ($Y2 - $Y1) / ($X2 - $X1);
6115
               if( $SlopeC == 0 )
6116
                { $Slope = "="; }
6117
               elseif( $SlopeC > 0 )
6118
                { $Slope = "+"; }
6119
               elseif ( $SlopeC < 0 )
6120
                { $Slope = "-"; }
6121
              }
6122
6123
             if ( !is_array($Intersections) )
6124
              { $Intersections[] = $X; }
6125
             elseif( !in_array($X,$Intersections) )
6126
              { $Intersections[] = $X; }
6127
             elseif( in_array($X,$Intersections) )
6128
              {
6129
               if ($Y == $DebugLine) { echo $Slope."/".$LastSlope."(".$X.") "; }
6130
6131
               if ( $Slope == "=" && $LastSlope == "-"  )                             { $Intersections[] = $X; }
6132
               if ( $Slope != $LastSlope && $LastSlope != "!" && $LastSlope != "=" )  { $Intersections[] = $X; }
6133
               if ( $Slope != $LastSlope && $LastSlope == "!" && $Slope == "+" )      { $Intersections[] = $X; }
6134
              }
6135
6136
             if ( is_array($Intersections) && in_array($X,$Intersections) && $LastSlope == "=" && ($Slope == "-" )) { $Intersections[] = $X; }
6137
6138
             $LastSlope = $Slope;
6139
            }
6140
          }
6141
         if ( $RestoreLast != "-" ) { $Intersections[] = $RestoreLast; echo "@".$Y."\r\n"; }
6142
6143
         if ( is_array($Intersections) )
6144
          {
6145
           sort($Intersections);
6146
6147
           if ($Y == $DebugLine) { print_r($Intersections); }
6148
6149
           /* Remove NULL plots */
6150
           $Result = "";
6151
           for($i=0;$i<=count($Intersections)-1;$i=$i+2)
6152
            {
6153
             if ( isset($Intersections[$i+1]) )
6154
              { if ( $Intersections[$i] != $Intersections[$i+1] ) { $Result[] = $Intersections[$i]; $Result[] = $Intersections[$i+1]; } }
6155
            }
6156
6157
           if ( is_array($Result) )
6158
            {
6159
             $Intersections = $Result;
6160
6161
             $LastX = OUT_OF_SIGHT;
6162
             foreach($Intersections as $Key => $X)
6163
              {
6164
               if ( $LastX == OUT_OF_SIGHT )
6165
                $LastX = $X;
6166
               elseif ( $LastX != OUT_OF_SIGHT )
6167
                {
6168
                 if ( $this->getFirstDecimal($LastX) > 1 ) { $LastX++; }
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class pDraw as the method getFirstDecimal() does only exist in the following sub-classes of pDraw: pImage. 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...
6169
6170
                 $Color = $DefaultColor;
6171
                 if ( $Threshold != NULL )
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $Threshold of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
6172
                  {
6173
                   foreach($Threshold as $Key => $Parameters)
0 ignored issues
show
Bug introduced by
The expression $Threshold of type string is not traversable.
Loading history...
6174
                    {
6175
                     if ( $Y <= $Parameters["MinX"] && $Y >= $Parameters["MaxX"])
6176
                      {
6177
                       if ( isset($Parameters["R"]) ) { $R = $Parameters["R"]; } else { $R = 0; }
6178
                       if ( isset($Parameters["G"]) ) { $G = $Parameters["G"]; } else { $G = 0; }
6179
                       if ( isset($Parameters["B"]) ) { $B = $Parameters["B"]; } else { $B = 0; }
6180
                       if ( isset($Parameters["Alpha"]) ) { $Alpha = $Parameters["Alpha"]; } else { $Alpha = 100; }
6181
                       $Color = $this->allocateColor($this->Picture,$R,$G,$B,$Alpha);
6182
                      }
6183
                    }
6184
                  }
6185
6186
                 imageline($this->Picture,$LastX,$Y,$X,$Y,$Color);
6187
6188
                 if ( $Y == $DebugLine) { imageline($this->Picture,$LastX,$Y,$X,$Y,$DebugColor); }
6189
6190
                 $LastX = OUT_OF_SIGHT;
6191
                }
6192
              }
6193
            }
6194
          }
6195
        }
6196
      }
6197
6198
     /* Draw the polygon border, if required */
6199
     if ( !$NoBorder)
6200
      {
6201
       foreach($Segments as $Key => $Coords)
0 ignored issues
show
Bug introduced by
The expression $Segments of type string is not traversable.
Loading history...
6202
        $this->drawLine($Coords["X1"],$Coords["Y1"],$Coords["X2"],$Coords["Y2"],array("R"=>$BorderR,"G"=>$BorderG,"B"=>$BorderB,"Alpha"=>$BorderAlpha,"Threshold"=>$Threshold));
6203
      }
6204
6205
     $this->Shadow = $RestoreShadow;
6206
    }
6207
6208
   /* Return the abscissa margin */
6209
   function getAbscissaMargin($Data)
6210
    {
6211
     foreach($Data["Axis"] as $AxisID => $Values) { if ( $Values["Identity"] == AXIS_X ) { return($Values["Margin"]); } }
6212
     return(0);
6213
    }
6214
6215
  }
6216
?>