1 | <?php |
---|
2 | /** |
---|
3 | * Taxonomy API |
---|
4 | * |
---|
5 | * @package WordPress |
---|
6 | * @subpackage Taxonomy |
---|
7 | * @since 2.3.0 |
---|
8 | */ |
---|
9 | |
---|
10 | // |
---|
11 | // Taxonomy Registration |
---|
12 | // |
---|
13 | |
---|
14 | /** |
---|
15 | * Creates the initial taxonomies. |
---|
16 | * |
---|
17 | * This function fires twice: in wp-settings.php before plugins are loaded (for |
---|
18 | * backwards compatibility reasons), and again on the 'init' action. We must avoid |
---|
19 | * registering rewrite rules before the 'init' action. |
---|
20 | */ |
---|
21 | function create_initial_taxonomies() { |
---|
22 | global $wp_rewrite; |
---|
23 | |
---|
24 | if ( ! did_action( 'init' ) ) { |
---|
25 | $rewrite = array( 'category' => false, 'post_tag' => false, 'post_format' => false ); |
---|
26 | } else { |
---|
27 | |
---|
28 | /** |
---|
29 | * Filter the post formats rewrite base. |
---|
30 | * |
---|
31 | * @since 3.1.0 |
---|
32 | * |
---|
33 | * @param string $context Context of the rewrite base. Default 'type'. |
---|
34 | */ |
---|
35 | $post_format_base = apply_filters( 'post_format_rewrite_base', 'type' ); |
---|
36 | $rewrite = array( |
---|
37 | 'category' => array( |
---|
38 | 'hierarchical' => true, |
---|
39 | 'slug' => get_option('category_base') ? get_option('category_base') : 'category', |
---|
40 | 'with_front' => ! get_option('category_base') || $wp_rewrite->using_index_permalinks(), |
---|
41 | 'ep_mask' => EP_CATEGORIES, |
---|
42 | ), |
---|
43 | 'post_tag' => array( |
---|
44 | 'slug' => get_option('tag_base') ? get_option('tag_base') : 'tag', |
---|
45 | 'with_front' => ! get_option('tag_base') || $wp_rewrite->using_index_permalinks(), |
---|
46 | 'ep_mask' => EP_TAGS, |
---|
47 | ), |
---|
48 | 'post_format' => $post_format_base ? array( 'slug' => $post_format_base ) : false, |
---|
49 | ); |
---|
50 | } |
---|
51 | |
---|
52 | register_taxonomy( 'category', 'post', array( |
---|
53 | 'hierarchical' => true, |
---|
54 | 'query_var' => 'category_name', |
---|
55 | 'rewrite' => $rewrite['category'], |
---|
56 | 'public' => true, |
---|
57 | 'show_ui' => true, |
---|
58 | 'show_admin_column' => true, |
---|
59 | '_builtin' => true, |
---|
60 | ) ); |
---|
61 | |
---|
62 | register_taxonomy( 'post_tag', 'post', array( |
---|
63 | 'hierarchical' => false, |
---|
64 | 'query_var' => 'tag', |
---|
65 | 'rewrite' => $rewrite['post_tag'], |
---|
66 | 'public' => true, |
---|
67 | 'show_ui' => true, |
---|
68 | 'show_admin_column' => true, |
---|
69 | '_builtin' => true, |
---|
70 | ) ); |
---|
71 | |
---|
72 | register_taxonomy( 'nav_menu', 'nav_menu_item', array( |
---|
73 | 'public' => false, |
---|
74 | 'hierarchical' => false, |
---|
75 | 'labels' => array( |
---|
76 | 'name' => __( 'Navigation Menus' ), |
---|
77 | 'singular_name' => __( 'Navigation Menu' ), |
---|
78 | ), |
---|
79 | 'query_var' => false, |
---|
80 | 'rewrite' => false, |
---|
81 | 'show_ui' => false, |
---|
82 | '_builtin' => true, |
---|
83 | 'show_in_nav_menus' => false, |
---|
84 | ) ); |
---|
85 | |
---|
86 | register_taxonomy( 'link_category', 'link', array( |
---|
87 | 'hierarchical' => false, |
---|
88 | 'labels' => array( |
---|
89 | 'name' => __( 'Link Categories' ), |
---|
90 | 'singular_name' => __( 'Link Category' ), |
---|
91 | 'search_items' => __( 'Search Link Categories' ), |
---|
92 | 'popular_items' => null, |
---|
93 | 'all_items' => __( 'All Link Categories' ), |
---|
94 | 'edit_item' => __( 'Edit Link Category' ), |
---|
95 | 'update_item' => __( 'Update Link Category' ), |
---|
96 | 'add_new_item' => __( 'Add New Link Category' ), |
---|
97 | 'new_item_name' => __( 'New Link Category Name' ), |
---|
98 | 'separate_items_with_commas' => null, |
---|
99 | 'add_or_remove_items' => null, |
---|
100 | 'choose_from_most_used' => null, |
---|
101 | ), |
---|
102 | 'capabilities' => array( |
---|
103 | 'manage_terms' => 'manage_links', |
---|
104 | 'edit_terms' => 'manage_links', |
---|
105 | 'delete_terms' => 'manage_links', |
---|
106 | 'assign_terms' => 'manage_links', |
---|
107 | ), |
---|
108 | 'query_var' => false, |
---|
109 | 'rewrite' => false, |
---|
110 | 'public' => false, |
---|
111 | 'show_ui' => false, |
---|
112 | '_builtin' => true, |
---|
113 | ) ); |
---|
114 | |
---|
115 | register_taxonomy( 'post_format', 'post', array( |
---|
116 | 'public' => true, |
---|
117 | 'hierarchical' => false, |
---|
118 | 'labels' => array( |
---|
119 | 'name' => _x( 'Format', 'post format' ), |
---|
120 | 'singular_name' => _x( 'Format', 'post format' ), |
---|
121 | ), |
---|
122 | 'query_var' => true, |
---|
123 | 'rewrite' => $rewrite['post_format'], |
---|
124 | 'show_ui' => false, |
---|
125 | '_builtin' => true, |
---|
126 | 'show_in_nav_menus' => current_theme_supports( 'post-formats' ), |
---|
127 | ) ); |
---|
128 | } |
---|
129 | add_action( 'init', 'create_initial_taxonomies', 0 ); // highest priority |
---|
130 | |
---|
131 | /** |
---|
132 | * Get a list of registered taxonomy objects. |
---|
133 | * |
---|
134 | * @since 3.0.0 |
---|
135 | * @uses $wp_taxonomies |
---|
136 | * @see register_taxonomy |
---|
137 | * |
---|
138 | * @param array $args An array of key => value arguments to match against the taxonomy objects. |
---|
139 | * @param string $output The type of output to return, either taxonomy 'names' or 'objects'. 'names' is the default. |
---|
140 | * @param string $operator The logical operation to perform. 'or' means only one element |
---|
141 | * from the array needs to match; 'and' means all elements must match. The default is 'and'. |
---|
142 | * @return array A list of taxonomy names or objects |
---|
143 | */ |
---|
144 | function get_taxonomies( $args = array(), $output = 'names', $operator = 'and' ) { |
---|
145 | global $wp_taxonomies; |
---|
146 | |
---|
147 | $field = ('names' == $output) ? 'name' : false; |
---|
148 | |
---|
149 | return wp_filter_object_list($wp_taxonomies, $args, $operator, $field); |
---|
150 | } |
---|
151 | |
---|
152 | /** |
---|
153 | * Return all of the taxonomy names that are of $object_type. |
---|
154 | * |
---|
155 | * It appears that this function can be used to find all of the names inside of |
---|
156 | * $wp_taxonomies global variable. |
---|
157 | * |
---|
158 | * <code><?php $taxonomies = get_object_taxonomies('post'); ?></code> Should |
---|
159 | * result in <code>Array('category', 'post_tag')</code> |
---|
160 | * |
---|
161 | * @since 2.3.0 |
---|
162 | * |
---|
163 | * @uses $wp_taxonomies |
---|
164 | * |
---|
165 | * @param array|string|object $object Name of the type of taxonomy object, or an object (row from posts) |
---|
166 | * @param string $output The type of output to return, either taxonomy 'names' or 'objects'. 'names' is the default. |
---|
167 | * @return array The names of all taxonomy of $object_type. |
---|
168 | */ |
---|
169 | function get_object_taxonomies($object, $output = 'names') { |
---|
170 | global $wp_taxonomies; |
---|
171 | |
---|
172 | if ( is_object($object) ) { |
---|
173 | if ( $object->post_type == 'attachment' ) |
---|
174 | return get_attachment_taxonomies($object); |
---|
175 | $object = $object->post_type; |
---|
176 | } |
---|
177 | |
---|
178 | $object = (array) $object; |
---|
179 | |
---|
180 | $taxonomies = array(); |
---|
181 | foreach ( (array) $wp_taxonomies as $tax_name => $tax_obj ) { |
---|
182 | if ( array_intersect($object, (array) $tax_obj->object_type) ) { |
---|
183 | if ( 'names' == $output ) |
---|
184 | $taxonomies[] = $tax_name; |
---|
185 | else |
---|
186 | $taxonomies[ $tax_name ] = $tax_obj; |
---|
187 | } |
---|
188 | } |
---|
189 | |
---|
190 | return $taxonomies; |
---|
191 | } |
---|
192 | |
---|
193 | /** |
---|
194 | * Retrieves the taxonomy object of $taxonomy. |
---|
195 | * |
---|
196 | * The get_taxonomy function will first check that the parameter string given |
---|
197 | * is a taxonomy object and if it is, it will return it. |
---|
198 | * |
---|
199 | * @since 2.3.0 |
---|
200 | * |
---|
201 | * @uses $wp_taxonomies |
---|
202 | * @uses taxonomy_exists() Checks whether taxonomy exists |
---|
203 | * |
---|
204 | * @param string $taxonomy Name of taxonomy object to return |
---|
205 | * @return object|bool The Taxonomy Object or false if $taxonomy doesn't exist |
---|
206 | */ |
---|
207 | function get_taxonomy( $taxonomy ) { |
---|
208 | global $wp_taxonomies; |
---|
209 | |
---|
210 | if ( ! taxonomy_exists( $taxonomy ) ) |
---|
211 | return false; |
---|
212 | |
---|
213 | return $wp_taxonomies[$taxonomy]; |
---|
214 | } |
---|
215 | |
---|
216 | /** |
---|
217 | * Checks that the taxonomy name exists. |
---|
218 | * |
---|
219 | * Formerly is_taxonomy(), introduced in 2.3.0. |
---|
220 | * |
---|
221 | * @since 3.0.0 |
---|
222 | * |
---|
223 | * @uses $wp_taxonomies |
---|
224 | * |
---|
225 | * @param string $taxonomy Name of taxonomy object |
---|
226 | * @return bool Whether the taxonomy exists. |
---|
227 | */ |
---|
228 | function taxonomy_exists( $taxonomy ) { |
---|
229 | global $wp_taxonomies; |
---|
230 | |
---|
231 | return isset( $wp_taxonomies[$taxonomy] ); |
---|
232 | } |
---|
233 | |
---|
234 | /** |
---|
235 | * Whether the taxonomy object is hierarchical. |
---|
236 | * |
---|
237 | * Checks to make sure that the taxonomy is an object first. Then Gets the |
---|
238 | * object, and finally returns the hierarchical value in the object. |
---|
239 | * |
---|
240 | * A false return value might also mean that the taxonomy does not exist. |
---|
241 | * |
---|
242 | * @since 2.3.0 |
---|
243 | * |
---|
244 | * @uses taxonomy_exists() Checks whether taxonomy exists |
---|
245 | * @uses get_taxonomy() Used to get the taxonomy object |
---|
246 | * |
---|
247 | * @param string $taxonomy Name of taxonomy object |
---|
248 | * @return bool Whether the taxonomy is hierarchical |
---|
249 | */ |
---|
250 | function is_taxonomy_hierarchical($taxonomy) { |
---|
251 | if ( ! taxonomy_exists($taxonomy) ) |
---|
252 | return false; |
---|
253 | |
---|
254 | $taxonomy = get_taxonomy($taxonomy); |
---|
255 | return $taxonomy->hierarchical; |
---|
256 | } |
---|
257 | |
---|
258 | /** |
---|
259 | * Create or modify a taxonomy object. Do not use before init. |
---|
260 | * |
---|
261 | * A simple function for creating or modifying a taxonomy object based on the |
---|
262 | * parameters given. The function will accept an array (third optional |
---|
263 | * parameter), along with strings for the taxonomy name and another string for |
---|
264 | * the object type. |
---|
265 | * |
---|
266 | * Nothing is returned, so expect error maybe or use taxonomy_exists() to check |
---|
267 | * whether taxonomy exists. |
---|
268 | * |
---|
269 | * Optional $args contents: |
---|
270 | * |
---|
271 | * - label - Name of the taxonomy shown in the menu. Usually plural. If not set, labels['name'] will be used. |
---|
272 | * - labels - An array of labels for this taxonomy. |
---|
273 | * * By default tag labels are used for non-hierarchical types and category labels for hierarchical ones. |
---|
274 | * * You can see accepted values in {@link get_taxonomy_labels()}. |
---|
275 | * - description - A short descriptive summary of what the taxonomy is for. Defaults to blank. |
---|
276 | * - public - If the taxonomy should be publicly queryable; //@TODO not implemented. |
---|
277 | * * Defaults to true. |
---|
278 | * - hierarchical - Whether the taxonomy is hierarchical (e.g. category). Defaults to false. |
---|
279 | * - show_ui - Whether to generate a default UI for managing this taxonomy in the admin. |
---|
280 | * * If not set, the default is inherited from public. |
---|
281 | * - show_in_menu - Whether to show the taxonomy in the admin menu. |
---|
282 | * * If true, the taxonomy is shown as a submenu of the object type menu. |
---|
283 | * * If false, no menu is shown. |
---|
284 | * * show_ui must be true. |
---|
285 | * * If not set, the default is inherited from show_ui. |
---|
286 | * - show_in_nav_menus - Makes this taxonomy available for selection in navigation menus. |
---|
287 | * * If not set, the default is inherited from public. |
---|
288 | * - show_tagcloud - Whether to list the taxonomy in the Tag Cloud Widget. |
---|
289 | * * If not set, the default is inherited from show_ui. |
---|
290 | * - show_admin_column - Whether to display a column for the taxonomy on its post type listing screens. |
---|
291 | * * Defaults to false. |
---|
292 | * - meta_box_cb - Provide a callback function for the meta box display. |
---|
293 | * * If not set, defaults to post_categories_meta_box for hierarchical taxonomies |
---|
294 | * and post_tags_meta_box for non-hierarchical. |
---|
295 | * * If false, no meta box is shown. |
---|
296 | * - capabilities - Array of capabilities for this taxonomy. |
---|
297 | * * You can see accepted values in this function. |
---|
298 | * - rewrite - Triggers the handling of rewrites for this taxonomy. Defaults to true, using $taxonomy as slug. |
---|
299 | * * To prevent rewrite, set to false. |
---|
300 | * * To specify rewrite rules, an array can be passed with any of these keys |
---|
301 | * * 'slug' => string Customize the permastruct slug. Defaults to $taxonomy key |
---|
302 | * * 'with_front' => bool Should the permastruct be prepended with WP_Rewrite::$front. Defaults to true. |
---|
303 | * * 'hierarchical' => bool Either hierarchical rewrite tag or not. Defaults to false. |
---|
304 | * * 'ep_mask' => const Assign an endpoint mask. |
---|
305 | * * If not specified, defaults to EP_NONE. |
---|
306 | * - query_var - Sets the query_var key for this taxonomy. Defaults to $taxonomy key |
---|
307 | * * If false, a taxonomy cannot be loaded at ?{query_var}={term_slug} |
---|
308 | * * If specified as a string, the query ?{query_var_string}={term_slug} will be valid. |
---|
309 | * - update_count_callback - Works much like a hook, in that it will be called when the count is updated. |
---|
310 | * * Defaults to _update_post_term_count() for taxonomies attached to post types, which then confirms |
---|
311 | * that the objects are published before counting them. |
---|
312 | * * Defaults to _update_generic_term_count() for taxonomies attached to other object types, such as links. |
---|
313 | * - _builtin - true if this taxonomy is a native or "built-in" taxonomy. THIS IS FOR INTERNAL USE ONLY! |
---|
314 | * |
---|
315 | * @since 2.3.0 |
---|
316 | * @uses $wp_taxonomies Inserts new taxonomy object into the list |
---|
317 | * @uses $wp Adds query vars |
---|
318 | * |
---|
319 | * @param string $taxonomy Taxonomy key, must not exceed 32 characters. |
---|
320 | * @param array|string $object_type Name of the object type for the taxonomy object. |
---|
321 | * @param array|string $args See optional args description above. |
---|
322 | * @return null|WP_Error WP_Error if errors, otherwise null. |
---|
323 | */ |
---|
324 | function register_taxonomy( $taxonomy, $object_type, $args = array() ) { |
---|
325 | global $wp_taxonomies, $wp; |
---|
326 | |
---|
327 | if ( ! is_array( $wp_taxonomies ) ) |
---|
328 | $wp_taxonomies = array(); |
---|
329 | |
---|
330 | $defaults = array( |
---|
331 | 'labels' => array(), |
---|
332 | 'description' => '', |
---|
333 | 'public' => true, |
---|
334 | 'hierarchical' => false, |
---|
335 | 'show_ui' => null, |
---|
336 | 'show_in_menu' => null, |
---|
337 | 'show_in_nav_menus' => null, |
---|
338 | 'show_tagcloud' => null, |
---|
339 | 'show_admin_column' => false, |
---|
340 | 'meta_box_cb' => null, |
---|
341 | 'capabilities' => array(), |
---|
342 | 'rewrite' => true, |
---|
343 | 'query_var' => $taxonomy, |
---|
344 | 'update_count_callback' => '', |
---|
345 | '_builtin' => false, |
---|
346 | ); |
---|
347 | $args = wp_parse_args( $args, $defaults ); |
---|
348 | |
---|
349 | if ( strlen( $taxonomy ) > 32 ) { |
---|
350 | _doing_it_wrong( __FUNCTION__, __( 'Taxonomies cannot exceed 32 characters in length' ), '4.0' ); |
---|
351 | return new WP_Error( 'taxonomy_too_long', __( 'Taxonomies cannot exceed 32 characters in length' ) ); |
---|
352 | } |
---|
353 | |
---|
354 | if ( false !== $args['query_var'] && ! empty( $wp ) ) { |
---|
355 | if ( true === $args['query_var'] ) |
---|
356 | $args['query_var'] = $taxonomy; |
---|
357 | else |
---|
358 | $args['query_var'] = sanitize_title_with_dashes( $args['query_var'] ); |
---|
359 | $wp->add_query_var( $args['query_var'] ); |
---|
360 | } |
---|
361 | |
---|
362 | if ( false !== $args['rewrite'] && ( is_admin() || '' != get_option( 'permalink_structure' ) ) ) { |
---|
363 | $args['rewrite'] = wp_parse_args( $args['rewrite'], array( |
---|
364 | 'with_front' => true, |
---|
365 | 'hierarchical' => false, |
---|
366 | 'ep_mask' => EP_NONE, |
---|
367 | ) ); |
---|
368 | |
---|
369 | if ( empty( $args['rewrite']['slug'] ) ) |
---|
370 | $args['rewrite']['slug'] = sanitize_title_with_dashes( $taxonomy ); |
---|
371 | |
---|
372 | if ( $args['hierarchical'] && $args['rewrite']['hierarchical'] ) |
---|
373 | $tag = '(.+?)'; |
---|
374 | else |
---|
375 | $tag = '([^/]+)'; |
---|
376 | |
---|
377 | add_rewrite_tag( "%$taxonomy%", $tag, $args['query_var'] ? "{$args['query_var']}=" : "taxonomy=$taxonomy&term=" ); |
---|
378 | add_permastruct( $taxonomy, "{$args['rewrite']['slug']}/%$taxonomy%", $args['rewrite'] ); |
---|
379 | } |
---|
380 | |
---|
381 | // If not set, default to the setting for public. |
---|
382 | if ( null === $args['show_ui'] ) |
---|
383 | $args['show_ui'] = $args['public']; |
---|
384 | |
---|
385 | // If not set, default to the setting for show_ui. |
---|
386 | if ( null === $args['show_in_menu' ] || ! $args['show_ui'] ) |
---|
387 | $args['show_in_menu' ] = $args['show_ui']; |
---|
388 | |
---|
389 | // If not set, default to the setting for public. |
---|
390 | if ( null === $args['show_in_nav_menus'] ) |
---|
391 | $args['show_in_nav_menus'] = $args['public']; |
---|
392 | |
---|
393 | // If not set, default to the setting for show_ui. |
---|
394 | if ( null === $args['show_tagcloud'] ) |
---|
395 | $args['show_tagcloud'] = $args['show_ui']; |
---|
396 | |
---|
397 | $default_caps = array( |
---|
398 | 'manage_terms' => 'manage_categories', |
---|
399 | 'edit_terms' => 'manage_categories', |
---|
400 | 'delete_terms' => 'manage_categories', |
---|
401 | 'assign_terms' => 'edit_posts', |
---|
402 | ); |
---|
403 | $args['cap'] = (object) array_merge( $default_caps, $args['capabilities'] ); |
---|
404 | unset( $args['capabilities'] ); |
---|
405 | |
---|
406 | $args['name'] = $taxonomy; |
---|
407 | $args['object_type'] = array_unique( (array) $object_type ); |
---|
408 | |
---|
409 | $args['labels'] = get_taxonomy_labels( (object) $args ); |
---|
410 | $args['label'] = $args['labels']->name; |
---|
411 | |
---|
412 | // If not set, use the default meta box |
---|
413 | if ( null === $args['meta_box_cb'] ) { |
---|
414 | if ( $args['hierarchical'] ) |
---|
415 | $args['meta_box_cb'] = 'post_categories_meta_box'; |
---|
416 | else |
---|
417 | $args['meta_box_cb'] = 'post_tags_meta_box'; |
---|
418 | } |
---|
419 | |
---|
420 | $wp_taxonomies[ $taxonomy ] = (object) $args; |
---|
421 | |
---|
422 | // register callback handling for metabox |
---|
423 | add_filter( 'wp_ajax_add-' . $taxonomy, '_wp_ajax_add_hierarchical_term' ); |
---|
424 | |
---|
425 | /** |
---|
426 | * Fires after a taxonomy is registered. |
---|
427 | * |
---|
428 | * @since 3.3.0 |
---|
429 | * |
---|
430 | * @param string $taxonomy Taxonomy slug. |
---|
431 | * @param array|string $object_type Object type or array of object types. |
---|
432 | * @param array $args Array of taxonomy registration arguments. |
---|
433 | */ |
---|
434 | do_action( 'registered_taxonomy', $taxonomy, $object_type, $args ); |
---|
435 | } |
---|
436 | |
---|
437 | /** |
---|
438 | * Builds an object with all taxonomy labels out of a taxonomy object |
---|
439 | * |
---|
440 | * Accepted keys of the label array in the taxonomy object: |
---|
441 | * - name - general name for the taxonomy, usually plural. The same as and overridden by $tax->label. Default is Tags/Categories |
---|
442 | * - singular_name - name for one object of this taxonomy. Default is Tag/Category |
---|
443 | * - search_items - Default is Search Tags/Search Categories |
---|
444 | * - popular_items - This string isn't used on hierarchical taxonomies. Default is Popular Tags |
---|
445 | * - all_items - Default is All Tags/All Categories |
---|
446 | * - parent_item - This string isn't used on non-hierarchical taxonomies. In hierarchical ones the default is Parent Category |
---|
447 | * - parent_item_colon - The same as <code>parent_item</code>, but with colon <code>:</code> in the end |
---|
448 | * - edit_item - Default is Edit Tag/Edit Category |
---|
449 | * - view_item - Default is View Tag/View Category |
---|
450 | * - update_item - Default is Update Tag/Update Category |
---|
451 | * - add_new_item - Default is Add New Tag/Add New Category |
---|
452 | * - new_item_name - Default is New Tag Name/New Category Name |
---|
453 | * - separate_items_with_commas - This string isn't used on hierarchical taxonomies. Default is "Separate tags with commas", used in the meta box. |
---|
454 | * - add_or_remove_items - This string isn't used on hierarchical taxonomies. Default is "Add or remove tags", used in the meta box when JavaScript is disabled. |
---|
455 | * - choose_from_most_used - This string isn't used on hierarchical taxonomies. Default is "Choose from the most used tags", used in the meta box. |
---|
456 | * - not_found - This string isn't used on hierarchical taxonomies. Default is "No tags found", used in the meta box. |
---|
457 | * |
---|
458 | * Above, the first default value is for non-hierarchical taxonomies (like tags) and the second one is for hierarchical taxonomies (like categories). |
---|
459 | * |
---|
460 | * @since 3.0.0 |
---|
461 | * @param object $tax Taxonomy object |
---|
462 | * @return object object with all the labels as member variables |
---|
463 | */ |
---|
464 | |
---|
465 | function get_taxonomy_labels( $tax ) { |
---|
466 | $tax->labels = (array) $tax->labels; |
---|
467 | |
---|
468 | if ( isset( $tax->helps ) && empty( $tax->labels['separate_items_with_commas'] ) ) |
---|
469 | $tax->labels['separate_items_with_commas'] = $tax->helps; |
---|
470 | |
---|
471 | if ( isset( $tax->no_tagcloud ) && empty( $tax->labels['not_found'] ) ) |
---|
472 | $tax->labels['not_found'] = $tax->no_tagcloud; |
---|
473 | |
---|
474 | $nohier_vs_hier_defaults = array( |
---|
475 | 'name' => array( _x( 'Tags', 'taxonomy general name' ), _x( 'Categories', 'taxonomy general name' ) ), |
---|
476 | 'singular_name' => array( _x( 'Tag', 'taxonomy singular name' ), _x( 'Category', 'taxonomy singular name' ) ), |
---|
477 | 'search_items' => array( __( 'Search Tags' ), __( 'Search Categories' ) ), |
---|
478 | 'popular_items' => array( __( 'Popular Tags' ), null ), |
---|
479 | 'all_items' => array( __( 'All Tags' ), __( 'All Categories' ) ), |
---|
480 | 'parent_item' => array( null, __( 'Parent Category' ) ), |
---|
481 | 'parent_item_colon' => array( null, __( 'Parent Category:' ) ), |
---|
482 | 'edit_item' => array( __( 'Edit Tag' ), __( 'Edit Category' ) ), |
---|
483 | 'view_item' => array( __( 'View Tag' ), __( 'View Category' ) ), |
---|
484 | 'update_item' => array( __( 'Update Tag' ), __( 'Update Category' ) ), |
---|
485 | 'add_new_item' => array( __( 'Add New Tag' ), __( 'Add New Category' ) ), |
---|
486 | 'new_item_name' => array( __( 'New Tag Name' ), __( 'New Category Name' ) ), |
---|
487 | 'separate_items_with_commas' => array( __( 'Separate tags with commas' ), null ), |
---|
488 | 'add_or_remove_items' => array( __( 'Add or remove tags' ), null ), |
---|
489 | 'choose_from_most_used' => array( __( 'Choose from the most used tags' ), null ), |
---|
490 | 'not_found' => array( __( 'No tags found.' ), null ), |
---|
491 | ); |
---|
492 | $nohier_vs_hier_defaults['menu_name'] = $nohier_vs_hier_defaults['name']; |
---|
493 | |
---|
494 | return _get_custom_object_labels( $tax, $nohier_vs_hier_defaults ); |
---|
495 | } |
---|
496 | |
---|
497 | /** |
---|
498 | * Add an already registered taxonomy to an object type. |
---|
499 | * |
---|
500 | * @since 3.0.0 |
---|
501 | * @uses $wp_taxonomies Modifies taxonomy object |
---|
502 | * |
---|
503 | * @param string $taxonomy Name of taxonomy object |
---|
504 | * @param string $object_type Name of the object type |
---|
505 | * @return bool True if successful, false if not |
---|
506 | */ |
---|
507 | function register_taxonomy_for_object_type( $taxonomy, $object_type) { |
---|
508 | global $wp_taxonomies; |
---|
509 | |
---|
510 | if ( !isset($wp_taxonomies[$taxonomy]) ) |
---|
511 | return false; |
---|
512 | |
---|
513 | if ( ! get_post_type_object($object_type) ) |
---|
514 | return false; |
---|
515 | |
---|
516 | if ( ! in_array( $object_type, $wp_taxonomies[$taxonomy]->object_type ) ) |
---|
517 | $wp_taxonomies[$taxonomy]->object_type[] = $object_type; |
---|
518 | |
---|
519 | return true; |
---|
520 | } |
---|
521 | |
---|
522 | /** |
---|
523 | * Remove an already registered taxonomy from an object type. |
---|
524 | * |
---|
525 | * @since 3.7.0 |
---|
526 | * |
---|
527 | * @param string $taxonomy Name of taxonomy object. |
---|
528 | * @param string $object_type Name of the object type. |
---|
529 | * @return bool True if successful, false if not. |
---|
530 | */ |
---|
531 | function unregister_taxonomy_for_object_type( $taxonomy, $object_type ) { |
---|
532 | global $wp_taxonomies; |
---|
533 | |
---|
534 | if ( ! isset( $wp_taxonomies[ $taxonomy ] ) ) |
---|
535 | return false; |
---|
536 | |
---|
537 | if ( ! get_post_type_object( $object_type ) ) |
---|
538 | return false; |
---|
539 | |
---|
540 | $key = array_search( $object_type, $wp_taxonomies[ $taxonomy ]->object_type, true ); |
---|
541 | if ( false === $key ) |
---|
542 | return false; |
---|
543 | |
---|
544 | unset( $wp_taxonomies[ $taxonomy ]->object_type[ $key ] ); |
---|
545 | return true; |
---|
546 | } |
---|
547 | |
---|
548 | // |
---|
549 | // Term API |
---|
550 | // |
---|
551 | |
---|
552 | /** |
---|
553 | * Retrieve object_ids of valid taxonomy and term. |
---|
554 | * |
---|
555 | * The strings of $taxonomies must exist before this function will continue. On |
---|
556 | * failure of finding a valid taxonomy, it will return an WP_Error class, kind |
---|
557 | * of like Exceptions in PHP 5, except you can't catch them. Even so, you can |
---|
558 | * still test for the WP_Error class and get the error message. |
---|
559 | * |
---|
560 | * The $terms aren't checked the same as $taxonomies, but still need to exist |
---|
561 | * for $object_ids to be returned. |
---|
562 | * |
---|
563 | * It is possible to change the order that object_ids is returned by either |
---|
564 | * using PHP sort family functions or using the database by using $args with |
---|
565 | * either ASC or DESC array. The value should be in the key named 'order'. |
---|
566 | * |
---|
567 | * @since 2.3.0 |
---|
568 | * |
---|
569 | * @uses $wpdb |
---|
570 | * @uses wp_parse_args() Creates an array from string $args. |
---|
571 | * |
---|
572 | * @param int|array $term_ids Term id or array of term ids of terms that will be used |
---|
573 | * @param string|array $taxonomies String of taxonomy name or Array of string values of taxonomy names |
---|
574 | * @param array|string $args Change the order of the object_ids, either ASC or DESC |
---|
575 | * @return WP_Error|array If the taxonomy does not exist, then WP_Error will be returned. On success |
---|
576 | * the array can be empty meaning that there are no $object_ids found or it will return the $object_ids found. |
---|
577 | */ |
---|
578 | function get_objects_in_term( $term_ids, $taxonomies, $args = array() ) { |
---|
579 | global $wpdb; |
---|
580 | |
---|
581 | if ( ! is_array( $term_ids ) ) { |
---|
582 | $term_ids = array( $term_ids ); |
---|
583 | } |
---|
584 | if ( ! is_array( $taxonomies ) ) { |
---|
585 | $taxonomies = array( $taxonomies ); |
---|
586 | } |
---|
587 | foreach ( (array) $taxonomies as $taxonomy ) { |
---|
588 | if ( ! taxonomy_exists( $taxonomy ) ) { |
---|
589 | return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy' ) ); |
---|
590 | } |
---|
591 | } |
---|
592 | |
---|
593 | $defaults = array( 'order' => 'ASC' ); |
---|
594 | $args = wp_parse_args( $args, $defaults ); |
---|
595 | |
---|
596 | $order = ( 'desc' == strtolower( $args['order'] ) ) ? 'DESC' : 'ASC'; |
---|
597 | |
---|
598 | $term_ids = array_map('intval', $term_ids ); |
---|
599 | |
---|
600 | $taxonomies = "'" . implode( "', '", $taxonomies ) . "'"; |
---|
601 | $term_ids = "'" . implode( "', '", $term_ids ) . "'"; |
---|
602 | |
---|
603 | $object_ids = $wpdb->get_col("SELECT tr.object_id FROM $wpdb->term_relationships AS tr INNER JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ($taxonomies) AND tt.term_id IN ($term_ids) ORDER BY tr.object_id $order"); |
---|
604 | |
---|
605 | if ( ! $object_ids ){ |
---|
606 | return array(); |
---|
607 | } |
---|
608 | return $object_ids; |
---|
609 | } |
---|
610 | |
---|
611 | /** |
---|
612 | * Given a taxonomy query, generates SQL to be appended to a main query. |
---|
613 | * |
---|
614 | * @since 3.1.0 |
---|
615 | * |
---|
616 | * @see WP_Tax_Query |
---|
617 | * |
---|
618 | * @param array $tax_query A compact tax query |
---|
619 | * @param string $primary_table |
---|
620 | * @param string $primary_id_column |
---|
621 | * @return array |
---|
622 | */ |
---|
623 | function get_tax_sql( $tax_query, $primary_table, $primary_id_column ) { |
---|
624 | $tax_query_obj = new WP_Tax_Query( $tax_query ); |
---|
625 | return $tax_query_obj->get_sql( $primary_table, $primary_id_column ); |
---|
626 | } |
---|
627 | |
---|
628 | /** |
---|
629 | * Container class for a multiple taxonomy query. |
---|
630 | * |
---|
631 | * @since 3.1.0 |
---|
632 | */ |
---|
633 | class WP_Tax_Query { |
---|
634 | |
---|
635 | /** |
---|
636 | * List of taxonomy queries. A single taxonomy query is an associative array: |
---|
637 | * - 'taxonomy' string The taxonomy being queried. Optional when using the term_taxonomy_id field. |
---|
638 | * - 'terms' string|array The list of terms |
---|
639 | * - 'field' string (optional) Which term field is being used. |
---|
640 | * Possible values: 'term_id', 'slug', 'name', or 'term_taxonomy_id' |
---|
641 | * Default: 'term_id' |
---|
642 | * - 'operator' string (optional) |
---|
643 | * Possible values: 'AND', 'IN' or 'NOT IN'. |
---|
644 | * Default: 'IN' |
---|
645 | * - 'include_children' bool (optional) Whether to include child terms. Requires that a taxonomy be specified. |
---|
646 | * Default: true |
---|
647 | * |
---|
648 | * @since 3.1.0 |
---|
649 | * @access public |
---|
650 | * @var array |
---|
651 | */ |
---|
652 | public $queries = array(); |
---|
653 | |
---|
654 | /** |
---|
655 | * The relation between the queries. Can be one of 'AND' or 'OR'. |
---|
656 | * |
---|
657 | * @since 3.1.0 |
---|
658 | * @access public |
---|
659 | * @var string |
---|
660 | */ |
---|
661 | public $relation; |
---|
662 | |
---|
663 | /** |
---|
664 | * Standard response when the query should not return any rows. |
---|
665 | * |
---|
666 | * @since 3.2.0 |
---|
667 | * @access private |
---|
668 | * @var string |
---|
669 | */ |
---|
670 | private static $no_results = array( 'join' => '', 'where' => ' AND 0 = 1' ); |
---|
671 | |
---|
672 | /** |
---|
673 | * Constructor. |
---|
674 | * |
---|
675 | * Parses a compact tax query and sets defaults. |
---|
676 | * |
---|
677 | * @since 3.1.0 |
---|
678 | * @access public |
---|
679 | * |
---|
680 | * @param array $tax_query A compact tax query: |
---|
681 | * array( |
---|
682 | * 'relation' => 'OR', |
---|
683 | * array( |
---|
684 | * 'taxonomy' => 'tax1', |
---|
685 | * 'terms' => array( 'term1', 'term2' ), |
---|
686 | * 'field' => 'slug', |
---|
687 | * ), |
---|
688 | * array( |
---|
689 | * 'taxonomy' => 'tax2', |
---|
690 | * 'terms' => array( 'term-a', 'term-b' ), |
---|
691 | * 'field' => 'slug', |
---|
692 | * ), |
---|
693 | * ) |
---|
694 | */ |
---|
695 | public function __construct( $tax_query ) { |
---|
696 | if ( isset( $tax_query['relation'] ) && strtoupper( $tax_query['relation'] ) == 'OR' ) { |
---|
697 | $this->relation = 'OR'; |
---|
698 | } else { |
---|
699 | $this->relation = 'AND'; |
---|
700 | } |
---|
701 | |
---|
702 | $defaults = array( |
---|
703 | 'taxonomy' => '', |
---|
704 | 'terms' => array(), |
---|
705 | 'include_children' => true, |
---|
706 | 'field' => 'term_id', |
---|
707 | 'operator' => 'IN', |
---|
708 | ); |
---|
709 | |
---|
710 | foreach ( $tax_query as $query ) { |
---|
711 | if ( ! is_array( $query ) ) |
---|
712 | continue; |
---|
713 | |
---|
714 | $query = array_merge( $defaults, $query ); |
---|
715 | |
---|
716 | $query['terms'] = (array) $query['terms']; |
---|
717 | |
---|
718 | $this->queries[] = $query; |
---|
719 | } |
---|
720 | } |
---|
721 | |
---|
722 | /** |
---|
723 | * Generates SQL clauses to be appended to a main query. |
---|
724 | * |
---|
725 | * @since 3.1.0 |
---|
726 | * @access public |
---|
727 | * |
---|
728 | * @param string $primary_table |
---|
729 | * @param string $primary_id_column |
---|
730 | * @return array |
---|
731 | */ |
---|
732 | public function get_sql( $primary_table, $primary_id_column ) { |
---|
733 | global $wpdb; |
---|
734 | |
---|
735 | $join = ''; |
---|
736 | $where = array(); |
---|
737 | $i = 0; |
---|
738 | $count = count( $this->queries ); |
---|
739 | |
---|
740 | foreach ( $this->queries as $index => $query ) { |
---|
741 | $this->clean_query( $query ); |
---|
742 | |
---|
743 | if ( is_wp_error( $query ) ) { |
---|
744 | return self::$no_results; |
---|
745 | } |
---|
746 | |
---|
747 | $terms = $query['terms']; |
---|
748 | $operator = strtoupper( $query['operator'] ); |
---|
749 | |
---|
750 | if ( 'IN' == $operator ) { |
---|
751 | |
---|
752 | if ( empty( $terms ) ) { |
---|
753 | if ( 'OR' == $this->relation ) { |
---|
754 | if ( ( $index + 1 === $count ) && empty( $where ) ) { |
---|
755 | return self::$no_results; |
---|
756 | } |
---|
757 | continue; |
---|
758 | } else { |
---|
759 | return self::$no_results; |
---|
760 | } |
---|
761 | } |
---|
762 | |
---|
763 | $terms = implode( ',', $terms ); |
---|
764 | |
---|
765 | $alias = $i ? 'tt' . $i : $wpdb->term_relationships; |
---|
766 | |
---|
767 | $join .= " INNER JOIN $wpdb->term_relationships"; |
---|
768 | $join .= $i ? " AS $alias" : ''; |
---|
769 | $join .= " ON ($primary_table.$primary_id_column = $alias.object_id)"; |
---|
770 | |
---|
771 | $where[] = "$alias.term_taxonomy_id $operator ($terms)"; |
---|
772 | } elseif ( 'NOT IN' == $operator ) { |
---|
773 | |
---|
774 | if ( empty( $terms ) ) { |
---|
775 | continue; |
---|
776 | } |
---|
777 | |
---|
778 | $terms = implode( ',', $terms ); |
---|
779 | |
---|
780 | $where[] = "$primary_table.$primary_id_column NOT IN ( |
---|
781 | SELECT object_id |
---|
782 | FROM $wpdb->term_relationships |
---|
783 | WHERE term_taxonomy_id IN ($terms) |
---|
784 | )"; |
---|
785 | } elseif ( 'AND' == $operator ) { |
---|
786 | |
---|
787 | if ( empty( $terms ) ) { |
---|
788 | continue; |
---|
789 | } |
---|
790 | |
---|
791 | $num_terms = count( $terms ); |
---|
792 | |
---|
793 | $terms = implode( ',', $terms ); |
---|
794 | |
---|
795 | $where[] = "( |
---|
796 | SELECT COUNT(1) |
---|
797 | FROM $wpdb->term_relationships |
---|
798 | WHERE term_taxonomy_id IN ($terms) |
---|
799 | AND object_id = $primary_table.$primary_id_column |
---|
800 | ) = $num_terms"; |
---|
801 | } |
---|
802 | |
---|
803 | $i++; |
---|
804 | } |
---|
805 | |
---|
806 | if ( ! empty( $where ) ) { |
---|
807 | $where = ' AND ( ' . implode( " $this->relation ", $where ) . ' )'; |
---|
808 | } else { |
---|
809 | $where = ''; |
---|
810 | } |
---|
811 | return compact( 'join', 'where' ); |
---|
812 | } |
---|
813 | |
---|
814 | /** |
---|
815 | * Validates a single query. |
---|
816 | * |
---|
817 | * @since 3.2.0 |
---|
818 | * @access private |
---|
819 | * |
---|
820 | * @param array &$query The single query |
---|
821 | */ |
---|
822 | private function clean_query( &$query ) { |
---|
823 | if ( empty( $query['taxonomy'] ) ) { |
---|
824 | if ( 'term_taxonomy_id' !== $query['field'] ) { |
---|
825 | $query = new WP_Error( 'Invalid taxonomy' ); |
---|
826 | return; |
---|
827 | } |
---|
828 | |
---|
829 | // so long as there are shared terms, include_children requires that a taxonomy is set |
---|
830 | $query['include_children'] = false; |
---|
831 | } elseif ( ! taxonomy_exists( $query['taxonomy'] ) ) { |
---|
832 | $query = new WP_Error( 'Invalid taxonomy' ); |
---|
833 | return; |
---|
834 | } |
---|
835 | |
---|
836 | $query['terms'] = array_unique( (array) $query['terms'] ); |
---|
837 | |
---|
838 | if ( is_taxonomy_hierarchical( $query['taxonomy'] ) && $query['include_children'] ) { |
---|
839 | $this->transform_query( $query, 'term_id' ); |
---|
840 | |
---|
841 | if ( is_wp_error( $query ) ) |
---|
842 | return; |
---|
843 | |
---|
844 | $children = array(); |
---|
845 | foreach ( $query['terms'] as $term ) { |
---|
846 | $children = array_merge( $children, get_term_children( $term, $query['taxonomy'] ) ); |
---|
847 | $children[] = $term; |
---|
848 | } |
---|
849 | $query['terms'] = $children; |
---|
850 | } |
---|
851 | |
---|
852 | $this->transform_query( $query, 'term_taxonomy_id' ); |
---|
853 | } |
---|
854 | |
---|
855 | /** |
---|
856 | * Transforms a single query, from one field to another. |
---|
857 | * |
---|
858 | * @since 3.2.0 |
---|
859 | * |
---|
860 | * @param array &$query The single query |
---|
861 | * @param string $resulting_field The resulting field |
---|
862 | */ |
---|
863 | public function transform_query( &$query, $resulting_field ) { |
---|
864 | global $wpdb; |
---|
865 | |
---|
866 | if ( empty( $query['terms'] ) ) |
---|
867 | return; |
---|
868 | |
---|
869 | if ( $query['field'] == $resulting_field ) |
---|
870 | return; |
---|
871 | |
---|
872 | $resulting_field = sanitize_key( $resulting_field ); |
---|
873 | |
---|
874 | switch ( $query['field'] ) { |
---|
875 | case 'slug': |
---|
876 | case 'name': |
---|
877 | $terms = "'" . implode( "','", array_map( 'sanitize_title_for_query', $query['terms'] ) ) . "'"; |
---|
878 | $terms = $wpdb->get_col( " |
---|
879 | SELECT $wpdb->term_taxonomy.$resulting_field |
---|
880 | FROM $wpdb->term_taxonomy |
---|
881 | INNER JOIN $wpdb->terms USING (term_id) |
---|
882 | WHERE taxonomy = '{$query['taxonomy']}' |
---|
883 | AND $wpdb->terms.{$query['field']} IN ($terms) |
---|
884 | " ); |
---|
885 | break; |
---|
886 | case 'term_taxonomy_id': |
---|
887 | $terms = implode( ',', array_map( 'intval', $query['terms'] ) ); |
---|
888 | $terms = $wpdb->get_col( " |
---|
889 | SELECT $resulting_field |
---|
890 | FROM $wpdb->term_taxonomy |
---|
891 | WHERE term_taxonomy_id IN ($terms) |
---|
892 | " ); |
---|
893 | break; |
---|
894 | default: |
---|
895 | $terms = implode( ',', array_map( 'intval', $query['terms'] ) ); |
---|
896 | $terms = $wpdb->get_col( " |
---|
897 | SELECT $resulting_field |
---|
898 | FROM $wpdb->term_taxonomy |
---|
899 | WHERE taxonomy = '{$query['taxonomy']}' |
---|
900 | AND term_id IN ($terms) |
---|
901 | " ); |
---|
902 | } |
---|
903 | |
---|
904 | if ( 'AND' == $query['operator'] && count( $terms ) < count( $query['terms'] ) ) { |
---|
905 | $query = new WP_Error( 'Inexistent terms' ); |
---|
906 | return; |
---|
907 | } |
---|
908 | |
---|
909 | $query['terms'] = $terms; |
---|
910 | $query['field'] = $resulting_field; |
---|
911 | } |
---|
912 | } |
---|
913 | |
---|
914 | /** |
---|
915 | * Get all Term data from database by Term ID. |
---|
916 | * |
---|
917 | * The usage of the get_term function is to apply filters to a term object. It |
---|
918 | * is possible to get a term object from the database before applying the |
---|
919 | * filters. |
---|
920 | * |
---|
921 | * $term ID must be part of $taxonomy, to get from the database. Failure, might |
---|
922 | * be able to be captured by the hooks. Failure would be the same value as $wpdb |
---|
923 | * returns for the get_row method. |
---|
924 | * |
---|
925 | * There are two hooks, one is specifically for each term, named 'get_term', and |
---|
926 | * the second is for the taxonomy name, 'term_$taxonomy'. Both hooks gets the |
---|
927 | * term object, and the taxonomy name as parameters. Both hooks are expected to |
---|
928 | * return a Term object. |
---|
929 | * |
---|
930 | * 'get_term' hook - Takes two parameters the term Object and the taxonomy name. |
---|
931 | * Must return term object. Used in get_term() as a catch-all filter for every |
---|
932 | * $term. |
---|
933 | * |
---|
934 | * 'get_$taxonomy' hook - Takes two parameters the term Object and the taxonomy |
---|
935 | * name. Must return term object. $taxonomy will be the taxonomy name, so for |
---|
936 | * example, if 'category', it would be 'get_category' as the filter name. Useful |
---|
937 | * for custom taxonomies or plugging into default taxonomies. |
---|
938 | * |
---|
939 | * @since 2.3.0 |
---|
940 | * |
---|
941 | * @uses $wpdb |
---|
942 | * @uses sanitize_term() Cleanses the term based on $filter context before returning. |
---|
943 | * @see sanitize_term_field() The $context param lists the available values for get_term_by() $filter param. |
---|
944 | * |
---|
945 | * @param int|object $term If integer, will get from database. If object will apply filters and return $term. |
---|
946 | * @param string $taxonomy Taxonomy name that $term is part of. |
---|
947 | * @param string $output Constant OBJECT, ARRAY_A, or ARRAY_N |
---|
948 | * @param string $filter Optional, default is raw or no WordPress defined filter will applied. |
---|
949 | * @return mixed|null|WP_Error Term Row from database. Will return null if $term is empty. If taxonomy does not |
---|
950 | * exist then WP_Error will be returned. |
---|
951 | */ |
---|
952 | function get_term($term, $taxonomy, $output = OBJECT, $filter = 'raw') { |
---|
953 | global $wpdb; |
---|
954 | |
---|
955 | if ( empty($term) ) { |
---|
956 | $error = new WP_Error('invalid_term', __('Empty Term')); |
---|
957 | return $error; |
---|
958 | } |
---|
959 | |
---|
960 | if ( ! taxonomy_exists($taxonomy) ) { |
---|
961 | $error = new WP_Error('invalid_taxonomy', __('Invalid taxonomy')); |
---|
962 | return $error; |
---|
963 | } |
---|
964 | |
---|
965 | if ( is_object($term) && empty($term->filter) ) { |
---|
966 | wp_cache_add($term->term_id, $term, $taxonomy); |
---|
967 | $_term = $term; |
---|
968 | } else { |
---|
969 | if ( is_object($term) ) |
---|
970 | $term = $term->term_id; |
---|
971 | if ( !$term = (int) $term ) |
---|
972 | return null; |
---|
973 | if ( ! $_term = wp_cache_get($term, $taxonomy) ) { |
---|
974 | $_term = $wpdb->get_row( $wpdb->prepare( "SELECT t.*, tt.* FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy = %s AND t.term_id = %d LIMIT 1", $taxonomy, $term) ); |
---|
975 | if ( ! $_term ) |
---|
976 | return null; |
---|
977 | wp_cache_add($term, $_term, $taxonomy); |
---|
978 | } |
---|
979 | } |
---|
980 | |
---|
981 | /** |
---|
982 | * Filter a term. |
---|
983 | * |
---|
984 | * @since 2.3.0 |
---|
985 | * |
---|
986 | * @param int|object $_term Term object or ID. |
---|
987 | * @param string $taxonomy The taxonomy slug. |
---|
988 | */ |
---|
989 | $_term = apply_filters( 'get_term', $_term, $taxonomy ); |
---|
990 | |
---|
991 | /** |
---|
992 | * Filter a taxonomy. |
---|
993 | * |
---|
994 | * The dynamic portion of the filter name, $taxonomy, refers |
---|
995 | * to the taxonomy slug. |
---|
996 | * |
---|
997 | * @since 2.3.0 |
---|
998 | * |
---|
999 | * @param int|object $_term Term object or ID. |
---|
1000 | * @param string $taxonomy The taxonomy slug. |
---|
1001 | */ |
---|
1002 | $_term = apply_filters( "get_$taxonomy", $_term, $taxonomy ); |
---|
1003 | $_term = sanitize_term($_term, $taxonomy, $filter); |
---|
1004 | |
---|
1005 | if ( $output == OBJECT ) { |
---|
1006 | return $_term; |
---|
1007 | } elseif ( $output == ARRAY_A ) { |
---|
1008 | $__term = get_object_vars($_term); |
---|
1009 | return $__term; |
---|
1010 | } elseif ( $output == ARRAY_N ) { |
---|
1011 | $__term = array_values(get_object_vars($_term)); |
---|
1012 | return $__term; |
---|
1013 | } else { |
---|
1014 | return $_term; |
---|
1015 | } |
---|
1016 | } |
---|
1017 | |
---|
1018 | /** |
---|
1019 | * Get all Term data from database by Term field and data. |
---|
1020 | * |
---|
1021 | * Warning: $value is not escaped for 'name' $field. You must do it yourself, if |
---|
1022 | * required. |
---|
1023 | * |
---|
1024 | * The default $field is 'id', therefore it is possible to also use null for |
---|
1025 | * field, but not recommended that you do so. |
---|
1026 | * |
---|
1027 | * If $value does not exist, the return value will be false. If $taxonomy exists |
---|
1028 | * and $field and $value combinations exist, the Term will be returned. |
---|
1029 | * |
---|
1030 | * @since 2.3.0 |
---|
1031 | * |
---|
1032 | * @uses $wpdb |
---|
1033 | * @uses sanitize_term() Cleanses the term based on $filter context before returning. |
---|
1034 | * @see sanitize_term_field() The $context param lists the available values for get_term_by() $filter param. |
---|
1035 | * |
---|
1036 | * @param string $field Either 'slug', 'name', 'id' (term_id), or 'term_taxonomy_id' |
---|
1037 | * @param string|int $value Search for this term value |
---|
1038 | * @param string $taxonomy Taxonomy Name |
---|
1039 | * @param string $output Constant OBJECT, ARRAY_A, or ARRAY_N |
---|
1040 | * @param string $filter Optional, default is raw or no WordPress defined filter will applied. |
---|
1041 | * @return mixed Term Row from database. Will return false if $taxonomy does not exist or $term was not found. |
---|
1042 | */ |
---|
1043 | function get_term_by($field, $value, $taxonomy, $output = OBJECT, $filter = 'raw') { |
---|
1044 | global $wpdb; |
---|
1045 | |
---|
1046 | if ( ! taxonomy_exists($taxonomy) ) |
---|
1047 | return false; |
---|
1048 | |
---|
1049 | if ( 'slug' == $field ) { |
---|
1050 | $field = 't.slug'; |
---|
1051 | $value = sanitize_title($value); |
---|
1052 | if ( empty($value) ) |
---|
1053 | return false; |
---|
1054 | } else if ( 'name' == $field ) { |
---|
1055 | // Assume already escaped |
---|
1056 | $value = wp_unslash($value); |
---|
1057 | $field = 't.name'; |
---|
1058 | } else if ( 'term_taxonomy_id' == $field ) { |
---|
1059 | $value = (int) $value; |
---|
1060 | $field = 'tt.term_taxonomy_id'; |
---|
1061 | } else { |
---|
1062 | $term = get_term( (int) $value, $taxonomy, $output, $filter); |
---|
1063 | if ( is_wp_error( $term ) ) |
---|
1064 | $term = false; |
---|
1065 | return $term; |
---|
1066 | } |
---|
1067 | |
---|
1068 | $term = $wpdb->get_row( $wpdb->prepare( "SELECT t.*, tt.* FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy = %s AND $field = %s LIMIT 1", $taxonomy, $value) ); |
---|
1069 | if ( !$term ) |
---|
1070 | return false; |
---|
1071 | |
---|
1072 | wp_cache_add($term->term_id, $term, $taxonomy); |
---|
1073 | |
---|
1074 | /** This filter is documented in wp-includes/taxonomy.php */ |
---|
1075 | $term = apply_filters( 'get_term', $term, $taxonomy ); |
---|
1076 | |
---|
1077 | /** This filter is documented in wp-includes/taxonomy.php */ |
---|
1078 | $term = apply_filters( "get_$taxonomy", $term, $taxonomy ); |
---|
1079 | |
---|
1080 | $term = sanitize_term($term, $taxonomy, $filter); |
---|
1081 | |
---|
1082 | if ( $output == OBJECT ) { |
---|
1083 | return $term; |
---|
1084 | } elseif ( $output == ARRAY_A ) { |
---|
1085 | return get_object_vars($term); |
---|
1086 | } elseif ( $output == ARRAY_N ) { |
---|
1087 | return array_values(get_object_vars($term)); |
---|
1088 | } else { |
---|
1089 | return $term; |
---|
1090 | } |
---|
1091 | } |
---|
1092 | |
---|
1093 | /** |
---|
1094 | * Merge all term children into a single array of their IDs. |
---|
1095 | * |
---|
1096 | * This recursive function will merge all of the children of $term into the same |
---|
1097 | * array of term IDs. Only useful for taxonomies which are hierarchical. |
---|
1098 | * |
---|
1099 | * Will return an empty array if $term does not exist in $taxonomy. |
---|
1100 | * |
---|
1101 | * @since 2.3.0 |
---|
1102 | * |
---|
1103 | * @uses $wpdb |
---|
1104 | * @uses _get_term_hierarchy() |
---|
1105 | * @uses get_term_children() Used to get the children of both $taxonomy and the parent $term |
---|
1106 | * |
---|
1107 | * @param string $term_id ID of Term to get children |
---|
1108 | * @param string $taxonomy Taxonomy Name |
---|
1109 | * @return array|WP_Error List of Term IDs. WP_Error returned if $taxonomy does not exist |
---|
1110 | */ |
---|
1111 | function get_term_children( $term_id, $taxonomy ) { |
---|
1112 | if ( ! taxonomy_exists($taxonomy) ) |
---|
1113 | return new WP_Error('invalid_taxonomy', __('Invalid taxonomy')); |
---|
1114 | |
---|
1115 | $term_id = intval( $term_id ); |
---|
1116 | |
---|
1117 | $terms = _get_term_hierarchy($taxonomy); |
---|
1118 | |
---|
1119 | if ( ! isset($terms[$term_id]) ) |
---|
1120 | return array(); |
---|
1121 | |
---|
1122 | $children = $terms[$term_id]; |
---|
1123 | |
---|
1124 | foreach ( (array) $terms[$term_id] as $child ) { |
---|
1125 | if ( $term_id == $child ) { |
---|
1126 | continue; |
---|
1127 | } |
---|
1128 | |
---|
1129 | if ( isset($terms[$child]) ) |
---|
1130 | $children = array_merge($children, get_term_children($child, $taxonomy)); |
---|
1131 | } |
---|
1132 | |
---|
1133 | return $children; |
---|
1134 | } |
---|
1135 | |
---|
1136 | /** |
---|
1137 | * Get sanitized Term field. |
---|
1138 | * |
---|
1139 | * Does checks for $term, based on the $taxonomy. The function is for contextual |
---|
1140 | * reasons and for simplicity of usage. See sanitize_term_field() for more |
---|
1141 | * information. |
---|
1142 | * |
---|
1143 | * @since 2.3.0 |
---|
1144 | * |
---|
1145 | * @uses sanitize_term_field() Passes the return value in sanitize_term_field on success. |
---|
1146 | * |
---|
1147 | * @param string $field Term field to fetch |
---|
1148 | * @param int $term Term ID |
---|
1149 | * @param string $taxonomy Taxonomy Name |
---|
1150 | * @param string $context Optional, default is display. Look at sanitize_term_field() for available options. |
---|
1151 | * @return mixed Will return an empty string if $term is not an object or if $field is not set in $term. |
---|
1152 | */ |
---|
1153 | function get_term_field( $field, $term, $taxonomy, $context = 'display' ) { |
---|
1154 | $term = (int) $term; |
---|
1155 | $term = get_term( $term, $taxonomy ); |
---|
1156 | if ( is_wp_error($term) ) |
---|
1157 | return $term; |
---|
1158 | |
---|
1159 | if ( !is_object($term) ) |
---|
1160 | return ''; |
---|
1161 | |
---|
1162 | if ( !isset($term->$field) ) |
---|
1163 | return ''; |
---|
1164 | |
---|
1165 | return sanitize_term_field($field, $term->$field, $term->term_id, $taxonomy, $context); |
---|
1166 | } |
---|
1167 | |
---|
1168 | /** |
---|
1169 | * Sanitizes Term for editing. |
---|
1170 | * |
---|
1171 | * Return value is sanitize_term() and usage is for sanitizing the term for |
---|
1172 | * editing. Function is for contextual and simplicity. |
---|
1173 | * |
---|
1174 | * @since 2.3.0 |
---|
1175 | * |
---|
1176 | * @uses sanitize_term() Passes the return value on success |
---|
1177 | * |
---|
1178 | * @param int|object $id Term ID or Object |
---|
1179 | * @param string $taxonomy Taxonomy Name |
---|
1180 | * @return mixed|null|WP_Error Will return empty string if $term is not an object. |
---|
1181 | */ |
---|
1182 | function get_term_to_edit( $id, $taxonomy ) { |
---|
1183 | $term = get_term( $id, $taxonomy ); |
---|
1184 | |
---|
1185 | if ( is_wp_error($term) ) |
---|
1186 | return $term; |
---|
1187 | |
---|
1188 | if ( !is_object($term) ) |
---|
1189 | return ''; |
---|
1190 | |
---|
1191 | return sanitize_term($term, $taxonomy, 'edit'); |
---|
1192 | } |
---|
1193 | |
---|
1194 | /** |
---|
1195 | * Retrieve the terms in a given taxonomy or list of taxonomies. |
---|
1196 | * |
---|
1197 | * You can fully inject any customizations to the query before it is sent, as |
---|
1198 | * well as control the output with a filter. |
---|
1199 | * |
---|
1200 | * The 'get_terms' filter will be called when the cache has the term and will |
---|
1201 | * pass the found term along with the array of $taxonomies and array of $args. |
---|
1202 | * This filter is also called before the array of terms is passed and will pass |
---|
1203 | * the array of terms, along with the $taxonomies and $args. |
---|
1204 | * |
---|
1205 | * The 'list_terms_exclusions' filter passes the compiled exclusions along with |
---|
1206 | * the $args. |
---|
1207 | * |
---|
1208 | * The 'get_terms_orderby' filter passes the ORDER BY clause for the query |
---|
1209 | * along with the $args array. |
---|
1210 | * |
---|
1211 | * The 'get_terms_fields' filter passes the fields for the SELECT query |
---|
1212 | * along with the $args array. |
---|
1213 | * |
---|
1214 | * @since 2.3.0 |
---|
1215 | * |
---|
1216 | * @global wpdb $wpdb WordPress database access abstraction object. |
---|
1217 | * |
---|
1218 | * @param string|array $taxonomies Taxonomy name or list of Taxonomy names. |
---|
1219 | * @param array|string $args { |
---|
1220 | * Optional. Array or string of arguments to get terms. |
---|
1221 | * |
---|
1222 | * @type string $orderby Field(s) to order terms by. Accepts term fields, though |
---|
1223 | * empty defaults to 'term_id'. Default 'name'. |
---|
1224 | * @type string $order Whether to order terms in ascending or descending order. |
---|
1225 | * Accepts 'ASC' (ascending) or 'DESC' (descending). |
---|
1226 | * Default 'ASC'. |
---|
1227 | * @type bool|int $hide_empty Whether to hide terms not assigned to any posts. Accepts |
---|
1228 | * 1|true or 0|false. Default 1|true. |
---|
1229 | * @type array|string $include Array or comma/space-separated string of term ids to include. |
---|
1230 | * Default empty array. |
---|
1231 | * @type array|string $exclude Array or comma/space-separated string of term ids to exclude. |
---|
1232 | * If $include is non-empty, $exclude is ignored. |
---|
1233 | * Default empty array. |
---|
1234 | * @type array|string $exclude_tree Array or comma/space-separated string of term ids to exclude |
---|
1235 | * along with all of their descendant terms. If $include is |
---|
1236 | * non-empty, $exclude_tree is ignored. Default empty array. |
---|
1237 | * @type int $number Maximum number of terms to return. Accepts 1+ or -1 (all). |
---|
1238 | * Default -1. |
---|
1239 | * @type int $offset The number by which to offset the terms query. Default empty. |
---|
1240 | * @type string $fields Term fields to query for. Accepts 'all' (returns an array of |
---|
1241 | * term objects), 'ids' or 'names' (returns an array of integers |
---|
1242 | * or strings, respectively. Default 'all'. |
---|
1243 | * @type string $slug Slug to return term(s) for. Default empty. |
---|
1244 | * @type bool $hierarchical Whether to include terms that have non-empty descendants (even |
---|
1245 | * if $hide_empty is set to true). Default true. |
---|
1246 | * @type string $search Search criteria to match terms. Will be SQL-formatted with |
---|
1247 | * wildcards before and after. Default empty. |
---|
1248 | * @type string $name__like Retrieve terms with criteria by which a term is LIKE $name__like. |
---|
1249 | * Default empty. |
---|
1250 | * @type string $description__like Retrieve terms where the description is LIKE $description__like. |
---|
1251 | * Default empty. |
---|
1252 | * @type bool $pad_counts Whether to pad the quantity of a term's children in the quantity |
---|
1253 | * of each term's "count" object variable. Default false. |
---|
1254 | * @type string $get Whether to return terms regardless of ancestry or whether the terms |
---|
1255 | * are empty. Accepts 'all' or empty (disabled). Default empty. |
---|
1256 | * @type int $child_of Term ID to retrieve child terms of. If multiple taxonomies |
---|
1257 | * are passed, $child_of is ignored. Default 0. |
---|
1258 | * @type int|string $parent Parent term ID to retrieve direct-child terms of. Default empty. |
---|
1259 | * @type string $cache_domain Unique cache key to be produced when this query is stored in an |
---|
1260 | * object cache. Default is 'core'. |
---|
1261 | * } |
---|
1262 | * @return array|WP_Error List of Term Objects and their children. Will return WP_Error, if any of $taxonomies |
---|
1263 | * do not exist. |
---|
1264 | */ |
---|
1265 | function get_terms( $taxonomies, $args = '' ) { |
---|
1266 | global $wpdb; |
---|
1267 | $empty_array = array(); |
---|
1268 | |
---|
1269 | $single_taxonomy = ! is_array( $taxonomies ) || 1 === count( $taxonomies ); |
---|
1270 | if ( ! is_array( $taxonomies ) ) { |
---|
1271 | $taxonomies = array( $taxonomies ); |
---|
1272 | } |
---|
1273 | |
---|
1274 | foreach ( $taxonomies as $taxonomy ) { |
---|
1275 | if ( ! taxonomy_exists($taxonomy) ) { |
---|
1276 | $error = new WP_Error('invalid_taxonomy', __('Invalid taxonomy')); |
---|
1277 | return $error; |
---|
1278 | } |
---|
1279 | } |
---|
1280 | |
---|
1281 | $defaults = array('orderby' => 'name', 'order' => 'ASC', |
---|
1282 | 'hide_empty' => true, 'exclude' => array(), 'exclude_tree' => array(), 'include' => array(), |
---|
1283 | 'number' => '', 'fields' => 'all', 'slug' => '', 'parent' => '', |
---|
1284 | 'hierarchical' => true, 'child_of' => 0, 'get' => '', 'name__like' => '', 'description__like' => '', |
---|
1285 | 'pad_counts' => false, 'offset' => '', 'search' => '', 'cache_domain' => 'core' ); |
---|
1286 | $args = wp_parse_args( $args, $defaults ); |
---|
1287 | $args['number'] = absint( $args['number'] ); |
---|
1288 | $args['offset'] = absint( $args['offset'] ); |
---|
1289 | if ( !$single_taxonomy || ! is_taxonomy_hierarchical( reset( $taxonomies ) ) || |
---|
1290 | ( '' !== $args['parent'] && 0 !== $args['parent'] ) ) { |
---|
1291 | $args['child_of'] = 0; |
---|
1292 | $args['hierarchical'] = false; |
---|
1293 | $args['pad_counts'] = false; |
---|
1294 | } |
---|
1295 | |
---|
1296 | if ( 'all' == $args['get'] ) { |
---|
1297 | $args['child_of'] = 0; |
---|
1298 | $args['hide_empty'] = 0; |
---|
1299 | $args['hierarchical'] = false; |
---|
1300 | $args['pad_counts'] = false; |
---|
1301 | } |
---|
1302 | |
---|
1303 | /** |
---|
1304 | * Filter the terms query arguments. |
---|
1305 | * |
---|
1306 | * @since 3.1.0 |
---|
1307 | * |
---|
1308 | * @param array $args An array of arguments. |
---|
1309 | * @param string|array $taxonomies A taxonomy or array of taxonomies. |
---|
1310 | */ |
---|
1311 | $args = apply_filters( 'get_terms_args', $args, $taxonomies ); |
---|
1312 | |
---|
1313 | $child_of = $args['child_of']; |
---|
1314 | if ( $child_of ) { |
---|
1315 | $hierarchy = _get_term_hierarchy( reset( $taxonomies ) ); |
---|
1316 | if ( ! isset( $hierarchy[ $child_of ] ) ) { |
---|
1317 | return $empty_array; |
---|
1318 | } |
---|
1319 | } |
---|
1320 | |
---|
1321 | $parent = $args['parent']; |
---|
1322 | if ( $parent ) { |
---|
1323 | $hierarchy = _get_term_hierarchy( reset( $taxonomies ) ); |
---|
1324 | if ( ! isset( $hierarchy[ $parent ] ) ) { |
---|
1325 | return $empty_array; |
---|
1326 | } |
---|
1327 | } |
---|
1328 | |
---|
1329 | $_orderby = strtolower( $args['orderby'] ); |
---|
1330 | if ( 'count' == $_orderby ) { |
---|
1331 | $orderby = 'tt.count'; |
---|
1332 | } else if ( 'name' == $_orderby ) { |
---|
1333 | $orderby = 't.name'; |
---|
1334 | } else if ( 'slug' == $_orderby ) { |
---|
1335 | $orderby = 't.slug'; |
---|
1336 | } else if ( 'term_group' == $_orderby ) { |
---|
1337 | $orderby = 't.term_group'; |
---|
1338 | } else if ( 'none' == $_orderby ) { |
---|
1339 | $orderby = ''; |
---|
1340 | } elseif ( empty($_orderby) || 'id' == $_orderby ) { |
---|
1341 | $orderby = 't.term_id'; |
---|
1342 | } else { |
---|
1343 | $orderby = 't.name'; |
---|
1344 | } |
---|
1345 | /** |
---|
1346 | * Filter the ORDERBY clause of the terms query. |
---|
1347 | * |
---|
1348 | * @since 2.8.0 |
---|
1349 | * |
---|
1350 | * @param string $orderby ORDERBY clause of the terms query. |
---|
1351 | * @param array $args An array of terms query arguments. |
---|
1352 | * @param string|array $taxonomies A taxonomy or array of taxonomies. |
---|
1353 | */ |
---|
1354 | $orderby = apply_filters( 'get_terms_orderby', $orderby, $args, $taxonomies ); |
---|
1355 | |
---|
1356 | $order = strtoupper( $args['order'] ); |
---|
1357 | if ( ! empty( $orderby ) ) { |
---|
1358 | $orderby = "ORDER BY $orderby"; |
---|
1359 | } else { |
---|
1360 | $order = ''; |
---|
1361 | } |
---|
1362 | |
---|
1363 | if ( '' !== $order && ! in_array( $order, array( 'ASC', 'DESC' ) ) ) { |
---|
1364 | $order = 'ASC'; |
---|
1365 | } |
---|
1366 | |
---|
1367 | $where = "tt.taxonomy IN ('" . implode("', '", $taxonomies) . "')"; |
---|
1368 | |
---|
1369 | $exclude = $args['exclude']; |
---|
1370 | $exclude_tree = $args['exclude_tree']; |
---|
1371 | $include = $args['include']; |
---|
1372 | |
---|
1373 | $inclusions = ''; |
---|
1374 | if ( ! empty( $include ) ) { |
---|
1375 | $exclude = ''; |
---|
1376 | $exclude_tree = ''; |
---|
1377 | $inclusions = implode( ',', wp_parse_id_list( $include ) ); |
---|
1378 | } |
---|
1379 | |
---|
1380 | if ( ! empty( $inclusions ) ) { |
---|
1381 | $inclusions = ' AND t.term_id IN ( ' . $inclusions . ' )'; |
---|
1382 | $where .= $inclusions; |
---|
1383 | } |
---|
1384 | |
---|
1385 | if ( ! empty( $exclude_tree ) ) { |
---|
1386 | $exclude_tree = wp_parse_id_list( $exclude_tree ); |
---|
1387 | $excluded_children = $exclude_tree; |
---|
1388 | foreach ( $exclude_tree as $extrunk ) { |
---|
1389 | $excluded_children = array_merge( |
---|
1390 | $excluded_children, |
---|
1391 | (array) get_terms( $taxonomies[0], array( 'child_of' => intval( $extrunk ), 'fields' => 'ids', 'hide_empty' => 0 ) ) |
---|
1392 | ); |
---|
1393 | } |
---|
1394 | $exclusions = implode( ',', array_map( 'intval', $excluded_children ) ); |
---|
1395 | } else { |
---|
1396 | $exclusions = ''; |
---|
1397 | } |
---|
1398 | |
---|
1399 | if ( ! empty( $exclude ) ) { |
---|
1400 | $exterms = wp_parse_id_list( $exclude ); |
---|
1401 | if ( empty( $exclusions ) ) { |
---|
1402 | $exclusions = implode( ',', $exterms ); |
---|
1403 | } else { |
---|
1404 | $exclusions .= ', ' . implode( ',', $exterms ); |
---|
1405 | } |
---|
1406 | } |
---|
1407 | |
---|
1408 | if ( ! empty( $exclusions ) ) { |
---|
1409 | $exclusions = ' AND t.term_id NOT IN (' . $exclusions . ')'; |
---|
1410 | } |
---|
1411 | |
---|
1412 | /** |
---|
1413 | * Filter the terms to exclude from the terms query. |
---|
1414 | * |
---|
1415 | * @since 2.3.0 |
---|
1416 | * |
---|
1417 | * @param string $exclusions NOT IN clause of the terms query. |
---|
1418 | * @param array $args An array of terms query arguments. |
---|
1419 | * @param string|array $taxonomies A taxonomy or array of taxonomies. |
---|
1420 | */ |
---|
1421 | $exclusions = apply_filters( 'list_terms_exclusions', $exclusions, $args, $taxonomies ); |
---|
1422 | |
---|
1423 | if ( ! empty( $exclusions ) ) { |
---|
1424 | $where .= $exclusions; |
---|
1425 | } |
---|
1426 | |
---|
1427 | if ( ! empty( $args['slug'] ) ) { |
---|
1428 | $slug = sanitize_title( $args['slug'] ); |
---|
1429 | $where .= " AND t.slug = '$slug'"; |
---|
1430 | } |
---|
1431 | |
---|
1432 | if ( ! empty( $args['name__like'] ) ) { |
---|
1433 | $where .= $wpdb->prepare( " AND t.name LIKE %s", '%' . $wpdb->esc_like( $args['name__like'] ) . '%' ); |
---|
1434 | } |
---|
1435 | |
---|
1436 | if ( ! empty( $args['description__like'] ) ) { |
---|
1437 | $where .= $wpdb->prepare( " AND tt.description LIKE %s", '%' . $wpdb->esc_like( $args['description__like'] ) . '%' ); |
---|
1438 | } |
---|
1439 | |
---|
1440 | if ( '' !== $parent ) { |
---|
1441 | $parent = (int) $parent; |
---|
1442 | $where .= " AND tt.parent = '$parent'"; |
---|
1443 | } |
---|
1444 | |
---|
1445 | $hierarchical = $args['hierarchical']; |
---|
1446 | if ( 'count' == $args['fields'] ) { |
---|
1447 | $hierarchical = false; |
---|
1448 | } |
---|
1449 | if ( $args['hide_empty'] && !$hierarchical ) { |
---|
1450 | $where .= ' AND tt.count > 0'; |
---|
1451 | } |
---|
1452 | |
---|
1453 | $number = $args['number']; |
---|
1454 | $offset = $args['offset']; |
---|
1455 | |
---|
1456 | // don't limit the query results when we have to descend the family tree |
---|
1457 | if ( $number && ! $hierarchical && ! $child_of && '' === $parent ) { |
---|
1458 | if ( $offset ) { |
---|
1459 | $limits = 'LIMIT ' . $offset . ',' . $number; |
---|
1460 | } else { |
---|
1461 | $limits = 'LIMIT ' . $number; |
---|
1462 | } |
---|
1463 | } else { |
---|
1464 | $limits = ''; |
---|
1465 | } |
---|
1466 | |
---|
1467 | if ( ! empty( $args['search'] ) ) { |
---|
1468 | $like = '%' . $wpdb->esc_like( $args['search'] ) . '%'; |
---|
1469 | $where .= $wpdb->prepare( ' AND ((t.name LIKE %s) OR (t.slug LIKE %s))', $like, $like ); |
---|
1470 | } |
---|
1471 | |
---|
1472 | $selects = array(); |
---|
1473 | switch ( $args['fields'] ) { |
---|
1474 | case 'all': |
---|
1475 | $selects = array( 't.*', 'tt.*' ); |
---|
1476 | break; |
---|
1477 | case 'ids': |
---|
1478 | case 'id=>parent': |
---|
1479 | $selects = array( 't.term_id', 'tt.parent', 'tt.count' ); |
---|
1480 | break; |
---|
1481 | case 'names': |
---|
1482 | $selects = array( 't.term_id', 'tt.parent', 'tt.count', 't.name' ); |
---|
1483 | break; |
---|
1484 | case 'count': |
---|
1485 | $orderby = ''; |
---|
1486 | $order = ''; |
---|
1487 | $selects = array( 'COUNT(*)' ); |
---|
1488 | break; |
---|
1489 | case 'id=>name': |
---|
1490 | $selects = array( 't.term_id', 't.name' ); |
---|
1491 | break; |
---|
1492 | case 'id=>slug': |
---|
1493 | $selects = array( 't.term_id', 't.slug' ); |
---|
1494 | break; |
---|
1495 | } |
---|
1496 | |
---|
1497 | $_fields = $args['fields']; |
---|
1498 | |
---|
1499 | /** |
---|
1500 | * Filter the fields to select in the terms query. |
---|
1501 | * |
---|
1502 | * @since 2.8.0 |
---|
1503 | * |
---|
1504 | * @param array $selects An array of fields to select for the terms query. |
---|
1505 | * @param array $args An array of term query arguments. |
---|
1506 | * @param string|array $taxonomies A taxonomy or array of taxonomies. |
---|
1507 | */ |
---|
1508 | $fields = implode( ', ', apply_filters( 'get_terms_fields', $selects, $args, $taxonomies ) ); |
---|
1509 | |
---|
1510 | $join = "INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id"; |
---|
1511 | |
---|
1512 | $pieces = array( 'fields', 'join', 'where', 'orderby', 'order', 'limits' ); |
---|
1513 | |
---|
1514 | /** |
---|
1515 | * Filter the terms query SQL clauses. |
---|
1516 | * |
---|
1517 | * @since 3.1.0 |
---|
1518 | * |
---|
1519 | * @param array $pieces Terms query SQL clauses. |
---|
1520 | * @param string|array $taxonomies A taxonomy or array of taxonomies. |
---|
1521 | * @param array $args An array of terms query arguments. |
---|
1522 | */ |
---|
1523 | $clauses = apply_filters( 'terms_clauses', compact( $pieces ), $taxonomies, $args ); |
---|
1524 | $fields = isset( $clauses[ 'fields' ] ) ? $clauses[ 'fields' ] : ''; |
---|
1525 | $join = isset( $clauses[ 'join' ] ) ? $clauses[ 'join' ] : ''; |
---|
1526 | $where = isset( $clauses[ 'where' ] ) ? $clauses[ 'where' ] : ''; |
---|
1527 | $orderby = isset( $clauses[ 'orderby' ] ) ? $clauses[ 'orderby' ] : ''; |
---|
1528 | $order = isset( $clauses[ 'order' ] ) ? $clauses[ 'order' ] : ''; |
---|
1529 | $limits = isset( $clauses[ 'limits' ] ) ? $clauses[ 'limits' ] : ''; |
---|
1530 | |
---|
1531 | $query = "SELECT $fields FROM $wpdb->terms AS t $join WHERE $where $orderby $order $limits"; |
---|
1532 | |
---|
1533 | // $args can be whatever, only use the args defined in defaults to compute the key |
---|
1534 | $filter_key = ( has_filter('list_terms_exclusions') ) ? serialize($GLOBALS['wp_filter']['list_terms_exclusions']) : ''; |
---|
1535 | $key = md5( $query . $filter_key ); |
---|
1536 | $last_changed = wp_cache_get( 'last_changed', 'terms' ); |
---|
1537 | if ( ! $last_changed ) { |
---|
1538 | $last_changed = microtime(); |
---|
1539 | wp_cache_set( 'last_changed', $last_changed, 'terms' ); |
---|
1540 | } |
---|
1541 | $cache_key = "get_terms:$key:$last_changed"; |
---|
1542 | $cache = wp_cache_get( $cache_key, 'terms' ); |
---|
1543 | if ( false !== $cache ) { |
---|
1544 | |
---|
1545 | /** |
---|
1546 | * Filter the given taxonomy's terms cache. |
---|
1547 | * |
---|
1548 | * @since 2.3.0 |
---|
1549 | * |
---|
1550 | * @param array $cache Cached array of terms for the given taxonomy. |
---|
1551 | * @param string|array $taxonomies A taxonomy or array of taxonomies. |
---|
1552 | * @param array $args An array of arguments to get terms. |
---|
1553 | */ |
---|
1554 | $cache = apply_filters( 'get_terms', $cache, $taxonomies, $args ); |
---|
1555 | return $cache; |
---|
1556 | } |
---|
1557 | |
---|
1558 | if ( 'count' == $_fields ) { |
---|
1559 | $term_count = $wpdb->get_var($query); |
---|
1560 | return $term_count; |
---|
1561 | } |
---|
1562 | |
---|
1563 | $terms = $wpdb->get_results($query); |
---|
1564 | if ( 'all' == $_fields ) { |
---|
1565 | update_term_cache($terms); |
---|
1566 | } |
---|
1567 | |
---|
1568 | if ( empty($terms) ) { |
---|
1569 | wp_cache_add( $cache_key, array(), 'terms', DAY_IN_SECONDS ); |
---|
1570 | |
---|
1571 | /** This filter is documented in wp-includes/taxonomy.php */ |
---|
1572 | $terms = apply_filters( 'get_terms', array(), $taxonomies, $args ); |
---|
1573 | return $terms; |
---|
1574 | } |
---|
1575 | |
---|
1576 | if ( $child_of ) { |
---|
1577 | $children = _get_term_hierarchy( reset( $taxonomies ) ); |
---|
1578 | if ( ! empty( $children ) ) { |
---|
1579 | $terms = _get_term_children( $child_of, $terms, reset( $taxonomies ) ); |
---|
1580 | } |
---|
1581 | } |
---|
1582 | |
---|
1583 | // Update term counts to include children. |
---|
1584 | if ( $args['pad_counts'] && 'all' == $_fields ) { |
---|
1585 | _pad_term_counts( $terms, reset( $taxonomies ) ); |
---|
1586 | } |
---|
1587 | // Make sure we show empty categories that have children. |
---|
1588 | if ( $hierarchical && $args['hide_empty'] && is_array( $terms ) ) { |
---|
1589 | foreach ( $terms as $k => $term ) { |
---|
1590 | if ( ! $term->count ) { |
---|
1591 | $children = get_term_children( $term->term_id, reset( $taxonomies ) ); |
---|
1592 | if ( is_array( $children ) ) { |
---|
1593 | foreach ( $children as $child_id ) { |
---|
1594 | $child = get_term( $child_id, reset( $taxonomies ) ); |
---|
1595 | if ( $child->count ) { |
---|
1596 | continue 2; |
---|
1597 | } |
---|
1598 | } |
---|
1599 | } |
---|
1600 | |
---|
1601 | // It really is empty |
---|
1602 | unset($terms[$k]); |
---|
1603 | } |
---|
1604 | } |
---|
1605 | } |
---|
1606 | reset( $terms ); |
---|
1607 | |
---|
1608 | $_terms = array(); |
---|
1609 | if ( 'id=>parent' == $_fields ) { |
---|
1610 | while ( $term = array_shift( $terms ) ) { |
---|
1611 | $_terms[$term->term_id] = $term->parent; |
---|
1612 | } |
---|
1613 | } elseif ( 'ids' == $_fields ) { |
---|
1614 | while ( $term = array_shift( $terms ) ) { |
---|
1615 | $_terms[] = $term->term_id; |
---|
1616 | } |
---|
1617 | } elseif ( 'names' == $_fields ) { |
---|
1618 | while ( $term = array_shift( $terms ) ) { |
---|
1619 | $_terms[] = $term->name; |
---|
1620 | } |
---|
1621 | } elseif ( 'id=>name' == $_fields ) { |
---|
1622 | while ( $term = array_shift( $terms ) ) { |
---|
1623 | $_terms[$term->term_id] = $term->name; |
---|
1624 | } |
---|
1625 | } elseif ( 'id=>slug' == $_fields ) { |
---|
1626 | while ( $term = array_shift( $terms ) ) { |
---|
1627 | $_terms[$term->term_id] = $term->slug; |
---|
1628 | } |
---|
1629 | } |
---|
1630 | |
---|
1631 | if ( ! empty( $_terms ) ) { |
---|
1632 | $terms = $_terms; |
---|
1633 | } |
---|
1634 | |
---|
1635 | if ( $number && is_array( $terms ) && count( $terms ) > $number ) { |
---|
1636 | $terms = array_slice( $terms, $offset, $number ); |
---|
1637 | } |
---|
1638 | |
---|
1639 | wp_cache_add( $cache_key, $terms, 'terms', DAY_IN_SECONDS ); |
---|
1640 | |
---|
1641 | /** This filter is documented in wp-includes/taxonomy */ |
---|
1642 | $terms = apply_filters( 'get_terms', $terms, $taxonomies, $args ); |
---|
1643 | return $terms; |
---|
1644 | } |
---|
1645 | |
---|
1646 | /** |
---|
1647 | * Check if Term exists. |
---|
1648 | * |
---|
1649 | * Formerly is_term(), introduced in 2.3.0. |
---|
1650 | * |
---|
1651 | * @since 3.0.0 |
---|
1652 | * |
---|
1653 | * @uses $wpdb |
---|
1654 | * |
---|
1655 | * @param int|string $term The term to check |
---|
1656 | * @param string $taxonomy The taxonomy name to use |
---|
1657 | * @param int $parent ID of parent term under which to confine the exists search. |
---|
1658 | * @return mixed Returns 0 if the term does not exist. Returns the term ID if no taxonomy is specified |
---|
1659 | * and the term ID exists. Returns an array of the term ID and the term taxonomy ID |
---|
1660 | * if the taxonomy is specified and the pairing exists. |
---|
1661 | */ |
---|
1662 | function term_exists($term, $taxonomy = '', $parent = 0) { |
---|
1663 | global $wpdb; |
---|
1664 | |
---|
1665 | $select = "SELECT term_id FROM $wpdb->terms as t WHERE "; |
---|
1666 | $tax_select = "SELECT tt.term_id, tt.term_taxonomy_id FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy as tt ON tt.term_id = t.term_id WHERE "; |
---|
1667 | |
---|
1668 | if ( is_int($term) ) { |
---|
1669 | if ( 0 == $term ) |
---|
1670 | return 0; |
---|
1671 | $where = 't.term_id = %d'; |
---|
1672 | if ( !empty($taxonomy) ) |
---|
1673 | return $wpdb->get_row( $wpdb->prepare( $tax_select . $where . " AND tt.taxonomy = %s", $term, $taxonomy ), ARRAY_A ); |
---|
1674 | else |
---|
1675 | return $wpdb->get_var( $wpdb->prepare( $select . $where, $term ) ); |
---|
1676 | } |
---|
1677 | |
---|
1678 | $term = trim( wp_unslash( $term ) ); |
---|
1679 | |
---|
1680 | if ( '' === $slug = sanitize_title($term) ) |
---|
1681 | return 0; |
---|
1682 | |
---|
1683 | $where = 't.slug = %s'; |
---|
1684 | $else_where = 't.name = %s'; |
---|
1685 | $where_fields = array($slug); |
---|
1686 | $else_where_fields = array($term); |
---|
1687 | if ( !empty($taxonomy) ) { |
---|
1688 | $parent = (int) $parent; |
---|
1689 | if ( $parent > 0 ) { |
---|
1690 | $where_fields[] = $parent; |
---|
1691 | $else_where_fields[] = $parent; |
---|
1692 | $where .= ' AND tt.parent = %d'; |
---|
1693 | $else_where .= ' AND tt.parent = %d'; |
---|
1694 | } |
---|
1695 | |
---|
1696 | $where_fields[] = $taxonomy; |
---|
1697 | $else_where_fields[] = $taxonomy; |
---|
1698 | |
---|
1699 | if ( $result = $wpdb->get_row( $wpdb->prepare("SELECT tt.term_id, tt.term_taxonomy_id FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy as tt ON tt.term_id = t.term_id WHERE $where AND tt.taxonomy = %s", $where_fields), ARRAY_A) ) |
---|
1700 | return $result; |
---|
1701 | |
---|
1702 | return $wpdb->get_row( $wpdb->prepare("SELECT tt.term_id, tt.term_taxonomy_id FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy as tt ON tt.term_id = t.term_id WHERE $else_where AND tt.taxonomy = %s", $else_where_fields), ARRAY_A); |
---|
1703 | } |
---|
1704 | |
---|
1705 | if ( $result = $wpdb->get_var( $wpdb->prepare("SELECT term_id FROM $wpdb->terms as t WHERE $where", $where_fields) ) ) |
---|
1706 | return $result; |
---|
1707 | |
---|
1708 | return $wpdb->get_var( $wpdb->prepare("SELECT term_id FROM $wpdb->terms as t WHERE $else_where", $else_where_fields) ); |
---|
1709 | } |
---|
1710 | |
---|
1711 | /** |
---|
1712 | * Check if a term is an ancestor of another term. |
---|
1713 | * |
---|
1714 | * You can use either an id or the term object for both parameters. |
---|
1715 | * |
---|
1716 | * @since 3.4.0 |
---|
1717 | * |
---|
1718 | * @param int|object $term1 ID or object to check if this is the parent term. |
---|
1719 | * @param int|object $term2 The child term. |
---|
1720 | * @param string $taxonomy Taxonomy name that $term1 and $term2 belong to. |
---|
1721 | * @return bool Whether $term2 is child of $term1 |
---|
1722 | */ |
---|
1723 | function term_is_ancestor_of( $term1, $term2, $taxonomy ) { |
---|
1724 | if ( ! isset( $term1->term_id ) ) |
---|
1725 | $term1 = get_term( $term1, $taxonomy ); |
---|
1726 | if ( ! isset( $term2->parent ) ) |
---|
1727 | $term2 = get_term( $term2, $taxonomy ); |
---|
1728 | |
---|
1729 | if ( empty( $term1->term_id ) || empty( $term2->parent ) ) |
---|
1730 | return false; |
---|
1731 | if ( $term2->parent == $term1->term_id ) |
---|
1732 | return true; |
---|
1733 | |
---|
1734 | return term_is_ancestor_of( $term1, get_term( $term2->parent, $taxonomy ), $taxonomy ); |
---|
1735 | } |
---|
1736 | |
---|
1737 | /** |
---|
1738 | * Sanitize Term all fields. |
---|
1739 | * |
---|
1740 | * Relies on sanitize_term_field() to sanitize the term. The difference is that |
---|
1741 | * this function will sanitize <strong>all</strong> fields. The context is based |
---|
1742 | * on sanitize_term_field(). |
---|
1743 | * |
---|
1744 | * The $term is expected to be either an array or an object. |
---|
1745 | * |
---|
1746 | * @since 2.3.0 |
---|
1747 | * |
---|
1748 | * @uses sanitize_term_field Used to sanitize all fields in a term |
---|
1749 | * |
---|
1750 | * @param array|object $term The term to check |
---|
1751 | * @param string $taxonomy The taxonomy name to use |
---|
1752 | * @param string $context Default is 'display'. |
---|
1753 | * @return array|object Term with all fields sanitized |
---|
1754 | */ |
---|
1755 | function sanitize_term($term, $taxonomy, $context = 'display') { |
---|
1756 | |
---|
1757 | $fields = array( 'term_id', 'name', 'description', 'slug', 'count', 'parent', 'term_group', 'term_taxonomy_id', 'object_id' ); |
---|
1758 | |
---|
1759 | $do_object = is_object( $term ); |
---|
1760 | |
---|
1761 | $term_id = $do_object ? $term->term_id : (isset($term['term_id']) ? $term['term_id'] : 0); |
---|
1762 | |
---|
1763 | foreach ( (array) $fields as $field ) { |
---|
1764 | if ( $do_object ) { |
---|
1765 | if ( isset($term->$field) ) |
---|
1766 | $term->$field = sanitize_term_field($field, $term->$field, $term_id, $taxonomy, $context); |
---|
1767 | } else { |
---|
1768 | if ( isset($term[$field]) ) |
---|
1769 | $term[$field] = sanitize_term_field($field, $term[$field], $term_id, $taxonomy, $context); |
---|
1770 | } |
---|
1771 | } |
---|
1772 | |
---|
1773 | if ( $do_object ) |
---|
1774 | $term->filter = $context; |
---|
1775 | else |
---|
1776 | $term['filter'] = $context; |
---|
1777 | |
---|
1778 | return $term; |
---|
1779 | } |
---|
1780 | |
---|
1781 | /** |
---|
1782 | * Cleanse the field value in the term based on the context. |
---|
1783 | * |
---|
1784 | * Passing a term field value through the function should be assumed to have |
---|
1785 | * cleansed the value for whatever context the term field is going to be used. |
---|
1786 | * |
---|
1787 | * If no context or an unsupported context is given, then default filters will |
---|
1788 | * be applied. |
---|
1789 | * |
---|
1790 | * There are enough filters for each context to support a custom filtering |
---|
1791 | * without creating your own filter function. Simply create a function that |
---|
1792 | * hooks into the filter you need. |
---|
1793 | * |
---|
1794 | * @since 2.3.0 |
---|
1795 | * |
---|
1796 | * @uses $wpdb |
---|
1797 | * |
---|
1798 | * @param string $field Term field to sanitize |
---|
1799 | * @param string $value Search for this term value |
---|
1800 | * @param int $term_id Term ID |
---|
1801 | * @param string $taxonomy Taxonomy Name |
---|
1802 | * @param string $context Either edit, db, display, attribute, or js. |
---|
1803 | * @return mixed sanitized field |
---|
1804 | */ |
---|
1805 | function sanitize_term_field($field, $value, $term_id, $taxonomy, $context) { |
---|
1806 | $int_fields = array( 'parent', 'term_id', 'count', 'term_group', 'term_taxonomy_id', 'object_id' ); |
---|
1807 | if ( in_array( $field, $int_fields ) ) { |
---|
1808 | $value = (int) $value; |
---|
1809 | if ( $value < 0 ) |
---|
1810 | $value = 0; |
---|
1811 | } |
---|
1812 | |
---|
1813 | if ( 'raw' == $context ) |
---|
1814 | return $value; |
---|
1815 | |
---|
1816 | if ( 'edit' == $context ) { |
---|
1817 | |
---|
1818 | /** |
---|
1819 | * Filter a term field to edit before it is sanitized. |
---|
1820 | * |
---|
1821 | * The dynamic portion of the filter name, $field, refers to the term field. |
---|
1822 | * |
---|
1823 | * @since 2.3.0 |
---|
1824 | * |
---|
1825 | * @param mixed $value Value of the term field. |
---|
1826 | * @param int $term_id Term ID. |
---|
1827 | * @param string $taxonomy Taxonomy slug. |
---|
1828 | */ |
---|
1829 | $value = apply_filters( "edit_term_{$field}", $value, $term_id, $taxonomy ); |
---|
1830 | |
---|
1831 | /** |
---|
1832 | * Filter the taxonomy field to edit before it is sanitized. |
---|
1833 | * |
---|
1834 | * The dynamic portions of the filter name, $taxonomy, and $field, refer |
---|
1835 | * to the taxonomy slug and taxonomy field, respectively. |
---|
1836 | * |
---|
1837 | * @since 2.3.0 |
---|
1838 | * |
---|
1839 | * @param mixed $value Value of the taxonomy field to edit. |
---|
1840 | * @param int $term_id Term ID. |
---|
1841 | */ |
---|
1842 | $value = apply_filters( "edit_{$taxonomy}_{$field}", $value, $term_id ); |
---|
1843 | if ( 'description' == $field ) |
---|
1844 | $value = esc_html($value); // textarea_escaped |
---|
1845 | else |
---|
1846 | $value = esc_attr($value); |
---|
1847 | } else if ( 'db' == $context ) { |
---|
1848 | |
---|
1849 | /** |
---|
1850 | * Filter a term field value before it is sanitized. |
---|
1851 | * |
---|
1852 | * The dynamic portion of the filter name, $field, refers to the term field. |
---|
1853 | * |
---|
1854 | * @since 2.3.0 |
---|
1855 | * |
---|
1856 | * @param mixed $value Value of the term field. |
---|
1857 | * @param string $taxonomy Taxonomy slug. |
---|
1858 | */ |
---|
1859 | $value = apply_filters( "pre_term_{$field}", $value, $taxonomy ); |
---|
1860 | |
---|
1861 | /** |
---|
1862 | * Filter a taxonomy field before it is sanitized. |
---|
1863 | * |
---|
1864 | * The dynamic portions of the filter name, $taxonomy, and $field, refer |
---|
1865 | * to the taxonomy slug and field name, respectively. |
---|
1866 | * |
---|
1867 | * @since 2.3.0 |
---|
1868 | * |
---|
1869 | * @param mixed $value Value of the taxonomy field. |
---|
1870 | */ |
---|
1871 | $value = apply_filters( "pre_{$taxonomy}_{$field}", $value ); |
---|
1872 | // Back compat filters |
---|
1873 | if ( 'slug' == $field ) { |
---|
1874 | /** |
---|
1875 | * Filter the category nicename before it is sanitized. |
---|
1876 | * |
---|
1877 | * Use the pre_{$taxonomy}_{$field} hook instead. |
---|
1878 | * |
---|
1879 | * @since 2.0.3 |
---|
1880 | * |
---|
1881 | * @param string $value The category nicename. |
---|
1882 | */ |
---|
1883 | $value = apply_filters( 'pre_category_nicename', $value ); |
---|
1884 | } |
---|
1885 | |
---|
1886 | } else if ( 'rss' == $context ) { |
---|
1887 | |
---|
1888 | /** |
---|
1889 | * Filter the term field for use in RSS. |
---|
1890 | * |
---|
1891 | * The dynamic portion of the filter name, $field, refers to the term field. |
---|
1892 | * |
---|
1893 | * @since 2.3.0 |
---|
1894 | * |
---|
1895 | * @param mixed $value Value of the term field. |
---|
1896 | * @param string $taxonomy Taxonomy slug. |
---|
1897 | */ |
---|
1898 | $value = apply_filters( "term_{$field}_rss", $value, $taxonomy ); |
---|
1899 | |
---|
1900 | /** |
---|
1901 | * Filter the taxonomy field for use in RSS. |
---|
1902 | * |
---|
1903 | * The dynamic portions of the hook name, $taxonomy, and $field, refer |
---|
1904 | * to the taxonomy slug and field name, respectively. |
---|
1905 | * |
---|
1906 | * @since 2.3.0 |
---|
1907 | * |
---|
1908 | * @param mixed $value Value of the taxonomy field. |
---|
1909 | */ |
---|
1910 | $value = apply_filters( "{$taxonomy}_{$field}_rss", $value ); |
---|
1911 | } else { |
---|
1912 | // Use display filters by default. |
---|
1913 | |
---|
1914 | /** |
---|
1915 | * Filter the term field sanitized for display. |
---|
1916 | * |
---|
1917 | * The dynamic portion of the filter name, $field, refers to the term field name. |
---|
1918 | * |
---|
1919 | * @since 2.3.0 |
---|
1920 | * |
---|
1921 | * @param mixed $value Value of the term field. |
---|
1922 | * @param int $term_id Term ID. |
---|
1923 | * @param string $taxonomy Taxonomy slug. |
---|
1924 | * @param string $context Context to retrieve the term field value. |
---|
1925 | */ |
---|
1926 | $value = apply_filters( "term_{$field}", $value, $term_id, $taxonomy, $context ); |
---|
1927 | |
---|
1928 | /** |
---|
1929 | * Filter the taxonomy field sanitized for display. |
---|
1930 | * |
---|
1931 | * The dynamic portions of the filter name, $taxonomy, and $field, refer |
---|
1932 | * to the taxonomy slug and taxonomy field, respectively. |
---|
1933 | * |
---|
1934 | * @since 2.3.0 |
---|
1935 | * |
---|
1936 | * @param mixed $value Value of the taxonomy field. |
---|
1937 | * @param int $term_id Term ID. |
---|
1938 | * @param string $context Context to retrieve the taxonomy field value. |
---|
1939 | */ |
---|
1940 | $value = apply_filters( "{$taxonomy}_{$field}", $value, $term_id, $context ); |
---|
1941 | } |
---|
1942 | |
---|
1943 | if ( 'attribute' == $context ) |
---|
1944 | $value = esc_attr($value); |
---|
1945 | else if ( 'js' == $context ) |
---|
1946 | $value = esc_js($value); |
---|
1947 | |
---|
1948 | return $value; |
---|
1949 | } |
---|
1950 | |
---|
1951 | /** |
---|
1952 | * Count how many terms are in Taxonomy. |
---|
1953 | * |
---|
1954 | * Default $args is 'hide_empty' which can be 'hide_empty=true' or array('hide_empty' => true). |
---|
1955 | * |
---|
1956 | * @since 2.3.0 |
---|
1957 | * |
---|
1958 | * @uses get_terms() |
---|
1959 | * @uses wp_parse_args() Turns strings into arrays and merges defaults into an array. |
---|
1960 | * |
---|
1961 | * @param string $taxonomy Taxonomy name |
---|
1962 | * @param array|string $args Overwrite defaults. See get_terms() |
---|
1963 | * @return int|WP_Error How many terms are in $taxonomy. WP_Error if $taxonomy does not exist. |
---|
1964 | */ |
---|
1965 | function wp_count_terms( $taxonomy, $args = array() ) { |
---|
1966 | $defaults = array('hide_empty' => false); |
---|
1967 | $args = wp_parse_args($args, $defaults); |
---|
1968 | |
---|
1969 | // backwards compatibility |
---|
1970 | if ( isset($args['ignore_empty']) ) { |
---|
1971 | $args['hide_empty'] = $args['ignore_empty']; |
---|
1972 | unset($args['ignore_empty']); |
---|
1973 | } |
---|
1974 | |
---|
1975 | $args['fields'] = 'count'; |
---|
1976 | |
---|
1977 | return get_terms($taxonomy, $args); |
---|
1978 | } |
---|
1979 | |
---|
1980 | /** |
---|
1981 | * Will unlink the object from the taxonomy or taxonomies. |
---|
1982 | * |
---|
1983 | * Will remove all relationships between the object and any terms in |
---|
1984 | * a particular taxonomy or taxonomies. Does not remove the term or |
---|
1985 | * taxonomy itself. |
---|
1986 | * |
---|
1987 | * @since 2.3.0 |
---|
1988 | * @uses wp_remove_object_terms() |
---|
1989 | * |
---|
1990 | * @param int $object_id The term Object Id that refers to the term |
---|
1991 | * @param string|array $taxonomies List of Taxonomy Names or single Taxonomy name. |
---|
1992 | */ |
---|
1993 | function wp_delete_object_term_relationships( $object_id, $taxonomies ) { |
---|
1994 | $object_id = (int) $object_id; |
---|
1995 | |
---|
1996 | if ( !is_array($taxonomies) ) |
---|
1997 | $taxonomies = array($taxonomies); |
---|
1998 | |
---|
1999 | foreach ( (array) $taxonomies as $taxonomy ) { |
---|
2000 | $term_ids = wp_get_object_terms( $object_id, $taxonomy, array( 'fields' => 'ids' ) ); |
---|
2001 | $term_ids = array_map( 'intval', $term_ids ); |
---|
2002 | wp_remove_object_terms( $object_id, $term_ids, $taxonomy ); |
---|
2003 | } |
---|
2004 | } |
---|
2005 | |
---|
2006 | /** |
---|
2007 | * Removes a term from the database. |
---|
2008 | * |
---|
2009 | * If the term is a parent of other terms, then the children will be updated to |
---|
2010 | * that term's parent. |
---|
2011 | * |
---|
2012 | * The $args 'default' will only override the terms found, if there is only one |
---|
2013 | * term found. Any other and the found terms are used. |
---|
2014 | * |
---|
2015 | * The $args 'force_default' will force the term supplied as default to be |
---|
2016 | * assigned even if the object was not going to be termless |
---|
2017 | * |
---|
2018 | * @since 2.3.0 |
---|
2019 | * |
---|
2020 | * @uses $wpdb |
---|
2021 | * |
---|
2022 | * @param int $term Term ID |
---|
2023 | * @param string $taxonomy Taxonomy Name |
---|
2024 | * @param array|string $args Optional. Change 'default' term id and override found term ids. |
---|
2025 | * @return bool|WP_Error Returns false if not term; true if completes delete action. |
---|
2026 | */ |
---|
2027 | function wp_delete_term( $term, $taxonomy, $args = array() ) { |
---|
2028 | global $wpdb; |
---|
2029 | |
---|
2030 | $term = (int) $term; |
---|
2031 | |
---|
2032 | if ( ! $ids = term_exists($term, $taxonomy) ) |
---|
2033 | return false; |
---|
2034 | if ( is_wp_error( $ids ) ) |
---|
2035 | return $ids; |
---|
2036 | |
---|
2037 | $tt_id = $ids['term_taxonomy_id']; |
---|
2038 | |
---|
2039 | $defaults = array(); |
---|
2040 | |
---|
2041 | if ( 'category' == $taxonomy ) { |
---|
2042 | $defaults['default'] = get_option( 'default_category' ); |
---|
2043 | if ( $defaults['default'] == $term ) |
---|
2044 | return 0; // Don't delete the default category |
---|
2045 | } |
---|
2046 | |
---|
2047 | $args = wp_parse_args($args, $defaults); |
---|
2048 | |
---|
2049 | if ( isset( $args['default'] ) ) { |
---|
2050 | $default = (int) $args['default']; |
---|
2051 | if ( ! term_exists( $default, $taxonomy ) ) { |
---|
2052 | unset( $default ); |
---|
2053 | } |
---|
2054 | } |
---|
2055 | |
---|
2056 | if ( isset( $args['force_default'] ) ) { |
---|
2057 | $force_default = $args['force_default']; |
---|
2058 | } |
---|
2059 | |
---|
2060 | // Update children to point to new parent |
---|
2061 | if ( is_taxonomy_hierarchical($taxonomy) ) { |
---|
2062 | $term_obj = get_term($term, $taxonomy); |
---|
2063 | if ( is_wp_error( $term_obj ) ) |
---|
2064 | return $term_obj; |
---|
2065 | $parent = $term_obj->parent; |
---|
2066 | |
---|
2067 | $edit_tt_ids = $wpdb->get_col( "SELECT `term_taxonomy_id` FROM $wpdb->term_taxonomy WHERE `parent` = " . (int)$term_obj->term_id ); |
---|
2068 | |
---|
2069 | /** |
---|
2070 | * Fires immediately before a term to delete's children are reassigned a parent. |
---|
2071 | * |
---|
2072 | * @since 2.9.0 |
---|
2073 | * |
---|
2074 | * @param array $edit_tt_ids An array of term taxonomy IDs for the given term. |
---|
2075 | */ |
---|
2076 | do_action( 'edit_term_taxonomies', $edit_tt_ids ); |
---|
2077 | $wpdb->update( $wpdb->term_taxonomy, compact( 'parent' ), array( 'parent' => $term_obj->term_id) + compact( 'taxonomy' ) ); |
---|
2078 | |
---|
2079 | /** |
---|
2080 | * Fires immediately after a term to delete's children are reassigned a parent. |
---|
2081 | * |
---|
2082 | * @since 2.9.0 |
---|
2083 | * |
---|
2084 | * @param array $edit_tt_ids An array of term taxonomy IDs for the given term. |
---|
2085 | */ |
---|
2086 | do_action( 'edited_term_taxonomies', $edit_tt_ids ); |
---|
2087 | } |
---|
2088 | |
---|
2089 | $objects = $wpdb->get_col( $wpdb->prepare( "SELECT object_id FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d", $tt_id ) ); |
---|
2090 | |
---|
2091 | foreach ( (array) $objects as $object ) { |
---|
2092 | $terms = wp_get_object_terms($object, $taxonomy, array('fields' => 'ids', 'orderby' => 'none')); |
---|
2093 | if ( 1 == count($terms) && isset($default) ) { |
---|
2094 | $terms = array($default); |
---|
2095 | } else { |
---|
2096 | $terms = array_diff($terms, array($term)); |
---|
2097 | if (isset($default) && isset($force_default) && $force_default) |
---|
2098 | $terms = array_merge($terms, array($default)); |
---|
2099 | } |
---|
2100 | $terms = array_map('intval', $terms); |
---|
2101 | wp_set_object_terms($object, $terms, $taxonomy); |
---|
2102 | } |
---|
2103 | |
---|
2104 | // Clean the relationship caches for all object types using this term |
---|
2105 | $tax_object = get_taxonomy( $taxonomy ); |
---|
2106 | foreach ( $tax_object->object_type as $object_type ) |
---|
2107 | clean_object_term_cache( $objects, $object_type ); |
---|
2108 | |
---|
2109 | // Get the object before deletion so we can pass to actions below |
---|
2110 | $deleted_term = get_term( $term, $taxonomy ); |
---|
2111 | |
---|
2112 | /** |
---|
2113 | * Fires immediately before a term taxonomy ID is deleted. |
---|
2114 | * |
---|
2115 | * @since 2.9.0 |
---|
2116 | * |
---|
2117 | * @param int $tt_id Term taxonomy ID. |
---|
2118 | */ |
---|
2119 | do_action( 'delete_term_taxonomy', $tt_id ); |
---|
2120 | $wpdb->delete( $wpdb->term_taxonomy, array( 'term_taxonomy_id' => $tt_id ) ); |
---|
2121 | |
---|
2122 | /** |
---|
2123 | * Fires immediately after a term taxonomy ID is deleted. |
---|
2124 | * |
---|
2125 | * @since 2.9.0 |
---|
2126 | * |
---|
2127 | * @param int $tt_id Term taxonomy ID. |
---|
2128 | */ |
---|
2129 | do_action( 'deleted_term_taxonomy', $tt_id ); |
---|
2130 | |
---|
2131 | // Delete the term if no taxonomies use it. |
---|
2132 | if ( !$wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_taxonomy WHERE term_id = %d", $term) ) ) |
---|
2133 | $wpdb->delete( $wpdb->terms, array( 'term_id' => $term ) ); |
---|
2134 | |
---|
2135 | clean_term_cache($term, $taxonomy); |
---|
2136 | |
---|
2137 | /** |
---|
2138 | * Fires after a term is deleted from the database and the cache is cleaned. |
---|
2139 | * |
---|
2140 | * @since 2.5.0 |
---|
2141 | * |
---|
2142 | * @param int $term Term ID. |
---|
2143 | * @param int $tt_id Term taxonomy ID. |
---|
2144 | * @param string $taxonomy Taxonomy slug. |
---|
2145 | * @param mixed $deleted_term Copy of the already-deleted term, in the form specified |
---|
2146 | * by the parent function. WP_Error otherwise. |
---|
2147 | */ |
---|
2148 | do_action( 'delete_term', $term, $tt_id, $taxonomy, $deleted_term ); |
---|
2149 | |
---|
2150 | /** |
---|
2151 | * Fires after a term in a specific taxonomy is deleted. |
---|
2152 | * |
---|
2153 | * The dynamic portion of the hook name, $taxonomy, refers to the specific |
---|
2154 | * taxonomy the term belonged to. |
---|
2155 | * |
---|
2156 | * @since 2.3.0 |
---|
2157 | * |
---|
2158 | * @param int $term Term ID. |
---|
2159 | * @param int $tt_id Term taxonomy ID. |
---|
2160 | * @param mixed $deleted_term Copy of the already-deleted term, in the form specified |
---|
2161 | * by the parent function. WP_Error otherwise. |
---|
2162 | */ |
---|
2163 | do_action( "delete_$taxonomy", $term, $tt_id, $deleted_term ); |
---|
2164 | |
---|
2165 | return true; |
---|
2166 | } |
---|
2167 | |
---|
2168 | /** |
---|
2169 | * Deletes one existing category. |
---|
2170 | * |
---|
2171 | * @since 2.0.0 |
---|
2172 | * @uses wp_delete_term() |
---|
2173 | * |
---|
2174 | * @param int $cat_ID |
---|
2175 | * @return mixed Returns true if completes delete action; false if term doesn't exist; |
---|
2176 | * Zero on attempted deletion of default Category; WP_Error object is also a possibility. |
---|
2177 | */ |
---|
2178 | function wp_delete_category( $cat_ID ) { |
---|
2179 | return wp_delete_term( $cat_ID, 'category' ); |
---|
2180 | } |
---|
2181 | |
---|
2182 | /** |
---|
2183 | * Retrieves the terms associated with the given object(s), in the supplied taxonomies. |
---|
2184 | * |
---|
2185 | * The following information has to do the $args parameter and for what can be |
---|
2186 | * contained in the string or array of that parameter, if it exists. |
---|
2187 | * |
---|
2188 | * The first argument is called, 'orderby' and has the default value of 'name'. |
---|
2189 | * The other value that is supported is 'count'. |
---|
2190 | * |
---|
2191 | * The second argument is called, 'order' and has the default value of 'ASC'. |
---|
2192 | * The only other value that will be acceptable is 'DESC'. |
---|
2193 | * |
---|
2194 | * The final argument supported is called, 'fields' and has the default value of |
---|
2195 | * 'all'. There are multiple other options that can be used instead. Supported |
---|
2196 | * values are as follows: 'all', 'ids', 'names', and finally |
---|
2197 | * 'all_with_object_id'. |
---|
2198 | * |
---|
2199 | * The fields argument also decides what will be returned. If 'all' or |
---|
2200 | * 'all_with_object_id' is chosen or the default kept intact, then all matching |
---|
2201 | * terms objects will be returned. If either 'ids' or 'names' is used, then an |
---|
2202 | * array of all matching term ids or term names will be returned respectively. |
---|
2203 | * |
---|
2204 | * @since 2.3.0 |
---|
2205 | * @uses $wpdb |
---|
2206 | * |
---|
2207 | * @param int|array $object_ids The ID(s) of the object(s) to retrieve. |
---|
2208 | * @param string|array $taxonomies The taxonomies to retrieve terms from. |
---|
2209 | * @param array|string $args Change what is returned |
---|
2210 | * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if any of the $taxonomies don't exist. |
---|
2211 | */ |
---|
2212 | function wp_get_object_terms($object_ids, $taxonomies, $args = array()) { |
---|
2213 | global $wpdb; |
---|
2214 | |
---|
2215 | if ( empty( $object_ids ) || empty( $taxonomies ) ) |
---|
2216 | return array(); |
---|
2217 | |
---|
2218 | if ( !is_array($taxonomies) ) |
---|
2219 | $taxonomies = array($taxonomies); |
---|
2220 | |
---|
2221 | foreach ( $taxonomies as $taxonomy ) { |
---|
2222 | if ( ! taxonomy_exists($taxonomy) ) |
---|
2223 | return new WP_Error('invalid_taxonomy', __('Invalid taxonomy')); |
---|
2224 | } |
---|
2225 | |
---|
2226 | if ( !is_array($object_ids) ) |
---|
2227 | $object_ids = array($object_ids); |
---|
2228 | $object_ids = array_map('intval', $object_ids); |
---|
2229 | |
---|
2230 | $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all'); |
---|
2231 | $args = wp_parse_args( $args, $defaults ); |
---|
2232 | |
---|
2233 | $terms = array(); |
---|
2234 | if ( count($taxonomies) > 1 ) { |
---|
2235 | foreach ( $taxonomies as $index => $taxonomy ) { |
---|
2236 | $t = get_taxonomy($taxonomy); |
---|
2237 | if ( isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args) ) { |
---|
2238 | unset($taxonomies[$index]); |
---|
2239 | $terms = array_merge($terms, wp_get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args))); |
---|
2240 | } |
---|
2241 | } |
---|
2242 | } else { |
---|
2243 | $t = get_taxonomy($taxonomies[0]); |
---|
2244 | if ( isset($t->args) && is_array($t->args) ) |
---|
2245 | $args = array_merge($args, $t->args); |
---|
2246 | } |
---|
2247 | |
---|
2248 | $orderby = $args['orderby']; |
---|
2249 | $order = $args['order']; |
---|
2250 | $fields = $args['fields']; |
---|
2251 | |
---|
2252 | if ( 'count' == $orderby ) |
---|
2253 | $orderby = 'tt.count'; |
---|
2254 | else if ( 'name' == $orderby ) |
---|
2255 | $orderby = 't.name'; |
---|
2256 | else if ( 'slug' == $orderby ) |
---|
2257 | $orderby = 't.slug'; |
---|
2258 | else if ( 'term_group' == $orderby ) |
---|
2259 | $orderby = 't.term_group'; |
---|
2260 | else if ( 'term_order' == $orderby ) |
---|
2261 | $orderby = 'tr.term_order'; |
---|
2262 | else if ( 'none' == $orderby ) { |
---|
2263 | $orderby = ''; |
---|
2264 | $order = ''; |
---|
2265 | } else { |
---|
2266 | $orderby = 't.term_id'; |
---|
2267 | } |
---|
2268 | |
---|
2269 | // tt_ids queries can only be none or tr.term_taxonomy_id |
---|
2270 | if ( ('tt_ids' == $fields) && !empty($orderby) ) |
---|
2271 | $orderby = 'tr.term_taxonomy_id'; |
---|
2272 | |
---|
2273 | if ( !empty($orderby) ) |
---|
2274 | $orderby = "ORDER BY $orderby"; |
---|
2275 | |
---|
2276 | $order = strtoupper( $order ); |
---|
2277 | if ( '' !== $order && ! in_array( $order, array( 'ASC', 'DESC' ) ) ) |
---|
2278 | $order = 'ASC'; |
---|
2279 | |
---|
2280 | $taxonomies = "'" . implode("', '", $taxonomies) . "'"; |
---|
2281 | $object_ids = implode(', ', $object_ids); |
---|
2282 | |
---|
2283 | $select_this = ''; |
---|
2284 | if ( 'all' == $fields ) |
---|
2285 | $select_this = 't.*, tt.*'; |
---|
2286 | else if ( 'ids' == $fields ) |
---|
2287 | $select_this = 't.term_id'; |
---|
2288 | else if ( 'names' == $fields ) |
---|
2289 | $select_this = 't.name'; |
---|
2290 | else if ( 'slugs' == $fields ) |
---|
2291 | $select_this = 't.slug'; |
---|
2292 | else if ( 'all_with_object_id' == $fields ) |
---|
2293 | $select_this = 't.*, tt.*, tr.object_id'; |
---|
2294 | |
---|
2295 | $query = "SELECT $select_this FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN $wpdb->term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ($taxonomies) AND tr.object_id IN ($object_ids) $orderby $order"; |
---|
2296 | |
---|
2297 | $objects = false; |
---|
2298 | if ( 'all' == $fields || 'all_with_object_id' == $fields ) { |
---|
2299 | $_terms = $wpdb->get_results( $query ); |
---|
2300 | foreach ( $_terms as $key => $term ) { |
---|
2301 | $_terms[$key] = sanitize_term( $term, $taxonomy, 'raw' ); |
---|
2302 | } |
---|
2303 | $terms = array_merge( $terms, $_terms ); |
---|
2304 | update_term_cache( $terms ); |
---|
2305 | $objects = true; |
---|
2306 | } else if ( 'ids' == $fields || 'names' == $fields || 'slugs' == $fields ) { |
---|
2307 | $_terms = $wpdb->get_col( $query ); |
---|
2308 | $_field = ( 'ids' == $fields ) ? 'term_id' : 'name'; |
---|
2309 | foreach ( $_terms as $key => $term ) { |
---|
2310 | $_terms[$key] = sanitize_term_field( $_field, $term, $term, $taxonomy, 'raw' ); |
---|
2311 | } |
---|
2312 | $terms = array_merge( $terms, $_terms ); |
---|
2313 | } else if ( 'tt_ids' == $fields ) { |
---|
2314 | $terms = $wpdb->get_col("SELECT tr.term_taxonomy_id FROM $wpdb->term_relationships AS tr INNER JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tr.object_id IN ($object_ids) AND tt.taxonomy IN ($taxonomies) $orderby $order"); |
---|
2315 | foreach ( $terms as $key => $tt_id ) { |
---|
2316 | $terms[$key] = sanitize_term_field( 'term_taxonomy_id', $tt_id, 0, $taxonomy, 'raw' ); // 0 should be the term id, however is not needed when using raw context. |
---|
2317 | } |
---|
2318 | } |
---|
2319 | |
---|
2320 | if ( ! $terms ) { |
---|
2321 | $terms = array(); |
---|
2322 | } elseif ( $objects && 'all_with_object_id' !== $fields ) { |
---|
2323 | $_tt_ids = array(); |
---|
2324 | $_terms = array(); |
---|
2325 | foreach ( $terms as $term ) { |
---|
2326 | if ( in_array( $term->term_taxonomy_id, $_tt_ids ) ) { |
---|
2327 | continue; |
---|
2328 | } |
---|
2329 | |
---|
2330 | $_tt_ids[] = $term->term_taxonomy_id; |
---|
2331 | $_terms[] = $term; |
---|
2332 | } |
---|
2333 | $terms = $_terms; |
---|
2334 | } elseif ( ! $objects ) { |
---|
2335 | $terms = array_values( array_unique( $terms ) ); |
---|
2336 | } |
---|
2337 | /** |
---|
2338 | * Filter the terms for a given object or objects. |
---|
2339 | * |
---|
2340 | * @since 2.8.0 |
---|
2341 | * |
---|
2342 | * @param array $terms An array of terms for the given object or objects. |
---|
2343 | * @param array|int $object_ids Object ID or array of IDs. |
---|
2344 | * @param array|string $taxonomies A taxonomy or array of taxonomies. |
---|
2345 | * @param array $args An array of arguments for retrieving terms for |
---|
2346 | * the given object(s). |
---|
2347 | */ |
---|
2348 | return apply_filters( 'wp_get_object_terms', $terms, $object_ids, $taxonomies, $args ); |
---|
2349 | } |
---|
2350 | |
---|
2351 | /** |
---|
2352 | * Add a new term to the database. |
---|
2353 | * |
---|
2354 | * A non-existent term is inserted in the following sequence: |
---|
2355 | * 1. The term is added to the term table, then related to the taxonomy. |
---|
2356 | * 2. If everything is correct, several actions are fired. |
---|
2357 | * 3. The 'term_id_filter' is evaluated. |
---|
2358 | * 4. The term cache is cleaned. |
---|
2359 | * 5. Several more actions are fired. |
---|
2360 | * 6. An array is returned containing the term_id and term_taxonomy_id. |
---|
2361 | * |
---|
2362 | * If the 'slug' argument is not empty, then it is checked to see if the term |
---|
2363 | * is invalid. If it is not a valid, existing term, it is added and the term_id |
---|
2364 | * is given. |
---|
2365 | * |
---|
2366 | * If the taxonomy is hierarchical, and the 'parent' argument is not empty, |
---|
2367 | * the term is inserted and the term_id will be given. |
---|
2368 | |
---|
2369 | * Error handling: |
---|
2370 | * If $taxonomy does not exist or $term is empty, |
---|
2371 | * a WP_Error object will be returned. |
---|
2372 | * |
---|
2373 | * If the term already exists on the same hierarchical level, |
---|
2374 | * or the term slug and name are not unique, a WP_Error object will be returned. |
---|
2375 | * |
---|
2376 | * @global wpdb $wpdb The WordPress database object. |
---|
2377 | |
---|
2378 | * @since 2.3.0 |
---|
2379 | * |
---|
2380 | * @param string $term The term to add or update. |
---|
2381 | * @param string $taxonomy The taxonomy to which to add the term |
---|
2382 | * @param array|string $args { |
---|
2383 | * Arguments to change values of the inserted term. |
---|
2384 | * |
---|
2385 | * @type string 'alias_of' Slug of the term to make this term an alias of. |
---|
2386 | * Default empty string. Accepts a term slug. |
---|
2387 | * @type string 'description' The term description. |
---|
2388 | * Default empty string. |
---|
2389 | * @type int 'parent' The id of the parent term. |
---|
2390 | * Default 0. |
---|
2391 | * @type string 'slug' The term slug to use. |
---|
2392 | * Default empty string. |
---|
2393 | * } |
---|
2394 | * @return array|WP_Error An array containing the term_id and term_taxonomy_id, WP_Error otherwise. |
---|
2395 | */ |
---|
2396 | function wp_insert_term( $term, $taxonomy, $args = array() ) { |
---|
2397 | global $wpdb; |
---|
2398 | |
---|
2399 | if ( ! taxonomy_exists($taxonomy) ) { |
---|
2400 | return new WP_Error('invalid_taxonomy', __('Invalid taxonomy')); |
---|
2401 | } |
---|
2402 | /** |
---|
2403 | * Filter a term before it is sanitized and inserted into the database. |
---|
2404 | * |
---|
2405 | * @since 3.0.0 |
---|
2406 | * |
---|
2407 | * @param string $term The term to add or update. |
---|
2408 | * @param string $taxonomy Taxonomy slug. |
---|
2409 | */ |
---|
2410 | $term = apply_filters( 'pre_insert_term', $term, $taxonomy ); |
---|
2411 | if ( is_wp_error( $term ) ) { |
---|
2412 | return $term; |
---|
2413 | } |
---|
2414 | if ( is_int($term) && 0 == $term ) { |
---|
2415 | return new WP_Error('invalid_term_id', __('Invalid term ID')); |
---|
2416 | } |
---|
2417 | if ( '' == trim($term) ) { |
---|
2418 | return new WP_Error('empty_term_name', __('A name is required for this term')); |
---|
2419 | } |
---|
2420 | $defaults = array( 'alias_of' => '', 'description' => '', 'parent' => 0, 'slug' => ''); |
---|
2421 | $args = wp_parse_args( $args, $defaults ); |
---|
2422 | |
---|
2423 | if ( $args['parent'] > 0 && ! term_exists( (int) $args['parent'] ) ) { |
---|
2424 | return new WP_Error( 'missing_parent', __( 'Parent term does not exist.' ) ); |
---|
2425 | } |
---|
2426 | $args['name'] = $term; |
---|
2427 | $args['taxonomy'] = $taxonomy; |
---|
2428 | $args = sanitize_term($args, $taxonomy, 'db'); |
---|
2429 | |
---|
2430 | // expected_slashed ($name) |
---|
2431 | $name = wp_unslash( $args['name'] ); |
---|
2432 | $description = wp_unslash( $args['description'] ); |
---|
2433 | $parent = (int) $args['parent']; |
---|
2434 | |
---|
2435 | $slug_provided = ! empty( $args['slug'] ); |
---|
2436 | if ( ! $slug_provided ) { |
---|
2437 | $_name = trim( $name ); |
---|
2438 | $existing_term = get_term_by( 'name', $_name, $taxonomy ); |
---|
2439 | if ( $existing_term ) { |
---|
2440 | $slug = $existing_term->slug; |
---|
2441 | } else { |
---|
2442 | $slug = sanitize_title( $name ); |
---|
2443 | } |
---|
2444 | } else { |
---|
2445 | $slug = $args['slug']; |
---|
2446 | } |
---|
2447 | |
---|
2448 | $term_group = 0; |
---|
2449 | if ( $args['alias_of'] ) { |
---|
2450 | $alias = $wpdb->get_row( $wpdb->prepare( "SELECT term_id, term_group FROM $wpdb->terms WHERE slug = %s", $args['alias_of'] ) ); |
---|
2451 | if ( $alias->term_group ) { |
---|
2452 | // The alias we want is already in a group, so let's use that one. |
---|
2453 | $term_group = $alias->term_group; |
---|
2454 | } else { |
---|
2455 | // The alias isn't in a group, so let's create a new one and firstly add the alias term to it. |
---|
2456 | $term_group = $wpdb->get_var("SELECT MAX(term_group) FROM $wpdb->terms") + 1; |
---|
2457 | |
---|
2458 | /** |
---|
2459 | * Fires immediately before the given terms are edited. |
---|
2460 | * |
---|
2461 | * @since 2.9.0 |
---|
2462 | * |
---|
2463 | * @param int $term_id Term ID. |
---|
2464 | * @param string $taxonomy Taxonomy slug. |
---|
2465 | */ |
---|
2466 | do_action( 'edit_terms', $alias->term_id, $taxonomy ); |
---|
2467 | $wpdb->update($wpdb->terms, compact('term_group'), array('term_id' => $alias->term_id) ); |
---|
2468 | |
---|
2469 | /** |
---|
2470 | * Fires immediately after the given terms are edited. |
---|
2471 | * |
---|
2472 | * @since 2.9.0 |
---|
2473 | * |
---|
2474 | * @param int $term_id Term ID |
---|
2475 | * @param string $taxonomy Taxonomy slug. |
---|
2476 | */ |
---|
2477 | do_action( 'edited_terms', $alias->term_id, $taxonomy ); |
---|
2478 | } |
---|
2479 | } |
---|
2480 | |
---|
2481 | if ( $term_id = term_exists($slug) ) { |
---|
2482 | $existing_term = $wpdb->get_row( $wpdb->prepare( "SELECT name FROM $wpdb->terms WHERE term_id = %d", $term_id), ARRAY_A ); |
---|
2483 | // We've got an existing term in the same taxonomy, which matches the name of the new term: |
---|
2484 | if ( is_taxonomy_hierarchical($taxonomy) && $existing_term['name'] == $name && $exists = term_exists( (int) $term_id, $taxonomy ) ) { |
---|
2485 | // Hierarchical, and it matches an existing term, Do not allow same "name" in the same level. |
---|
2486 | $siblings = get_terms($taxonomy, array('fields' => 'names', 'get' => 'all', 'parent' => $parent ) ); |
---|
2487 | if ( in_array($name, $siblings) ) { |
---|
2488 | if ( $slug_provided ) { |
---|
2489 | return new WP_Error( 'term_exists', __( 'A term with the name and slug provided already exists with this parent.' ), $exists['term_id'] ); |
---|
2490 | } else { |
---|
2491 | return new WP_Error( 'term_exists', __( 'A term with the name provided already exists with this parent.' ), $exists['term_id'] ); |
---|
2492 | } |
---|
2493 | } else { |
---|
2494 | $slug = wp_unique_term_slug($slug, (object) $args); |
---|
2495 | if ( false === $wpdb->insert( $wpdb->terms, compact( 'name', 'slug', 'term_group' ) ) ) { |
---|
2496 | return new WP_Error('db_insert_error', __('Could not insert term into the database'), $wpdb->last_error); |
---|
2497 | } |
---|
2498 | $term_id = (int) $wpdb->insert_id; |
---|
2499 | } |
---|
2500 | } elseif ( $existing_term['name'] != $name ) { |
---|
2501 | // We've got an existing term, with a different name, Create the new term. |
---|
2502 | $slug = wp_unique_term_slug($slug, (object) $args); |
---|
2503 | if ( false === $wpdb->insert( $wpdb->terms, compact( 'name', 'slug', 'term_group' ) ) ) { |
---|
2504 | return new WP_Error('db_insert_error', __('Could not insert term into the database'), $wpdb->last_error); |
---|
2505 | } |
---|
2506 | $term_id = (int) $wpdb->insert_id; |
---|
2507 | } elseif ( $exists = term_exists( (int) $term_id, $taxonomy ) ) { |
---|
2508 | // Same name, same slug. |
---|
2509 | return new WP_Error( 'term_exists', __( 'A term with the name and slug provided already exists.' ), $exists['term_id'] ); |
---|
2510 | } |
---|
2511 | } else { |
---|
2512 | // This term does not exist at all in the database, Create it. |
---|
2513 | $slug = wp_unique_term_slug($slug, (object) $args); |
---|
2514 | if ( false === $wpdb->insert( $wpdb->terms, compact( 'name', 'slug', 'term_group' ) ) ) { |
---|
2515 | return new WP_Error('db_insert_error', __('Could not insert term into the database'), $wpdb->last_error); |
---|
2516 | } |
---|
2517 | $term_id = (int) $wpdb->insert_id; |
---|
2518 | } |
---|
2519 | |
---|
2520 | // Seems unreachable, However, Is used in the case that a term name is provided, which sanitizes to an empty string. |
---|
2521 | if ( empty($slug) ) { |
---|
2522 | $slug = sanitize_title($slug, $term_id); |
---|
2523 | |
---|
2524 | /** This action is documented in wp-includes/taxonomy.php */ |
---|
2525 | do_action( 'edit_terms', $term_id, $taxonomy ); |
---|
2526 | $wpdb->update( $wpdb->terms, compact( 'slug' ), compact( 'term_id' ) ); |
---|
2527 | |
---|
2528 | /** This action is documented in wp-includes/taxonomy.php */ |
---|
2529 | do_action( 'edited_terms', $term_id, $taxonomy ); |
---|
2530 | } |
---|
2531 | |
---|
2532 | $tt_id = $wpdb->get_var( $wpdb->prepare( "SELECT tt.term_taxonomy_id FROM $wpdb->term_taxonomy AS tt INNER JOIN $wpdb->terms AS t ON tt.term_id = t.term_id WHERE tt.taxonomy = %s AND t.term_id = %d", $taxonomy, $term_id ) ); |
---|
2533 | |
---|
2534 | if ( !empty($tt_id) ) { |
---|
2535 | return array('term_id' => $term_id, 'term_taxonomy_id' => $tt_id); |
---|
2536 | } |
---|
2537 | $wpdb->insert( $wpdb->term_taxonomy, compact( 'term_id', 'taxonomy', 'description', 'parent') + array( 'count' => 0 ) ); |
---|
2538 | $tt_id = (int) $wpdb->insert_id; |
---|
2539 | |
---|
2540 | /** |
---|
2541 | * Fires immediately after a new term is created, before the term cache is cleaned. |
---|
2542 | * |
---|
2543 | * @since 2.3.0 |
---|
2544 | * |
---|
2545 | * @param int $term_id Term ID. |
---|
2546 | * @param int $tt_id Term taxonomy ID. |
---|
2547 | * @param string $taxonomy Taxonomy slug. |
---|
2548 | */ |
---|
2549 | do_action( "create_term", $term_id, $tt_id, $taxonomy ); |
---|
2550 | |
---|
2551 | /** |
---|
2552 | * Fires after a new term is created for a specific taxonomy. |
---|
2553 | * |
---|
2554 | * The dynamic portion of the hook name, $taxonomy, refers |
---|
2555 | * to the slug of the taxonomy the term was created for. |
---|
2556 | * |
---|
2557 | * @since 2.3.0 |
---|
2558 | * |
---|
2559 | * @param int $term_id Term ID. |
---|
2560 | * @param int $tt_id Term taxonomy ID. |
---|
2561 | */ |
---|
2562 | do_action( "create_$taxonomy", $term_id, $tt_id ); |
---|
2563 | |
---|
2564 | /** |
---|
2565 | * Filter the term ID after a new term is created. |
---|
2566 | * |
---|
2567 | * @since 2.3.0 |
---|
2568 | * |
---|
2569 | * @param int $term_id Term ID. |
---|
2570 | * @param int $tt_id Taxonomy term ID. |
---|
2571 | */ |
---|
2572 | $term_id = apply_filters( 'term_id_filter', $term_id, $tt_id ); |
---|
2573 | |
---|
2574 | clean_term_cache($term_id, $taxonomy); |
---|
2575 | |
---|
2576 | /** |
---|
2577 | * Fires after a new term is created, and after the term cache has been cleaned. |
---|
2578 | * |
---|
2579 | * @since 2.3.0 |
---|
2580 | */ |
---|
2581 | do_action( "created_term", $term_id, $tt_id, $taxonomy ); |
---|
2582 | |
---|
2583 | /** |
---|
2584 | * Fires after a new term in a specific taxonomy is created, and after the term |
---|
2585 | * cache has been cleaned. |
---|
2586 | * |
---|
2587 | * @since 2.3.0 |
---|
2588 | * |
---|
2589 | * @param int $term_id Term ID. |
---|
2590 | * @param int $tt_id Term taxonomy ID. |
---|
2591 | */ |
---|
2592 | do_action( "created_$taxonomy", $term_id, $tt_id ); |
---|
2593 | |
---|
2594 | return array('term_id' => $term_id, 'term_taxonomy_id' => $tt_id); |
---|
2595 | } |
---|
2596 | |
---|
2597 | /** |
---|
2598 | * Create Term and Taxonomy Relationships. |
---|
2599 | * |
---|
2600 | * Relates an object (post, link etc) to a term and taxonomy type. Creates the |
---|
2601 | * term and taxonomy relationship if it doesn't already exist. Creates a term if |
---|
2602 | * it doesn't exist (using the slug). |
---|
2603 | * |
---|
2604 | * A relationship means that the term is grouped in or belongs to the taxonomy. |
---|
2605 | * A term has no meaning until it is given context by defining which taxonomy it |
---|
2606 | * exists under. |
---|
2607 | * |
---|
2608 | * @since 2.3.0 |
---|
2609 | * @uses wp_remove_object_terms() |
---|
2610 | * |
---|
2611 | * @param int $object_id The object to relate to. |
---|
2612 | * @param array|int|string $terms A single term slug, single term id, or array of either term slugs or ids. |
---|
2613 | * Will replace all existing related terms in this taxonomy. |
---|
2614 | * @param array|string $taxonomy The context in which to relate the term to the object. |
---|
2615 | * @param bool $append Optional. If false will delete difference of terms. Default false. |
---|
2616 | * @return array|WP_Error Affected Term IDs. |
---|
2617 | */ |
---|
2618 | function wp_set_object_terms( $object_id, $terms, $taxonomy, $append = false ) { |
---|
2619 | global $wpdb; |
---|
2620 | |
---|
2621 | $object_id = (int) $object_id; |
---|
2622 | |
---|
2623 | if ( ! taxonomy_exists($taxonomy) ) |
---|
2624 | return new WP_Error('invalid_taxonomy', __('Invalid taxonomy')); |
---|
2625 | |
---|
2626 | if ( !is_array($terms) ) |
---|
2627 | $terms = array($terms); |
---|
2628 | |
---|
2629 | if ( ! $append ) |
---|
2630 | $old_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'orderby' => 'none')); |
---|
2631 | else |
---|
2632 | $old_tt_ids = array(); |
---|
2633 | |
---|
2634 | $tt_ids = array(); |
---|
2635 | $term_ids = array(); |
---|
2636 | $new_tt_ids = array(); |
---|
2637 | |
---|
2638 | foreach ( (array) $terms as $term) { |
---|
2639 | if ( !strlen(trim($term)) ) |
---|
2640 | continue; |
---|
2641 | |
---|
2642 | if ( !$term_info = term_exists($term, $taxonomy) ) { |
---|
2643 | // Skip if a non-existent term ID is passed. |
---|
2644 | if ( is_int($term) ) |
---|
2645 | continue; |
---|
2646 | $term_info = wp_insert_term($term, $taxonomy); |
---|
2647 | } |
---|
2648 | if ( is_wp_error($term_info) ) |
---|
2649 | return $term_info; |
---|
2650 | $term_ids[] = $term_info['term_id']; |
---|
2651 | $tt_id = $term_info['term_taxonomy_id']; |
---|
2652 | $tt_ids[] = $tt_id; |
---|
2653 | |
---|
2654 | if ( $wpdb->get_var( $wpdb->prepare( "SELECT term_taxonomy_id FROM $wpdb->term_relationships WHERE object_id = %d AND term_taxonomy_id = %d", $object_id, $tt_id ) ) ) |
---|
2655 | continue; |
---|
2656 | |
---|
2657 | /** |
---|
2658 | * Fires immediately before an object-term relationship is added. |
---|
2659 | * |
---|
2660 | * @since 2.9.0 |
---|
2661 | * |
---|
2662 | * @param int $object_id Object ID. |
---|
2663 | * @param int $tt_id Term taxonomy ID. |
---|
2664 | */ |
---|
2665 | do_action( 'add_term_relationship', $object_id, $tt_id ); |
---|
2666 | $wpdb->insert( $wpdb->term_relationships, array( 'object_id' => $object_id, 'term_taxonomy_id' => $tt_id ) ); |
---|
2667 | |
---|
2668 | /** |
---|
2669 | * Fires immediately after an object-term relationship is added. |
---|
2670 | * |
---|
2671 | * @since 2.9.0 |
---|
2672 | * |
---|
2673 | * @param int $object_id Object ID. |
---|
2674 | * @param int $tt_id Term taxonomy ID. |
---|
2675 | */ |
---|
2676 | do_action( 'added_term_relationship', $object_id, $tt_id ); |
---|
2677 | $new_tt_ids[] = $tt_id; |
---|
2678 | } |
---|
2679 | |
---|
2680 | if ( $new_tt_ids ) |
---|
2681 | wp_update_term_count( $new_tt_ids, $taxonomy ); |
---|
2682 | |
---|
2683 | if ( ! $append ) { |
---|
2684 | $delete_tt_ids = array_diff( $old_tt_ids, $tt_ids ); |
---|
2685 | |
---|
2686 | if ( $delete_tt_ids ) { |
---|
2687 | $in_delete_tt_ids = "'" . implode( "', '", $delete_tt_ids ) . "'"; |
---|
2688 | $delete_term_ids = $wpdb->get_col( $wpdb->prepare( "SELECT tt.term_id FROM $wpdb->term_taxonomy AS tt WHERE tt.taxonomy = %s AND tt.term_taxonomy_id IN ($in_delete_tt_ids)", $taxonomy ) ); |
---|
2689 | $delete_term_ids = array_map( 'intval', $delete_term_ids ); |
---|
2690 | |
---|
2691 | $remove = wp_remove_object_terms( $object_id, $delete_term_ids, $taxonomy ); |
---|
2692 | if ( is_wp_error( $remove ) ) { |
---|
2693 | return $remove; |
---|
2694 | } |
---|
2695 | } |
---|
2696 | } |
---|
2697 | |
---|
2698 | $t = get_taxonomy($taxonomy); |
---|
2699 | if ( ! $append && isset($t->sort) && $t->sort ) { |
---|
2700 | $values = array(); |
---|
2701 | $term_order = 0; |
---|
2702 | $final_tt_ids = wp_get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids')); |
---|
2703 | foreach ( $tt_ids as $tt_id ) |
---|
2704 | if ( in_array($tt_id, $final_tt_ids) ) |
---|
2705 | $values[] = $wpdb->prepare( "(%d, %d, %d)", $object_id, $tt_id, ++$term_order); |
---|
2706 | if ( $values ) |
---|
2707 | if ( false === $wpdb->query( "INSERT INTO $wpdb->term_relationships (object_id, term_taxonomy_id, term_order) VALUES " . join( ',', $values ) . " ON DUPLICATE KEY UPDATE term_order = VALUES(term_order)" ) ) |
---|
2708 | return new WP_Error( 'db_insert_error', __( 'Could not insert term relationship into the database' ), $wpdb->last_error ); |
---|
2709 | } |
---|
2710 | |
---|
2711 | wp_cache_delete( $object_id, $taxonomy . '_relationships' ); |
---|
2712 | |
---|
2713 | /** |
---|
2714 | * Fires after an object's terms have been set. |
---|
2715 | * |
---|
2716 | * @since 2.8.0 |
---|
2717 | * |
---|
2718 | * @param int $object_id Object ID. |
---|
2719 | * @param array $terms An array of object terms. |
---|
2720 | * @param array $tt_ids An array of term taxonomy IDs. |
---|
2721 | * @param string $taxonomy Taxonomy slug. |
---|
2722 | * @param bool $append Whether to append new terms to the old terms. |
---|
2723 | * @param array $old_tt_ids Old array of term taxonomy IDs. |
---|
2724 | */ |
---|
2725 | do_action( 'set_object_terms', $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids ); |
---|
2726 | return $tt_ids; |
---|
2727 | } |
---|
2728 | |
---|
2729 | /** |
---|
2730 | * Add term(s) associated with a given object. |
---|
2731 | * |
---|
2732 | * @since 3.6.0 |
---|
2733 | * @uses wp_set_object_terms() |
---|
2734 | * |
---|
2735 | * @param int $object_id The ID of the object to which the terms will be added. |
---|
2736 | * @param array|int|string $terms The slug(s) or ID(s) of the term(s) to add. |
---|
2737 | * @param array|string $taxonomy Taxonomy name. |
---|
2738 | * @return array|WP_Error Affected Term IDs |
---|
2739 | */ |
---|
2740 | function wp_add_object_terms( $object_id, $terms, $taxonomy ) { |
---|
2741 | return wp_set_object_terms( $object_id, $terms, $taxonomy, true ); |
---|
2742 | } |
---|
2743 | |
---|
2744 | /** |
---|
2745 | * Remove term(s) associated with a given object. |
---|
2746 | * |
---|
2747 | * @since 3.6.0 |
---|
2748 | * @uses $wpdb |
---|
2749 | * |
---|
2750 | * @param int $object_id The ID of the object from which the terms will be removed. |
---|
2751 | * @param array|int|string $terms The slug(s) or ID(s) of the term(s) to remove. |
---|
2752 | * @param array|string $taxonomy Taxonomy name. |
---|
2753 | * @return bool|WP_Error True on success, false or WP_Error on failure. |
---|
2754 | */ |
---|
2755 | function wp_remove_object_terms( $object_id, $terms, $taxonomy ) { |
---|
2756 | global $wpdb; |
---|
2757 | |
---|
2758 | $object_id = (int) $object_id; |
---|
2759 | |
---|
2760 | if ( ! taxonomy_exists( $taxonomy ) ) { |
---|
2761 | return new WP_Error( 'invalid_taxonomy', __( 'Invalid Taxonomy' ) ); |
---|
2762 | } |
---|
2763 | |
---|
2764 | if ( ! is_array( $terms ) ) { |
---|
2765 | $terms = array( $terms ); |
---|
2766 | } |
---|
2767 | |
---|
2768 | $tt_ids = array(); |
---|
2769 | |
---|
2770 | foreach ( (array) $terms as $term ) { |
---|
2771 | if ( ! strlen( trim( $term ) ) ) { |
---|
2772 | continue; |
---|
2773 | } |
---|
2774 | |
---|
2775 | if ( ! $term_info = term_exists( $term, $taxonomy ) ) { |
---|
2776 | // Skip if a non-existent term ID is passed. |
---|
2777 | if ( is_int( $term ) ) { |
---|
2778 | continue; |
---|
2779 | } |
---|
2780 | } |
---|
2781 | |
---|
2782 | if ( is_wp_error( $term_info ) ) { |
---|
2783 | return $term_info; |
---|
2784 | } |
---|
2785 | |
---|
2786 | $tt_ids[] = $term_info['term_taxonomy_id']; |
---|
2787 | } |
---|
2788 | |
---|
2789 | if ( $tt_ids ) { |
---|
2790 | $in_tt_ids = "'" . implode( "', '", $tt_ids ) . "'"; |
---|
2791 | |
---|
2792 | /** |
---|
2793 | * Fires immediately before an object-term relationship is deleted. |
---|
2794 | * |
---|
2795 | * @since 2.9.0 |
---|
2796 | * |
---|
2797 | * @param int $object_id Object ID. |
---|
2798 | * @param array $tt_ids An array of term taxonomy IDs. |
---|
2799 | */ |
---|
2800 | do_action( 'delete_term_relationships', $object_id, $tt_ids ); |
---|
2801 | $deleted = $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->term_relationships WHERE object_id = %d AND term_taxonomy_id IN ($in_tt_ids)", $object_id ) ); |
---|
2802 | |
---|
2803 | /** |
---|
2804 | * Fires immediately after an object-term relationship is deleted. |
---|
2805 | * |
---|
2806 | * @since 2.9.0 |
---|
2807 | * |
---|
2808 | * @param int $object_id Object ID. |
---|
2809 | * @param array $tt_ids An array of term taxonomy IDs. |
---|
2810 | */ |
---|
2811 | do_action( 'deleted_term_relationships', $object_id, $tt_ids ); |
---|
2812 | wp_update_term_count( $tt_ids, $taxonomy ); |
---|
2813 | |
---|
2814 | return (bool) $deleted; |
---|
2815 | } |
---|
2816 | |
---|
2817 | return false; |
---|
2818 | } |
---|
2819 | |
---|
2820 | /** |
---|
2821 | * Will make slug unique, if it isn't already. |
---|
2822 | * |
---|
2823 | * The $slug has to be unique global to every taxonomy, meaning that one |
---|
2824 | * taxonomy term can't have a matching slug with another taxonomy term. Each |
---|
2825 | * slug has to be globally unique for every taxonomy. |
---|
2826 | * |
---|
2827 | * The way this works is that if the taxonomy that the term belongs to is |
---|
2828 | * hierarchical and has a parent, it will append that parent to the $slug. |
---|
2829 | * |
---|
2830 | * If that still doesn't return an unique slug, then it try to append a number |
---|
2831 | * until it finds a number that is truly unique. |
---|
2832 | * |
---|
2833 | * The only purpose for $term is for appending a parent, if one exists. |
---|
2834 | * |
---|
2835 | * @since 2.3.0 |
---|
2836 | * @uses $wpdb |
---|
2837 | * |
---|
2838 | * @param string $slug The string that will be tried for a unique slug |
---|
2839 | * @param object $term The term object that the $slug will belong too |
---|
2840 | * @return string Will return a true unique slug. |
---|
2841 | */ |
---|
2842 | function wp_unique_term_slug($slug, $term) { |
---|
2843 | global $wpdb; |
---|
2844 | |
---|
2845 | if ( ! term_exists( $slug ) ) |
---|
2846 | return $slug; |
---|
2847 | |
---|
2848 | // If the taxonomy supports hierarchy and the term has a parent, make the slug unique |
---|
2849 | // by incorporating parent slugs. |
---|
2850 | if ( is_taxonomy_hierarchical($term->taxonomy) && !empty($term->parent) ) { |
---|
2851 | $the_parent = $term->parent; |
---|
2852 | while ( ! empty($the_parent) ) { |
---|
2853 | $parent_term = get_term($the_parent, $term->taxonomy); |
---|
2854 | if ( is_wp_error($parent_term) || empty($parent_term) ) |
---|
2855 | break; |
---|
2856 | $slug .= '-' . $parent_term->slug; |
---|
2857 | if ( ! term_exists( $slug ) ) |
---|
2858 | return $slug; |
---|
2859 | |
---|
2860 | if ( empty($parent_term->parent) ) |
---|
2861 | break; |
---|
2862 | $the_parent = $parent_term->parent; |
---|
2863 | } |
---|
2864 | } |
---|
2865 | |
---|
2866 | // If we didn't get a unique slug, try appending a number to make it unique. |
---|
2867 | if ( ! empty( $term->term_id ) ) |
---|
2868 | $query = $wpdb->prepare( "SELECT slug FROM $wpdb->terms WHERE slug = %s AND term_id != %d", $slug, $term->term_id ); |
---|
2869 | else |
---|
2870 | $query = $wpdb->prepare( "SELECT slug FROM $wpdb->terms WHERE slug = %s", $slug ); |
---|
2871 | |
---|
2872 | if ( $wpdb->get_var( $query ) ) { |
---|
2873 | $num = 2; |
---|
2874 | do { |
---|
2875 | $alt_slug = $slug . "-$num"; |
---|
2876 | $num++; |
---|
2877 | $slug_check = $wpdb->get_var( $wpdb->prepare( "SELECT slug FROM $wpdb->terms WHERE slug = %s", $alt_slug ) ); |
---|
2878 | } while ( $slug_check ); |
---|
2879 | $slug = $alt_slug; |
---|
2880 | } |
---|
2881 | |
---|
2882 | return $slug; |
---|
2883 | } |
---|
2884 | |
---|
2885 | /** |
---|
2886 | * Update term based on arguments provided. |
---|
2887 | * |
---|
2888 | * The $args will indiscriminately override all values with the same field name. |
---|
2889 | * Care must be taken to not override important information need to update or |
---|
2890 | * update will fail (or perhaps create a new term, neither would be acceptable). |
---|
2891 | * |
---|
2892 | * Defaults will set 'alias_of', 'description', 'parent', and 'slug' if not |
---|
2893 | * defined in $args already. |
---|
2894 | * |
---|
2895 | * 'alias_of' will create a term group, if it doesn't already exist, and update |
---|
2896 | * it for the $term. |
---|
2897 | * |
---|
2898 | * If the 'slug' argument in $args is missing, then the 'name' in $args will be |
---|
2899 | * used. It should also be noted that if you set 'slug' and it isn't unique then |
---|
2900 | * a WP_Error will be passed back. If you don't pass any slug, then a unique one |
---|
2901 | * will be created for you. |
---|
2902 | * |
---|
2903 | * For what can be overrode in $args, check the term scheme can contain and stay |
---|
2904 | * away from the term keys. |
---|
2905 | * |
---|
2906 | * @since 2.3.0 |
---|
2907 | * |
---|
2908 | * @uses $wpdb |
---|
2909 | * |
---|
2910 | * @param int $term_id The ID of the term |
---|
2911 | * @param string $taxonomy The context in which to relate the term to the object. |
---|
2912 | * @param array|string $args Overwrite term field values |
---|
2913 | * @return array|WP_Error Returns Term ID and Taxonomy Term ID |
---|
2914 | */ |
---|
2915 | function wp_update_term( $term_id, $taxonomy, $args = array() ) { |
---|
2916 | global $wpdb; |
---|
2917 | |
---|
2918 | if ( ! taxonomy_exists($taxonomy) ) |
---|
2919 | return new WP_Error('invalid_taxonomy', __('Invalid taxonomy')); |
---|
2920 | |
---|
2921 | $term_id = (int) $term_id; |
---|
2922 | |
---|
2923 | // First, get all of the original args |
---|
2924 | $term = get_term ($term_id, $taxonomy, ARRAY_A); |
---|
2925 | |
---|
2926 | if ( is_wp_error( $term ) ) |
---|
2927 | return $term; |
---|
2928 | |
---|
2929 | // Escape data pulled from DB. |
---|
2930 | $term = wp_slash($term); |
---|
2931 | |
---|
2932 | // Merge old and new args with new args overwriting old ones. |
---|
2933 | $args = array_merge($term, $args); |
---|
2934 | |
---|
2935 | $defaults = array( 'alias_of' => '', 'description' => '', 'parent' => 0, 'slug' => ''); |
---|
2936 | $args = wp_parse_args($args, $defaults); |
---|
2937 | $args = sanitize_term($args, $taxonomy, 'db'); |
---|
2938 | $parsed_args = $args; |
---|
2939 | |
---|
2940 | // expected_slashed ($name) |
---|
2941 | $name = wp_unslash( $args['name'] ); |
---|
2942 | $description = wp_unslash( $args['description'] ); |
---|
2943 | |
---|
2944 | $parsed_args['name'] = $name; |
---|
2945 | $parsed_args['description'] = $description; |
---|
2946 | |
---|
2947 | if ( '' == trim($name) ) |
---|
2948 | return new WP_Error('empty_term_name', __('A name is required for this term')); |
---|
2949 | |
---|
2950 | $empty_slug = false; |
---|
2951 | if ( empty( $args['slug'] ) ) { |
---|
2952 | $empty_slug = true; |
---|
2953 | $slug = sanitize_title($name); |
---|
2954 | } else { |
---|
2955 | $slug = $args['slug']; |
---|
2956 | } |
---|
2957 | |
---|
2958 | $parsed_args['slug'] = $slug; |
---|
2959 | |
---|
2960 | $term_group = isset( $parsed_args['term_group'] ) ? $parsed_args['term_group'] : 0; |
---|
2961 | if ( $args['alias_of'] ) { |
---|
2962 | $alias = $wpdb->get_row( $wpdb->prepare( "SELECT term_id, term_group FROM $wpdb->terms WHERE slug = %s", $args['alias_of'] ) ); |
---|
2963 | if ( $alias->term_group ) { |
---|
2964 | // The alias we want is already in a group, so let's use that one. |
---|
2965 | $term_group = $alias->term_group; |
---|
2966 | } else { |
---|
2967 | // The alias isn't in a group, so let's create a new one and firstly add the alias term to it. |
---|
2968 | $term_group = $wpdb->get_var("SELECT MAX(term_group) FROM $wpdb->terms") + 1; |
---|
2969 | |
---|
2970 | /** This action is documented in wp-includes/taxonomy.php */ |
---|
2971 | do_action( 'edit_terms', $alias->term_id, $taxonomy ); |
---|
2972 | $wpdb->update( $wpdb->terms, compact('term_group'), array( 'term_id' => $alias->term_id ) ); |
---|
2973 | |
---|
2974 | /** This action is documented in wp-includes/taxonomy.php */ |
---|
2975 | do_action( 'edited_terms', $alias->term_id, $taxonomy ); |
---|
2976 | } |
---|
2977 | |
---|
2978 | $parsed_args['term_group'] = $term_group; |
---|
2979 | } |
---|
2980 | |
---|
2981 | /** |
---|
2982 | * Filter the term parent. |
---|
2983 | * |
---|
2984 | * Hook to this filter to see if it will cause a hierarchy loop. |
---|
2985 | * |
---|
2986 | * @since 3.1.0 |
---|
2987 | * |
---|
2988 | * @param int $parent ID of the parent term. |
---|
2989 | * @param int $term_id Term ID. |
---|
2990 | * @param string $taxonomy Taxonomy slug. |
---|
2991 | * @param array $parsed_args An array of potentially altered update arguments for the given term. |
---|
2992 | * @param array $args An array of update arguments for the given term. |
---|
2993 | */ |
---|
2994 | $parent = apply_filters( 'wp_update_term_parent', $args['parent'], $term_id, $taxonomy, $parsed_args, $args ); |
---|
2995 | |
---|
2996 | // Check for duplicate slug |
---|
2997 | $id = $wpdb->get_var( $wpdb->prepare( "SELECT term_id FROM $wpdb->terms WHERE slug = %s", $slug ) ); |
---|
2998 | if ( $id && ($id != $term_id) ) { |
---|
2999 | // If an empty slug was passed or the parent changed, reset the slug to something unique. |
---|
3000 | // Otherwise, bail. |
---|
3001 | if ( $empty_slug || ( $parent != $term['parent']) ) |
---|
3002 | $slug = wp_unique_term_slug($slug, (object) $args); |
---|
3003 | else |
---|
3004 | return new WP_Error('duplicate_term_slug', sprintf(__('The slug “%s” is already in use by another term'), $slug)); |
---|
3005 | } |
---|
3006 | |
---|
3007 | /** This action is documented in wp-includes/taxonomy.php */ |
---|
3008 | do_action( 'edit_terms', $term_id, $taxonomy ); |
---|
3009 | $wpdb->update($wpdb->terms, compact( 'name', 'slug', 'term_group' ), compact( 'term_id' ) ); |
---|
3010 | if ( empty($slug) ) { |
---|
3011 | $slug = sanitize_title($name, $term_id); |
---|
3012 | $wpdb->update( $wpdb->terms, compact( 'slug' ), compact( 'term_id' ) ); |
---|
3013 | } |
---|
3014 | |
---|
3015 | /** This action is documented in wp-includes/taxonomy.php */ |
---|
3016 | do_action( 'edited_terms', $term_id, $taxonomy ); |
---|
3017 | |
---|
3018 | $tt_id = $wpdb->get_var( $wpdb->prepare( "SELECT tt.term_taxonomy_id FROM $wpdb->term_taxonomy AS tt INNER JOIN $wpdb->terms AS t ON tt.term_id = t.term_id WHERE tt.taxonomy = %s AND t.term_id = %d", $taxonomy, $term_id) ); |
---|
3019 | |
---|
3020 | /** |
---|
3021 | * Fires immediate before a term-taxonomy relationship is updated. |
---|
3022 | * |
---|
3023 | * @since 2.9.0 |
---|
3024 | * |
---|
3025 | * @param int $tt_id Term taxonomy ID. |
---|
3026 | * @param string $taxonomy Taxonomy slug. |
---|
3027 | */ |
---|
3028 | do_action( 'edit_term_taxonomy', $tt_id, $taxonomy ); |
---|
3029 | $wpdb->update( $wpdb->term_taxonomy, compact( 'term_id', 'taxonomy', 'description', 'parent' ), array( 'term_taxonomy_id' => $tt_id ) ); |
---|
3030 | |
---|
3031 | /** |
---|
3032 | * Fires immediately after a term-taxonomy relationship is updated. |
---|
3033 | * |
---|
3034 | * @since 2.9.0 |
---|
3035 | * |
---|
3036 | * @param int $tt_id Term taxonomy ID. |
---|
3037 | * @param string $taxonomy Taxonomy slug. |
---|
3038 | */ |
---|
3039 | do_action( 'edited_term_taxonomy', $tt_id, $taxonomy ); |
---|
3040 | |
---|
3041 | // Clean the relationship caches for all object types using this term |
---|
3042 | $objects = $wpdb->get_col( $wpdb->prepare( "SELECT object_id FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d", $tt_id ) ); |
---|
3043 | $tax_object = get_taxonomy( $taxonomy ); |
---|
3044 | foreach ( $tax_object->object_type as $object_type ) { |
---|
3045 | clean_object_term_cache( $objects, $object_type ); |
---|
3046 | } |
---|
3047 | |
---|
3048 | /** |
---|
3049 | * Fires after a term has been updated, but before the term cache has been cleaned. |
---|
3050 | * |
---|
3051 | * @since 2.3.0 |
---|
3052 | * |
---|
3053 | * @param int $term_id Term ID. |
---|
3054 | * @param int $tt_id Term taxonomy ID. |
---|
3055 | * @param string $taxonomy Taxonomy slug. |
---|
3056 | */ |
---|
3057 | do_action( "edit_term", $term_id, $tt_id, $taxonomy ); |
---|
3058 | |
---|
3059 | /** |
---|
3060 | * Fires after a term in a specific taxonomy has been updated, but before the term |
---|
3061 | * cache has been cleaned. |
---|
3062 | * |
---|
3063 | * The dynamic portion of the hook name, $taxonomy, refers to the taxonomy slug. |
---|
3064 | * |
---|
3065 | * @since 2.3.0 |
---|
3066 | * |
---|
3067 | * @param int $term_id Term ID. |
---|
3068 | * @param int $tt_id Term taxonomy ID. |
---|
3069 | */ |
---|
3070 | do_action( "edit_$taxonomy", $term_id, $tt_id ); |
---|
3071 | |
---|
3072 | /** This filter is documented in wp-includes/taxonomy.php */ |
---|
3073 | $term_id = apply_filters( 'term_id_filter', $term_id, $tt_id ); |
---|
3074 | |
---|
3075 | clean_term_cache($term_id, $taxonomy); |
---|
3076 | |
---|
3077 | /** |
---|
3078 | * Fires after a term has been updated, and the term cache has been cleaned. |
---|
3079 | * |
---|
3080 | * @since 2.3.0 |
---|
3081 | * |
---|
3082 | * @param int $term_id Term ID. |
---|
3083 | * @param int $tt_id Term taxonomy ID. |
---|
3084 | * @param string $taxonomy Taxonomy slug. |
---|
3085 | */ |
---|
3086 | do_action( "edited_term", $term_id, $tt_id, $taxonomy ); |
---|
3087 | |
---|
3088 | /** |
---|
3089 | * Fires after a term for a specific taxonomy has been updated, and the term |
---|
3090 | * cache has been cleaned. |
---|
3091 | * |
---|
3092 | * The dynamic portion of the hook name, $taxonomy, refers to the taxonomy slug. |
---|
3093 | * |
---|
3094 | * @since 2.3.0 |
---|
3095 | * |
---|
3096 | * @param int $term_id Term ID. |
---|
3097 | * @param int $tt_id Term taxonomy ID. |
---|
3098 | */ |
---|
3099 | do_action( "edited_$taxonomy", $term_id, $tt_id ); |
---|
3100 | |
---|
3101 | return array('term_id' => $term_id, 'term_taxonomy_id' => $tt_id); |
---|
3102 | } |
---|
3103 | |
---|
3104 | /** |
---|
3105 | * Enable or disable term counting. |
---|
3106 | * |
---|
3107 | * @since 2.5.0 |
---|
3108 | * |
---|
3109 | * @param bool $defer Optional. Enable if true, disable if false. |
---|
3110 | * @return bool Whether term counting is enabled or disabled. |
---|
3111 | */ |
---|
3112 | function wp_defer_term_counting($defer=null) { |
---|
3113 | static $_defer = false; |
---|
3114 | |
---|
3115 | if ( is_bool($defer) ) { |
---|
3116 | $_defer = $defer; |
---|
3117 | // flush any deferred counts |
---|
3118 | if ( !$defer ) |
---|
3119 | wp_update_term_count( null, null, true ); |
---|
3120 | } |
---|
3121 | |
---|
3122 | return $_defer; |
---|
3123 | } |
---|
3124 | |
---|
3125 | /** |
---|
3126 | * Updates the amount of terms in taxonomy. |
---|
3127 | * |
---|
3128 | * If there is a taxonomy callback applied, then it will be called for updating |
---|
3129 | * the count. |
---|
3130 | * |
---|
3131 | * The default action is to count what the amount of terms have the relationship |
---|
3132 | * of term ID. Once that is done, then update the database. |
---|
3133 | * |
---|
3134 | * @since 2.3.0 |
---|
3135 | * @uses $wpdb |
---|
3136 | * |
---|
3137 | * @param int|array $terms The term_taxonomy_id of the terms |
---|
3138 | * @param string $taxonomy The context of the term. |
---|
3139 | * @return bool If no terms will return false, and if successful will return true. |
---|
3140 | */ |
---|
3141 | function wp_update_term_count( $terms, $taxonomy, $do_deferred=false ) { |
---|
3142 | static $_deferred = array(); |
---|
3143 | |
---|
3144 | if ( $do_deferred ) { |
---|
3145 | foreach ( (array) array_keys($_deferred) as $tax ) { |
---|
3146 | wp_update_term_count_now( $_deferred[$tax], $tax ); |
---|
3147 | unset( $_deferred[$tax] ); |
---|
3148 | } |
---|
3149 | } |
---|
3150 | |
---|
3151 | if ( empty($terms) ) |
---|
3152 | return false; |
---|
3153 | |
---|
3154 | if ( !is_array($terms) ) |
---|
3155 | $terms = array($terms); |
---|
3156 | |
---|
3157 | if ( wp_defer_term_counting() ) { |
---|
3158 | if ( !isset($_deferred[$taxonomy]) ) |
---|
3159 | $_deferred[$taxonomy] = array(); |
---|
3160 | $_deferred[$taxonomy] = array_unique( array_merge($_deferred[$taxonomy], $terms) ); |
---|
3161 | return true; |
---|
3162 | } |
---|
3163 | |
---|
3164 | return wp_update_term_count_now( $terms, $taxonomy ); |
---|
3165 | } |
---|
3166 | |
---|
3167 | /** |
---|
3168 | * Perform term count update immediately. |
---|
3169 | * |
---|
3170 | * @since 2.5.0 |
---|
3171 | * |
---|
3172 | * @param array $terms The term_taxonomy_id of terms to update. |
---|
3173 | * @param string $taxonomy The context of the term. |
---|
3174 | * @return bool Always true when complete. |
---|
3175 | */ |
---|
3176 | function wp_update_term_count_now( $terms, $taxonomy ) { |
---|
3177 | $terms = array_map('intval', $terms); |
---|
3178 | |
---|
3179 | $taxonomy = get_taxonomy($taxonomy); |
---|
3180 | if ( !empty($taxonomy->update_count_callback) ) { |
---|
3181 | call_user_func($taxonomy->update_count_callback, $terms, $taxonomy); |
---|
3182 | } else { |
---|
3183 | $object_types = (array) $taxonomy->object_type; |
---|
3184 | foreach ( $object_types as &$object_type ) { |
---|
3185 | if ( 0 === strpos( $object_type, 'attachment:' ) ) |
---|
3186 | list( $object_type ) = explode( ':', $object_type ); |
---|
3187 | } |
---|
3188 | |
---|
3189 | if ( $object_types == array_filter( $object_types, 'post_type_exists' ) ) { |
---|
3190 | // Only post types are attached to this taxonomy |
---|
3191 | _update_post_term_count( $terms, $taxonomy ); |
---|
3192 | } else { |
---|
3193 | // Default count updater |
---|
3194 | _update_generic_term_count( $terms, $taxonomy ); |
---|
3195 | } |
---|
3196 | } |
---|
3197 | |
---|
3198 | clean_term_cache($terms, '', false); |
---|
3199 | |
---|
3200 | return true; |
---|
3201 | } |
---|
3202 | |
---|
3203 | // |
---|
3204 | // Cache |
---|
3205 | // |
---|
3206 | |
---|
3207 | /** |
---|
3208 | * Removes the taxonomy relationship to terms from the cache. |
---|
3209 | * |
---|
3210 | * Will remove the entire taxonomy relationship containing term $object_id. The |
---|
3211 | * term IDs have to exist within the taxonomy $object_type for the deletion to |
---|
3212 | * take place. |
---|
3213 | * |
---|
3214 | * @since 2.3.0 |
---|
3215 | * |
---|
3216 | * @see get_object_taxonomies() for more on $object_type |
---|
3217 | * |
---|
3218 | * @param int|array $object_ids Single or list of term object ID(s) |
---|
3219 | * @param array|string $object_type The taxonomy object type |
---|
3220 | */ |
---|
3221 | function clean_object_term_cache($object_ids, $object_type) { |
---|
3222 | if ( !is_array($object_ids) ) |
---|
3223 | $object_ids = array($object_ids); |
---|
3224 | |
---|
3225 | $taxonomies = get_object_taxonomies( $object_type ); |
---|
3226 | |
---|
3227 | foreach ( $object_ids as $id ) { |
---|
3228 | foreach ( $taxonomies as $taxonomy ) { |
---|
3229 | wp_cache_delete($id, "{$taxonomy}_relationships"); |
---|
3230 | } |
---|
3231 | } |
---|
3232 | |
---|
3233 | /** |
---|
3234 | * Fires after the object term cache has been cleaned. |
---|
3235 | * |
---|
3236 | * @since 2.5.0 |
---|
3237 | * |
---|
3238 | * @param array $object_ids An array of object IDs. |
---|
3239 | * @param string $objet_type Object type. |
---|
3240 | */ |
---|
3241 | do_action( 'clean_object_term_cache', $object_ids, $object_type ); |
---|
3242 | } |
---|
3243 | |
---|
3244 | /** |
---|
3245 | * Will remove all of the term ids from the cache. |
---|
3246 | * |
---|
3247 | * @since 2.3.0 |
---|
3248 | * @uses $wpdb |
---|
3249 | * |
---|
3250 | * @param int|array $ids Single or list of Term IDs |
---|
3251 | * @param string $taxonomy Can be empty and will assume tt_ids, else will use for context. |
---|
3252 | * @param bool $clean_taxonomy Whether to clean taxonomy wide caches (true), or just individual term object caches (false). Default is true. |
---|
3253 | */ |
---|
3254 | function clean_term_cache($ids, $taxonomy = '', $clean_taxonomy = true) { |
---|
3255 | global $wpdb; |
---|
3256 | |
---|
3257 | if ( !is_array($ids) ) |
---|
3258 | $ids = array($ids); |
---|
3259 | |
---|
3260 | $taxonomies = array(); |
---|
3261 | // If no taxonomy, assume tt_ids. |
---|
3262 | if ( empty($taxonomy) ) { |
---|
3263 | $tt_ids = array_map('intval', $ids); |
---|
3264 | $tt_ids = implode(', ', $tt_ids); |
---|
3265 | $terms = $wpdb->get_results("SELECT term_id, taxonomy FROM $wpdb->term_taxonomy WHERE term_taxonomy_id IN ($tt_ids)"); |
---|
3266 | $ids = array(); |
---|
3267 | foreach ( (array) $terms as $term ) { |
---|
3268 | $taxonomies[] = $term->taxonomy; |
---|
3269 | $ids[] = $term->term_id; |
---|
3270 | wp_cache_delete($term->term_id, $term->taxonomy); |
---|
3271 | } |
---|
3272 | $taxonomies = array_unique($taxonomies); |
---|
3273 | } else { |
---|
3274 | $taxonomies = array($taxonomy); |
---|
3275 | foreach ( $taxonomies as $taxonomy ) { |
---|
3276 | foreach ( $ids as $id ) { |
---|
3277 | wp_cache_delete($id, $taxonomy); |
---|
3278 | } |
---|
3279 | } |
---|
3280 | } |
---|
3281 | |
---|
3282 | foreach ( $taxonomies as $taxonomy ) { |
---|
3283 | if ( $clean_taxonomy ) { |
---|
3284 | wp_cache_delete('all_ids', $taxonomy); |
---|
3285 | wp_cache_delete('get', $taxonomy); |
---|
3286 | delete_option("{$taxonomy}_children"); |
---|
3287 | // Regenerate {$taxonomy}_children |
---|
3288 | _get_term_hierarchy($taxonomy); |
---|
3289 | } |
---|
3290 | |
---|
3291 | /** |
---|
3292 | * Fires once after each taxonomy's term cache has been cleaned. |
---|
3293 | * |
---|
3294 | * @since 2.5.0 |
---|
3295 | * |
---|
3296 | * @param array $ids An array of term IDs. |
---|
3297 | * @param string $taxonomy Taxonomy slug. |
---|
3298 | */ |
---|
3299 | do_action( 'clean_term_cache', $ids, $taxonomy ); |
---|
3300 | } |
---|
3301 | |
---|
3302 | wp_cache_set( 'last_changed', microtime(), 'terms' ); |
---|
3303 | } |
---|
3304 | |
---|
3305 | /** |
---|
3306 | * Retrieves the taxonomy relationship to the term object id. |
---|
3307 | * |
---|
3308 | * @since 2.3.0 |
---|
3309 | * |
---|
3310 | * @uses wp_cache_get() Retrieves taxonomy relationship from cache |
---|
3311 | * |
---|
3312 | * @param int|array $id Term object ID |
---|
3313 | * @param string $taxonomy Taxonomy Name |
---|
3314 | * @return bool|array Empty array if $terms found, but not $taxonomy. False if nothing is in cache for $taxonomy and $id. |
---|
3315 | */ |
---|
3316 | function get_object_term_cache($id, $taxonomy) { |
---|
3317 | $cache = wp_cache_get($id, "{$taxonomy}_relationships"); |
---|
3318 | return $cache; |
---|
3319 | } |
---|
3320 | |
---|
3321 | /** |
---|
3322 | * Updates the cache for Term ID(s). |
---|
3323 | * |
---|
3324 | * Will only update the cache for terms not already cached. |
---|
3325 | * |
---|
3326 | * The $object_ids expects that the ids be separated by commas, if it is a |
---|
3327 | * string. |
---|
3328 | * |
---|
3329 | * It should be noted that update_object_term_cache() is very time extensive. It |
---|
3330 | * is advised that the function is not called very often or at least not for a |
---|
3331 | * lot of terms that exist in a lot of taxonomies. The amount of time increases |
---|
3332 | * for each term and it also increases for each taxonomy the term belongs to. |
---|
3333 | * |
---|
3334 | * @since 2.3.0 |
---|
3335 | * @uses wp_get_object_terms() Used to get terms from the database to update |
---|
3336 | * |
---|
3337 | * @param string|array $object_ids Single or list of term object ID(s) |
---|
3338 | * @param array|string $object_type The taxonomy object type |
---|
3339 | * @return null|bool Null value is given with empty $object_ids. False if |
---|
3340 | */ |
---|
3341 | function update_object_term_cache($object_ids, $object_type) { |
---|
3342 | if ( empty($object_ids) ) |
---|
3343 | return; |
---|
3344 | |
---|
3345 | if ( !is_array($object_ids) ) |
---|
3346 | $object_ids = explode(',', $object_ids); |
---|
3347 | |
---|
3348 | $object_ids = array_map('intval', $object_ids); |
---|
3349 | |
---|
3350 | $taxonomies = get_object_taxonomies($object_type); |
---|
3351 | |
---|
3352 | $ids = array(); |
---|
3353 | foreach ( (array) $object_ids as $id ) { |
---|
3354 | foreach ( $taxonomies as $taxonomy ) { |
---|
3355 | if ( false === wp_cache_get($id, "{$taxonomy}_relationships") ) { |
---|
3356 | $ids[] = $id; |
---|
3357 | break; |
---|
3358 | } |
---|
3359 | } |
---|
3360 | } |
---|
3361 | |
---|
3362 | if ( empty( $ids ) ) |
---|
3363 | return false; |
---|
3364 | |
---|
3365 | $terms = wp_get_object_terms($ids, $taxonomies, array('fields' => 'all_with_object_id')); |
---|
3366 | |
---|
3367 | $object_terms = array(); |
---|
3368 | foreach ( (array) $terms as $term ) |
---|
3369 | $object_terms[$term->object_id][$term->taxonomy][$term->term_id] = $term; |
---|
3370 | |
---|
3371 | foreach ( $ids as $id ) { |
---|
3372 | foreach ( $taxonomies as $taxonomy ) { |
---|
3373 | if ( ! isset($object_terms[$id][$taxonomy]) ) { |
---|
3374 | if ( !isset($object_terms[$id]) ) |
---|
3375 | $object_terms[$id] = array(); |
---|
3376 | $object_terms[$id][$taxonomy] = array(); |
---|
3377 | } |
---|
3378 | } |
---|
3379 | } |
---|
3380 | |
---|
3381 | foreach ( $object_terms as $id => $value ) { |
---|
3382 | foreach ( $value as $taxonomy => $terms ) { |
---|
3383 | wp_cache_add( $id, $terms, "{$taxonomy}_relationships" ); |
---|
3384 | } |
---|
3385 | } |
---|
3386 | } |
---|
3387 | |
---|
3388 | /** |
---|
3389 | * Updates Terms to Taxonomy in cache. |
---|
3390 | * |
---|
3391 | * @since 2.3.0 |
---|
3392 | * |
---|
3393 | * @param array $terms List of Term objects to change |
---|
3394 | * @param string $taxonomy Optional. Update Term to this taxonomy in cache |
---|
3395 | */ |
---|
3396 | function update_term_cache($terms, $taxonomy = '') { |
---|
3397 | foreach ( (array) $terms as $term ) { |
---|
3398 | $term_taxonomy = $taxonomy; |
---|
3399 | if ( empty($term_taxonomy) ) |
---|
3400 | $term_taxonomy = $term->taxonomy; |
---|
3401 | |
---|
3402 | wp_cache_add($term->term_id, $term, $term_taxonomy); |
---|
3403 | } |
---|
3404 | } |
---|
3405 | |
---|
3406 | // |
---|
3407 | // Private |
---|
3408 | // |
---|
3409 | |
---|
3410 | /** |
---|
3411 | * Retrieves children of taxonomy as Term IDs. |
---|
3412 | * |
---|
3413 | * @access private |
---|
3414 | * @since 2.3.0 |
---|
3415 | * |
---|
3416 | * @uses update_option() Stores all of the children in "$taxonomy_children" |
---|
3417 | * option. That is the name of the taxonomy, immediately followed by '_children'. |
---|
3418 | * |
---|
3419 | * @param string $taxonomy Taxonomy Name |
---|
3420 | * @return array Empty if $taxonomy isn't hierarchical or returns children as Term IDs. |
---|
3421 | */ |
---|
3422 | function _get_term_hierarchy($taxonomy) { |
---|
3423 | if ( !is_taxonomy_hierarchical($taxonomy) ) |
---|
3424 | return array(); |
---|
3425 | $children = get_option("{$taxonomy}_children"); |
---|
3426 | |
---|
3427 | if ( is_array($children) ) |
---|
3428 | return $children; |
---|
3429 | $children = array(); |
---|
3430 | $terms = get_terms($taxonomy, array('get' => 'all', 'orderby' => 'id', 'fields' => 'id=>parent')); |
---|
3431 | foreach ( $terms as $term_id => $parent ) { |
---|
3432 | if ( $parent > 0 ) |
---|
3433 | $children[$parent][] = $term_id; |
---|
3434 | } |
---|
3435 | update_option("{$taxonomy}_children", $children); |
---|
3436 | |
---|
3437 | return $children; |
---|
3438 | } |
---|
3439 | |
---|
3440 | /** |
---|
3441 | * Get the subset of $terms that are descendants of $term_id. |
---|
3442 | * |
---|
3443 | * If $terms is an array of objects, then _get_term_children returns an array of objects. |
---|
3444 | * If $terms is an array of IDs, then _get_term_children returns an array of IDs. |
---|
3445 | * |
---|
3446 | * @access private |
---|
3447 | * @since 2.3.0 |
---|
3448 | * |
---|
3449 | * @param int $term_id The ancestor term: all returned terms should be descendants of $term_id. |
---|
3450 | * @param array $terms The set of terms---either an array of term objects or term IDs---from which those that are descendants of $term_id will be chosen. |
---|
3451 | * @param string $taxonomy The taxonomy which determines the hierarchy of the terms. |
---|
3452 | * @return array The subset of $terms that are descendants of $term_id. |
---|
3453 | */ |
---|
3454 | function _get_term_children($term_id, $terms, $taxonomy) { |
---|
3455 | $empty_array = array(); |
---|
3456 | if ( empty($terms) ) |
---|
3457 | return $empty_array; |
---|
3458 | |
---|
3459 | $term_list = array(); |
---|
3460 | $has_children = _get_term_hierarchy($taxonomy); |
---|
3461 | |
---|
3462 | if ( ( 0 != $term_id ) && ! isset($has_children[$term_id]) ) |
---|
3463 | return $empty_array; |
---|
3464 | |
---|
3465 | foreach ( (array) $terms as $term ) { |
---|
3466 | $use_id = false; |
---|
3467 | if ( !is_object($term) ) { |
---|
3468 | $term = get_term($term, $taxonomy); |
---|
3469 | if ( is_wp_error( $term ) ) |
---|
3470 | return $term; |
---|
3471 | $use_id = true; |
---|
3472 | } |
---|
3473 | |
---|
3474 | if ( $term->term_id == $term_id ) { |
---|
3475 | continue; |
---|
3476 | } |
---|
3477 | |
---|
3478 | if ( $term->parent == $term_id ) { |
---|
3479 | if ( $use_id ) |
---|
3480 | $term_list[] = $term->term_id; |
---|
3481 | else |
---|
3482 | $term_list[] = $term; |
---|
3483 | |
---|
3484 | if ( !isset($has_children[$term->term_id]) ) |
---|
3485 | continue; |
---|
3486 | |
---|
3487 | if ( $children = _get_term_children($term->term_id, $terms, $taxonomy) ) |
---|
3488 | $term_list = array_merge($term_list, $children); |
---|
3489 | } |
---|
3490 | } |
---|
3491 | |
---|
3492 | return $term_list; |
---|
3493 | } |
---|
3494 | |
---|
3495 | /** |
---|
3496 | * Add count of children to parent count. |
---|
3497 | * |
---|
3498 | * Recalculates term counts by including items from child terms. Assumes all |
---|
3499 | * relevant children are already in the $terms argument. |
---|
3500 | * |
---|
3501 | * @access private |
---|
3502 | * @since 2.3.0 |
---|
3503 | * @uses $wpdb |
---|
3504 | * |
---|
3505 | * @param array $terms List of Term IDs |
---|
3506 | * @param string $taxonomy Term Context |
---|
3507 | * @return null Will break from function if conditions are not met. |
---|
3508 | */ |
---|
3509 | function _pad_term_counts(&$terms, $taxonomy) { |
---|
3510 | global $wpdb; |
---|
3511 | |
---|
3512 | // This function only works for hierarchical taxonomies like post categories. |
---|
3513 | if ( !is_taxonomy_hierarchical( $taxonomy ) ) |
---|
3514 | return; |
---|
3515 | |
---|
3516 | $term_hier = _get_term_hierarchy($taxonomy); |
---|
3517 | |
---|
3518 | if ( empty($term_hier) ) |
---|
3519 | return; |
---|
3520 | |
---|
3521 | $term_items = array(); |
---|
3522 | |
---|
3523 | foreach ( (array) $terms as $key => $term ) { |
---|
3524 | $terms_by_id[$term->term_id] = & $terms[$key]; |
---|
3525 | $term_ids[$term->term_taxonomy_id] = $term->term_id; |
---|
3526 | } |
---|
3527 | |
---|
3528 | // Get the object and term ids and stick them in a lookup table |
---|
3529 | $tax_obj = get_taxonomy($taxonomy); |
---|
3530 | $object_types = esc_sql($tax_obj->object_type); |
---|
3531 | $results = $wpdb->get_results("SELECT object_id, term_taxonomy_id FROM $wpdb->term_relationships INNER JOIN $wpdb->posts ON object_id = ID WHERE term_taxonomy_id IN (" . implode(',', array_keys($term_ids)) . ") AND post_type IN ('" . implode("', '", $object_types) . "') AND post_status = 'publish'"); |
---|
3532 | foreach ( $results as $row ) { |
---|
3533 | $id = $term_ids[$row->term_taxonomy_id]; |
---|
3534 | $term_items[$id][$row->object_id] = isset($term_items[$id][$row->object_id]) ? ++$term_items[$id][$row->object_id] : 1; |
---|
3535 | } |
---|
3536 | |
---|
3537 | // Touch every ancestor's lookup row for each post in each term |
---|
3538 | foreach ( $term_ids as $term_id ) { |
---|
3539 | $child = $term_id; |
---|
3540 | while ( !empty( $terms_by_id[$child] ) && $parent = $terms_by_id[$child]->parent ) { |
---|
3541 | if ( !empty( $term_items[$term_id] ) ) |
---|
3542 | foreach ( $term_items[$term_id] as $item_id => $touches ) { |
---|
3543 | $term_items[$parent][$item_id] = isset($term_items[$parent][$item_id]) ? ++$term_items[$parent][$item_id]: 1; |
---|
3544 | } |
---|
3545 | $child = $parent; |
---|
3546 | } |
---|
3547 | } |
---|
3548 | |
---|
3549 | // Transfer the touched cells |
---|
3550 | foreach ( (array) $term_items as $id => $items ) |
---|
3551 | if ( isset($terms_by_id[$id]) ) |
---|
3552 | $terms_by_id[$id]->count = count($items); |
---|
3553 | } |
---|
3554 | |
---|
3555 | // |
---|
3556 | // Default callbacks |
---|
3557 | // |
---|
3558 | |
---|
3559 | /** |
---|
3560 | * Will update term count based on object types of the current taxonomy. |
---|
3561 | * |
---|
3562 | * Private function for the default callback for post_tag and category |
---|
3563 | * taxonomies. |
---|
3564 | * |
---|
3565 | * @access private |
---|
3566 | * @since 2.3.0 |
---|
3567 | * @uses $wpdb |
---|
3568 | * |
---|
3569 | * @param array $terms List of Term taxonomy IDs |
---|
3570 | * @param object $taxonomy Current taxonomy object of terms |
---|
3571 | */ |
---|
3572 | function _update_post_term_count( $terms, $taxonomy ) { |
---|
3573 | global $wpdb; |
---|
3574 | |
---|
3575 | $object_types = (array) $taxonomy->object_type; |
---|
3576 | |
---|
3577 | foreach ( $object_types as &$object_type ) |
---|
3578 | list( $object_type ) = explode( ':', $object_type ); |
---|
3579 | |
---|
3580 | $object_types = array_unique( $object_types ); |
---|
3581 | |
---|
3582 | if ( false !== ( $check_attachments = array_search( 'attachment', $object_types ) ) ) { |
---|
3583 | unset( $object_types[ $check_attachments ] ); |
---|
3584 | $check_attachments = true; |
---|
3585 | } |
---|
3586 | |
---|
3587 | if ( $object_types ) |
---|
3588 | $object_types = esc_sql( array_filter( $object_types, 'post_type_exists' ) ); |
---|
3589 | |
---|
3590 | foreach ( (array) $terms as $term ) { |
---|
3591 | $count = 0; |
---|
3592 | |
---|
3593 | // Attachments can be 'inherit' status, we need to base count off the parent's status if so |
---|
3594 | if ( $check_attachments ) |
---|
3595 | $count += (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_relationships, $wpdb->posts p1 WHERE p1.ID = $wpdb->term_relationships.object_id AND ( post_status = 'publish' OR ( post_status = 'inherit' AND post_parent > 0 AND ( SELECT post_status FROM $wpdb->posts WHERE ID = p1.post_parent ) = 'publish' ) ) AND post_type = 'attachment' AND term_taxonomy_id = %d", $term ) ); |
---|
3596 | |
---|
3597 | if ( $object_types ) |
---|
3598 | $count += (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_relationships, $wpdb->posts WHERE $wpdb->posts.ID = $wpdb->term_relationships.object_id AND post_status = 'publish' AND post_type IN ('" . implode("', '", $object_types ) . "') AND term_taxonomy_id = %d", $term ) ); |
---|
3599 | |
---|
3600 | /** This action is documented in wp-includes/taxonomy.php */ |
---|
3601 | do_action( 'edit_term_taxonomy', $term, $taxonomy ); |
---|
3602 | $wpdb->update( $wpdb->term_taxonomy, compact( 'count' ), array( 'term_taxonomy_id' => $term ) ); |
---|
3603 | |
---|
3604 | /** This action is documented in wp-includes/taxonomy.php */ |
---|
3605 | do_action( 'edited_term_taxonomy', $term, $taxonomy ); |
---|
3606 | } |
---|
3607 | } |
---|
3608 | |
---|
3609 | /** |
---|
3610 | * Will update term count based on number of objects. |
---|
3611 | * |
---|
3612 | * Default callback for the link_category taxonomy. |
---|
3613 | * |
---|
3614 | * @since 3.3.0 |
---|
3615 | * @uses $wpdb |
---|
3616 | * |
---|
3617 | * @param array $terms List of Term taxonomy IDs |
---|
3618 | * @param object $taxonomy Current taxonomy object of terms |
---|
3619 | */ |
---|
3620 | function _update_generic_term_count( $terms, $taxonomy ) { |
---|
3621 | global $wpdb; |
---|
3622 | |
---|
3623 | foreach ( (array) $terms as $term ) { |
---|
3624 | $count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d", $term ) ); |
---|
3625 | |
---|
3626 | /** This action is documented in wp-includes/taxonomy.php */ |
---|
3627 | do_action( 'edit_term_taxonomy', $term, $taxonomy ); |
---|
3628 | $wpdb->update( $wpdb->term_taxonomy, compact( 'count' ), array( 'term_taxonomy_id' => $term ) ); |
---|
3629 | |
---|
3630 | /** This action is documented in wp-includes/taxonomy.php */ |
---|
3631 | do_action( 'edited_term_taxonomy', $term, $taxonomy ); |
---|
3632 | } |
---|
3633 | } |
---|
3634 | |
---|
3635 | /** |
---|
3636 | * Generates a permalink for a taxonomy term archive. |
---|
3637 | * |
---|
3638 | * @since 2.5.0 |
---|
3639 | * |
---|
3640 | * @param object|int|string $term |
---|
3641 | * @param string $taxonomy (optional if $term is object) |
---|
3642 | * @return string|WP_Error HTML link to taxonomy term archive on success, WP_Error if term does not exist. |
---|
3643 | */ |
---|
3644 | function get_term_link( $term, $taxonomy = '') { |
---|
3645 | global $wp_rewrite; |
---|
3646 | |
---|
3647 | if ( !is_object($term) ) { |
---|
3648 | if ( is_int($term) ) { |
---|
3649 | $term = get_term($term, $taxonomy); |
---|
3650 | } else { |
---|
3651 | $term = get_term_by('slug', $term, $taxonomy); |
---|
3652 | } |
---|
3653 | } |
---|
3654 | |
---|
3655 | if ( !is_object($term) ) |
---|
3656 | $term = new WP_Error('invalid_term', __('Empty Term')); |
---|
3657 | |
---|
3658 | if ( is_wp_error( $term ) ) |
---|
3659 | return $term; |
---|
3660 | |
---|
3661 | $taxonomy = $term->taxonomy; |
---|
3662 | |
---|
3663 | $termlink = $wp_rewrite->get_extra_permastruct($taxonomy); |
---|
3664 | |
---|
3665 | $slug = $term->slug; |
---|
3666 | $t = get_taxonomy($taxonomy); |
---|
3667 | |
---|
3668 | if ( empty($termlink) ) { |
---|
3669 | if ( 'category' == $taxonomy ) |
---|
3670 | $termlink = '?cat=' . $term->term_id; |
---|
3671 | elseif ( $t->query_var ) |
---|
3672 | $termlink = "?$t->query_var=$slug"; |
---|
3673 | else |
---|
3674 | $termlink = "?taxonomy=$taxonomy&term=$slug"; |
---|
3675 | $termlink = home_url($termlink); |
---|
3676 | } else { |
---|
3677 | if ( $t->rewrite['hierarchical'] ) { |
---|
3678 | $hierarchical_slugs = array(); |
---|
3679 | $ancestors = get_ancestors($term->term_id, $taxonomy); |
---|
3680 | foreach ( (array)$ancestors as $ancestor ) { |
---|
3681 | $ancestor_term = get_term($ancestor, $taxonomy); |
---|
3682 | $hierarchical_slugs[] = $ancestor_term->slug; |
---|
3683 | } |
---|
3684 | $hierarchical_slugs = array_reverse($hierarchical_slugs); |
---|
3685 | $hierarchical_slugs[] = $slug; |
---|
3686 | $termlink = str_replace("%$taxonomy%", implode('/', $hierarchical_slugs), $termlink); |
---|
3687 | } else { |
---|
3688 | $termlink = str_replace("%$taxonomy%", $slug, $termlink); |
---|
3689 | } |
---|
3690 | $termlink = home_url( user_trailingslashit($termlink, 'category') ); |
---|
3691 | } |
---|
3692 | // Back Compat filters. |
---|
3693 | if ( 'post_tag' == $taxonomy ) { |
---|
3694 | |
---|
3695 | /** |
---|
3696 | * Filter the tag link. |
---|
3697 | * |
---|
3698 | * @since 2.3.0 |
---|
3699 | * @deprecated 2.5.0 Use 'term_link' instead. |
---|
3700 | * |
---|
3701 | * @param string $termlink Tag link URL. |
---|
3702 | * @param int $term_id Term ID. |
---|
3703 | */ |
---|
3704 | $termlink = apply_filters( 'tag_link', $termlink, $term->term_id ); |
---|
3705 | } elseif ( 'category' == $taxonomy ) { |
---|
3706 | |
---|
3707 | /** |
---|
3708 | * Filter the category link. |
---|
3709 | * |
---|
3710 | * @since 1.5.0 |
---|
3711 | * @deprecated 2.5.0 Use 'term_link' instead. |
---|
3712 | * |
---|
3713 | * @param string $termlink Category link URL. |
---|
3714 | * @param int $term_id Term ID. |
---|
3715 | */ |
---|
3716 | $termlink = apply_filters( 'category_link', $termlink, $term->term_id ); |
---|
3717 | } |
---|
3718 | |
---|
3719 | /** |
---|
3720 | * Filter the term link. |
---|
3721 | * |
---|
3722 | * @since 2.5.0 |
---|
3723 | * |
---|
3724 | * @param string $termlink Term link URL. |
---|
3725 | * @param object $term Term object. |
---|
3726 | * @param string $taxonomy Taxonomy slug. |
---|
3727 | */ |
---|
3728 | return apply_filters( 'term_link', $termlink, $term, $taxonomy ); |
---|
3729 | } |
---|
3730 | |
---|
3731 | /** |
---|
3732 | * Display the taxonomies of a post with available options. |
---|
3733 | * |
---|
3734 | * This function can be used within the loop to display the taxonomies for a |
---|
3735 | * post without specifying the Post ID. You can also use it outside the Loop to |
---|
3736 | * display the taxonomies for a specific post. |
---|
3737 | * |
---|
3738 | * The available defaults are: |
---|
3739 | * 'post' : default is 0. The post ID to get taxonomies of. |
---|
3740 | * 'before' : default is empty string. Display before taxonomies list. |
---|
3741 | * 'sep' : default is empty string. Separate every taxonomy with value in this. |
---|
3742 | * 'after' : default is empty string. Display this after the taxonomies list. |
---|
3743 | * 'template' : The template to use for displaying the taxonomy terms. |
---|
3744 | * |
---|
3745 | * @since 2.5.0 |
---|
3746 | * @uses get_the_taxonomies() |
---|
3747 | * |
---|
3748 | * @param array $args Override the defaults. |
---|
3749 | */ |
---|
3750 | function the_taxonomies( $args = array() ) { |
---|
3751 | $defaults = array( |
---|
3752 | 'post' => 0, |
---|
3753 | 'before' => '', |
---|
3754 | 'sep' => ' ', |
---|
3755 | 'after' => '', |
---|
3756 | /* translators: %s: taxonomy label, %l: list of term links */ |
---|
3757 | 'template' => __( '%s: %l.' ) |
---|
3758 | ); |
---|
3759 | |
---|
3760 | $r = wp_parse_args( $args, $defaults ); |
---|
3761 | |
---|
3762 | echo $r['before'] . join( $r['sep'], get_the_taxonomies( $r['post'], $r ) ) . $r['after']; |
---|
3763 | } |
---|
3764 | |
---|
3765 | /** |
---|
3766 | * Retrieve all taxonomies associated with a post. |
---|
3767 | * |
---|
3768 | * This function can be used within the loop. It will also return an array of |
---|
3769 | * the taxonomies with links to the taxonomy and name. |
---|
3770 | * |
---|
3771 | * @since 2.5.0 |
---|
3772 | * |
---|
3773 | * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. |
---|
3774 | * @param array $args Override the defaults. |
---|
3775 | * @return array List of taxonomies. |
---|
3776 | */ |
---|
3777 | function get_the_taxonomies( $post = 0, $args = array() ) { |
---|
3778 | $post = get_post( $post ); |
---|
3779 | |
---|
3780 | $args = wp_parse_args( $args, array( |
---|
3781 | /* translators: %s: taxonomy label, %l: list of term links */ |
---|
3782 | 'template' => __( '%s: %l.' ), |
---|
3783 | ) ); |
---|
3784 | |
---|
3785 | $taxonomies = array(); |
---|
3786 | |
---|
3787 | if ( ! $post ) { |
---|
3788 | return $taxonomies; |
---|
3789 | } |
---|
3790 | |
---|
3791 | foreach ( get_object_taxonomies( $post ) as $taxonomy ) { |
---|
3792 | $t = (array) get_taxonomy( $taxonomy ); |
---|
3793 | if ( empty( $t['label'] ) ) { |
---|
3794 | $t['label'] = $taxonomy; |
---|
3795 | } |
---|
3796 | if ( empty( $t['args'] ) ) { |
---|
3797 | $t['args'] = array(); |
---|
3798 | } |
---|
3799 | if ( empty( $t['template'] ) ) { |
---|
3800 | $t['template'] = $args['template']; |
---|
3801 | } |
---|
3802 | |
---|
3803 | $terms = get_object_term_cache( $post->ID, $taxonomy ); |
---|
3804 | if ( false === $terms ) { |
---|
3805 | $terms = wp_get_object_terms( $post->ID, $taxonomy, $t['args'] ); |
---|
3806 | } |
---|
3807 | $links = array(); |
---|
3808 | |
---|
3809 | foreach ( $terms as $term ) { |
---|
3810 | $links[] = "<a href='" . esc_attr( get_term_link( $term ) ) . "'>$term->name</a>"; |
---|
3811 | } |
---|
3812 | if ( $links ) { |
---|
3813 | $taxonomies[$taxonomy] = wp_sprintf( $t['template'], $t['label'], $links, $terms ); |
---|
3814 | } |
---|
3815 | } |
---|
3816 | return $taxonomies; |
---|
3817 | } |
---|
3818 | |
---|
3819 | /** |
---|
3820 | * Retrieve all taxonomies of a post with just the names. |
---|
3821 | * |
---|
3822 | * @since 2.5.0 |
---|
3823 | * |
---|
3824 | * @uses get_object_taxonomies() |
---|
3825 | * |
---|
3826 | * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. |
---|
3827 | * @return array |
---|
3828 | */ |
---|
3829 | function get_post_taxonomies( $post = 0 ) { |
---|
3830 | $post = get_post( $post ); |
---|
3831 | |
---|
3832 | return get_object_taxonomies($post); |
---|
3833 | } |
---|
3834 | |
---|
3835 | /** |
---|
3836 | * Determine if the given object is associated with any of the given terms. |
---|
3837 | * |
---|
3838 | * The given terms are checked against the object's terms' term_ids, names and slugs. |
---|
3839 | * Terms given as integers will only be checked against the object's terms' term_ids. |
---|
3840 | * If no terms are given, determines if object is associated with any terms in the given taxonomy. |
---|
3841 | * |
---|
3842 | * @since 2.7.0 |
---|
3843 | * @uses get_object_term_cache() |
---|
3844 | * @uses wp_get_object_terms() |
---|
3845 | * |
---|
3846 | * @param int $object_id ID of the object (post ID, link ID, ...) |
---|
3847 | * @param string $taxonomy Single taxonomy name |
---|
3848 | * @param int|string|array $terms Optional. Term term_id, name, slug or array of said |
---|
3849 | * @return bool|WP_Error. WP_Error on input error. |
---|
3850 | */ |
---|
3851 | function is_object_in_term( $object_id, $taxonomy, $terms = null ) { |
---|
3852 | if ( !$object_id = (int) $object_id ) |
---|
3853 | return new WP_Error( 'invalid_object', __( 'Invalid object ID' ) ); |
---|
3854 | |
---|
3855 | $object_terms = get_object_term_cache( $object_id, $taxonomy ); |
---|
3856 | if ( false === $object_terms ) |
---|
3857 | $object_terms = wp_get_object_terms( $object_id, $taxonomy ); |
---|
3858 | |
---|
3859 | if ( is_wp_error( $object_terms ) ) |
---|
3860 | return $object_terms; |
---|
3861 | if ( empty( $object_terms ) ) |
---|
3862 | return false; |
---|
3863 | if ( empty( $terms ) ) |
---|
3864 | return ( !empty( $object_terms ) ); |
---|
3865 | |
---|
3866 | $terms = (array) $terms; |
---|
3867 | |
---|
3868 | if ( $ints = array_filter( $terms, 'is_int' ) ) |
---|
3869 | $strs = array_diff( $terms, $ints ); |
---|
3870 | else |
---|
3871 | $strs =& $terms; |
---|
3872 | |
---|
3873 | foreach ( $object_terms as $object_term ) { |
---|
3874 | if ( $ints && in_array( $object_term->term_id, $ints ) ) return true; // If int, check against term_id |
---|
3875 | if ( $strs ) { |
---|
3876 | if ( in_array( $object_term->term_id, $strs ) ) return true; |
---|
3877 | if ( in_array( $object_term->name, $strs ) ) return true; |
---|
3878 | if ( in_array( $object_term->slug, $strs ) ) return true; |
---|
3879 | } |
---|
3880 | } |
---|
3881 | |
---|
3882 | return false; |
---|
3883 | } |
---|
3884 | |
---|
3885 | /** |
---|
3886 | * Determine if the given object type is associated with the given taxonomy. |
---|
3887 | * |
---|
3888 | * @since 3.0.0 |
---|
3889 | * @uses get_object_taxonomies() |
---|
3890 | * |
---|
3891 | * @param string $object_type Object type string |
---|
3892 | * @param string $taxonomy Single taxonomy name |
---|
3893 | * @return bool True if object is associated with the taxonomy, otherwise false. |
---|
3894 | */ |
---|
3895 | function is_object_in_taxonomy($object_type, $taxonomy) { |
---|
3896 | $taxonomies = get_object_taxonomies($object_type); |
---|
3897 | |
---|
3898 | if ( empty($taxonomies) ) |
---|
3899 | return false; |
---|
3900 | |
---|
3901 | if ( in_array($taxonomy, $taxonomies) ) |
---|
3902 | return true; |
---|
3903 | |
---|
3904 | return false; |
---|
3905 | } |
---|
3906 | |
---|
3907 | /** |
---|
3908 | * Get an array of ancestor IDs for a given object. |
---|
3909 | * |
---|
3910 | * @param int $object_id The ID of the object |
---|
3911 | * @param string $object_type The type of object for which we'll be retrieving ancestors. |
---|
3912 | * @return array of ancestors from lowest to highest in the hierarchy. |
---|
3913 | */ |
---|
3914 | function get_ancestors($object_id = 0, $object_type = '') { |
---|
3915 | $object_id = (int) $object_id; |
---|
3916 | |
---|
3917 | $ancestors = array(); |
---|
3918 | |
---|
3919 | if ( empty( $object_id ) ) { |
---|
3920 | |
---|
3921 | /** This filter is documented in wp-includes/taxonomy.php */ |
---|
3922 | return apply_filters( 'get_ancestors', $ancestors, $object_id, $object_type ); |
---|
3923 | } |
---|
3924 | |
---|
3925 | if ( is_taxonomy_hierarchical( $object_type ) ) { |
---|
3926 | $term = get_term($object_id, $object_type); |
---|
3927 | while ( ! is_wp_error($term) && ! empty( $term->parent ) && ! in_array( $term->parent, $ancestors ) ) { |
---|
3928 | $ancestors[] = (int) $term->parent; |
---|
3929 | $term = get_term($term->parent, $object_type); |
---|
3930 | } |
---|
3931 | } elseif ( post_type_exists( $object_type ) ) { |
---|
3932 | $ancestors = get_post_ancestors($object_id); |
---|
3933 | } |
---|
3934 | |
---|
3935 | /** |
---|
3936 | * Filter a given object's ancestors. |
---|
3937 | * |
---|
3938 | * @since 3.1.0 |
---|
3939 | * |
---|
3940 | * @param array $ancestors An array of object ancestors. |
---|
3941 | * @param int $object_id Object ID. |
---|
3942 | * @param string $object_type Type of object. |
---|
3943 | */ |
---|
3944 | return apply_filters( 'get_ancestors', $ancestors, $object_id, $object_type ); |
---|
3945 | } |
---|
3946 | |
---|
3947 | /** |
---|
3948 | * Returns the term's parent's term_ID |
---|
3949 | * |
---|
3950 | * @since 3.1.0 |
---|
3951 | * |
---|
3952 | * @param int $term_id |
---|
3953 | * @param string $taxonomy |
---|
3954 | * |
---|
3955 | * @return int|bool false on error |
---|
3956 | */ |
---|
3957 | function wp_get_term_taxonomy_parent_id( $term_id, $taxonomy ) { |
---|
3958 | $term = get_term( $term_id, $taxonomy ); |
---|
3959 | if ( !$term || is_wp_error( $term ) ) |
---|
3960 | return false; |
---|
3961 | return (int) $term->parent; |
---|
3962 | } |
---|
3963 | |
---|
3964 | /** |
---|
3965 | * Checks the given subset of the term hierarchy for hierarchy loops. |
---|
3966 | * Prevents loops from forming and breaks those that it finds. |
---|
3967 | * |
---|
3968 | * Attached to the wp_update_term_parent filter. |
---|
3969 | * |
---|
3970 | * @since 3.1.0 |
---|
3971 | * @uses wp_find_hierarchy_loop() |
---|
3972 | * |
---|
3973 | * @param int $parent term_id of the parent for the term we're checking. |
---|
3974 | * @param int $term_id The term we're checking. |
---|
3975 | * @param string $taxonomy The taxonomy of the term we're checking. |
---|
3976 | * |
---|
3977 | * @return int The new parent for the term. |
---|
3978 | */ |
---|
3979 | function wp_check_term_hierarchy_for_loops( $parent, $term_id, $taxonomy ) { |
---|
3980 | // Nothing fancy here - bail |
---|
3981 | if ( !$parent ) |
---|
3982 | return 0; |
---|
3983 | |
---|
3984 | // Can't be its own parent |
---|
3985 | if ( $parent == $term_id ) |
---|
3986 | return 0; |
---|
3987 | |
---|
3988 | // Now look for larger loops |
---|
3989 | |
---|
3990 | if ( !$loop = wp_find_hierarchy_loop( 'wp_get_term_taxonomy_parent_id', $term_id, $parent, array( $taxonomy ) ) ) |
---|
3991 | return $parent; // No loop |
---|
3992 | |
---|
3993 | // Setting $parent to the given value causes a loop |
---|
3994 | if ( isset( $loop[$term_id] ) ) |
---|
3995 | return 0; |
---|
3996 | |
---|
3997 | // There's a loop, but it doesn't contain $term_id. Break the loop. |
---|
3998 | foreach ( array_keys( $loop ) as $loop_member ) |
---|
3999 | wp_update_term( $loop_member, $taxonomy, array( 'parent' => 0 ) ); |
---|
4000 | |
---|
4001 | return $parent; |
---|
4002 | } |
---|