Skip to content

Instantly share code, notes, and snippets.

@hellofromtonya
Last active July 21, 2017 14:51
Show Gist options
  • Save hellofromtonya/510501db5f3c54a57bcc1f2b5ceaa1cf to your computer and use it in GitHub Desktop.
Save hellofromtonya/510501db5f3c54a57bcc1f2b5ceaa1cf to your computer and use it in GitHub Desktop.
Grab all of the term ancestors (child and walk up the tree) + the requested metadata.
<?php
/**
* Get the specified metadata value for the term or from
* one of it's parent terms.
*
* @since 1.0.0
*
* @param WP_Term $term Term object
* @param string $meta_key The meta key to retrieve.
*
* @return mixed|null
*/
function get_hierarchichal_term_metadata( WP_Term $term, $meta_key ) {
if ( ! is_taxonomy_hierarchical( $term->taxonomy ) ) {
return;
}
if ( ! has_parent_term( $term ) ) {
return;
}
$term_ancestors = get_terms_ancestory_tree( $term->term_id, $meta_key );
if ( $term_ancestors === false ) {
return;
}
// Loop through the objects until you find one that has a meta value.
foreach( (array) $term_ancestors as $term_ancestor ) {
if ( $term_ancestor->meta_value ) {
return $term_ancestor->meta_value;
}
}
// Whoops, didn't find one with a value for that meta key.
return;
}
/**
* Get an array of term ancestors for the given term id, meaning
* the SQL query starts at the given term id and then walks up
* the parent tree as it stores the columns.
*
* The result is an array of stdClass objects that have the following:
* term_id => int
* parent_id => int
* meta_value => value of that meta key's column
*
* @since 1.0.0
*
* @param integer $term_id
* @param string $meta_key The meta key to retrieve.
*
* @return array|bool
*/
function get_terms_ancestory_tree( $term_id, $meta_key ) {
global $wpdb;
$sql_query =
"SELECT t.term_id, @parent := t.parent AS parent_id, tm.meta_value
FROM (
SELECT *
FROM {$wpdb->term_taxonomy} AS tt
ORDER BY tt.parent DESC
) AS t
JOIN (
SELECT @parent := %d
) AS tmp
LEFT JOIN {$wpdb->termmeta} AS tm ON tm.term_id = @parent AND tm.meta_key = %s
WHERE t.term_id = @parent;";
$sql_query = $wpdb->prepare( $sql_query, $term_id, $meta_key );
$results = $wpdb->get_results( $sql_query );
if ( ! $results || ! is_array( $results ) ) {
return false;
}
return $results;
}
/**
* Checks if the term has a parent.
*
* @since 1.0.0
*
* @param WP_Term $term Term object.
*
* @return bool
*/
function has_parent_term( WP_Term $term ) {
return ( $term->parent > 0 );
}
@hellofromtonya
Copy link
Author

This approach grabs all of the database information in one database hit for the given term ID and requested meta key. It's more performant than using a recursive solution like this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment