[ Index ]

WordPress Cross Reference

title

Body

[close]

/wp-includes/ -> class-wp-walker.php (source)

   1  <?php
   2  /**
   3   * A class for displaying various tree-like structures.
   4   *
   5   * Extend the Walker class to use it, see examples below. Child classes
   6   * do not need to implement all of the abstract methods in the class. The child
   7   * only needs to implement the methods that are needed.
   8   *
   9   * @since 2.1.0
  10   *
  11   * @package WordPress
  12   * @abstract
  13   */
  14  class Walker {
  15      /**
  16       * What the class handles.
  17       *
  18       * @since 2.1.0
  19       * @var string
  20       * @access public
  21       */
  22      var $tree_type;
  23  
  24      /**
  25       * DB fields to use.
  26       *
  27       * @since 2.1.0
  28       * @var array
  29       * @access protected
  30       */
  31      var $db_fields;
  32  
  33      /**
  34       * Max number of pages walked by the paged walker
  35       *
  36       * @since 2.7.0
  37       * @var int
  38       * @access protected
  39       */
  40      var $max_pages = 1;
  41  
  42      /**
  43       * Starts the list before the elements are added.
  44       *
  45       * The $args parameter holds additional values that may be used with the child
  46       * class methods. This method is called at the start of the output list.
  47       *
  48       * @since 2.1.0
  49       * @abstract
  50       *
  51       * @param string $output Passed by reference. Used to append additional content.
  52       * @param int    $depth  Depth of the item.
  53       * @param array  $args   An array of additional arguments.
  54       */
  55  	function start_lvl( &$output, $depth = 0, $args = array() ) {}
  56  
  57      /**
  58       * Ends the list of after the elements are added.
  59       *
  60       * The $args parameter holds additional values that may be used with the child
  61       * class methods. This method finishes the list at the end of output of the elements.
  62       *
  63       * @since 2.1.0
  64       * @abstract
  65       *
  66       * @param string $output Passed by reference. Used to append additional content.
  67       * @param int    $depth  Depth of the item.
  68       * @param array  $args   An array of additional arguments.
  69       */
  70  	function end_lvl( &$output, $depth = 0, $args = array() ) {}
  71  
  72      /**
  73       * Start the element output.
  74       *
  75       * The $args parameter holds additional values that may be used with the child
  76       * class methods. Includes the element output also.
  77       *
  78       * @since 2.1.0
  79       * @abstract
  80       *
  81       * @param string $output            Passed by reference. Used to append additional content.
  82       * @param object $object            The data object.
  83       * @param int    $depth             Depth of the item.
  84       * @param array  $args              An array of additional arguments.
  85       * @param int    $current_object_id ID of the current item.
  86       */
  87  	function start_el( &$output, $object, $depth = 0, $args = array(), $current_object_id = 0 ) {}
  88  
  89      /**
  90       * Ends the element output, if needed.
  91       *
  92       * The $args parameter holds additional values that may be used with the child class methods.
  93       *
  94       * @since 2.1.0
  95       * @abstract
  96       *
  97       * @param string $output Passed by reference. Used to append additional content.
  98       * @param object $object The data object.
  99       * @param int    $depth  Depth of the item.
 100       * @param array  $args   An array of additional arguments.
 101       */
 102  	function end_el( &$output, $object, $depth = 0, $args = array() ) {}
 103  
 104      /**
 105       * Traverse elements to create list from elements.
 106       *
 107       * Display one element if the element doesn't have any children otherwise,
 108       * display the element and its children. Will only traverse up to the max
 109       * depth and no ignore elements under that depth. It is possible to set the
 110       * max depth to include all depths, see walk() method.
 111       *
 112       * This method should not be called directly, use the walk() method instead.
 113       *
 114       * @since 2.5.0
 115       *
 116       * @param object $element           Data object.
 117       * @param array  $children_elements List of elements to continue traversing.
 118       * @param int    $max_depth         Max depth to traverse.
 119       * @param int    $depth             Depth of current element.
 120       * @param array  $args              An array of arguments.
 121       * @param string $output            Passed by reference. Used to append additional content.
 122       * @return null Null on failure with no changes to parameters.
 123       */
 124  	function display_element( $element, &$children_elements, $max_depth, $depth, $args, &$output ) {
 125  
 126          if ( !$element )
 127              return;
 128  
 129          $id_field = $this->db_fields['id'];
 130  
 131          //display this element
 132          if ( isset( $args[0] ) && is_array( $args[0] ) )
 133              $args[0]['has_children'] = ! empty( $children_elements[$element->$id_field] );
 134          $cb_args = array_merge( array(&$output, $element, $depth), $args);
 135          call_user_func_array(array($this, 'start_el'), $cb_args);
 136  
 137          $id = $element->$id_field;
 138  
 139          // descend only when the depth is right and there are childrens for this element
 140          if ( ($max_depth == 0 || $max_depth > $depth+1 ) && isset( $children_elements[$id]) ) {
 141  
 142              foreach( $children_elements[ $id ] as $child ){
 143  
 144                  if ( !isset($newlevel) ) {
 145                      $newlevel = true;
 146                      //start the child delimiter
 147                      $cb_args = array_merge( array(&$output, $depth), $args);
 148                      call_user_func_array(array($this, 'start_lvl'), $cb_args);
 149                  }
 150                  $this->display_element( $child, $children_elements, $max_depth, $depth + 1, $args, $output );
 151              }
 152              unset( $children_elements[ $id ] );
 153          }
 154  
 155          if ( isset($newlevel) && $newlevel ){
 156              //end the child delimiter
 157              $cb_args = array_merge( array(&$output, $depth), $args);
 158              call_user_func_array(array($this, 'end_lvl'), $cb_args);
 159          }
 160  
 161          //end this element
 162          $cb_args = array_merge( array(&$output, $element, $depth), $args);
 163          call_user_func_array(array($this, 'end_el'), $cb_args);
 164      }
 165  
 166      /**
 167       * Display array of elements hierarchically.
 168       *
 169       * Does not assume any existing order of elements.
 170       *
 171       * $max_depth = -1 means flatly display every element.
 172       * $max_depth = 0 means display all levels.
 173       * $max_depth > 0 specifies the number of display levels.
 174       *
 175       * @since 2.1.0
 176       *
 177       * @param array $elements  An array of elements.
 178       * @param int   $max_depth The maximum hierarchical depth.
 179       * @return string The hierarchical item output.
 180       */
 181  	function walk( $elements, $max_depth) {
 182  
 183          $args = array_slice(func_get_args(), 2);
 184          $output = '';
 185  
 186          if ($max_depth < -1) //invalid parameter
 187              return $output;
 188  
 189          if (empty($elements)) //nothing to walk
 190              return $output;
 191  
 192          $id_field = $this->db_fields['id'];
 193          $parent_field = $this->db_fields['parent'];
 194  
 195          // flat display
 196          if ( -1 == $max_depth ) {
 197              $empty_array = array();
 198              foreach ( $elements as $e )
 199                  $this->display_element( $e, $empty_array, 1, 0, $args, $output );
 200              return $output;
 201          }
 202  
 203          /*
 204           * Need to display in hierarchical order.
 205           * Separate elements into two buckets: top level and children elements.
 206           * Children_elements is two dimensional array, eg.
 207           * Children_elements[10][] contains all sub-elements whose parent is 10.
 208           */
 209          $top_level_elements = array();
 210          $children_elements  = array();
 211          foreach ( $elements as $e) {
 212              if ( 0 == $e->$parent_field )
 213                  $top_level_elements[] = $e;
 214              else
 215                  $children_elements[ $e->$parent_field ][] = $e;
 216          }
 217  
 218          /*
 219           * When none of the elements is top level.
 220           * Assume the first one must be root of the sub elements.
 221           */
 222          if ( empty($top_level_elements) ) {
 223  
 224              $first = array_slice( $elements, 0, 1 );
 225              $root = $first[0];
 226  
 227              $top_level_elements = array();
 228              $children_elements  = array();
 229              foreach ( $elements as $e) {
 230                  if ( $root->$parent_field == $e->$parent_field )
 231                      $top_level_elements[] = $e;
 232                  else
 233                      $children_elements[ $e->$parent_field ][] = $e;
 234              }
 235          }
 236  
 237          foreach ( $top_level_elements as $e )
 238              $this->display_element( $e, $children_elements, $max_depth, 0, $args, $output );
 239  
 240          /*
 241           * If we are displaying all levels, and remaining children_elements is not empty,
 242           * then we got orphans, which should be displayed regardless.
 243           */
 244          if ( ( $max_depth == 0 ) && count( $children_elements ) > 0 ) {
 245              $empty_array = array();
 246              foreach ( $children_elements as $orphans )
 247                  foreach( $orphans as $op )
 248                      $this->display_element( $op, $empty_array, 1, 0, $args, $output );
 249           }
 250  
 251           return $output;
 252      }
 253  
 254      /**
 255        * paged_walk() - produce a page of nested elements
 256        *
 257        * Given an array of hierarchical elements, the maximum depth, a specific page number,
 258        * and number of elements per page, this function first determines all top level root elements
 259        * belonging to that page, then lists them and all of their children in hierarchical order.
 260        *
 261       * $max_depth = 0 means display all levels.
 262       * $max_depth > 0 specifies the number of display levels.
 263       *
 264        * @since 2.7.0
 265       *
 266        * @param int $max_depth The maximum hierarchical depth.
 267        * @param int $page_num  The specific page number, beginning with 1.
 268        * @return string XHTML of the specified page of elements
 269        */
 270  	function paged_walk( $elements, $max_depth, $page_num, $per_page ) {
 271  
 272          /* sanity check */
 273          if ( empty($elements) || $max_depth < -1 )
 274              return '';
 275  
 276          $args = array_slice( func_get_args(), 4 );
 277          $output = '';
 278  
 279          $id_field = $this->db_fields['id'];
 280          $parent_field = $this->db_fields['parent'];
 281  
 282          $count = -1;
 283          if ( -1 == $max_depth )
 284              $total_top = count( $elements );
 285          if ( $page_num < 1 || $per_page < 0  ) {
 286              // No paging
 287              $paging = false;
 288              $start = 0;
 289              if ( -1 == $max_depth )
 290                  $end = $total_top;
 291              $this->max_pages = 1;
 292          } else {
 293              $paging = true;
 294              $start = ( (int)$page_num - 1 ) * (int)$per_page;
 295              $end   = $start + $per_page;
 296              if ( -1 == $max_depth )
 297                  $this->max_pages = ceil($total_top / $per_page);
 298          }
 299  
 300          // flat display
 301          if ( -1 == $max_depth ) {
 302              if ( !empty($args[0]['reverse_top_level']) ) {
 303                  $elements = array_reverse( $elements );
 304                  $oldstart = $start;
 305                  $start = $total_top - $end;
 306                  $end = $total_top - $oldstart;
 307              }
 308  
 309              $empty_array = array();
 310              foreach ( $elements as $e ) {
 311                  $count++;
 312                  if ( $count < $start )
 313                      continue;
 314                  if ( $count >= $end )
 315                      break;
 316                  $this->display_element( $e, $empty_array, 1, 0, $args, $output );
 317              }
 318              return $output;
 319          }
 320  
 321          /*
 322           * Separate elements into two buckets: top level and children elements.
 323           * Children_elements is two dimensional array, e.g.
 324           * $children_elements[10][] contains all sub-elements whose parent is 10.
 325           */
 326          $top_level_elements = array();
 327          $children_elements  = array();
 328          foreach ( $elements as $e) {
 329              if ( 0 == $e->$parent_field )
 330                  $top_level_elements[] = $e;
 331              else
 332                  $children_elements[ $e->$parent_field ][] = $e;
 333          }
 334  
 335          $total_top = count( $top_level_elements );
 336          if ( $paging )
 337              $this->max_pages = ceil($total_top / $per_page);
 338          else
 339              $end = $total_top;
 340  
 341          if ( !empty($args[0]['reverse_top_level']) ) {
 342              $top_level_elements = array_reverse( $top_level_elements );
 343              $oldstart = $start;
 344              $start = $total_top - $end;
 345              $end = $total_top - $oldstart;
 346          }
 347          if ( !empty($args[0]['reverse_children']) ) {
 348              foreach ( $children_elements as $parent => $children )
 349                  $children_elements[$parent] = array_reverse( $children );
 350          }
 351  
 352          foreach ( $top_level_elements as $e ) {
 353              $count++;
 354  
 355              // For the last page, need to unset earlier children in order to keep track of orphans.
 356              if ( $end >= $total_top && $count < $start )
 357                      $this->unset_children( $e, $children_elements );
 358  
 359              if ( $count < $start )
 360                  continue;
 361  
 362              if ( $count >= $end )
 363                  break;
 364  
 365              $this->display_element( $e, $children_elements, $max_depth, 0, $args, $output );
 366          }
 367  
 368          if ( $end >= $total_top && count( $children_elements ) > 0 ) {
 369              $empty_array = array();
 370              foreach ( $children_elements as $orphans )
 371                  foreach( $orphans as $op )
 372                      $this->display_element( $op, $empty_array, 1, 0, $args, $output );
 373          }
 374  
 375          return $output;
 376      }
 377  
 378  	function get_number_of_root_elements( $elements ){
 379  
 380          $num = 0;
 381          $parent_field = $this->db_fields['parent'];
 382  
 383          foreach ( $elements as $e) {
 384              if ( 0 == $e->$parent_field )
 385                  $num++;
 386          }
 387          return $num;
 388      }
 389  
 390      // Unset all the children for a given top level element.
 391  	function unset_children( $e, &$children_elements ){
 392  
 393          if ( !$e || !$children_elements )
 394              return;
 395  
 396          $id_field = $this->db_fields['id'];
 397          $id = $e->$id_field;
 398  
 399          if ( !empty($children_elements[$id]) && is_array($children_elements[$id]) )
 400              foreach ( (array) $children_elements[$id] as $child )
 401                  $this->unset_children( $child, $children_elements );
 402  
 403          if ( isset($children_elements[$id]) )
 404              unset( $children_elements[$id] );
 405  
 406      }
 407  
 408  } // Walker


Generated: Tue Mar 25 01:41:18 2014 WordPress honlapkészítés: online1.hu