foreach ( $terms as $term ) { $term_id = $term->term_id; $parent_id = $term->parent; $temp_parents[ $term_id ] = $parent_id; if ( ! isset( $temp_children[ $parent_id ] ) ) { $temp_children[ $parent_id ] = array(); } $temp_children[ $parent_id ][] = $term_id; $temp_terms[ $term_id ] = array( 'slug' => $term->slug, 'name' => $term->name, 'parent' => $parent_id, 'term_id' => $term->term_id, ); } // Pre-compute descendants and ancestors. foreach ( array_keys( $temp_parents ) as $term_id ) { $map['descendants'][ $term_id ] = $this->compute_descendants( $term_id, $temp_children ); $map['ancestors'][ $term_id ] = $this->compute_ancestors( $term_id, $temp_parents ); } foreach ( $temp_children[0] as $term_id ) { $this->build_term_tree( $map['tree'], $term_id, $temp_children, $temp_terms ); } return $map; } /** * Recursively build hierarchical term tree with depth and parent. * * @param array $tree Reference to tree array being built. * @param int $term_id Current term ID. * @param array $children Children relationships map (parent_id => [child_ids]). * @param array $temp_terms Term data indexed by term_id. * @param int $depth Current depth level in hierarchy. */ private function build_term_tree( &$tree, $term_id, $children, $temp_terms, $depth = 0 ) { $tree[ $term_id ] = $temp_terms[ $term_id ]; $tree[ $term_id ]['depth'] = $depth; if ( ! empty( $children[ $term_id ] ) ) { foreach ( $children[ $term_id ] as $child_id ) { $this->build_term_tree( $tree[ $term_id ]['children'], $child_id, $children, $temp_terms, $depth + 1 ); } } } /** * Compute all descendants of a term. * * @param int $term_id The term ID. * @param array $children Children relationships map. * @return array Array of descendant term IDs. */ private function compute_descendants( int $term_id, array $children ): array { $descendants = array(); if ( ! isset( $children[ $term_id ] ) ) { return $descendants; } foreach ( $children[ $term_id ] as $child_id ) { $descendants[] = $child_id; $descendants = array_merge( $descendants, $this->compute_descendants( $child_id, $children ) ); } return array_unique( $descendants ); } /** * Compute ancestor chain for a term. * * @param int $term_id The term ID. * @param array $parent_lookup Parent relationships. * @return array Array of ancestor term IDs (bottom-up). */ private function compute_ancestors( int $term_id, array $parent_lookup ): array { $ancestors = array(); $current_id = $term_id; while ( isset( $parent_lookup[ $current_id ] ) && $parent_lookup[ $current_id ] > 0 ) { $parent_id = $parent_lookup[ $current_id ]; $ancestors[] = $parent_id; $current_id = $parent_id; } return $ancestors; } }