Completed
Push — master ( 249923...ac15b4 )
by Jeroen De
135:11 queued 115:11
created

formats/tree/TreeResultPrinter.php (3 issues)

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
namespace SRF\Formats\Tree;
4
5
/**
6
 * File holding the Tree class.
7
 * @author Stephan Gambke
8
 */
9
use \Exception;
10
use Html;
11
use SMW\DIProperty;
12
use SMW\DIWikiPage;
13
use SMW\ListResultPrinter;
14
use SMWQueryResult;
15
use Title;
16
17
/**
18
 * Result printer that prints query results as a tree (nested html lists).
19
 *
20
 * The available formats are 'tree', 'ultree', 'oltree'. 'tree' is an alias of
21
 * 'ultree'. In an #ask query the parameter 'parent' must be set to contain the
22
 * name of the property, that gives the parent page of the subject page.
23
 *
24
 */
25
class TreeResultPrinter extends ListResultPrinter {
26
27
	private $standardTemplateParameters;
28
29
	/**
30
	 * @var SMWQueryResult | null
31
	 */
32
	private $queryResult = null;
33
34
	/**
35
	 * (non-PHPdoc)
36
	 * @see SMWResultPrinter::getName()
37
	 */
38
	public function getName() {
39
		// Give grep a chance to find the usages:
40
		// srf-printername-tree, srf-printername-ultree, srf-printername-oltree
41
		return \Message::newFromKey( 'srf-printername-' . $this->mFormat )->text();
42
	}
43
44
	/**
45
	 * @return SMWQueryResult
46
	 * @throws Exception
47
	 */
48 5
	public function getQueryResult() {
49
50 5
		if ( $this->queryResult === null ) {
51
			throw new Exception( __METHOD__ . ' called outside of ' . __CLASS__ . '::getResultText().');
52
		}
53
54 5
		return $this->queryResult;
55
	}
56
57
	/**
58
	 * @param SMWQueryResult | null $queryResult
59
	 */
60 7
	public function setQueryResult( $queryResult ) {
61 7
		$this->queryResult = $queryResult;
62 7
	}
63
64
	/**
65
	 * @see ResultPrinter::postProcessParameters()
66
	 */
67 8
	protected function postProcessParameters() {
68
69 8
		parent::postProcessParameters();
70
71
		// Don't support pagination in trees
72 8
		$this->mSearchlabel = null;
73
74 8
		if ( array_key_exists( 'template arguments', $this->params )
75 8
			&& $this->params['template arguments'] !== 'numbered' ) {
76
77 8
			if ( filter_var( $this->params[ 'named args' ], FILTER_VALIDATE_BOOLEAN ) === true ) {
78
				$this->params['template arguments'] = 'legacy';
79
			} elseif (
80 8
				$this->params['template arguments'] !== 'named' &&
81 8
				$this->params['template arguments'] !== 'legacy'
82
			) {
83
				// default
84 8
				$this->params['template arguments'] = 'numbered';
85
			}
86
		}
87
88
		// Allow "_" for encoding spaces, as documented
89 8
		$this->params[ 'sep' ] = str_replace( '_', ' ', $this->params[ 'sep' ] );
90
91 8
		if ( !ctype_digit( strval( $this->params[ 'start level' ] ) ) || $this->params[ 'start level' ] < 1 ) {
92
			$this->params[ 'start level' ] = 1;
93
		}
94
95 8
	}
96
97
	/**
98
	 * Return serialised results in specified format.
99
	 * @param SMWQueryResult $queryResult
100
	 * @param $outputmode
101
	 * @return string
102
	 */
103 7
	protected function getResultText( SMWQueryResult $queryResult, $outputmode ) {
104
105 7
		$this->setQueryResult( $queryResult );
106
107 7
		if ( $this->params[ 'parent' ] === '' ) {
108 2
			$this->addError( 'srf-tree-noparentprop' );
109 2
			return '';
110
		}
111
112 5
		$rootHash = $this->getRootHash();
113
114 5
		if ( $rootHash === false ) {
115
			$this->addError( 'srf-tree-rootinvalid', $this->params[ 'root' ] );
116
			return '';
117
		}
118
119 5
		$this->hasTemplates =
120 5
			$this->params[ 'introtemplate' ] !== '' ||
121 5
			$this->params[ 'outrotemplate' ] !== '' ||
122 5
			$this->params[ 'template' ] !== '';
123
124 5
		if ( $this->hasTemplates ) {
125 3
			$this->initalizeStandardTemplateParameters();
126
		}
127
128 5
		$tree = $this->buildTreeFromQueryResult( $rootHash );
129 5
		$lines = $this->buildLinesFromTree( $tree );
130
131
		// Display default if the result is empty
132 5
		if ( count( $lines ) === 0 ) {
133
			return $this->params[ 'default' ];
134
		}
135
136
		// FIXME: Linking to further events ($this->linkFurtherResults())
137
		// does not make sense for tree format. But maybe display a warning?
138
139 5
		$resultText = join( "\n", array_merge(
140 5
			[ $this->getTemplateCall( $this->params[ 'introtemplate' ] ) ],
141 5
			$lines,
142 5
			[ $this->getTemplateCall( $this->params[ 'outrotemplate' ] ) ]
143
		) );
144
145 5
		$this->setQueryResult( null );
146
147 5
		return Html::rawElement( 'div', [ 'class' => 'srf-tree' ], $resultText );
148
	}
149
150
	/**
151
	 * @param string $templateName
152
	 * @param string[] $params
153
	 * @return string
154
	 */
155 5
	public function getTemplateCall( $templateName, $params = [] ) {
156
157 5
		if ( $templateName === '' ) {
158 5
			return '';
159
		}
160
161 3
		return '{{' . $templateName . '|' . join( '|', $params ) . $this->standardTemplateParameters . '}}';
162
	}
163
164
	/**
165
	 * @see SMWResultPrinter::getParamDefinitions
166
	 *
167
	 * @since 1.8
168
	 *
169
	 * @param $definitions array of IParamDefinition
170
	 *
171
	 * @return array of IParamDefinition|array
172
	 */
173 8
	public function getParamDefinitions( array $definitions ) {
174 8
		$params = parent::getParamDefinitions( $definitions );
175
176 8
		$params[ 'parent' ] = [
177
			'default' => '',
178
			'message' => 'srf-paramdesc-tree-parent',
179
		];
180
181 8
		$params[ 'root' ] = [
182
			'default' => '',
183
			'message' => 'srf-paramdesc-tree-root',
184
		];
185
186 8
		$params[ 'start level' ] = [
187
			'default' => 1,
188
			'message' => 'srf-paramdesc-tree-startlevel',
189
			'type' => 'integer',
190
		];
191
192 8
		$params[ 'sep' ] = [
193
			'default' => ', ',
194
			'message' => 'smw-paramdesc-sep',
195
		];
196
197 8
		$params[ 'template arguments' ] = [
198
			'default' => '',
199
			'message' => 'smw-paramdesc-template-arguments',
200
		];
201
202 8
		return $params;
203
	}
204
205
	/**
206
	 * @param string $rootHash
207
	 * @return TreeNode
208
	 */
209 5
	protected function buildTreeFromQueryResult( $rootHash ) {
210
211 5
		$nodes = $this->getHashOfNodes();
212
213 5
		if ( $rootHash !== '' && !array_key_exists( $rootHash, $nodes ) ) {
214
			return new TreeNode();
215
		}
216
217 5
		return $this->buildTreeFromNodeList( $rootHash, $nodes );
218
	}
219
220
	/**
221
	 * @return string | false
222
	 */
223 5
	protected function getRootHash() {
224
225 5
		if ( $this->params[ 'root' ] === '' ) {
226 5
			return '';
227
		}
228
229
		// get the title object of the root page
230 1
		$rootTitle = Title::newFromText( $this->params[ 'root' ] );
231
232 1
		if ( $rootTitle !== null ) {
233 1
			return DIWikiPage::newFromTitle( $rootTitle )->getSerialization();
234
		}
235
236
		return false;
237
238
	}
239
240
	/**
241
	 * @return TreeNode[]
242
	 */
243 5
	protected function getHashOfNodes() {
244
245
		/** @var TreeNode[] $nodes */
246 5
		$nodes = [];
247
248 5
		$queryResult = $this->getQueryResult();
249
250 5
		$row = $queryResult->getNext();
251 5
		while ( $row !== false ) {
252 5
			$node = new TreeNode( $row );
253 5
			$nodes[ $node->getHash() ] = $node;
254 5
			$row = $queryResult->getNext();
255
		}
256
257 5
		return $nodes;
258
	}
259
260
	/**
261
	 * Returns a linker object for making hyperlinks
262
	 * @return \Linker
263
	 */
264 1
	public function getLinker( $firstcol = false ) {
265 1
		return $this->mLinker;
266
	}
267
268
	/**
269
	 * Depending on current linking settings, returns a linker object
270
	 * for making hyperlinks or NULL if no links should be created.
271
	 *
272
	 * @param int $column Column number
273
	 * @return \Linker|null
274
	 */
275 5
	public function getLinkerForColumn( $column ) {
276 5
		return parent::getLinker( $column === 0 );
277
	}
278
279 3
	private function initalizeStandardTemplateParameters() {
280
281 3
		$query = $this->getQueryResult()->getQuery();
282
283 3
		$this->standardTemplateParameters =
284 3
			( trim( $this->params[ 'userparam' ] ) !== '' ? ( '|userparam=' . trim( $this->params['userparam'] ) ) : '' ) .
285 3
			'|smw-resultquerycondition=' . $query->getQueryString() .
286 3
			'|smw-resultquerylimit=' . $query->getLimit() .
287 3
			'|smw-resultqueryoffset=' . $query->getOffset();
288
289 3
	}
290
291
	/**
292
	 * @param string $rootHash
293
	 * @param TreeNode[] $nodes
294
	 * @return TreeNode
295
	 */
296 5
	protected function buildTreeFromNodeList( $rootHash, $nodes ) {
297
298 5
		$isRootSpecified = $rootHash !== '';
299
300 5
		$root = new TreeNode();
301 5
		if ( $isRootSpecified ) {
302 1
			$root->addChild( $nodes[ $rootHash ] );
303
		}
304
305 5
		$store = $this->getQueryResult()->getStore();
306 5
		$parentPointerProperty = DIProperty::newFromUserLabel( $this->params[ 'parent' ] );
307
308 5
		foreach ( $nodes as $hash => $node ) {
309
310 5
			$parents = $store->getPropertyValues(
311 5
				$node->getResultSubject(), $parentPointerProperty
312
			);
313
314 5
			if ( empty( $parents ) && !$isRootSpecified ) {
315
316 5
				$root->addChild( $node );
317
318
			} else {
319
320 4
				foreach ( $parents as $parent ) {
321
322 4
					$parentHash = $parent->getSerialization();
323
324
					try {
325 4
						if ( array_key_exists( $parentHash, $nodes ) ) {
326 4
							$errorCode = $nodes[ $parentHash ]->addChild( $node );
0 ignored issues
show
$errorCode is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
327
						} elseif ( !$isRootSpecified ) {
328
							$errorCode = $root->addChild( $node );
0 ignored issues
show
$errorCode is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
329
						} else {
330
							// Drop node. It is not part of the tree.
331 4
							$errorCode = null;
0 ignored issues
show
$errorCode is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
332
						}
333 1
					} catch ( Exception $e ) {
334 5
						$this->addError( $e->getMessage(), $node->getResultSubject()->getTitle()->getPrefixedText() );
335
					}
336
				}
337
			}
338
		}
339 5
		return $root;
340
	}
341
342
	/**
343
	 * @param TreeNode $tree
344
	 * @return mixed
345
	 */
346 5
	protected function buildLinesFromTree( $tree ) {
347
		$nodePrinterConfiguration = [
348 5
			'format' => trim( $this->params[ 'format' ] ),
349 5
			'template' => trim( $this->params[ 'template' ] ),
350 5
			'headers' => $this->params[ 'headers' ],
351 5
			'template arguments' => $this->params['template arguments'],
352 5
			'sep' => $this->params[ 'sep' ],
353
		];
354
355 5
		$visitor = new TreeNodePrinter( $this, $nodePrinterConfiguration );
356 5
		$lines = $tree->accept( $visitor );
357 5
		return $lines;
358
	}
359
360
	/**
361
	 * @param string $msgkey
362
	 * @param string | string[] $params
363
	 */
364 3
	protected function addError( $msgkey, $params = [] ) {
365
366 3
		parent::addError(
367 3
			\Message::newFromKey( $msgkey )
368 3
				->params( $params )
369 3
				->inContentLanguage()->text()
370
			);
371 3
	}
372
373
}
374
375