WordPress.org

Make WordPress Core

Opened 2 years ago

Last modified 2 years ago

#32789 new enhancement

Abstract get_category_by_path into get_term_by_path

Reported by: sc0ttkclark Owned by:
Milestone: Future Release Priority: normal
Severity: normal Version:
Component: Taxonomy Keywords: needs-patch needs-unit-tests
Focuses: Cc:

Description

Having a function like get_term_by_path would be great as currently you have to fork the get_category_by_path function on your own to get a term by path for any other custom taxonomy.

Would there be any opposition to a patch for this? The abstracted function wouldn't house the _make_cat_compat usage, which would remain in the backwards compatible get_category_by_path function after checking to see if $category is not null.

Change History (5)

#1 @sc0ttkclark
2 years ago

Based on get_category_by_path:

/**
 * Retrieve term based on URL containing the term slug.
 *
 * Breaks the $term_path parameter up to get the term slug.
 *
 * Tries to find the child path and will return it. If it doesn't find a
 * match, then it will return the first term matching slug, if $full_match,
 * is set to false. If it does not, then it will return null.
 *
 * It is also possible that it will return a WP_Error object on failure. Check
 * for it when using this function.
 *
 * @param string $term_path URL containing term slugs.
 * @param string $taxonomy Taxonomy to match path for.
 * @param bool $full_match Optional. Whether full path should be matched.
 * @param string $output Optional. Constant OBJECT, ARRAY_A, or ARRAY_N
 *
 * @return null|object|array|\WP_Error Null on failure. Type is based on $output value.
 */
function get_term_by_path( $term_path, $taxonomy, $full_match = true, $output = OBJECT ) {

	$term_path = rawurlencode( urldecode( $term_path ) );
	$term_path = str_replace( '%2F', '/', $term_path );
	$term_path = str_replace( '%20', ' ', $term_path );

	$term_paths = '/' . trim( $term_path, '/' );

	$leaf_path = sanitize_title( basename( $term_paths ) );

	$term_paths = explode( '/', $term_paths );

	$full_path = '';

	foreach ( (array) $term_paths as $pathdir ) {
		if ( '' != $pathdir ) {
			$full_path .= '/';
		}

		$full_path .= sanitize_title( $pathdir );
	}

	$terms = get_terms( $taxonomy, array( 'get' => 'all', 'slug' => $leaf_path ) );

	if ( empty( $terms ) ) {
		return null;
	} elseif ( is_wp_error( $terms ) ) {
		return $terms;
	}

	foreach ( $terms as $term ) {
		$current_term = $term;

		$path = '/' . $leaf_path;

		while ( ( $current_term->parent != 0 ) && ( $current_term->parent != $current_term->term_id ) ) {
			$current_term = get_term( $current_term->parent, $taxonomy );

			if ( is_wp_error( $current_term ) ) {
				return $current_term;
			}

			$path = '/' . $current_term->slug . $path;
		}

		if ( $path === $full_path ) {
			return get_term( $term->term_id, $taxonomy, $output );
		}
	}

	// If full matching is not required, return the first cat that matches the leaf.
	if ( ! $full_match ) {
		$term = reset( $terms );

		return get_term( $term->term_id, $taxonomy, $output );
	}

	return null;

}

I added $taxonomy as a required second parameter.

I also fixed a few things, one was @return was not properly reporting WP_Error as a possible return type, others were formatting or variable names. The get_terms empty check did not have an elseif check for is_wp_error( $terms ) so that's been put in place as well.

Last edited 2 years ago by sc0ttkclark (previous) (diff)

#2 @johnbillion
2 years ago

  • Keywords needs-patch needs-unit-tests added

#3 @snakefoot
2 years ago

I have noticed that get_category_by_path doesn't work well with category-hierarchy, where the same slug exists with different parent.

Maybe fix this new generic term-method to handle this? And make get_category_by_path() call the new method?

Could be nice if the following was possible:

/men/shoes/
/women/shoes/

#4 @snakefoot
2 years ago

Also if the taxonomy-type doesn't support parent-hierarchy (Like categories), then you can perform fast optimization by just doing term-lookup of the last slug.

#5 @wonderboymusic
2 years ago

  • Milestone changed from Awaiting Review to Future Release
Note: See TracTickets for help on using tickets.