1
|
|
|
<?php |
|
|
|
|
2
|
|
|
|
3
|
|
|
if ( !defined( 'MEDIAWIKI' ) ) { |
4
|
|
|
echo( "This file is an extension to the MediaWiki software and cannot be used standalone.\n" ); |
5
|
|
|
} |
6
|
|
|
|
7
|
|
|
/** In this class we store things related to data processing **/ |
8
|
|
|
|
9
|
|
|
class SDImportData { |
|
|
|
|
10
|
|
|
|
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* Occurs after the save page request has been processed. |
14
|
|
|
* |
15
|
|
|
* @param WikiPage $wikiPage |
16
|
|
|
* @param User $user |
17
|
|
|
* @param Content $content |
18
|
|
|
* @param string $summary |
19
|
|
|
* @param boolean $isMinor |
20
|
|
|
* @param boolean $isWatch |
21
|
|
|
* @param $section Deprecated |
22
|
|
|
* @param integer $flags |
23
|
|
|
* @param {Revision|null} $revision |
|
|
|
|
24
|
|
|
* @param Status $status |
25
|
|
|
* @param integer $baseRevId |
26
|
|
|
* @param integer $undidRevId |
27
|
|
|
* |
28
|
|
|
* @return boolean |
29
|
|
|
* @see https://www.mediawiki.org/wiki/Manual:Hooks/PageContentSaveComplete |
30
|
|
|
*/ |
31
|
|
|
public static function saveJSONData( $wikiPage, $user, $content, $summary, $isMinor, $isWatch, $section, $flags, $revision, $status, $baseRevId, $undidRevId=null ) { |
|
|
|
|
32
|
|
|
|
33
|
|
|
global $wgSDImportDataPage; |
|
|
|
|
34
|
|
|
|
35
|
|
|
if ( $wikiPage ) { |
36
|
|
|
|
37
|
|
|
// Get NS |
38
|
|
|
$pageTitle = $wikiPage->getTitle(); |
39
|
|
|
|
40
|
|
|
if ( is_object( $pageTitle ) ) { |
41
|
|
|
|
42
|
|
|
$ns = $pageTitle->getNamespace(); |
43
|
|
|
|
44
|
|
|
if ( key_exists( $ns, $wgSDImportDataPage ) ) { |
45
|
|
|
|
46
|
|
|
$nsRepo = $wgSDImportDataPage[$ns]; |
47
|
|
|
|
48
|
|
|
if ( array_key_exists( "json", $nsRepo ) ) { |
49
|
|
|
|
50
|
|
|
if ( $nsRepo["json"] ) { |
51
|
|
|
|
52
|
|
|
list( $args, $table ) = self::getJSONContent( $content ); |
53
|
|
|
|
54
|
|
|
$object = self::getSelector( $args, $nsRepo, "rowobject" ); // String |
55
|
|
|
$fields = self::getSelector( $args, $nsRepo, "rowfields", "Array" ); |
56
|
|
|
$types = self::getSelector( $args, $nsRepo, "typefields", "Array" ); // Array |
57
|
|
|
$refs = self::getSelector( $args, $nsRepo, "ref" ); // Hash |
58
|
|
|
$pre = self::getSelector( $args, $nsRepo, "prefields" ); // Array |
59
|
|
|
$post = self::getSelector( $args, $nsRepo, "postfields" ); // Array |
60
|
|
|
$single = self::getSelector( $args, $nsRepo, "single" ); // Boolean |
61
|
|
|
|
62
|
|
|
// Adding properties, unless they exist |
63
|
|
|
$propertyTypes = self::addPropertyTypes( $fields, $types ); |
64
|
|
|
// TODO: Handling failing, etc. |
65
|
|
|
self::importProperties( $propertyTypes ); |
66
|
|
|
|
67
|
|
|
// No more properties added than their types |
68
|
|
|
if ( sizeof( array_keys( $fields ) ) > sizeof( $propertyTypes ) ) { |
69
|
|
|
|
70
|
|
|
for ( $f = sizeof( array_keys( $fields ) ); $f >= sizeof( $propertyTypes ); $f-- ) { |
|
|
|
|
71
|
|
|
array_pop( $fields ); |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
$dprops = array(); |
77
|
|
|
|
78
|
|
|
if ( $refs ) { |
79
|
|
|
foreach ( $refs as $key => $val ) { |
80
|
|
|
$dprops[ $key ] = self::processWikiText( $val, $pageTitle ); |
81
|
|
|
} |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
if ( $table ) { |
85
|
|
|
|
86
|
|
|
foreach ( $table as $row ) { |
87
|
|
|
$fieldcount = 0; |
88
|
|
|
$struct = array(); |
89
|
|
|
foreach ( $row as $field ) { |
90
|
|
|
|
91
|
|
|
$field = trim( $field ); |
92
|
|
|
|
93
|
|
|
if ( ! empty( $field ) ) { |
94
|
|
|
$pretxt = ""; |
95
|
|
|
if ( isset( $pre[ $fieldcount ] ) && !empty( $pre[ $fieldcount ] ) ) { |
96
|
|
|
$pretxt = $pre[ $fieldcount ].":"; // : for pre |
97
|
|
|
} |
98
|
|
|
$postxt = ""; |
99
|
|
|
if ( isset( $post[ $fieldcount ] ) && !empty( $post[ $fieldcount ] ) ) { |
100
|
|
|
$postxt = "@".$post[ $fieldcount ]; // @ for post |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
if ( array_key_exists( $fieldcount, $fields ) ) { |
104
|
|
|
$struct[ $fields[ $fieldcount ] ] = $pretxt.$field.$postxt; |
105
|
|
|
} |
106
|
|
|
} |
107
|
|
|
$fieldcount++; |
108
|
|
|
} |
109
|
|
|
foreach ( $dprops as $dpropk => $dpropv ) { |
110
|
|
|
$struct[ $dpropk ] = $dpropv; |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
if ( count( array_keys( $struct ) ) > 0 ) { |
114
|
|
|
|
115
|
|
|
if ( $single ) { |
116
|
|
|
self::insertObjectviaJSON( $wikiPage, $revision, $user, $struct ); |
|
|
|
|
117
|
|
|
} else { |
118
|
|
|
self::insertInternalObjectviaJSON( $wikiPage, $revision, $user, $object, $struct ); |
|
|
|
|
119
|
|
|
} |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
return true; |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
|
140
|
|
|
/** |
141
|
|
|
* Function for combining properties and types |
142
|
|
|
* @param $props array |
143
|
|
|
* @param $types array |
144
|
|
|
* |
145
|
|
|
* @return array |
146
|
|
|
*/ |
147
|
|
|
public static function addPropertyTypes( $props, $types ) { |
148
|
|
|
|
149
|
|
|
$count = 0; |
150
|
|
|
|
151
|
|
|
foreach ( $types as $type ) { |
152
|
|
|
|
153
|
|
|
if ( array_key_exists( $count, $props ) ) { |
154
|
|
|
|
155
|
|
|
$prop = $props[ $count ]; |
156
|
|
|
$propertyTypes[ $prop ] = $type; |
|
|
|
|
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
$count++; |
160
|
|
|
|
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
return $propertyTypes; |
|
|
|
|
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* Function for importing Properties straight into the wiki |
168
|
|
|
* @param $propertyTypes array |
169
|
|
|
* @param $overwrite boolean |
170
|
|
|
* @param $user User |
171
|
|
|
* |
172
|
|
|
* @return array |
173
|
|
|
*/ |
174
|
|
|
public static function importProperties( $propertyTypes, $overwrite=false, $user=null) { |
|
|
|
|
175
|
|
|
|
176
|
|
|
$edit_summary = "Adding property via SDImport"; |
177
|
|
|
$listProps = array(); |
178
|
|
|
|
179
|
|
|
foreach ( $propertyTypes as $prop => $type ) { |
180
|
|
|
|
181
|
|
|
// Consider going ahead it type is not null |
182
|
|
|
if ( $type ) { |
183
|
|
|
|
184
|
|
|
// TODO: to consider not hardcoding NS |
185
|
|
|
$propPageName = "Property:".$prop; |
186
|
|
|
|
187
|
|
|
$propTitle = Title::newFromText( $propPageName ); |
188
|
|
|
|
189
|
|
|
$wikiPage = new WikiPage( $propTitle ); |
190
|
|
|
|
191
|
|
|
if ( ! $wikiPage->exists() || ( $wikiPage->exists() && $overwrite ) ) { |
192
|
|
|
|
193
|
|
|
$text = "[[Has type::".$type."]]"; |
194
|
|
|
|
195
|
|
|
$new_content = new WikitextContent( $text ); |
196
|
|
|
$status = $wikiPage->doEditContent( $new_content, $edit_summary ); |
|
|
|
|
197
|
|
|
|
198
|
|
|
// Adding list |
199
|
|
|
// TODO: ideally handling Status |
200
|
|
|
array_push( $listProps, $prop ); |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
|
208
|
|
|
return $listProps; |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
/** |
212
|
|
|
* @param $pageTitle Title |
213
|
|
|
* @param $object string |
214
|
|
|
* @param struct object |
215
|
|
|
* |
216
|
|
|
* @return boolean |
217
|
|
|
*/ |
218
|
|
|
public static function insertInternalObject( $parser, $pageTitle, $object, $struct ) { |
219
|
|
|
|
220
|
|
|
# TODO: Check if this will work |
221
|
|
|
if ( ! $parser ) { |
222
|
|
|
$parser = new Parser(); |
223
|
|
|
$parser->setTitle( $pageTitle ); // Put context |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
$subobjectArgs = array( &$parser ); |
227
|
|
|
// Blank first argument, so that subobject ID will be |
228
|
|
|
// an automatically-generated random number. |
229
|
|
|
$subobjectArgs[1] = ''; |
230
|
|
|
// "main" property, pointing back to the page. |
231
|
|
|
$mainPageName = $pageTitle->getText(); |
232
|
|
|
$mainPageNamespace = $pageTitle->getNsText(); |
233
|
|
|
if ( $mainPageNamespace != '' ) { |
234
|
|
|
$mainPageName = $mainPageNamespace . ':' . $mainPageName; |
235
|
|
|
} |
236
|
|
|
$subobjectArgs[2] = $object . '=' . $mainPageName; |
237
|
|
|
|
238
|
|
|
foreach ( $struct as $prop => $value ) { |
239
|
|
|
$subobjectArgs[] = $prop . '=' . $value; |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
if ( class_exists( 'SMW\SubobjectParserFunction' ) ) { |
243
|
|
|
// SMW 1.9+ |
244
|
|
|
$subobjectFunction = \SMW\ParserFunctionFactory::newFromParser( $parser )->getSubobjectParser(); |
|
|
|
|
245
|
|
|
return $subobjectFunction->parse( new SMW\ParserParameterFormatter( $subobjectArgs ) ); |
246
|
|
|
} else { |
247
|
|
|
// SMW 1.8 |
248
|
|
|
call_user_func_array( array( 'SMWSubobject', 'render' ), $subobjectArgs ); |
249
|
|
|
} |
250
|
|
|
return; |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
|
254
|
|
|
/** |
255
|
|
|
* @param $wikiPage wikiPage |
256
|
|
|
* @param $revision revision |
257
|
|
|
* @param $user user |
258
|
|
|
* @param struct object |
259
|
|
|
* |
260
|
|
|
* @return boolean |
261
|
|
|
* |
262
|
|
|
* Code adapted from: https://github.com/SemanticMediaWiki/SemanticMediaWiki/issues/2974 |
263
|
|
|
*/ |
264
|
|
|
public static function insertObjectviaJSON( $wikiPage, $revision, $user, $struct ) { |
265
|
|
|
|
266
|
|
|
$applicationFactory = \SMW\ApplicationFactory::getInstance(); |
267
|
|
|
|
268
|
|
|
$mwCollaboratorFactory = $applicationFactory->newMwCollaboratorFactory(); |
269
|
|
|
|
270
|
|
|
/** * Initialize the ParserOuput object */ |
271
|
|
|
$editInfoProvider = $mwCollaboratorFactory->newEditInfoProvider( $wikiPage, $revision, $user ); |
272
|
|
|
|
273
|
|
|
$parserOutput = $editInfoProvider->fetchEditInfo()->getOutput(); |
274
|
|
|
|
275
|
|
|
if ( !$parserOutput instanceof \ParserOutput ) { |
|
|
|
|
276
|
|
|
return true; |
277
|
|
|
} |
278
|
|
|
|
279
|
|
|
$parserData = $applicationFactory->newParserData( $wikiPage->getTitle(), $parserOutput ); |
280
|
|
|
|
281
|
|
|
$subject = $parserData->getSubject(); |
282
|
|
|
|
283
|
|
|
$subject = new \SMW\DIWikiPage( $subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki() ); |
284
|
|
|
|
285
|
|
|
// TODO: To finish |
286
|
|
|
foreach ( $struct as $property => $value ) { |
287
|
|
|
// Struct to iterate |
288
|
|
|
|
289
|
|
|
$dataValue = \SMW\DataValueFactory::getInstance()->newDataValueByText( $property, $value, false, $subject ); |
290
|
|
|
|
291
|
|
|
$parserData->getSemanticData()->addDataValue( $dataValue ); |
292
|
|
|
|
293
|
|
|
} |
294
|
|
|
|
295
|
|
|
// This part is used to add the subobject the the main subject |
296
|
|
|
$parserData->pushSemanticDataToParserOutput(); |
297
|
|
|
$parserData->updateStore(); |
298
|
|
|
// Below it works event with maintenance function |
299
|
|
|
// $store = \SMW\StoreFactory::getStore(); |
|
|
|
|
300
|
|
|
// $store->updateData( $parserData->getSemanticData() ); |
|
|
|
|
301
|
|
|
|
302
|
|
|
return true; |
303
|
|
|
} |
304
|
|
|
|
305
|
|
|
/** |
306
|
|
|
* @param $wikiPage wikiPage |
307
|
|
|
* @param $revision revision |
308
|
|
|
* @param $user user |
309
|
|
|
* @param $object string |
310
|
|
|
* @param struct object |
311
|
|
|
* |
312
|
|
|
* @return boolean |
313
|
|
|
* |
314
|
|
|
* Code from: https://github.com/SemanticMediaWiki/SemanticMediaWiki/issues/2974 |
315
|
|
|
*/ |
316
|
|
|
public static function insertInternalObjectviaJSON( $wikiPage, $revision, $user, $object, $struct ) { |
317
|
|
|
|
318
|
|
|
$applicationFactory = \SMW\ApplicationFactory::getInstance(); |
319
|
|
|
|
320
|
|
|
$mwCollaboratorFactory = $applicationFactory->newMwCollaboratorFactory(); |
321
|
|
|
|
322
|
|
|
/** * Initialize the ParserOuput object */ |
323
|
|
|
$editInfoProvider = $mwCollaboratorFactory->newEditInfoProvider( $wikiPage, $revision, $user ); |
324
|
|
|
|
325
|
|
|
$parserOutput = $editInfoProvider->fetchEditInfo()->getOutput(); |
326
|
|
|
|
327
|
|
|
if ( !$parserOutput instanceof \ParserOutput ) { |
|
|
|
|
328
|
|
|
return true; |
329
|
|
|
} |
330
|
|
|
|
331
|
|
|
$parserData = $applicationFactory->newParserData( $wikiPage->getTitle(), $parserOutput ); |
332
|
|
|
|
333
|
|
|
$subject = $parserData->getSubject(); |
334
|
|
|
|
335
|
|
|
// Identify the content as unique |
336
|
|
|
$subobjectName = '_SDI' . md5( json_encode( $struct ) ); |
337
|
|
|
|
338
|
|
|
$subject = new \SMW\DIWikiPage( $subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), $subobjectName ); |
339
|
|
|
|
340
|
|
|
// Build the subobject by using a separate container object |
341
|
|
|
$containerSemanticData = new \SMWContainerSemanticData( $subject ); |
342
|
|
|
|
343
|
|
|
// Iterate through here |
344
|
|
|
|
345
|
|
|
foreach ( $struct as $property => $value ) { |
346
|
|
|
// If you don't know the type, use the DataValueFactory |
347
|
|
|
$dataValue = \SMW\DataValueFactory::getInstance()->newDataValueByText( $property, $value ); |
348
|
|
|
$containerSemanticData->addDataValue( $dataValue ); |
349
|
|
|
} |
350
|
|
|
|
351
|
|
|
// Object assignation |
352
|
|
|
|
353
|
|
|
if ( $object ) { |
354
|
|
|
|
355
|
|
|
if ( ! empty( $object ) ) { |
356
|
|
|
|
357
|
|
|
if ( $wikiPage->getTitle() ) { |
358
|
|
|
|
359
|
|
|
$fullTitle = $wikiPage->getTitle()->getPrefixedText(); |
360
|
|
|
|
361
|
|
|
$dataValue = \SMW\DataValueFactory::getInstance()->newDataValueByText( $object, $fullTitle ); |
362
|
|
|
$containerSemanticData->addDataValue( $dataValue ); |
363
|
|
|
|
364
|
|
|
} |
365
|
|
|
|
366
|
|
|
} |
367
|
|
|
|
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
|
371
|
|
|
// This part is used to add the subobject the the main subject |
372
|
|
|
$parserData->getSemanticData()->addPropertyObjectValue( new \SMW\DIProperty( \SMW\DIProperty::TYPE_SUBOBJECT ), new \SMWDIContainer( $containerSemanticData ) ); |
373
|
|
|
$parserData->pushSemanticDataToParserOutput(); |
374
|
|
|
$parserData->updateStore(); |
375
|
|
|
|
376
|
|
|
// Below it works event with maintenance function |
377
|
|
|
// $store = \SMW\StoreFactory::getStore(); |
|
|
|
|
378
|
|
|
// $store->updateData( $parserData->getSemanticData() ); |
|
|
|
|
379
|
|
|
|
380
|
|
|
return true; |
381
|
|
|
} |
382
|
|
|
|
383
|
|
|
|
384
|
|
|
/** |
385
|
|
|
* @first -> First hash |
386
|
|
|
* @second -> Second hash |
387
|
|
|
* @key -> Actual key |
388
|
|
|
|
389
|
|
|
* @return variable (depending on case) |
390
|
|
|
*/ |
391
|
|
|
public static function getSelector( $first, $second, $key, $opt=null ) { |
392
|
|
|
|
393
|
|
|
if ( key_exists( $key, $first ) ) { |
394
|
|
|
// Here process |
395
|
|
|
|
396
|
|
|
$array = array(); |
397
|
|
|
|
398
|
|
|
if ( is_array( $first[ $key ] ) ) { |
399
|
|
|
$keyvals = $first[ $key ]; |
400
|
|
|
} else { |
401
|
|
|
$keyvals = explode( ",", $first[ $key ] ); |
402
|
|
|
} |
403
|
|
|
|
404
|
|
|
if ( self::isAssocArray( $keyvals ) || ( $opt && $opt === "Array" ) ) { |
405
|
|
|
|
406
|
|
|
return $keyvals; |
407
|
|
|
|
408
|
|
|
} else { |
409
|
|
|
|
410
|
|
|
if ( count( $keyvals ) < 2 ) { |
411
|
|
|
// If => ergo hash |
412
|
|
|
|
413
|
|
|
$keyhvals = explode( "#", $keyvals[0], 2 ); |
414
|
|
|
|
415
|
|
|
if ( count( $keyhvals ) > 1 ) { |
416
|
|
|
$array[ trim( $keyhvals[0] ) ] = trim( $keyhvals[1] ); |
417
|
|
|
return $array; |
418
|
|
|
} else { |
419
|
|
|
return trim( $keyhvals[0] ); |
420
|
|
|
} |
421
|
|
|
} else { |
422
|
|
|
|
423
|
|
|
foreach ( $keyvals as $keyval ) { |
424
|
|
|
$keyval = trim( $keyval ); |
425
|
|
|
|
426
|
|
|
// If => ergo hash |
427
|
|
|
$keyhvals = explode( "#", $keyval, 2 ); |
428
|
|
|
|
429
|
|
|
if ( count( $keyhvals ) > 1 ) { |
430
|
|
|
$array[ trim( $keyhvals[0] ) ] = trim( $keyhvals[1] ); |
431
|
|
|
} |
432
|
|
|
else { |
433
|
|
|
array_push( $array, trim( $keyhvals[0] ) ); |
434
|
|
|
} |
435
|
|
|
} |
436
|
|
|
|
437
|
|
|
return $array; |
438
|
|
|
} |
439
|
|
|
|
440
|
|
|
} |
441
|
|
|
|
442
|
|
|
} else { |
443
|
|
|
if ( key_exists( $key, $second ) ) { |
444
|
|
|
// Direct |
445
|
|
|
return $second[$key]; |
446
|
|
|
} else { |
447
|
|
|
return false; |
448
|
|
|
} |
449
|
|
|
} |
450
|
|
|
|
451
|
|
|
} |
452
|
|
|
|
453
|
|
|
|
454
|
|
|
/** |
455
|
|
|
* Whether associative array or not |
456
|
|
|
* $arr Array |
457
|
|
|
* @return boolean |
458
|
|
|
*/ |
459
|
|
|
|
460
|
|
|
public static function isAssocArray( array $arr ) { |
461
|
|
|
if (array() === $arr) return false; |
462
|
|
|
return array_keys($arr) !== range(0, count($arr) - 1); |
463
|
|
|
} |
464
|
|
|
|
465
|
|
|
|
466
|
|
|
|
467
|
|
|
/** |
468
|
|
|
* Occurs after the save page request has been processed. |
469
|
|
|
* @see https://www.mediawiki.org/wiki/Manual:Hooks/PageContentSaveComplete |
470
|
|
|
* |
471
|
|
|
* @param text string |
472
|
|
|
* |
473
|
|
|
* @return boolean |
474
|
|
|
*/ |
475
|
|
|
public static function processWikiText( $text, $pageTitle ) { |
476
|
|
|
|
477
|
|
|
// TODO: Ideally a full wikitext processing here, etc. |
478
|
|
|
|
479
|
|
|
if ( $text == '{{PAGENAME}}' ) { |
480
|
|
|
$text = $pageTitle->getText(); |
481
|
|
|
} elseif ( $text == '{{FULLPAGENAME}}' ) { |
482
|
|
|
$text = $pageTitle->getPrefixedText(); |
483
|
|
|
} else { |
|
|
|
|
484
|
|
|
// Do nothing; |
485
|
|
|
} |
486
|
|
|
|
487
|
|
|
return $text; |
488
|
|
|
} |
489
|
|
|
|
490
|
|
|
|
491
|
|
|
private static function getJSONContent( $content ) { |
492
|
|
|
|
493
|
|
|
$outcome = array( ); |
494
|
|
|
$args = null; |
495
|
|
|
$data = null; |
496
|
|
|
|
497
|
|
|
if ( $content ) { |
498
|
|
|
|
499
|
|
|
if ( is_object( $content ) ) { |
500
|
|
|
|
501
|
|
|
if ( $content->getModel() == CONTENT_MODEL_JSON ) { |
502
|
|
|
|
503
|
|
|
// Only act if JSON |
504
|
|
|
|
505
|
|
|
$json = $content->getNativeData(); |
506
|
|
|
|
507
|
|
|
|
508
|
|
|
list( $args, $data ) = self::processJSON( $json ); |
509
|
|
|
} |
510
|
|
|
|
511
|
|
|
} |
512
|
|
|
} |
513
|
|
|
|
514
|
|
|
array_push( $outcome, $args ); |
515
|
|
|
array_push( $outcome, $data ); |
516
|
|
|
|
517
|
|
|
return $outcome; |
518
|
|
|
} |
519
|
|
|
|
520
|
|
|
|
521
|
|
|
private static function processJSON( $json ) { |
522
|
|
|
|
523
|
|
|
$outcome = array( ); |
524
|
|
|
$args = null; |
525
|
|
|
$data = null; |
526
|
|
|
|
527
|
|
|
$SDIJSON = false; |
528
|
|
|
|
529
|
|
|
// Check JSON is valid |
530
|
|
|
$jsonObj = json_decode( $json, true ); |
531
|
|
|
|
532
|
|
|
if ( $jsonObj ) { |
533
|
|
|
|
534
|
|
|
if ( array_key_exists( "meta", $jsonObj ) ) { |
535
|
|
|
|
536
|
|
|
$meta = $jsonObj["meta"]; |
537
|
|
|
|
538
|
|
|
if ( array_key_exists( "app", $meta ) ) { |
539
|
|
|
|
540
|
|
|
if ( $meta["app"] === "SDI" ) { |
541
|
|
|
$SDIJSON = true; |
542
|
|
|
} |
543
|
|
|
|
544
|
|
|
} |
545
|
|
|
|
546
|
|
|
$args = $meta; |
547
|
|
|
|
548
|
|
|
# TODO: Addding more custom fields to args |
549
|
|
|
|
550
|
|
|
|
551
|
|
|
if ( array_key_exists( "data", $jsonObj ) && $SDIJSON ) { |
552
|
|
|
|
553
|
|
|
$dataObj = $jsonObj["data"]; |
554
|
|
|
|
555
|
|
|
$data = self::checkJSONData( $dataObj ); |
556
|
|
|
|
557
|
|
|
} |
558
|
|
|
} |
559
|
|
|
|
560
|
|
|
} |
561
|
|
|
|
562
|
|
|
|
563
|
|
|
array_push( $outcome, $args ); |
564
|
|
|
array_push( $outcome, $data ); |
565
|
|
|
|
566
|
|
|
return $outcome; |
567
|
|
|
|
568
|
|
|
} |
569
|
|
|
|
570
|
|
|
private static function checkJSONData( $dataObj ) { |
571
|
|
|
|
572
|
|
|
$data = null; |
573
|
|
|
|
574
|
|
|
if ( is_array( $dataObj ) ) { |
575
|
|
|
|
576
|
|
|
if ( count( $dataObj ) > 0 ) { |
577
|
|
|
|
578
|
|
|
$bad = false; |
579
|
|
|
|
580
|
|
|
// We should have an array of arrays |
581
|
|
|
foreach ( $dataObj as $row ) { |
582
|
|
|
|
583
|
|
|
if ( ! is_array( $row ) ) { |
584
|
|
|
$bad = true; |
585
|
|
|
} |
586
|
|
|
} |
587
|
|
|
|
588
|
|
|
if ( ! $bad ) { |
589
|
|
|
$data = $dataObj; |
590
|
|
|
} |
591
|
|
|
|
592
|
|
|
} |
593
|
|
|
} |
594
|
|
|
|
595
|
|
|
|
596
|
|
|
return $data; |
597
|
|
|
} |
598
|
|
|
|
599
|
|
|
|
600
|
|
|
/** Import of Wikitext, let's say, at commit */ |
601
|
|
|
/** |
602
|
|
|
* @text Bulk data text |
603
|
|
|
* @pagetitle Title of the page |
604
|
|
|
* @delimiter Delimiter of CSV |
605
|
|
|
* @enclosure Enclosure of CSV |
606
|
|
|
* @num Occurrence in page. If only one, then 0 |
607
|
|
|
* @return status of update |
608
|
|
|
*/ |
609
|
|
|
public static function importWikiText( $text, $pagetitle, $separator=NULL, $delimiter=NULL, $num=0 ) { |
|
|
|
|
610
|
|
|
|
611
|
|
|
$title = Title::newFromText( $pagetitle ); |
612
|
|
|
$wikipage = WikiPage::factory( $title ); |
613
|
|
|
|
614
|
|
|
# Default cases |
615
|
|
|
$newpage = false; |
616
|
|
|
$contentModel = "wikitext"; |
617
|
|
|
|
618
|
|
|
$extraInfo = ""; |
619
|
|
|
|
620
|
|
|
$ns = $pageTitle->getNamespace(); |
|
|
|
|
621
|
|
|
|
622
|
|
|
if ( $GLOBALS["wgSDImportDataPage"] && array_key_exists( $ns, $GLOBALS["wgSDImportDataPage"] ) ) { |
623
|
|
|
|
624
|
|
|
if ( $separator !== NULL ) { |
625
|
|
|
if ( array_key_exists( "separator", $GLOBALS["wgSDImportDataPage"][$ns] ) ) { |
626
|
|
|
if ( $GLOBALS["wgSDImportDataPage"][$ns]["separator"] != $separator ) { |
627
|
|
|
$extraInfo = $extraInfo . " separator=\"".$separator."\""; |
628
|
|
|
} |
629
|
|
|
} |
630
|
|
|
} |
631
|
|
|
if ( $delimiter !== NULL ) { |
632
|
|
|
if ( array_key_exists( "delimiter", $GLOBALS["wgSDImportDataPage"][$ns] ) ) { |
633
|
|
|
if ( $GLOBALS["wgSDImportDataPage"][$ns]["delimiter"] != $delimiter ) { |
634
|
|
|
$extraInfo = $extraInfo . " delimiter='".$delimiter."' "; |
|
|
|
|
635
|
|
|
} |
636
|
|
|
} |
637
|
|
|
} |
638
|
|
|
} |
639
|
|
|
|
640
|
|
|
// Retrievet text of page |
641
|
|
|
// Back-compatibility, just in case |
642
|
|
|
|
643
|
|
|
// TODO: Handle if creation of page |
644
|
|
|
if ( ! $wikipage->exists() ) { |
645
|
|
|
$newpage = true; |
646
|
|
|
} |
647
|
|
|
|
648
|
|
|
if ( ! $newpage ) { |
649
|
|
|
|
650
|
|
|
if ( method_exists ( $wikipage, "getContent" ) ) { |
651
|
|
|
$mainContent = $wikipage->getContent(); |
652
|
|
|
$mainText = $mainContent->getNativeData(); |
653
|
|
|
$contentModel = $wikipage->getContentModel(); |
654
|
|
|
|
655
|
|
|
if ( ! $contentModel ) { |
656
|
|
|
$contentModel = "wikitext"; |
657
|
|
|
} |
658
|
|
|
|
659
|
|
|
} else { |
660
|
|
|
$mainText = $wikipage->getText(); |
661
|
|
|
$contentModel = "wikitext"; |
662
|
|
|
} |
663
|
|
|
|
664
|
|
|
} |
665
|
|
|
|
666
|
|
|
$status = 0; |
667
|
|
|
$tableText = ""; |
668
|
|
|
|
669
|
|
|
# Allow only in wikitext context |
670
|
|
|
if ( $contentModel === "wikitext" ) { |
671
|
|
|
|
672
|
|
|
|
673
|
|
|
if ( ! $newpage ) { |
674
|
|
|
|
675
|
|
|
// Get matches |
676
|
|
|
$page_parts = preg_split( "/(<smwdata.*?>)/", $mainText, -1, PREG_SPLIT_DELIM_CAPTURE ); |
|
|
|
|
677
|
|
|
|
678
|
|
|
$count = 0; |
679
|
|
|
$outcome = array(); |
680
|
|
|
|
681
|
|
|
foreach ( $page_parts as $page_part ) { |
682
|
|
|
|
683
|
|
|
if ( preg_match( "/<smwdata/", $page_part ) ) { |
684
|
|
|
$count = $count + 1; |
685
|
|
|
} else { |
686
|
|
|
if ( $num == $count - 1 ) { |
687
|
|
|
if ( preg_match( "/<\/smwdata/", $page_part ) ) { |
688
|
|
|
|
689
|
|
|
$in_parts = preg_split( "/(<\/smwdata.*?>)/", $page_part, -1, PREG_SPLIT_DELIM_CAPTURE ); |
690
|
|
|
$in_parts[0] = "\n".$text."\n"; |
691
|
|
|
$page_part = implode( "", $in_parts ); |
692
|
|
|
} |
693
|
|
|
} |
694
|
|
|
} |
695
|
|
|
|
696
|
|
|
array_push( $outcome, $page_part ); |
697
|
|
|
} |
698
|
|
|
|
699
|
|
|
// If stuff |
700
|
|
|
if ( count( $outcome ) > 0 ) { |
701
|
|
|
|
702
|
|
|
$tableText = implode( "", $outcome ); |
703
|
|
|
} |
704
|
|
|
|
705
|
|
|
} else { |
706
|
|
|
|
707
|
|
|
$tableText = "<smwdata>".$text."</smwdata>"; |
708
|
|
|
|
709
|
|
|
} |
710
|
|
|
|
711
|
|
|
|
712
|
|
|
if ( ! empty( $tableText ) ) { |
713
|
|
|
|
714
|
|
|
// Submit content |
715
|
|
|
// Back-compatibility, just in case |
716
|
|
|
if ( method_exists ( $wikipage, "doEditContent" ) ) { |
717
|
|
|
$content = new WikiTextContent( $tableText ); |
718
|
|
|
$status = $wikipage->doEditContent( $content, "Updating content" ); |
719
|
|
|
} else { |
720
|
|
|
$status = $wikipage->doEdit( $tableText, "Updating content" ); |
721
|
|
|
} |
722
|
|
|
|
723
|
|
|
} |
724
|
|
|
|
725
|
|
|
// TODO: Handle status value if not normal one |
726
|
|
|
|
727
|
|
|
} |
728
|
|
|
|
729
|
|
|
return $status; |
730
|
|
|
} |
731
|
|
|
|
732
|
|
|
|
733
|
|
|
|
734
|
|
|
/** |
735
|
|
|
* @text Bulk data text |
736
|
|
|
* @pagetitle Title of the page |
737
|
|
|
* @return status of update |
738
|
|
|
*/ |
739
|
|
|
|
740
|
|
|
public static function importJSONBatch( $text, $namespace="", $overwrite=false) { |
741
|
|
|
|
742
|
|
|
$jsonObj = json_decode( $text, true ); |
743
|
|
|
$dataObj = $jsonObj["data"]; |
744
|
|
|
$dataHash = array(); |
745
|
|
|
|
746
|
|
|
// If namespace is numeric, check if in config |
747
|
|
|
if ( is_numeric( $namespace ) ) { |
748
|
|
|
|
749
|
|
|
global $wgContLang; |
|
|
|
|
750
|
|
|
|
751
|
|
|
if ( $namespace == 0 ) { |
752
|
|
|
|
753
|
|
|
$namespace = ""; |
754
|
|
|
|
755
|
|
|
} else { |
756
|
|
|
|
757
|
|
|
if ( $wgContLang->getNsText( intval( $namespace, 10 ) ) ) { |
758
|
|
|
|
759
|
|
|
$namespace = $wgContLang->getNsText( intval( $namespace, 10 ) ); |
760
|
|
|
} |
761
|
|
|
|
762
|
|
|
} |
763
|
|
|
} |
764
|
|
|
|
765
|
|
|
for ( $x=0; $x <count($dataObj); $x++ ) { |
|
|
|
|
766
|
|
|
|
767
|
|
|
if ( count( $dataObj[$x] ) > 1 ) { |
768
|
|
|
|
769
|
|
|
$pageCell = array_shift( $dataObj[$x] ); |
770
|
|
|
|
771
|
|
|
if ( $pageCell !== "" ) { |
772
|
|
|
|
773
|
|
|
if ( $namespace === "" ) { |
774
|
|
|
$pagetitle = $pageCell; |
775
|
|
|
} else { |
776
|
|
|
$pagetitle = $namespace . ':' . $pageCell; |
777
|
|
|
} |
778
|
|
|
|
779
|
|
|
} |
780
|
|
|
|
781
|
|
|
if ( ! $dataHash[ $pagetitle ] ) { |
782
|
|
|
$dataHash[ $pagetitle ] = array(); |
|
|
|
|
783
|
|
|
} |
784
|
|
|
|
785
|
|
|
array_push( $dataHash[ $pagetitle ], $dataObj[$x] ); |
786
|
|
|
|
787
|
|
|
} |
788
|
|
|
|
789
|
|
|
} |
790
|
|
|
|
791
|
|
|
foreach ( $dataHash as $pagetitle => $dataArray ) { |
792
|
|
|
|
793
|
|
|
$jsonSubObj = array(); |
794
|
|
|
$jsonSubObj["data"] = $dataArray; |
795
|
|
|
$jsonSubObj["meta"] = $jsonObj["meta"]; |
796
|
|
|
|
797
|
|
|
self::importJSON( json_encode( $jsonSubObj ), $pagetitle, $overwrite ); |
798
|
|
|
|
799
|
|
|
} |
800
|
|
|
|
801
|
|
|
return true; |
802
|
|
|
|
803
|
|
|
} |
804
|
|
|
|
805
|
|
|
/** Import of JSON into a page, let's say, at commit **/ |
806
|
|
|
/** |
807
|
|
|
* @text Bulk data text |
808
|
|
|
* @pagetitle Title of the page |
809
|
|
|
* @return status of update |
810
|
|
|
*/ |
811
|
|
|
public static function importJSON( $text, $pagetitle, $overwrite=false) { |
812
|
|
|
|
813
|
|
|
$title = Title::newFromText( $pagetitle ); |
814
|
|
|
$wikipage = WikiPage::factory( $title ); |
815
|
|
|
$goahead = true; |
816
|
|
|
$status = false; |
817
|
|
|
// Check if exists |
818
|
|
|
if ( $wikipage->exists() && ! $overwrite ) { |
819
|
|
|
$goahead = false; |
820
|
|
|
} |
821
|
|
|
if ( $goahead ) { |
822
|
|
|
// Check compatibility. Only if newer versions of MW |
823
|
|
|
if ( method_exists ( $wikipage, "getContent" ) ) { |
824
|
|
|
$contentModel = $wikipage->getContentModel(); |
825
|
|
|
if ( $contentModel === "json" || ! $wikipage->exists() ) { |
826
|
|
|
$content = new JSONContent($text); |
827
|
|
|
$status = $wikipage->doEditContent( $content, "Updating content" ); |
828
|
|
|
} |
829
|
|
|
} |
830
|
|
|
} |
831
|
|
|
return $status; |
832
|
|
|
} |
833
|
|
|
|
834
|
|
|
/** TODO: TO BE UPDATED **/ |
835
|
|
|
public static function prepareStructForJSON( $meta, $data ) { |
836
|
|
|
|
837
|
|
|
$strJSON = ""; |
838
|
|
|
|
839
|
|
|
if ( $data ) { |
840
|
|
|
|
841
|
|
|
$obj = array( ); |
842
|
|
|
|
843
|
|
|
// TODO: this may change in future versions |
844
|
|
|
$obj["meta"] = array(); |
845
|
|
|
$obj["meta"]["app"] = "SDI"; |
846
|
|
|
$obj["meta"]["version"] = 0.1; |
847
|
|
|
|
848
|
|
|
if ( $meta ) { |
849
|
|
|
|
850
|
|
|
if ( array_key_exists( "rowfields", $meta ) ) { |
851
|
|
|
$obj["meta"]["rowfields"] = $meta["rowfields"]; |
852
|
|
|
} |
853
|
|
|
} |
854
|
|
|
|
855
|
|
|
$obj["data"] = $data; |
856
|
|
|
|
857
|
|
|
$strJSON = json_encode( $obj ); |
858
|
|
|
} |
859
|
|
|
|
860
|
|
|
return $strJSON; |
861
|
|
|
} |
862
|
|
|
|
863
|
|
|
|
864
|
|
|
/** |
865
|
|
|
* @param $out OutputPage |
866
|
|
|
* @param $text string |
867
|
|
|
* @return $out OutputPage |
868
|
|
|
*/ |
|
|
|
|
869
|
|
|
|
870
|
|
|
public static function onOutputPageBeforeHTML( &$out, &$text ) { |
|
|
|
|
871
|
|
|
|
872
|
|
|
// We add Modules |
873
|
|
|
$out->addModules( 'ext.sdimport' ); |
874
|
|
|
|
875
|
|
|
global $wgSDImportDataPage; |
|
|
|
|
876
|
|
|
|
877
|
|
|
// Get Namespace |
878
|
|
|
|
879
|
|
|
$context = RequestContext::getMain(); |
880
|
|
|
if ( $context ) { |
881
|
|
|
$pageTitle = $context->getTitle(); |
882
|
|
|
if ( $pageTitle ) { |
883
|
|
|
|
884
|
|
|
$ns = $pageTitle->getNamespace(); |
885
|
|
|
|
886
|
|
|
if ( array_key_exists( $ns, $wgSDImportDataPage ) ) { |
887
|
|
|
|
888
|
|
|
if ( array_key_exists( "form", $wgSDImportDataPage[$ns] ) ) { |
889
|
|
|
|
890
|
|
|
if ( $wgSDImportDataPage[$ns]["form"] === true ) { |
891
|
|
|
|
892
|
|
|
// Adding form libraries only if needed |
893
|
|
|
$out->addModules( 'ext.sdimport.form' ); |
894
|
|
|
|
895
|
|
|
} |
896
|
|
|
} |
897
|
|
|
} |
898
|
|
|
|
899
|
|
|
} |
900
|
|
|
} |
901
|
|
|
|
902
|
|
|
return $out; |
903
|
|
|
} |
904
|
|
|
|
905
|
|
|
/** This allow PHP vars to be exposed to JavaScript **/ |
906
|
|
|
|
907
|
|
|
public static function onResourceLoaderGetConfigVars( &$vars ) { |
908
|
|
|
|
909
|
|
|
global $wgSDImportDataPage; |
|
|
|
|
910
|
|
|
|
911
|
|
|
|
912
|
|
|
$vars['wgSDImportDataPage'] = $wgSDImportDataPage; |
913
|
|
|
|
914
|
|
|
return true; |
915
|
|
|
} |
916
|
|
|
} |
917
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.