WordPress.org

Make WordPress Core

Changeset 6384


Ignore:
Timestamp:
12/14/2007 09:46:52 PM (12 years ago)
Author:
ryan
Message:

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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}
Note: See TracChangeset for help on using the changeset viewer.