Last active
April 20, 2018 04:24
-
-
Save tlovett1/ec0e2f6c4efcb7555f653e7bd4d52463 to your computer and use it in GitHub Desktop.
Performant utility function for building a tree of WordPress terms.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Performant utility function for building a term tree. | |
* | |
* Tree will look like this: | |
* [ | |
* WP_Term( | |
* name | |
* slug | |
* children ->[ | |
* WP_Term() | |
* ] | |
* ), | |
* WP_Term() | |
* ] | |
* | |
* Example usage: | |
* $terms = get_terms( [ 'taxonomy' => 'category' ] ); | |
* $term_tree = wp_get_term_tree( $terms ); | |
* | |
* @param array $all_terms Pass get_terms() as this argument where terms are objects NOT arrays | |
* @param string|bool $orderby Can be count|name|false. This is how each tree branch will be ordered | |
* @param string $order Can be asc|desc. This is the direction ordering will occur. | |
* @param bool $flat If false, a tree will be returned e.g. an array of top level terms | |
* which children linked within each node. If true, the tree will be | |
* "flattened" | |
* @since 2.5 | |
* @return array | |
*/ | |
function wp_get_term_tree( $all_terms, $orderby = 'count', $order = 'desc', $flat = false ) { | |
$terms_map = array(); | |
$terms_tree = array(); | |
$iteration_id = 0; | |
while ( true ) { | |
if ( empty( $all_terms ) ) { | |
break; | |
} | |
foreach ( $all_terms as $key => $term ) { | |
$iteration_id++; | |
if ( ! isset( $term->children ) ) { | |
$term->children = array(); | |
} | |
if ( ! isset( $terms_map[ $term->term_id ] ) ) { | |
$terms_map[ $term->term_id ] = $term; | |
} | |
if ( empty( $term->parent ) ) { | |
$term->level = 0; | |
if ( empty( $orderby ) ) { | |
$terms_tree[] = $term; | |
} elseif ( 'count' === $orderby ) { | |
/** | |
* We add this weird number to get past terms with the same count | |
*/ | |
$terms_tree[ ( ( $term->count * 10000000 ) + $iteration_id ) ] = $term; | |
} elseif ( 'name' === $orderby ) { | |
$terms_tree[ strtolower( $term->name ) ] = $term; | |
} | |
unset( $all_terms[ $key ] ); | |
} else { | |
if ( ! empty( $terms_map[ $term->parent ] ) && isset( $terms_map[ $term->parent ]->level ) ) { | |
if ( empty( $orderby ) ) { | |
$terms_map[ $term->parent ]->children[] = $term; | |
} elseif ( 'count' === $orderby ) { | |
$terms_map[ $term->parent ]->children[ ( ( $term->count * 10000000 ) + $iteration_id ) ] = $term; | |
} elseif ( 'name' === $orderby ) { | |
$terms_map[ $term->parent ]->children[ $term->name ] = $term; | |
} | |
$parent_level = ( $terms_map[ $term->parent ]->level ) ? $terms_map[ $term->parent ]->level : 0; | |
$term->level = $parent_level + 1; | |
$term->parent_term = $terms_map[ $term->parent ]; | |
unset( $all_terms[ $key ] ); | |
} | |
} | |
} | |
} | |
if ( ! empty( $orderby ) ) { | |
if ( 'asc' === $order ) { | |
ksort( $terms_tree ); | |
} else { | |
krsort( $terms_tree ); | |
} | |
foreach ( $terms_map as $term ) { | |
if ( 'asc' === $order ) { | |
ksort( $term->children ); | |
} else { | |
krsort( $term->children ); | |
} | |
$term->children = array_values( $term->children ); | |
} | |
$terms_tree = array_values( $terms_tree ); | |
} | |
if ( $flat ) { | |
$flat_tree = array(); | |
foreach ( $terms_tree as $term ) { | |
$flat_tree[] = $term; | |
$to_process = $term->children; | |
while ( ! empty( $to_process ) ) { | |
$term = array_shift( $to_process ); | |
$flat_tree[] = $term; | |
if ( ! empty( $term->children ) ) { | |
$to_process = $term->children + $to_process; | |
} | |
} | |
} | |
return $flat_tree; | |
} | |
return $terms_tree; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment