wp/wp-includes/class-wp-walker.php
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
equal deleted inserted replaced
20:7b1b88e27a20 21:48c4eec2b7e6
     9  * @since 2.1.0
     9  * @since 2.1.0
    10  *
    10  *
    11  * @package WordPress
    11  * @package WordPress
    12  * @abstract
    12  * @abstract
    13  */
    13  */
       
    14 #[AllowDynamicProperties]
    14 class Walker {
    15 class Walker {
    15 	/**
    16 	/**
    16 	 * What the class handles.
    17 	 * What the class handles.
    17 	 *
    18 	 *
    18 	 * @since 2.1.0
    19 	 * @since 2.1.0
   132 	public function display_element( $element, &$children_elements, $max_depth, $depth, $args, &$output ) {
   133 	public function display_element( $element, &$children_elements, $max_depth, $depth, $args, &$output ) {
   133 		if ( ! $element ) {
   134 		if ( ! $element ) {
   134 			return;
   135 			return;
   135 		}
   136 		}
   136 
   137 
       
   138 		$max_depth = (int) $max_depth;
       
   139 		$depth     = (int) $depth;
       
   140 
   137 		$id_field = $this->db_fields['id'];
   141 		$id_field = $this->db_fields['id'];
   138 		$id       = $element->$id_field;
   142 		$id       = $element->$id_field;
   139 
   143 
   140 		// Display this element.
   144 		// Display this element.
   141 		$this->has_children = ! empty( $children_elements[ $id ] );
   145 		$this->has_children = ! empty( $children_elements[ $id ] );
   144 		}
   148 		}
   145 
   149 
   146 		$this->start_el( $output, $element, $depth, ...array_values( $args ) );
   150 		$this->start_el( $output, $element, $depth, ...array_values( $args ) );
   147 
   151 
   148 		// Descend only when the depth is right and there are children for this element.
   152 		// Descend only when the depth is right and there are children for this element.
   149 		if ( ( 0 == $max_depth || $max_depth > $depth + 1 ) && isset( $children_elements[ $id ] ) ) {
   153 		if ( ( 0 === $max_depth || $max_depth > $depth + 1 ) && isset( $children_elements[ $id ] ) ) {
   150 
   154 
   151 			foreach ( $children_elements[ $id ] as $child ) {
   155 			foreach ( $children_elements[ $id ] as $child ) {
   152 
   156 
   153 				if ( ! isset( $newlevel ) ) {
   157 				if ( ! isset( $newlevel ) ) {
   154 					$newlevel = true;
   158 					$newlevel = true;
   188 	 * @return string The hierarchical item output.
   192 	 * @return string The hierarchical item output.
   189 	 */
   193 	 */
   190 	public function walk( $elements, $max_depth, ...$args ) {
   194 	public function walk( $elements, $max_depth, ...$args ) {
   191 		$output = '';
   195 		$output = '';
   192 
   196 
       
   197 		$max_depth = (int) $max_depth;
       
   198 
   193 		// Invalid parameter or nothing to walk.
   199 		// Invalid parameter or nothing to walk.
   194 		if ( $max_depth < -1 || empty( $elements ) ) {
   200 		if ( $max_depth < -1 || empty( $elements ) ) {
   195 			return $output;
   201 			return $output;
   196 		}
   202 		}
   197 
   203 
   198 		$parent_field = $this->db_fields['parent'];
   204 		$parent_field = $this->db_fields['parent'];
   199 
   205 
   200 		// Flat display.
   206 		// Flat display.
   201 		if ( -1 == $max_depth ) {
   207 		if ( -1 === $max_depth ) {
   202 			$empty_array = array();
   208 			$empty_array = array();
   203 			foreach ( $elements as $e ) {
   209 			foreach ( $elements as $e ) {
   204 				$this->display_element( $e, $empty_array, 1, 0, $args, $output );
   210 				$this->display_element( $e, $empty_array, 1, 0, $args, $output );
   205 			}
   211 			}
   206 			return $output;
   212 			return $output;
   232 			$root  = $first[0];
   238 			$root  = $first[0];
   233 
   239 
   234 			$top_level_elements = array();
   240 			$top_level_elements = array();
   235 			$children_elements  = array();
   241 			$children_elements  = array();
   236 			foreach ( $elements as $e ) {
   242 			foreach ( $elements as $e ) {
   237 				if ( $root->$parent_field == $e->$parent_field ) {
   243 				if ( $root->$parent_field === $e->$parent_field ) {
   238 					$top_level_elements[] = $e;
   244 					$top_level_elements[] = $e;
   239 				} else {
   245 				} else {
   240 					$children_elements[ $e->$parent_field ][] = $e;
   246 					$children_elements[ $e->$parent_field ][] = $e;
   241 				}
   247 				}
   242 			}
   248 			}
   248 
   254 
   249 		/*
   255 		/*
   250 		 * If we are displaying all levels, and remaining children_elements is not empty,
   256 		 * If we are displaying all levels, and remaining children_elements is not empty,
   251 		 * then we got orphans, which should be displayed regardless.
   257 		 * then we got orphans, which should be displayed regardless.
   252 		 */
   258 		 */
   253 		if ( ( 0 == $max_depth ) && count( $children_elements ) > 0 ) {
   259 		if ( ( 0 === $max_depth ) && count( $children_elements ) > 0 ) {
   254 			$empty_array = array();
   260 			$empty_array = array();
   255 			foreach ( $children_elements as $orphans ) {
   261 			foreach ( $children_elements as $orphans ) {
   256 				foreach ( $orphans as $op ) {
   262 				foreach ( $orphans as $op ) {
   257 					$this->display_element( $op, $empty_array, 1, 0, $args, $output );
   263 					$this->display_element( $op, $empty_array, 1, 0, $args, $output );
   258 				}
   264 				}
   282 	 * @param int   $per_page  Number of elements per page.
   288 	 * @param int   $per_page  Number of elements per page.
   283 	 * @param mixed ...$args   Optional additional arguments.
   289 	 * @param mixed ...$args   Optional additional arguments.
   284 	 * @return string XHTML of the specified page of elements.
   290 	 * @return string XHTML of the specified page of elements.
   285 	 */
   291 	 */
   286 	public function paged_walk( $elements, $max_depth, $page_num, $per_page, ...$args ) {
   292 	public function paged_walk( $elements, $max_depth, $page_num, $per_page, ...$args ) {
       
   293 		$output = '';
       
   294 
       
   295 		$max_depth = (int) $max_depth;
       
   296 
   287 		if ( empty( $elements ) || $max_depth < -1 ) {
   297 		if ( empty( $elements ) || $max_depth < -1 ) {
   288 			return '';
   298 			return $output;
   289 		}
   299 		}
   290 
       
   291 		$output = '';
       
   292 
   300 
   293 		$parent_field = $this->db_fields['parent'];
   301 		$parent_field = $this->db_fields['parent'];
   294 
   302 
   295 		$count = -1;
   303 		$count = -1;
   296 		if ( -1 == $max_depth ) {
   304 		if ( -1 === $max_depth ) {
   297 			$total_top = count( $elements );
   305 			$total_top = count( $elements );
   298 		}
   306 		}
   299 		if ( $page_num < 1 || $per_page < 0 ) {
   307 		if ( $page_num < 1 || $per_page < 0 ) {
   300 			// No paging.
   308 			// No paging.
   301 			$paging = false;
   309 			$paging = false;
   302 			$start  = 0;
   310 			$start  = 0;
   303 			if ( -1 == $max_depth ) {
   311 			if ( -1 === $max_depth ) {
   304 				$end = $total_top;
   312 				$end = $total_top;
   305 			}
   313 			}
   306 			$this->max_pages = 1;
   314 			$this->max_pages = 1;
   307 		} else {
   315 		} else {
   308 			$paging = true;
   316 			$paging = true;
   309 			$start  = ( (int) $page_num - 1 ) * (int) $per_page;
   317 			$start  = ( (int) $page_num - 1 ) * (int) $per_page;
   310 			$end    = $start + $per_page;
   318 			$end    = $start + $per_page;
   311 			if ( -1 == $max_depth ) {
   319 			if ( -1 === $max_depth ) {
   312 				$this->max_pages = ceil( $total_top / $per_page );
   320 				$this->max_pages = (int) ceil( $total_top / $per_page );
   313 			}
   321 			}
   314 		}
   322 		}
   315 
   323 
   316 		// Flat display.
   324 		// Flat display.
   317 		if ( -1 == $max_depth ) {
   325 		if ( -1 === $max_depth ) {
   318 			if ( ! empty( $args[0]['reverse_top_level'] ) ) {
   326 			if ( ! empty( $args[0]['reverse_top_level'] ) ) {
   319 				$elements = array_reverse( $elements );
   327 				$elements = array_reverse( $elements );
   320 				$oldstart = $start;
   328 				$oldstart = $start;
   321 				$start    = $total_top - $end;
   329 				$start    = $total_top - $end;
   322 				$end      = $total_top - $oldstart;
   330 				$end      = $total_top - $oldstart;
   323 			}
   331 			}
   324 
   332 
   325 			$empty_array = array();
   333 			$empty_array = array();
   326 			foreach ( $elements as $e ) {
   334 			foreach ( $elements as $e ) {
   327 				$count++;
   335 				++$count;
   328 				if ( $count < $start ) {
   336 				if ( $count < $start ) {
   329 					continue;
   337 					continue;
   330 				}
   338 				}
   331 				if ( $count >= $end ) {
   339 				if ( $count >= $end ) {
   332 					break;
   340 					break;
   351 			}
   359 			}
   352 		}
   360 		}
   353 
   361 
   354 		$total_top = count( $top_level_elements );
   362 		$total_top = count( $top_level_elements );
   355 		if ( $paging ) {
   363 		if ( $paging ) {
   356 			$this->max_pages = ceil( $total_top / $per_page );
   364 			$this->max_pages = (int) ceil( $total_top / $per_page );
   357 		} else {
   365 		} else {
   358 			$end = $total_top;
   366 			$end = $total_top;
   359 		}
   367 		}
   360 
   368 
   361 		if ( ! empty( $args[0]['reverse_top_level'] ) ) {
   369 		if ( ! empty( $args[0]['reverse_top_level'] ) ) {
   369 				$children_elements[ $parent ] = array_reverse( $children );
   377 				$children_elements[ $parent ] = array_reverse( $children );
   370 			}
   378 			}
   371 		}
   379 		}
   372 
   380 
   373 		foreach ( $top_level_elements as $e ) {
   381 		foreach ( $top_level_elements as $e ) {
   374 			$count++;
   382 			++$count;
   375 
   383 
   376 			// For the last page, need to unset earlier children in order to keep track of orphans.
   384 			// For the last page, need to unset earlier children in order to keep track of orphans.
   377 			if ( $end >= $total_top && $count < $start ) {
   385 			if ( $end >= $total_top && $count < $start ) {
   378 					$this->unset_children( $e, $children_elements );
   386 					$this->unset_children( $e, $children_elements );
   379 			}
   387 			}
   413 		$num          = 0;
   421 		$num          = 0;
   414 		$parent_field = $this->db_fields['parent'];
   422 		$parent_field = $this->db_fields['parent'];
   415 
   423 
   416 		foreach ( $elements as $e ) {
   424 		foreach ( $elements as $e ) {
   417 			if ( empty( $e->$parent_field ) ) {
   425 			if ( empty( $e->$parent_field ) ) {
   418 				$num++;
   426 				++$num;
   419 			}
   427 			}
   420 		}
   428 		}
   421 		return $num;
   429 		return $num;
   422 	}
   430 	}
   423 
   431 
   443 			}
   451 			}
   444 		}
   452 		}
   445 
   453 
   446 		unset( $children_elements[ $id ] );
   454 		unset( $children_elements[ $id ] );
   447 	}
   455 	}
   448 
       
   449 }
   456 }