SRFExhibit   F
last analyzed

Complexity

Total Complexity 97

Size/Duplication

Total Lines 614
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 97
lcom 1
cbo 3
dl 0
loc 614
ccs 0
cts 521
cp 0
rs 1.986
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A getResult() 0 5 1
A encodePropertyName() 0 3 1
A determineNamespace() 0 17 4
F getResultText() 0 551 90
A getParamDefinitions() 0 13 1

How to fix   Complexity   

Complex Class

Complex classes like SRFExhibit 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 SRFExhibit, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Use Exhibit to print query results.
4
 *
5
 * @author Fabian Howahl
6
 * @file
7
 * @ingroup SMWQuery
8
 */
9
10
/**
11
 * Result printer using Exhibit to display query results
12
 *
13
 * @ingroup SMWQuery
14
 */
15
class SRFExhibit extends SMWResultPrinter {
16
17
	// /mapping between SMW's and Exhibit's the data types
18
	protected $m_types = [ "_wpg" => "text", "_num" => "number", "_dat" => "date", "_geo" => "text", "_uri" => "url" ];
19
20
	protected static $exhibitRunningNumber = 0; // not sufficient since there might be multiple pages rendered within one PHP run; but good enough now
21
22
	// /overwrite function to allow execution of result printer even if no results are available (in case remote query yields no results in local wiki)
23
	public function getResult( $results, $params, $outputmode ) {
24
		$this->readParameters( $params, $outputmode );
25
		$result = $this->getResultText( $results, $outputmode );
26
		return $result;
27
	}
28
29
	// /function aligns the format of SMW's property names to Exhibit's format
30
	protected function encodePropertyName( $property ) {
31
		return strtolower( str_replace( " ", "_", trim( $property ) ) );
32
	}
33
34
	// /Tries to determine the namespace in the event it got lost
35
	protected function determineNamespace( $res ) {
36
		$row = $res->getNext();
37
		if ( $row != null ) {
38
			$tmp = clone $row[0];
39
			$object = $tmp->getNextDataValue();
40
41
			if ( $object instanceof SMWWikiPageValue ) {
42
				$value = $object->getPrefixedText();
43
				if ( strpos( $value, ':' ) ) {
44
					$value = explode( ':', $value, 2 );
45
					return $value[0] . ':';
46
				}
47
			}
48
		}
49
50
		return "";
51
	}
52
53
	protected function getResultText( SMWQueryResult $res, $outputmode ) {
54
55
		global $smwgIQRunningNumber, $wgScriptPath, $wgGoogleMapsKey, $srfgScriptPath;
56
57
		if ( defined( 'MW_SUPPORTS_RESOURCE_MODULES' ) ) {
58
			SMWOutputs::requireHeadItem( 'exhibit-compat', Html::linkedScript( "$wgScriptPath/common/wikibits.js" ) );
59
		}
60
61
		// //////////////////////////////
62
		// ///////REMOTE STUFF///////////
63
		// //////////////////////////////
64
65
		$remote = false;
66
67
		// in case the remote parameter is set, a link to the JSON export of the remote wiki is included in the header as data source for Exhibit
68
		// this section creates the link
69
		if ( array_key_exists( 'remote', $this->params ) && srfgExhibitRemote == true ) {
70
71
			$remote = true;
72
73
			// fetch interwiki link
74
			$dbr = &wfGetDB( DB_SLAVE );
75
			$cl = $dbr->tableName( 'interwiki' );
76
			$dbres = $dbr->select( $cl, 'iw_url', "iw_prefix='" . $this->params['remote'] . "'", __METHOD__, [] );
77
			$row = $dbr->fetchRow( $dbres );
78
			$extlinkpattern = $row[iw_url];
79
			$dbr->freeResult( $dbres );
80
81
			$newheader = '<link rel="exhibit/data" type="application/jsonp" href="';
82
			$link = $res->getQueryLink( 'JSON Link' );
83
			$link->setParameter( 'json', 'format' );
84
85
			if ( array_key_exists(
86
				'callback',
87
				$this->params
88
			) ) { // check if a special name for the callback function is set, if not stick with 'callback'
89
				$callbackfunc = $this->params['callback'];
90
			} else {
91
				$callbackfunc = 'callback';
92
			}
93
94
			if ( array_key_exists( 'limit', $this->params ) ) {
95
				$link->setParameter( $this->params['limit'], 'limit' );
96
			}
97
98
			$link->setParameter( $callbackfunc, 'callback' );
99
			$link = $link->getText( 2, $this->mLinker );
100
101
			list( $link, $trash ) = explode( '|', $link );
0 ignored issues
show
Unused Code introduced by Jeroen De Dauw
The assignment to $trash is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
102
			$link = str_replace( '[[:', '', $link );
103
104
			$newheader .= str_replace( '$1', $link, $extlinkpattern );
105
			$newheader .= '" ex:jsonp-callback="' . $callbackfunc . '"';
106
			$newheader .= '/>';
107
108
			SMWOutputs::requireHeadItem( 'REMOTE', $newheader );
109
		}
110
111
		// the following variables indicate the use of special views
112
		// the variable's values define the way Exhibit is called
113
		$timeline = false;
114
		$map = false;
115
116
		/*The javascript file adopted from Wibbit uses a bunch of javascript variables in the header to store information about the Exhibit markup.
117
		 The following code sequence creates these variables*/
118
119
		// prepare sources (the sources holds information about the table which contains the information)
120
		$colstack = [];
121
		foreach ( $res->getPrintRequests() as $pr ) {
122
			$colstack[] = $this->encodePropertyName( $pr->getLabel() ) . ':' . ( array_key_exists(
123
					$pr->getTypeID(),
124
					$this->m_types
125
				) ? $this->m_types[$pr->getTypeID()] : 'text' );
126
		}
127
		array_shift( $colstack );
128
		array_unshift( $colstack, 'label' );
129
130
		if ( SRFExhibit::$exhibitRunningNumber == 0 ) {
131
			$sourcesrc = "var ex_sources = { source" . ( $smwgIQRunningNumber - 1 ) . ": { id:  'querytable" . $smwgIQRunningNumber . "' , columns: '" . implode(
132
					',',
133
					$colstack
134
				) . "'.split(','), hideTable: '1', type: 'Item', label: 'Item', pluralLabel: 'Items' } };";
135
		} else {
136
			$sourcesrc = "sources.source" . $smwgIQRunningNumber . " =  { id:  'querytable" . $smwgIQRunningNumber . "' , columns: '" . implode(
137
					',',
138
					$colstack
139
				) . "'.split(','), hideTable: '1', type: 'Item', label: 'Item', pluralLabel: 'Items' };";
140
		}
141
		$sourcesrc = "<script type=\"text/javascript\">" . $sourcesrc . "</script>";
142
143
		// prepare facets
144
		$facetcounter = 0;
145
		if ( array_key_exists( 'facets', $this->params ) ) {
146
			$facets = explode( ',', $this->params['facets'] );
147
			$facetstack = [];
148
			$params = [ 'height' ];
149
			$facparams = [];
150
			foreach ( $params as $param ) {
151
				if ( array_key_exists( $param, $this->params ) ) {
152
					$facparams[] = 'ex:' . $param . '="' . $this->encodePropertyName( $this->params[$param] ) . '" ';
153
				}
154
			}
155
			foreach ( $facets as $facet ) {
156
				$facet = trim( $facet );
157
				if ( strtolower( $facet ) == "search" ) { // special facet (text search)
158
					$facetstack[] = ' facet' . $facetcounter++ . ': { position : "right", innerHTML: \'ex:role="facet" ex:showMissing="false" ex:facetClass="TextSearch" ex:facetLabel="' . $facet . '"\'}';
159
				} else { // usual facet
160
					foreach ( $res->getPrintRequests() as $pr ) {
161
						if ( $this->encodePropertyName( $pr->getLabel() ) == $this->encodePropertyName( $facet ) ) {
162
							switch ( $pr->getTypeID() ) {
163
								case '_num':
164
									$facetstack[] = ' facet' . $facetcounter++ . ': { position : "right", innerHTML: \'ex:role="facet" ex:showMissing="false" ex:expression=".' . $this->encodePropertyName(
165
											$facet
166
										) . '" ex:facetLabel="' . $facet . '" ex:facetClass="Slider"\'}';
167
									break;
168
								default:
169
									$facetstack[] = ' facet' . $facetcounter++ . ': { position : "right", innerHTML: \'ex:role="facet" ex:showMissing="false" ' . implode(
170
											" ",
171
											$facparams
172
										) . ' ex:expression=".' . $this->encodePropertyName(
173
											$facet
174
										) . '" ex:facetLabel="' . $facet . '"\'}';
175
							}
176
						}
177
178
					}
179
				}
180
			}
181
			$facetstring = implode( ',', $facetstack );
182
		} else {
183
			$facetstring = '';
184
		}
185
		$facetsrc = "var ex_facets = {" . $facetstring . " };";
186
187
		// prepare views
188
		$stylesrc = '';
189
		if ( array_key_exists( 'views', $this->params ) ) {
190
			$views = explode( ',', $this->params['views'] );
191
		} else {
192
			$views[] = 'tiles';
0 ignored issues
show
Coding Style Comprehensibility introduced by Jeroen De Dauw
$views was never initialized. Although not strictly required by PHP, it is generally a good practice to add $views = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
193
		}
194
195
		foreach ( $views as $view ) {
196
			switch ( trim( $view ) ) {
197
				case 'tabular':// table view (the columns are automatically defined by the selected properties)
198
					$thstack = [];
199
					foreach ( $res->getPrintRequests() as $pr ) {
200
						$thstack[] = "." . $this->encodePropertyName( $pr->getLabel() );
201
					}
202
					array_shift( $thstack );
203
					array_unshift( $thstack, '.label' );
204
					$stylesrc = 'var myStyler = function(table, database) {table.className=\'smwtable\';};'; // assign SMWtable CSS to Exhibit tabular view
205
					$viewstack[] = 'ex:role=\'view\' ex:viewClass=\'Tabular\' ex:showSummary=\'false\' ex:sortAscending=\'true\' ex:tableStyler=\'myStyler\'  ex:label=\'Table\' ex:columns=\'' . implode(
0 ignored issues
show
Coding Style Comprehensibility introduced by Jeroen De Dauw
$viewstack was never initialized. Although not strictly required by PHP, it is generally a good practice to add $viewstack = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
206
							',',
207
							$thstack
208
						) . '\' ex:sortAscending=\'false\'';
209
					break;
210
				case 'timeline':// timeline view
211
					$timeline = true;
212
					$exparams = [
213
						'start',
214
						'end',
215
						'proxy',
216
						'colorkey' ]; // parameters expecting an Exhibit graph expression
217
					$usparams = [
218
						'timelineheight',
219
						'topbandheight',
220
						'bottombandheight',
221
						'bottombandunit',
222
						'topbandunit' ]; // parametes expecting a textual or numeric value
223
					$tlparams = [];
224
					foreach ( $exparams as $param ) {
225
						if ( array_key_exists( $param, $this->params ) ) {
226
							$tlparams[] = 'ex:' . $param . '=\'.' . $this->encodePropertyName(
227
									$this->params[$param]
228
								) . '\' ';
229
						}
230
					}
231
					foreach ( $usparams as $param ) {
232
						if ( array_key_exists( $param, $this->params ) ) {
233
							$tlparams[] = 'ex:' . $param . '=\'' . $this->encodePropertyName(
234
									$this->params[$param]
235
								) . '\' ';
236
						}
237
					}
238
					if ( !array_key_exists(
239
						'start',
240
						$this->params
241
					) ) {// find out if a start and/or end date is specified
242
						$dates = [];
243
						foreach ( $res->getPrintRequests() as $pr ) {
244
							if ( $pr->getTypeID() == '_dat' ) {
245
								$dates[] = $pr;
246
								if ( sizeof( $dates ) > 2 ) {
247
									break;
248
								}
249
							}
250
						}
251
						if ( sizeof( $dates ) == 1 ) {
252
							$tlparams[] = 'ex:start=\'.' . $this->encodePropertyName( $dates[0]->getLabel() ) . '\' ';
253
						} elseif ( sizeof( $dates ) == 2 ) {
254
							$tlparams[] = 'ex:start=\'.' . $this->encodePropertyName( $dates[0]->getLabel() ) . '\' ';
255
							$tlparams[] = 'ex:end=\'.' . $this->encodePropertyName( $dates[1]->getLabel() ) . '\' ';
256
						}
257
					}
258
					$viewstack[] = 'ex:role=\'view\' ex:viewClass=\'Timeline\' ex:label=\'Timeline\' ex:showSummary=\'false\' ' . implode(
0 ignored issues
show
Bug introduced by Jeroen De Dauw
The variable $viewstack 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...
259
							" ",
260
							$tlparams
261
						);
262
					break;
263
				case 'map':// map view
264
					if ( isset( $wgGoogleMapsKey ) ) {
265
						$map = true;
266
						$exparams = [ 'latlng', 'colorkey' ];
267
						$usparams = [
268
							'type',
269
							'center',
270
							'zoom',
271
							'size',
272
							'scalecontrol',
273
							'overviewcontrol',
274
							'mapheight' ];
275
						$mapparams = [];
276
						foreach ( $exparams as $param ) {
277
							if ( array_key_exists( $param, $this->params ) ) {
278
								$mapparams[] = 'ex:' . $param . '=\'.' . $this->encodePropertyName(
279
										$this->params[$param]
280
									) . '\' ';
281
							}
282
						}
283
						foreach ( $usparams as $param ) {
284
							if ( array_key_exists( $param, $this->params ) ) {
285
								$mapparams[] = 'ex:' . $param . '=\'' . $this->encodePropertyName(
286
										$this->params[$param]
287
									) . '\' ';
288
							}
289
						}
290
						if ( !array_key_exists( 'start', $this->params ) && !array_key_exists(
291
								'end',
292
								$this->params
293
							) ) { // find out if a geographic coordinate is available
294
							foreach ( $res->getPrintRequests() as $pr ) {
295
								if ( $pr->getTypeID() == '_geo' ) {
296
									$mapparams[] = 'ex:latlng=\'.' . $this->encodePropertyName(
297
											$pr->getLabel()
298
										) . '\' ';
299
									break;
300
								}
301
							}
302
						}
303
						$viewstack[] .= 'ex:role=\'view\' ex:viewClass=\'Map\' ex:showSummary=\'false\' ex:label=\'Map\' ' . implode(
304
								" ",
305
								$mapparams
306
							);
307
					}
308
					break;
309
				default:
310
				case 'tiles':// tile view
0 ignored issues
show
Unused Code introduced by Jeroen De Dauw
case 'tiles': $sorts...$sortstring; break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
311
					$sortstring = '';
312
					if ( array_key_exists( 'sort', $this->params ) ) {
313
						$sortfields = explode( ",", $this->params['sort'] );
314
						foreach ( $sortfields as $field ) {
315
							$sortkeys[] = "." . $this->encodePropertyName( trim( $field ) );
316
						}
317
						$sortstring = 'ex:orders=\'' . implode( ",", $sortkeys ) . '\' ';
318
						if ( array_key_exists( 'order', $this->params ) ) {
319
							$sortstring .= ' ex:directions=\'' . $this->encodePropertyName(
320
									$this->params['order']
321
								) . '\'';
322
						}
323
						if ( array_key_exists( 'grouped', $this->params ) ) {
324
							$sortstring .= ' ex:grouped=\'' . $this->encodePropertyName(
325
									$this->params['grouped']
326
								) . '\'';
327
						}
328
					}
329
					$viewstack[] = 'ex:role=\'view\' ex:showSummary=\'false\' ' . $sortstring;
330
					break;
331
			}
332
		}
333
334
		$viewsrc = 'var ex_views = "' . implode( "/", $viewstack ) . '".split(\'/\');;';
335
336
		// prepare automatic lenses
337
338
		global $wgParser;
339
		$lenscounter = 0;
340
		$linkcounter = 0;
341
		$imagecounter = 0;
342
343
		if ( array_key_exists(
344
			'lens',
345
			$this->params
346
		) ) {// a customized lens is specified via the lens parameter within the query
347
			$lenstitle = Title::newFromText( "Template:" . $this->params['lens'] );
348
			$lensarticle = new Article( $lenstitle );
349
			$lenswikitext = $lensarticle->getContent();
350
351
			if ( preg_match_all(
352
				"/[\[][\[][Ii][m][a][g][e][:][{][{][{][1-9A-z\-[:space:]]*[}][}][}][\]][\]]/u",
353
				$lenswikitext,
354
				$matches
355
			) ) {
356
				foreach ( $matches as $match ) {
357
					foreach ( $match as $value ) {
358
						$strippedvalue = trim( substr( $value, 8 ), "[[{}]]" );
359
						$lenswikitext = str_replace(
360
							$value,
361
							'<div class="inlines" id="imagecontent' . $imagecounter . '">' . $this->encodePropertyName(
362
								strtolower( str_replace( "\n", "", $strippedvalue ) )
363
							) . '</div>',
364
							$lenswikitext
365
						);
366
						$imagecounter++;
367
					}
368
				}
369
			}
370
371
			if ( preg_match_all(
372
				"/[\[][\[][{][{][{][1-9A-z\-[:space:]]*[}][}][}][\]][\]]/u",
373
				$lenswikitext,
374
				$matches
375
			) ) {
376
				foreach ( $matches as $match ) {
377
					foreach ( $match as $value ) {
378
						$strippedvalue = trim( $value, "[[{}]]" );
379
						$lenswikitext = str_replace(
380
							$value,
381
							'<div class="inlines" id="linkcontent' . $linkcounter . '">' . $this->encodePropertyName(
382
								strtolower( str_replace( "\n", "", $strippedvalue ) )
383
							) . '</div>',
384
							$lenswikitext
385
						);
386
						$linkcounter++;
387
					}
388
				}
389
			}
390
391
			if ( preg_match_all( "/[{][{][{][1-9A-z\:\|\/\=\-[:space:]]*[}][}][}]/u", $lenswikitext, $matches ) ) {
392
				foreach ( $matches as $match ) {
393
					foreach ( $match as $value ) {
394
						$strippedvalue = trim( $value, "{}" );
395
						$lenswikitext = str_replace(
396
							$value,
397
							'<div class="inlines" id="lenscontent' . $lenscounter . '">' . $this->encodePropertyName(
398
								strtolower( str_replace( "\n", "", $strippedvalue ) )
399
							) . '</div>',
400
							$lenswikitext
401
						);
402
						$lenscounter++;
403
					}
404
				}
405
			}
406
407
			$lenshtml = $wgParser->internalParse(
408
				$lenswikitext
409
			);// $wgParser->parse($lenswikitext, $lenstitle, new ParserOptions(), true, true)->getText();
410
411
			$lenssrc = "var ex_lens = '" . str_replace(
412
					"\n",
413
					"",
414
					$lenshtml
415
				) . "';ex_lenscounter =" . $lenscounter . ";ex_linkcounter=" . $linkcounter . ";ex_imagecounter=" . $imagecounter . ";";
416
		} else {// generic lens (creates links to further content (property-pages, pages about values)
417
			foreach ( $res->getPrintRequests() as $pr ) {
418
				if ( $remote ) {
419
					$wikiurl = str_replace( "$1", "", $extlinkpattern );
0 ignored issues
show
Bug introduced by Jeroen De Dauw
The variable $extlinkpattern 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...
420
				} else {
421
					$wikiurl = $wgScriptPath . "/index.php?title=";
422
				}
423
				if ( $pr->getTypeID() == '_wpg' ) {
424
					$prefix = '';
425
					if ( $pr->getLabel() == 'Category' ) {
426
						$prefix = "Category:";
427
					}
428
					$lensstack[] = '<tr ex:if-exists=".' . $this->encodePropertyName(
0 ignored issues
show
Coding Style Comprehensibility introduced by Jeroen De Dauw
$lensstack was never initialized. Although not strictly required by PHP, it is generally a good practice to add $lensstack = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
429
							$pr->getLabel()
430
						) . '"><td width="20%">' . $pr->getText(
431
							0,
432
							$this->mLinker
433
						) . '</td><td width="80%" ex:content=".' . $this->encodePropertyName(
434
							$pr->getLabel()
435
						) . '"><a ex:href-subcontent="' . $wikiurl . $prefix . '{{urlencval(value)}}"><div ex:content="value" class="name"></div></a></td></tr>';
436
				} else {
437
					$lensstack[] = '<tr ex:if-exists=".' . $this->encodePropertyName(
0 ignored issues
show
Bug introduced by Jeroen De Dauw
The variable $lensstack 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...
438
							$pr->getLabel()
439
						) . '"><td width="20%">' . $pr->getText(
440
							0,
441
							$this->mLinker
442
						) . '</td><td width="80%"><div ex:content=".' . $this->encodePropertyName(
443
							$pr->getLabel()
444
						) . '" class="name"></div></td></tr>';
445
				}
446
			}
447
			array_shift( $lensstack );
448
			$lenssrc = 'var ex_lens = \'<table width=100% cellpadding=3><tr><th class="head" align=left bgcolor="#DDDDDD"><a ex:href-subcontent="' . $wikiurl . $this->determineNamespace(
0 ignored issues
show
Bug introduced by Jeroen De Dauw
The variable $wikiurl 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...
449
					clone $res
450
				) . '{{urlenc(.label)}}" class="linkhead"><div ex:content=".label" class="name"></div></a></th></tr></table><table width="100%" cellpadding=3>' . implode(
451
					"",
452
					$lensstack
453
				) . '</table>\'; ex_lenscounter = 0; ex_linkcounter=0; ex_imagecounter=0;';
454
		}
455
456
		if ( $remote ) {
457
			$varremote = 'true';
458
		} else {
459
			$varremote = 'false';
460
		}
461
462
		// Handling special formats like date
463
		$formatssrc = 'var formats =\'\'';
464
		if ( array_key_exists( 'date', $this->params ) ) {
465
			$formatssrc = 'var formats = \'ex:formats="date { mode:' . $this->params['date'] . '; show:date }"\';';
466
		}
467
468
		// create a URL pointing to the corresponding JSON feed
469
		$label = '';
470
		$JSONlink = $res->getQueryLink( $label );
471
		if ( $this->getSearchLabel( SMW_OUTPUT_WIKI ) != '' ) { // used as a file name
472
			$link->setParameter( $this->getSearchLabel( SMW_OUTPUT_WIKI ), 'searchlabel' );
0 ignored issues
show
Bug introduced by Jeroen De Dauw
The variable $link 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...
473
		}
474
		if ( array_key_exists( 'limit', $this->params ) ) {
475
			$JSONlink->setParameter( htmlspecialchars( $this->params['limit'] ), 'limit' );
476
		}
477
		$JSONlink->setParameter( 'json', 'format' );
478
		$stringtoedit = explode( "|", $JSONlink->getText( $outputmode, $this->mLinker ) );
479
		$stringtoedit = substr( $stringtoedit[0], 3 );
480
		$JSONlinksrc = "var JSONlink = '" . $stringtoedit . "';";
481
482
		// create script header with variables containing the Exhibit markup
483
		$headervars = "<script type='text/javascript'>\n\t\t\t" . $facetsrc . "\n\t\t\t" . $viewsrc . "\n\t\t\t" . $lenssrc . "\n\t\t\t" . $stylesrc . "\n\t\t\t" . $formatssrc . "\n\t\t\t" . $JSONlinksrc . "\n\t\t\t var remote=" . $varremote . ";</script>";
484
485
		// To run Exhibit some links to the scripts of the API need to be included in the header
486
487
		$ExhibitScriptSrc1 = '<script type="text/javascript" src="' . $srfgScriptPath . '/Exhibit/exhibit/exhibit-api.js?autoCreate=false&safe=true&bundle=false';
488
		if ( $timeline ) {
489
			$ExhibitScriptSrc1 .= '&views=timeline';
490
		}
491
		if ( $map ) {
492
			$ExhibitScriptSrc1 .= '&gmapkey=' . $wgGoogleMapsKey;
493
		}
494
		$ExhibitScriptSrc1 .= '"></script>';
495
		$ExhibitScriptSrc2 = '<script type="text/javascript" src="' . $srfgScriptPath . '/Exhibit/SRF_Exhibit.js"></script>';
496
		$CSSSrc = '<link rel="stylesheet" type="text/css" href="' . $srfgScriptPath . '/Exhibit/SRF_Exhibit.css"></link>';
497
498
		SMWOutputs::requireHeadItem( 'CSS', $CSSSrc ); // include CSS
499
		SMWOutputs::requireHeadItem( 'EXHIBIT1', $ExhibitScriptSrc1 ); // include Exhibit API
500
		SMWOutputs::requireHeadItem(
501
			'EXHIBIT2',
502
			$ExhibitScriptSrc2
503
		); // includes javascript overwriting the Exhibit start-up functions
504
		SMWOutputs::requireHeadItem( 'SOURCES' . $smwgIQRunningNumber, $sourcesrc );// include sources variable
505
		SMWOutputs::requireHeadItem( 'VIEWSFACETS', $headervars );// include views and facets variable
506
507
		if ( !$remote ) {
508
509
			// print input table
510
			// print header
511
			$result = "<table style=\"display:none\" class=\"smwtable\" id=\"querytable" . $smwgIQRunningNumber . "\">\n";
512
			if ( $this->mShowHeaders ) { // building headers
513
				$result .= "\t<tr>\n";
514
				foreach ( $res->getPrintRequests() as $pr ) {
515
					if ( $pr->getText( $outputmode, $this->getLinker( 0 ) ) == '' ) {
516
						$headerlabel = "Name";
517
					} else {
518
						$headerlabel = $pr->getText( $outputmode, $this->getLinker( 0 ) );
519
					}
520
					$result .= "\t\t<th>" . $headerlabel . "</th>\n";
521
				}
522
				$result .= "\t</tr>\n";
523
			}
524
525
			// print all result rows
526
			while ( $row = $res->getNext() ) {
527
				$result .= "\t<tr>\n";
528
				foreach ( $row as $field ) {
529
					$result .= "\t\t<td>";
530
					$textstack = [];
531
					while ( ( $object = $field->getNextDataValue() ) !== false ) {
532
						switch ( $object->getTypeID() ) {
533
							case '_wpg':
534
								$textstack[] = $object->getLongText( $outputmode, $this->getLinker( 0 ) );
535
								break;
536
							case '_geo':
537
								$c = $object->getDBKeys();
538
								$textstack[] = $c[0] . "," . $c[1];
539
								break;
540
							case '_num':
541
								if ( method_exists( $object, 'getValueKey' ) ) {
542
									$textstack[] = $object->getValueKey( $outputmode, $this->getLinker( 0 ) );
543
								} else {
544
									$textstack[] = $object->getNumericValue( $outputmode, $this->getLinker( 0 ) );
545
								}
546
								break;
547
							case '_dat':
548
								$textstack[] = $object->getYear() . "-" . str_pad(
549
										$object->getMonth(),
550
										2,
551
										'0',
552
										STR_PAD_LEFT
553
									) . "-" . str_pad(
554
										$object->getDay(),
555
										2,
556
										'0',
557
										STR_PAD_LEFT
558
									) . " " . $object->getTimeString();
559
								break;
560
							case '_ema':
561
								$textstack[] = $object->getShortWikiText( $this->getLinker( 0 ) );
562
								break;
563
							case '_tel':
564
							case '_anu':
565
							case '_uri':
566
								$textstack[] = $object->getWikiValue();
567
								break;
568
							case '__sin':
569
								$tmp = $object->getShortText( $outputmode, null );
570
								if ( strpos( $tmp, ":" ) ) {
571
									$tmp = explode( ":", $tmp, 2 );
572
									$tmp = $tmp[1];
573
								}
574
								$textstack[] = $tmp;
575
								break;
576
							case '_txt':
577
							case '_cod':
578
							case '_str':
579
								$textstack[] = $object->getWikiValue();
580
								break;
581
							default:
582
								$textstack[] = $object->getLongHTMLText( $this->getLinker( 0 ) );
583
						}
584
					}
585
586
					if ( $textstack != null ) {
587
						$result .= implode( ';', $textstack ) . "</td>\n";
588
					} else {
589
						$result .= "</td>\n";
590
					}
591
				}
592
				$result .= "\t</tr>\n";
593
			}
594
			$result .= "</table>\n";
595
		}
596
597
		if ( SRFExhibit::$exhibitRunningNumber == 0 ) {
598
			$result .= "<div id=\"exhibitLocation\"></div>";
0 ignored issues
show
Bug introduced by Jeroen De Dauw
The variable $result 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...
599
		} // print placeholder (just print it one time)
600
		$this->isHTML = ( $outputmode == SMW_OUTPUT_HTML ); // yes, our code can be viewed as HTML if requested, no more parsing needed
601
		SRFExhibit::$exhibitRunningNumber++;
602
		return $result;
603
	}
604
605
	/**
606
	 * @see SMWResultPrinter::getParamDefinitions
607
	 *
608
	 * @since 1.8
609
	 *
610
	 * @param $definitions array of IParamDefinition
611
	 *
612
	 * @return array of IParamDefinition|array
613
	 */
614
	public function getParamDefinitions( array $definitions ) {
615
		$params = parent::getParamDefinitions( $definitions );
616
617
		$params[] = [
618
			'name' => 'views',
619
			'message' => 'srf_paramdesc_views',
620
			'islist' => true,
621
			'values' => [ 'tiles', 'tabular', 'timeline', 'maps' ] ];
622
		$params[] = [ 'name' => 'facets', 'message' => 'srf_paramdesc_facets' ];
623
		$params[] = [ 'name' => 'lens', 'message' => 'srf_paramdesc_lens' ];
624
625
		return $params;
626
	}
627
628
}
629