132
* Get a list of registered taxonomy objects.
137
* Retrieves a list of registered taxonomy names or objects.
135
* @uses $wp_taxonomies
137
* @param array $args An array of key => value arguments to match against the taxonomy objects.
138
* @param string $output The type of output to return, either taxonomy 'names' or 'objects'. 'names' is the default.
139
* @param string $operator The logical operation to perform. 'or' means only one element
140
* from the array needs to match; 'and' means all elements must match. The default is 'and'.
141
* @return array A list of taxonomy names or objects
141
* @global array $wp_taxonomies The registered taxonomies.
143
* @param array $args Optional. An array of `key => value` arguments to match against the taxonomy objects.
144
* Default empty array.
145
* @param string $output Optional. The type of output to return in the array. Accepts either taxonomy 'names'
146
* or 'objects'. Default 'names'.
147
* @param string $operator Optional. The logical operation to perform. Accepts 'and' or 'or'. 'or' means only
148
* one element from the array needs to match; 'and' means all elements must match.
150
* @return array A list of taxonomy names or objects.
143
152
function get_taxonomies( $args = array(), $output = 'names', $operator = 'and' ) {
144
153
global $wp_taxonomies;
162
* @uses $wp_taxonomies
171
* @global array $wp_taxonomies The registered taxonomies.
164
* @param array|string|object $object Name of the type of taxonomy object, or an object (row from posts)
165
* @param string $output The type of output to return, either taxonomy 'names' or 'objects'. 'names' is the default.
173
* @param array|string|WP_Post $object Name of the type of taxonomy object, or an object (row from posts)
174
* @param string $output Optional. The type of output to return in the array. Accepts either
175
* taxonomy 'names' or 'objects'. Default 'names'.
166
176
* @return array The names of all taxonomy of $object_type.
168
function get_object_taxonomies($object, $output = 'names') {
178
function get_object_taxonomies( $object, $output = 'names' ) {
169
179
global $wp_taxonomies;
171
181
if ( is_object($object) ) {
309
319
* * Defaults to _update_generic_term_count() for taxonomies attached to other object types, such as links.
310
320
* - _builtin - true if this taxonomy is a native or "built-in" taxonomy. THIS IS FOR INTERNAL USE ONLY!
322
* @todo Document $args as a hash notation.
313
325
* @since 4.2.0 Introduced `show_in_quick_edit` argument.
315
327
* @global array $wp_taxonomies Registered taxonomies.
316
328
* @global WP $wp WP instance.
318
* @param string $taxonomy Taxonomy key, must not exceed 32 characters.
330
* @param string $taxonomy Taxonomy key, must not exceed 32 characters.
319
331
* @param array|string $object_type Name of the object type for the taxonomy object.
320
* @param array|string $args See optional args description above.
321
* @return null|WP_Error WP_Error if errors, otherwise null.
332
* @param array|string $args See optional args description above.
333
* @return WP_Error|void WP_Error, if errors.
323
335
function register_taxonomy( $taxonomy, $object_type, $args = array() ) {
324
336
global $wp_taxonomies, $wp;
460
472
* - 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.
461
473
* - 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.
462
474
* - not_found - Default is "No tags found"/"No categories found", used in the meta box and taxonomy list table.
475
* - no_terms - Default is "No tags"/"No categories", used in the posts and media list tables.
464
477
* Above, the first default value is for non-hierarchical taxonomies (like tags) and the second one is for hierarchical taxonomies (like categories).
479
* @todo Better documentation for the labels array.
467
* @param object $tax Taxonomy object
468
* @return object object with all the labels as member variables
482
* @since 4.3.0 Added the `no_terms` label.
484
* @param object $tax Taxonomy object.
485
* @return object object with all the labels as member variables.
471
487
function get_taxonomy_labels( $tax ) {
472
488
$tax->labels = (array) $tax->labels;
504
521
* Add an already registered taxonomy to an object type.
507
* @uses $wp_taxonomies Modifies taxonomy object
509
* @param string $taxonomy Name of taxonomy object
510
* @param string $object_type Name of the object type
511
* @return bool True if successful, false if not
525
* @global array $wp_taxonomies The registered taxonomies.
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.
513
531
function register_taxonomy_for_object_type( $taxonomy, $object_type) {
514
532
global $wp_taxonomies;
575
598
* @global wpdb $wpdb WordPress database abstraction object.
577
* @param int|array $term_ids Term id or array of term ids of terms that will be used
578
* @param string|array $taxonomies String of taxonomy name or Array of string values of taxonomy names
579
* @param array|string $args Change the order of the object_ids, either ASC or DESC
580
* @return WP_Error|array If the taxonomy does not exist, then WP_Error will be returned. On success
600
* @param int|array $term_ids Term id or array of term ids of terms that will be used.
601
* @param string|array $taxonomies String of taxonomy name or Array of string values of taxonomy names.
602
* @param array|string $args Change the order of the object_ids, either ASC or DESC.
603
* @return WP_Error|array If the taxonomy does not exist, then WP_Error will be returned. On success.
581
604
* the array can be empty meaning that there are no $object_ids found or it will return the $object_ids found.
583
606
function get_objects_in_term( $term_ids, $taxonomies, $args = array() ) {
1290
1323
* term object, and the taxonomy name as parameters. Both hooks are expected to
1291
1324
* return a Term object.
1293
* 'get_term' hook - Takes two parameters the term Object and the taxonomy name.
1326
* {@see 'get_term'} hook - Takes two parameters the term Object and the taxonomy name.
1294
1327
* Must return term object. Used in get_term() as a catch-all filter for every
1297
* 'get_$taxonomy' hook - Takes two parameters the term Object and the taxonomy
1330
* {@see 'get_$taxonomy'} hook - Takes two parameters the term Object and the taxonomy
1298
1331
* name. Must return term object. $taxonomy will be the taxonomy name, so for
1299
1332
* example, if 'category', it would be 'get_category' as the filter name. Useful
1300
1333
* for custom taxonomies or plugging into default taxonomies.
1335
* @todo Better formatting for DocBlock
1304
1339
* @global wpdb $wpdb WordPress database abstraction object.
1305
1340
* @see sanitize_term_field() The $context param lists the available values for get_term_by() $filter param.
1307
* @param int|object $term If integer, will get from database. If object will apply filters and return $term.
1308
* @param string $taxonomy Taxonomy name that $term is part of.
1309
* @param string $output Constant OBJECT, ARRAY_A, or ARRAY_N
1310
* @param string $filter Optional, default is raw or no WordPress defined filter will applied.
1311
* @return mixed|null|WP_Error Term Row from database. Will return null if $term is empty. If taxonomy does not
1342
* @param int|object $term If integer, will get from database. If object will apply filters and return $term.
1343
* @param string $taxonomy Taxonomy name that $term is part of.
1344
* @param string $output Constant OBJECT, ARRAY_A, or ARRAY_N
1345
* @param string $filter Optional, default is raw or no WordPress defined filter will applied.
1346
* @return object|array|null|WP_Error Term Row from database. Will return null if $term is empty. If taxonomy does not
1312
1347
* exist then WP_Error will be returned.
1314
1349
function get_term($term, $taxonomy, $output = OBJECT, $filter = 'raw') {
1317
if ( empty($term) ) {
1318
$error = new WP_Error('invalid_term', __('Empty Term'));
1352
if ( empty( $term ) ) {
1353
return new WP_Error( 'invalid_term', __( 'Empty Term' ) );
1322
if ( ! taxonomy_exists($taxonomy) ) {
1323
$error = new WP_Error('invalid_taxonomy', __('Invalid taxonomy'));
1356
if ( ! taxonomy_exists( $taxonomy ) ) {
1357
return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy' ) );
1327
1360
if ( is_object($term) && empty($term->filter) ) {
1389
1422
* If $value does not exist, the return value will be false. If $taxonomy exists
1390
1423
* and $field and $value combinations exist, the Term will be returned.
1425
* @todo Better formatting for DocBlock.
1394
1429
* @global wpdb $wpdb WordPress database abstraction object.
1395
1430
* @see sanitize_term_field() The $context param lists the available values for get_term_by() $filter param.
1397
* @param string $field Either 'slug', 'name', 'id' (term_id), or 'term_taxonomy_id'
1398
* @param string|int $value Search for this term value
1399
* @param string $taxonomy Taxonomy Name
1400
* @param string $output Constant OBJECT, ARRAY_A, or ARRAY_N
1401
* @param string $filter Optional, default is raw or no WordPress defined filter will applied.
1402
* @return mixed Term Row from database. Will return false if $taxonomy does not exist or $term was not found.
1432
* @param string $field Either 'slug', 'name', 'id' (term_id), or 'term_taxonomy_id'
1433
* @param string|int $value Search for this term value
1434
* @param string $taxonomy Taxonomy Name
1435
* @param string $output Constant OBJECT, ARRAY_A, or ARRAY_N
1436
* @param string $filter Optional, default is raw or no WordPress defined filter will applied.
1437
* @return object|array|null|WP_Error|false Term Row from database.
1438
* Will return false if $taxonomy does not exist or $term was not found.
1404
1440
function get_term_by($field, $value, $taxonomy, $output = OBJECT, $filter = 'raw') {
1504
* @param string $field Term field to fetch
1505
* @param int $term Term ID
1506
* @param string $taxonomy Taxonomy Name
1507
* @param string $context Optional, default is display. Look at sanitize_term_field() for available options.
1508
* @return mixed Will return an empty string if $term is not an object or if $field is not set in $term.
1538
* @param string $field Term field to fetch.
1539
* @param int $term Term ID.
1540
* @param string $taxonomy Taxonomy Name.
1541
* @param string $context Optional, default is display. Look at sanitize_term_field() for available options.
1542
* @return string|int|null|WP_Error Will return an empty string if $term is not an object or if $field is not set in $term.
1510
1544
function get_term_field( $field, $term, $taxonomy, $context = 'display' ) {
1511
1545
$term = (int) $term;
1552
1586
* You can fully inject any customizations to the query before it is sent, as
1553
1587
* well as control the output with a filter.
1555
* The 'get_terms' filter will be called when the cache has the term and will
1589
* The {@see 'get_terms'} filter will be called when the cache has the term and will
1556
1590
* pass the found term along with the array of $taxonomies and array of $args.
1557
1591
* This filter is also called before the array of terms is passed and will pass
1558
1592
* the array of terms, along with the $taxonomies and $args.
1560
* The 'list_terms_exclusions' filter passes the compiled exclusions along with
1594
* The {@see 'list_terms_exclusions'} filter passes the compiled exclusions along with
1563
* The 'get_terms_orderby' filter passes the ORDER BY clause for the query
1597
* The {@see 'get_terms_orderby'} filter passes the `ORDER BY` clause for the query
1564
1598
* along with the $args array.
1567
1601
* @since 4.2.0 Introduced 'name' and 'childless' parameters.
1569
* @global wpdb $wpdb WordPress database abstraction object.
1603
* @global wpdb $wpdb WordPress database abstraction object.
1604
* @global array $wp_filter
1571
1606
* @param string|array $taxonomies Taxonomy name or list of Taxonomy names.
1572
1607
* @param array|string $args {
1844
1878
if ( ! empty( $args['name'] ) ) {
1845
if ( is_array( $args['name'] ) ) {
1846
$name = array_map( 'sanitize_text_field', $args['name'] );
1847
$where .= " AND t.name IN ('" . implode( "', '", array_map( 'esc_sql', $name ) ) . "')";
1849
$name = sanitize_text_field( $args['name'] );
1850
$where .= $wpdb->prepare( " AND t.name = %s", $name );
1879
$names = (array) $args['name'];
1880
foreach ( $names as &$_name ) {
1881
$_name = sanitize_term_field( 'name', $_name, 0, reset( $taxonomies ), 'db' );
1884
$where .= " AND t.name IN ('" . implode( "', '", array_map( 'esc_sql', $names ) ) . "')";
1854
1887
if ( ! empty( $args['slug'] ) ) {
2071
2102
* @global wpdb $wpdb WordPress database abstraction object.
2073
* @param int|string $term The term to check
2074
* @param string $taxonomy The taxonomy name to use
2075
* @param int $parent Optional. ID of parent term under which to confine the exists search.
2104
* @param int|string $term The term to check
2105
* @param string $taxonomy The taxonomy name to use
2106
* @param int $parent Optional. ID of parent term under which to confine the exists search.
2076
2107
* @return mixed Returns null if the term does not exist. Returns the term ID
2077
2108
* if no taxonomy is specified and the term ID exists. Returns
2078
2109
* an array of the term ID and the term taxonomy ID the taxonomy
2137
* @param int|object $term1 ID or object to check if this is the parent term.
2138
* @param int|object $term2 The child term.
2139
* @param string $taxonomy Taxonomy name that $term1 and $term2 belong to.
2140
* @return bool Whether $term2 is child of $term1
2168
* @param int|object $term1 ID or object to check if this is the parent term.
2169
* @param int|object $term2 The child term.
2170
* @param string $taxonomy Taxonomy name that $term1 and `$term2` belong to.
2171
* @return bool Whether `$term2` is a child of `$term1`.
2142
2173
function term_is_ancestor_of( $term1, $term2, $taxonomy ) {
2143
2174
if ( ! isset( $term1->term_id ) )
2167
* @param array|object $term The term to check
2168
* @param string $taxonomy The taxonomy name to use
2169
* @param string $context Default is 'display'.
2170
* @return array|object Term with all fields sanitized
2198
* @param array|object $term The term to check.
2199
* @param string $taxonomy The taxonomy name to use.
2200
* @param string $context Optional. Context in which to sanitize the term. Accepts 'edit', 'db',
2201
* 'display', 'attribute', or 'js'. Default 'display'.
2202
* @return array|object Term with all fields sanitized.
2172
2204
function sanitize_term($term, $taxonomy, $context = 'display') {
2174
2205
$fields = array( 'term_id', 'name', 'description', 'slug', 'count', 'parent', 'term_group', 'term_taxonomy_id', 'object_id' );
2176
2207
$do_object = is_object( $term );
2213
* @global wpdb $wpdb WordPress database abstraction object.
2215
* @param string $field Term field to sanitize
2216
* @param string $value Search for this term value
2217
* @param int $term_id Term ID
2218
* @param string $taxonomy Taxonomy Name
2219
* @param string $context Either edit, db, display, attribute, or js.
2220
* @return mixed sanitized field
2244
* @param string $field Term field to sanitize.
2245
* @param string $value Search for this term value.
2246
* @param int $term_id Term ID.
2247
* @param string $taxonomy Taxonomy Name.
2248
* @param string $context Context in which to sanitize the term field. Accepts 'edit', 'db', 'display',
2249
* 'attribute', or 'js'.
2250
* @return mixed Sanitized field.
2222
2252
function sanitize_term_field($field, $value, $term_id, $taxonomy, $context) {
2223
2253
$int_fields = array( 'parent', 'term_id', 'count', 'term_group', 'term_taxonomy_id', 'object_id' );
2371
2403
* Default $args is 'hide_empty' which can be 'hide_empty=true' or array('hide_empty' => true).
2405
* @todo Document $args as a hash notation.
2375
* @param string $taxonomy Taxonomy name
2376
* @param array|string $args Overwrite defaults. See get_terms()
2377
* @return int|WP_Error How many terms are in $taxonomy. WP_Error if $taxonomy does not exist.
2409
* @param string $taxonomy Taxonomy name
2410
* @param array|string $args Overwrite defaults. See get_terms()
2411
* @return array|int|WP_Error How many terms are in $taxonomy. WP_Error if $taxonomy does not exist.
2379
2413
function wp_count_terms( $taxonomy, $args = array() ) {
2380
2414
$defaults = array('hide_empty' => false);
2422
2456
* If the term is a parent of other terms, then the children will be updated to
2423
2457
* that term's parent.
2425
* The $args 'default' will only override the terms found, if there is only one
2459
* The `$args` 'default' will only override the terms found, if there is only one
2426
2460
* term found. Any other and the found terms are used.
2428
2462
* The $args 'force_default' will force the term supplied as default to be
2429
2463
* assigned even if the object was not going to be termless
2465
* @todo Document $args as a hash notation.
2433
2469
* @global wpdb $wpdb WordPress database abstraction object.
2435
* @param int $term Term ID
2436
* @param string $taxonomy Taxonomy Name
2437
* @param array|string $args Optional. Change 'default' term id and override found term ids.
2438
* @return bool|WP_Error Returns false if not term; true if completes delete action.
2471
* @param int $term Term ID.
2472
* @param string $taxonomy Taxonomy Name.
2473
* @param array|string $args Optional. Change 'default' term id and override found term ids.
2474
* @return bool|int|WP_Error Returns false if not term; true if completes delete action.
2440
2476
function wp_delete_term( $term, $taxonomy, $args = array() ) {
2679
2716
if ( in_array( $orderby, array( 'term_id', 'name', 'slug', 'term_group' ) ) ) {
2680
2717
$orderby = "t.$orderby";
2681
} else if ( in_array( $orderby, array( 'count', 'parent', 'taxonomy', 'term_taxonomy_id' ) ) ) {
2718
} elseif ( in_array( $orderby, array( 'count', 'parent', 'taxonomy', 'term_taxonomy_id' ) ) ) {
2682
2719
$orderby = "tt.$orderby";
2683
} else if ( 'term_order' === $orderby ) {
2720
} elseif ( 'term_order' === $orderby ) {
2684
2721
$orderby = 'tr.term_order';
2685
} else if ( 'none' === $orderby ) {
2722
} elseif ( 'none' === $orderby ) {
3022
3059
* Fires after a new term is created, and after the term cache has been cleaned.
3063
* @param int $term_id Term ID.
3064
* @param int $tt_id Term taxonomy ID.
3065
* @param string $taxonomy Taxonomy slug.
3026
do_action( "created_term", $term_id, $tt_id, $taxonomy );
3067
do_action( 'created_term', $term_id, $tt_id, $taxonomy );
3029
3070
* Fires after a new term in a specific taxonomy is created, and after the term
3030
3071
* cache has been cleaned.
3073
* The dynamic portion of the hook name, `$taxonomy`, refers to the taxonomy slug.
3034
3077
* @param int $term_id Term ID.
3192
3237
* @global wpdb $wpdb WordPress database abstraction object.
3194
* @param int $object_id The ID of the object from which the terms will be removed.
3195
* @param array|int|string $terms The slug(s) or ID(s) of the term(s) to remove.
3196
* @param array|string $taxonomy Taxonomy name.
3239
* @param int $object_id The ID of the object from which the terms will be removed.
3240
* @param array|int|string $terms The slug(s) or ID(s) of the term(s) to remove.
3241
* @param array|string $taxonomy Taxonomy name.
3197
3242
* @return bool|WP_Error True on success, false or WP_Error on failure.
3199
3244
function wp_remove_object_terms( $object_id, $terms, $taxonomy ) {
3274
3320
* If that still doesn't return an unique slug, then it try to append a number
3275
3321
* until it finds a number that is truly unique.
3277
* The only purpose for $term is for appending a parent, if one exists.
3323
* The only purpose for `$term` is for appending a parent, if one exists.
3281
3327
* @global wpdb $wpdb WordPress database abstraction object.
3283
* @param string $slug The string that will be tried for a unique slug
3284
* @param object $term The term object that the $slug will belong too
3329
* @param string $slug The string that will be tried for a unique slug.
3330
* @param object $term The term object that the `$slug` will belong to.
3285
3331
* @return string Will return a true unique slug.
3287
function wp_unique_term_slug($slug, $term) {
3333
function wp_unique_term_slug( $slug, $term ) {
3290
if ( ! term_exists( $slug ) )
3336
$needs_suffix = true;
3337
$original_slug = $slug;
3293
3339
// As of 4.1, duplicate slugs are allowed as long as they're in different taxonomies.
3294
if ( get_option( 'db_version' ) >= 30133 && ! get_term_by( 'slug', $slug, $term->taxonomy ) ) {
3340
if ( ! term_exists( $slug ) || get_option( 'db_version' ) >= 30133 && ! get_term_by( 'slug', $slug, $term->taxonomy ) ) {
3341
$needs_suffix = false;
3298
// If the taxonomy supports hierarchy and the term has a parent, make the slug unique
3299
// by incorporating parent slugs.
3300
if ( is_taxonomy_hierarchical($term->taxonomy) && !empty($term->parent) ) {
3345
* If the taxonomy supports hierarchy and the term has a parent, make the slug unique
3346
* by incorporating parent slugs.
3348
$parent_suffix = '';
3349
if ( $needs_suffix && is_taxonomy_hierarchical( $term->taxonomy ) && ! empty( $term->parent ) ) {
3301
3350
$the_parent = $term->parent;
3302
3351
while ( ! empty($the_parent) ) {
3303
3352
$parent_term = get_term($the_parent, $term->taxonomy);
3304
3353
if ( is_wp_error($parent_term) || empty($parent_term) )
3306
$slug .= '-' . $parent_term->slug;
3307
if ( ! term_exists( $slug ) )
3355
$parent_suffix .= '-' . $parent_term->slug;
3356
if ( ! term_exists( $slug . $parent_suffix ) ) {
3310
3360
if ( empty($parent_term->parent) )
3316
3366
// If we didn't get a unique slug, try appending a number to make it unique.
3317
if ( ! empty( $term->term_id ) )
3318
$query = $wpdb->prepare( "SELECT slug FROM $wpdb->terms WHERE slug = %s AND term_id != %d", $slug, $term->term_id );
3320
$query = $wpdb->prepare( "SELECT slug FROM $wpdb->terms WHERE slug = %s", $slug );
3322
if ( $wpdb->get_var( $query ) ) {
3325
$alt_slug = $slug . "-$num";
3327
$slug_check = $wpdb->get_var( $wpdb->prepare( "SELECT slug FROM $wpdb->terms WHERE slug = %s", $alt_slug ) );
3328
} while ( $slug_check );
3369
* Filter whether the proposed unique term slug is bad.
3373
* @param bool $needs_suffix Whether the slug needs to be made unique with a suffix.
3374
* @param string $slug The slug.
3375
* @param object $term Term object.
3377
if ( apply_filters( 'wp_unique_term_slug_is_bad_slug', $needs_suffix, $slug, $term ) ) {
3378
if ( $parent_suffix ) {
3379
$slug .= $parent_suffix;
3381
if ( ! empty( $term->term_id ) )
3382
$query = $wpdb->prepare( "SELECT slug FROM $wpdb->terms WHERE slug = %s AND term_id != %d", $slug, $term->term_id );
3384
$query = $wpdb->prepare( "SELECT slug FROM $wpdb->terms WHERE slug = %s", $slug );
3386
if ( $wpdb->get_var( $query ) ) {
3389
$alt_slug = $slug . "-$num";
3391
$slug_check = $wpdb->get_var( $wpdb->prepare( "SELECT slug FROM $wpdb->terms WHERE slug = %s", $alt_slug ) );
3392
} while ( $slug_check );
3399
* Filter the unique term slug.
3403
* @param string $slug Unique term slug.
3404
* @param object $term Term object.
3405
* @param string $original_slug Slug originally passed to the function for testing.
3407
return apply_filters( 'wp_unique_term_slug', $slug, $term, $original_slug );
3350
3425
* a WP_Error will be passed back. If you don't pass any slug, then a unique one
3351
3426
* will be created for you.
3353
* For what can be overrode in $args, check the term scheme can contain and stay
3428
* For what can be overrode in `$args`, check the term scheme can contain and stay
3354
3429
* away from the term keys.
3358
3433
* @global wpdb $wpdb WordPress database abstraction object.
3360
* @param int $term_id The ID of the term
3361
* @param string $taxonomy The context in which to relate the term to the object.
3362
* @param array|string $args Overwrite term field values
3435
* @param int $term_id The ID of the term
3436
* @param string $taxonomy The context in which to relate the term to the object.
3437
* @param array|string $args Optional. Array of get_terms() arguments. Default empty array.
3363
3438
* @return array|WP_Error Returns Term ID and Taxonomy Term ID
3365
3440
function wp_update_term( $term_id, $taxonomy, $args = array() ) {
3689
3767
* Removes the taxonomy relationship to terms from the cache.
3691
* Will remove the entire taxonomy relationship containing term $object_id. The
3692
* term IDs have to exist within the taxonomy $object_type for the deletion to
3769
* Will remove the entire taxonomy relationship containing term `$object_id`. The
3770
* term IDs have to exist within the taxonomy `$object_type` for the deletion to
3697
* @see get_object_taxonomies() for more on $object_type
3775
* @see get_object_taxonomies() for more on $object_type.
3699
* @param int|array $object_ids Single or list of term object ID(s)
3700
* @param array|string $object_type The taxonomy object type
3777
* @param int|array $object_ids Single or list of term object ID(s).
3778
* @param array|string $object_type The taxonomy object type.
3702
3780
function clean_object_term_cache($object_ids, $object_type) {
3703
3781
if ( !is_array($object_ids) )
3730
3808
* @global wpdb $wpdb WordPress database abstraction object.
3809
* @global bool $_wp_suspend_cache_invalidation
3732
* @param int|array $ids Single or list of Term IDs
3733
* @param string $taxonomy Can be empty and will assume tt_ids, else will use for context.
3734
* @param bool $clean_taxonomy Whether to clean taxonomy wide caches (true), or just individual term object caches (false). Default is true.
3811
* @param int|array $ids Single or list of Term IDs.
3812
* @param string $taxonomy Optional. Can be empty and will assume `tt_ids`, else will use for context.
3814
* @param bool $clean_taxonomy Optional. Whether to clean taxonomy wide caches (true), or just individual
3815
* term object caches (false). Default true.
3736
3817
function clean_term_cache($ids, $taxonomy = '', $clean_taxonomy = true) {
3818
global $wpdb, $_wp_suspend_cache_invalidation;
3820
if ( ! empty( $_wp_suspend_cache_invalidation ) ) {
3739
3824
if ( !is_array($ids) )
3740
3825
$ids = array($ids);
3792
* @param int $id Term object ID
3793
* @param string $taxonomy Taxonomy Name
3794
* @return bool|array Empty array if $terms found, but not $taxonomy. False if nothing is in cache for $taxonomy and $id.
3877
* @param int $id Term object ID.
3878
* @param string $taxonomy Taxonomy name.
3879
* @return bool|mixed Empty array if $terms found, but not `$taxonomy`. False if nothing is in cache
3880
* for `$taxonomy` and `$id`.
3796
function get_object_term_cache($id, $taxonomy) {
3797
$cache = wp_cache_get($id, "{$taxonomy}_relationships");
3882
function get_object_term_cache( $id, $taxonomy ) {
3883
return wp_cache_get( $id, "{$taxonomy}_relationships" );
3915
3999
* Get the subset of $terms that are descendants of $term_id.
3917
* If $terms is an array of objects, then _get_term_children returns an array of objects.
3918
* If $terms is an array of IDs, then _get_term_children returns an array of IDs.
4001
* If `$terms` is an array of objects, then _get_term_children() returns an array of objects.
4002
* If `$terms` is an array of IDs, then _get_term_children() returns an array of IDs.
3920
4004
* @access private
3923
* @param int $term_id The ancestor term: all returned terms should be descendants of $term_id.
4007
* @param int $term_id The ancestor term: all returned terms should be descendants of `$term_id`.
3924
4008
* @param array $terms The set of terms - either an array of term objects or term IDs - from which those that
3925
4009
* are descendants of $term_id will be chosen.
3926
4010
* @param string $taxonomy The taxonomy which determines the hierarchy of the terms.
3927
* @param array $ancestors Term ancestors that have already been identified. Passed by reference, to keep track of
3928
* found terms when recursing the hierarchy. The array of located ancestors is used to prevent
3929
* infinite recursion loops. For performance, term_ids are used as array keys, with 1 as value.
3930
* @return array The subset of $terms that are descendants of $term_id.
4011
* @param array $ancestors Optional. Term ancestors that have already been identified. Passed by reference, to keep
4012
* track of found terms when recursing the hierarchy. The array of located ancestors is used
4013
* to prevent infinite recursion loops. For performance, `term_ids` are used as array keys,
4014
* with 1 as value. Default empty array.
4015
* @return array|WP_Error The subset of $terms that are descendants of $term_id.
3932
4017
function _get_term_children( $term_id, $terms, $taxonomy, &$ancestors = array() ) {
3933
4018
$empty_array = array();
3990
4075
* @global wpdb $wpdb WordPress database abstraction object.
3992
* @param array $terms List of Term IDs
3993
* @param string $taxonomy Term Context
3994
* @return null Will break from function if conditions are not met.
4077
* @param array $terms List of term IDs, passed by reference.
4078
* @param string $taxonomy Term context.
3996
function _pad_term_counts(&$terms, $taxonomy) {
4080
function _pad_term_counts( &$terms, $taxonomy ) {
3999
4083
// This function only works for hierarchical taxonomies like post categories.
4133
* Create a new term for a term_taxonomy item that currently shares its term with another term_taxonomy.
4217
* Create a new term for a term_taxonomy item that currently shares its term
4218
* with another term_taxonomy.
4138
* @param int $term_id ID of the shared term.
4139
* @param int $term_taxonomy_id ID of the term_taxonomy item to receive a new term.
4222
* @since 4.3.0 Introduced `$record` parameter. Also, `$term_id` and
4223
* `$term_taxonomy_id` can now accept objects.
4225
* @global wpdb $wpdb
4227
* @param int|object $term_id ID of the shared term, or the shared term object.
4228
* @param int|object $term_taxonomy_id ID of the term_taxonomy item to receive a new term, or the term_taxonomy object
4229
* (corresponding to a row from the term_taxonomy table).
4230
* @param bool $record Whether to record data about the split term in the options table. The recording
4231
* process has the potential to be resource-intensive, so during batch operations
4232
* it can be beneficial to skip inline recording and do it just once, after the
4233
* batch is processed. Only set this to `false` if you know what you are doing.
4140
4235
* @return int|WP_Error When the current term does not need to be split (or cannot be split on the current
4141
4236
* database schema), `$term_id` is returned. When the term is successfully split, the
4142
4237
* new term_id is returned. A WP_Error is returned for miscellaneous errors.
4144
function _split_shared_term( $term_id, $term_taxonomy_id ) {
4239
function _split_shared_term( $term_id, $term_taxonomy_id, $record = true ) {
4147
// Don't try to split terms if database schema does not support shared slugs.
4148
$current_db_version = get_option( 'db_version' );
4149
if ( $current_db_version < 30133 ) {
4242
if ( is_object( $term_id ) ) {
4243
$shared_term = $term_id;
4244
$term_id = intval( $shared_term->term_id );
4247
if ( is_object( $term_taxonomy_id ) ) {
4248
$term_taxonomy = $term_taxonomy_id;
4249
$term_taxonomy_id = intval( $term_taxonomy->term_taxonomy_id );
4153
4252
// If there are no shared term_taxonomy rows, there's nothing to do here.
4154
4253
$shared_tt_count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_taxonomy tt WHERE tt.term_id = %d AND tt.term_taxonomy_id != %d", $term_id, $term_taxonomy_id ) );
4155
4255
if ( ! $shared_tt_count ) {
4156
4256
return $term_id;
4260
* Verify that the term_taxonomy_id passed to the function is actually associated with the term_id.
4261
* If there's a mismatch, it may mean that the term is already split. Return the actual term_id from the db.
4263
$check_term_id = $wpdb->get_var( $wpdb->prepare( "SELECT term_id FROM $wpdb->term_taxonomy WHERE term_taxonomy_id = %d", $term_taxonomy_id ) );
4264
if ( $check_term_id != $term_id ) {
4265
return $check_term_id;
4159
4268
// Pull up data about the currently shared slug, which we'll use to populate the new one.
4160
$shared_term = $wpdb->get_row( $wpdb->prepare( "SELECT t.* FROM $wpdb->terms t WHERE t.term_id = %d", $term_id ) );
4269
if ( empty( $shared_term ) ) {
4270
$shared_term = $wpdb->get_row( $wpdb->prepare( "SELECT t.* FROM $wpdb->terms t WHERE t.term_id = %d", $term_id ) );
4162
4273
$new_term_data = array(
4163
4274
'name' => $shared_term->name,
4180
4291
// Reassign child terms to the new parent.
4181
$term_taxonomy = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->term_taxonomy WHERE term_taxonomy_id = %d", $term_taxonomy_id ) );
4182
$children_tt_ids = $wpdb->get_col( $wpdb->prepare( "SELECT term_taxonomy_id FROM $wpdb->term_taxonomy WHERE taxonomy = %s AND parent = %d", $term_taxonomy->taxonomy, $term_id ) );
4292
if ( empty( $term_taxonomy ) ) {
4293
$term_taxonomy = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->term_taxonomy WHERE term_taxonomy_id = %d", $term_taxonomy_id ) );
4296
$children_tt_ids = $wpdb->get_col( $wpdb->prepare( "SELECT term_taxonomy_id FROM $wpdb->term_taxonomy WHERE parent = %d AND taxonomy = %s", $term_id, $term_taxonomy->taxonomy ) );
4184
4297
if ( ! empty( $children_tt_ids ) ) {
4185
4298
foreach ( $children_tt_ids as $child_tt_id ) {
4186
4299
$wpdb->update( $wpdb->term_taxonomy,
4205
4318
// Keep a record of term_ids that have been split, keyed by old term_id. See {@see wp_get_split_term()}.
4206
$split_term_data = get_option( '_split_terms', array() );
4207
if ( ! isset( $split_term_data[ $term_id ] ) ) {
4208
$split_term_data[ $term_id ] = array();
4320
$split_term_data = get_option( '_split_terms', array() );
4321
if ( ! isset( $split_term_data[ $term_id ] ) ) {
4322
$split_term_data[ $term_id ] = array();
4325
$split_term_data[ $term_id ][ $term_taxonomy->taxonomy ] = $new_term_id;
4326
update_option( '_split_terms', $split_term_data );
4211
$split_term_data[ $term_id ][ $term_taxonomy->taxonomy ] = $new_term_id;
4213
update_option( '_split_terms', $split_term_data );
4216
4330
* Fires after a previously shared taxonomy term is split into two separate terms.
4345
* Splits a batch of shared taxonomy terms.
4349
* @global wpdb $wpdb WordPress database abstraction object.
4351
function _wp_batch_split_terms() {
4354
$lock_name = 'term_split.lock';
4357
$lock_result = $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO `$wpdb->options` ( `option_name`, `option_value`, `autoload` ) VALUES (%s, %s, 'no') /* LOCK */", $lock_name, time() ) );
4359
if ( ! $lock_result ) {
4360
$lock_result = get_option( $lock_name );
4362
// Bail if we were unable to create a lock, or if the existing lock is still valid.
4363
if ( ! $lock_result || ( $lock_result > ( time() - HOUR_IN_SECONDS ) ) ) {
4364
wp_schedule_single_event( time() + ( 5 * MINUTE_IN_SECONDS ), 'wp_split_shared_term_batch' );
4369
// Update the lock, as by this point we've definitely got a lock, just need to fire the actions.
4370
update_option( $lock_name, time() );
4372
// Get a list of shared terms (those with more than one associated row in term_taxonomy).
4373
$shared_terms = $wpdb->get_results(
4374
"SELECT tt.term_id, t.*, count(*) as term_tt_count FROM {$wpdb->term_taxonomy} tt
4375
LEFT JOIN {$wpdb->terms} t ON t.term_id = tt.term_id
4377
HAVING term_tt_count > 1
4381
// No more terms, we're done here.
4382
if ( ! $shared_terms ) {
4383
update_option( 'finished_splitting_shared_terms', true );
4384
delete_option( $lock_name );
4388
// Shared terms found? We'll need to run this script again.
4389
wp_schedule_single_event( time() + ( 2 * MINUTE_IN_SECONDS ), 'wp_split_shared_term_batch' );
4391
// Rekey shared term array for faster lookups.
4392
$_shared_terms = array();
4393
foreach ( $shared_terms as $shared_term ) {
4394
$term_id = intval( $shared_term->term_id );
4395
$_shared_terms[ $term_id ] = $shared_term;
4397
$shared_terms = $_shared_terms;
4399
// Get term taxonomy data for all shared terms.
4400
$shared_term_ids = implode( ',', array_keys( $shared_terms ) );
4401
$shared_tts = $wpdb->get_results( "SELECT * FROM {$wpdb->term_taxonomy} WHERE `term_id` IN ({$shared_term_ids})" );
4403
// Split term data recording is slow, so we do it just once, outside the loop.
4404
$split_term_data = get_option( '_split_terms', array() );
4405
$skipped_first_term = $taxonomies = array();
4406
foreach ( $shared_tts as $shared_tt ) {
4407
$term_id = intval( $shared_tt->term_id );
4409
// Don't split the first tt belonging to a given term_id.
4410
if ( ! isset( $skipped_first_term[ $term_id ] ) ) {
4411
$skipped_first_term[ $term_id ] = 1;
4415
if ( ! isset( $split_term_data[ $term_id ] ) ) {
4416
$split_term_data[ $term_id ] = array();
4419
// Keep track of taxonomies whose hierarchies need flushing.
4420
if ( ! isset( $taxonomies[ $shared_tt->taxonomy ] ) ) {
4421
$taxonomies[ $shared_tt->taxonomy ] = 1;
4425
$split_term_data[ $term_id ][ $shared_tt->taxonomy ] = _split_shared_term( $shared_terms[ $term_id ], $shared_tt, false );
4428
// Rebuild the cached hierarchy for each affected taxonomy.
4429
foreach ( array_keys( $taxonomies ) as $tax ) {
4430
delete_option( "{$tax}_children" );
4431
_get_term_hierarchy( $tax );
4434
update_option( '_split_terms', $split_term_data );
4436
delete_option( $lock_name );
4440
* In order to avoid the wp_batch_split_terms() job being accidentally removed,
4441
* check that it's still scheduled while we haven't finished splitting terms.
4446
function _wp_check_for_scheduled_split_terms() {
4447
if ( ! get_option( 'finished_splitting_shared_terms' ) && ! wp_next_scheduled( 'wp_batch_split_terms' ) ) {
4448
wp_schedule_single_event( 'wp_batch_split_terms', time() + MINUTE_IN_SECONDS );
4231
4453
* Check default categories when a term gets split to see if any of them need to be updated.
4510
* If the term being split is a nav_menu, change associations.
4515
* @global wpdb $wpdb
4517
* @param int $term_id ID of the formerly shared term.
4518
* @param int $new_term_id ID of the new term created for the $term_taxonomy_id.
4519
* @param int $term_taxonomy_id ID for the term_taxonomy row affected by the split.
4520
* @param string $taxonomy Taxonomy for the split term.
4522
function _wp_check_split_nav_menu_terms( $term_id, $new_term_id, $term_taxonomy_id, $taxonomy ) {
4523
if ( 'nav_menu' !== $taxonomy ) {
4527
// Update menu locations.
4528
$locations = get_nav_menu_locations();
4529
foreach ( $locations as $location => $menu_id ) {
4530
if ( $term_id == $menu_id ) {
4531
$locations[ $location ] = $new_term_id;
4534
set_theme_mod( 'nav_menu_locations', $locations );
4286
4538
* Get data about terms that previously shared a single term_id, but have since been split.
4309
4561
* @param int $old_term_id Term ID. This is the old, pre-split term ID.
4310
4562
* @param string $taxonomy Taxonomy that the term belongs to.
4311
* @return bool|int If a previously split term is found corresponding to the old term_id and taxonomy,
4312
* the new term_id will be returned. If no previously split term is found matching
4313
* the parameters, returns false.
4563
* @return int|false If a previously split term is found corresponding to the old term_id and taxonomy,
4564
* the new term_id will be returned. If no previously split term is found matching
4565
* the parameters, returns false.
4315
4567
function wp_get_split_term( $old_term_id, $taxonomy ) {
4316
4568
$split_terms = wp_get_split_terms( $old_term_id );
4583
* @global WP_Rewrite $wp_rewrite
4331
4585
* @param object|int|string $term The term object, ID, or slug whose link will be retrieved.
4332
4586
* @param string $taxonomy Optional. Taxonomy. Default empty.
4333
4587
* @return string|WP_Error HTML link to taxonomy term archive on success, WP_Error if term does not exist.
4335
function get_term_link( $term, $taxonomy = '') {
4589
function get_term_link( $term, $taxonomy = '' ) {
4336
4590
global $wp_rewrite;
4338
4592
if ( !is_object($term) ) {
4339
if ( is_int($term) ) {
4340
$term = get_term($term, $taxonomy);
4593
if ( is_int( $term ) ) {
4594
$term = get_term( $term, $taxonomy );
4342
$term = get_term_by('slug', $term, $taxonomy);
4596
$term = get_term_by( 'slug', $term, $taxonomy );
4543
* @param int $object_id ID of the object (post ID, link ID, ...)
4544
* @param string $taxonomy Single taxonomy name
4545
* @param int|string|array $terms Optional. Term term_id, name, slug or array of said
4797
* @param int $object_id ID of the object (post ID, link ID, ...).
4798
* @param string $taxonomy Single taxonomy name.
4799
* @param int|string|array $terms Optional. Term term_id, name, slug or array of said. Default null.
4546
4800
* @return bool|WP_Error WP_Error on input error.
4548
4802
function is_object_in_term( $object_id, $taxonomy, $terms = null ) {
4596
* @param string $object_type Object type string
4597
* @param string $taxonomy Single taxonomy name
4850
* @param string $object_type Object type string.
4851
* @param string $taxonomy Single taxonomy name.
4598
4852
* @return bool True if object is associated with the taxonomy, otherwise false.
4600
function is_object_in_taxonomy($object_type, $taxonomy) {
4601
$taxonomies = get_object_taxonomies($object_type);
4603
if ( empty($taxonomies) )
4854
function is_object_in_taxonomy( $object_type, $taxonomy ) {
4855
$taxonomies = get_object_taxonomies( $object_type );
4856
if ( empty( $taxonomies ) ) {
4606
if ( in_array($taxonomy, $taxonomies) )
4859
return in_array( $taxonomy, $taxonomies );
4669
* Returns the term's parent's term_ID
4919
* Returns the term's parent's term_ID.
4673
* @param int $term_id
4674
* @param string $taxonomy
4676
* @return int|bool false on error
4923
* @param int $term_id Term ID.
4924
* @param string $taxonomy Taxonomy name.
4925
* @return int|false False on error.
4678
4927
function wp_get_term_taxonomy_parent_id( $term_id, $taxonomy ) {
4679
4928
$term = get_term( $term_id, $taxonomy );
4680
if ( !$term || is_wp_error( $term ) )
4929
if ( ! $term || is_wp_error( $term ) ) {
4682
4932
return (int) $term->parent;
4686
4936
* Checks the given subset of the term hierarchy for hierarchy loops.
4687
4937
* Prevents loops from forming and breaks those that it finds.
4689
* Attached to the wp_update_term_parent filter.
4939
* Attached to the {@see 'wp_update_term_parent'} filter.
4693
* @param int $parent term_id of the parent for the term we're checking.
4694
* @param int $term_id The term we're checking.
4943
* @param int $parent `term_id` of the parent for the term we're checking.
4944
* @param int $term_id The term we're checking.
4695
4945
* @param string $taxonomy The taxonomy of the term we're checking.
4697
4947
* @return int The new parent for the term.
4701
4951
if ( !$parent )
4704
// Can't be its own parent
4954
// Can't be its own parent.
4705
4955
if ( $parent == $term_id )
4708
// Now look for larger loops
4958
// Now look for larger loops.
4710
4959
if ( !$loop = wp_find_hierarchy_loop( 'wp_get_term_taxonomy_parent_id', $term_id, $parent, array( $taxonomy ) ) )
4711
4960
return $parent; // No loop
4713
// Setting $parent to the given value causes a loop
4962
// Setting $parent to the given value causes a loop.
4714
4963
if ( isset( $loop[$term_id] ) )