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 SRF\Outline\TemplateBuilder; |
||
4 | |||
5 | /** |
||
6 | * A class to print query results in an outline format, along with some |
||
7 | * helper classes to handle the aggregation |
||
8 | */ |
||
9 | |||
10 | /** |
||
11 | * Represents a single item, or page, in the outline - contains both the |
||
12 | * SMWResultArray and an array of some of its values, for easier aggregation |
||
13 | */ |
||
14 | class SRFOutlineItem { |
||
15 | |||
16 | var $mRow; |
||
17 | var $mVals; |
||
18 | |||
19 | 1 | function __construct( $row ) { |
|
20 | 1 | $this->mRow = $row; |
|
21 | 1 | $this->mVals = []; |
|
22 | 1 | } |
|
23 | |||
24 | 1 | function addFieldValue( $field_name, $field_val ) { |
|
25 | 1 | if ( array_key_exists( $field_name, $this->mVals ) ) { |
|
26 | $this->mVals[$field_name][] = $field_val; |
||
27 | } else { |
||
28 | 1 | $this->mVals[$field_name] = [ $field_val ]; |
|
29 | } |
||
30 | 1 | } |
|
31 | |||
32 | 1 | function getFieldValues( $field_name ) { |
|
33 | 1 | if ( array_key_exists( $field_name, $this->mVals ) ) { |
|
34 | 1 | return $this->mVals[$field_name]; |
|
35 | } else { |
||
36 | return [ wfMessage( 'srf_outline_novalue' )->text() ]; |
||
37 | } |
||
38 | } |
||
39 | } |
||
40 | |||
41 | /** |
||
42 | * A tree structure for holding the outline data |
||
43 | */ |
||
44 | class SRFOutlineTree { |
||
45 | |||
46 | var $mTree; |
||
47 | var $mUnsortedItems; |
||
48 | var $itemCount = 0; |
||
49 | var $leafCount = 0; |
||
50 | |||
51 | 1 | function __construct( $items = [] ) { |
|
0 ignored issues
–
show
|
|||
52 | 1 | $this->mTree = []; |
|
53 | 1 | $this->mUnsortedItems = $items; |
|
54 | 1 | } |
|
55 | |||
56 | 1 | function addItem( $item ) { |
|
57 | 1 | $this->mUnsortedItems[] = $item; |
|
58 | 1 | $this->itemCount++; |
|
59 | 1 | } |
|
60 | |||
61 | 1 | function categorizeItem( $vals, $item ) { |
|
62 | 1 | foreach ( $vals as $val ) { |
|
63 | 1 | if ( array_key_exists( $val, $this->mTree ) ) { |
|
64 | 1 | $this->mTree[$val]->mUnsortedItems[] = $item; |
|
65 | 1 | $this->mTree[$val]->leafCount++; |
|
66 | } else { |
||
67 | 1 | $this->mTree[$val] = new SRFOutlineTree( [ $item ] ); |
|
68 | 1 | $this->mTree[$val]->leafCount++; |
|
69 | } |
||
70 | } |
||
71 | 1 | } |
|
72 | |||
73 | 1 | function addProperty( $property ) { |
|
74 | 1 | if ( count( $this->mUnsortedItems ) > 0 ) { |
|
75 | 1 | foreach ( $this->mUnsortedItems as $item ) { |
|
76 | 1 | $cur_vals = $item->getFieldValues( $property ); |
|
77 | 1 | $this->categorizeItem( $cur_vals, $item ); |
|
78 | } |
||
79 | 1 | $this->mUnsortedItems = null; |
|
80 | } else { |
||
81 | 1 | foreach ( $this->mTree as $i => $node ) { |
|
82 | 1 | $this->mTree[$i]->addProperty( $property ); |
|
83 | } |
||
84 | } |
||
85 | 1 | } |
|
86 | } |
||
87 | |||
88 | class SRFOutline extends SMWResultPrinter { |
||
89 | |||
90 | protected $mOutlineProperties = []; |
||
91 | protected $mInnerFormat = ''; |
||
92 | |||
93 | public function getName() { |
||
94 | return wfMessage( 'srf_printername_outline' )->text(); |
||
95 | } |
||
96 | |||
97 | /** |
||
98 | * Code mostly copied from SMW's SMWListResultPrinter::getResultText() |
||
99 | */ |
||
100 | function printItem( $item ) { |
||
101 | $first_col = true; |
||
102 | $found_values = false; // has anything but the first column been printed? |
||
103 | $result = ""; |
||
104 | foreach ( $item->mRow as $orig_ra ) { |
||
105 | // handling is somewhat simpler for SMW 1.5+ |
||
106 | $realFunction = [ 'SMWQueryResult', 'getResults' ]; |
||
107 | if ( is_callable( $realFunction ) ) { |
||
108 | // make a new copy of this, so that the call to |
||
109 | // getNextText() will work again |
||
110 | $ra = clone ( $orig_ra ); |
||
111 | } else { |
||
112 | // make a new copy of this, so that the call to |
||
113 | // getNextText() will work again |
||
114 | $ra = new SMWResultArray( $orig_ra->getContent(), $orig_ra->getPrintRequest() ); |
||
115 | } |
||
116 | $val = $ra->getPrintRequest()->getText( SMW_OUTPUT_WIKI, null ); |
||
117 | if ( in_array( $val, $this->params['outlineproperties'] ) ) { |
||
118 | continue; |
||
119 | } |
||
120 | $first_value = true; |
||
121 | while ( ( $text = $ra->getNextText( SMW_OUTPUT_WIKI, $this->mLinker ) ) !== false ) { |
||
122 | if ( !$first_col && !$found_values ) { // first values after first column |
||
123 | $result .= ' ('; |
||
124 | $found_values = true; |
||
125 | } elseif ( $found_values || !$first_value ) { |
||
126 | // any value after '(' or non-first values on first column |
||
127 | $result .= ', '; |
||
128 | } |
||
129 | if ( $first_value ) { // first value in any column, print header |
||
130 | $first_value = false; |
||
131 | if ( $this->mShowHeaders && ( '' != $ra->getPrintRequest()->getLabel() ) ) { |
||
132 | $result .= $ra->getPrintRequest()->getText( SMW_OUTPUT_WIKI, $this->mLinker ) . ' '; |
||
133 | } |
||
134 | } |
||
135 | $result .= $text; // actual output value |
||
136 | } |
||
137 | $first_col = false; |
||
138 | } |
||
139 | if ( $found_values ) { |
||
140 | $result .= ')'; |
||
141 | } |
||
142 | return $result; |
||
143 | } |
||
144 | |||
145 | function printTree( $outline_tree, $level = 0 ) { |
||
146 | $text = ""; |
||
147 | if ( !is_null( $outline_tree->mUnsortedItems ) ) { |
||
148 | $text .= "<ul>\n"; |
||
149 | foreach ( $outline_tree->mUnsortedItems as $item ) { |
||
150 | $text .= "<li>{$this->printItem($item)}</li>\n"; |
||
151 | } |
||
152 | $text .= "</ul>\n"; |
||
153 | } |
||
154 | if ( $level > 0 ) { |
||
155 | $text .= "<ul>\n"; |
||
156 | } |
||
157 | $num_levels = count( $this->params['outlineproperties'] ); |
||
158 | // set font size and weight depending on level we're at |
||
159 | $font_level = $level; |
||
160 | if ( $num_levels < 4 ) { |
||
161 | $font_level += ( 4 - $num_levels ); |
||
162 | } |
||
163 | if ( $font_level == 0 ) { |
||
164 | $font_size = 'x-large'; |
||
165 | } elseif ( $font_level == 1 ) { |
||
166 | $font_size = 'large'; |
||
167 | } elseif ( $font_level == 2 ) { |
||
168 | $font_size = 'medium'; |
||
169 | } else { |
||
170 | $font_size = 'small'; |
||
171 | } |
||
172 | if ( $font_level == 3 ) { |
||
173 | $font_weight = 'bold'; |
||
174 | } else { |
||
175 | $font_weight = 'regular'; |
||
176 | } |
||
177 | foreach ( $outline_tree->mTree as $key => $node ) { |
||
178 | $text .= "<p style=\"font-size: $font_size; font-weight: $font_weight;\">$key</p>\n"; |
||
179 | $text .= $this->printTree( $node, $level + 1 ); |
||
180 | } |
||
181 | if ( $level > 0 ) { |
||
182 | $text .= "</ul>\n"; |
||
183 | } |
||
184 | return $text; |
||
185 | } |
||
186 | |||
187 | 1 | protected function getResultText( SMWQueryResult $res, $outputmode ) { |
|
188 | 1 | $print_fields = []; |
|
189 | 1 | foreach ( $res->getPrintRequests() as $pr ) { |
|
190 | 1 | $field_name = $pr->getText( $outputmode, $this->mLinker ); |
|
191 | // only print it if it's not already part of the |
||
192 | // outline |
||
193 | 1 | if ( !in_array( $field_name, $this->params['outlineproperties'] ) ) { |
|
194 | 1 | $print_fields[] = $field_name; |
|
195 | } |
||
196 | } |
||
197 | |||
198 | // for each result row, create an array of the row itself |
||
199 | // and all its sorted-on fields, and add it to the initial |
||
200 | // 'tree' |
||
201 | 1 | $outline_tree = new SRFOutlineTree(); |
|
202 | 1 | while ( $row = $res->getNext() ) { |
|
203 | 1 | $item = new SRFOutlineItem( $row ); |
|
204 | 1 | foreach ( $row as $field ) { |
|
205 | 1 | $field_name = $field->getPrintRequest()->getText( SMW_OUTPUT_HTML ); |
|
206 | 1 | if ( in_array( $field_name, $this->params['outlineproperties'] ) ) { |
|
207 | 1 | while ( ( $object = $field->getNextDataValue() ) !== false ) { |
|
208 | 1 | $field_val = $object->getLongWikiText( $this->mLinker ); |
|
209 | 1 | $item->addFieldValue( $field_name, $field_val ); |
|
210 | } |
||
211 | } |
||
212 | } |
||
213 | 1 | $outline_tree->addItem( $item ); |
|
214 | } |
||
215 | |||
216 | // now, cycle through the outline properties, creating the |
||
217 | // tree |
||
218 | 1 | foreach ( $this->params['outlineproperties'] as $outline_prop ) { |
|
219 | 1 | $outline_tree->addProperty( $outline_prop ); |
|
220 | } |
||
221 | |||
222 | 1 | if ( $this->params['template'] !== '' ) { |
|
223 | 1 | $this->hasTemplates = true; |
|
224 | 1 | $templateBuilder = new TemplateBuilder( |
|
225 | 1 | $this->params |
|
226 | ); |
||
227 | |||
228 | 1 | $templateBuilder->setLinker( $this->mLinker ); |
|
229 | 1 | $result = $templateBuilder->build( $outline_tree ); |
|
230 | } else { |
||
231 | $result = $this->printTree( $outline_tree ); |
||
232 | } |
||
233 | |||
234 | 1 | if ( $this->linkFurtherResults( $res ) ) { |
|
235 | $link = $this->getFurtherResultsLink( $res, $outputmode ); |
||
236 | |||
237 | $result .= $link->getText( $outputmode, $this->mLinker ) . "\n"; |
||
238 | } |
||
239 | |||
240 | 1 | return $result; |
|
241 | } |
||
242 | |||
243 | /** |
||
244 | * @see SMWResultPrinter::getParamDefinitions |
||
245 | * |
||
246 | * @since 1.8 |
||
247 | * |
||
248 | * @param $definitions array of IParamDefinition |
||
249 | * |
||
250 | * @return array of IParamDefinition|array |
||
251 | */ |
||
252 | 1 | public function getParamDefinitions( array $definitions ) { |
|
253 | 1 | $params = parent::getParamDefinitions( $definitions ); |
|
254 | |||
255 | 1 | $params['outlineproperties'] = [ |
|
256 | 'islist' => true, |
||
257 | 'default' => [], |
||
258 | 'message' => 'srf_paramdesc_outlineproperties', |
||
259 | ]; |
||
260 | |||
261 | 1 | $params[] = [ |
|
262 | 'name' => 'template', |
||
263 | 'message' => 'smw-paramdesc-template', |
||
264 | 'default' => '', |
||
265 | ]; |
||
266 | |||
267 | 1 | $params[] = [ |
|
268 | 'name' => 'userparam', |
||
269 | 'message' => 'smw-paramdesc-userparam', |
||
270 | 'default' => '', |
||
271 | ]; |
||
272 | |||
273 | 1 | $params[] = [ |
|
274 | 'name' => 'named args', |
||
275 | 'type' => 'boolean', |
||
276 | 'message' => 'smw-paramdesc-named_args', |
||
277 | 'default' => true, |
||
278 | ]; |
||
279 | |||
280 | 1 | return $params; |
|
281 | } |
||
282 | |||
283 | } |
||
284 |
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 toprotected
if a sub-class needs to have access, orpublic
if an external class needs access.