pSpring::drawSpring()   F
last analyzed

Complexity

Conditions 51
Paths > 20000

Size

Total Lines 198
Code Lines 115

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2652
Metric Value
cc 51
eloc 115
nc 429496.7295
nop 2
dl 0
loc 198
ccs 0
cts 167
cp 0
crap 2652
rs 2

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
     pSpring - class to draw spring graphs
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("NODE_TYPE_FREE"	, 690001);
17
 define("NODE_TYPE_CENTRAL"	, 690002);
18
19
 define("NODE_SHAPE_CIRCLE"	, 690011);
20
 define("NODE_SHAPE_TRIANGLE"	, 690012);
21
 define("NODE_SHAPE_SQUARE"	, 690013);
22
23
 define("ALGORITHM_RANDOM"	, 690021);
24
 define("ALGORITHM_WEIGHTED"	, 690022);
25
 define("ALGORITHM_CIRCULAR"	, 690023);
26
 define("ALGORITHM_CENTRAL"	, 690024);
27
28
 define("LABEL_CLASSIC"		, 690031);
29
 define("LABEL_LIGHT"		, 690032);
30
31
 /* pSpring class definition */
32
 class pSpring
33
  {
34
   var $History;
35
   var $pChartObject;
36
   var $Data;
37
   var $Links;
38
   var $X1;
39
   var $Y1;
40
   var $X2;
41
   var $Y2;
42
   var $AutoComputeFreeZone;
43
   var $Labels;
44
45
   /* Class creator */
46
   function pSpring()
47
    {
48
     /* Initialise data arrays */
49
     $this->Data = "";
50
     $this->Links = "";
51
52
     /* Set nodes defaults */
53
     $this->Default["R"]		= 255;
54
     $this->Default["G"]		= 255;
55
     $this->Default["B"]		= 255;
56
     $this->Default["Alpha"]		= 100;
57
     $this->Default["BorderR"]		= 0;
58
     $this->Default["BorderG"]		= 0;
59
     $this->Default["BorderB"]		= 0;
60
     $this->Default["BorderAlpha"]	= 100;
61
     $this->Default["Surrounding"]	= NULL;
62
     $this->Default["BackgroundR"]	= 255;
63
     $this->Default["BackgroundG"]	= 255;
64
     $this->Default["BackgroundB"]	= 255;
65
     $this->Default["BackgroundAlpha"]	= 0;
66
     $this->Default["Force"]		= 1;
67
     $this->Default["NodeType"]		= NODE_TYPE_FREE;
68
     $this->Default["Size"]		= 5;
69
     $this->Default["Shape"]		= NODE_SHAPE_CIRCLE;
70
     $this->Default["FreeZone"]		= 40;
71
     $this->Default["LinkR"]		= 0;
72
     $this->Default["LinkG"]		= 0;
73
     $this->Default["LinkB"]		= 0;
74
     $this->Default["LinkAlpha"]	= 0;
75
76
     $this->Labels["Type"]		= LABEL_CLASSIC;
77
     $this->Labels["R"]			= 0;
78
     $this->Labels["G"]			= 0;
79
     $this->Labels["B"]			= 0;
80
     $this->Labels["Alpha"]		= 100;
81
82
     $this->AutoComputeFreeZone         = FALSE;
83
    }
84
85
   /* Set default links options */
86
   function setLinkDefaults($Settings="")
87
    {
88
     if ( isset($Settings["R"]) )     { $this->Default["LinkR"] = $Settings["R"]; }
89
     if ( isset($Settings["G"]) )     { $this->Default["LinkG"] = $Settings["G"]; }
90
     if ( isset($Settings["B"]) )     { $this->Default["LinkB"] = $Settings["B"]; }
91
     if ( isset($Settings["Alpha"]) ) { $this->Default["LinkAlpha"] = $Settings["Alpha"]; }
92
    }
93
94
   /* Set default links options */
95
   function setLabelsSettings($Settings="")
96
    {
97
     if ( isset($Settings["Type"]) )  { $this->Labels["Type"] = $Settings["Type"]; }
98
     if ( isset($Settings["R"]) )     { $this->Labels["R"] = $Settings["R"]; }
99
     if ( isset($Settings["G"]) )     { $this->Labels["G"] = $Settings["G"]; }
100
     if ( isset($Settings["B"]) )     { $this->Labels["B"] = $Settings["B"]; }
101
     if ( isset($Settings["Alpha"]) ) { $this->Labels["Alpha"] = $Settings["Alpha"]; }
102
    }
103
104
   /* Auto compute the FreeZone size based on the number of connections */
105
   function autoFreeZone()
106
    {
107
     /* Check connections reciprocity */
108
     foreach($this->Data as $Key => $Settings)
0 ignored issues
show
Bug introduced by
The expression $this->Data of type string|integer 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...
109
      {
110
       if ( isset($Settings["Connections"]) )
111
        { $this->Data[$Key]["FreeZone"] = count($Settings["Connections"])*10 + 20; }
112
       else
113
        { $this->Data[$Key]["FreeZone"] = 20; }
114
      }
115
116
    }
117
118
   /* Set link properties */
119
   function linkProperties($FromNode,$ToNode,$Settings)
120
    {
121
     if ( !isset($this->Data[$FromNode]) ) { return(0); }
122
     if ( !isset($this->Data[$ToNode]) )   { return(0); }
123
124
     $R			= isset($Settings["R"]) ? $Settings["R"] : 0;
125
     $G			= isset($Settings["G"]) ? $Settings["G"] : 0;
126
     $B			= isset($Settings["B"]) ? $Settings["B"] : 0;
127
     $Alpha		= isset($Settings["Alpha"]) ? $Settings["Alpha"] : 100;
128
     $Name		= isset($Settings["Name"]) ? $Settings["Name"] : NULL;
129
     $Ticks		= isset($Settings["Ticks"]) ? $Settings["Ticks"] : NULL;
130
131
     $this->Links[$FromNode][$ToNode]["R"] = $R;         $this->Links[$ToNode][$FromNode]["R"] = $R;
132
     $this->Links[$FromNode][$ToNode]["G"] = $G;         $this->Links[$ToNode][$FromNode]["G"] = $G;
133
     $this->Links[$FromNode][$ToNode]["B"] = $B;         $this->Links[$ToNode][$FromNode]["B"] = $B;
134
     $this->Links[$FromNode][$ToNode]["Alpha"] = $Alpha; $this->Links[$ToNode][$FromNode]["Alpha"] = $Alpha;
135
     $this->Links[$FromNode][$ToNode]["Name"] = $Name;   $this->Links[$ToNode][$FromNode]["Name"] = $Name;
136
     $this->Links[$FromNode][$ToNode]["Ticks"] = $Ticks; $this->Links[$ToNode][$FromNode]["Ticks"] = $Ticks;
137
    }
138
139
   function setNodeDefaults($Settings="")
140
    {
141
     if ( isset($Settings["R"]) ) { $this->Default["R"]					= $Settings["R"]; }
142
     if ( isset($Settings["G"]) ) { $this->Default["G"]					= $Settings["G"]; }
143
     if ( isset($Settings["B"]) ) { $this->Default["B"]					= $Settings["B"]; }
144
     if ( isset($Settings["Alpha"]) ) { $this->Default["Alpha"]				= $Settings["Alpha"]; }
145
     if ( isset($Settings["BorderR"]) ) { $this->Default["BorderR"]			= $Settings["BorderR"]; }
146
     if ( isset($Settings["BorderG"]) ) { $this->Default["BorderG"]			= $Settings["BorderG"]; }
147
     if ( isset($Settings["BorderB"]) ) { $this->Default["BorderB"]			= $Settings["BorderB"]; }
148
     if ( isset($Settings["BorderAlpha"]) ) { $this->Default["BorderAlpha"]		= $Settings["BorderAlpha"]; }
149
     if ( isset($Settings["Surrounding"]) ) { $this->Default["Surrounding"]		= $Settings["Surrounding"]; }
150
     if ( isset($Settings["BackgroundR"]) ) { $this->Default["BackgroundR"]		= $Settings["BackgroundR"]; }
151
     if ( isset($Settings["BackgroundG"]) ) { $this->Default["BackgroundG"]		= $Settings["BackgroundG"]; }
152
     if ( isset($Settings["BackgroundB"]) ) { $this->Default["BackgroundB"]		= $Settings["BackgroundB"]; }
153
     if ( isset($Settings["BackgroundAlpha"]) ) { $this->Default["BackgroundAlpha"]	= $Settings["BackgroundAlpha"]; }
154
     if ( isset($Settings["NodeType"]) ) { $this->Default["NodeType"]			= $Settings["NodeType"]; }
155
     if ( isset($Settings["Size"]) ) { $this->Default["Size"]				= $Settings["Size"]; }
156
     if ( isset($Settings["Shape"]) ) { $this->Default["Shape"]				= $Settings["Shape"]; }
157
     if ( isset($Settings["FreeZone"]) ) { $this->Default["FreeZone"]			= $Settings["FreeZone"]; }
158
    }
159
160
   /* Add a node */
161
   function addNode($NodeID,$Settings="")
162
    {
163
     /* if the node already exists, ignore */
164
     if (isset($this->Data[$NodeID])) { return(0); }
165
166
     $Name		= isset($Settings["Name"]) ? $Settings["Name"] : "Node ".$NodeID;
167
     $Connections	= isset($Settings["Connections"]) ? $Settings["Connections"] : NULL;
168
169
     $R			= isset($Settings["R"]) ? $Settings["R"] : $this->Default["R"];
170
     $G			= isset($Settings["G"]) ? $Settings["G"] : $this->Default["G"];
171
     $B			= isset($Settings["B"]) ? $Settings["B"] : $this->Default["B"];
172
     $Alpha		= isset($Settings["Alpha"]) ? $Settings["Alpha"] : $this->Default["Alpha"];
173
     $BorderR		= isset($Settings["BorderR"]) ? $Settings["BorderR"] : $this->Default["BorderR"];
174
     $BorderG		= isset($Settings["BorderG"]) ? $Settings["BorderG"] : $this->Default["BorderG"];
175
     $BorderB		= isset($Settings["BorderB"]) ? $Settings["BorderB"] : $this->Default["BorderB"];
176
     $BorderAlpha	= isset($Settings["BorderAlpha"]) ? $Settings["BorderAlpha"] : $this->Default["BorderAlpha"];
177
     $Surrounding	= isset($Settings["Surrounding"]) ? $Settings["Surrounding"] : $this->Default["Surrounding"];
178
     $BackgroundR	= isset($Settings["BackgroundR"]) ? $Settings["BackgroundR"] : $this->Default["BackgroundR"];
179
     $BackgroundG	= isset($Settings["BackgroundG"]) ? $Settings["BackgroundG"] : $this->Default["BackgroundG"];
180
     $BackgroundB	= isset($Settings["BackgroundB"]) ? $Settings["BackgroundB"] : $this->Default["BackgroundB"];
181
     $BackgroundAlpha	= isset($Settings["BackgroundAlpha"]) ? $Settings["BackgroundAlpha"] : $this->Default["BackgroundAlpha"];
182
     $Force		= isset($Settings["Force"]) ? $Settings["Force"] :  $this->Default["Force"];
183
     $NodeType		= isset($Settings["NodeType"]) ? $Settings["NodeType"] : $this->Default["NodeType"];
184
     $Size		= isset($Settings["Size"]) ? $Settings["Size"] : $this->Default["Size"];
185
     $Shape		= isset($Settings["Shape"]) ? $Settings["Shape"] : $this->Default["Shape"];
186
     $FreeZone		= isset($Settings["FreeZone"]) ? $Settings["FreeZone"] : $this->Default["FreeZone"];
187
188
     if ( $Surrounding != NULL ) { $BorderR = $R + $Surrounding; $BorderG = $G + $Surrounding; $BorderB = $B + $Surrounding; }
189
190
     $this->Data[$NodeID]["R"] = $R; $this->Data[$NodeID]["G"] = $G; $this->Data[$NodeID]["B"] = $B; $this->Data[$NodeID]["Alpha"] = $Alpha;
191
     $this->Data[$NodeID]["BorderR"] = $BorderR; $this->Data[$NodeID]["BorderG"] = $BorderG; $this->Data[$NodeID]["BorderB"] = $BorderB; $this->Data[$NodeID]["BorderAlpha"] = $BorderAlpha;
192
     $this->Data[$NodeID]["BackgroundR"]	= $BackgroundR; $this->Data[$NodeID]["BackgroundG"] = $BackgroundG; $this->Data[$NodeID]["BackgroundB"] = $BackgroundB; $this->Data[$NodeID]["BackgroundAlpha"] = $BackgroundAlpha;
193
     $this->Data[$NodeID]["Name"]		= $Name;
194
     $this->Data[$NodeID]["Force"]		= $Force;
195
     $this->Data[$NodeID]["Type"]		= $NodeType;
196
     $this->Data[$NodeID]["Size"]		= $Size;
197
     $this->Data[$NodeID]["Shape"]		= $Shape;
198
     $this->Data[$NodeID]["FreeZone"]		= $FreeZone;
199
     if ( $Connections != NULL )
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $Connections of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
200
      {
201
       if ( is_array($Connections ) )
202
        {
203
         foreach($Connections as $Key => $Value)
204
          $this->Data[$NodeID]["Connections"][] = $Value;
205
        }
206
       else
207
        $this->Data[$NodeID]["Connections"][] = $Connections;
208
      }
209
    }
210
211
   /* Set color attribute for a list of nodes */
212
   function setNodesColor($Nodes,$Settings="")
213
    {
214
     if ( is_array($Nodes) )
215
      {
216
       foreach ($Nodes as $Key => $NodeID)
217
        {
218
         if (isset($this->Data[$NodeID]) )
219
          {
220
           if ( isset($Settings["R"]) ) { $this->Data[$NodeID]["R"] = $Settings["R"]; }
221
           if ( isset($Settings["G"]) ) { $this->Data[$NodeID]["G"] = $Settings["G"]; }
222
           if ( isset($Settings["B"]) ) { $this->Data[$NodeID]["B"] = $Settings["B"]; }
223
           if ( isset($Settings["Alpha"]) ) { $this->Data[$NodeID]["Alpha"] = $Settings["Alpha"]; }
224
           if ( isset($Settings["BorderR"]) ) { $this->Data[$NodeID]["BorderR"] = $Settings["BorderR"]; }
225
           if ( isset($Settings["BorderG"]) ) { $this->Data[$NodeID]["BorderG"] = $Settings["BorderG"]; }
226
           if ( isset($Settings["BorderB"]) ) { $this->Data[$NodeID]["BorderB"] = $Settings["BorderB"]; }
227
           if ( isset($Settings["BorderAlpha"]) ) { $this->Data[$NodeID]["BorderAlpha"] = $Settings["BorderAlpha"]; }
228
           if ( isset($Settings["Surrounding"]) ) { $this->Data[$NodeID]["BorderR"] = $this->Data[$NodeID]["R"] + $Settings["Surrounding"]; $this->Data[$NodeID]["BorderG"] = $this->Data[$NodeID]["G"] + $Settings["Surrounding"]; $this->Data[$NodeID]["BorderB"] = $this->Data[$NodeID]["B"] + $Settings["Surrounding"]; }
229
          }
230
        }
231
      }
232
     else
233
      {
234
       if ( isset($Settings["R"]) ) { $this->Data[$Nodes]["R"] = $Settings["R"]; }
235
       if ( isset($Settings["G"]) ) { $this->Data[$Nodes]["G"] = $Settings["G"]; }
236
       if ( isset($Settings["B"]) ) { $this->Data[$Nodes]["B"] = $Settings["B"]; }
237
       if ( isset($Settings["Alpha"]) ) { $this->Data[$Nodes]["Alpha"] = $Settings["Alpha"]; }
238
       if ( isset($Settings["BorderR"]) ) { $this->Data[$Nodes]["BorderR"] = $Settings["BorderR"]; }
239
       if ( isset($Settings["BorderG"]) ) { $this->Data[$Nodes]["BorderG"] = $Settings["BorderG"]; }
240
       if ( isset($Settings["BorderB"]) ) { $this->Data[$Nodes]["BorderB"] = $Settings["BorderB"]; }
241
       if ( isset($Settings["BorderAlpha"]) ) { $this->Data[$Nodes]["BorderAlpha"] = $Settings["BorderAlpha"]; }
242
       if ( isset($Settings["Surrounding"]) ) { $this->Data[$Nodes]["BorderR"] = $this->Data[$NodeID]["R"] + $Settings["Surrounding"]; $this->Data[$NodeID]["BorderG"] = $this->Data[$NodeID]["G"] + $Settings["Surrounding"]; $this->Data[$NodeID]["BorderB"] = $this->Data[$NodeID]["B"] + $Settings["Surrounding"]; }
0 ignored issues
show
Bug introduced by
The variable $NodeID seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
243
      }
244
    }
245
246
   /* Returns all the nodes details */
247
   function dumpNodes()
248
    { return($this->Data); }
249
250
   /* Check if a connection exists and create it if required */
251
   function checkConnection($SourceID, $TargetID)
252
    {
253
     if ( isset($this->Data[$SourceID]["Connections"]) )
254
      {
255
       foreach ($this->Data[$SourceID]["Connections"] as $Key => $ConnectionID)
256
        { if ( $TargetID == $ConnectionID ) { return(TRUE); } }
257
      }
258
     $this->Data[$SourceID]["Connections"][] = $TargetID;
259
    }
260
   /* Get the median linked nodes position */
261
   function getMedianOffset($Key,$X,$Y)
262
    {
263
     $Cpt = 1;
264
     if ( isset($this->Data[$Key]["Connections"]) )
265
      {
266
       foreach($this->Data[$Key]["Connections"] as $ID => $NodeID)
267
        {
268
         if ( isset($this->Data[$NodeID]["X"]) && isset($this->Data[$NodeID]["Y"]) )
269
          {
270
           $X = $X + $this->Data[$NodeID]["X"];
271
           $Y = $Y + $this->Data[$NodeID]["Y"];
272
           $Cpt++;
273
          }
274
        }
275
      }
276
     return(array("X"=>$X/$Cpt,"Y"=>$Y/$Cpt));
277
    }
278
279
   /* Return the ID of the attached partner with the biggest weight */
280
   function getBiggestPartner($Key)
281
    {
282
     if ( !isset($this->Data[$Key]["Connections"]) ) { return(""); }
283
284
     $MaxWeight = 0; $Result = "";
285
     foreach($this->Data[$Key]["Connections"] as $Key => $PeerID)
286
      {
287
       if ( $this->Data[$PeerID]["Weight"] > $MaxWeight )
288
        { $MaxWeight = $this->Data[$PeerID]["Weight"]; $Result = $PeerID; }
289
      }
290
     return($Result);
291
    }
292
293
   /* Do the initial node positions computing pass */
294
   function firstPass($Algorithm)
295
    {
296
     $CenterX = ($this->X2 - $this->X1) / 2 + $this->X1;
297
     $CenterY = ($this->Y2 - $this->Y1) / 2 + $this->Y1;
298
299
     /* Check connections reciprocity */
300
     foreach($this->Data as $Key => $Settings)
0 ignored issues
show
Bug introduced by
The expression $this->Data of type string|integer 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...
301
      {
302
       if ( isset($Settings["Connections"]) )
303
        {
304
         foreach($Settings["Connections"] as $ID => $ConnectionID)
305
          $this->checkConnection($ConnectionID,$Key);
306
        }
307
      }
308
309
     if ( $this->AutoComputeFreeZone ) { $this->autoFreeZone(); }
310
311
     /* Get the max number of connections */
312
     $MaxConnections = 0;
313
     foreach($this->Data as $Key => $Settings)
0 ignored issues
show
Bug introduced by
The expression $this->Data of type string|integer 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...
314
      { if ( isset($Settings["Connections"]) ) { if ( $MaxConnections < count($Settings["Connections"] ) ) { $MaxConnections = count($Settings["Connections"]); } } }
315
316
     if ( $Algorithm == ALGORITHM_WEIGHTED )
317
      {
318
       foreach($this->Data as $Key => $Settings)
0 ignored issues
show
Bug introduced by
The expression $this->Data of type string|integer 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...
319
        {
320
         if ( $Settings["Type"] == NODE_TYPE_CENTRAL ) { $this->Data[$Key]["X"] = $CenterX; $this->Data[$Key]["Y"] = $CenterY; }
321
         if ( $Settings["Type"] == NODE_TYPE_FREE )
322
          {
323
           if ( isset($Settings["Connections"]) )
324
            { $Connections = count($Settings["Connections"]); }
325
           else
326
            { $Connections = 0; }
327
328
           $Ring  = $MaxConnections - $Connections;
329
           $Angle = rand(0,360);
330
           
331
           $this->Data[$Key]["X"] = cos(deg2rad($Angle)) * ($Ring*$this->RingSize) + $CenterX;
332
           $this->Data[$Key]["Y"] = sin(deg2rad($Angle)) * ($Ring*$this->RingSize) + $CenterY;
333
          }
334
        }
335
      }
336
     elseif ( $Algorithm == ALGORITHM_CENTRAL )
337
      {
338
       /* Put a weight on each nodes */
339
       foreach($this->Data as $Key => $Settings)
0 ignored issues
show
Bug introduced by
The expression $this->Data of type string|integer 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...
340
        {
341
         if ( isset($Settings["Connections"]) )
342
          $this->Data[$Key]["Weight"] = count($Settings["Connections"]);
343
         else
344
          $this->Data[$Key]["Weight"] = 0;
345
        }
346
347
       $MaxConnections = $MaxConnections + 1;
348
       for($i=$MaxConnections;$i>=0;$i--)
349
        {
350
         foreach($this->Data as $Key => $Settings)
0 ignored issues
show
Bug introduced by
The expression $this->Data of type string|integer 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...
351
          {
352
           if ( $Settings["Type"] == NODE_TYPE_CENTRAL ) { $this->Data[$Key]["X"] = $CenterX; $this->Data[$Key]["Y"] = $CenterY; }
353
           if ( $Settings["Type"] == NODE_TYPE_FREE )
354
            {
355
             if ( isset($Settings["Connections"]) )
356
              { $Connections = count($Settings["Connections"]); }
357
             else
358
              { $Connections = 0; }
359
360
             if ( $Connections == $i )
361
              {
362
               $BiggestPartner = $this->getBiggestPartner($Key);
363
               if ( $BiggestPartner != "" )
364
                {
365
                 $Ring          = $this->Data[$BiggestPartner]["FreeZone"];
366
                 $Weight        = $this->Data[$BiggestPartner]["Weight"];
367
                 $AngleDivision = 360 / $this->Data[$BiggestPartner]["Weight"];
368
                 $Done          = FALSE; $Tries = 0;
369
                 while (!$Done && $Tries <= $Weight*2)
370
                  {
371
                   $Tries++;
372
                   $Angle = floor(rand(0,$Weight)*$AngleDivision);
373
                   if ( !isset($this->Data[$BiggestPartner]["Angular"][$Angle]) || !isset($this->Data[$BiggestPartner]["Angular"]) )
374
                    {
375
                     $this->Data[$BiggestPartner]["Angular"][$Angle] = $Angle;
376
                     $Done = TRUE; 
377
                    }
378
                  }
379
                 if ( !$Done )
380
                  { $Angle = rand(0,360); $this->Data[$BiggestPartner]["Angular"][$Angle] = $Angle; }
381
382
                 $X = cos(deg2rad($Angle)) * ($Ring) + $this->Data[$BiggestPartner]["X"];
383
                 $Y = sin(deg2rad($Angle)) * ($Ring) + $this->Data[$BiggestPartner]["Y"];
384
385
                 $this->Data[$Key]["X"] = $X;
386
                 $this->Data[$Key]["Y"] = $Y;
387
                }
388
              }
389
            }
390
          }
391
        }
392
      }
393
     elseif ( $Algorithm == ALGORITHM_CIRCULAR )
394
      {
395
       $MaxConnections = $MaxConnections + 1;
396
       for($i=$MaxConnections;$i>=0;$i--)
397
        {
398
         foreach($this->Data as $Key => $Settings)
0 ignored issues
show
Bug introduced by
The expression $this->Data of type string|integer 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...
399
          {
400
           if ( $Settings["Type"] == NODE_TYPE_CENTRAL ) { $this->Data[$Key]["X"] = $CenterX; $this->Data[$Key]["Y"] = $CenterY; }
401
           if ( $Settings["Type"] == NODE_TYPE_FREE )
402
            {
403
             if ( isset($Settings["Connections"]) )
404
              { $Connections = count($Settings["Connections"]); }
405
             else
406
              { $Connections = 0; }
407
408
             if ( $Connections == $i )
409
              {
410
               $Ring  = $MaxConnections - $Connections;
411
               $Angle = rand(0,360);
412
413
               $X = cos(deg2rad($Angle)) * ($Ring*$this->RingSize) + $CenterX;
414
               $Y = sin(deg2rad($Angle)) * ($Ring*$this->RingSize) + $CenterY;
415
416
               $MedianOffset = $this->getMedianOffset($Key,$X,$Y);
417
418
               $this->Data[$Key]["X"] = $MedianOffset["X"];
419
               $this->Data[$Key]["Y"] = $MedianOffset["Y"];
420
              }
421
            }
422
          }
423
        }
424
      }
425
     elseif ( $Algorithm == ALGORITHM_RANDOM )
426
      {
427
       foreach($this->Data as $Key => $Settings)
0 ignored issues
show
Bug introduced by
The expression $this->Data of type string|integer 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...
428
        {
429
         if ( $Settings["Type"] == NODE_TYPE_FREE )
430
          {
431
           $this->Data[$Key]["X"] = $CenterX + rand(-20,20);
432
           $this->Data[$Key]["Y"] = $CenterY + rand(-20,20);
433
          }
434
         if ( $Settings["Type"] == NODE_TYPE_CENTRAL ) { $this->Data[$Key]["X"] = $CenterX; $this->Data[$Key]["Y"] = $CenterY; }
435
        }
436
      }
437
    }
438
439
   /* Compute one pass */
440
   function doPass()
441
    {
442
     /* Compute vectors */
443
     foreach($this->Data as $Key => $Settings)
0 ignored issues
show
Bug introduced by
The expression $this->Data of type string|integer 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...
444
      {
445
       if ( $Settings["Type"] != NODE_TYPE_CENTRAL )
446
        {
447
         unset($this->Data[$Key]["Vectors"]);
448
449
         $X1 = $Settings["X"];
450
         $Y1 = $Settings["Y"];
451
452
         /* Repulsion vectors */
453
         foreach($this->Data as $Key2 => $Settings2)
0 ignored issues
show
Bug introduced by
The expression $this->Data of type string|integer 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...
454
          {
455
           if ( $Key != $Key2 )
456
            {
457
             $X2 = $this->Data[$Key2]["X"];
458
             $Y2 = $this->Data[$Key2]["Y"];
459
             $FreeZone = $this->Data[$Key2]["FreeZone"];
460
461
             $Distance = $this->getDistance($X1,$Y1,$X2,$Y2);
462
             $Angle    = $this->getAngle($X1,$Y1,$X2,$Y2) + 180;
463
464
             /* Nodes too close, repulsion occurs */
465
             if ( $Distance < $FreeZone )
466
              {
467
               $Force = log(pow(2,$FreeZone-$Distance));
468
               if ( $Force > 1 )
469
                { $this->Data[$Key]["Vectors"][] = array("Type"=>"R","Angle"=>$Angle % 360,"Force"=>$Force); }
470
              }
471
            }
472
          }
473
474
         /* Attraction vectors */
475
         if ( isset($Settings["Connections"]) )
476
          {
477
           foreach($Settings["Connections"] as $ID => $NodeID)
478
            {
479
             if ( isset($this->Data[$NodeID]) )
480
              {
481
               $X2 = $this->Data[$NodeID]["X"];
482
               $Y2 = $this->Data[$NodeID]["Y"];
483
               $FreeZone = $this->Data[$Key2]["FreeZone"];
0 ignored issues
show
Bug introduced by
The variable $Key2 seems to be defined by a foreach iteration on line 453. Are you sure the iterator is never empty, otherwise this variable is not defined?

It seems like you are relying on a variable being defined by an iteration:

foreach ($a as $b) {
}

// $b is defined here only if $a has elements, for example if $a is array()
// then $b would not be defined here. To avoid that, we recommend to set a
// default value for $b.


// Better
$b = 0; // or whatever default makes sense in your context
foreach ($a as $b) {
}

// $b is now guaranteed to be defined here.
Loading history...
484
485
               $Distance = $this->getDistance($X1,$Y1,$X2,$Y2);
486
               $Angle    = $this->getAngle($X1,$Y1,$X2,$Y2);
487
488
               if ( $Distance > $FreeZone )
489
                $Force = log(($Distance-$FreeZone)+1);
490
               else
491
                { $Force = log(($FreeZone-$Distance)+1); ($Angle = $Angle + 180); }
492
493
               if ( $Force > 1 )
494
                $this->Data[$Key]["Vectors"][] = array("Type"=>"A","Angle"=>$Angle % 360,"Force"=>$Force);
495
              }
496
            }
497
          }
498
        }
499
      }
500
501
     /* Move the nodes accoding to the vectors */
502
     foreach($this->Data as $Key => $Settings)
0 ignored issues
show
Bug introduced by
The expression $this->Data of type string|integer 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...
503
      {
504
       $X = $Settings["X"];
505
       $Y = $Settings["Y"];
506
507
       if ( isset($Settings["Vectors"]) && $Settings["Type"] != NODE_TYPE_CENTRAL )
508
        {
509
         foreach($Settings["Vectors"] as $ID => $Vector)
510
          {
511
           $Type  = $Vector["Type"];
512
           $Force = $Vector["Force"];
513
           $Angle = $Vector["Angle"];
514
           $Factor = $Type == "A" ? $this->MagneticForceA : $this->MagneticForceR;
515
516
           $X = cos(deg2rad($Angle)) * $Force * $Factor + $X;
517
           $Y = sin(deg2rad($Angle)) * $Force * $Factor + $Y;
518
          }
519
        }
520
521
       $this->Data[$Key]["X"] = $X;
522
       $this->Data[$Key]["Y"] = $Y;
523
      }
524
    }
525
526
   function lastPass()
527
    {
528
     /* Put everything inside the graph area */
529
     foreach($this->Data as $Key => $Settings)
0 ignored issues
show
Bug introduced by
The expression $this->Data of type string|integer 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...
530
      {
531
       $X = $Settings["X"];
532
       $Y = $Settings["Y"];
533
534
       if ( $X < $this->X1 ) { $X = $this->X1; }
535
       if ( $X > $this->X2 ) { $X = $this->X2; }
536
       if ( $Y < $this->Y1 ) { $Y = $this->Y1; }
537
       if ( $Y > $this->Y2 ) { $Y = $this->Y2; }
538
539
       $this->Data[$Key]["X"] = $X;
540
       $this->Data[$Key]["Y"] = $Y;
541
      }
542
543
     /* Dump all links */
544
     $Links = "";
545
     foreach($this->Data as $Key => $Settings)
0 ignored issues
show
Bug introduced by
The expression $this->Data of type string|integer 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...
546
      {
547
       $X1 = $Settings["X"];
548
       $Y1 = $Settings["Y"];
549
550
       if ( isset($Settings["Connections"]) )
551
        {
552
         foreach ($Settings["Connections"] as $ID => $NodeID)
553
          {
554
           if ( isset($this->Data[$NodeID]) )
555
            {
556
             $X2 = $this->Data[$NodeID]["X"];
557
             $Y2 = $this->Data[$NodeID]["Y"];
558
559
             $Links[] = array("X1"=>$X1,"Y1"=>$Y1,"X2"=>$X2,"Y2"=>$Y2,"Source"=>$Settings["Name"],"Destination"=>$this->Data[$NodeID]["Name"]);
560
            }
561
          }
562
        }
563
      }
564
565
     /* Check collisions */
566
     $Conflicts = 0;
567
     foreach($this->Data as $Key => $Settings)
0 ignored issues
show
Bug introduced by
The expression $this->Data of type string|integer 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...
568
      {
569
       $X1 = $Settings["X"];
570
       $Y1 = $Settings["Y"];
571
572
       if ( isset($Settings["Connections"]) )
573
        {
574
         foreach ($Settings["Connections"] as $ID => $NodeID)
575
          {
576
           if ( isset($this->Data[$NodeID]) )
577
            {
578
             $X2 = $this->Data[$NodeID]["X"];
579
             $Y2 = $this->Data[$NodeID]["Y"];
580
581
             foreach($Links as $IDLinks => $Link)
0 ignored issues
show
Bug introduced by
The expression $Links of type string is not traversable.
Loading history...
582
              {
583
               $X3 = $Link["X1"]; $Y3 = $Link["Y1"]; $X4 = $Link["X2"]; $Y4 = $Link["Y2"];
584
585
               if ( !($X1 == $X3 && $X2 == $X4 && $Y1 == $Y3 && $Y2 == $Y4 ) )
586
                {
587
                 if ( $this->intersect($X1,$Y1,$X2,$Y2,$X3,$Y3,$X4,$Y4) )
588
                  {
589
                   if ( $Link["Source"] != $Settings["Name"] && $Link["Source"] != $this->Data[$NodeID]["Name"] && $Link["Destination"] != $Settings["Name"] && $Link["Destination"] != $this->Data[$NodeID]["Name"] )
590
                    { $Conflicts++; }
591
                  }
592
                }
593
              }
594
            }
595
          }
596
        }
597
      }
598
     return($Conflicts/2);
599
    }
600
601
   /* Center the graph */
602
   function center()
603
    {
604
     /* Determine the real center */
605
     $TargetCenterX = ($this->X2 - $this->X1) / 2 + $this->X1;
606
     $TargetCenterY = ($this->Y2 - $this->Y1) / 2 + $this->Y1;
607
608
     /* Get current boundaries */
609
     $XMin = $this->X2; $XMax = $this->X1;
610
     $YMin = $this->Y2; $YMax = $this->Y1;
611
     foreach($this->Data as $Key => $Settings)
0 ignored issues
show
Bug introduced by
The expression $this->Data of type string|integer 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...
612
      {
613
       $X = $Settings["X"];
614
       $Y = $Settings["Y"];
615
616
       if ( $X < $XMin) { $XMin = $X; }
617
       if ( $X > $XMax) { $XMax = $X; }
618
       if ( $Y < $YMin) { $YMin = $Y; }
619
       if ( $Y > $YMax) { $YMax = $Y; }
620
      }
621
     $CurrentCenterX = ($XMax - $XMin) / 2 + $XMin;
622
     $CurrentCenterY = ($YMax - $YMin) / 2 + $YMin;
623
624
     /* Compute the offset to apply */
625
     $XOffset = $TargetCenterX - $CurrentCenterX;
626
     $YOffset = $TargetCenterY - $CurrentCenterY;
627
628
     /* Correct the points position */
629
     foreach($this->Data as $Key => $Settings)
0 ignored issues
show
Bug introduced by
The expression $this->Data of type string|integer 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...
630
      {
631
       $this->Data[$Key]["X"] = $Settings["X"] + $XOffset;
632
       $this->Data[$Key]["Y"] = $Settings["Y"] + $YOffset;
633
      }
634
    }
635
636
   /* Create the encoded string */
637
   function drawSpring($Object,$Settings="")
638
    {
639
     $this->pChartObject = $Object;
640
641
     $Pass			= isset($Settings["Pass"]) ? $Settings["Pass"] : 50;
642
     $Retries			= isset($Settings["Retry"]) ? $Settings["Retry"] : 10;
643
     $this->MagneticForceA	= isset($Settings["MagneticForceA"]) ? $Settings["MagneticForceA"] : 1.5;
644
     $this->MagneticForceR	= isset($Settings["MagneticForceR"]) ? $Settings["MagneticForceR"] : 2;
645
     $this->RingSize		= isset($Settings["RingSize"]) ? $Settings["RingSize"] : 40;
646
     $DrawVectors		= isset($Settings["DrawVectors"]) ? $Settings["DrawVectors"] : FALSE;
647
     $DrawQuietZone		= isset($Settings["DrawQuietZone"]) ? $Settings["DrawQuietZone"] : FALSE;
648
     $CenterGraph		= isset($Settings["CenterGraph"]) ? $Settings["CenterGraph"] : TRUE;
649
     $TextPadding		= isset($Settings["TextPadding"]) ? $Settings["TextPadding"] : 4;
650
     $Algorithm			= isset($Settings["Algorithm"]) ? $Settings["Algorithm"] : ALGORITHM_WEIGHTED;
651
652
     $FontSize		= $Object->FontSize;
653
     $this->X1		= $Object->GraphAreaX1;
654
     $this->Y1		= $Object->GraphAreaY1;
655
     $this->X2		= $Object->GraphAreaX2;
656
     $this->Y2		= $Object->GraphAreaY2;
657
658
     $Conflicts = 1; $Jobs = 0; $this->History["MinimumConflicts"] = -1;
659
     while ($Conflicts != 0 && $Jobs < $Retries )
660
      {
661
       $Jobs++;
662
663
       /* Compute the initial settings */
664
       $this->firstPass($Algorithm);
665
666
       /* Apply the vectors */
667
       if ( $Pass > 0 ) 
668
        {
669
         for ($i=0; $i<=$Pass; $i++) { $this->doPass(); }
670
        }
671
672
       $Conflicts = $this->lastPass();
673
       if ( $this->History["MinimumConflicts"] == -1 || $Conflicts < $this->History["MinimumConflicts"] )
674
        { $this->History["MinimumConflicts"] = $Conflicts; $this->History["Result"] = $this->Data; }
675
      }
676
677
     $Conflicts  = $this->History["MinimumConflicts"];
678
     $this->Data = $this->History["Result"];
679
680
     if ( $CenterGraph ) { $this->center(); }
681
682
     /* Draw the connections */
683
     $Drawn = "";
684
     foreach($this->Data as $Key => $Settings)
0 ignored issues
show
Bug introduced by
The expression $this->Data 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...
685
      {
686
       $X	= $Settings["X"];
687
       $Y	= $Settings["Y"];
688
689
       if ( isset($Settings["Connections"]) )
690
        {
691
         foreach ($Settings["Connections"] as $ID => $NodeID)
692
          {
693
           if ( !isset($Drawn[$Key]) )    { $Drawn[$Key] = ""; }
694
           if ( !isset($Drawn[$NodeID]) ) { $Drawn[$NodeID] = ""; }
695
696
           if ( isset($this->Data[$NodeID]) && !isset($Drawn[$Key][$NodeID]) && !isset($Drawn[$NodeID][$Key]) )
697
            {
698
             $Color = array("R"=>$this->Default["LinkR"],"G"=>$this->Default["LinkG"],"B"=>$this->Default["LinkB"],"Alpha"=>$this->Default["Alpha"]);
699
700
             if ( $this->Links != "" )
701
              {
702
               if ( isset($this->Links[$Key][$NodeID]["R"]) )
703
                { $Color = array("R"=>$this->Links[$Key][$NodeID]["R"],"G"=>$this->Links[$Key][$NodeID]["G"],"B"=>$this->Links[$Key][$NodeID]["B"],"Alpha"=>$this->Links[$Key][$NodeID]["Alpha"]); }
704
705
               if ( isset($this->Links[$Key][$NodeID]["Ticks"]) )
706
                 { $Color["Ticks"] = $this->Links[$Key][$NodeID]["Ticks"]; }
707
              }
708
709
             $X2 = $this->Data[$NodeID]["X"];
710
             $Y2 = $this->Data[$NodeID]["Y"];
711
             $this->pChartObject->drawLine($X,$Y,$X2,$Y2,$Color);
712
             $Drawn[$Key][$NodeID] = TRUE;
713
714
             if ( isset($this->Links) && $this->Links != "" )
715
              {
716
               if ( isset($this->Links[$Key][$NodeID]["Name"]) || isset($this->Links[$NodeID][$Key]["Name"]) )
717
                {
718
                 $Name  = isset($this->Links[$Key][$NodeID]["Name"]) ? $this->Links[$Key][$NodeID]["Name"] : $this->Links[$NodeID][$Key]["Name"];
719
                 $TxtX  = ($X2 - $X)/2 + $X;
720
                 $TxtY  = ($Y2 - $Y)/2 + $Y;
721
722
                 if ( $X <= $X2 )
723
                  $Angle = (360-$this->getAngle($X,$Y,$X2,$Y2)) % 360;
724
                 else
725
                  $Angle = (360-$this->getAngle($X2,$Y2,$X,$Y)) % 360;
726
727
                 $Settings          = $Color;
728
                 $Settings["Angle"] = $Angle;
729
                 $Settings["Align"] = TEXT_ALIGN_BOTTOMMIDDLE;
730
                 $this->pChartObject->drawText($TxtX,$TxtY,$Name,$Settings);
731
                }
732
              }
733
            }
734
          }
735
        }
736
      }
737
738
     /* Draw the quiet zones */
739
     if ( $DrawQuietZone )
740
      {
741
       foreach($this->Data as $Key => $Settings)
0 ignored issues
show
Bug introduced by
The expression $this->Data 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...
742
        {
743
         $X	 = $Settings["X"];
744
         $Y	 = $Settings["Y"];
745
         $FreeZone = $Settings["FreeZone"];
746
747
         $this->pChartObject->drawFilledCircle($X,$Y,$FreeZone,array("R"=>0,"G"=>0,"B"=>0,"Alpha"=>2));
748
        }
749
      }
750
751
752
     /* Draw the nodes */
753
     foreach($this->Data as $Key => $Settings)
0 ignored issues
show
Bug introduced by
The expression $this->Data 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...
754
      {
755
       $X	 = $Settings["X"];
756
       $Y	 = $Settings["Y"];
757
       $Name	 = $Settings["Name"];
758
       $FreeZone = $Settings["FreeZone"];
759
       $Shape    = $Settings["Shape"];
760
       $Size     = $Settings["Size"];
761
762
       $Color	 = array("R"=>$Settings["R"],"G"=>$Settings["G"],"B"=>$Settings["B"],"Alpha"=>$Settings["Alpha"],"BorderR"=>$Settings["BorderR"],"BorderG"=>$Settings["BorderG"],"BorderB"=>$Settings["BorderB"],"BorderApha"=>$Settings["BorderAlpha"]);
763
764
       if ( $Shape == NODE_SHAPE_CIRCLE )
765
        {
766
         $this->pChartObject->drawFilledCircle($X,$Y,$Size,$Color);
767
        }
768
       elseif ( $Shape == NODE_SHAPE_TRIANGLE )
769
        {
770
         $Points = "";
771
         $Points[] = cos(deg2rad(270)) * $Size + $X; $Points[] = sin(deg2rad(270)) * $Size + $Y;
772
         $Points[] = cos(deg2rad(45)) * $Size + $X;  $Points[] = sin(deg2rad(45)) * $Size + $Y;
773
         $Points[] = cos(deg2rad(135)) * $Size + $X; $Points[] = sin(deg2rad(135)) * $Size + $Y;
774
         $this->pChartObject->drawPolygon($Points,$Color);
775
        }
776
       elseif ( $Shape == NODE_SHAPE_SQUARE )
777
        {
778
         $Offset = $Size/2; $Size = $Size / 2;
779
         $this->pChartObject->drawFilledRectangle($X-$Offset,$Y-$Offset,$X+$Offset,$Y+$Offset,$Color);
780
        }
781
782
       if ( $Name != "" )
783
        {
784
         $LabelOptions = array("R"=>$this->Labels["R"],"G"=>$this->Labels["G"],"B"=>$this->Labels["B"],"Alpha"=>$this->Labels["Alpha"]);
785
786
         if ( $this->Labels["Type"] == LABEL_LIGHT )
787
          {
788
           $LabelOptions["Align"] = TEXT_ALIGN_BOTTOMLEFT;
789
           $this->pChartObject->drawText($X,$Y,$Name,$LabelOptions);
790
          }
791
         elseif ( $this->Labels["Type"] == LABEL_CLASSIC )
792
          {
793
           $LabelOptions["Align"]         = TEXT_ALIGN_TOPMIDDLE;
794
           $LabelOptions["DrawBox"]       = TRUE;
795
           $LabelOptions["BoxAlpha"]      = 50;
796
           $LabelOptions["BorderOffset"]  = 4;
797
           $LabelOptions["RoundedRadius"] = 3;
798
           $LabelOptions["BoxRounded"]    = TRUE;
799
           $LabelOptions["NoShadow"]      = TRUE;
800
801
           $this->pChartObject->drawText($X,$Y+$Size+$TextPadding,$Name,$LabelOptions);
802
          }
803
        }
804
      }
805
806
     /* Draw the vectors */
807
     if ( $DrawVectors )
808
      {
809
       foreach($this->Data as $Key => $Settings)
0 ignored issues
show
Bug introduced by
The expression $this->Data 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...
810
        {
811
         $X1 = $Settings["X"];
812
         $Y1 = $Settings["Y"];
813
814
         if ( isset($Settings["Vectors"]) && $Settings["Type"] != NODE_TYPE_CENTRAL )
815
          {
816
           foreach($Settings["Vectors"] as $ID => $Vector)
817
            {
818
             $Type  = $Vector["Type"];
819
             $Force = $Vector["Force"];
820
             $Angle = $Vector["Angle"];
821
             $Factor = $Type == "A" ? $this->MagneticForceA : $this->MagneticForceR;
822
             $Color  = $Type == "A" ? array("FillR"=>255,"FillG"=>0,"FillB"=>0) : array("FillR"=>0,"FillG"=>255,"FillB"=>0);
823
824
             $X2 = cos(deg2rad($Angle)) * $Force * $Factor + $X1;
825
             $Y2 = sin(deg2rad($Angle)) * $Force * $Factor + $Y1;
826
827
             $this->pChartObject->drawArrow($X1,$Y1,$X2,$Y2,$Color);
828
            }
829
          }
830
        }
831
      }
832
833
     return(array("Pass"=>$Jobs,"Conflicts"=>$Conflicts));
834
    }
835
836
   /* Return the distance between two points */
837
   function getDistance($X1,$Y1,$X2,$Y2)
838
    { return (sqrt(($X2-$X1)*($X2-$X1)+($Y2-$Y1)*($Y2-$Y1))); }
839
840
   /* Return the angle made by a line and the X axis */
841
   function getAngle($X1,$Y1,$X2,$Y2)
842
    {
843
     $Opposite = $Y2 - $Y1; $Adjacent = $X2 - $X1;$Angle = rad2deg(atan2($Opposite,$Adjacent));
844
     if ($Angle > 0) { return($Angle); } else { return(360-abs($Angle)); }
845
    }
846
847
   function intersect($X1,$Y1,$X2,$Y2,$X3,$Y3,$X4,$Y4)
848
    {
849
     $A = (($X3 * $Y4 - $X4 * $Y3) * ($X1 - $X2) - ($X1 * $Y2 - $X2 * $Y1) * ($X3 - $X4));
850
     $B = (($Y1 - $Y2) * ($X3 - $X4) - ($Y3 - $Y4) * ($X1 - $X2));
851
852
     if ( $B == 0 ) { return(FALSE); }
853
     $Xi = $A / $B;
854
855
     $C = ($X1 - $X2);
856
     if ( $C == 0 ) { return(FALSE); }
857
     $Yi = $Xi * (($Y1 - $Y2)/$C) + (($X1 * $Y2 - $X2 * $Y1)/$C);
858
859
     if ( $Xi >= min($X1,$X2) && $Xi >= min($X3,$X4) && $Xi <= max($X1,$X2) && $Xi <= max($X3,$X4))
860
      {
861
       if ( $Yi >= min($Y1,$Y2) && $Yi >= min($Y3,$Y4) && $Yi <= max($Y1,$Y2) && $Yi <= max($Y3,$Y4))
862
        { return(TRUE); }
863
      }
864
865
      return(FALSE);   
866
    }
867
  }
868
?>