1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace SMW\Scribunto; |
4
|
|
|
|
5
|
|
|
use Scribunto_LuaLibraryBase; |
6
|
|
|
use SMW\DIProperty; |
7
|
|
|
use SMW\ApplicationFactory; |
8
|
|
|
use SMWQueryResult as QueryResult; |
9
|
|
|
use SMWOutputs; |
10
|
|
|
|
11
|
|
|
/** |
12
|
|
|
* @license GNU GPL v2+ |
13
|
|
|
* @since 1.0 |
14
|
|
|
* |
15
|
|
|
* @author mwjames |
16
|
|
|
*/ |
17
|
|
|
class ScribuntoLuaLibrary extends Scribunto_LuaLibraryBase { |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* @var LibraryFactory |
21
|
|
|
*/ |
22
|
|
|
private $libraryFactory; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* This is the name of the key for error messages |
26
|
|
|
* |
27
|
|
|
* @var string |
28
|
|
|
* @since 1.0 |
29
|
|
|
*/ |
30
|
|
|
const SMW_ERROR_FIELD = 'error'; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* @since 1.0 |
34
|
|
|
*/ |
35
|
49 |
|
public function register() { |
36
|
|
|
|
37
|
|
|
$lib = [ |
38
|
49 |
|
'ask' => [ $this, 'ask' ], |
39
|
49 |
|
'getPropertyType' => [ $this, 'getPropertyType' ], |
40
|
49 |
|
'getQueryResult' => [ $this, 'getQueryResult' ], |
41
|
49 |
|
'info' => [ $this, 'info' ], |
42
|
49 |
|
'set' => [ $this, 'set' ], |
43
|
49 |
|
'subobject' => [ $this, 'subobject' ], |
44
|
|
|
]; |
45
|
|
|
|
46
|
49 |
|
$this->getEngine()->registerInterface( __DIR__ . '/' . 'mw.smw.lua', $lib, [] ); |
47
|
49 |
|
} |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* This mirrors the functionality of the parser function #ask and makes it |
51
|
|
|
* available in lua. |
52
|
|
|
* |
53
|
|
|
* @since 1.0 |
54
|
|
|
* |
55
|
|
|
* @param string|array $arguments parameters passed from lua, string or array depending on call |
56
|
|
|
* |
57
|
|
|
* @return array array( null ) or array[] |
58
|
|
|
*/ |
59
|
10 |
|
public function ask( $arguments = null ) { |
60
|
|
|
|
61
|
10 |
|
$queryResult = $this->getLibraryFactory()->newQueryResultFrom( |
62
|
10 |
|
$this->processLuaArguments( $arguments ) |
63
|
|
|
); |
64
|
|
|
|
65
|
10 |
|
if ( !$this->isAQueryResult( $queryResult ) ) { |
66
|
1 |
|
return [ $queryResult ]; |
67
|
|
|
} |
68
|
|
|
|
69
|
9 |
|
$luaResultProcessor = $this->getLibraryFactory()->newLuaAskResultProcessor( |
70
|
9 |
|
$queryResult |
71
|
|
|
); |
72
|
|
|
|
73
|
9 |
|
$result = $luaResultProcessor->getProcessedResult(); |
74
|
|
|
|
75
|
9 |
|
return [ $this->convertArrayToLuaTable( $result ) ]; |
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
/** |
79
|
|
|
* Returns property type |
80
|
|
|
* |
81
|
|
|
* @since 1.0 |
82
|
|
|
* |
83
|
|
|
* @param string $propertyName |
84
|
|
|
* |
85
|
|
|
* @return array |
86
|
|
|
*/ |
87
|
5 |
|
public function getPropertyType( $propertyName = null ) { |
88
|
|
|
|
89
|
5 |
|
$this->checkType( 'getPropertyType', 1, $propertyName, 'string' ); |
90
|
5 |
|
$propertyName = trim( $propertyName ); |
91
|
|
|
|
92
|
5 |
|
if ( $propertyName === '' ) { |
93
|
3 |
|
return [ null ]; |
94
|
|
|
} |
95
|
|
|
|
96
|
3 |
|
$property = DIProperty::newFromUserLabel( $propertyName ); |
97
|
|
|
|
98
|
3 |
|
if ( $property === null ) { |
99
|
|
|
return [ null ]; |
100
|
|
|
} |
101
|
|
|
|
102
|
3 |
|
return [ $property->findPropertyTypeID() ]; |
|
|
|
|
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
/** |
106
|
|
|
* Returns query results in for of the standard API return format |
107
|
|
|
* |
108
|
|
|
* @since 1.0 |
109
|
|
|
* |
110
|
|
|
* @param string|array $arguments |
111
|
|
|
* |
112
|
|
|
* @return array |
113
|
|
|
*/ |
114
|
8 |
|
public function getQueryResult( $arguments = null ) { |
115
|
|
|
|
116
|
8 |
|
$queryResult = $this->getLibraryFactory()->newQueryResultFrom( |
117
|
8 |
|
$this->processLuaArguments( $arguments ) |
118
|
|
|
); |
119
|
|
|
|
120
|
8 |
|
if ( !$this->isAQueryResult( $queryResult ) ) { |
121
|
1 |
|
return [ $queryResult ]; |
122
|
|
|
} |
123
|
|
|
|
124
|
7 |
|
$result = $queryResult->toArray(); |
125
|
|
|
|
126
|
7 |
|
if( !empty( $result["results"] ) ) { |
127
|
|
|
// as of now, "results" has page names as keys. lua is not very good, keeping non-number keys in order |
128
|
|
|
// so replace string keys with the corresponding number, starting with 0. |
129
|
3 |
|
$result["results"] = array_combine( range( 0, count( $result["results"] ) - 1 ), array_values( $result["results"] ) ); |
130
|
|
|
} |
131
|
|
|
|
132
|
7 |
|
return [ $this->convertArrayToLuaTable( $result ) ]; |
133
|
|
|
} |
134
|
|
|
|
135
|
|
|
/** |
136
|
|
|
* This mirrors the functionality of the parser function #info and makes it |
137
|
|
|
* available to lua. |
138
|
|
|
* |
139
|
|
|
* @since 1.0 |
140
|
|
|
* |
141
|
|
|
* @param string $text text to show inside the info popup |
142
|
|
|
* @param string $icon identifier for the icon to use |
143
|
|
|
* |
144
|
|
|
* @return string[] |
145
|
|
|
*/ |
146
|
7 |
|
public function info( $text, $icon = 'info' ) { |
147
|
|
|
|
148
|
|
|
// do some parameter processing |
149
|
7 |
|
if ( ! trim( $text ) || ! is_string( $text ) ) { |
150
|
|
|
// no info-text present, or wrong type. abort |
151
|
3 |
|
return null; |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
// check if icon is set and valid |
155
|
5 |
|
if ( !is_string( $icon ) || !in_array( $icon, [ 'note', 'warning' ] ) ) { |
156
|
5 |
|
$icon = 'info'; |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
// the actual info message is easy to create: |
160
|
5 |
|
$result = smwfEncodeMessages( |
161
|
5 |
|
[ $text ], |
162
|
5 |
|
$icon, |
163
|
5 |
|
' <!--br-->', |
164
|
5 |
|
false // No escaping. |
165
|
|
|
); |
166
|
|
|
|
167
|
|
|
// to have all necessary data committed to output, use SMWOutputs::commitToParser() |
168
|
5 |
|
SMWOutputs::commitToParser( |
169
|
5 |
|
$this->getEngine()->getParser() |
170
|
|
|
); |
171
|
|
|
|
172
|
5 |
|
return [ $this->doPostProcessParserFunctionCallResult( $result ) ]; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* This mirrors the functionality of the parser function #set and makes it |
177
|
|
|
* available in lua. |
178
|
|
|
* |
179
|
|
|
* @since 1.0 |
180
|
|
|
* |
181
|
|
|
* @param string|array $arguments arguments passed from lua, string or array depending on call |
182
|
|
|
* |
183
|
|
|
* @return null|array|array[] |
184
|
|
|
*/ |
185
|
20 |
|
public function set( $arguments ) { |
186
|
|
|
|
187
|
20 |
|
$arguments = $this->processLuaArguments( $arguments ); |
188
|
|
|
|
189
|
20 |
|
$setParserFunction = $this->getLibraryFactory()->newSetParserFunction( |
190
|
20 |
|
$this->getEngine()->getParser() |
191
|
|
|
); |
192
|
|
|
|
193
|
20 |
|
$parserFunctionCallResult = $setParserFunction->parse( |
194
|
20 |
|
$this->getLibraryFactory()->newParserParameterProcessorFrom( $arguments ) |
195
|
|
|
); |
196
|
|
|
|
197
|
|
|
// get usable result |
198
|
20 |
|
$result = $this->doPostProcessParserFunctionCallResult( |
199
|
20 |
|
$parserFunctionCallResult |
200
|
|
|
); |
201
|
|
|
|
202
|
20 |
|
if ( strlen( $result ) ) { |
203
|
|
|
// if result is a non empty string, assume an error message |
204
|
3 |
|
return [ [ 1 => false, self::SMW_ERROR_FIELD => preg_replace( '/<[^>]+>/', '', $result ) ] ]; |
205
|
|
|
} |
206
|
|
|
|
207
|
|
|
// on success, return true |
208
|
18 |
|
return [ 1 => true ]; |
209
|
|
|
} |
210
|
|
|
|
211
|
|
|
/** |
212
|
|
|
* This mirrors the functionality of the parser function #subobject and |
213
|
|
|
* makes it available to lua. |
214
|
|
|
* |
215
|
|
|
* @param string|array $arguments arguments passed from lua, string or array depending on call |
216
|
|
|
* @param string $subobjectId if you need to manually assign an id, do this here |
217
|
|
|
* |
218
|
|
|
* @return null|array|array[] |
219
|
|
|
*/ |
220
|
23 |
|
public function subobject( $arguments, $subobjectId = null ) { |
221
|
|
|
|
222
|
23 |
|
$arguments = $this->processLuaArguments( $arguments ); |
223
|
|
|
|
224
|
|
|
// parameters[0] would be the subobject id, so unshift |
225
|
23 |
|
array_unshift( $arguments, null ); |
226
|
|
|
|
227
|
|
|
// if subobject id was set, put it on position 0 |
228
|
23 |
|
if ( !is_null( $subobjectId ) && $subobjectId ) { |
229
|
|
|
// user deliberately set an id for this subobject |
230
|
11 |
|
$arguments[0] = $subobjectId; |
231
|
|
|
|
232
|
|
|
// we need to ksort, otherwise ParameterProcessorFactory doesn't |
233
|
|
|
// recognize the id |
234
|
11 |
|
ksort( $arguments ); |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
// prepare subobjectParserFunction object |
238
|
23 |
|
$subobjectParserFunction = $this->getLibraryFactory()->newSubobjectParserFunction( |
239
|
23 |
|
$this->getEngine()->getParser() |
240
|
|
|
); |
241
|
|
|
|
242
|
23 |
|
$parserFunctionCallResult = $subobjectParserFunction->parse( |
243
|
23 |
|
$this->getLibraryFactory()->newParserParameterProcessorFrom( $arguments ) |
244
|
|
|
); |
245
|
|
|
|
246
|
23 |
|
if ( strlen( $result = $this->doPostProcessParserFunctionCallResult( $parserFunctionCallResult ) ) ) { |
247
|
|
|
// if result a non empty string, assume an error message |
248
|
4 |
|
return [ [ 1 => false, self::SMW_ERROR_FIELD => preg_replace( '/<[^>]+>/', '', $result ) ] ]; |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
// on success, return true |
252
|
19 |
|
return [ 1 => true ]; |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
/** |
256
|
|
|
* This takes an array and converts it so, that the result is a viable lua table. |
257
|
|
|
* I.e. the resulting table has its numerical indices start with 1 |
258
|
|
|
* If `$ar` is not an array, it is simply returned |
259
|
|
|
* @param mixed $ar |
260
|
|
|
* @return mixed array |
261
|
|
|
*/ |
262
|
15 |
|
private function convertArrayToLuaTable( $ar ) { |
263
|
|
|
|
264
|
15 |
|
if ( is_array( $ar) ) { |
265
|
10 |
|
foreach ( $ar as $key => $value ) { |
266
|
10 |
|
$ar[$key] = $this->convertArrayToLuaTable( $value ); |
267
|
|
|
} |
268
|
10 |
|
array_unshift( $ar, '' ); |
269
|
10 |
|
unset( $ar[0] ); |
270
|
|
|
} |
271
|
15 |
|
return $ar; |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
/** |
275
|
|
|
* Takes a result returned from a parser function call and prepares it to be |
276
|
|
|
* used as parsed string. |
277
|
|
|
* |
278
|
|
|
* @since 1.0 |
279
|
|
|
* |
280
|
|
|
* @param string|array $parserFunctionResult |
281
|
|
|
* |
282
|
|
|
* @return string |
283
|
|
|
*/ |
284
|
48 |
|
private function doPostProcessParserFunctionCallResult( $parserFunctionResult ) { |
285
|
|
|
|
286
|
|
|
// parser function call can return string or array |
287
|
48 |
|
if ( is_array( $parserFunctionResult ) ) { |
288
|
20 |
|
$result = $parserFunctionResult[0]; |
289
|
20 |
|
$noParse = isset( $parserFunctionResult['noparse'] ) ? $parserFunctionResult['noparse'] : true; |
290
|
|
|
} else { |
291
|
28 |
|
$result = $parserFunctionResult; |
292
|
28 |
|
$noParse = true; |
293
|
|
|
} |
294
|
|
|
|
295
|
48 |
|
if ( !$noParse ) { |
296
|
|
|
$result = $this->getEngine()->getParser()->recursiveTagParseFully( $result ); |
297
|
|
|
} |
298
|
|
|
|
299
|
48 |
|
return trim( $result ); |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
/** |
303
|
|
|
* Returns the LibraryFactory singleton (and creates it first, if not already present) |
304
|
|
|
* |
305
|
|
|
* @since 1.0 |
306
|
|
|
* |
307
|
|
|
* @return LibraryFactory |
308
|
|
|
*/ |
309
|
59 |
|
private function getLibraryFactory() { |
310
|
|
|
|
311
|
59 |
|
if ( $this->libraryFactory !== null ) { |
312
|
53 |
|
return $this->libraryFactory; |
313
|
|
|
} |
314
|
|
|
|
315
|
59 |
|
$this->libraryFactory = new LibraryFactory( |
316
|
59 |
|
ApplicationFactory::getInstance()->getStore() |
317
|
|
|
); |
318
|
|
|
|
319
|
59 |
|
return $this->libraryFactory; |
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
/** |
323
|
|
|
* Tests, if supplied parameter `$queryResult` is a valid {@see QueryResult} |
324
|
|
|
* |
325
|
|
|
* @since 1.0 |
326
|
|
|
* |
327
|
|
|
* @param mixed $queryResult |
328
|
|
|
* |
329
|
|
|
* @return bool |
330
|
|
|
*/ |
331
|
16 |
|
private function isAQueryResult( $queryResult ) { |
332
|
16 |
|
return is_a( $queryResult, QueryResult::class ); |
333
|
|
|
} |
334
|
|
|
|
335
|
|
|
/** |
336
|
|
|
* Takes the $arguments passed from lua and pre-processes them: make sure, |
337
|
|
|
* we have a sequence array (not associative) |
338
|
|
|
* |
339
|
|
|
* @since 1.0 |
340
|
|
|
* |
341
|
|
|
* @param string|array $arguments |
342
|
|
|
* |
343
|
|
|
* @return array |
344
|
|
|
*/ |
345
|
59 |
|
private function processLuaArguments( $arguments ) { |
346
|
|
|
|
347
|
|
|
// make sure, we have an array of parameters |
348
|
59 |
|
if ( !is_array( $arguments ) ) { |
349
|
21 |
|
$arguments = preg_split( "/(?<=[^\|])\|(?=[^\|])/", $arguments ); |
350
|
|
|
} |
351
|
|
|
|
352
|
|
|
// if $arguments were supplied as key => value pair (aka associative array), |
353
|
|
|
// we rectify this here |
354
|
59 |
|
$processedArguments = []; |
355
|
59 |
|
foreach ( $arguments as $key => $value ) { |
356
|
55 |
|
if ( is_array( $value ) ) { |
357
|
|
|
// user supplied data in form property => [ 'value1', 'value2' ] |
358
|
2 |
|
foreach ( $value as $item ) { |
359
|
2 |
|
$processedArguments[] = $key . '=' . $item; |
360
|
|
|
} |
361
|
|
|
} else { |
362
|
53 |
|
if ( !is_int($key) && !preg_match('/^[0-9]+$/', $key) ) { |
363
|
22 |
|
$value = (string)$key . '=' . (string)$value; |
364
|
|
|
} |
365
|
55 |
|
$processedArguments[] = $value; |
366
|
|
|
} |
367
|
|
|
} |
368
|
|
|
|
369
|
59 |
|
return $processedArguments; |
370
|
|
|
} |
371
|
|
|
|
372
|
|
|
} |
373
|
|
|
|
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.