139 $this->has_children = ! empty( $children_elements[ $id ] ); |
139 $this->has_children = ! empty( $children_elements[ $id ] ); |
140 if ( isset( $args[0] ) && is_array( $args[0] ) ) { |
140 if ( isset( $args[0] ) && is_array( $args[0] ) ) { |
141 $args[0]['has_children'] = $this->has_children; // Back-compat. |
141 $args[0]['has_children'] = $this->has_children; // Back-compat. |
142 } |
142 } |
143 |
143 |
144 $cb_args = array_merge( array(&$output, $element, $depth), $args); |
144 $cb_args = array_merge( array( &$output, $element, $depth ), $args ); |
145 call_user_func_array(array($this, 'start_el'), $cb_args); |
145 call_user_func_array( array( $this, 'start_el' ), $cb_args ); |
146 |
146 |
147 // descend only when the depth is right and there are childrens for this element |
147 // descend only when the depth is right and there are childrens for this element |
148 if ( ($max_depth == 0 || $max_depth > $depth+1 ) && isset( $children_elements[$id]) ) { |
148 if ( ( $max_depth == 0 || $max_depth > $depth + 1 ) && isset( $children_elements[ $id ] ) ) { |
149 |
149 |
150 foreach ( $children_elements[ $id ] as $child ){ |
150 foreach ( $children_elements[ $id ] as $child ) { |
151 |
151 |
152 if ( !isset($newlevel) ) { |
152 if ( ! isset( $newlevel ) ) { |
153 $newlevel = true; |
153 $newlevel = true; |
154 //start the child delimiter |
154 //start the child delimiter |
155 $cb_args = array_merge( array(&$output, $depth), $args); |
155 $cb_args = array_merge( array( &$output, $depth ), $args ); |
156 call_user_func_array(array($this, 'start_lvl'), $cb_args); |
156 call_user_func_array( array( $this, 'start_lvl' ), $cb_args ); |
157 } |
157 } |
158 $this->display_element( $child, $children_elements, $max_depth, $depth + 1, $args, $output ); |
158 $this->display_element( $child, $children_elements, $max_depth, $depth + 1, $args, $output ); |
159 } |
159 } |
160 unset( $children_elements[ $id ] ); |
160 unset( $children_elements[ $id ] ); |
161 } |
161 } |
162 |
162 |
163 if ( isset($newlevel) && $newlevel ){ |
163 if ( isset( $newlevel ) && $newlevel ) { |
164 //end the child delimiter |
164 //end the child delimiter |
165 $cb_args = array_merge( array(&$output, $depth), $args); |
165 $cb_args = array_merge( array( &$output, $depth ), $args ); |
166 call_user_func_array(array($this, 'end_lvl'), $cb_args); |
166 call_user_func_array( array( $this, 'end_lvl' ), $cb_args ); |
167 } |
167 } |
168 |
168 |
169 //end this element |
169 //end this element |
170 $cb_args = array_merge( array(&$output, $element, $depth), $args); |
170 $cb_args = array_merge( array( &$output, $element, $depth ), $args ); |
171 call_user_func_array(array($this, 'end_el'), $cb_args); |
171 call_user_func_array( array( $this, 'end_el' ), $cb_args ); |
172 } |
172 } |
173 |
173 |
174 /** |
174 /** |
175 * Display array of elements hierarchically. |
175 * Display array of elements hierarchically. |
176 * |
176 * |
211 * Children_elements is two dimensional array, eg. |
212 * Children_elements is two dimensional array, eg. |
212 * Children_elements[10][] contains all sub-elements whose parent is 10. |
213 * Children_elements[10][] contains all sub-elements whose parent is 10. |
213 */ |
214 */ |
214 $top_level_elements = array(); |
215 $top_level_elements = array(); |
215 $children_elements = array(); |
216 $children_elements = array(); |
216 foreach ( $elements as $e) { |
217 foreach ( $elements as $e ) { |
217 if ( empty( $e->$parent_field ) ) |
218 if ( empty( $e->$parent_field ) ) { |
218 $top_level_elements[] = $e; |
219 $top_level_elements[] = $e; |
219 else |
220 } else { |
220 $children_elements[ $e->$parent_field ][] = $e; |
221 $children_elements[ $e->$parent_field ][] = $e; |
|
222 } |
221 } |
223 } |
222 |
224 |
223 /* |
225 /* |
224 * When none of the elements is top level. |
226 * When none of the elements is top level. |
225 * Assume the first one must be root of the sub elements. |
227 * Assume the first one must be root of the sub elements. |
226 */ |
228 */ |
227 if ( empty($top_level_elements) ) { |
229 if ( empty( $top_level_elements ) ) { |
228 |
230 |
229 $first = array_slice( $elements, 0, 1 ); |
231 $first = array_slice( $elements, 0, 1 ); |
230 $root = $first[0]; |
232 $root = $first[0]; |
231 |
233 |
232 $top_level_elements = array(); |
234 $top_level_elements = array(); |
233 $children_elements = array(); |
235 $children_elements = array(); |
234 foreach ( $elements as $e) { |
236 foreach ( $elements as $e ) { |
235 if ( $root->$parent_field == $e->$parent_field ) |
237 if ( $root->$parent_field == $e->$parent_field ) { |
236 $top_level_elements[] = $e; |
238 $top_level_elements[] = $e; |
237 else |
239 } else { |
238 $children_elements[ $e->$parent_field ][] = $e; |
240 $children_elements[ $e->$parent_field ][] = $e; |
239 } |
241 } |
240 } |
242 } |
241 |
243 } |
242 foreach ( $top_level_elements as $e ) |
244 |
|
245 foreach ( $top_level_elements as $e ) { |
243 $this->display_element( $e, $children_elements, $max_depth, 0, $args, $output ); |
246 $this->display_element( $e, $children_elements, $max_depth, 0, $args, $output ); |
|
247 } |
244 |
248 |
245 /* |
249 /* |
246 * If we are displaying all levels, and remaining children_elements is not empty, |
250 * If we are displaying all levels, and remaining children_elements is not empty, |
247 * then we got orphans, which should be displayed regardless. |
251 * then we got orphans, which should be displayed regardless. |
248 */ |
252 */ |
249 if ( ( $max_depth == 0 ) && count( $children_elements ) > 0 ) { |
253 if ( ( $max_depth == 0 ) && count( $children_elements ) > 0 ) { |
250 $empty_array = array(); |
254 $empty_array = array(); |
251 foreach ( $children_elements as $orphans ) |
255 foreach ( $children_elements as $orphans ) { |
252 foreach ( $orphans as $op ) |
256 foreach ( $orphans as $op ) { |
253 $this->display_element( $op, $empty_array, 1, 0, $args, $output ); |
257 $this->display_element( $op, $empty_array, 1, 0, $args, $output ); |
254 } |
258 } |
255 |
259 } |
256 return $output; |
260 } |
|
261 |
|
262 return $output; |
257 } |
263 } |
258 |
264 |
259 /** |
265 /** |
260 * paged_walk() - produce a page of nested elements |
266 * paged_walk() - produce a page of nested elements |
261 * |
267 * |
262 * Given an array of hierarchical elements, the maximum depth, a specific page number, |
268 * Given an array of hierarchical elements, the maximum depth, a specific page number, |
263 * and number of elements per page, this function first determines all top level root elements |
269 * and number of elements per page, this function first determines all top level root elements |
264 * belonging to that page, then lists them and all of their children in hierarchical order. |
270 * belonging to that page, then lists them and all of their children in hierarchical order. |
265 * |
271 * |
266 * $max_depth = 0 means display all levels. |
272 * $max_depth = 0 means display all levels. |
267 * $max_depth > 0 specifies the number of display levels. |
273 * $max_depth > 0 specifies the number of display levels. |
268 * |
274 * |
269 * @since 2.7.0 |
275 * @since 2.7.0 |
270 * |
276 * |
271 * @param array $elements |
277 * @param array $elements |
272 * @param int $max_depth The maximum hierarchical depth. |
278 * @param int $max_depth The maximum hierarchical depth. |
273 * @param int $page_num The specific page number, beginning with 1. |
279 * @param int $page_num The specific page number, beginning with 1. |
274 * @param int $per_page |
280 * @param int $per_page |
277 public function paged_walk( $elements, $max_depth, $page_num, $per_page ) { |
283 public function paged_walk( $elements, $max_depth, $page_num, $per_page ) { |
278 if ( empty( $elements ) || $max_depth < -1 ) { |
284 if ( empty( $elements ) || $max_depth < -1 ) { |
279 return ''; |
285 return ''; |
280 } |
286 } |
281 |
287 |
282 $args = array_slice( func_get_args(), 4 ); |
288 $args = array_slice( func_get_args(), 4 ); |
283 $output = ''; |
289 $output = ''; |
284 |
290 |
285 $parent_field = $this->db_fields['parent']; |
291 $parent_field = $this->db_fields['parent']; |
286 |
292 |
287 $count = -1; |
293 $count = -1; |
288 if ( -1 == $max_depth ) |
294 if ( -1 == $max_depth ) { |
289 $total_top = count( $elements ); |
295 $total_top = count( $elements ); |
290 if ( $page_num < 1 || $per_page < 0 ) { |
296 } |
|
297 if ( $page_num < 1 || $per_page < 0 ) { |
291 // No paging |
298 // No paging |
292 $paging = false; |
299 $paging = false; |
293 $start = 0; |
300 $start = 0; |
294 if ( -1 == $max_depth ) |
301 if ( -1 == $max_depth ) { |
295 $end = $total_top; |
302 $end = $total_top; |
|
303 } |
296 $this->max_pages = 1; |
304 $this->max_pages = 1; |
297 } else { |
305 } else { |
298 $paging = true; |
306 $paging = true; |
299 $start = ( (int)$page_num - 1 ) * (int)$per_page; |
307 $start = ( (int) $page_num - 1 ) * (int) $per_page; |
300 $end = $start + $per_page; |
308 $end = $start + $per_page; |
301 if ( -1 == $max_depth ) |
309 if ( -1 == $max_depth ) { |
302 $this->max_pages = ceil($total_top / $per_page); |
310 $this->max_pages = ceil( $total_top / $per_page ); |
|
311 } |
303 } |
312 } |
304 |
313 |
305 // flat display |
314 // flat display |
306 if ( -1 == $max_depth ) { |
315 if ( -1 == $max_depth ) { |
307 if ( !empty($args[0]['reverse_top_level']) ) { |
316 if ( ! empty( $args[0]['reverse_top_level'] ) ) { |
308 $elements = array_reverse( $elements ); |
317 $elements = array_reverse( $elements ); |
309 $oldstart = $start; |
318 $oldstart = $start; |
310 $start = $total_top - $end; |
319 $start = $total_top - $end; |
311 $end = $total_top - $oldstart; |
320 $end = $total_top - $oldstart; |
312 } |
321 } |
313 |
322 |
314 $empty_array = array(); |
323 $empty_array = array(); |
315 foreach ( $elements as $e ) { |
324 foreach ( $elements as $e ) { |
316 $count++; |
325 $count++; |
317 if ( $count < $start ) |
326 if ( $count < $start ) { |
318 continue; |
327 continue; |
319 if ( $count >= $end ) |
328 } |
|
329 if ( $count >= $end ) { |
320 break; |
330 break; |
|
331 } |
321 $this->display_element( $e, $empty_array, 1, 0, $args, $output ); |
332 $this->display_element( $e, $empty_array, 1, 0, $args, $output ); |
322 } |
333 } |
323 return $output; |
334 return $output; |
324 } |
335 } |
325 |
336 |
328 * Children_elements is two dimensional array, e.g. |
339 * Children_elements is two dimensional array, e.g. |
329 * $children_elements[10][] contains all sub-elements whose parent is 10. |
340 * $children_elements[10][] contains all sub-elements whose parent is 10. |
330 */ |
341 */ |
331 $top_level_elements = array(); |
342 $top_level_elements = array(); |
332 $children_elements = array(); |
343 $children_elements = array(); |
333 foreach ( $elements as $e) { |
344 foreach ( $elements as $e ) { |
334 if ( 0 == $e->$parent_field ) |
345 if ( 0 == $e->$parent_field ) { |
335 $top_level_elements[] = $e; |
346 $top_level_elements[] = $e; |
336 else |
347 } else { |
337 $children_elements[ $e->$parent_field ][] = $e; |
348 $children_elements[ $e->$parent_field ][] = $e; |
|
349 } |
338 } |
350 } |
339 |
351 |
340 $total_top = count( $top_level_elements ); |
352 $total_top = count( $top_level_elements ); |
341 if ( $paging ) |
353 if ( $paging ) { |
342 $this->max_pages = ceil($total_top / $per_page); |
354 $this->max_pages = ceil( $total_top / $per_page ); |
343 else |
355 } else { |
344 $end = $total_top; |
356 $end = $total_top; |
345 |
357 } |
346 if ( !empty($args[0]['reverse_top_level']) ) { |
358 |
|
359 if ( ! empty( $args[0]['reverse_top_level'] ) ) { |
347 $top_level_elements = array_reverse( $top_level_elements ); |
360 $top_level_elements = array_reverse( $top_level_elements ); |
348 $oldstart = $start; |
361 $oldstart = $start; |
349 $start = $total_top - $end; |
362 $start = $total_top - $end; |
350 $end = $total_top - $oldstart; |
363 $end = $total_top - $oldstart; |
351 } |
364 } |
352 if ( !empty($args[0]['reverse_children']) ) { |
365 if ( ! empty( $args[0]['reverse_children'] ) ) { |
353 foreach ( $children_elements as $parent => $children ) |
366 foreach ( $children_elements as $parent => $children ) { |
354 $children_elements[$parent] = array_reverse( $children ); |
367 $children_elements[ $parent ] = array_reverse( $children ); |
|
368 } |
355 } |
369 } |
356 |
370 |
357 foreach ( $top_level_elements as $e ) { |
371 foreach ( $top_level_elements as $e ) { |
358 $count++; |
372 $count++; |
359 |
373 |
360 // For the last page, need to unset earlier children in order to keep track of orphans. |
374 // For the last page, need to unset earlier children in order to keep track of orphans. |
361 if ( $end >= $total_top && $count < $start ) |
375 if ( $end >= $total_top && $count < $start ) { |
362 $this->unset_children( $e, $children_elements ); |
376 $this->unset_children( $e, $children_elements ); |
363 |
377 } |
364 if ( $count < $start ) |
378 |
|
379 if ( $count < $start ) { |
365 continue; |
380 continue; |
366 |
381 } |
367 if ( $count >= $end ) |
382 |
|
383 if ( $count >= $end ) { |
368 break; |
384 break; |
|
385 } |
369 |
386 |
370 $this->display_element( $e, $children_elements, $max_depth, 0, $args, $output ); |
387 $this->display_element( $e, $children_elements, $max_depth, 0, $args, $output ); |
371 } |
388 } |
372 |
389 |
373 if ( $end >= $total_top && count( $children_elements ) > 0 ) { |
390 if ( $end >= $total_top && count( $children_elements ) > 0 ) { |
374 $empty_array = array(); |
391 $empty_array = array(); |
375 foreach ( $children_elements as $orphans ) |
392 foreach ( $children_elements as $orphans ) { |
376 foreach ( $orphans as $op ) |
393 foreach ( $orphans as $op ) { |
377 $this->display_element( $op, $empty_array, 1, 0, $args, $output ); |
394 $this->display_element( $op, $empty_array, 1, 0, $args, $output ); |
|
395 } |
|
396 } |
378 } |
397 } |
379 |
398 |
380 return $output; |
399 return $output; |
381 } |
400 } |
382 |
401 |