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 ); |
|
|
|
|
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'; |
|
|
|
|
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( |
|
|
|
|
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( |
|
|
|
|
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 |
|
|
|
|
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 ); |
|
|
|
|
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( |
|
|
|
|
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( |
|
|
|
|
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( |
|
|
|
|
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' ); |
|
|
|
|
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>"; |
|
|
|
|
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
|
|
|
|
This checks looks for assignemnts to variables using the
list(...)
function, where not all assigned variables are subsequently used.Consider the following code example.
Only the variables
$a
and$c
are used. There was no need to assign$b
.Instead, the list call could have been.