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