SMWQueryProcessor   C
last analyzed

Complexity

Total Complexity 58

Size/Duplication

Total Lines 574
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 13

Test Coverage

Coverage 96.43%

Importance

Changes 0
Metric Value
dl 0
loc 574
ccs 162
cts 168
cp 0.9643
rs 6.3005
c 0
b 0
f 0
wmc 58
lcom 1
cbo 13

16 Methods

Rating   Name   Duplication   Size   Complexity  
A getQueryAndParamsFromFunctionParams() 0 12 2
A getResultFromFunctionParams() 0 11 2
A getResultFromQueryString() 0 8 1
B getResultFromQuery() 0 38 6
A getStoreFromParams() 0 3 1
A getResultPrinter() 0 11 2
B getParameters() 0 88 4
A getSourceParam() 0 8 3
A getFormatParameters() 0 11 2
A getSortKeys() 0 3 1
A processFunctionParams() 0 3 1
A getProcessedParams() 0 5 1
A getValidatorForParams() 0 14 1
C createQuery() 0 59 11
B addThisPrintout() 0 12 5
C getComponentsFromFunctionParams() 0 70 15

How to fix   Complexity   

Complex Class

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

1
<?php
2
3
use ParamProcessor\Options;
4
use ParamProcessor\Param;
5
use ParamProcessor\ParamDefinition;
6
use ParamProcessor\Processor;
7
use SMW\Query\PrintRequest;
8
use SMW\Query\PrintRequestFactory;
9
use SMW\ApplicationFactory;
10
use SMW\Message;
11
use SMW\Query\QueryContext;
12
use SMW\Query\ResultFormatNotFoundException;
13
14
/**
15
 * This file contains a static class for accessing functions to generate and execute
16
 * semantic queries and to serialise their results.
17
 *
18
 * @ingroup SMWQuery
19
 * @author Markus Krötzsch
20
 */
21
22
/**
23
 * Static class for accessing functions to generate and execute semantic queries
24
 * and to serialise their results.
25
 * @ingroup SMWQuery
26
 */
27
class SMWQueryProcessor implements QueryContext {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
28
29
	/**
30
	 * Takes an array of unprocessed parameters, processes them using
31
	 * Validator, and returns them.
32
	 *
33
	 * Both input and output arrays are
34
	 * param name (string) => param value (mixed)
35
	 *
36
	 * @since 1.6.2
37
	 * The return value changed in SMW 1.8 from an array with result values
38
	 * to an array with Param objects.
39
	 *
40
	 * @param array $params
41
	 * @param array $printRequests
42
	 * @param boolean $unknownInvalid
43
	 *
44
	 * @return Param[]
45
	 */
46 111
	public static function getProcessedParams( array $params, array $printRequests = array(), $unknownInvalid = true ) {
47 111
		$validator = self::getValidatorForParams( $params, $printRequests, $unknownInvalid );
48 111
		$validator->processParameters();
49 111
		return $validator->getParameters();
0 ignored issues
show
Deprecated Code introduced by
The method ParamProcessor\Processor::getParameters() has been deprecated with message: since 1.0

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.

Loading history...
50
	}
51
52
	/**
53
	 * Takes an array of unprocessed parameters,
54
	 * and sets them on a new Validator object,
55
	 * which is returned and ready to process the parameters.
56
	 *
57
	 * @since 1.8
58
	 *
59
	 * @param array $params
60
	 * @param array $printRequests
61
	 * @param boolean $unknownInvalid
62
	 *
63
	 * @return Processor
64
	 */
65 111
	public static function getValidatorForParams( array $params, array $printRequests = array(), $unknownInvalid = true ) {
66 111
		$paramDefinitions = self::getParameters();
67
68 111
		$paramDefinitions['format']->setPrintRequests( $printRequests );
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface ParamProcessor\IParamDefinition as the method setPrintRequests() does only exist in the following implementations of said interface: SMWParamFormat.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
69
70 111
		$processorOptions = new Options();
71 111
		$processorOptions->setUnknownInvalid( $unknownInvalid );
72
73 111
		$validator = Processor::newFromOptions( $processorOptions );
74
75 111
		$validator->setParameters( $params, $paramDefinitions, false );
0 ignored issues
show
Unused Code introduced by
The call to Processor::setParameters() has too many arguments starting with false.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
76
77 111
		return $validator;
78
	}
79
80
	/**
81
	 * Parse a query string given in SMW's query language to create
82
	 * an SMWQuery. Parameters are given as key-value-pairs in the
83
	 * given array. The parameter $context defines in what context the
84
	 * query is used, which affects ceretain general settings.
85
	 * An object of type SMWQuery is returned.
86
	 *
87
	 * The format string is used to specify the output format if already
88
	 * known. Otherwise it will be determined from the parameters when
89
	 * needed. This parameter is just for optimisation in a common case.
90
	 *
91
	 * @param string $queryString
92
	 * @param array $params These need to be the result of a list fed to getProcessedParams
93
	 * @param $context
94
	 * @param string $format
95
	 * @param array $extraPrintouts
96
	 *
97
	 * @return SMWQuery
98
	 */
99 111
	static public function createQuery( $queryString, array $params, $context = self::INLINE_QUERY, $format = '', array $extraPrintouts = array(), $contextPage = null ) {
0 ignored issues
show
Coding Style introduced by
createQuery uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
100
101 111
		if ( $format === '' || is_null( $format ) ) {
102 109
			$format = $params['format']->getValue();
103
		}
104
105 111
		$defaultSort = 'ASC';
106
107 111
		if ( $format == 'count' ) {
108 2
			$queryMode = SMWQuery::MODE_COUNT;
109 110
		} elseif ( $format == 'debug' ) {
110 1
			$queryMode = SMWQuery::MODE_DEBUG;
111
		} else {
112 109
			$printer = self::getResultPrinter( $format, $context );
113 109
			$queryMode = $printer->getQueryMode( $context );
114 109
			$defaultSort = $printer->getDefaultSort();
115
		}
116
117
		// set mode, limit, and offset:
118 111
		$offset = 0;
119 111
		$limit = $GLOBALS['smwgQDefaultLimit'];
120
121 111
		if ( ( array_key_exists( 'offset', $params ) ) && ( is_int( $params['offset']->getValue() + 0 ) ) ) {
122 111
			$offset = $params['offset']->getValue();
123
		}
124
125 111
		if ( ( array_key_exists( 'limit', $params ) ) && ( is_int( trim( $params['limit']->getValue() ) + 0 ) ) ) {
126 111
			$limit = $params['limit']->getValue();
127
128
			// limit < 0: always show further results link only
129 111
			if ( ( trim( $params['limit']->getValue() ) + 0 ) < 0 ) {
130
				$queryMode = SMWQuery::MODE_NONE;
131
			}
132
		}
133
134
		// largest possible limit for "count", even inline
135 111
		if ( $queryMode == SMWQuery::MODE_COUNT ) {
136 2
			$offset = 0;
137 2
			$limit = $GLOBALS['smwgQMaxLimit'];
138
		}
139
140 111
		$queryCreator = ApplicationFactory::getInstance()->getQueryFactory()->newQueryCreator();
141
142 111
		$queryCreator->setConfiguration(  array(
143 111
			'extraPrintouts' => $extraPrintouts,
144 111
			'queryMode'   => $queryMode,
145 111
			'context'     => $context,
146 111
			'contextPage' => $contextPage,
147 111
			'offset'      => $offset,
148 111
			'limit'       => $limit,
149 111
			'querySource' => $params['source']->getValue(),
150 111
			'mainLabel'   => $params['mainlabel']->getValue(),
151 111
			'sort'        => $params['sort']->getValue(),
152 111
			'order'       => $params['order']->getValue(),
153 111
			'defaultSort' => $defaultSort
154
		) );
155
156 111
		return $queryCreator->create( $queryString );
157
	}
158
159
	/**
160
	 * @deprecated since 2.5, This method should no longer be used but since it
161
	 * was made protected (and therefore can be derived from) it will remain until
162
	 * 3.0 to avoid a breaking BC.
163
	 *
164
	 * Takes the sort and order parameters and returns a list of sort keys and a list of errors.
165
	 *
166
	 * @since 1.7
167
	 *
168
	 * @param array $sortParam
169
	 * @param array $orders
0 ignored issues
show
Bug introduced by
There is no parameter named $orders. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
170
	 * @param string $defaultSort
171
	 *
172
	 * @return array ( keys => array(), errors => array() )
173
	 */
174
	protected static function getSortKeys( array $sortParam, array $orderParam, $defaultSort ) {
175
		return ApplicationFactory::getInstance()->getQueryFactory()->newConfigurableQueryCreator()->getSortKeys( $sortParam, $orderParam, $defaultSort );
0 ignored issues
show
Bug introduced by
The method newConfigurableQueryCreator() does not seem to exist on object<SMW\QueryFactory>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
176
	}
177
178
	/**
179
	 * Add the subject print request, unless mainlabel is set to "-".
180
	 *
181
	 * @since 1.7
182
	 *
183
	 * @param array $printRequests
184
	 * @param array $rawParams
185
	 */
186 104
	public static function addThisPrintout( array &$printRequests, array $rawParams ) {
187 104
		if ( !is_null( $printRequests ) ) {
188 104
			$hasMainlabel = array_key_exists( 'mainlabel', $rawParams );
189
190 104
			if  ( !$hasMainlabel || trim( $rawParams['mainlabel'] ) !== '-' ) {
191 103
				array_unshift( $printRequests, new PrintRequest(
192 103
					PrintRequest::PRINT_THIS,
193 103
					$hasMainlabel ? $rawParams['mainlabel'] : ''
194
				) );
195
			}
196
		}
197 104
	}
198
199
	/**
200
	 * Preprocess a query as given by an array of parameters as is typically
201
	 * produced by the #ask parser function. The parsing results in a querystring,
202
	 * an array of additional parameters, and an array of additional SMWPrintRequest
203
	 * objects, which are filled into call-by-ref parameters.
204
	 * $showMode is true if the input should be treated as if given by #show
205
	 *
206
	 * @param array $rawParams
207
	 * @param string $querystring
208
	 * @param array $params
209
	 * @param array $printouts array of SMWPrintRequest
210
	 * @param boolean $showMode
211
	 * @deprecated Will vanish after SMW 1.8 is released.
212
	 * Use getComponentsFromFunctionParams which has a cleaner interface.
213
	 */
214
	static public function processFunctionParams( array $rawParams, &$querystring, &$params, &$printouts, $showMode = false ) {
0 ignored issues
show
Unused Code introduced by
The parameter $querystring is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $params is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $printouts is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
215
		list( $querystring, $params, $printouts ) = self::getComponentsFromFunctionParams( $rawParams, $showMode );
216
	}
217
218
219
	/**
220
	 * Preprocess a query as given by an array of parameters as is
221
	 * typically produced by the #ask parser function or by Special:Ask.
222
	 * The parsing results in a querystring, an array of additional
223
	 * parameters, and an array of additional SMWPrintRequest objects,
224
	 * which are returned in an array with three components. If
225
	 * $showMode is true then the input will be processed as if for #show.
226
	 * This uses a slightly different way to get the query, and different
227
	 * default labels (empty) for additional print requests.
228
	 *
229
	 * @param array $rawParams
230
	 * @param boolean $showMode
231
	 * @return array( string, array( string => string ), array( SMWPrintRequest ) )
0 ignored issues
show
Documentation introduced by
The doc-type array( could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
232
	 */
233 119
	static public function getComponentsFromFunctionParams( array $rawParams, $showMode ) {
0 ignored issues
show
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
234 119
		$queryString = '';
235 119
		$parameters = array();
236 119
		$printouts = array();
237
238 119
		$lastprintout = null;
239 119
		$printRequestFactory = new PrintRequestFactory();
240
241 119
		foreach ( $rawParams as $name => $rawParam ) {
242
			// special handling for arrays - this can happen if the
243
			// parameter came from a checkboxes input in Special:Ask:
244 118
			if ( is_array( $rawParam ) ) {
245
				$rawParam = implode( ',', array_keys( $rawParam ) );
246
			}
247
248
			// Bug 32955 / #640
249
			// Modify (e.g. replace `=`) a condition string only if enclosed by [[ ... ]]
250 118
			$rawParam = preg_replace_callback(
251 118
				'/\[\[([^\[\]]*)\]\]/xu',
252 118
				function( array $matches ) {
253 113
					return str_replace( array( '=' ), array( '-3D' ), $matches[0] );
254 118
				},
255
				$rawParam
256
			);
257
258
			// #1258 (named_args -> named args)
259
			// accept 'name' => 'value' just as '' => 'name=value':
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
260 118
			if ( is_string( $name ) && ( $name !== '' ) ) {
261
				$rawParam = str_replace( "_", " ", $name ) . '=' . $rawParam;
262
			}
263
264 118
			if ( $rawParam === '' ) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
265 118
			} elseif ( $rawParam { 0 } == '?' ) { // print statement
266 85
				$rawParam = substr( $rawParam, 1 );
267 85
				$lastprintout = $printRequestFactory->newPrintRequestFromText( $rawParam, $showMode );
268 85
				if ( !is_null( $lastprintout ) ) {
269 85
					$printouts[] = $lastprintout;
270
				}
271 118
			} elseif ( $rawParam[0] == '+' ) { // print request parameter
272 10
				if ( !is_null( $lastprintout ) ) {
273 9
					$rawParam = substr( $rawParam, 1 );
274 9
					$parts = explode( '=', $rawParam, 2 );
275 9
					if ( count( $parts ) == 2 ) {
276 9
						$lastprintout->setParameter( trim( $parts[0] ), $parts[1] );
277
					} else {
278 10
						$lastprintout->setParameter( trim( $parts[0] ), null );
279
					}
280
				}
281
			} else { // parameter or query
282
283
				// #1645
284 118
				$parts = $showMode && $name == 0 ? $rawParam : explode( '=', $rawParam, 2 );
285
286 118
				if ( count( $parts ) >= 2 ) {
287
					// don't trim here, some parameters care for " "
288 86
					$parameters[strtolower( trim( $parts[0] ) )] = $parts[1];
289
				} else {
290 118
					$queryString .= $rawParam;
291
				}
292
			}
293
		}
294
295 119
		$queryString = str_replace( array( '&lt;', '&gt;', '-3D' ), array( '<', '>', '=' ), $queryString );
296
297 119
		if ( $showMode ) {
298 13
			$queryString = "[[:$queryString]]";
299
		}
300
301 119
		return array( $queryString, $parameters, $printouts);
302
	}
303
304
	/**
305
	 * Process and answer a query as given by an array of parameters as is
306
	 * typically produced by the #ask parser function. The parameter
307
	 * $context defines in what context the query is used, which affects
308
	 * certain general settings.
309
	 *
310
	 * The main task of this function is to preprocess the raw parameters
311
	 * to obtain actual parameters, printout requests, and the query string
312
	 * for further processing.
313
	 *
314
	 * @since 1.8
315
	 * @param array $rawParams user-provided list of unparsed parameters
316
	 * @param integer $outputMode SMW_OUTPUT_WIKI, SMW_OUTPUT_HTML, ...
317
	 * @param integer $context INLINE_QUERY, SPECIAL_PAGE, CONCEPT_DESC
318
	 * @param boolean $showMode process like #show parser function?
319
	 * @return array( SMWQuery, array of IParam )
0 ignored issues
show
Documentation introduced by
The doc-type array( could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
320
	 */
321 105
	static public function getQueryAndParamsFromFunctionParams( array $rawParams, $outputMode, $context, $showMode, $contextPage = null ) {
0 ignored issues
show
Unused Code introduced by
The parameter $outputMode is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
322 105
		list( $queryString, $params, $printouts ) = self::getComponentsFromFunctionParams( $rawParams, $showMode );
323
324 105
		if ( !$showMode ) {
325 101
			self::addThisPrintout( $printouts, $params );
326
		}
327
328 105
		$params = self::getProcessedParams( $params, $printouts );
329
330 105
		$query  = self::createQuery( $queryString, $params, $context, '', $printouts, $contextPage );
331 105
		return array( $query, $params );
332
	}
333
334
	/**
335
	 * Process and answer a query as given by an array of parameters as is
336
	 * typically produced by the #ask parser function. The result is formatted
337
	 * according to the specified $outputformat. The parameter $context defines
338
	 * in what context the query is used, which affects ceretain general settings.
339
	 *
340
	 * The main task of this function is to preprocess the raw parameters to
341
	 * obtain actual parameters, printout requests, and the query string for
342
	 * further processing.
343
	 *
344
	 * @note Consider using getQueryAndParamsFromFunctionParams() and
345
	 * getResultFromQuery() instead.
346
	 * @deprecated Will vanish after release of SMW 1.8.
347
	 * See SMW_Ask.php for example code on how to get query results from
348
	 * #ask function parameters.
349
	 */
350
	static public function getResultFromFunctionParams( array $rawParams, $outputMode, $context = self::INLINE_QUERY, $showMode = false ) {
0 ignored issues
show
Unused Code introduced by
The parameter $outputMode is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
351
		list( $queryString, $params, $printouts ) = self::getComponentsFromFunctionParams( $rawParams, $showMode );
352
353
		if ( !$showMode ) {
354
			self::addThisPrintout( $printouts, $params );
355
		}
356
357
		$params = self::getProcessedParams( $params, $printouts );
358
359
		return self::getResultFromQueryString( $queryString, $params, $printouts, SMW_OUTPUT_WIKI, $context );
0 ignored issues
show
Deprecated Code introduced by
The method SMWQueryProcessor::getResultFromQueryString() has been deprecated with message: Will vanish after release of SMW 1.8.
See SMW_Ask.php for example code on how to get query results from
#ask function parameters.

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.

Loading history...
360
	}
361
362
	/**
363
	 * Process a query string in SMW's query language and return a formatted
364
	 * result set as specified by $outputmode. A parameter array of key-value-pairs
365
	 * constrains the query and determines the serialisation mode for results. The
366
	 * parameter $context defines in what context the query is used, which affects
367
	 * certain general settings. Finally, $extraprintouts supplies additional
368
	 * printout requests for the query results.
369
	 *
370
	 * @param string $queryString
371
	 * @param array $params These need to be the result of a list fed to getProcessedParams
372
	 * @param $extraPrintouts
373
	 * @param $outputMode
374
	 * @param $context
375
	 *
376
	 * @return string
377
	 * @deprecated Will vanish after release of SMW 1.8.
378
	 * See SMW_Ask.php for example code on how to get query results from
379
	 * #ask function parameters.
380
	 */
381
	static public function getResultFromQueryString( $queryString, array $params, $extraPrintouts, $outputMode, $context = self::INLINE_QUERY ) {
0 ignored issues
show
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
382
383
		$query  = self::createQuery( $queryString, $params, $context, '', $extraPrintouts );
384
		$result = self::getResultFromQuery( $query, $params, $outputMode, $context );
385
386
387
		return $result;
388
	}
389
390
	/**
391
	 * Create a fully formatted result string from a query and its
392
	 * parameters. The method takes care of processing various types of
393
	 * query result. Most cases are handled by printers, but counting and
394
	 * debugging uses special code.
395
	 *
396
	 * @param SMWQuery $query
397
	 * @param array $params These need to be the result of a list fed to getProcessedParams
398
	 * @param integer $outputMode
399
	 * @param integer $context
400
	 * @since before 1.7, but public only since 1.8
401
	 *
402
	 * @return string
403
	 */
404 96
	public static function getResultFromQuery( SMWQuery $query, array $params, $outputMode, $context ) {
405
406 96
		$res = self::getStoreFromParams( $params )->getQueryResult( $query );
407 95
		$start = microtime( true );
408
409 95
		if ( ( $query->querymode == SMWQuery::MODE_INSTANCES ) ||
410 95
			( $query->querymode == SMWQuery::MODE_NONE ) ) {
411
412 93
			$printer = self::getResultPrinter( $params['format']->getValue(), $context );
413 93
			$result = $printer->getResult( $res, $params, $outputMode );
414
415 93
			$query->setOption( SMWQuery::PROC_PRINT_TIME, microtime( true ) - $start );
416 93
			return $result;
417
		} else { // result for counting or debugging is just a string or number
418
419 2
			if ( $res instanceof SMWQueryResult ) {
420 1
				$res = $res->getCountValue();
421
			}
422
423 2
			if ( is_numeric( $res ) ) {
424 1
				$res = strval( $res );
425
			}
426
427 2
			if ( is_string( $res ) ) {
428 2
				$result = str_replace( '_', ' ', $params['intro']->getValue() )
429 2
					. $res
430 2
					. str_replace( '_', ' ', $params['outro']->getValue() )
431 2
					. smwfEncodeMessages( $query->getErrors() );
432
			} else {
433
				// When no valid result was obtained, $res will be a SMWQueryResult.
434
				$result = smwfEncodeMessages( $query->getErrors() );
435
			}
436
437 2
			$query->setOption( SMWQuery::PROC_PRINT_TIME, microtime( true ) - $start );
438
439 2
			return $result;
440
		}
441
	}
442
443 96
	private static function getStoreFromParams( array $params ) {
444 96
		return ApplicationFactory::getInstance()->getQuerySourceFactory()->get( $params['source']->getValue() );
445
	}
446
447
	/**
448
	 * Find suitable SMWResultPrinter for the given format. The context in
449
	 * which the query is to be used determines some basic settings of the
450
	 * returned printer object. Possible contexts are
451
	 * SMWQueryProcessor::SPECIAL_PAGE, SMWQueryProcessor::INLINE_QUERY,
452
	 * SMWQueryProcessor::CONCEPT_DESC.
453
	 *
454
	 * @param string $format
455
	 * @param $context
456
	 *
457
	 * @return SMWResultPrinter
458
	 * @throws MissingResultFormatException
459
	 */
460 113
	static public function getResultPrinter( $format, $context = self::SPECIAL_PAGE ) {
0 ignored issues
show
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
461 113
		global $smwgResultFormats;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
462
463 113
		if ( !array_key_exists( $format, $smwgResultFormats ) ) {
464
			throw new ResultFormatNotFoundException( "There is no result format for '$format'." );
465
		}
466
467 113
		$formatClass = $smwgResultFormats[$format];
468
469 113
		return new $formatClass( $format, ( $context != self::SPECIAL_PAGE ) );
470
	}
471
472
	/**
473
	 * A function to describe the allowed parameters of a query using
474
	 * any specific format - most query printers should override this
475
	 * function.
476
	 *
477
	 * @since 1.6.2, return element type changed in 1.8
478
	 *
479
	 * @return IParamDefinition[]
480
	 */
481 113
	public static function getParameters() {
0 ignored issues
show
Coding Style introduced by
getParameters uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
482 113
		$params = array();
483
484 113
		$allowedFormats = $GLOBALS['smwgResultFormats'];
485
486 113
		foreach ( $GLOBALS['smwgResultAliases'] as $aliases ) {
487 113
			$allowedFormats += $aliases;
488
		}
489
490 113
		$allowedFormats[] = 'auto';
491
492 113
		$params['format'] = array(
493
			'type' => 'smwformat',
494
			'default' => 'auto',
495
		);
496
497
		// TODO $params['format']->setToLower( true );
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
498
		// TODO $allowedFormats
499
500 113
		$params['source'] = self::getSourceParam();
501
502 113
		$params['limit'] = array(
503 113
			'type' => 'integer',
504 113
			'default' => $GLOBALS['smwgQDefaultLimit'],
505
			'negatives' => false,
506
		);
507
508 113
		$params['offset'] = array(
509 113
			'type' => 'integer',
510 113
			'default' => 0,
511
			'negatives' => false,
512 113
			'upperbound' => $GLOBALS['smwgQUpperbound'],
513
		);
514
515 113
		$params['link'] = array(
516
			'default' => 'all',
517
			'values' => array( 'all', 'subject', 'none' ),
518
		);
519
520 113
		$params['sort'] = array(
521
			'islist' => true,
522
			'default' => array( '' ), // The empty string represents the page itself, which should be sorted by default.
523
		);
524
525 113
		$params['order'] = array(
526
			'islist' => true,
527
			'default' => array(),
528
			'values' => array( 'descending', 'desc', 'asc', 'ascending', 'rand', 'random' ),
529
		);
530
531 113
		$params['headers'] = array(
532
			'default' => 'show',
533
			'values' => array( 'show', 'hide', 'plain' ),
534
		);
535
536 113
		$params['mainlabel'] = array(
537
			'default' => false,
538
		);
539
540 113
		$params['intro'] = array(
541
			'default' => '',
542
		);
543
544 113
		$params['outro'] = array(
545
			'default' => '',
546
		);
547
548 113
		$params['searchlabel'] = array(
549 113
			'default' => Message::get( 'smw_iq_moreresults', Message::TEXT, Message::USER_LANGUAGE )
550
		);
551
552 113
		$params['default'] = array(
553
			'default' => '',
554
		);
555
556
		// Give grep a chance to find the usages:
557
		// smw-paramdesc-format, smw-paramdesc-source, smw-paramdesc-limit, smw-paramdesc-offset,
558
		// smw-paramdesc-link, smw-paramdesc-sort, smw-paramdesc-order, smw-paramdesc-headers,
559
		// smw-paramdesc-mainlabel, smw-paramdesc-intro, smw-paramdesc-outro, smw-paramdesc-searchlabel,
560
		// smw-paramdesc-default
561 113
		foreach ( $params as $name => &$param ) {
562 113
			if ( is_array( $param ) ) {
563 113
				$param['message'] = 'smw-paramdesc-' . $name;
564
			}
565
		}
566
567 113
		return ParamDefinition::getCleanDefinitions( $params );
0 ignored issues
show
Documentation introduced by
$params is of type array<string,array<strin...fault\":\"string\"}>"}>, but the function expects a array<integer,object<Par...ssor\IParamDefinition>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
568
	}
569
570 113
	private static function getSourceParam() {
0 ignored issues
show
Coding Style introduced by
getSourceParam uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
571 113
		$sourceValues = is_array( $GLOBALS['smwgQuerySources'] ) ? array_keys( $GLOBALS['smwgQuerySources'] ) : array();
572
573
		return array(
574 113
			'default' => array_key_exists( 'default', $sourceValues ) ? 'default' : '',
575 113
			'values' => $sourceValues,
576
		);
577
	}
578
579
	/**
580
	 * Returns the definitions of all parameters supported by the specified format.
581
	 *
582
	 * @since 1.8
583
	 *
584
	 * @param string $format
585
	 *
586
	 * @return ParamDefinition[]
587
	 */
588 1
	public static function getFormatParameters( $format ) {
0 ignored issues
show
Coding Style introduced by
getFormatParameters uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
589 1
		SMWParamFormat::resolveFormatAliases( $format );
590
591 1
		if ( array_key_exists( $format, $GLOBALS['smwgResultFormats'] ) ) {
592 1
			return ParamDefinition::getCleanDefinitions(
593 1
				self::getResultPrinter( $format )->getParamDefinitions( self::getParameters() )
594
			);
595
		} else {
596
			return array();
597
		}
598
	}
599
600
}
601