Completed
Push — master ( 9eae06...a41cb5 )
by mw
16s
created

includes/storage/SMW_ResultArray.php (2 issues)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
use SMW\DataValueFactory;
4
use SMW\InTextAnnotationParser;
5
use SMW\Query\PrintRequest;
6
use SMW\Query\TemporaryEntityListAccumulator;
7
use SMWDataItem as DataItem;
8
use SMWDIBlob as DIBlob;
9
10
/**
11
 * Container for the contents of a single result field of a query result,
12
 * i.e. basically an array of SMWDataItems with some additional parameters.
13
 * The content of the array is fetched on demand only.
14
 *
15
 * @ingroup SMWQuery
16
 *
17
 * @author Markus Krötzsch
18
 * @author Jeroen De Dauw < [email protected] >
19
 */
20
class SMWResultArray {
21
22
	/**
23
	 * @var PrintRequest
24
	 */
25
	private $mPrintRequest;
26
27
	/**
28
	 * @var SMWDIWikiPage
29
	 */
30
	private $mResult;
31
32
	/**
33
	 * @var SMWStore
34
	 */
35
	private $mStore;
36
37
	/**
38
	 * @var SMWDataItem[]|false
39
	 */
40
	private $mContent;
41
42
	/**
43
	 * @var TemporaryEntityListAccumulator|null
44
	 */
45
	private $temporaryEntityListAccumulator;
46
47
	static private $catCacheObj = false;
48
	static private $catCache = false;
49
50
	/**
51
	 * Constructor.
52
	 *
53
	 * @param SMWDIWikiPage $resultPage
54
	 * @param PrintRequest $printRequest
55
	 * @param SMWStore $store
56
	 */
57 82
	public function __construct( SMWDIWikiPage $resultPage, PrintRequest $printRequest, SMWStore $store ) {
58 82
		$this->mResult = $resultPage;
59 82
		$this->mPrintRequest = $printRequest;
60 82
		$this->mStore = $store;
61 82
		$this->mContent = false;
62 82
	}
63
64
	/**
65
	 * Get the SMWStore object that this result is based on.
66
	 *
67
	 * @return SMWStore
68
	 */
69
	public function getStore() {
70
		return $this->mStore;
71
	}
72
73
	/**
74
	 * Returns the SMWDIWikiPage object to which this SMWResultArray refers.
75
	 * If you only care for those objects, consider using SMWQueryResult::getResults()
76
	 * directly.
77
	 *
78
	 * @return SMWDIWikiPage
79
	 */
80 1
	public function getResultSubject() {
81 1
		return $this->mResult;
82
	}
83
84
	/**
85
	 * Temporary track what entities are used while being instantiated, so an external
86
	 * service can have access to the list without requiring to resolve the objects
87
	 * independently.
88
	 *
89
	 * @since  2.4
90
	 *
91
	 * @return TemporaryEntityListAccumulator
92
	 */
93 82
	public function setEntityListAccumulator( TemporaryEntityListAccumulator $temporaryEntityListAccumulator ) {
94 82
		$this->temporaryEntityListAccumulator = $temporaryEntityListAccumulator;
95 82
	}
96
97
	/**
98
	 * Returns an array of SMWDataItem objects that contain the results of
99
	 * the given print request for the given result object.
100
	 *
101
	 * @return SMWDataItem[]|false
102
	 */
103 4
	public function getContent() {
104 4
		$this->loadContent();
105 4
		return $this->mContent;
106
	}
107
108
	/**
109
	 * Return a PrintRequest object describing what is contained in this
110
	 * result set.
111
	 *
112
	 * @return PrintRequest
113
	 */
114 51
	public function getPrintRequest() {
115 51
		return $this->mPrintRequest;
116
	}
117
118
	/**
119
	 * Compatibility alias for getNextDatItem().
120
	 * @deprecated since 1.6. Call getNextDataValue() or getNextDataItem() directly as needed. Method will vanish before SMW 1.7.
121
	 */
122
	public function getNextObject() {
123
		return $this->getNextDataValue();
124
	}
125
126
	/**
127
	 * Return the next SMWDataItem object or false if no further object exists.
128
	 *
129
	 * @since 1.6
130
	 *
131
	 * @return SMWDataItem|false
132
	 */
133 82
	public function getNextDataItem() {
134 82
		$this->loadContent();
135 82
		$result = current( $this->mContent );
136
137 82
		if ( $this->temporaryEntityListAccumulator !== null && $result instanceof DataItem ) {
138 82
			$this->temporaryEntityListAccumulator->addToEntityList( null, $result );
139
		}
140
141 82
		next( $this->mContent );
142 82
		return $result;
143
	}
144
145
	/**
146
	 * Set the internal pointer of the array of SMWDataItem objects to its first
147
	 * element. Return the first SMWDataItem object or false if the array is
148
	 * empty.
149
	 *
150
	 * @since 1.7.1
151
	 *
152
	 * @return SMWDataItem|false
153
	 */
154
	public function reset() {
155
		$this->loadContent();
156
		return reset( $this->mContent );
157
	}
158
159
	/**
160
	 * Return an SMWDataValue object for the next SMWDataItem object or
161
	 * false if no further object exists.
162
	 *
163
	 * @since 1.6
164
	 *
165
	 * @return SMWDataValue|false
166
	 */
167 79
	public function getNextDataValue() {
168 79
		$dataItem = $this->getNextDataItem();
169
170 79
		if ( $dataItem === false ) {
171 78
			return false;
172
		}
173
174 79
		if ( $this->mPrintRequest->getMode() == PrintRequest::PRINT_PROP &&
175 79
		    strpos( $this->mPrintRequest->getTypeID(), '_rec' ) !== false &&
176 79
		    $this->mPrintRequest->getParameter( 'index' ) !== false ) {
177
178 4
			$recordValue = DataValueFactory::getInstance()->newDataValueByItem(
179
				$dataItem,
180 4
				$this->mPrintRequest->getData()->getDataItem()
181
			);
182
183 4
			$diProperty = $recordValue->getPropertyDataItemByIndex(
0 ignored issues
show
The method getPropertyDataItemByIndex() does not exist on SMWDataValue. Did you maybe mean getProperty()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
184 4
				$this->mPrintRequest->getParameter( 'index' )
185
			);
186 79
		} elseif ( $this->mPrintRequest->getMode() == PrintRequest::PRINT_PROP ) {
187 70
			$diProperty = $this->mPrintRequest->getData()->getDataItem();
188
		} else {
189 54
			$diProperty = null;
190
		}
191
192
		// refs #1314
193 79
		if ( $this->mPrintRequest->getMode() == PrintRequest::PRINT_PROP &&
194 79
			strpos( $this->mPrintRequest->getTypeID(), '_txt' ) !== false &&
195 79
			$dataItem instanceof DIBlob ) {
196 18
			$dataItem = new DIBlob(
197 18
				InTextAnnotationParser::removeAnnotation( $dataItem->getString() )
198
			);
199
		}
200
201 79
		$dataValue = DataValueFactory::getInstance()->newDataValueByItem(
202
			$dataItem,
203
			$diProperty
204
		);
205
206 79
		$dataValue->setContextPage(
207 79
			$this->mResult
208
		);
209
210 79
		if ( $this->mPrintRequest->getOutputFormat() ) {
211 15
			$dataValue->setOutputFormat( $this->mPrintRequest->getOutputFormat() );
212
		}
213
214 79
		if ( $this->temporaryEntityListAccumulator !== null && $dataItem instanceof DataItem ) {
215 79
			$this->temporaryEntityListAccumulator->addToEntityList( $diProperty, $dataItem );
216
		}
217
218 79
		return $dataValue;
219
	}
220
221
	/**
222
	 * Return the main text representation of the next SMWDataItem object
223
	 * in the specified format, or false if no further object exists.
224
	 *
225
	 * The parameter $linker controls linking of title values and should
226
	 * be some Linker object (or NULL for no linking).
227
	 *
228
	 * @param integer $outputMode
229
	 * @param mixed $linker
230
	 *
231
	 * @return string|false
232
	 */
233 10
	public function getNextText( $outputMode, $linker = null ) {
234 10
		$dataValue = $this->getNextDataValue();
235 10
		if ( $dataValue !== false ) { // Print data values.
236 10
			return $dataValue->getShortText( $outputMode, $linker );
237
		} else {
238 10
			return false;
239
		}
240
	}
241
242
	/**
243
	 * Load results of the given print request and result subject. This is only
244
	 * done when needed.
245
	 */
246 82
	protected function loadContent() {
247 82
		if ( $this->mContent !== false ) {
248 81
			return;
249
		}
250
251 82
		switch ( $this->mPrintRequest->getMode() ) {
252 82
			case PrintRequest::PRINT_THIS: // NOTE: The limit is ignored here.
253 54
				$this->mContent = array( $this->mResult );
254 54
			break;
255 76
			case PrintRequest::PRINT_CATS:
256
				// Always recompute cache here to ensure output format is respected.
257 3
				self::$catCache = $this->mStore->getPropertyValues( $this->mResult,
258 3
					new SMW\DIProperty( '_INST' ), $this->getRequestOptions( false ) );
259 3
				self::$catCacheObj = $this->mResult->getHash();
260
261 3
				$limit = $this->mPrintRequest->getParameter( 'limit' );
262 3
				$this->mContent = ( $limit === false ) ? ( self::$catCache ) :
263
					array_slice( self::$catCache, 0, $limit );
264 3
			break;
265 75
			case PrintRequest::PRINT_PROP:
266 75
				$propertyValue = $this->mPrintRequest->getData();
267 75
				if ( $propertyValue->isValid() ) {
268 75
					$this->mContent = $this->mStore->getPropertyValues( $this->mResult,
269 75
						$propertyValue->getDataItem(), $this->getRequestOptions() );
270
				} else {
271
					$this->mContent = array();
272
				}
273
274
				// Print one component of a multi-valued string.
275
				// Known limitation: the printrequest still is of type _rec, so if printers check
276
				// for this then they will not recognize that it returns some more concrete type.
277 75
				if ( strpos( $this->mPrintRequest->getTypeID(), '_rec' ) !== false &&
278 75
				     ( $this->mPrintRequest->getParameter( 'index' ) !== false ) ) {
279 4
					$index = $this->mPrintRequest->getParameter( 'index' );
280 4
					$newcontent = array();
281
282 4
					foreach ( $this->mContent as $diContainer ) {
283 4
						/* SMWRecordValue */ $recordValue = DataValueFactory::getInstance()->newDataValueByItem( $diContainer, $propertyValue->getDataItem() );
284
285 4
						if ( ( $dataItem = $recordValue->getDataItemByIndex( $index ) ) !== null ) {
0 ignored issues
show
The method getDataItemByIndex() does not exist on SMWDataValue. Did you maybe mean getDataItem()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
286 4
							$newcontent[] = $dataItem;
287
						}
288
					}
289
290 4
					$this->mContent = $newcontent;
291
				}
292 75
			break;
293
			case PrintRequest::PRINT_CCAT: ///NOTE: The limit is ignored here.
294
				if ( self::$catCacheObj != $this->mResult->getHash() ) {
295
					self::$catCache = $this->mStore->getPropertyValues( $this->mResult, new SMW\DIProperty( '_INST' ) );
296
					self::$catCacheObj = $this->mResult->getHash();
297
				}
298
299
				$found = false;
300
				$prkey = $this->mPrintRequest->getData()->getDBkey();
301
302
				foreach ( self::$catCache as $cat ) {
303
					if ( $cat->getDBkey() == $prkey ) {
304
						$found = true;
305
						break;
306
					}
307
				}
308
				$this->mContent = array( new SMWDIBoolean( $found ) );
309
			break;
310
			default: $this->mContent = array(); // Unknown print request.
311
		}
312
313 82
		reset( $this->mContent );
314
315 82
	}
316
317
	/**
318
	 * Make a request option object based on the given parameters, and
319
	 * return NULL if no such object is required. The parameter defines
320
	 * if the limit should be taken into account, which is not always desired
321
	 * (especially if results are to be cached for future use).
322
	 *
323
	 * @param boolean $useLimit
324
	 *
325
	 * @return SMWRequestOptions|null
326
	 */
327 76
	protected function getRequestOptions( $useLimit = true ) {
328 76
		$limit = $useLimit ? $this->mPrintRequest->getParameter( 'limit' ) : false;
329 76
		$order = trim( $this->mPrintRequest->getParameter( 'order' ) );
330
331
		// Important: use "!=" for order, since trim() above does never return "false", use "!==" for limit since "0" is meaningful here.
332 76
		if ( ( $limit !== false ) || ( $order != false ) ) {
333 2
			$options = new SMWRequestOptions();
334
335 2
			if ( $limit !== false ) {
336 1
				$options->limit = trim( $limit );
337
			}
338
339 2
			if ( ( $order == 'descending' ) || ( $order == 'reverse' ) || ( $order == 'desc' ) ) {
340 2
				$options->sort = true;
341 2
				$options->ascending = false;
342 1
			} elseif ( ( $order == 'ascending' ) || ( $order == 'asc' ) ) {
343 1
				$options->sort = true;
344 2
				$options->ascending = true;
345
			}
346
		} else {
347 74
			$options = null;
348
		}
349
350 76
		return $options;
351
	}
352
353
}
354