132 public function display_element( $element, &$children_elements, $max_depth, $depth, $args, &$output ) { |
133 public function display_element( $element, &$children_elements, $max_depth, $depth, $args, &$output ) { |
133 if ( ! $element ) { |
134 if ( ! $element ) { |
134 return; |
135 return; |
135 } |
136 } |
136 |
137 |
|
138 $max_depth = (int) $max_depth; |
|
139 $depth = (int) $depth; |
|
140 |
137 $id_field = $this->db_fields['id']; |
141 $id_field = $this->db_fields['id']; |
138 $id = $element->$id_field; |
142 $id = $element->$id_field; |
139 |
143 |
140 // Display this element. |
144 // Display this element. |
141 $this->has_children = ! empty( $children_elements[ $id ] ); |
145 $this->has_children = ! empty( $children_elements[ $id ] ); |
144 } |
148 } |
145 |
149 |
146 $this->start_el( $output, $element, $depth, ...array_values( $args ) ); |
150 $this->start_el( $output, $element, $depth, ...array_values( $args ) ); |
147 |
151 |
148 // Descend only when the depth is right and there are children for this element. |
152 // Descend only when the depth is right and there are children for this element. |
149 if ( ( 0 == $max_depth || $max_depth > $depth + 1 ) && isset( $children_elements[ $id ] ) ) { |
153 if ( ( 0 === $max_depth || $max_depth > $depth + 1 ) && isset( $children_elements[ $id ] ) ) { |
150 |
154 |
151 foreach ( $children_elements[ $id ] as $child ) { |
155 foreach ( $children_elements[ $id ] as $child ) { |
152 |
156 |
153 if ( ! isset( $newlevel ) ) { |
157 if ( ! isset( $newlevel ) ) { |
154 $newlevel = true; |
158 $newlevel = true; |
188 * @return string The hierarchical item output. |
192 * @return string The hierarchical item output. |
189 */ |
193 */ |
190 public function walk( $elements, $max_depth, ...$args ) { |
194 public function walk( $elements, $max_depth, ...$args ) { |
191 $output = ''; |
195 $output = ''; |
192 |
196 |
|
197 $max_depth = (int) $max_depth; |
|
198 |
193 // Invalid parameter or nothing to walk. |
199 // Invalid parameter or nothing to walk. |
194 if ( $max_depth < -1 || empty( $elements ) ) { |
200 if ( $max_depth < -1 || empty( $elements ) ) { |
195 return $output; |
201 return $output; |
196 } |
202 } |
197 |
203 |
198 $parent_field = $this->db_fields['parent']; |
204 $parent_field = $this->db_fields['parent']; |
199 |
205 |
200 // Flat display. |
206 // Flat display. |
201 if ( -1 == $max_depth ) { |
207 if ( -1 === $max_depth ) { |
202 $empty_array = array(); |
208 $empty_array = array(); |
203 foreach ( $elements as $e ) { |
209 foreach ( $elements as $e ) { |
204 $this->display_element( $e, $empty_array, 1, 0, $args, $output ); |
210 $this->display_element( $e, $empty_array, 1, 0, $args, $output ); |
205 } |
211 } |
206 return $output; |
212 return $output; |
232 $root = $first[0]; |
238 $root = $first[0]; |
233 |
239 |
234 $top_level_elements = array(); |
240 $top_level_elements = array(); |
235 $children_elements = array(); |
241 $children_elements = array(); |
236 foreach ( $elements as $e ) { |
242 foreach ( $elements as $e ) { |
237 if ( $root->$parent_field == $e->$parent_field ) { |
243 if ( $root->$parent_field === $e->$parent_field ) { |
238 $top_level_elements[] = $e; |
244 $top_level_elements[] = $e; |
239 } else { |
245 } else { |
240 $children_elements[ $e->$parent_field ][] = $e; |
246 $children_elements[ $e->$parent_field ][] = $e; |
241 } |
247 } |
242 } |
248 } |
248 |
254 |
249 /* |
255 /* |
250 * If we are displaying all levels, and remaining children_elements is not empty, |
256 * If we are displaying all levels, and remaining children_elements is not empty, |
251 * then we got orphans, which should be displayed regardless. |
257 * then we got orphans, which should be displayed regardless. |
252 */ |
258 */ |
253 if ( ( 0 == $max_depth ) && count( $children_elements ) > 0 ) { |
259 if ( ( 0 === $max_depth ) && count( $children_elements ) > 0 ) { |
254 $empty_array = array(); |
260 $empty_array = array(); |
255 foreach ( $children_elements as $orphans ) { |
261 foreach ( $children_elements as $orphans ) { |
256 foreach ( $orphans as $op ) { |
262 foreach ( $orphans as $op ) { |
257 $this->display_element( $op, $empty_array, 1, 0, $args, $output ); |
263 $this->display_element( $op, $empty_array, 1, 0, $args, $output ); |
258 } |
264 } |
282 * @param int $per_page Number of elements per page. |
288 * @param int $per_page Number of elements per page. |
283 * @param mixed ...$args Optional additional arguments. |
289 * @param mixed ...$args Optional additional arguments. |
284 * @return string XHTML of the specified page of elements. |
290 * @return string XHTML of the specified page of elements. |
285 */ |
291 */ |
286 public function paged_walk( $elements, $max_depth, $page_num, $per_page, ...$args ) { |
292 public function paged_walk( $elements, $max_depth, $page_num, $per_page, ...$args ) { |
|
293 $output = ''; |
|
294 |
|
295 $max_depth = (int) $max_depth; |
|
296 |
287 if ( empty( $elements ) || $max_depth < -1 ) { |
297 if ( empty( $elements ) || $max_depth < -1 ) { |
288 return ''; |
298 return $output; |
289 } |
299 } |
290 |
|
291 $output = ''; |
|
292 |
300 |
293 $parent_field = $this->db_fields['parent']; |
301 $parent_field = $this->db_fields['parent']; |
294 |
302 |
295 $count = -1; |
303 $count = -1; |
296 if ( -1 == $max_depth ) { |
304 if ( -1 === $max_depth ) { |
297 $total_top = count( $elements ); |
305 $total_top = count( $elements ); |
298 } |
306 } |
299 if ( $page_num < 1 || $per_page < 0 ) { |
307 if ( $page_num < 1 || $per_page < 0 ) { |
300 // No paging. |
308 // No paging. |
301 $paging = false; |
309 $paging = false; |
302 $start = 0; |
310 $start = 0; |
303 if ( -1 == $max_depth ) { |
311 if ( -1 === $max_depth ) { |
304 $end = $total_top; |
312 $end = $total_top; |
305 } |
313 } |
306 $this->max_pages = 1; |
314 $this->max_pages = 1; |
307 } else { |
315 } else { |
308 $paging = true; |
316 $paging = true; |
309 $start = ( (int) $page_num - 1 ) * (int) $per_page; |
317 $start = ( (int) $page_num - 1 ) * (int) $per_page; |
310 $end = $start + $per_page; |
318 $end = $start + $per_page; |
311 if ( -1 == $max_depth ) { |
319 if ( -1 === $max_depth ) { |
312 $this->max_pages = ceil( $total_top / $per_page ); |
320 $this->max_pages = (int) ceil( $total_top / $per_page ); |
313 } |
321 } |
314 } |
322 } |
315 |
323 |
316 // Flat display. |
324 // Flat display. |
317 if ( -1 == $max_depth ) { |
325 if ( -1 === $max_depth ) { |
318 if ( ! empty( $args[0]['reverse_top_level'] ) ) { |
326 if ( ! empty( $args[0]['reverse_top_level'] ) ) { |
319 $elements = array_reverse( $elements ); |
327 $elements = array_reverse( $elements ); |
320 $oldstart = $start; |
328 $oldstart = $start; |
321 $start = $total_top - $end; |
329 $start = $total_top - $end; |
322 $end = $total_top - $oldstart; |
330 $end = $total_top - $oldstart; |
323 } |
331 } |
324 |
332 |
325 $empty_array = array(); |
333 $empty_array = array(); |
326 foreach ( $elements as $e ) { |
334 foreach ( $elements as $e ) { |
327 $count++; |
335 ++$count; |
328 if ( $count < $start ) { |
336 if ( $count < $start ) { |
329 continue; |
337 continue; |
330 } |
338 } |
331 if ( $count >= $end ) { |
339 if ( $count >= $end ) { |
332 break; |
340 break; |
369 $children_elements[ $parent ] = array_reverse( $children ); |
377 $children_elements[ $parent ] = array_reverse( $children ); |
370 } |
378 } |
371 } |
379 } |
372 |
380 |
373 foreach ( $top_level_elements as $e ) { |
381 foreach ( $top_level_elements as $e ) { |
374 $count++; |
382 ++$count; |
375 |
383 |
376 // For the last page, need to unset earlier children in order to keep track of orphans. |
384 // For the last page, need to unset earlier children in order to keep track of orphans. |
377 if ( $end >= $total_top && $count < $start ) { |
385 if ( $end >= $total_top && $count < $start ) { |
378 $this->unset_children( $e, $children_elements ); |
386 $this->unset_children( $e, $children_elements ); |
379 } |
387 } |