Changeset 6384

Show
Ignore:
Timestamp:
12/14/07 21:46:52 (1 year ago)
Author:
ryan
Message:

Faster page and cat walker. Props hailin. see #5458

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/wp-includes/classes.php

    r6365 r6384  
    387387} 
    388388 
    389  
    390 // A class for displaying various tree-like structures. Extend the Walker class to use it, see examples at the bottom 
    391  
     389/*  
     390 * A class for displaying various tree-like structures.  
     391 * Extend the Walker class to use it, see examples at the bottom 
     392 */ 
    392393class Walker { 
    393394    var $tree_type; 
     
    400401    function end_el($output)    { return $output; } 
    401402 
    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     
    410417        $id_field = $this->db_fields['id']; 
    411418        $parent_field = $this->db_fields['parent']; 
    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--;  
    431448            } 
    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; 
    490503    } 
    491504}