Completed
Push — master ( 9b2ed5...981814 )
by Jeroen De
76:07
created

formats/outline/SRF_Outline.php (2 issues)

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
/**
4
 * A class to print query results in an outline format, along with some
5
 * helper classes to handle the aggregation
6
 */
7
8
/**
9
 * Represents a single item, or page, in the outline - contains both the
10
 * SMWResultArray and an array of some of its values, for easier aggregation
11
 */
12
class SRFOutlineItem {
13
14
	var $mRow;
15
	var $mVals;
16
17
	function __construct( $row ) {
18
		$this->mRow = $row;
19
		$this->mVals = [];
20
	}
21
22
	function addFieldValue( $field_name, $field_val ) {
23
		if ( array_key_exists( $field_name, $this->mVals ) ) {
24
			$this->mVals[$field_name][] = $field_val;
25
		} else {
26
			$this->mVals[$field_name] = [ $field_val ];
27
		}
28
	}
29
30
	function getFieldValues( $field_name ) {
31
		if ( array_key_exists( $field_name, $this->mVals ) ) {
32
			return $this->mVals[$field_name];
33
		} else {
34
			return [ wfMessage( 'srf_outline_novalue' )->text() ];
35
		}
36
	}
37
}
38
39
/**
40
 * A tree structure for holding the outline data
41
 */
42
class SRFOutlineTree {
43
44
	var $mTree;
45
	var $mUnsortedItems;
46
47
	function __construct( $items = [] ) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Comprehensibility Best Practice introduced by
It is recommend to declare an explicit visibility for __construct.

Generally, we recommend to declare visibility for all methods in your source code. This has the advantage of clearly communication to other developers, and also yourself, how this method should be consumed.

If you are not sure which visibility to choose, it is a good idea to start with the most restrictive visibility, and then raise visibility as needed, i.e. start with private, and only raise it to protected if a sub-class needs to have access, or public if an external class needs access.

Loading history...
48
		$this->mTree = [];
49
		$this->mUnsortedItems = $items;
50
	}
51
52
	function addItem( $item ) {
53
		$this->mUnsortedItems[] = $item;
54
	}
55
56
	function categorizeItem( $vals, $item ) {
57
		foreach ( $vals as $val ) {
58
			if ( array_key_exists( $val, $this->mTree ) ) {
59
				$this->mTree[$val]->mUnsortedItems[] = $item;
60
			} else {
61
				$this->mTree[$val] = new SRFOutlineTree( [ $item ] );
62
			}
63
		}
64
	}
65
66
	function addProperty( $property ) {
67
		if ( count( $this->mUnsortedItems ) > 0 ) {
68
			foreach ( $this->mUnsortedItems as $item ) {
69
				$cur_vals = $item->getFieldValues( $property );
70
				$this->categorizeItem( $cur_vals, $item );
71
			}
72
			$this->mUnsortedItems = null;
73
		} else {
74
			foreach ( $this->mTree as $i => $node ) {
75
				$this->mTree[$i]->addProperty( $property );
76
			}
77
		}
78
	}
79
}
80
81
class SRFOutline extends SMWResultPrinter {
82
83
	protected $mOutlineProperties = [];
84
	protected $mInnerFormat = '';
85
86
	protected function handleParameters( array $params, $outputmode ) {
87
		parent::handleParameters( $params, $outputmode );
88
		$this->mOutlineProperties = $params['outlineproperties'];
89
	}
90
91
	public function getName() {
92
		return wfMessage( 'srf_printername_outline' )->text();
93
	}
94
95
	/**
96
	 * Code mostly copied from SMW's SMWListResultPrinter::getResultText()
97
	 */
98
	function printItem( $item ) {
99
		$first_col = true;
100
		$found_values = false; // has anything but the first column been printed?
101
		$result = "";
102
		foreach ( $item->mRow as $orig_ra ) {
103
			// handling is somewhat simpler for SMW 1.5+
104
			$realFunction = [ 'SMWQueryResult', 'getResults' ];
105
			if ( is_callable( $realFunction ) ) {
106
				// make a new copy of this, so that the call to
107
				// getNextText() will work again
108
				$ra = clone ( $orig_ra );
109
			} else {
110
				// make a new copy of this, so that the call to
111
				// getNextText() will work again
112
				$ra = new SMWResultArray( $orig_ra->getContent(), $orig_ra->getPrintRequest() );
113
			}
114
			$val = $ra->getPrintRequest()->getText( SMW_OUTPUT_WIKI, null );
115
			if ( in_array( $val, $this->mOutlineProperties ) ) {
116
				continue;
117
			}
118
			$first_value = true;
119
			while ( ( $text = $ra->getNextText( SMW_OUTPUT_WIKI, $this->mLinker ) ) !== false ) {
120
				if ( !$first_col && !$found_values ) { // first values after first column
121
					$result .= ' (';
122
					$found_values = true;
123
				} elseif ( $found_values || !$first_value ) {
124
					// any value after '(' or non-first values on first column
125
					$result .= ', ';
126
				}
127
				if ( $first_value ) { // first value in any column, print header
128
					$first_value = false;
129
					if ( $this->mShowHeaders && ( '' != $ra->getPrintRequest()->getLabel() ) ) {
130
						$result .= $ra->getPrintRequest()->getText( SMW_OUTPUT_WIKI, $this->mLinker ) . ' ';
131
					}
132
				}
133
				$result .= $text; // actual output value
134
			}
135
			$first_col = false;
136
		}
137
		if ( $found_values ) {
138
			$result .= ')';
139
		}
140
		return $result;
141
	}
142
143
	function printTree( $outline_tree, $level = 0 ) {
144
		$text = "";
145
		if ( !is_null( $outline_tree->mUnsortedItems ) ) {
146
			$text .= "<ul>\n";
147
			foreach ( $outline_tree->mUnsortedItems as $item ) {
148
				$text .= "<li>{$this->printItem($item)}</li>\n";
149
			}
150
			$text .= "</ul>\n";
151
		}
152
		if ( $level > 0 ) {
153
			$text .= "<ul>\n";
154
		}
155
		$num_levels = count( $this->mOutlineProperties );
156
		// set font size and weight depending on level we're at
157
		$font_level = $level;
158
		if ( $num_levels < 4 ) {
159
			$font_level += ( 4 - $num_levels );
160
		}
161
		if ( $font_level == 0 ) {
162
			$font_size = 'x-large';
163
		} elseif ( $font_level == 1 ) {
164
			$font_size = 'large';
165
		} elseif ( $font_level == 2 ) {
166
			$font_size = 'medium';
167
		} else {
168
			$font_size = 'small';
169
		}
170
		if ( $font_level == 3 ) {
171
			$font_weight = 'bold';
172
		} else {
173
			$font_weight = 'regular';
174
		}
175
		foreach ( $outline_tree->mTree as $key => $node ) {
176
			$text .= "<p style=\"font-size: $font_size; font-weight: $font_weight;\">$key</p>\n";
177
			$text .= $this->printTree( $node, $level + 1 );
178
		}
179
		if ( $level > 0 ) {
180
			$text .= "</ul>\n";
181
		}
182
		return $text;
183
	}
184
185
	protected function getResultText( SMWQueryResult $res, $outputmode ) {
186
		$print_fields = [];
187
		foreach ( $res->getPrintRequests() as $pr ) {
188
			$field_name = $pr->getText( $outputmode, $this->mLinker );
189
			// only print it if it's not already part of the
190
			// outline
191
			if ( !in_array( $field_name, $this->mOutlineProperties ) ) {
192
				$print_fields[] = $field_name;
193
			}
194
		}
195
196
		// for each result row, create an array of the row itself
197
		// and all its sorted-on fields, and add it to the initial
198
		// 'tree'
199
		$outline_tree = new SRFOutlineTree();
200
		while ( $row = $res->getNext() ) {
201
			$item = new SRFOutlineItem( $row );
202
			foreach ( $row as $field ) {
203
				$field_name = $field->getPrintRequest()->getText( SMW_OUTPUT_HTML );
204
				if ( in_array( $field_name, $this->mOutlineProperties ) ) {
205
					while ( ( $object = $field->getNextDataValue() ) !== false ) {
206
						$field_val = $object->getLongWikiText( $this->mLinker );
207
						$item->addFieldValue( $field_name, $field_val );
208
					}
209
				}
210
			}
211
			$outline_tree->addItem( $item );
212
		}
213
214
		// now, cycle through the outline properties, creating the
215
		// tree
216
		foreach ( $this->mOutlineProperties as $outline_prop ) {
217
			$outline_tree->addProperty( $outline_prop );
218
		}
219
		$result = $this->printTree( $outline_tree );
220
221
		// print further results footer
222
		if ( $this->linkFurtherResults( $res ) ) {
223
			$link = $res->getQueryLink();
224
			if ( $this->getSearchLabel( $outputmode ) ) {
225
				$link->setCaption( $this->getSearchLabel( $outputmode ) );
226
			}
227
			$link->setParameter( 'outline', 'format' );
228
			if ( array_key_exists( 'outlineproperties', $this->params ) ) {
229
				$link->setParameter( $this->params['outlineproperties'], 'outlineproperties' );
230
			}
231
			$result .= $link->getText( $outputmode, $this->mLinker ) . "\n";
232
		}
233
		return $result;
234
	}
235
236
	/**
237
	 * @see SMWResultPrinter::getParamDefinitions
238
	 *
239
	 * @since 1.8
240
	 *
241
	 * @param $definitions array of IParamDefinition
242
	 *
243
	 * @return array of IParamDefinition|array
244
	 */
245
	public function getParamDefinitions( array $definitions ) {
246
		$params = parent::getParamDefinitions( $definitions );
247
248
		$params['outlineproperties'] = [
249
			'islist' => true,
250
			'default' => [],
251
			'message' => 'srf_paramdesc_outlineproperties',
252
		];
253
254
		return $params;
255
	}
256
257
}
258