| 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 | } |
|---|