Skip to content

Commit 70444a5

Browse files
committed
feat(Functions): Added term utils
1 parent 72da061 commit 70444a5

File tree

3 files changed

+171
-1
lines changed

3 files changed

+171
-1
lines changed

Term.php

+149
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
<?php //phpcs:disable SlevomatCodingStandard.Operators.SpreadOperatorSpacing.IncorrectSpacesAfterOperator
2+
3+
namespace XWP\Helper\Functions;
4+
5+
use Closure;
6+
use WP_Error;
7+
use WP_Term;
8+
9+
/**
10+
* Taxonomy and term helper functions.
11+
*/
12+
final class Term {
13+
/**
14+
* Formats a term name with its ancestors.
15+
*
16+
* @param WP_Term|int|string|null|array|\WP_Error $term WP_Term object, Term ID, Term slug, or Term name.
17+
* @param array<string, mixed> $args Formatting arguments. Default empty array.
18+
* - formatter (callable) Custom formatter for the displayed term name. Default null.
19+
* - count (bool) Whether to include the term count in the formatted name. Default false.
20+
* - link_format (string|callable|array|bool) URL Link format for the term link. Default false.
21+
* - link_items (bool) Whether to link the term items. Default false.
22+
* - link_final (bool) Whether to link the final term. Default true.
23+
* - separator (string) Separator between terms. Default ' > '.
24+
* - taxonomy (string) Taxonomy name. Default null. Mandatory if $term is a string. Optional otherwise.
25+
* @return string Formatted term name with ancestors.
26+
*/
27+
public static function format_hierarhical_name( WP_Term|int|string|null|array|\WP_Error $term, array $args = array() ): string {
28+
$args = self::parse_format_args( $args );
29+
$term = self::get_term_object( $term, $args['taxonomy'] ?? null );
30+
31+
if ( ! $term ) {
32+
return '';
33+
}
34+
35+
$formatter = self::get_name_formatter( $args );
36+
$formatted = \array_map( \get_term( ... ), \get_ancestors( $term->term_id, $term->taxonomy ) );
37+
$formatted = \array_map( $formatter, \array_reverse( $formatted ) );
38+
$formatted[] = $args['link_final'] ? $formatter( $term ) : $term->name;
39+
40+
$formatted = \implode( $args['separator'], $formatted );
41+
42+
return $args['show_count'] ? \sprintf( '%s (%d)', $formatted, $term->count ) : $formatted;
43+
}
44+
45+
/**
46+
* Parse the arguments for the term name formatter.
47+
*
48+
* @param array $args The arguments for the term name formatter.
49+
* @return array
50+
*/
51+
private static function parse_format_args( array $args ): array {
52+
$defs = array(
53+
'formatter' => null,
54+
'link_final' => true,
55+
'link_format' => true,
56+
'link_items' => true,
57+
'separator' => ' > ',
58+
'show_count' => false,
59+
'taxonomy' => null,
60+
);
61+
62+
if ( ! $args['link_format'] ) {
63+
$args['link_items'] = false;
64+
$args['link_final'] = false;
65+
}
66+
67+
return \wp_parse_args( $args, $defs );
68+
}
69+
70+
/**
71+
* Get the formatter for the term name.
72+
*
73+
* @param array $args The arguments for the term name formatter.
74+
* @return Closure
75+
*/
76+
private static function get_name_formatter( array $args ): Closure {
77+
if ( \is_callable( $args['formatter'] ?? null ) ) {
78+
return $args['formatter']( ... );
79+
}
80+
81+
$formatter ??= $args['link_items'] && $args['link_format']
82+
? self::get_link_formatter( $args['link_format'] )
83+
: null;
84+
85+
if ( ! $formatter ) {
86+
return static fn( WP_Term $term ) => \esc_html( $term->name );
87+
}
88+
89+
return static fn( WP_Term $term ) => \sprintf(
90+
'<a href="%s">%s</a>',
91+
\esc_url( $formatter( $term ) ),
92+
\esc_html( $term->name ),
93+
);
94+
}
95+
96+
/**
97+
* Get the link formatter for the term name.
98+
*
99+
* @param string|callable|array|bool $fmt The link format for the term name.
100+
* @return Closure|null
101+
*/
102+
private static function get_link_formatter( string|callable|array|bool $fmt ): ?Closure {
103+
return match ( true ) {
104+
\is_bool( $fmt ) && $fmt => \get_term_link( ... ),
105+
\is_callable( $fmt ) => $fmt( ... ),
106+
\is_array( $fmt ) => static fn( $t ) => \call_user_func( $fmt, $t ),
107+
\is_string( $fmt ) => static fn( $t ) => \add_query_arg( $t->taxonomy, $t->slug, $fmt ),
108+
default => null,
109+
};
110+
}
111+
112+
/**
113+
* Get a term object from a variety of inputs.
114+
*
115+
* @param WP_Term|\WP_Error|int|string|null|array $from The term object, term ID, term slug, term name, or term array.
116+
* @param string|null $tax The taxonomy name.
117+
*/
118+
public static function get_term_object( WP_Term|\WP_Error|int|string|null|array $from, ?string $tax = null ): ?WP_Term {
119+
$term = match ( true ) {
120+
$from instanceof WP_Term => $from,
121+
\is_numeric( $from ) => \get_term( \absint( $from ) ),
122+
\is_string( $from ) && $tax => \get_term_by( 'slug', $from, $tax ),
123+
\is_array( $from ) => self::get_term_object_from_array( $from, $tax ),
124+
\is_wp_error( $from ) => null,
125+
default => null,
126+
};
127+
128+
return $term instanceof WP_Term ? $term : null;
129+
}
130+
131+
/**
132+
* Get a term object from an array.
133+
*
134+
* @param array $arr The term array.
135+
* @param string|null $taxonomy The taxonomy name.
136+
* @return WP_Term|\WP_Error|null|bool The term object or error.
137+
*/
138+
private static function get_term_object_from_array( array $arr, ?string $taxonomy = null ): WP_Term|\WP_Error|null|bool {
139+
$tax = $taxonomy ?? $arr['taxonomy'] ?? $arr['tax'] ?? null;
140+
$id = $arr['term_id'] ?? $arr['id'] ?? $arr['ID'] ?? false;
141+
142+
return match ( true ) {
143+
false !== $id && 0 > $id => \get_term_by( 'id', $id, $tax ),
144+
isset( $arr['slug'], $tax ) => \get_term_by( 'slug', $arr['slug'], $tax ),
145+
isset( $arr['name'], $tax ) => \get_term_by( 'name', $arr['name'], $tax ),
146+
default => null,
147+
};
148+
}
149+
}

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"prefer-stable": true,
2929
"autoload": {
3030
"psr-4": {
31-
"XWP\\Helper\\Functions\\": ""
31+
"XWP\\Helper\\Functions\\": "."
3232
},
3333
"files": [
3434
"xwp-helper-fns.php"

xwp-helper-fns.php

+21
Original file line numberDiff line numberDiff line change
@@ -223,3 +223,24 @@ function xwp_fetch_req_var( $key, $def = null ) {
223223
return f\Request::fetch_req_var( $key, $def );
224224
}
225225
endif;
226+
227+
228+
if ( ! function_exists( 'xwp_format_term_name' ) ) :
229+
/**
230+
* Format a term name with term parents.
231+
*
232+
* @param WP_Term|int|string|null|array|\WP_Error $term WP_Term object, Term ID, Term slug, or Term name.
233+
* @param array<string, mixed> $args Formatting arguments. Default empty array.
234+
* - formatter (callable) Custom formatter for the displayed term name. Default null.
235+
* - count (bool) Whether to include the term count in the formatted name. Default false.
236+
* - link_format (string|callable|array|bool) URL Link format for the term link. Default false.
237+
* - link_items (bool) Whether to link the term items. Default false.
238+
* - link_final (bool) Whether to link the final term. Default true.
239+
* - separator (string) Separator between terms. Default ' > '.
240+
* - taxonomy (string) Taxonomy name. Default null. Mandatory if $term is a string. Optional otherwise.
241+
* @return string Formatted term name with ancestors.
242+
*/
243+
function xwp_format_term_name( WP_Term|int|string|null|array|\WP_Error $term, array $args = array() ): string {
244+
return f\Term::format_hierarhical_name( $term, $args );
245+
}
246+
endif;

0 commit comments

Comments
 (0)