| 412 | | |
|---|
| 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; |
|---|
| | 419 | |
|---|
| | 420 | //display this element |
|---|
| | 421 | $cb_args = array_merge( array($output, $element, $depth), $args); |
|---|
| | 422 | $output = call_user_func_array(array(&$this, 'start_el'), $cb_args); |
|---|
| | 423 | |
|---|
| | 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--; |
|---|
| 432 | | |
|---|
| 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 | | } |
|---|
| 457 | | |
|---|
| 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 | | } |
|---|
| 477 | | |
|---|
| 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; |
|---|
| 487 | | } |
|---|
| 488 | | |
|---|
| 489 | | return $output; |
|---|
| | 449 | } |
|---|
| | 450 | return $output; |
|---|
| | 451 | } |
|---|
| | 452 | |
|---|
| | 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 = ''; |
|---|
| | 463 | |
|---|
| | 464 | $id_field = $this->db_fields['id']; |
|---|
| | 465 | $parent_field = $this->db_fields['parent']; |
|---|
| | 466 | |
|---|
| | 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; |
|---|
| | 473 | } |
|---|
| | 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; |
|---|