SRFJitGraph   B
last analyzed

Complexity

Total Complexity 44

Size/Duplication

Total Lines 369
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 2

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 44
lcom 2
cbo 2
dl 0
loc 369
ccs 0
cts 229
cp 0
rs 8.8798
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
F handleParameters() 0 80 19
A getName() 0 5 1
F getResultText() 0 159 22
A includeJS() 0 28 1
A getParamDefinitions() 0 41 1

How to fix   Complexity   

Complex Class

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

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

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

1
<?php
2
/**
3
 * Print query results in interactive graph using the
4
 * JavaScript InfoVis Toolkit (http://thejit.org)
5
 *
6
 * @since 1.7.1
7
 *
8
 * @file SRF_JitGraph.php
9
 * @ingroup SemanticResultFormats
10
 */
11
12
/**
13
 * Result printer for timeline data.
14
 *
15
 * @ingroup SemanticResultFormats
16
 */
17
class SRFJitGraph extends SMWResultPrinter {
18
19
	public static $NODE_SHAPES = [ 'circle', 'rectangle', 'square', 'ellipse', 'triangle', 'star' ];
20
21
	protected $m_graphName = '227';
22
	protected $m_graphLabel = false;
23
	protected $m_graphColor = false;
24
	protected $m_graphLegend = false;
25
	protected $m_graphLink = false;
26
	protected $m_rankdir = "LR";
27
	protected $m_graphSize = "";
28
	protected $m_labelArray = [];
29
	protected $m_graphNodeType = 'circle';
30
	protected $m_graphNodeSize = 12;
31
	protected $m_graphRootNode = false;
32
	protected $m_nodeTypes = [ 'circle', 'rectangle', 'square', 'ellipse', 'triangle', 'star' ];
33
34
	protected $m_nodeColorArray = [
35
		'black' => '#00FF00',
36
		'red' => '#CF2A2A',
37
		'green' => '#558800',
38
		'blue' => '#005588' ];
39
	protected $m_rootNodeColor = '#CF2A2A'; //Red
40
	protected $m_graphNodeColor = '#005588'; //Blue
41
42
	protected $m_settings = [
43
		"divID" => "infovis",
44
		"edgeColor" => "#23A4FF",
45
		"edgeWidth" => 2,
46
		"edgeLength" => 150,
47
		"navigation" => true,
48
		"zooming" => false,
49
		"panning" => "avoid nodes",
50
		"labelColor" => "#000000"
51
	];
52
53
	protected $m_edgeColors = [];
54
	protected $m_edgeNames = [];
55
56
	protected $debug_out = '';
57
58
	protected function handleParameters( array $params, $outputmode ) {
59
		parent::handleParameters( $params, $outputmode );
60
61
		if ( array_key_exists( 'graphname', $params ) ) {
62
			$this->m_graphName = trim( $params['graphname'] );
63
		}
64
65
		$this->m_graphNodeType = $params['graphnodetype'];
66
67
//		if ( array_key_exists( 'graphnodetype', $params ) ) {
68
//			$userType = strtolower( trim( $params['graphnodetype'] ) );
69
//			if ( in_array($userType, $this->m_nodeTypes) ) {
70
//				$this->m_graphNodeType = $userType;
71
//			}
72
//
73
//		}
74
75
		if ( array_key_exists( 'graphnodesize', $params ) ) {
76
77
			$userSize = intval( trim( $params['graphnodesize'] ) );
78
			if ( $userSize > 0 ) {
79
				$this->m_graphNodeSize = $userSize;
80
			}
81
		}
82
		if ( array_key_exists( 'graphsize', $params ) ) {
83
84
			$this->m_graphSize = trim( $params['graphsize'] );
85
86
		}
87
		if ( array_key_exists( 'graphrootnode', $params ) ) {
88
89
			if ( strtolower( trim( $params['graphrootnode'] ) ) == 'yes' ) {
90
				$this->m_graphRootNode = true;
91
			}
92
93
		}
94
		if ( array_key_exists( 'graphlegend', $params ) ) {
95
96
			if ( strtolower( trim( $params['graphlegend'] ) ) == 'yes' ) {
97
				$this->m_graphLegend = true;
98
			}
99
100
		}
101
102
		if ( array_key_exists( 'graphlabel', $params ) ) {
103
104
			if ( strtolower( trim( $params['graphlabel'] ) ) == 'yes' ) {
105
				$this->m_graphLabel = true;
106
			}
107
108
		}
109
		if ( array_key_exists( 'graphnodecolor', $params ) ) {
110
			$userNodeColor = strtolower( trim( $params['graphnodecolor'] ) );
111
			if ( array_key_exists( $userNodeColor, $this->m_nodeColorArray ) ) {
112
				$this->m_graphNodeColor = $this->m_nodeColorArray[$userNodeColor];
113
				$this->debug_out .= "graphNodeColor: " . $this->m_graphNodeColor . " | ";
114
			}
115
		}
116
		if ( array_key_exists( 'rootnodecolor', $params ) ) {
117
			$userRootNodeColor = strtolower( trim( $params['rootnodecolor'] ) );
118
			if ( array_key_exists( $userRootNodeColor, $this->m_nodeColorArray ) ) {
119
				$this->m_rootNodeColor = $this->m_nodeColorArray[$userRootNodeColor];
120
			}
121
		}
122
		if ( array_key_exists( 'graphlink', $params ) ) {
123
124
			if ( strtolower( trim( $params['graphlink'] ) ) == 'yes' ) {
125
				$this->m_graphLink = true;
126
			}
127
128
		}
129
		if ( array_key_exists( 'graphcolor', $params ) ) {
130
131
			if ( strtolower( trim( $params['graphcolor'] ) ) == 'yes' ) {
132
				$this->m_graphColor = true;
133
			}
134
135
		}
136
137
	}
138
139
	public function getName() {
140
		// Give grep a chance to find the usages:
141
		// srf_printername_outline, srf_printername_sum, srf_printername_average, srf_printername_max
142
		return wfMessage( 'srf_printername_' . $this->mFormat )->text();
143
	}
144
145
	protected function getResultText( SMWQueryResult $res, $outputmode ) {
146
		global $wgTitle, $wgOut;
147
148
		if ( class_exists( 'ResourceLoader' ) ) {
149
			$wgOut->addModules( 'ext.srf.jitgraph' );
150
		} else {
151
			//Include javascript files in the HTML header
152
			$this->includeJS();
153
		}
154
155
		$json = "[";
156
		$jsonLeafs = "";
157
158
		while ( $row = $res->getNext() ) {
159
160
			$firstcol = true;
161
162
			foreach ( $row as $field ) {
163
				while ( ( $object = $field->getNextDataValue() ) !== false ) {
164
					$text = $object->getShortText( $outputmode );
165
166
					$nodeLinkTitle = Title::newFromText( $text );
167
					$nodeLinkURL = $nodeLinkTitle->getFullURL();
168
169
					if ( $firstcol ) {
170
						$firstcolvalue = $object->getShortText( $outputmode );
171
172
						//Title of the page where the result format is being displayed
173
						$thisPageTitle = $wgTitle->getPrefixedText();
174
175
						//This little block adds the name of the current edge to the list later used to compile the graph legend
176
						$req = $field->getPrintRequest();
177
						$labelName = trim( $req->getLabel() );
178
179
						//Different color options and formatting for the page currently on.
180
						if ( strcmp( $thisPageTitle, $text ) == 0 && $this->m_graphRootNode ) {
181
							$json .= "{ \"id\":\"$text\", ";
182
							$json .= "\"name\":\"$text\", ";
183
							$json .= "\"data\":{\"\$color\": \"$this->m_rootNodeColor\", ";
184
							$json .= "\"\$type\":\"$this->m_graphNodeType\", ";
185
							$json .= "\"\$dim\":\"17\", ";
186
							$json .= "\"\$url\":\"$nodeLinkURL\", ";
187
							$json .= "\"\$edgeType\":\"$labelName\" ";
188
						} else {
189
							$json .= "{ \"id\":\"$text\", ";
190
							$json .= "\"name\":\"$text\", ";
191
							$json .= "\"data\":{\"\$color\": \"$this->m_graphNodeColor\", ";
192
							$json .= "\"\$type\":\"$this->m_graphNodeType\", ";
193
							$json .= "\"\$dim\":\"$this->m_graphNodeSize\", ";
194
							$json .= "\"\$url\":\"$nodeLinkURL\", ";
195
							$json .= "\"\$edgeType\":\"$labelName\" ";
196
197
							if ( !in_array( $labelName, $this->m_edgeNames ) && strlen( $labelName ) > 0 ) {
198
								$this->m_edgeNames[] = $labelName;
199
							}
200
						}
201
202
						$json .= "}, ";
203
						$json .= "\"adjacencies\":[ ";
204
					}
205
206
					if ( !$firstcol ) {
207
208
						$json .= "{ \"nodeTo\":\"$text\", ";
209
						$json .= "\"nodeFrom\":\"$firstcolvalue\", ";
0 ignored issues
show
Bug introduced by Jeroen De Dauw
The variable $firstcolvalue does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
210
						$json .= "\"data\":{\"\$color\":\"#$this->m_rootNodeColor\",\"\$url\":\"$nodeLinkURL\"}},";
211
						if ( ( $this->m_graphLabel == true ) || ( $this->m_graphColor == true ) ) {
0 ignored issues
show
Coding Style Best Practice introduced by Jeroen De Dauw
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...
212
							$req = $field->getPrintRequest();
213
							$labelName = $req->getLabel();
214
215
							if ( array_search( $labelName, $this->m_labelArray, true ) === false ) {
216
								$this->m_labelArray[] = $labelName;
217
							}
218
							$key = array_search( $labelName, $this->m_labelArray, true );
219
220
							if ( $this->m_graphLabel == true ) {
0 ignored issues
show
Coding Style Best Practice introduced by Jeroen De Dauw
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...
221
222
							}
223
							if ( $this->m_graphColor == true ) {
0 ignored issues
show
Coding Style Best Practice introduced by Jeroen De Dauw
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...
224
225
							}
226
						}
227
228
						//Create an explicit node for each leaf.
229
						$jsonLeafs .= "{ \"id\":\"$text\", ";
230
						$jsonLeafs .= "\"name\":\"$text\", ";
231
232
						if ( strcmp( $thisPageTitle, $text ) == 0 ) {
0 ignored issues
show
Bug introduced by Jeroen De Dauw
The variable $thisPageTitle does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
233
							$rootNodeSize = $this->m_graphNodeSize + 5;
234
							$jsonLeafs .= "\"data\":{\"\$color\": \"$this->m_rootNodeColor\", ";
235
							$jsonLeafs .= "\"\$dim\":\"$rootNodeSize\", ";
236
						} else {
237
							$jsonLeafs .= "\"data\":{\"\$color\": \"$this->m_graphNodeColor\", ";
238
							$jsonLeafs .= "\"\$dim\":\"$this->m_graphNodeSize\", ";
239
						}
240
						$jsonLeafs .= "\"\$type\":\"$this->m_graphNodeType\", ";
241
						$jsonLeafs .= "\"\$url\":\"$nodeLinkURL\", ";
242
						$jsonLeafs .= "\"\$edgeType\":\"$labelName\" ";
0 ignored issues
show
Bug introduced by Jeroen De Dauw
The variable $labelName does not seem to be defined for all execution paths leading up to this point.

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

Let’s take a look at an example:

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

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

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

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

Available Fixes

  1. Check for existence of the variable explicitly:

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

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

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
243
						$jsonLeafs .= "}, ";
244
						$jsonLeafs .= "\"adjacencies\":[]},";
245
246
						//This little block adds the name of the current edge to the list later used to compile the graph legend
247
						$req = $field->getPrintRequest();
248
						$labelName = trim( $req->getLabel() );
249
						if ( !in_array( $labelName, $this->m_edgeNames ) && strlen( $labelName ) > 0 ) {
250
							$this->m_edgeNames[] = $labelName;
251
						}
252
					}
253
				}
254
255
				$firstcol = false;
256
			}
257
			$json = substr( $json, 0, -1 ); // Trim the comma after the last item in the list
258
			$json .= "]},"; //close adjacencies array
259
260
			//Append the leaf nodes.
261
			//$jsonLeafs = substr($jsonLeafs,0,-1); // Trim the comma after the last item in the list
262
			$json .= $jsonLeafs;
263
			$jsonLeafs = "";
264
		}
265
		$json = substr( $json, 0, -1 ); // Trim the comma after the last item in the list
266
		$json .= "]"; //close the json object array
267
268
		$result = '';
269
270
		if ( $this->m_graphLabel || true ) {
271
			$result .= '<h3>' . $this->m_graphName . '</h3>';
272
		}
273
274
		$d_id = rand( 1000, 9999 );
275
		$divID = 'infovis-' . $d_id; //generate a random id to have the ability to display multiple graphs on a single page.
276
		$this->m_settings['d_id'] = $d_id;
277
		$this->m_settings['divID'] = $divID;
278
279
		//User Settings
280
		$userSettings = "var graphSettings = {";
281
		foreach ( $this->m_settings as $key => $value ) {
282
			$userSettings .= "\"$key\": \"$value\",";
283
		}
284
		substr( $userSettings, 0, -1 );
285
		$userSettings .= "};";
286
287
		$result .= '<div id="center-container" class="className"><span class="progressBar" id="progress-' . $d_id . '">0%</span><div id="' . $this->m_settings['divID'] . '" class="infovis"></div>' . '' . '</div>';
288
289
		$result .= "<script>";
290
		$result .= $userSettings;
291
		// FIXME: init function cannot be called here, use JS in a separate file and bind to the onload event.
292
		$result .= "var json=" . $json . "; this.init(json, graphSettings);" . 'jQuery("#progress-' . $d_id . '").progressBar();';
293
		$result .= 'jQuery(document).load(function() {});';
294
		//$result .= '$("#progress1").progressBar();';
295
		$result .= "</script>";
296
297
		// yes, our code can be viewed as HTML if requested, no more parsing needed
298
		//$this->isHTML = $outputmode == SMW_OUTPUT_HTML;
299
300
		$this->isHTML = true;
301
302
		return $result;
303
	}
304
305
	protected function includeJS() {
306
		SMWOutputs::requireHeadItem( SMW_HEADER_STYLE );
307
308
		//$wgOut->addModules( 'ext.srf.jitgraph' );
309
310
		global $srfgScriptPath;
311
312
		SMWOutputs::requireHeadItem(
313
			'smw_jgcss',
314
			'<link rel="stylesheet" type="text/css" href="' . $srfgScriptPath .
315
			'/JitGraph/base.css"></link>'
316
		);
317
		SMWOutputs::requireHeadItem(
318
			'smw_jgloader',
319
			'<script type="text/javascript" src="' . $srfgScriptPath .
320
			'/JitGraph/jquery.progressbar.js"></script>'
321
		);
322
		SMWOutputs::requireHeadItem(
323
			'smw_jg',
324
			'<script type="text/javascript" src="' . $srfgScriptPath .
325
			'/JitGraph/Jit/jit.js"></script>'
326
		);
327
		SMWOutputs::requireHeadItem(
328
			'smw_jghelper',
329
			'<script type="text/javascript" src="' . $srfgScriptPath .
330
			'/JitGraph/SRF_JitGraph.js"></script>'
331
		);
332
	}
333
334
	/**
335
	 * @see SMWResultPrinter::getParamDefinitions
336
	 *
337
	 * @since 1.8
338
	 *
339
	 * @param $definitions array of IParamDefinition
340
	 *
341
	 * @return array of IParamDefinition|array
342
	 */
343
	public function getParamDefinitions( array $definitions ) {
344
		$params = parent::getParamDefinitions( $definitions );
345
346
		$params['graphname'] = [
347
			'default' => 'GraphName',
348
			'message' => 'srf_paramdesc_graphname',
349
		];
350
351
		$params['graphnodetype'] = [
352
			'default' => false,
353
			'message' => 'srf-paramdesc-graph-graphnodetype',
354
			'values' => self::$NODE_SHAPES,
355
		];
356
357
		$params['graphsize'] = [
358
			'type' => 'integer',
359
			'default' => '',
360
			'manipulatedefault' => false,
361
			'message' => 'srf_paramdesc_graphsize',
362
		];
363
364
		$params['graphlegend'] = [
365
			'type' => 'boolean',
366
			'default' => false,
367
			'message' => 'srf_paramdesc_graphlegend',
368
		];
369
370
		$params['graphlabel'] = [
371
			'type' => 'boolean',
372
			'default' => false,
373
			'message' => 'srf_paramdesc_graphlabel',
374
		];
375
376
		$params['graphcolor'] = [
377
			'type' => 'boolean',
378
			'default' => false,
379
			'message' => 'srf_paramdesc_graphcolor',
380
		];
381
382
		return $params;
383
	}
384
385
}
386