| 402 | | function walk($elements, $to_depth) { |
| 403 | | $args = array_slice(func_get_args(), 2); $parents = array(); $depth = 1; $previous_element = ''; $output = ''; |
| 404 | | |
| 405 | | //padding at the end |
| 406 | | $last_element->post_parent = 0; |
| 407 | | $last_element->post_id = 0; |
| 408 | | $elements[] = $last_element; |
| 409 | | |
| | 403 | /* |
| | 404 | * display one element if the element doesn't have any children |
| | 405 | * otherwise, display the element and its children |
| | 406 | */ |
| | 407 | function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, $output ) { |
| | 408 | |
| | 409 | if ( !$element) |
| | 410 | return $output; |
| | 411 | |
| | 412 | if ( $max_depth != 0 ) { |
| | 413 | if ($depth >= $max_depth) |
| | 414 | return $output; |
| | 415 | } |
| | 416 | |
| 413 | | $flat = ($to_depth == -1) ? true : false; |
| 414 | | |
| 415 | | foreach ( $elements as $element ) { |
| 416 | | // If flat, start and end the element and skip the level checks. |
| 417 | | if ( $flat) { |
| 418 | | // Start the element. |
| 419 | | if ( isset($element->$id_field) && $element->$id_field != 0 ) { |
| 420 | | $cb_args = array_merge( array($output, $element, $depth - 1), $args); |
| 421 | | $output = call_user_func_array(array(&$this, 'start_el'), $cb_args); |
| 422 | | } |
| 423 | | |
| 424 | | // End the element. |
| 425 | | if ( isset($element->$id_field) && $element->$id_field != 0 ) { |
| 426 | | $cb_args = array_merge( array($output, $element, $depth - 1), $args); |
| 427 | | $output = call_user_func_array(array(&$this, 'end_el'), $cb_args); |
| 428 | | } |
| 429 | | |
| 430 | | continue; |
| | 424 | if ( !$children_elements ) { |
| | 425 | //close off this element |
| | 426 | $cb_args = array_merge( array($output, $element, $depth), $args); |
| | 427 | $output = call_user_func_array(array(&$this, 'end_el'), $cb_args); |
| | 428 | return $output; |
| | 429 | } |
| | 430 | |
| | 431 | for ( $i = 0; $i < sizeof( $children_elements ); $i++ ) { |
| | 432 | $child = $children_elements[$i]; |
| | 433 | |
| | 434 | if ( $child->$parent_field == $element->$id_field ) { |
| | 435 | |
| | 436 | array_splice( $children_elements, $i, 1 ); |
| | 437 | |
| | 438 | //start the child delimiter |
| | 439 | $cb_args = array_merge( array($output, $depth), $args); |
| | 440 | $output = call_user_func_array(array(&$this, 'start_lvl'), $cb_args); |
| | 441 | |
| | 442 | $output = $this->display_element( $child, $children_elements, $max_depth, $depth + 1, $args, $output ); |
| | 443 | |
| | 444 | //end the child delimiter |
| | 445 | $cb_args = array_merge( array($output, $depth), $args); |
| | 446 | $output = call_user_func_array(array(&$this, 'end_lvl'), $cb_args); |
| | 447 | $i--; |
| 433 | | // Walk the tree. |
| 434 | | if ( !empty($previous_element) && ($element->$parent_field == $previous_element->$id_field) ) { |
| 435 | | // Previous element is my parent. Descend a level. |
| 436 | | array_unshift($parents, $previous_element); |
| 437 | | if ( !$to_depth || ($depth < $to_depth) ) { //only descend if we're below $to_depth |
| 438 | | $cb_args = array_merge( array($output, $depth), $args); |
| 439 | | $output = call_user_func_array(array(&$this, 'start_lvl'), $cb_args); |
| 440 | | } else if ( $to_depth && $depth == $to_depth ) { // If we've reached depth, end the previous element. |
| 441 | | $cb_args = array_merge( array($output, $previous_element, $depth), $args); |
| 442 | | $output = call_user_func_array(array(&$this, 'end_el'), $cb_args); |
| 443 | | } |
| 444 | | $depth++; //always do this so when we start the element further down, we know where we are |
| 445 | | } else if ( $element->$parent_field == $previous_element->$parent_field) { |
| 446 | | // On the same level as previous element. |
| 447 | | if ( !$to_depth || ($depth <= $to_depth) ) { |
| 448 | | $cb_args = array_merge( array($output, $previous_element, $depth - 1), $args); |
| 449 | | $output = call_user_func_array(array(&$this, 'end_el'), $cb_args); |
| 450 | | } |
| 451 | | } else if ( $depth > 1 ) { |
| 452 | | // Ascend one or more levels. |
| 453 | | if ( !$to_depth || ($depth <= $to_depth) ) { |
| 454 | | $cb_args = array_merge( array($output, $previous_element, $depth - 1), $args); |
| 455 | | $output = call_user_func_array(array(&$this, 'end_el'), $cb_args); |
| 456 | | } |
| | 453 | /* |
| | 454 | * displays array of elements hierarchically |
| | 455 | * max_depth = -1 means flatly display every element |
| | 456 | * max_depth = 0 means display all levels |
| | 457 | * max_depth > 0 specifies the number of display levels. |
| | 458 | */ |
| | 459 | function walk( $elements, $max_depth) { |
| | 460 | |
| | 461 | $args = array_slice(func_get_args(), 2); |
| | 462 | $output = ''; |
| 458 | | while ( $parent = array_shift($parents) ) { |
| 459 | | $depth--; |
| 460 | | if ( !$to_depth || ($depth < $to_depth) ) { |
| 461 | | $cb_args = array_merge( array($output, $depth), $args); |
| 462 | | $output = call_user_func_array(array(&$this, 'end_lvl'), $cb_args); |
| 463 | | $cb_args = array_merge( array($output, $parent, $depth - 1), $args); |
| 464 | | $output = call_user_func_array(array(&$this, 'end_el'), $cb_args); |
| 465 | | } |
| 466 | | if ( $element->$parent_field == $parents[0]->$id_field ) { |
| 467 | | break; |
| 468 | | } |
| 469 | | } |
| 470 | | } else if ( !empty($previous_element) ) { |
| 471 | | // Close off previous element. |
| 472 | | if ( !$to_depth || ($depth <= $to_depth) ) { |
| 473 | | $cb_args = array_merge( array($output, $previous_element, $depth - 1), $args); |
| 474 | | $output = call_user_func_array(array(&$this, 'end_el'), $cb_args); |
| 475 | | } |
| 476 | | } |
| | 464 | $id_field = $this->db_fields['id']; |
| | 465 | $parent_field = $this->db_fields['parent']; |
| 478 | | // Start the element. |
| 479 | | if ( !$to_depth || ($depth <= $to_depth) ) { |
| 480 | | if ( $element->$id_field != 0 ) { |
| 481 | | $cb_args = array_merge( array($output, $element, $depth - 1), $args); |
| 482 | | $output = call_user_func_array(array(&$this, 'start_el'), $cb_args); |
| 483 | | } |
| 484 | | } |
| 485 | | |
| 486 | | $previous_element = $element; |
| | 467 | $flat = ($max_depth == -1) ? true : false; |
| | 468 | if ( $flat ) { |
| | 469 | $empty_array = array(); |
| | 470 | foreach ( $elements as $e ) |
| | 471 | $output = $this->display_element( $e, $empty_array, 1, 0, $args, $output ); |
| | 472 | return $output; |
| 488 | | |
| 489 | | return $output; |
| | 474 | |
| | 475 | /* |
| | 476 | * need to display in hierarchical order |
| | 477 | * splice elements into two buckets: those without parent and those with parent |
| | 478 | */ |
| | 479 | |
| | 480 | $top_level_elements = array(); |
| | 481 | $children_elements = array(); |
| | 482 | |
| | 483 | foreach ( $elements as $e) { |
| | 484 | if ( 0 == $e->$parent_field ) |
| | 485 | $top_level_elements[] = $e; |
| | 486 | else |
| | 487 | $children_elements[] = $e; |
| | 488 | } |
| | 489 | |
| | 490 | foreach ( $top_level_elements as $e ) |
| | 491 | $output = $this->display_element( $e, $children_elements, $max_depth, 0, $args, $output ); |
| | 492 | |
| | 493 | /* |
| | 494 | * if we are displaying all levels, and remaining children_elements is not empty, |
| | 495 | * then we got orphans, which should be displayed regardless |
| | 496 | */ |
| | 497 | if ( ( $max_depth == 0 ) && sizeof( $children_elements ) > 0 ) { |
| | 498 | $empty_array = array(); |
| | 499 | foreach ( $children_elements as $orphan_e ) |
| | 500 | $output = $this->display_element( $orphan_e, $empty_array, 1, 0, $args, $output ); |
| | 501 | } |
| | 502 | return $output; |