Opened 9 years ago
Last modified 5 years ago
#36171 new enhancement
Proposed clean up of get_the_category_list() and link filter
Reported by: | pietergoosen | Owned by: | |
---|---|---|---|
Milestone: | Priority: | normal | |
Severity: | normal | Version: | 4.4.2 |
Component: | Taxonomy | Keywords: | needs-testing needs-unit-tests |
Focuses: | template | Cc: |
Description
The current source code of the get_the_category_list()
function is quite messy and there is also a lot of duplicate code which we can avoid.
Also, on a micro optimization level, in stead of passing the category ID to get_category_link()
, we can pass the whole category object. Doing this will avoid the extra overhead of having to get the complete category object from the term cache.
There is also no filter to filter each category link on category level, we only have the the_category
filter which filters the string of links. We have being receiving a couple of questions on wordpress.stackexchange.com regarding filtering these category links according to category. Here is such one question.
My proposal is included in my code, a filter called the_category_list_links
which we can use to filter each category link individually according to the category. One such use-case of the filter can look something like
add_filter( 'the_category_list_links', function ( $the_link_list, $category, $cat_parents ) { $category_color = get_field( 'category_color', $category ); if ( !$category_color ) return $the_link_list; $the_link_list = str_replace( '<a', '<a style="color:' . $category_color . '"', $the_link_list ); return $the_link_list; }, 10, 3 );
On initial testing, I can confirm that my code is slightly faster that the current code, and the new the_category_list_links
filter is working as intended
Here is the proposed cleanup
/** * Retrieve category list in either HTML list or custom format. * * @since 1.5.1 * * @global WP_Rewrite $wp_rewrite * * @param string $separator Optional, default is empty string. Separator for between the categories. * @param string $parents Optional. How to display the parents. * @param int $post_id Optional. Post ID to retrieve categories. * @return string */ function get_the_category_list( $separator = '', $parents = '', $post_id = false ) { global $wp_rewrite; if ( ! is_object_in_taxonomy( get_post_type( $post_id ), 'category' ) ) { /** This filter is documented in wp-includes/category-template.php */ return apply_filters( 'the_category', '', $separator, $parents ); } /** * Filter the categories before building the category list. * * @since 4.4.0 * * @param array $categories An array of the post's categories. * @param int|bool $post_id ID of the post we're retrieving categories for. When `false`, we assume the * current post in the loop. */ $categories = apply_filters( 'the_category_list', get_the_category( $post_id ), $post_id ); if ( empty( $categories ) ) { /** This filter is documented in wp-includes/category-template.php */ return apply_filters( 'the_category', __( 'Uncategorized' ), $separator, $parents ); } $rel = ( is_object( $wp_rewrite ) && $wp_rewrite->using_permalinks() ) ? 'rel="category tag"' : 'rel="category"'; $links = array(); foreach ( $categories as $category ) { /** * Break the link for better link building */ $start_link = '<a href="' . esc_url( get_category_link( $category->term_id ) ) . '" ' . $rel . '>'; $end_link = $category->name . '</a>'; /** * Build the category links */ $the_link_list = ''; switch ( strtolower( $parents ) ) { case 'multiple': $cat_parents = $category->parent ? get_category_parents( $category->parent, true, $separator ) : ''; $the_link_list = $cat_parents . ' ' . $start_link . $end_link; break; case 'single': $cat_parents = $category->parent ? get_category_parents( $category->parent, false, $separator ) : ''; $the_link_list = $start_link . $cat_parents . $end_link; break; case '': default: $the_link_list = $start_link . $end_link; } /** * Filter the category links on category level. * * @since X.X.X * * @param string $the_link_list Post category link. * @param object $category The current category object * @param $cat_parents Link list of parents of the current category */ $links[] = apply_filters( 'the_category_list_links', $the_link_list, $category, $cat_parents ); } $thelist = ''; if( '' === $separator ) { $thelist .= '<ul class="post-categories">'; $thelist .= "\n\t<li>"; $thelist .= implode( "</li>\n\t<li>", $links ); $thelist .= '</li>'; $thelist .= '</ul>'; } else { $thelist .= implode( $separator, $links ); } /** * Filter the category or list of categories. * * @since 1.2.0 * * @param array $thelist List of categories for the current post. * @param string $separator Separator used between the categories. * @param string $parents How to display the category parents. Accepts 'multiple', * 'single', or empty. */ return apply_filters( 'the_category', $thelist, $separator, $parents ); }
Attachments (2)
Change History (5)
#2
follow-up:
↓ 3
@
9 years ago
- Component changed from Formatting to Taxonomy
- Focuses template added; performance removed
- Keywords needs-unit-tests added
- Milestone changed from Awaiting Review to Future Release
#3
in reply to:
↑ 2
@
9 years ago
Replying to boonebgorges:
Hi @pietergoosen - Thanks very much for the suggested improvements.
The changes generally look good. The DRY cleanup looks fine at a glance, and the additional filter will be quite welcome.
I've reformatted your suggestions as a proper patch. See https://make.wordpress.org/core/handbook/tutorials/trac/submitting-a-patch/ for more info on how patches are generated. 36171.diff
Unfortunately,
get_the_category_list()
currently has zero coverage by automated tests. Fairly decent tests are critical before we can consider this kind of refactor.
Thank you for your feedback, I really appreciate it. Thanks for the tutorial, this is my first submit, so the tutorial will help in future ;-)
I do agree that some testing is needed. I'm not particulary happy with how parent are displayed, and the fact that the new proposed filter do not directly target parents. I have kept the original way how the function handles parents for now. Ideally I would like to drop get_category_parents()
from the function and let get_the_category_list()
handles the parents so we can apply our filter on parent level as well.
I originally thought of also applying the new proposed filter (the_category_list_links
) to the get_category_parents()
, but I'm not sure how useful it will be there.
Any thoughts on this will be appreciated
Hi @pietergoosen - Thanks very much for the suggested improvements.
The changes generally look good. The DRY cleanup looks fine at a glance, and the additional filter will be quite welcome.
I've reformatted your suggestions as a proper patch. See https://make.wordpress.org/core/handbook/tutorials/trac/submitting-a-patch/ for more info on how patches are generated. 36171.diff
Unfortunately,
get_the_category_list()
currently has zero coverage by automated tests. Fairly decent tests are critical before we can consider this kind of refactor.