These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * Query format for arrays with features for Extensions 'Arrays' and 'HashTables' |
||
4 | * |
||
5 | * @file |
||
6 | * @ingroup SemanticResultFormats |
||
7 | * @author Daniel Werner < [email protected] > |
||
8 | * |
||
9 | * Doesn't require 'Arrays' nor 'HashTables' exytensions but has additional features |
||
10 | * ('name' parameter in either result format) if they are available. |
||
11 | * |
||
12 | * Arrays 2.0+ and HashTables 1.0+ are recommended but not necessary. |
||
13 | */ |
||
14 | |||
15 | /** |
||
16 | * Array format |
||
17 | */ |
||
18 | class SRFArray extends SMWResultPrinter { |
||
19 | |||
20 | protected static $mDefaultSeps = []; |
||
21 | protected $mSep; |
||
22 | protected $mPropSep; |
||
23 | protected $mManySep; |
||
24 | protected $mRecordSep; |
||
25 | protected $mHeaderSep; |
||
26 | protected $mArrayName = null; |
||
27 | protected $mShowPageTitles; |
||
28 | |||
29 | protected $mHideRecordGaps; |
||
30 | protected $mHidePropertyGaps; |
||
31 | |||
32 | /** |
||
33 | * @var Boolean true if 'mainlabel' parameter is set to '-' |
||
34 | */ |
||
35 | protected $mMainLabelHack = false; |
||
36 | |||
37 | 2 | public function __construct( $format, $inline = true ) { |
|
38 | 2 | parent::__construct( $format, $inline ); |
|
39 | //overwrite parent default behavior for linking: |
||
40 | 2 | $this->mLinkFirst = false; |
|
41 | 2 | $this->mLinkOthers = false; |
|
42 | 2 | } |
|
43 | |||
44 | public function getQueryMode( $context ) { |
||
45 | return SMWQuery::MODE_INSTANCES; |
||
46 | } |
||
47 | |||
48 | public function getName() { |
||
49 | // Give grep a chance to find the usages: |
||
50 | // srf_printername_array, srf_printername_hash |
||
51 | return wfMessage( 'srf_printername_' . $this->mFormat )->text(); |
||
52 | } |
||
53 | |||
54 | /* |
||
55 | // By overwriting this function, we disable default searchlabel handling? |
||
56 | public function getResult( SMWQueryResult $results, array $params, $outputmode ) { |
||
57 | $this->handleParameters( $params, $outputmode ); |
||
58 | return $this->getResultText( $results, $outputmode ); |
||
59 | } |
||
60 | */ |
||
61 | |||
62 | protected function getResultText( SMWQueryResult $res, $outputmode ) { |
||
63 | /* |
||
64 | * @todo |
||
65 | * labels of requested properties could define default values. Seems not possible at the moment because |
||
66 | * SMWPrintRequest::getLable() always returns the property name even if no specific label is defined. |
||
67 | */ |
||
68 | |||
69 | $perPage_items = []; |
||
70 | |||
71 | //for each page: |
||
72 | while ( $row = $res->getNext() ) { |
||
73 | $perProperty_items = []; |
||
74 | |||
75 | /** |
||
76 | * first field is always the page title, except, mainlabel is set to '-' |
||
77 | * |
||
78 | * @todo Is there some other way to check the data value directly for being the |
||
79 | * page title or not? SMWs behavior could change on mainlabel handling... |
||
80 | */ |
||
81 | $isPageTitle = !$this->mMainLabelHack; |
||
82 | |||
83 | //for each property on that page: |
||
84 | foreach ( $row as $field ) { // $row is array(), $field of type SMWResultArray |
||
85 | $manyValue_items = []; |
||
86 | $isMissingProperty = false; |
||
87 | |||
88 | $manyValues = $field->getContent(); |
||
89 | |||
90 | //If property is not set (has no value) on a page: |
||
91 | if ( empty( $manyValues ) ) { |
||
92 | $delivery = $this->deliverMissingProperty( $field ); |
||
93 | $manyValue_items = $this->fillDeliveryArray( $manyValue_items, $delivery ); |
||
94 | $isMissingProperty = true; |
||
95 | } else //otherwise collect property value (potentially many values): |
||
96 | { |
||
97 | while ( $obj = $field->getNextDataValue() ) { |
||
98 | |||
99 | $value_items = []; |
||
100 | $isRecord = false; |
||
101 | |||
102 | // handle page Title: |
||
103 | if ( $isPageTitle ) { |
||
104 | if ( !$this->mShowPageTitles ) { |
||
105 | $isPageTitle = false; |
||
106 | continue 2; //next property |
||
107 | } |
||
108 | $value_items = $this->fillDeliveryArray( |
||
109 | $value_items, |
||
110 | $this->deliverPageTitle( $obj, $this->mLinkFirst ) |
||
111 | ); |
||
112 | } // handle record values: |
||
113 | elseif ( $obj instanceof SMWRecordValue ) { |
||
114 | $recordItems = $obj->getDataItems(); |
||
115 | // walk all single values of the record set: |
||
116 | foreach ( $recordItems as $dataItem ) { |
||
117 | $recordField = $dataItem !== null ? SMWDataValueFactory::getInstance( |
||
118 | )->newDataValueByItem( $dataItem, null ) : null; |
||
119 | $value_items = $this->fillDeliveryArray( |
||
120 | $value_items, |
||
121 | $this->deliverRecordField( $recordField, $this->mLinkOthers ) |
||
122 | ); |
||
123 | } |
||
124 | $isRecord = true; |
||
125 | } // handle normal data values: |
||
126 | else { |
||
127 | $value_items = $this->fillDeliveryArray( |
||
128 | $value_items, |
||
129 | $this->deliverSingleValue( $obj, $this->mLinkOthers ) |
||
130 | ); |
||
131 | } |
||
132 | $delivery = $this->deliverSingleManyValuesData( $value_items, $isRecord, $isPageTitle ); |
||
133 | $manyValue_items = $this->fillDeliveryArray( $manyValue_items, $delivery ); |
||
134 | } |
||
135 | } // foreach... |
||
136 | $delivery = $this->deliverPropertiesManyValues( |
||
137 | $manyValue_items, |
||
138 | $isMissingProperty, |
||
139 | $isPageTitle, |
||
140 | $field |
||
141 | ); |
||
142 | $perProperty_items = $this->fillDeliveryArray( $perProperty_items, $delivery ); |
||
143 | $isPageTitle = false; // next one could be record or normal value |
||
144 | } // foreach... |
||
145 | $delivery = $this->deliverPageProperties( $perProperty_items ); |
||
146 | $perPage_items = $this->fillDeliveryArray( $perPage_items, $delivery ); |
||
147 | } // while... |
||
148 | |||
149 | $output = $this->deliverQueryResultPages( $perPage_items ); |
||
150 | |||
151 | return $output; |
||
152 | } |
||
153 | |||
154 | protected function fillDeliveryArray( $array = [], $value = null ) { |
||
155 | if ( !is_null( $value ) ) { //don't create any empty entries |
||
156 | $array[] = $value; |
||
157 | } |
||
158 | return $array; |
||
159 | } |
||
160 | |||
161 | protected function deliverPageTitle( $value, $link = false ) { |
||
162 | return $this->deliverSingleValue( $value, $link ); |
||
163 | } |
||
164 | |||
165 | protected function deliverRecordField( $value, $link = false ) { |
||
166 | if ( $value !== null ) // contains value |
||
167 | { |
||
168 | return $this->deliverSingleValue( $value, $link ); |
||
169 | } elseif ( $this->mHideRecordGaps ) { |
||
170 | return null; |
||
171 | } // hide gap |
||
172 | else { |
||
173 | return ''; |
||
174 | } // empty string will make sure that record value separators are generated |
||
175 | } |
||
176 | |||
177 | protected function deliverSingleValue( $value, $link = false ) { |
||
178 | //return trim( $value->getShortWikiText( $link ) ); |
||
179 | return trim( |
||
180 | Sanitizer::decodeCharReferences( $value->getShortWikiText( $link ) ) |
||
181 | ); // decode: better for further processing with array extension |
||
182 | } |
||
183 | |||
184 | // Property not declared on a page: |
||
185 | protected function deliverMissingProperty( SMWResultArray $field ) { |
||
186 | if ( $this->mHidePropertyGaps ) { |
||
187 | return null; |
||
188 | } else { |
||
189 | return ''; |
||
190 | } //empty string will make sure that array separator will be generated |
||
191 | /** @ToDo: System for Default values?... * */ |
||
192 | } |
||
193 | |||
194 | //represented by an array of record fields or just a single array value: |
||
195 | protected function deliverSingleManyValuesData( $value_items, $containsRecord, $isPageTitle ) { |
||
196 | if ( empty( $value_items ) ) //happens when one of the higher functions delivers null |
||
197 | { |
||
198 | return null; |
||
199 | } |
||
200 | return implode( $this->mRecordSep, $value_items ); |
||
201 | } |
||
202 | |||
203 | protected function deliverPropertiesManyValues( $manyValue_items, $isMissingProperty, $isPageTitle, SMWResultArray $data ) { |
||
204 | if ( empty( $manyValue_items ) ) { |
||
205 | return null; |
||
206 | } |
||
207 | |||
208 | $text = implode( $this->mManySep, $manyValue_items ); |
||
209 | |||
210 | // if property names should be displayed and this is not the page titles value: |
||
211 | if ( $this->mShowHeaders != SMW_HEADERS_HIDE && !$isPageTitle ) { |
||
212 | $linker = $this->mShowHeaders == SMW_HEADERS_PLAIN ? null : $this->mLinker; |
||
213 | $text = $data->getPrintRequest()->getText( SMW_OUTPUT_WIKI, $linker ) . $this->mHeaderSep . $text; |
||
214 | } |
||
215 | return $text; |
||
216 | } |
||
217 | |||
218 | protected function deliverPageProperties( $perProperty_items ) { |
||
219 | if ( empty( $perProperty_items ) ) { |
||
220 | return null; |
||
221 | } |
||
222 | return implode( $this->mPropSep, $perProperty_items ); |
||
223 | } |
||
224 | |||
225 | protected function deliverQueryResultPages( $perPage_items ) { |
||
226 | if ( $this->mArrayName !== null ) { |
||
227 | $this->createArray( $perPage_items ); //create Array |
||
228 | return ''; |
||
229 | } else { |
||
230 | return implode( $this->mSep, $perPage_items ); |
||
231 | } |
||
232 | } |
||
233 | |||
234 | /** |
||
235 | * Helper function to create a new Array within 'Arrays' extension. Takes care of different versions |
||
236 | * as well as the old 'ArrayExtension'. |
||
237 | */ |
||
238 | protected function createArray( $array ) { |
||
239 | global $wgArrayExtension; |
||
240 | |||
241 | $arrayId = $this->mArrayName; |
||
242 | |||
243 | if ( defined( 'ExtArrays::VERSION' ) ) { |
||
244 | // 'Arrays' extension 2+ |
||
245 | global $wgParser; |
||
246 | /** ToDo: is there a way to get the actual parser which has started the query? */ |
||
247 | ExtArrays::get( $wgParser )->createArray( $arrayId, $array ); |
||
248 | return true; |
||
249 | } |
||
250 | |||
251 | // compatbility to 'ArrayExtension' extension before 2.0: |
||
252 | |||
253 | if ( !isset( $wgArrayExtension ) ) { |
||
254 | //Hash extension is not installed in this wiki |
||
255 | return false; |
||
256 | } |
||
257 | $version = null; |
||
258 | if ( defined( 'ArrayExtension::VERSION' ) ) { |
||
259 | $version = ArrayExtension::VERSION; |
||
260 | } elseif ( defined( 'ExtArrayExtension::VERSION' ) ) { |
||
261 | $version = ExtArrayExtension::VERSION; |
||
262 | } |
||
263 | if ( $version !== null && version_compare( $version, '1.3.2', '>=' ) ) { |
||
264 | // ArrayExtension 1.3.2+ |
||
265 | $wgArrayExtension->createArray( $arrayId, $array ); |
||
266 | } else { |
||
267 | // dirty way |
||
268 | $wgArrayExtension->mArrays[trim( $arrayId )] = $array; |
||
269 | } |
||
270 | return true; |
||
271 | } |
||
272 | |||
273 | protected function initializeCfgValue( $dfltVal, $dfltCacheKey ) { |
||
274 | $cache = &self::$mDefaultSeps[$dfltCacheKey]; |
||
275 | if ( !isset( $cache ) ) { |
||
276 | $cache = $this->getCfgSepText( $dfltVal ); |
||
277 | if ( $cache === null ) { |
||
278 | // cache can't be initialized, propably function-reference in userconfig |
||
279 | // but format is not used in inline context, use fallback in this case: |
||
280 | global $srfgArraySepTextualFallbacks; |
||
281 | $cache = $srfgArraySepTextualFallbacks[$dfltCacheKey]; |
||
282 | } |
||
283 | } |
||
284 | return $cache; |
||
285 | } |
||
286 | |||
287 | protected function getCfgSepText( $obj ) { |
||
288 | if ( is_array( $obj ) ) { |
||
289 | // invalid definition: |
||
290 | if ( !array_key_exists( 0, $obj ) ) { |
||
291 | return null; |
||
292 | } |
||
293 | |||
294 | // check for config-defined arguments to pass to the page before processing it: |
||
295 | if ( array_key_exists( 'args', $obj ) && is_array( $obj['args'] ) ) { |
||
296 | $params = $obj['args']; |
||
297 | } else { |
||
298 | $params = []; |
||
299 | } // no arguments |
||
300 | |||
301 | // create title of page whose text should be used as separator: |
||
302 | $obj = Title::newFromText( $obj[0], ( array_key_exists( 1, $obj ) ? $obj[1] : NS_MAIN ) ); |
||
303 | } |
||
304 | if ( $obj instanceof Title ) { |
||
0 ignored issues
–
show
|
|||
305 | $article = new Article( $obj ); |
||
306 | } elseif ( $obj instanceof Article ) { |
||
0 ignored issues
–
show
The class
Article does not exist. Did you forget a USE statement, or did you not list all dependencies?
This error could be the result of: 1. Missing dependenciesPHP Analyzer uses your Are you sure this class is defined by one of your dependencies, or did you maybe
not list a dependency in either the 2. Missing use statementPHP does not complain about undefined classes in if ($x instanceof DoesNotExist) {
// Do something.
}
If you have not tested against this specific condition, such errors might go unnoticed.
Loading history...
|
|||
307 | $article = $obj; |
||
308 | } else { |
||
309 | return $obj; //only text |
||
310 | } |
||
311 | |||
312 | global $wgParser; |
||
313 | /* |
||
314 | * Feature to use page value as separator only works if Parser::parse() is running! |
||
315 | * That's not the case on semantic search special page for example! |
||
316 | */ |
||
317 | // can't use $this->mInline here since SMW 1.6.2 had a bug setting it to false in most cases! |
||
318 | if ( !isset( $wgParser->mOptions ) ) { |
||
319 | //if( ! $this->mInline ) { |
||
320 | return null; |
||
321 | } |
||
322 | |||
323 | /* |
||
324 | * parse page as if it were included like a template. Never use Parser::recursiveTagParse() or similar |
||
325 | * for this since it would call hooks we don't want to call and won't return wiki text for inclusion! |
||
326 | */ |
||
327 | $frame = $wgParser->getPreprocessor()->newCustomFrame( $params ); |
||
0 ignored issues
–
show
The variable
$params does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
Loading history...
|
|||
328 | // compatibility for 1.19, getContent() was implemented in 1.21. |
||
329 | // FIXME: Remove when support for MediaWiki 1.19 is dropped |
||
330 | if ( method_exists( $article, 'getContent' ) ) { |
||
331 | $content = $article->getContent( Revision::RAW )->getNativeData(); |
||
332 | } else { |
||
333 | $content = $article->getRawText(); |
||
334 | } |
||
335 | $text = $wgParser->preprocessToDom( $content, Parser::PTD_FOR_INCLUSION ); |
||
336 | $text = trim( $frame->expand( $text ) ); |
||
337 | |||
338 | return $text; |
||
339 | } |
||
340 | |||
341 | protected function handleParameters( array $params, $outputmode ) { |
||
342 | // does the link parameter: |
||
343 | parent::handleParameters( $params, $outputmode ); |
||
344 | |||
345 | //separators: |
||
346 | $this->mSep = $params['sep']; |
||
347 | $this->mPropSep = $params['propsep']; |
||
348 | $this->mManySep = $params['manysep']; |
||
349 | $this->mRecordSep = $params['recordsep']; |
||
350 | $this->mHeaderSep = $params['headersep']; |
||
351 | |||
352 | // only use this in inline mode, if text is given. Since SMW 1.6.2 '' is given, so if |
||
353 | // we wouldn't check, we would always end up with an array instead of visible output |
||
354 | if ( $params['name'] !== false && ( $this->mInline || trim( $params['name'] ) !== '' ) ) { |
||
355 | $this->mArrayName = trim( $params['name'] ); |
||
356 | $this->createArray( |
||
357 | [] |
||
358 | ); //create empty array in case we get no result so we won't have an undefined array in the end. |
||
359 | } |
||
360 | |||
361 | // if mainlabel set to '-', this will cause the titles not to appear, so make sure we catch this! |
||
362 | $this->mMainLabelHack = trim( $params['mainlabel'] ) === '-'; |
||
363 | |||
364 | // whether or not to display the page title: |
||
365 | $this->mShowPageTitles = strtolower( $params['titles'] ) != 'hide'; |
||
366 | |||
367 | switch ( strtolower( $params['hidegaps'] ) ) { |
||
368 | case 'none': |
||
369 | $this->mHideRecordGaps = false; |
||
370 | $this->mHidePropertyGaps = false; |
||
371 | break; |
||
372 | case 'all': |
||
373 | $this->mHideRecordGaps = true; |
||
374 | $this->mHidePropertyGaps = true; |
||
375 | break; |
||
376 | case 'property': |
||
377 | case 'prop': |
||
378 | case 'attribute': |
||
379 | case 'attr': |
||
380 | $this->mHideRecordGaps = false; |
||
381 | $this->mHidePropertyGaps = true; |
||
382 | break; |
||
383 | case 'record': |
||
384 | case 'rec': |
||
385 | case 'rcrd': |
||
386 | case 'n-ary': |
||
387 | case 'nary': |
||
388 | $this->mHideRecordGaps = true; |
||
389 | $this->mHidePropertyGaps = false; |
||
390 | break; |
||
391 | } |
||
392 | } |
||
393 | |||
394 | /** |
||
395 | * @see SMWResultPrinter::getParamDefinitions |
||
396 | * |
||
397 | * @since 1.8 |
||
398 | * |
||
399 | * @param $definitions array of IParamDefinition |
||
400 | * |
||
401 | * @return array of IParamDefinition|array |
||
402 | */ |
||
403 | public function getParamDefinitions( array $definitions ) { |
||
404 | $params = parent::getParamDefinitions( $definitions ); |
||
405 | |||
406 | ### adjusted basic SMW params: ### |
||
407 | |||
408 | $definitions['limit']->setDefault( $GLOBALS['smwgQMaxInlineLimit'] ); |
||
409 | $definitions['link']->setDefault( 'none' ); |
||
410 | $definitions['headers']->setDefault( 'hide' ); |
||
411 | |||
412 | ### new params: ### |
||
413 | |||
414 | $params['titles'] = [ |
||
415 | 'message' => 'srf_paramdesc_pagetitle', |
||
416 | 'values' => [ 'show', 'hide' ], |
||
417 | 'aliases' => [ 'pagetitle', 'pagetitles' ], |
||
418 | 'default' => 'show', |
||
419 | ]; |
||
420 | |||
421 | $params['hidegaps'] = [ |
||
422 | 'message' => 'srf_paramdesc_hidegaps', |
||
423 | 'values' => [ 'none', 'all', 'property', 'record' ], |
||
424 | 'default' => 'none', |
||
425 | ]; |
||
426 | |||
427 | $params['name'] = [ |
||
428 | 'message' => 'srf_paramdesc_arrayname', |
||
429 | 'default' => false, |
||
430 | 'manipulatedefault' => false, |
||
431 | ]; |
||
432 | |||
433 | // separators (default values are defined in the following globals:) |
||
434 | global $srfgArraySep, $srfgArrayPropSep, $srfgArrayManySep, $srfgArrayRecordSep, $srfgArrayHeaderSep; |
||
435 | |||
436 | $params['sep'] = [ |
||
437 | 'message' => 'smw-paramdesc-sep', |
||
438 | 'default' => $this->initializeCfgValue( $srfgArraySep, 'sep' ), |
||
439 | ]; |
||
440 | |||
441 | $params['propsep'] = [ |
||
442 | 'message' => 'srf_paramdesc_propsep', |
||
443 | 'default' => $this->initializeCfgValue( $srfgArrayPropSep, 'propsep' ), |
||
444 | ]; |
||
445 | |||
446 | $params['manysep'] = [ |
||
447 | 'message' => 'srf_paramdesc_manysep', |
||
448 | 'default' => $this->initializeCfgValue( $srfgArrayManySep, 'manysep' ), |
||
449 | ]; |
||
450 | |||
451 | $params['recordsep'] = [ |
||
452 | 'message' => 'srf_paramdesc_recordsep', |
||
453 | 'default' => $this->initializeCfgValue( $srfgArrayRecordSep, 'recordsep' ), |
||
454 | 'aliases' => [ 'narysep', 'rcrdsep', 'recsep' ], |
||
455 | ]; |
||
456 | |||
457 | $params['headersep'] = [ |
||
458 | 'message' => 'srf_paramdesc_headersep', |
||
459 | 'default' => $this->initializeCfgValue( $srfgArrayHeaderSep, 'headersep' ), |
||
460 | 'aliases' => [ 'narysep', 'rcrdsep', 'recsep' ], |
||
461 | ]; |
||
462 | |||
463 | return $params; |
||
464 | } |
||
465 | |||
466 | } |
||
467 | |||
468 | |||
469 | |||
470 |
This error could be the result of:
1. Missing dependencies
PHP Analyzer uses your
composer.json
file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects thecomposer.json
to be in the root folder of your repository.Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the
require
orrequire-dev
section?2. Missing use statement
PHP does not complain about undefined classes in
ìnstanceof
checks. For example, the following PHP code will work perfectly fine:If you have not tested against this specific condition, such errors might go unnoticed.