Completed
Push — master ( 6dc7d8...407c40 )
by Karsten
15:45
created

formats/graphviz/SRF_Graph.php (2 issues)

a variable is defined regardless of execution path.

Bug Major

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * SMW result printer for graphs using graphViz.
5
 * In order to use this printer you need to have both
6
 * the graphViz library installed on your system and
7
 * have the graphViz MediaWiki extension installed.
8
 *
9
 * @file SRF_Graph.php
10
 * @ingroup SemanticResultFormats
11
 *
12
 * @licence GNU GPL v2+
13
 * @author Frank Dengler
14
 * @author Jeroen De Dauw < [email protected] >
15
 */
16
class SRFGraph extends SMWResultPrinter {
17
18
	public static $NODE_SHAPES = [
19
		'box',
20
		'box3d',
21
		'circle',
22
		'component',
23
		'diamond',
24
		'doublecircle',
25
		'doubleoctagon',
26
		'egg',
27
		'ellipse',
28
		'folder',
29
		'hexagon',
30
		'house',
31
		'invhouse',
32
		'invtrapezium',
33
		'invtriangle',
34
		'Mcircle',
35
		'Mdiamond',
36
		'Msquare',
37
		'none',
38
		'note',
39
		'octagon',
40
		'parallelogram',
41
		'pentagon ',
42
		'plaintext',
43
		'point',
44
		'polygon',
45
		'rect',
46
		'rectangle',
47
		'septagon',
48
		'square',
49
		'tab',
50
		'trapezium',
51
		'triangle',
52
		'tripleoctagon',
53
	];
54
55
	protected $m_graphName;
56
	protected $m_graphLabel;
57
	protected $m_graphColor;
58
	protected $m_graphLegend;
59
	protected $m_graphLink;
60
	protected $m_rankdir;
61
	protected $m_graphSize;
62
	protected $m_labelArray = [];
63
	protected $m_graphColors = [
64
		'black',
65
		'red',
66
		'green',
67
		'blue',
68
		'darkviolet',
69
		'gold',
70
		'deeppink',
71
		'brown',
72
		'bisque',
73
		'darkgreen',
74
		'yellow',
75
		'darkblue',
76
		'magenta',
77
		'steelblue2' ];
78
	protected $m_nameProperty;
79
	protected $m_nodeShape;
80
	protected $m_parentRelation;
81
	protected $m_wordWrapLimit;
82
83
	/**
84
	 * (non-PHPdoc)
85
	 * @see SMWResultPrinter::handleParameters()
86
	 */
87
	protected function handleParameters( array $params, $outputmode ) {
88
		parent::handleParameters( $params, $outputmode );
89
90
		$this->m_graphName = trim( $params['graphname'] );
91
		$this->m_graphSize = trim( $params['graphsize'] );
92
93
		$this->m_graphLegend = $params['graphlegend'];
94
		$this->m_graphLabel = $params['graphlabel'];
95
96
		$this->m_rankdir = strtoupper( trim( $params['arrowdirection'] ) );
97
98
		$this->m_graphLink = $params['graphlink'];
99
		$this->m_graphColor = $params['graphcolor'];
100
101
		$this->m_nameProperty = $params['nameproperty'] === false ? false : trim( $params['nameproperty'] );
102
103
		$this->m_parentRelation = strtolower( trim( $params['relation'] ) ) == 'parent';
104
105
		$this->m_nodeShape = $params['nodeshape'];
106
		$this->m_wordWrapLimit = $params['wordwraplimit'];
107
	}
108
109
	protected function getResultText( SMWQueryResult $res, $outputmode ) {
110
111
		if ( !class_exists( 'GraphViz' )
112
			&& !class_exists( '\\MediaWiki\\Extension\\GraphViz\\GraphViz' )
113
		) {
114
			wfWarn( 'The SRF Graph printer needs the GraphViz extension to be installed.' );
115
			return '';
116
		}
117
118
		$this->isHTML = true;
119
120
		$graphInput = "digraph $this->m_graphName {";
121
		if ( $this->m_graphSize != '' ) {
122
			$graphInput .= "size=\"$this->m_graphSize\";";
123
		}
124
		if ( $this->m_nodeShape ) {
125
			$graphInput .= "node [shape=$this->m_nodeShape];";
126
		}
127
		$graphInput .= "rankdir=$this->m_rankdir;";
128
129
		while ( $row = $res->getNext() ) {
130
			$graphInput .= $this->getGVForItem( $row, $outputmode );
131
		}
132
133
		$graphInput .= "}";
134
135
		// Calls graphvizParserHook function from MediaWiki GraphViz extension
136
		$result = $GLOBALS['wgParser']->recursiveTagParse( "<graphviz>$graphInput</graphviz>" );
137
138
		if ( $this->m_graphLegend && $this->m_graphColor ) {
139
			$arrayCount = 0;
140
			$arraySize = count( $this->m_graphColors );
141
			$result .= "<P>";
142
143
			foreach ( $this->m_labelArray as $m_label ) {
144
				if ( $arrayCount >= $arraySize ) {
145
					$arrayCount = 0;
146
				}
147
148
				$color = $this->m_graphColors[$arrayCount];
149
				$result .= "<font color=$color>$color: $m_label </font><br />";
150
151
				$arrayCount += 1;
152
			}
153
154
			$result .= "</P>";
155
		}
156
157
		return $result;
158
	}
159
160
	/**
161
	 * Returns the GV for a single subject.
162
	 *
163
	 * @since 1.5.4
164
	 *
165
	 * @param array $row
166
	 * @param $outputmode
167
	 *
168
	 * @return string
169
	 */
170
	protected function getGVForItem( array /* of SMWResultArray */
171
	$row, $outputmode ) {
172
		$segments = [];
173
174
		// Loop throught all fields of the record.
175
		foreach ( $row as $i => $resultArray ) {
176
177
			// Loop throught all the parts of the field value.
178
			while ( ( $object = $resultArray->getNextDataValue() ) !== false ) {
179
				$propName = $resultArray->getPrintRequest()->getLabel();
180
				$isName = $this->m_nameProperty ? ( $i != 0 && $this->m_nameProperty === $propName ) : $i == 0;
181
182
				if ( $isName ) {
183
					$name = $this->getWordWrappedText( $object->getShortText( $outputmode ), $this->m_wordWrapLimit );
184
				}
185
186
				if ( !( $this->m_nameProperty && $i == 0 ) ) {
187
					$segments[] = $this->getGVForDataValue( $object, $outputmode, $isName, $name, $propName );
0 ignored issues
show
The variable $name 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...
188
				}
189
			}
190
		}
191
192
		return implode( "\n", $segments );
193
	}
194
195
	/**
196
	 * Returns the GV for a single SMWDataValue.
197
	 *
198
	 * @since 1.5.4
199
	 *
200
	 * @param SMWDataValue $object
201
	 * @param $outputmode
202
	 * @param boolean $isName Is this the name that should be used for the node?
203
	 * @param string $name
204
	 * @param string $labelName
205
	 *
206
	 * @return string
207
	 */
208
	protected function getGVForDataValue( SMWDataValue $object, $outputmode, $isName, $name, $labelName ) {
209
		$graphInput = '';
210
		$text = $object->getShortText( $outputmode );
211
212
		if ( $this->m_graphLink ) {
213
			$nodeLinkURL = "[[" . $text . "]]";
214
		}
215
216
		$text = $this->getWordWrappedText( $text, $this->m_wordWrapLimit );
217
218
		if ( $this->m_graphLink ) {
219
			$graphInput .= " \"$text\" [URL = \"$nodeLinkURL\"]; ";
0 ignored issues
show
The variable $nodeLinkURL 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...
220
		}
221
222
		if ( !$isName ) {
223
			$graphInput .= $this->m_parentRelation ? " \"$text\" -> \"$name\" " : " \"$name\" -> \"$text\" ";
224
225
			if ( $this->m_graphLabel || $this->m_graphColor ) {
226
				$graphInput .= ' [';
227
228
				if ( array_search( $labelName, $this->m_labelArray, true ) === false ) {
229
					$this->m_labelArray[] = $labelName;
230
				}
231
232
				$color = $this->m_graphColors[array_search( $labelName, $this->m_labelArray, true )];
233
234
				if ( $this->m_graphLabel ) {
235
					$graphInput .= "label=\"$labelName\"";
236
					if ( $this->m_graphColor ) {
237
						$graphInput .= ",fontcolor=$color,";
238
					}
239
				}
240
241
				if ( $this->m_graphColor ) {
242
					$graphInput .= "color=$color";
243
				}
244
245
				$graphInput .= ']';
246
247
			}
248
249
			$graphInput .= ';';
250
		}
251
252
		return $graphInput;
253
	}
254
255
	/**
256
	 * Returns the word wrapped version of the provided text.
257
	 *
258
	 * @since 1.5.4
259
	 *
260
	 * @param string $text
261
	 * @param integer $charLimit
262
	 *
263
	 * @return string
264
	 */
265
	protected function getWordWrappedText( $text, $charLimit ) {
266
		$charLimit = max( [ $charLimit, 1 ] );
267
		$segments = [];
268
269
		while ( strlen( $text ) > $charLimit ) {
270
			// Find the last space in the allowed range.
271
			$splitPosition = strrpos( substr( $text, 0, $charLimit ), ' ' );
272
273
			if ( $splitPosition === false ) {
274
				// If there is no space (lond word), find the next space.
275
				$splitPosition = strpos( $text, ' ' );
276
277
				if ( $splitPosition === false ) {
278
					// If there are no spaces, everything goes on one line.
279
					$splitPosition = strlen( $text ) - 1;
280
				}
281
			}
282
283
			$segments[] = substr( $text, 0, $splitPosition + 1 );
284
			$text = substr( $text, $splitPosition + 1 );
285
		}
286
287
		$segments[] = $text;
288
289
		return implode( '\n', $segments );
290
	}
291
292
	/**
293
	 * (non-PHPdoc)
294
	 * @see SMWResultPrinter::getName()
295
	 */
296
	public function getName() {
297
		return wfMessage( 'srf-printername-graph' )->text();
298
	}
299
300
	/**
301
	 * @see SMWResultPrinter::getParamDefinitions
302
	 *
303
	 * @since 1.8
304
	 *
305
	 * @param $definitions array of IParamDefinition
306
	 *
307
	 * @return array of IParamDefinition|array
308
	 */
309
	public function getParamDefinitions( array $definitions ) {
310
		$params = parent::getParamDefinitions( $definitions );
311
312
		$params['graphname'] = [
313
			'default' => 'QueryResult',
314
			'message' => 'srf-paramdesc-graphname',
315
		];
316
317
		$params['graphsize'] = [
318
			'type' => 'string',
319
			'default' => '',
320
			'message' => 'srf-paramdesc-graphsize',
321
			'manipulatedefault' => false,
322
		];
323
324
		$params['graphlegend'] = [
325
			'type' => 'boolean',
326
			'default' => false,
327
			'message' => 'srf-paramdesc-graphlegend',
328
		];
329
330
		$params['graphlabel'] = [
331
			'type' => 'boolean',
332
			'default' => false,
333
			'message' => 'srf-paramdesc-graphlabel',
334
		];
335
336
		$params['graphlink'] = [
337
			'type' => 'boolean',
338
			'default' => false,
339
			'message' => 'srf-paramdesc-graphlink',
340
		];
341
342
		$params['graphcolor'] = [
343
			'type' => 'boolean',
344
			'default' => false,
345
			'message' => 'srf-paramdesc-graphcolor',
346
		];
347
348
		$params['arrowdirection'] = [
349
			'aliases' => 'rankdir',
350
			'default' => 'LR',
351
			'message' => 'srf-paramdesc-rankdir',
352
			'values' => [ 'LR', 'RL', 'TB', 'BT' ],
353
		];
354
355
		$params['nodeshape'] = [
356
			'default' => false,
357
			'message' => 'srf-paramdesc-graph-nodeshape',
358
			'manipulatedefault' => false,
359
			'values' => self::$NODE_SHAPES,
360
		];
361
362
		$params['relation'] = [
363
			'default' => 'child',
364
			'message' => 'srf-paramdesc-graph-relation',
365
			'manipulatedefault' => false,
366
			'values' => [ 'parent', 'child' ],
367
		];
368
369
		$params['nameproperty'] = [
370
			'default' => false,
371
			'message' => 'srf-paramdesc-graph-nameprop',
372
			'manipulatedefault' => false,
373
		];
374
375
		$params['wordwraplimit'] = [
376
			'type' => 'integer',
377
			'default' => 25,
378
			'message' => 'srf-paramdesc-graph-wwl',
379
			'manipulatedefault' => false,
380
		];
381
382
		return $params;
383
	}
384
385
}
386