Completed
Push — master ( 27c003...7bb1fe )
by mw
16:46
created

ScribuntoLuaLibrary::subobject()   B

Complexity

Conditions 6
Paths 9

Size

Total Lines 40
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 6.1215

Importance

Changes 0
Metric Value
cc 6
eloc 17
nc 9
nop 2
dl 0
loc 40
ccs 17
cts 20
cp 0.85
crap 6.1215
rs 8.439
c 0
b 0
f 0
1
<?php
2
3
namespace SMW\Scribunto;
4
5
use Scribunto_LuaLibraryBase;
6
use SMW\DIProperty;
7
8
use SMWQueryProcessor as QueryProcessor;
9
use SMW\ApplicationFactory;
10
use SMW\ParameterProcessorFactory;
11
use SMW\ParserFunctionFactory;
12
use SMWOutputs;
13
14
/**
15
 * @license GNU GPL v2+
16
 * @since 1.0
17
 *
18
 * @author mwjames
19
 */
20
class ScribuntoLuaLibrary extends Scribunto_LuaLibraryBase {
21
22
	/**
23
	 * This is the name of the key for error messages
24
	 *
25
	 * @var string
26
	 * @since 1.0
27
	 */
28
	const SMW_ERROR_FIELD = 'error';
29
30
	/**
31
	 * @since 1.0
32
	 */
33
	public function register() {
34
35 13
		$lib = array(
36
			'getPropertyType' => array( $this, 'getPropertyType' ),
37
			'getQueryResult'  => array( $this, 'getQueryResult' ),
38 13
			'info'            => array( $this, 'info' ),
39 13
			'set'             => array( $this, 'set' ),
40 13
			'subobject'       => array( $this, 'subobject' ),
41 13
		);
42 13
43
		$this->getEngine()->registerInterface( __DIR__ . '/' . 'mw.smw.lua', $lib, array() );
44 13
	}
45 13
46
	/**
47
	 * Returns query results in for of the standard API return format
48
	 *
49
	 * @since 1.0
50
	 *
51
	 * @param string|array $arguments
52
	 *
53
	 * @return array
54
	 */
55
	public function getQueryResult( $arguments = null ) {
56 2
57
		$rawParameters = $this->processLuaArguments( $arguments );
58 2
59
		list( $queryString, $parameters, $printouts ) = QueryProcessor::getComponentsFromFunctionParams(
60 2
		    $rawParameters,
61 2
		    false
62
		);
63 2
64
		QueryProcessor::addThisPrintout( $printouts, $parameters );
65 2
66
		$query = QueryProcessor::createQuery(
67 2
		    $queryString,
68 2
		    QueryProcessor::getProcessedParams( $parameters, $printouts ),
69 2
		    QueryProcessor::SPECIAL_PAGE,
70 2
		    '',
71 2
		    $printouts
72
		);
73 2
74
		$queryResult = ApplicationFactory::getInstance()->getStore()->getQueryResult( $query )->toArray();
75 2
		if(!empty($queryResult["results"])) {
76 2
		    $queryResult["results"] = array_combine(range(1, count($queryResult["results"])), array_values($queryResult["results"]));
77
		}
78
		return array( $queryResult );
79 2
	}
80
81
	/**
82
	 * Returns property type
83
	 *
84
	 * @since 1.0
85
	 *
86
	 * @param string $propertyName
87
	 *
88
	 * @return array
89
	 */
90
	public function getPropertyType( $propertyName = null ) {
91 3
92
		$this->checkType( 'getPropertyType', 1, $propertyName, 'string' );
93 3
		$propertyName = trim( $propertyName );
94 3
95
		if ( $propertyName === '' ) {
96 3
			return array( null );
97 1
		}
98
99
		$property = DIProperty::newFromUserLabel( $propertyName );
100 2
101
		if ( $property === null ) {
102 2
			return array( null );
103
		}
104
105
		return array( $property->findPropertyTypeID() );
106 2
	}
107
108
	/**
109
	 * This mirrors the functionality of the parser function #info and makes it available to lua.
110
	 *
111
	 * @since 1.0
112
	 *
113
	 * @param string $text text to show inside the info popup
114
	 * @param string $icon identifier for the icon to use
115
	 *
116
	 * @uses \SMW\ParserFunctionFactory::__construct
117
	 *
118
	 * @return string[]
119
	 */
120
	public function info( $text, $icon = 'info' ) {
121 4
122
		$parser = $this->getEngine()->getParser();
123 4
124
		// do some parameter processing
125
		if ( ! trim( $text ) || ! is_string( $text ) ) {
126 4
			// no info-text present, or wrong type. abort
127
			return null;
128 1
		}
129
130
		// check if icon is set and valid
131
		if ( !is_string( $icon ) || !in_array( $icon, [ 'note', 'warning' ] ) ) {
132 3
			$icon = 'info';
133 3
		}
134 3
135
		// the actual info message is easy to create:
136
		$result = smwfEncodeMessages(
137 4
			array( $text ),
138 3
			$icon,
139 3
			' <!--br-->',
140 3
			false // No escaping.
141
		);
142 3
143
		// to have all necessary data committed to output, use SMWOutputs::commitToParser()
144
		SMWOutputs::commitToParser( $parser );
145 3
146
		return array( $this->getParsedResult( $result ) );
147 3
	}
148
149
	/**
150
	 * This mirrors the functionality of the parser function #set and makes it available in lua.
151
	 *
152
	 * @since 1.0
153
	 *
154
	 * @param string|array $parameters parameters passed from lua, string or array depending on call
155
	 *
156
	 * @uses \SMW\ParserFunctionFactory::__construct, ParameterProcessorFactory::newFromArray
157
	 *
158
	 * @return null|array|array[]
159
	 */
160
	public function set( $parameters ) {
161 4
162
		$parser = $this->getEngine()->getParser();
163 4
164
		// if we have no arguments, do nothing
165
		if ( !sizeof( $arguments = $this->processLuaArguments( $parameters ) ) ) {
166 4
			return null;
167 1
		}
168
169
		// prepare setParserFunction object
170
		$parserFunctionFactory = new ParserFunctionFactory( $parser );
171 3
		$setParserFunction = $parserFunctionFactory->newSetParserFunction( $parser );
172 3
173
		// call parse on setParserFunction
174
		$parserFunctionCallResult = $setParserFunction->parse(
175 3
			ParameterProcessorFactory::newFromArray( $arguments )
176 3
		);
177 3
178
		// get usable result
179
		$result = $this->getParsedResult( $parserFunctionCallResult );
180 3
181
		if ( strlen( $result ) ) {
182 3
			// if result a non empty string, assume an error message
183
			return array( [ 1 => false, self::SMW_ERROR_FIELD => preg_replace( '/<[^>]+>/', '', $result ) ] );
184 1
		} else {
185
			// on success, return true
186
			return array( 1 => true );
187 2
		}
188
	}
189
190
	/**
191
	 * This mirrors the functionality of the parser function #subobject and makes it available to lua.
192
	 *
193
	 * @param string|array $parameters parameters passed from lua, string or array depending on call
194
	 * @param string $subobjectId if you need to manually assign an id, do this here
195
	 *
196
	 * @uses \SMW\ParserFunctionFactory::__construct, \SMW\ParameterProcessorFactory::newFromArray
197
	 *
198
	 * @return null|array|array[]
199
	 */
200 6
	public function subobject( $parameters, $subobjectId = null ) {
201
202
		$parser = $this->getEngine()->getParser();
203 6
204 3
		// if we have no arguments, do nothing
205 3
		if ( !sizeof( $arguments = $this->processLuaArguments( $parameters ) ) ) {
206 3
			return null;
207 3
		}
208 3
209
		# parameters[0] would be the subobject id, so unshift
210
		if ( isset( $arguments[0] ) ) {
211 6
			array_unshift( $arguments, null );
212
		}
213
214
		# if subobject id was set, put it on position 0
215 6
		if ( !is_null( $subobjectId ) && $subobjectId ) {
216
			# user deliberately set an id for this subobject
217
			$arguments[0] = $subobjectId;
218
219
			# we need to ksort, otherwise ParameterProcessorFactory doesn't recognize the id
220
			ksort( $arguments );
221
		}
222
223
		# prepare subobjectParserFunction object
224
		$parserFunctionFactory = new ParserFunctionFactory( $parser );
225
		$subobjectParserFunction = $parserFunctionFactory->newSubobjectParserFunction( $parser );
226
227 4
		# pre-process the parameters for the subobject
228
		$processedParameter = ParameterProcessorFactory::newFromArray( $arguments );
229
230 4
		$parserFunctionCallResult = $subobjectParserFunction->parse( $processedParameter );
231 4
232 4
		if ( strlen( $result = $this->getParsedResult( $parserFunctionCallResult ) ) ) {
233
			// if result a non empty string, assume an error message
234
			return array( [ 1 => false, self::SMW_ERROR_FIELD => preg_replace( '/<[^>]+>/', '', $result ) ] );
235 4
		} else {
236 4
			// on success, return true
237 4
			return array( 1 => true );
238 1
		}
239
	}
240 4
241
	/**
242 3
	 * Takes a result returned from a parser function call and prepares it to be used as parsed string.
243 3
	 *
244 4
	 * @since 1.0
245
	 *
246 4
	 * @param string|array $parserFunctionResult
247
	 *
248
	 * @return string
249
	 */
250
	private function getParsedResult( $parserFunctionResult ) {
251
252
		// parser function call can return string or array
253
		if ( is_array( $parserFunctionResult ) ) {
254
			$result = $parserFunctionResult[0];
255
			$noParse = isset($parserFunctionResult['noparse']) ? $parserFunctionResult['noparse'] : true;
256
		} else {
257
			$result = $parserFunctionResult;
258
			$noParse = true;
259
		}
260
261
		if ( ! $noParse ) {
262
			$result = $this->getEngine()->getParser()->recursiveTagParseFully( $result );
263
		}
264
265
		return trim( $result );
266
	}
267
268
	/**
269
	 * Takes the $arguments passed from lua and pre-processes them: make sure, we have a sequence array (not associative)
270
	 *
271
	 * @since 1.0
272
	 *
273
	 * @param string|array $arguments
274
	 *
275
	 * @return array
276
	 */
277
	private function processLuaArguments( $arguments ) {
278
279
		// make sure, we have an array of parameters
280
		if ( !is_array( $arguments ) ) {
281
			$arguments = preg_split( "/(?<=[^\|])\|(?=[^\|])/", $arguments );
282
		}
283
284
		// if $arguments were supplied as key => value pair (aka associative array), we rectify this here
285
		$processedArguments = array();
286
		foreach ( $arguments as $key => $value ) {
287
			if ( !is_int( $key ) && !preg_match( '/[0-9]+/', $key ) ) {
288
				$value = (string) $key . '=' . (string) $value;
289
			}
290
			if ( $value ) {
291
				// only add, when value is set. could be empty, if lua function was called with no parameter or empty string
292
				$processedArguments[] = $value;
293
			}
294
		}
295
296
		return $processedArguments;
297
	}
298
299
}
300