Completed
Pull Request — master (#579)
by
unknown
05:37
created

GraphPrinter::processResultRow()   B

Complexity

Conditions 7
Paths 14

Size

Total Lines 35

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
dl 0
loc 35
ccs 0
cts 17
cp 0
rs 8.4266
c 0
b 0
f 0
cc 7
nc 14
nop 1
crap 56
1
<?php
2
3
namespace SRF\Graph;
4
5
use SMW\ResultPrinter;
6
use SMWQueryResult;
7
use SMWWikiPageValue;
8
use GraphViz;
9
use Html;
10
11
/**
12
 * SMW result printer for graphs using graphViz.
13
 * In order to use this printer you need to have both
14
 * the graphViz library installed on your system and
15
 * have the graphViz MediaWiki extension installed.
16
 *
17
 * @file SRF_Graph.php
18
 * @ingroup SemanticResultFormats
19
 *
20
 * @licence GNU GPL v2+
21
 * @author Frank Dengler
22
 * @author Jeroen De Dauw < [email protected] >
23
 * @author Sebastian Schmid
24
 */
25
class GraphPrinter extends ResultPrinter {
26
27
	//@see https://github.com/SemanticMediaWiki/SemanticMediaWiki/pull/4273
28
	// Implement `ResultPrinterDependency` once SMW 3.1 becomes mandatory
29
30
	const NODELABEL_DISPLAYTITLE = 'displaytitle';
31
	public static $NODE_LABELS = [
32
		self::NODELABEL_DISPLAYTITLE,
33
	];
34
35
	public static $NODE_SHAPES = [
36
		'box',
37
		'box3d',
38
		'circle',
39
		'component',
40
		'diamond',
41
		'doublecircle',
42
		'doubleoctagon',
43
		'egg',
44
		'ellipse',
45
		'folder',
46
		'hexagon',
47
		'house',
48
		'invhouse',
49
		'invtrapezium',
50
		'invtriangle',
51
		'Mcircle',
52
		'Mdiamond',
53
		'Msquare',
54
		'Mrecord',
55
		'none',
56
		'note',
57
		'octagon',
58
		'parallelogram',
59
		'pentagon ',
60
		'plaintext',
61
		'point',
62
		'polygon',
63
		'rect',
64
		'record',
65
		'rectangle',
66
		'septagon',
67
		'square',
68
		'tab',
69
		'trapezium',
70
		'triangle',
71
		'tripleoctagon',
72
	];
73
74
	public static $ARROW_SHAPES = [
75
		'box',
76
		'crow',
77
		'curve',
78
		'icurve',
79
		'diamond',
80
		'dot',
81
		'inv',
82
		'none',
83
		'normal',
84
		'tee',
85
		'vee',
86
	];
87
88
	private $nodes = [];
89
	private $options;
90
91
	public function getName() {
92
		return $this->msg( 'srf-printername-graph' )->text();
93
	}
94
95
	/**
96
	 * @see SMWResultPrinter::handleParameters()
97
	 */
98
	protected function handleParameters( array $params, $outputmode ) {
99
		parent::handleParameters( $params, $outputmode );
100
101
		$this->options = new GraphOptions($params);
102
	}
103
104
	/**
105
	 * @see ResultPrinterDependency::hasMissingDependency
106
	 *
107
	 * {@inheritDoc}
108
	 */
109
	public function hasMissingDependency() {
110
		return !class_exists( 'GraphViz' ) && !class_exists( '\\MediaWiki\\Extension\\GraphViz\\GraphViz' );
111
	}
112
113
	/**
114
	 * @see ResultPrinterDependency::getDependencyError
115
	 *
116
	 * {@inheritDoc}
117
	 */
118
	public function getDependencyError() {
119
		return Html::rawElement(
120
			'div',
121
			[
122
				'class' => 'smw-callout smw-callout-error'
123
			],
124
			'The SRF Graph printer requires the GraphViz extension to be installed.'
125
		);
126
	}
127
128
	/**
129
	 * @param SMWQueryResult $res
130
	 * @param $outputmode
131
	 *
132
	 * @return string
133
	 */
134
	protected function getResultText( SMWQueryResult $res, $outputmode ) {
135
136
		// Remove this once SRF requires 3.1+
137
		if ( $this->hasMissingDependency() ) {
138
			return $this->getDependencyError();
139
		}
140
141
		// iterate query result and create SRF\GraphNodes
142
		while ( $row = $res->getNext() ) {
143
			$this->processResultRow( $row );
144
		}
145
146
		// use GraphFormater to build the graph
147
		$graphFormatter = new GraphFormatter( $this->options );
148
		$graphFormatter->buildGraph( $this->nodes );
149
150
		// Calls graphvizParserHook function from MediaWiki GraphViz extension
151
		$result = $GLOBALS['wgParser']->recursiveTagParse( "<graphviz>" . $graphFormatter->getGraph
152
				() . "</graphviz>" );
153
154
		// append legend
155
		$result .= $graphFormatter->getGraphLegend();
156
157
		return $result;
158
	}
159
160
	/**
161
	 * Process a result row and create SRF\GraphNodes
162
	 *
163
	 * @since 3.1
164
	 *
165
	 * @param array $row
166
	 *
167
	 */
168
	protected function processResultRow( array /* of SMWResultArray */ $row ) {
169
170
		// loop through all row fields
171
		foreach ( $row as $i => $resultArray ) {
172
173
			// loop through all values of a multivalue field
174
			while ( ( /* SMWWikiPageValue */
175
				$object = $resultArray->getNextDataValue() ) !== false ) {
176
177
				$id = $object->getShortWikiText();
178
				$nodeExists = false;
179
180
				// check, if node has already been created
181
				/** @var GraphNode $node */
182
				foreach ( $this->nodes as $node ) {
183
					if ( $node->getID() == $id ) {
184
						$nodeExists = true;
185
						break;
186
					}
187
				}
188
189
				if ( !$nodeExists ) {
190
					$node = new GraphNode( $id );
191
					$node->setLabel( $object->getPreferredCaption() );
192
					$this->nodes[$id] = $node;
193
				}
194
195
				if ( $i == 0 ) {
196
					$parentId = $id;
197
				} else {
198
					$this->nodes[$id]->addParentNode( $resultArray->getPrintRequest()->getLabel(), $parentId );
0 ignored issues
show
Bug introduced by
The variable $parentId 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...
199
				}
200
			}
201
		}
202
	}
203
204
	/**
205
	 * @see SMWResultPrinter::getParamDefinitions
206
	 *
207
	 * @since 1.8
208
	 *
209
	 * @param $definitions array of IParamDefinition
210
	 *
211
	 * @return array of IParamDefinition|array
212
	 */
213
	public function getParamDefinitions( array $definitions ) {
214
		$params = parent::getParamDefinitions( $definitions );
215
216
		$params['graphname'] = [
217
			'default' => 'QueryResult',
218
			'message' => 'srf-paramdesc-graphname',
219
		];
220
221
		$params['graphsize'] = [
222
			'type' => 'string',
223
			'default' => '',
224
			'message' => 'srf-paramdesc-graphsize',
225
			'manipulatedefault' => false,
226
		];
227
228
		$params['graphfontsize'] = [
229
			'type' => 'integer',
230
			'default' => 10,
231
			'message' => 'srf-paramdesc-graphfontsize',
232
			'manipulatedefault' => false,
233
		];
234
235
		$params['graphlegend'] = [
236
			'type' => 'boolean',
237
			'default' => false,
238
			'message' => 'srf-paramdesc-graphlegend',
239
		];
240
241
		$params['graphlabel'] = [
242
			'type' => 'boolean',
243
			'default' => false,
244
			'message' => 'srf-paramdesc-graphlabel',
245
		];
246
247
		$params['graphlink'] = [
248
			'type' => 'boolean',
249
			'default' => false,
250
			'message' => 'srf-paramdesc-graphlink',
251
		];
252
253
		$params['graphcolor'] = [
254
			'type' => 'boolean',
255
			'default' => false,
256
			'message' => 'srf-paramdesc-graphcolor',
257
		];
258
259
		$params['arrowdirection'] = [
260
			'aliases' => 'rankdir',
261
			'default' => 'LR',
262
			'message' => 'srf-paramdesc-rankdir',
263
			'values'  => [ 'LR', 'RL', 'TB', 'BT' ],
264
		];
265
266
		$params['arrowhead'] = [
267
			'default' => 'normal',
268
			'message' => 'srf-paramdesc-arrowhead',
269
			'values' => self::$ARROW_SHAPES,
270
		];
271
272
		$params['nodeshape'] = [
273
			'default' => false,
274
			'message' => 'srf-paramdesc-graph-nodeshape',
275
			'manipulatedefault' => false,
276
			'values' => self::$NODE_SHAPES,
277
		];
278
279
		$params['relation'] = [
280
			'default' => 'child',
281
			'message' => 'srf-paramdesc-graph-relation',
282
			'manipulatedefault' => false,
283
			'values' => [ 'parent', 'child' ],
284
		];
285
286
		$params['wordwraplimit'] = [
287
			'type' => 'integer',
288
			'default' => 25,
289
			'message' => 'srf-paramdesc-graph-wwl',
290
			'manipulatedefault' => false,
291
		];
292
293
		$params['nodelabel'] = [
294
			'default' => '',
295
			'message' => 'srf-paramdesc-nodelabel',
296
			'values' => self::$NODE_LABELS,
297
		];
298
299
		return $params;
300
	}
301
}