Walker::walk()publicWP 2.1.0

Displays array of elements hierarchically.

Does not assume any existing order of elements.

$max_depth = -1 means flatly display every element. $max_depth = 0 means display all levels. $max_depth > 0 specifies the number of display levels.

Method of the class: Walker{}

No Hooks.

Return

String. The hierarchical item output.

Usage

$Walker = new Walker();
$Walker->walk( $elements, $max_depth, ...$args );
$elements(array) (required)
An array of elements.
$max_depth(int) (required)
The maximum hierarchical depth.
...$args(mixed) (required)
Optional additional arguments.

Changelog

Since 2.1.0 Introduced.
Since 5.3.0 Formalized the existing ...$args parameter by adding it to the function signature.

Walker::walk() code WP 6.6.2

public function walk( $elements, $max_depth, ...$args ) {
	$output = '';

	$max_depth = (int) $max_depth;

	// Invalid parameter or nothing to walk.
	if ( $max_depth < -1 || empty( $elements ) ) {
		return $output;
	}

	$parent_field = $this->db_fields['parent'];

	// Flat display.
	if ( -1 === $max_depth ) {
		$empty_array = array();
		foreach ( $elements as $e ) {
			$this->display_element( $e, $empty_array, 1, 0, $args, $output );
		}
		return $output;
	}

	/*
	 * Need to display in hierarchical order.
	 * Separate elements into two buckets: top level and children elements.
	 * Children_elements is two dimensional array. Example:
	 * Children_elements[10][] contains all sub-elements whose parent is 10.
	 */
	$top_level_elements = array();
	$children_elements  = array();
	foreach ( $elements as $e ) {
		if ( empty( $e->$parent_field ) ) {
			$top_level_elements[] = $e;
		} else {
			$children_elements[ $e->$parent_field ][] = $e;
		}
	}

	/*
	 * When none of the elements is top level.
	 * Assume the first one must be root of the sub elements.
	 */
	if ( empty( $top_level_elements ) ) {

		$first = array_slice( $elements, 0, 1 );
		$root  = $first[0];

		$top_level_elements = array();
		$children_elements  = array();
		foreach ( $elements as $e ) {
			if ( $root->$parent_field === $e->$parent_field ) {
				$top_level_elements[] = $e;
			} else {
				$children_elements[ $e->$parent_field ][] = $e;
			}
		}
	}

	foreach ( $top_level_elements as $e ) {
		$this->display_element( $e, $children_elements, $max_depth, 0, $args, $output );
	}

	/*
	 * If we are displaying all levels, and remaining children_elements is not empty,
	 * then we got orphans, which should be displayed regardless.
	 */
	if ( ( 0 === $max_depth ) && count( $children_elements ) > 0 ) {
		$empty_array = array();
		foreach ( $children_elements as $orphans ) {
			foreach ( $orphans as $op ) {
				$this->display_element( $op, $empty_array, 1, 0, $args, $output );
			}
		}
	}

	return $output;
}