2007-09-15 19:35:32 +02:00
< ? php
2007-10-16 00:49:31 +02:00
/**
2008-08-30 23:23:43 +02:00
* Taxonomy API
*
2015-05-05 04:01:25 +02:00
* @ since 2.3 . 0
*
2007-10-16 00:49:31 +02:00
* @ package WordPress
* @ subpackage Taxonomy
*/
2007-09-15 19:35:32 +02:00
//
// Taxonomy Registration
//
/**
2012-01-23 20:58:26 +01:00
* Creates the initial taxonomies .
*
* This function fires twice : in wp - settings . php before plugins are loaded ( for
2015-05-05 04:01:25 +02:00
* backwards compatibility reasons ), and again on the { @ see 'init' } action . We must
* avoid registering rewrite rules before the { @ see 'init' } action .
*
* @ since 2.8 . 0
*
* @ global WP_Rewrite $wp_rewrite The WordPress rewrite class .
2007-09-15 19:35:32 +02:00
*/
2009-04-17 01:17:49 +02:00
function create_initial_taxonomies () {
2011-03-09 06:18:45 +01:00
global $wp_rewrite ;
2012-01-23 20:58:26 +01:00
if ( ! did_action ( 'init' ) ) {
$rewrite = array ( 'category' => false , 'post_tag' => false , 'post_format' => false );
} else {
2014-03-28 22:29:13 +01:00
/**
* Filter the post formats rewrite base .
*
* @ since 3.1 . 0
*
* @ param string $context Context of the rewrite base . Default 'type' .
*/
2012-01-23 20:58:26 +01:00
$post_format_base = apply_filters ( 'post_format_rewrite_base' , 'type' );
$rewrite = array (
'category' => array (
'hierarchical' => true ,
'slug' => get_option ( 'category_base' ) ? get_option ( 'category_base' ) : 'category' ,
2012-01-23 21:10:01 +01:00
'with_front' => ! get_option ( 'category_base' ) || $wp_rewrite -> using_index_permalinks (),
2012-01-23 20:58:26 +01:00
'ep_mask' => EP_CATEGORIES ,
),
'post_tag' => array (
2014-10-09 02:58:20 +02:00
'hierarchical' => false ,
2012-01-23 20:58:26 +01:00
'slug' => get_option ( 'tag_base' ) ? get_option ( 'tag_base' ) : 'tag' ,
2012-01-23 21:10:01 +01:00
'with_front' => ! get_option ( 'tag_base' ) || $wp_rewrite -> using_index_permalinks (),
2012-01-23 20:58:26 +01:00
'ep_mask' => EP_TAGS ,
),
'post_format' => $post_format_base ? array ( 'slug' => $post_format_base ) : false ,
);
}
2010-05-04 08:13:28 +02:00
register_taxonomy ( 'category' , 'post' , array (
'hierarchical' => true ,
2010-10-06 13:04:03 +02:00
'query_var' => 'category_name' ,
2012-01-23 20:58:26 +01:00
'rewrite' => $rewrite [ 'category' ],
2010-05-04 08:13:28 +02:00
'public' => true ,
'show_ui' => true ,
2012-09-08 05:18:36 +02:00
'show_admin_column' => true ,
2010-05-04 08:13:28 +02:00
'_builtin' => true ,
2010-09-13 18:44:14 +02:00
) );
2010-01-26 12:32:04 +01:00
register_taxonomy ( 'post_tag' , 'post' , array (
2010-05-04 08:13:28 +02:00
'hierarchical' => false ,
2010-09-13 18:44:14 +02:00
'query_var' => 'tag' ,
2012-01-23 20:58:26 +01:00
'rewrite' => $rewrite [ 'post_tag' ],
2010-05-04 08:13:28 +02:00
'public' => true ,
'show_ui' => true ,
2012-09-08 05:18:36 +02:00
'show_admin_column' => true ,
2010-05-04 08:13:28 +02:00
'_builtin' => true ,
) );
2010-01-26 12:32:04 +01:00
2010-05-04 08:13:28 +02:00
register_taxonomy ( 'nav_menu' , 'nav_menu_item' , array (
2010-10-15 16:53:55 +02:00
'public' => false ,
2010-05-04 08:13:28 +02:00
'hierarchical' => false ,
2010-05-14 02:34:04 +02:00
'labels' => array (
'name' => __ ( 'Navigation Menus' ),
'singular_name' => __ ( 'Navigation Menu' ),
),
2010-05-04 08:13:28 +02:00
'query_var' => false ,
'rewrite' => false ,
'show_ui' => false ,
'_builtin' => true ,
2010-05-29 18:46:46 +02:00
'show_in_nav_menus' => false ,
2010-12-03 11:13:17 +01:00
) );
2010-02-20 22:57:43 +01:00
2010-05-04 08:13:28 +02:00
register_taxonomy ( 'link_category' , 'link' , array (
'hierarchical' => false ,
2010-05-14 02:34:04 +02:00
'labels' => array (
2010-08-11 23:54:51 +02:00
'name' => __ ( 'Link Categories' ),
'singular_name' => __ ( 'Link Category' ),
'search_items' => __ ( 'Search Link Categories' ),
'popular_items' => null ,
'all_items' => __ ( 'All Link Categories' ),
'edit_item' => __ ( 'Edit Link Category' ),
'update_item' => __ ( 'Update Link Category' ),
'add_new_item' => __ ( 'Add New Link Category' ),
'new_item_name' => __ ( 'New Link Category Name' ),
'separate_items_with_commas' => null ,
'add_or_remove_items' => null ,
'choose_from_most_used' => null ,
2010-05-14 02:34:04 +02:00
),
2012-08-13 18:18:42 +02:00
'capabilities' => array (
'manage_terms' => 'manage_links' ,
'edit_terms' => 'manage_links' ,
'delete_terms' => 'manage_links' ,
'assign_terms' => 'manage_links' ,
),
2010-05-04 08:13:28 +02:00
'query_var' => false ,
'rewrite' => false ,
'public' => false ,
'show_ui' => false ,
'_builtin' => true ,
2010-12-03 11:13:17 +01:00
) );
2010-11-12 11:58:58 +01:00
register_taxonomy ( 'post_format' , 'post' , array (
2010-12-03 11:13:17 +01:00
'public' => true ,
2010-10-12 20:33:14 +02:00
'hierarchical' => false ,
'labels' => array (
2011-01-31 13:18:57 +01:00
'name' => _x ( 'Format' , 'post format' ),
'singular_name' => _x ( 'Format' , 'post format' ),
2010-10-12 20:33:14 +02:00
),
2010-12-09 15:23:54 +01:00
'query_var' => true ,
2012-01-23 20:58:26 +01:00
'rewrite' => $rewrite [ 'post_format' ],
2010-10-12 20:33:14 +02:00
'show_ui' => false ,
'_builtin' => true ,
2012-02-08 18:12:02 +01:00
'show_in_nav_menus' => current_theme_supports ( 'post-formats' ),
2010-12-03 11:13:17 +01:00
) );
2009-04-17 01:17:49 +02:00
}
2007-09-15 19:35:32 +02:00
2010-03-06 19:20:11 +01:00
/**
2015-05-05 04:01:25 +02:00
* Retrieves a list of registered taxonomy names or objects .
2010-03-06 19:20:11 +01:00
*
* @ since 3.0 . 0
2015-05-05 04:01:25 +02:00
*
* @ global array $wp_taxonomies The registered taxonomies .
2010-03-06 19:20:11 +01:00
*
2015-05-05 04:05:24 +02:00
* @ param array $args Optional . An array of `key => value` arguments to match against the taxonomy objects .
* Default empty array .
* @ param string $output Optional . The type of output to return in the array . Accepts either taxonomy 'names'
* or 'objects' . Default 'names' .
* @ param string $operator Optional . The logical operation to perform . Accepts 'and' or 'or' . 'or' means only
* one element from the array needs to match ; 'and' means all elements must match .
* Default 'and' .
* @ return array A list of taxonomy names or objects .
2010-03-06 19:20:11 +01:00
*/
2010-04-16 16:08:58 +02:00
function get_taxonomies ( $args = array (), $output = 'names' , $operator = 'and' ) {
2010-03-06 19:20:11 +01:00
global $wp_taxonomies ;
2010-04-16 16:08:58 +02:00
$field = ( 'names' == $output ) ? 'name' : false ;
2010-03-06 19:20:11 +01:00
2010-04-16 16:08:58 +02:00
return wp_filter_object_list ( $wp_taxonomies , $args , $operator , $field );
2010-03-06 19:20:11 +01:00
}
2007-09-15 19:35:32 +02:00
/**
2008-06-22 22:23:23 +02:00
* Return all of the taxonomy names that are of $object_type .
2007-09-15 19:35:32 +02:00
*
* It appears that this function can be used to find all of the names inside of
* $wp_taxonomies global variable .
*
2014-11-24 07:31:21 +01:00
* `<?php $taxonomies = get_object_taxonomies('post'); ?>` Should
* result in `Array( 'category', 'post_tag' )`
2007-09-15 19:35:32 +02:00
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2008-02-05 07:47:27 +01:00
*
2015-05-05 04:01:25 +02:00
* @ global array $wp_taxonomies The registered taxonomies .
2007-09-15 19:35:32 +02:00
*
2008-03-26 07:37:19 +01:00
* @ param array | string | object $object Name of the type of taxonomy object , or an object ( row from posts )
2015-05-07 22:37:17 +02:00
* @ param string $output Optional . The type of output to return in the array . Accepts either
* taxonomy 'names' or 'objects' . Default 'names' .
2007-10-21 19:18:24 +02:00
* @ return array The names of all taxonomy of $object_type .
2007-09-15 19:35:32 +02:00
*/
2015-05-07 22:37:17 +02:00
function get_object_taxonomies ( $object , $output = 'names' ) {
2007-09-15 19:35:32 +02:00
global $wp_taxonomies ;
2008-03-26 07:37:19 +01:00
if ( is_object ( $object ) ) {
if ( $object -> post_type == 'attachment' )
return get_attachment_taxonomies ( $object );
$object = $object -> post_type ;
}
$object = ( array ) $object ;
2007-09-15 19:35:32 +02:00
$taxonomies = array ();
2010-05-06 20:07:50 +02:00
foreach ( ( array ) $wp_taxonomies as $tax_name => $tax_obj ) {
2010-05-06 20:16:39 +02:00
if ( array_intersect ( $object , ( array ) $tax_obj -> object_type ) ) {
if ( 'names' == $output )
$taxonomies [] = $tax_name ;
else
$taxonomies [ $tax_name ] = $tax_obj ;
}
2007-09-15 19:35:32 +02:00
}
return $taxonomies ;
}
/**
2008-06-22 22:23:23 +02:00
* Retrieves the taxonomy object of $taxonomy .
2007-09-15 19:35:32 +02:00
*
* The get_taxonomy function will first check that the parameter string given
* is a taxonomy object and if it is , it will return it .
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2007-10-21 19:18:24 +02:00
*
2015-05-05 04:01:25 +02:00
* @ global array $wp_taxonomies The registered taxonomies .
2007-09-15 19:35:32 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param string $taxonomy Name of taxonomy object to return .
* @ return object | bool The Taxonomy Object or false if $taxonomy doesn ' t exist .
2007-09-15 19:35:32 +02:00
*/
function get_taxonomy ( $taxonomy ) {
global $wp_taxonomies ;
2010-06-11 17:53:41 +02:00
if ( ! taxonomy_exists ( $taxonomy ) )
2007-09-15 19:35:32 +02:00
return false ;
return $wp_taxonomies [ $taxonomy ];
}
/**
2008-06-22 22:23:23 +02:00
* Checks that the taxonomy name exists .
2007-09-15 19:35:32 +02:00
*
2010-06-11 17:53:41 +02:00
* Formerly is_taxonomy (), introduced in 2.3 . 0.
*
* @ since 3.0 . 0
2008-02-05 07:47:27 +01:00
*
2015-05-05 04:01:25 +02:00
* @ global array $wp_taxonomies The registered taxonomies .
2007-10-21 19:18:24 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param string $taxonomy Name of taxonomy object .
2010-02-24 21:13:23 +01:00
* @ return bool Whether the taxonomy exists .
2007-09-15 19:35:32 +02:00
*/
2010-06-11 17:53:41 +02:00
function taxonomy_exists ( $taxonomy ) {
2007-09-15 19:35:32 +02:00
global $wp_taxonomies ;
2010-03-17 17:27:25 +01:00
2010-06-11 17:53:41 +02:00
return isset ( $wp_taxonomies [ $taxonomy ] );
2007-09-15 19:35:32 +02:00
}
/**
2008-06-22 22:23:23 +02:00
* Whether the taxonomy object is hierarchical .
2007-09-15 19:35:32 +02:00
*
2008-06-22 22:23:23 +02:00
* Checks to make sure that the taxonomy is an object first . Then Gets the
* object , and finally returns the hierarchical value in the object .
2007-09-15 19:35:32 +02:00
*
2007-10-16 00:49:31 +02:00
* A false return value might also mean that the taxonomy does not exist .
2007-09-15 19:35:32 +02:00
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2007-10-21 19:18:24 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param string $taxonomy Name of taxonomy object .
* @ return bool Whether the taxonomy is hierarchical .
2007-09-15 19:35:32 +02:00
*/
function is_taxonomy_hierarchical ( $taxonomy ) {
2010-06-11 17:53:41 +02:00
if ( ! taxonomy_exists ( $taxonomy ) )
2007-09-15 19:35:32 +02:00
return false ;
$taxonomy = get_taxonomy ( $taxonomy );
return $taxonomy -> hierarchical ;
}
/**
2008-06-22 22:23:23 +02:00
* Create or modify a taxonomy object . Do not use before init .
2007-09-15 19:35:32 +02:00
*
2008-06-22 22:23:23 +02:00
* A simple function for creating or modifying a taxonomy object based on the
* parameters given . The function will accept an array ( third optional
* parameter ), along with strings for the taxonomy name and another string for
* the object type .
2007-09-15 19:35:32 +02:00
*
2010-06-11 17:53:41 +02:00
* Nothing is returned , so expect error maybe or use taxonomy_exists () to check
2008-06-22 22:23:23 +02:00
* whether taxonomy exists .
2007-09-15 19:35:32 +02:00
*
2007-10-21 19:18:24 +02:00
* Optional $args contents :
2010-05-26 04:42:15 +02:00
*
2013-08-26 22:24:08 +02:00
* - label - Name of the taxonomy shown in the menu . Usually plural . If not set , labels [ 'name' ] will be used .
* - labels - An array of labels for this taxonomy .
* * By default tag labels are used for non - hierarchical types and category labels for hierarchical ones .
* * You can see accepted values in { @ link get_taxonomy_labels ()} .
* - description - A short descriptive summary of what the taxonomy is for . Defaults to blank .
* - public - If the taxonomy should be publicly queryable ; //@TODO not implemented.
* * Defaults to true .
* - hierarchical - Whether the taxonomy is hierarchical ( e . g . category ) . Defaults to false .
2014-05-02 13:29:13 +02:00
* - show_ui - Whether to generate a default UI for managing this taxonomy in the admin .
2013-08-26 22:24:08 +02:00
* * If not set , the default is inherited from public .
2014-05-02 13:29:13 +02:00
* - show_in_menu - Whether to show the taxonomy in the admin menu .
2013-08-27 00:35:10 +02:00
* * If true , the taxonomy is shown as a submenu of the object type menu .
* * If false , no menu is shown .
* * show_ui must be true .
* * If not set , the default is inherited from show_ui .
2013-08-26 22:24:08 +02:00
* - show_in_nav_menus - Makes this taxonomy available for selection in navigation menus .
* * If not set , the default is inherited from public .
* - show_tagcloud - Whether to list the taxonomy in the Tag Cloud Widget .
* * If not set , the default is inherited from show_ui .
2015-01-30 20:18:23 +01:00
* - show_in_quick_edit - Whether to show the taxonomy in the quick / bulk edit panel .
* * It not set , the default is inherited from show_ui .
2014-01-07 03:13:10 +01:00
* - show_admin_column - Whether to display a column for the taxonomy on its post type listing screens .
* * Defaults to false .
2013-10-27 17:29:09 +01:00
* - meta_box_cb - Provide a callback function for the meta box display .
* * If not set , defaults to post_categories_meta_box for hierarchical taxonomies
* and post_tags_meta_box for non - hierarchical .
* * If false , no meta box is shown .
2013-08-26 22:24:08 +02:00
* - capabilities - Array of capabilities for this taxonomy .
* * You can see accepted values in this function .
* - rewrite - Triggers the handling of rewrites for this taxonomy . Defaults to true , using $taxonomy as slug .
* * To prevent rewrite , set to false .
* * To specify rewrite rules , an array can be passed with any of these keys
* * 'slug' => string Customize the permastruct slug . Defaults to $taxonomy key
* * 'with_front' => bool Should the permastruct be prepended with WP_Rewrite :: $front . Defaults to true .
* * 'hierarchical' => bool Either hierarchical rewrite tag or not . Defaults to false .
* * 'ep_mask' => const Assign an endpoint mask .
* * If not specified , defaults to EP_NONE .
* - query_var - Sets the query_var key for this taxonomy . Defaults to $taxonomy key
* * If false , a taxonomy cannot be loaded at ? { query_var } = { term_slug }
* * If specified as a string , the query ? { query_var_string } = { term_slug } will be valid .
* - update_count_callback - Works much like a hook , in that it will be called when the count is updated .
* * Defaults to _update_post_term_count () for taxonomies attached to post types , which then confirms
* that the objects are published before counting them .
* * Defaults to _update_generic_term_count () for taxonomies attached to other object types , such as links .
* - _builtin - true if this taxonomy is a native or " built-in " taxonomy . THIS IS FOR INTERNAL USE ONLY !
2008-06-22 22:23:23 +02:00
*
2015-05-07 22:37:41 +02:00
* @ todo Document $args as a hash notation .
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2015-04-05 19:08:26 +02:00
* @ since 4.2 . 0 Introduced `show_in_quick_edit` argument .
*
* @ global array $wp_taxonomies Registered taxonomies .
* @ global WP $wp WP instance .
2008-02-05 07:47:27 +01:00
*
2013-08-26 22:24:08 +02:00
* @ param string $taxonomy Taxonomy key , must not exceed 32 characters .
2008-03-24 23:43:20 +01:00
* @ param array | string $object_type Name of the object type for the taxonomy object .
2013-08-26 22:24:08 +02:00
* @ param array | string $args See optional args description above .
2012-10-26 00:29:37 +02:00
* @ return null | WP_Error WP_Error if errors , otherwise null .
2007-09-15 19:35:32 +02:00
*/
function register_taxonomy ( $taxonomy , $object_type , $args = array () ) {
2012-02-28 21:29:33 +01:00
global $wp_taxonomies , $wp ;
2007-09-15 19:35:32 +02:00
2013-08-26 22:24:08 +02:00
if ( ! is_array ( $wp_taxonomies ) )
2009-04-29 18:40:36 +02:00
$wp_taxonomies = array ();
2013-03-04 03:48:20 +01:00
$defaults = array (
2013-08-26 22:24:08 +02:00
'labels' => array (),
'description' => '' ,
'public' => true ,
'hierarchical' => false ,
'show_ui' => null ,
2013-08-27 00:35:10 +02:00
'show_in_menu' => null ,
2013-08-26 22:24:08 +02:00
'show_in_nav_menus' => null ,
'show_tagcloud' => null ,
2015-01-30 20:18:23 +01:00
'show_in_quick_edit' => null ,
2014-01-07 03:13:10 +01:00
'show_admin_column' => false ,
2013-09-23 19:12:10 +02:00
'meta_box_cb' => null ,
2013-08-26 22:24:08 +02:00
'capabilities' => array (),
'rewrite' => true ,
'query_var' => $taxonomy ,
2013-03-04 03:48:20 +01:00
'update_count_callback' => '' ,
2013-08-26 22:24:08 +02:00
'_builtin' => false ,
2013-03-04 03:48:20 +01:00
);
2013-08-26 22:24:08 +02:00
$args = wp_parse_args ( $args , $defaults );
2007-09-15 19:35:32 +02:00
2015-02-13 17:27:26 +01:00
if ( empty ( $taxonomy ) || strlen ( $taxonomy ) > 32 ) {
_doing_it_wrong ( __FUNCTION__ , __ ( 'Taxonomy names must be between 1 and 32 characters in length.' ), '4.2' );
return new WP_Error ( 'taxonomy_length_invalid' , __ ( 'Taxonomy names must be between 1 and 32 characters in length.' ) );
2014-06-29 23:54:14 +02:00
}
2012-10-26 00:12:02 +02:00
2013-08-26 22:24:08 +02:00
if ( false !== $args [ 'query_var' ] && ! empty ( $wp ) ) {
2008-05-16 04:35:24 +02:00
if ( true === $args [ 'query_var' ] )
2008-03-26 07:37:19 +01:00
$args [ 'query_var' ] = $taxonomy ;
2012-08-20 19:25:06 +02:00
else
2013-08-26 22:24:08 +02:00
$args [ 'query_var' ] = sanitize_title_with_dashes ( $args [ 'query_var' ] );
$wp -> add_query_var ( $args [ 'query_var' ] );
2008-03-26 07:37:19 +01:00
}
2013-08-26 22:24:08 +02:00
if ( false !== $args [ 'rewrite' ] && ( is_admin () || '' != get_option ( 'permalink_structure' ) ) ) {
2013-09-18 22:39:09 +02:00
$args [ 'rewrite' ] = wp_parse_args ( $args [ 'rewrite' ], array (
2010-03-17 17:27:25 +01:00
'with_front' => true ,
2012-01-23 20:12:04 +01:00
'hierarchical' => false ,
'ep_mask' => EP_NONE ,
2013-09-18 22:39:09 +02:00
) );
if ( empty ( $args [ 'rewrite' ][ 'slug' ] ) )
$args [ 'rewrite' ][ 'slug' ] = sanitize_title_with_dashes ( $taxonomy );
2010-10-17 06:36:26 +02:00
if ( $args [ 'hierarchical' ] && $args [ 'rewrite' ][ 'hierarchical' ] )
2010-10-17 07:41:22 +02:00
$tag = '(.+?)' ;
2010-10-04 12:37:25 +02:00
else
2010-10-17 06:36:26 +02:00
$tag = '([^/]+)' ;
2012-02-28 21:29:33 +01:00
add_rewrite_tag ( " % $taxonomy % " , $tag , $args [ 'query_var' ] ? " { $args [ 'query_var' ] } = " : " taxonomy= $taxonomy &term= " );
add_permastruct ( $taxonomy , " { $args [ 'rewrite' ][ 'slug' ] } /% $taxonomy % " , $args [ 'rewrite' ] );
2008-03-23 18:02:11 +01:00
}
2013-08-26 22:24:08 +02:00
// If not set, default to the setting for public.
if ( null === $args [ 'show_ui' ] )
2010-02-19 11:21:29 +01:00
$args [ 'show_ui' ] = $args [ 'public' ];
2013-08-27 00:35:10 +02:00
// If not set, default to the setting for show_ui.
if ( null === $args [ 'show_in_menu' ] || ! $args [ 'show_ui' ] )
$args [ 'show_in_menu' ] = $args [ 'show_ui' ];
2013-08-26 22:24:08 +02:00
// If not set, default to the setting for public.
2010-05-29 18:46:46 +02:00
if ( null === $args [ 'show_in_nav_menus' ] )
$args [ 'show_in_nav_menus' ] = $args [ 'public' ];
2013-08-26 22:24:08 +02:00
// If not set, default to the setting for show_ui.
if ( null === $args [ 'show_tagcloud' ] )
2010-02-21 03:55:07 +01:00
$args [ 'show_tagcloud' ] = $args [ 'show_ui' ];
2015-01-30 20:18:23 +01:00
// If not set, default to the setting for show_ui.
if ( null === $args [ 'show_in_quick_edit' ] ) {
$args [ 'show_in_quick_edit' ] = $args [ 'show_ui' ];
}
2010-05-13 06:10:17 +02:00
$default_caps = array (
'manage_terms' => 'manage_categories' ,
'edit_terms' => 'manage_categories' ,
'delete_terms' => 'manage_categories' ,
'assign_terms' => 'edit_posts' ,
);
$args [ 'cap' ] = ( object ) array_merge ( $default_caps , $args [ 'capabilities' ] );
unset ( $args [ 'capabilities' ] );
2010-02-21 01:03:42 +01:00
2007-09-15 19:35:32 +02:00
$args [ 'name' ] = $taxonomy ;
2013-08-26 22:24:08 +02:00
$args [ 'object_type' ] = array_unique ( ( array ) $object_type );
2010-05-14 04:13:49 +02:00
2010-05-14 02:34:04 +02:00
$args [ 'labels' ] = get_taxonomy_labels ( ( object ) $args );
$args [ 'label' ] = $args [ 'labels' ] -> name ;
2010-05-26 04:42:15 +02:00
2013-09-23 19:12:10 +02:00
// If not set, use the default meta box
if ( null === $args [ 'meta_box_cb' ] ) {
if ( $args [ 'hierarchical' ] )
$args [ 'meta_box_cb' ] = 'post_categories_meta_box' ;
else
$args [ 'meta_box_cb' ] = 'post_tags_meta_box' ;
}
2013-08-26 22:24:08 +02:00
$wp_taxonomies [ $taxonomy ] = ( object ) $args ;
2010-04-02 19:07:30 +02:00
// register callback handling for metabox
2013-08-26 22:24:08 +02:00
add_filter ( 'wp_ajax_add-' . $taxonomy , '_wp_ajax_add_hierarchical_term' );
2011-09-30 11:53:35 +02:00
2014-03-28 22:29:13 +01:00
/**
* Fires after a taxonomy is registered .
*
* @ since 3.3 . 0
*
* @ param string $taxonomy Taxonomy slug .
* @ param array | string $object_type Object type or array of object types .
2014-08-11 23:17:17 +02:00
* @ param array $args Array of taxonomy registration arguments .
2014-03-28 22:29:13 +01:00
*/
2011-09-30 11:53:35 +02:00
do_action ( 'registered_taxonomy' , $taxonomy , $object_type , $args );
2007-09-15 19:35:32 +02:00
}
2010-05-14 02:34:04 +02:00
/**
* Builds an object with all taxonomy labels out of a taxonomy object
2010-05-26 04:42:15 +02:00
*
2010-05-14 02:34:04 +02:00
* Accepted keys of the label array in the taxonomy object :
2014-11-24 07:31:21 +01:00
*
2011-09-11 19:52:46 +02:00
* - name - general name for the taxonomy , usually plural . The same as and overridden by $tax -> label . Default is Tags / Categories
* - singular_name - name for one object of this taxonomy . Default is Tag / Category
2010-05-14 02:34:04 +02:00
* - search_items - Default is Search Tags / Search Categories
2010-06-04 21:21:06 +02:00
* - popular_items - This string isn ' t used on hierarchical taxonomies . Default is Popular Tags
2010-05-14 02:34:04 +02:00
* - all_items - Default is All Tags / All Categories
* - parent_item - This string isn ' t used on non - hierarchical taxonomies . In hierarchical ones the default is Parent Category
2014-12-03 14:55:24 +01:00
* - parent_item_colon - The same as `parent_item` , but with colon `:` in the end
2010-05-14 02:34:04 +02:00
* - edit_item - Default is Edit Tag / Edit Category
2012-04-11 22:08:30 +02:00
* - view_item - Default is View Tag / View Category
2010-05-14 02:34:04 +02:00
* - update_item - Default is Update Tag / Update Category
* - add_new_item - Default is Add New Tag / Add New Category
* - new_item_name - Default is New Tag Name / New Category Name
2012-04-11 22:08:30 +02:00
* - separate_items_with_commas - This string isn ' t used on hierarchical taxonomies . Default is " Separate tags with commas " , used in the meta box .
* - 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 .
* - 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 .
2015-01-03 07:20:21 +01:00
* - not_found - Default is " No tags found " / " No categories found " , used in the meta box and taxonomy list table .
2010-05-26 04:42:15 +02:00
*
2012-04-11 22:08:30 +02:00
* Above , the first default value is for non - hierarchical taxonomies ( like tags ) and the second one is for hierarchical taxonomies ( like categories ) .
2010-05-26 04:42:15 +02:00
*
2015-05-07 22:37:41 +02:00
* @ todo Better documentation for the labels array .
*
2010-05-14 02:34:04 +02:00
* @ since 3.0 . 0
2015-05-05 04:01:25 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param object $tax Taxonomy object .
* @ return object object with all the labels as member variables .
2010-05-14 02:34:04 +02:00
*/
function get_taxonomy_labels ( $tax ) {
2013-09-21 19:44:09 +02:00
$tax -> labels = ( array ) $tax -> labels ;
2010-06-10 18:07:33 +02:00
if ( isset ( $tax -> helps ) && empty ( $tax -> labels [ 'separate_items_with_commas' ] ) )
$tax -> labels [ 'separate_items_with_commas' ] = $tax -> helps ;
2013-02-25 20:39:38 +01:00
if ( isset ( $tax -> no_tagcloud ) && empty ( $tax -> labels [ 'not_found' ] ) )
$tax -> labels [ 'not_found' ] = $tax -> no_tagcloud ;
2013-02-25 19:35:05 +01:00
2010-05-14 02:34:04 +02:00
$nohier_vs_hier_defaults = array (
2011-09-11 19:52:46 +02:00
'name' => array ( _x ( 'Tags' , 'taxonomy general name' ), _x ( 'Categories' , 'taxonomy general name' ) ),
'singular_name' => array ( _x ( 'Tag' , 'taxonomy singular name' ), _x ( 'Category' , 'taxonomy singular name' ) ),
2010-05-14 02:34:04 +02:00
'search_items' => array ( __ ( 'Search Tags' ), __ ( 'Search Categories' ) ),
2010-06-04 21:21:06 +02:00
'popular_items' => array ( __ ( 'Popular Tags' ), null ),
2010-05-14 02:34:04 +02:00
'all_items' => array ( __ ( 'All Tags' ), __ ( 'All Categories' ) ),
'parent_item' => array ( null , __ ( 'Parent Category' ) ),
'parent_item_colon' => array ( null , __ ( 'Parent Category:' ) ),
'edit_item' => array ( __ ( 'Edit Tag' ), __ ( 'Edit Category' ) ),
2011-06-08 18:49:27 +02:00
'view_item' => array ( __ ( 'View Tag' ), __ ( 'View Category' ) ),
2010-05-14 02:34:04 +02:00
'update_item' => array ( __ ( 'Update Tag' ), __ ( 'Update Category' ) ),
'add_new_item' => array ( __ ( 'Add New Tag' ), __ ( 'Add New Category' ) ),
'new_item_name' => array ( __ ( 'New Tag Name' ), __ ( 'New Category Name' ) ),
2010-06-10 18:07:33 +02:00
'separate_items_with_commas' => array ( __ ( 'Separate tags with commas' ), null ),
'add_or_remove_items' => array ( __ ( 'Add or remove tags' ), null ),
'choose_from_most_used' => array ( __ ( 'Choose from the most used tags' ), null ),
2015-01-03 07:20:21 +01:00
'not_found' => array ( __ ( 'No tags found.' ), __ ( 'No categories found.' ) ),
2010-05-14 02:34:04 +02:00
);
2010-11-09 03:09:00 +01:00
$nohier_vs_hier_defaults [ 'menu_name' ] = $nohier_vs_hier_defaults [ 'name' ];
2010-05-14 02:34:04 +02:00
return _get_custom_object_labels ( $tax , $nohier_vs_hier_defaults );
}
2010-01-04 17:58:43 +01:00
/**
* Add an already registered taxonomy to an object type .
*
2010-03-26 20:13:36 +01:00
* @ since 3.0 . 0
2015-05-05 04:01:25 +02:00
*
* @ global array $wp_taxonomies The registered taxonomies .
2010-01-04 17:58:43 +01:00
*
2015-05-07 22:37:41 +02:00
* @ param string $taxonomy Name of taxonomy object .
* @ param string $object_type Name of the object type .
* @ return bool True if successful , false if not .
2010-01-04 17:58:43 +01:00
*/
function register_taxonomy_for_object_type ( $taxonomy , $object_type ) {
global $wp_taxonomies ;
if ( ! isset ( $wp_taxonomies [ $taxonomy ]) )
return false ;
if ( ! get_post_type_object ( $object_type ) )
return false ;
2011-04-23 11:27:37 +02:00
if ( ! in_array ( $object_type , $wp_taxonomies [ $taxonomy ] -> object_type ) )
$wp_taxonomies [ $taxonomy ] -> object_type [] = $object_type ;
2010-01-04 17:58:43 +01:00
return true ;
}
2013-09-24 04:54:08 +02:00
/**
* Remove an already registered taxonomy from an object type .
*
* @ since 3.7 . 0
*
2015-05-05 04:01:25 +02:00
* @ global array $wp_taxonomies The registered taxonomies .
*
2013-09-24 04:54:08 +02:00
* @ param string $taxonomy Name of taxonomy object .
* @ param string $object_type Name of the object type .
* @ return bool True if successful , false if not .
*/
function unregister_taxonomy_for_object_type ( $taxonomy , $object_type ) {
global $wp_taxonomies ;
if ( ! isset ( $wp_taxonomies [ $taxonomy ] ) )
return false ;
if ( ! get_post_type_object ( $object_type ) )
return false ;
$key = array_search ( $object_type , $wp_taxonomies [ $taxonomy ] -> object_type , true );
if ( false === $key )
return false ;
unset ( $wp_taxonomies [ $taxonomy ] -> object_type [ $key ] );
return true ;
}
2007-09-15 19:35:32 +02:00
//
// Term API
//
/**
2008-06-22 22:23:23 +02:00
* Retrieve object_ids of valid taxonomy and term .
2007-09-15 19:35:32 +02:00
*
2008-06-22 22:23:23 +02:00
* The strings of $taxonomies must exist before this function will continue . On
* failure of finding a valid taxonomy , it will return an WP_Error class , kind
* of like Exceptions in PHP 5 , except you can ' t catch them . Even so , you can
* still test for the WP_Error class and get the error message .
2007-09-15 19:35:32 +02:00
*
2008-06-22 22:23:23 +02:00
* The $terms aren ' t checked the same as $taxonomies , but still need to exist
* for $object_ids to be returned .
2007-09-15 19:35:32 +02:00
*
2008-06-22 22:23:23 +02:00
* It is possible to change the order that object_ids is returned by either
* using PHP sort family functions or using the database by using $args with
* either ASC or DESC array . The value should be in the key named 'order' .
2007-09-15 19:35:32 +02:00
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2007-10-21 19:18:24 +02:00
*
2014-10-31 18:56:22 +01:00
* @ global wpdb $wpdb WordPress database abstraction object .
2007-10-16 00:49:31 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param int | array $term_ids Term id or array of term ids of terms that will be used .
* @ param string | array $taxonomies String of taxonomy name or Array of string values of taxonomy names .
* @ param array | string $args Change the order of the object_ids , either ASC or DESC .
* @ return WP_Error | array If the taxonomy does not exist , then WP_Error will be returned . On success .
2010-11-17 02:56:01 +01:00
* the array can be empty meaning that there are no $object_ids found or it will return the $object_ids found .
2007-09-15 19:35:32 +02:00
*/
2010-11-17 02:56:01 +01:00
function get_objects_in_term ( $term_ids , $taxonomies , $args = array () ) {
2007-09-15 19:35:32 +02:00
global $wpdb ;
2014-05-15 07:43:16 +02:00
if ( ! is_array ( $term_ids ) ) {
2010-11-17 02:56:01 +01:00
$term_ids = array ( $term_ids );
2014-05-15 07:43:16 +02:00
}
if ( ! is_array ( $taxonomies ) ) {
2010-11-17 02:56:01 +01:00
$taxonomies = array ( $taxonomies );
2014-05-15 07:43:16 +02:00
}
2010-11-17 02:56:01 +01:00
foreach ( ( array ) $taxonomies as $taxonomy ) {
2014-05-15 07:43:16 +02:00
if ( ! taxonomy_exists ( $taxonomy ) ) {
2012-06-01 21:05:30 +02:00
return new WP_Error ( 'invalid_taxonomy' , __ ( 'Invalid taxonomy' ) );
2014-05-15 07:43:16 +02:00
}
2007-09-15 19:35:32 +02:00
}
2010-11-17 02:56:01 +01:00
$defaults = array ( 'order' => 'ASC' );
$args = wp_parse_args ( $args , $defaults );
2007-10-13 05:51:11 +02:00
2014-05-15 07:43:16 +02:00
$order = ( 'desc' == strtolower ( $args [ 'order' ] ) ) ? 'DESC' : 'ASC' ;
2007-09-15 19:35:32 +02:00
2010-11-17 02:56:01 +01:00
$term_ids = array_map ( 'intval' , $term_ids );
2010-10-06 14:06:23 +02:00
2010-03-26 15:00:17 +01:00
$taxonomies = " ' " . implode ( " ', ' " , $taxonomies ) . " ' " ;
2010-11-17 02:56:01 +01:00
$term_ids = " ' " . implode ( " ', ' " , $term_ids ) . " ' " ;
2007-09-15 19:35:32 +02:00
2010-11-17 02:56:01 +01:00
$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 " );
2010-09-13 18:44:14 +02:00
2014-05-15 07:43:16 +02:00
if ( ! $object_ids ){
2010-11-17 02:56:01 +01:00
return array ();
2014-05-15 07:43:16 +02:00
}
2010-11-17 02:56:01 +01:00
return $object_ids ;
2010-09-13 18:44:14 +02:00
}
2010-12-16 23:46:13 +01:00
/**
2010-12-10 09:20:46 +01:00
* Given a taxonomy query , generates SQL to be appended to a main query .
2010-11-10 00:30:35 +01:00
*
* @ since 3.1 . 0
*
2010-12-10 09:20:46 +01:00
* @ see WP_Tax_Query
2010-11-10 00:30:35 +01:00
*
2010-12-10 09:20:46 +01:00
* @ param array $tax_query A compact tax query
2010-11-17 02:56:01 +01:00
* @ param string $primary_table
* @ param string $primary_id_column
2010-11-21 15:09:01 +01:00
* @ return array
2010-11-10 00:30:35 +01:00
*/
2010-11-17 02:56:01 +01:00
function get_tax_sql ( $tax_query , $primary_table , $primary_id_column ) {
2010-12-09 20:29:21 +01:00
$tax_query_obj = new WP_Tax_Query ( $tax_query );
return $tax_query_obj -> get_sql ( $primary_table , $primary_id_column );
}
2010-11-23 21:22:27 +01:00
2010-12-10 09:20:46 +01:00
/**
2014-10-14 06:03:19 +02:00
* Class for generating SQL clauses that filter a primary query according to object taxonomy terms .
*
2015-05-07 22:37:41 +02:00
* `WP_Tax_Query` is a helper that allows primary query classes , such as WP_Query , to filter
2014-10-14 06:03:19 +02:00
* their results by object metadata , by generating `JOIN` and `WHERE` subclauses to be attached
* to the primary SQL query string .
2010-12-10 09:20:46 +01:00
*
* @ since 3.1 . 0
*/
2010-12-09 20:29:21 +01:00
class WP_Tax_Query {
2010-12-10 09:20:46 +01:00
/**
2014-10-14 06:03:19 +02:00
* Array of taxonomy queries .
*
* See { @ see WP_Tax_Query :: __construct ()} for information on tax query arguments .
2010-12-10 09:20:46 +01:00
*
* @ since 3.1 . 0
* @ access public
* @ var array
*/
2011-04-22 21:09:48 +02:00
public $queries = array ();
2010-12-09 18:05:40 +01:00
2010-12-10 09:20:46 +01:00
/**
* The relation between the queries . Can be one of 'AND' or 'OR' .
*
* @ since 3.1 . 0
* @ access public
* @ var string
*/
2011-04-22 21:09:48 +02:00
public $relation ;
2010-12-10 09:20:46 +01:00
/**
2011-04-22 21:09:48 +02:00
* Standard response when the query should not return any rows .
*
* @ since 3.2 . 0
* @ access private
* @ var string
*/
2014-10-14 06:03:19 +02:00
private static $no_results = array ( 'join' => array ( '' ), 'where' => array ( '0 = 1' ) );
2011-04-22 21:09:48 +02:00
/**
2014-10-14 06:03:19 +02:00
* A flat list of table aliases used in the JOIN clauses .
*
* @ since 4.1 . 0
* @ access protected
* @ var array
*/
protected $table_aliases = array ();
/**
* Terms and taxonomies fetched by this query .
2010-12-10 09:20:46 +01:00
*
2014-10-14 06:03:19 +02:00
* We store this data in a flat array because they are referenced in a
2015-05-07 22:37:41 +02:00
* number of places by WP_Query .
2014-10-14 06:03:19 +02:00
*
* @ since 4.1 . 0
* @ access public
* @ var array
*/
public $queried_terms = array ();
2014-11-03 04:45:22 +01:00
/**
* Database table that where the metadata ' s objects are stored ( eg $wpdb -> users ) .
*
* @ since 4.1 . 0
* @ access public
* @ var string
*/
public $primary_table ;
/**
2014-11-28 13:26:24 +01:00
* Column in 'primary_table' that represents the ID of the object .
2014-11-03 04:45:22 +01:00
*
* @ since 4.1 . 0
* @ access public
* @ var string
*/
public $primary_id_column ;
2014-10-14 06:03:19 +02:00
/**
* Constructor .
2010-12-10 09:20:46 +01:00
*
* @ since 3.1 . 0
2014-11-28 13:26:24 +01:00
* @ since 4.1 . 0 Added support for `$operator` 'NOT EXISTS' and 'EXISTS' values .
2010-12-10 09:20:46 +01:00
* @ access public
*
2014-10-14 06:03:19 +02:00
* @ param array $tax_query {
2014-10-15 02:54:21 +02:00
* Array of taxonomy query clauses .
2014-10-14 06:03:19 +02:00
*
* @ type string $relation Optional . The MySQL keyword used to join
* the clauses of the query . Accepts 'AND' , or 'OR' . Default 'AND' .
* @ type array {
* Optional . An array of first - order clause parameters , or another fully - formed tax query .
*
* @ type string $taxonomy Taxonomy being queried . Optional when field = term_taxonomy_id .
* @ type string | int | array $terms Term or terms to filter by .
* @ type string $field Field to match $terms against . Accepts 'term_id' , 'slug' ,
* 'name' , or 'term_taxonomy_id' . Default : 'term_id' .
* @ type string $operator MySQL operator to be used with $terms in the WHERE clause .
2014-10-15 02:54:21 +02:00
* Accepts 'AND' , 'IN' , 'NOT IN' , 'EXISTS' , 'NOT EXISTS' .
* Default : 'IN' .
2014-10-14 06:03:19 +02:00
* @ type bool $include_children Optional . Whether to include child terms .
* Requires a $taxonomy . Default : true .
* }
* }
2010-12-10 09:20:46 +01:00
*/
2011-04-22 21:09:48 +02:00
public function __construct ( $tax_query ) {
2014-10-15 18:40:18 +02:00
if ( isset ( $tax_query [ 'relation' ] ) ) {
$this -> relation = $this -> sanitize_relation ( $tax_query [ 'relation' ] );
2010-12-09 20:29:21 +01:00
} else {
$this -> relation = 'AND' ;
}
2010-11-23 21:22:27 +01:00
2014-10-14 06:03:19 +02:00
$this -> queries = $this -> sanitize_query ( $tax_query );
}
/**
2014-11-28 13:26:24 +01:00
* Ensure the 'tax_query' argument passed to the class constructor is well - formed .
2014-10-14 06:03:19 +02:00
*
* Ensures that each query - level clause has a 'relation' key , and that
2014-11-28 13:26:24 +01:00
* each first - order clause contains all the necessary keys from `$defaults` .
2014-10-14 06:03:19 +02:00
*
* @ since 4.1 . 0
* @ access public
*
2014-11-28 13:26:24 +01:00
* @ param array $queries Array of queries clauses .
2014-10-14 06:03:19 +02:00
* @ return array Sanitized array of query clauses .
*/
public function sanitize_query ( $queries ) {
$cleaned_query = array ();
2010-12-09 20:29:21 +01:00
$defaults = array (
'taxonomy' => '' ,
'terms' => array (),
'field' => 'term_id' ,
'operator' => 'IN' ,
2014-10-14 06:03:19 +02:00
'include_children' => true ,
2010-12-09 20:29:21 +01:00
);
2010-11-23 21:22:27 +01:00
2014-10-14 06:03:19 +02:00
foreach ( $queries as $key => $query ) {
if ( 'relation' === $key ) {
2014-10-15 18:40:18 +02:00
$cleaned_query [ 'relation' ] = $this -> sanitize_relation ( $query );
2014-10-14 06:03:19 +02:00
// First-order clause.
2015-01-08 07:26:23 +01:00
} elseif ( self :: is_first_order_clause ( $query ) ) {
2014-10-14 06:03:19 +02:00
$cleaned_clause = array_merge ( $defaults , $query );
$cleaned_clause [ 'terms' ] = ( array ) $cleaned_clause [ 'terms' ];
$cleaned_query [] = $cleaned_clause ;
/*
* Keep a copy of the clause in the flate
* $queried_terms array , for use in WP_Query .
*/
if ( ! empty ( $cleaned_clause [ 'taxonomy' ] ) && 'NOT IN' !== $cleaned_clause [ 'operator' ] ) {
$taxonomy = $cleaned_clause [ 'taxonomy' ];
if ( ! isset ( $this -> queried_terms [ $taxonomy ] ) ) {
$this -> queried_terms [ $taxonomy ] = array ();
}
2010-11-17 02:56:01 +01:00
2014-10-14 06:03:19 +02:00
/*
* Backward compatibility : Only store the first
* 'terms' and 'field' found for a given taxonomy .
*/
if ( ! empty ( $cleaned_clause [ 'terms' ] ) && ! isset ( $this -> queried_terms [ $taxonomy ][ 'terms' ] ) ) {
$this -> queried_terms [ $taxonomy ][ 'terms' ] = $cleaned_clause [ 'terms' ];
}
2010-11-10 00:30:35 +01:00
2014-10-14 06:03:19 +02:00
if ( ! empty ( $cleaned_clause [ 'field' ] ) && ! isset ( $this -> queried_terms [ $taxonomy ][ 'field' ] ) ) {
$this -> queried_terms [ $taxonomy ][ 'field' ] = $cleaned_clause [ 'field' ];
}
}
2010-12-13 22:21:50 +01:00
2014-10-14 06:03:19 +02:00
// Otherwise, it's a nested query, so we recurse.
2015-01-08 07:26:23 +01:00
} elseif ( is_array ( $query ) ) {
2014-10-14 06:03:19 +02:00
$cleaned_subquery = $this -> sanitize_query ( $query );
if ( ! empty ( $cleaned_subquery ) ) {
2014-10-15 18:40:18 +02:00
// All queries with children must have a relation.
if ( ! isset ( $cleaned_subquery [ 'relation' ] ) ) {
$cleaned_subquery [ 'relation' ] = 'AND' ;
}
2014-10-14 06:03:19 +02:00
$cleaned_query [] = $cleaned_subquery ;
}
}
2010-12-09 20:29:21 +01:00
}
2014-10-14 06:03:19 +02:00
return $cleaned_query ;
}
2014-10-15 18:40:18 +02:00
/**
* Sanitize a 'relation' operator .
*
* @ since 4.1 . 0
* @ access public
*
* @ param string $relation Raw relation key from the query argument .
2014-11-30 23:56:25 +01:00
* @ return string Sanitized relation ( 'AND' or 'OR' ) .
2014-10-15 18:40:18 +02:00
*/
public function sanitize_relation ( $relation ) {
if ( 'OR' === strtoupper ( $relation ) ) {
return 'OR' ;
} else {
return 'AND' ;
}
}
2014-10-14 06:03:19 +02:00
/**
* Determine whether a clause is first - order .
*
* A " first-order " clause is one that contains any of the first - order
* clause keys ( 'terms' , 'taxonomy' , 'include_children' , 'field' ,
* 'operator' ) . An empty clause also counts as a first - order clause ,
* for backward compatibility . Any clause that doesn ' t meet this is
* determined , by process of elimination , to be a higher - order query .
*
* @ since 4.1 . 0
* @ access protected
*
2014-11-28 13:26:24 +01:00
* @ param array $query Tax query arguments .
* @ return bool Whether the query clause is a first - order clause .
2014-10-14 06:03:19 +02:00
*/
protected static function is_first_order_clause ( $query ) {
2014-10-26 23:57:18 +01:00
return is_array ( $query ) && ( empty ( $query ) || array_key_exists ( 'terms' , $query ) || array_key_exists ( 'taxonomy' , $query ) || array_key_exists ( 'include_children' , $query ) || array_key_exists ( 'field' , $query ) || array_key_exists ( 'operator' , $query ) );
2010-12-09 20:29:21 +01:00
}
2010-11-10 00:30:35 +01:00
2010-12-10 09:20:46 +01:00
/**
* Generates SQL clauses to be appended to a main query .
*
* @ since 3.1 . 0
* @ access public
*
2014-10-14 06:03:19 +02:00
* @ param string $primary_table Database table where the object being filtered is stored ( eg wp_users ) .
* @ param string $primary_id_column ID column for the filtered object in $primary_table .
* @ return array {
* Array containing JOIN and WHERE SQL clauses to append to the main query .
*
* @ type string $join SQL fragment to append to the main JOIN clause .
* @ type string $where SQL fragment to append to the main WHERE clause .
* }
2010-12-10 09:20:46 +01:00
*/
2011-04-22 21:09:48 +02:00
public function get_sql ( $primary_table , $primary_id_column ) {
2014-10-14 06:03:19 +02:00
$this -> primary_table = $primary_table ;
$this -> primary_id_column = $primary_id_column ;
2010-11-10 00:30:35 +01:00
2014-10-14 06:03:19 +02:00
return $this -> get_sql_clauses ();
}
2010-11-16 17:24:14 +01:00
2014-10-14 06:03:19 +02:00
/**
* Generate SQL clauses to be appended to a main query .
*
2015-05-07 22:37:41 +02:00
* Called by the public WP_Tax_Query :: get_sql (), this method
2014-10-14 06:03:19 +02:00
* is abstracted out to maintain parity with the other Query classes .
*
* @ since 4.1 . 0
* @ access protected
*
* @ return array {
* Array containing JOIN and WHERE SQL clauses to append to the main query .
*
* @ type string $join SQL fragment to append to the main JOIN clause .
* @ type string $where SQL fragment to append to the main WHERE clause .
* }
*/
protected function get_sql_clauses () {
2014-10-15 18:40:18 +02:00
/*
* $queries are passed by reference to get_sql_for_query () for recursion .
* To keep $this -> queries unaltered , pass a copy .
*/
$queries = $this -> queries ;
$sql = $this -> get_sql_for_query ( $queries );
2010-11-23 21:22:27 +01:00
2014-10-14 06:03:19 +02:00
if ( ! empty ( $sql [ 'where' ] ) ) {
$sql [ 'where' ] = ' AND ' . $sql [ 'where' ];
}
2010-11-17 02:56:01 +01:00
2014-10-14 06:03:19 +02:00
return $sql ;
}
/**
* Generate SQL clauses for a single query array .
*
* If nested subqueries are found , this method recurses the tree to
* produce the properly nested SQL .
*
* @ since 4.1 . 0
* @ access protected
*
2014-11-28 13:26:24 +01:00
* @ param array $query Query to parse , passed by reference .
2014-10-14 06:03:19 +02:00
* @ param int $depth Optional . Number of tree levels deep we currently are .
2014-11-28 13:26:24 +01:00
* Used to calculate indentation . Default 0.
2014-10-14 06:03:19 +02:00
* @ return array {
* Array containing JOIN and WHERE SQL clauses to append to a single query array .
*
* @ type string $join SQL fragment to append to the main JOIN clause .
* @ type string $where SQL fragment to append to the main WHERE clause .
* }
*/
2014-10-15 18:40:18 +02:00
protected function get_sql_for_query ( & $query , $depth = 0 ) {
2014-10-14 06:03:19 +02:00
$sql_chunks = array (
'join' => array (),
'where' => array (),
);
$sql = array (
'join' => '' ,
'where' => '' ,
);
$indent = '' ;
for ( $i = 0 ; $i < $depth ; $i ++ ) {
$indent .= " " ;
}
2014-10-15 18:40:18 +02:00
foreach ( $query as $key => & $clause ) {
2014-10-14 06:03:19 +02:00
if ( 'relation' === $key ) {
$relation = $query [ 'relation' ];
2015-01-08 07:26:23 +01:00
} elseif ( is_array ( $clause ) ) {
2011-04-22 21:09:48 +02:00
2014-10-14 06:03:19 +02:00
// This is a first-order clause.
if ( $this -> is_first_order_clause ( $clause ) ) {
$clause_sql = $this -> get_sql_for_clause ( $clause , $query );
2010-11-23 21:22:27 +01:00
2014-10-14 06:03:19 +02:00
$where_count = count ( $clause_sql [ 'where' ] );
if ( ! $where_count ) {
$sql_chunks [ 'where' ][] = '' ;
2015-01-08 07:26:23 +01:00
} elseif ( 1 === $where_count ) {
2014-10-14 06:03:19 +02:00
$sql_chunks [ 'where' ][] = $clause_sql [ 'where' ][ 0 ];
2012-10-04 15:16:47 +02:00
} else {
2014-10-14 06:03:19 +02:00
$sql_chunks [ 'where' ][] = '( ' . implode ( ' AND ' , $clause_sql [ 'where' ] ) . ' )' ;
2012-10-04 15:16:47 +02:00
}
2014-10-14 06:03:19 +02:00
$sql_chunks [ 'join' ] = array_merge ( $sql_chunks [ 'join' ], $clause_sql [ 'join' ] );
// This is a subquery, so we recurse.
} else {
$clause_sql = $this -> get_sql_for_query ( $clause , $depth + 1 );
$sql_chunks [ 'where' ][] = $clause_sql [ 'where' ];
$sql_chunks [ 'join' ][] = $clause_sql [ 'join' ];
2010-12-09 20:29:21 +01:00
}
2014-10-14 06:03:19 +02:00
}
}
// Filter to remove empties.
$sql_chunks [ 'join' ] = array_filter ( $sql_chunks [ 'join' ] );
$sql_chunks [ 'where' ] = array_filter ( $sql_chunks [ 'where' ] );
if ( empty ( $relation ) ) {
$relation = 'AND' ;
}
2010-11-20 22:28:50 +01:00
2014-10-14 06:03:19 +02:00
// Filter duplicate JOIN clauses and combine into a single string.
if ( ! empty ( $sql_chunks [ 'join' ] ) ) {
$sql [ 'join' ] = implode ( ' ' , array_unique ( $sql_chunks [ 'join' ] ) );
}
2010-11-20 22:28:50 +01:00
2014-10-14 06:03:19 +02:00
// Generate a single WHERE clause with proper brackets and indentation.
if ( ! empty ( $sql_chunks [ 'where' ] ) ) {
$sql [ 'where' ] = '( ' . " \n " . $indent . implode ( ' ' . " \n " . $indent . $relation . ' ' . " \n " . $indent , $sql_chunks [ 'where' ] ) . " \n " . $indent . ')' ;
}
2010-11-23 21:22:27 +01:00
2014-10-14 06:03:19 +02:00
return $sql ;
}
2010-11-20 22:10:20 +01:00
2014-10-14 06:03:19 +02:00
/**
2014-11-28 13:26:24 +01:00
* Generate SQL JOIN and WHERE clauses for a " first-order " query clause .
2014-12-07 01:39:24 +01:00
*
2014-10-14 06:03:19 +02:00
* @ since 4.1 . 0
* @ access public
*
2015-05-05 04:01:25 +02:00
* @ global wpdb $wpdb The WordPress database abstraction object .
*
2015-05-07 22:37:41 +02:00
* @ param array $clause Query clause , passed by reference .
2014-11-28 13:26:24 +01:00
* @ param array $parent_query Parent query array .
2014-10-14 06:03:19 +02:00
* @ return array {
* Array containing JOIN and WHERE SQL clauses to append to a first - order query .
*
* @ type string $join SQL fragment to append to the main JOIN clause .
* @ type string $where SQL fragment to append to the main WHERE clause .
* }
*/
2014-10-15 18:40:18 +02:00
public function get_sql_for_clause ( & $clause , $parent_query ) {
2014-10-14 06:03:19 +02:00
global $wpdb ;
2010-11-10 00:30:35 +01:00
2014-10-14 06:03:19 +02:00
$sql = array (
'where' => array (),
'join' => array (),
);
2010-12-09 18:05:40 +01:00
2014-10-14 06:03:19 +02:00
$join = '' ;
2011-01-09 17:19:48 +01:00
2014-10-14 06:03:19 +02:00
$this -> clean_query ( $clause );
if ( is_wp_error ( $clause ) ) {
return self :: $no_results ;
}
2011-01-09 17:19:48 +01:00
2014-10-14 06:03:19 +02:00
$terms = $clause [ 'terms' ];
$operator = strtoupper ( $clause [ 'operator' ] );
2011-01-09 17:19:48 +01:00
2014-10-14 06:03:19 +02:00
if ( 'IN' == $operator ) {
2011-01-09 17:19:48 +01:00
2014-10-14 06:03:19 +02:00
if ( empty ( $terms ) ) {
return self :: $no_results ;
2010-12-09 20:29:21 +01:00
}
2010-12-09 18:05:40 +01:00
2014-10-14 06:03:19 +02:00
$terms = implode ( ',' , $terms );
2010-12-09 18:05:40 +01:00
2014-10-15 18:40:18 +02:00
/*
* Before creating another table join , see if this clause has a
* sibling with an existing join that can be shared .
*/
$alias = $this -> find_compatible_table_alias ( $clause , $parent_query );
if ( false === $alias ) {
$i = count ( $this -> table_aliases );
$alias = $i ? 'tt' . $i : $wpdb -> term_relationships ;
// Store the alias as part of a flat array to build future iterators.
$this -> table_aliases [] = $alias ;
// Store the alias with this clause, so later siblings can use it.
$clause [ 'alias' ] = $alias ;
$join .= " INNER JOIN $wpdb->term_relationships " ;
$join .= $i ? " AS $alias " : '' ;
$join .= " ON ( $this->primary_table . $this->primary_id_column = $alias .object_id) " ;
}
2014-10-14 06:03:19 +02:00
$where = " $alias .term_taxonomy_id $operator ( $terms ) " ;
} elseif ( 'NOT IN' == $operator ) {
if ( empty ( $terms ) ) {
2014-10-17 00:07:20 +02:00
return $sql ;
2014-10-14 06:03:19 +02:00
}
$terms = implode ( ',' , $terms );
$where = " $this->primary_table . $this->primary_id_column NOT IN (
SELECT object_id
FROM $wpdb -> term_relationships
WHERE term_taxonomy_id IN ( $terms )
) " ;
} elseif ( 'AND' == $operator ) {
if ( empty ( $terms ) ) {
2014-10-17 00:07:20 +02:00
return $sql ;
2014-10-14 06:03:19 +02:00
}
$num_terms = count ( $terms );
$terms = implode ( ',' , $terms );
$where = " (
SELECT COUNT ( 1 )
FROM $wpdb -> term_relationships
WHERE term_taxonomy_id IN ( $terms )
AND object_id = $this -> primary_table . $this -> primary_id_column
) = $num_terms " ;
2014-10-15 02:54:21 +02:00
} elseif ( 'NOT EXISTS' === $operator || 'EXISTS' === $operator ) {
$where = $wpdb -> prepare ( " $operator (
SELECT 1
FROM $wpdb -> term_relationships
INNER JOIN $wpdb -> term_taxonomy
ON $wpdb -> term_taxonomy . term_taxonomy_id = $wpdb -> term_relationships . term_taxonomy_id
WHERE $wpdb -> term_taxonomy . taxonomy = % s
AND $wpdb -> term_relationships . object_id = $this -> primary_table . $this -> primary_id_column
) " , $clause['taxonomy'] );
2014-05-15 07:41:14 +02:00
}
2014-10-14 06:03:19 +02:00
$sql [ 'join' ][] = $join ;
$sql [ 'where' ][] = $where ;
return $sql ;
2010-12-09 18:05:40 +01:00
}
2014-10-15 18:40:18 +02:00
/**
* Identify an existing table alias that is compatible with the current query clause .
*
* We avoid unnecessary table joins by allowing each clause to look for
* an existing table alias that is compatible with the query that it
2014-11-28 13:26:24 +01:00
* needs to perform .
*
* An existing alias is compatible if ( a ) it is a sibling of `$clause`
* ( ie , it ' s under the scope of the same relation ), and ( b ) the combination
* of operator and relation between the clauses allows for a shared table
2015-05-07 22:37:41 +02:00
* join . In the case of WP_Tax_Query , this only applies to 'IN'
2014-11-28 13:26:24 +01:00
* clauses that are connected by the relation 'OR' .
2014-10-15 18:40:18 +02:00
*
* @ since 4.1 . 0
* @ access protected
*
2014-11-28 13:26:24 +01:00
* @ param array $clause Query clause .
* @ param array $parent_query Parent query of $clause .
2014-10-15 18:40:18 +02:00
* @ return string | bool Table alias if found , otherwise false .
*/
protected function find_compatible_table_alias ( $clause , $parent_query ) {
$alias = false ;
// Sanity check. Only IN queries use the JOIN syntax .
if ( ! isset ( $clause [ 'operator' ] ) || 'IN' !== $clause [ 'operator' ] ) {
return $alias ;
}
// Since we're only checking IN queries, we're only concerned with OR relations.
if ( ! isset ( $parent_query [ 'relation' ] ) || 'OR' !== $parent_query [ 'relation' ] ) {
return $alias ;
}
$compatible_operators = array ( 'IN' );
foreach ( $parent_query as $sibling ) {
if ( ! is_array ( $sibling ) || ! $this -> is_first_order_clause ( $sibling ) ) {
continue ;
}
if ( empty ( $sibling [ 'alias' ] ) || empty ( $sibling [ 'operator' ] ) ) {
continue ;
}
// The sibling must both have compatible operator to share its alias.
if ( in_array ( strtoupper ( $sibling [ 'operator' ] ), $compatible_operators ) ) {
$alias = $sibling [ 'alias' ];
break ;
}
}
return $alias ;
}
2014-10-14 06:03:19 +02:00
2010-12-10 09:20:46 +01:00
/**
2011-04-22 21:09:48 +02:00
* Validates a single query .
2010-12-10 09:20:46 +01:00
*
2011-04-22 21:09:48 +02:00
* @ since 3.2 . 0
2010-12-10 09:20:46 +01:00
* @ access private
*
2014-10-14 06:03:19 +02:00
* @ param array & $query The single query .
2011-04-22 21:09:48 +02:00
*/
private function clean_query ( & $query ) {
2014-05-23 21:59:14 +02:00
if ( empty ( $query [ 'taxonomy' ] ) ) {
if ( 'term_taxonomy_id' !== $query [ 'field' ] ) {
$query = new WP_Error ( 'Invalid taxonomy' );
return ;
}
// so long as there are shared terms, include_children requires that a taxonomy is set
$query [ 'include_children' ] = false ;
} elseif ( ! taxonomy_exists ( $query [ 'taxonomy' ] ) ) {
2011-04-22 21:09:48 +02:00
$query = new WP_Error ( 'Invalid taxonomy' );
return ;
}
$query [ 'terms' ] = array_unique ( ( array ) $query [ 'terms' ] );
if ( is_taxonomy_hierarchical ( $query [ 'taxonomy' ] ) && $query [ 'include_children' ] ) {
$this -> transform_query ( $query , 'term_id' );
if ( is_wp_error ( $query ) )
return ;
$children = array ();
foreach ( $query [ 'terms' ] as $term ) {
$children = array_merge ( $children , get_term_children ( $term , $query [ 'taxonomy' ] ) );
$children [] = $term ;
}
$query [ 'terms' ] = $children ;
}
$this -> transform_query ( $query , 'term_taxonomy_id' );
}
/**
* Transforms a single query , from one field to another .
*
* @ since 3.2 . 0
*
2015-05-05 04:01:25 +02:00
* @ global wpdb $wpdb The WordPress database abstraction object .
*
2014-10-14 06:03:19 +02:00
* @ param array & $query The single query .
* @ param string $resulting_field The resulting field . Accepts 'slug' , 'name' , 'term_taxonomy_id' ,
2015-05-07 22:37:41 +02:00
* or 'term_id' . Default 'term_id' .
2010-12-10 09:20:46 +01:00
*/
2012-09-15 22:17:03 +02:00
public function transform_query ( & $query , $resulting_field ) {
2010-12-09 20:29:21 +01:00
global $wpdb ;
2010-11-17 02:56:01 +01:00
2011-04-22 21:09:48 +02:00
if ( empty ( $query [ 'terms' ] ) )
2010-12-09 20:29:21 +01:00
return ;
2011-04-22 21:09:48 +02:00
if ( $query [ 'field' ] == $resulting_field )
2010-12-09 20:29:21 +01:00
return ;
2013-07-16 16:21:05 +02:00
$resulting_field = sanitize_key ( $resulting_field );
2010-12-09 20:29:21 +01:00
2011-04-22 21:09:48 +02:00
switch ( $query [ 'field' ] ) {
2010-12-09 20:29:21 +01:00
case 'slug' :
case 'name' :
2015-02-06 03:02:23 +01:00
foreach ( $query [ 'terms' ] as & $term ) {
/*
* 0 is the $term_id parameter . We don 't have a term ID yet, but it doesn' t
* matter because `sanitize_term_field()` ignores the $term_id param when the
* context is 'db' .
*/
2015-02-08 02:59:24 +01:00
$term = " ' " . esc_sql ( sanitize_term_field ( $query [ 'field' ], $term , 0 , $query [ 'taxonomy' ], 'db' ) ) . " ' " ;
2015-02-06 03:02:23 +01:00
}
$terms = implode ( " , " , $query [ 'terms' ] );
2010-12-09 20:29:21 +01:00
$terms = $wpdb -> get_col ( "
SELECT $wpdb -> term_taxonomy . $resulting_field
FROM $wpdb -> term_taxonomy
INNER JOIN $wpdb -> terms USING ( term_id )
2011-04-22 21:09:48 +02:00
WHERE taxonomy = '{$query[' taxonomy ']}'
AND $wpdb -> terms . { $query [ 'field' ]} IN ( $terms )
2010-12-09 20:29:21 +01:00
" );
break ;
2012-08-20 18:49:21 +02:00
case 'term_taxonomy_id' :
$terms = implode ( ',' , array_map ( 'intval' , $query [ 'terms' ] ) );
$terms = $wpdb -> get_col ( "
SELECT $resulting_field
FROM $wpdb -> term_taxonomy
WHERE term_taxonomy_id IN ( $terms )
" );
break ;
2010-12-09 20:29:21 +01:00
default :
2011-04-22 21:09:48 +02:00
$terms = implode ( ',' , array_map ( 'intval' , $query [ 'terms' ] ) );
2010-12-09 20:29:21 +01:00
$terms = $wpdb -> get_col ( "
SELECT $resulting_field
FROM $wpdb -> term_taxonomy
2011-04-22 21:09:48 +02:00
WHERE taxonomy = '{$query[' taxonomy ']}'
2010-12-09 20:29:21 +01:00
AND term_id IN ( $terms )
" );
}
2011-04-22 21:09:48 +02:00
if ( 'AND' == $query [ 'operator' ] && count ( $terms ) < count ( $query [ 'terms' ] ) ) {
$query = new WP_Error ( 'Inexistent terms' );
return ;
}
$query [ 'terms' ] = $terms ;
$query [ 'field' ] = $resulting_field ;
2010-11-17 02:56:01 +01:00
}
}
2010-11-10 00:30:35 +01:00
2007-09-15 19:35:32 +02:00
/**
2008-06-22 22:23:23 +02:00
* Get all Term data from database by Term ID .
2007-10-16 00:49:31 +02:00
*
2008-06-22 22:23:23 +02:00
* The usage of the get_term function is to apply filters to a term object . It
* is possible to get a term object from the database before applying the
2007-10-21 19:18:24 +02:00
* filters .
2007-09-15 19:35:32 +02:00
*
2008-06-22 22:23:23 +02:00
* $term ID must be part of $taxonomy , to get from the database . Failure , might
* be able to be captured by the hooks . Failure would be the same value as $wpdb
* returns for the get_row method .
2007-09-15 19:35:32 +02:00
*
2008-06-22 22:23:23 +02:00
* There are two hooks , one is specifically for each term , named 'get_term' , and
* the second is for the taxonomy name , 'term_$taxonomy' . Both hooks gets the
* term object , and the taxonomy name as parameters . Both hooks are expected to
* return a Term object .
2007-10-21 19:18:24 +02:00
*
2015-05-07 22:37:41 +02:00
* { @ see 'get_term' } hook - Takes two parameters the term Object and the taxonomy name .
2008-06-22 22:23:23 +02:00
* Must return term object . Used in get_term () as a catch - all filter for every
* $term .
2007-10-21 19:18:24 +02:00
*
2015-05-07 22:37:41 +02:00
* { @ see 'get_$taxonomy' } hook - Takes two parameters the term Object and the taxonomy
2008-06-22 22:23:23 +02:00
* name . Must return term object . $taxonomy will be the taxonomy name , so for
* example , if 'category' , it would be 'get_category' as the filter name . Useful
* for custom taxonomies or plugging into default taxonomies .
2007-10-16 00:49:31 +02:00
*
2015-05-07 22:37:41 +02:00
* @ todo Better formatting for DocBlock
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2007-10-21 19:18:24 +02:00
*
2014-10-31 18:56:22 +01:00
* @ global wpdb $wpdb WordPress database abstraction object .
2007-12-14 01:25:39 +01:00
* @ see sanitize_term_field () The $context param lists the available values for get_term_by () $filter param .
2007-09-15 19:35:32 +02:00
*
2007-10-16 00:49:31 +02:00
* @ param int | object $term If integer , will get from database . If object will apply filters and return $term .
* @ param string $taxonomy Taxonomy name that $term is part of .
* @ param string $output Constant OBJECT , ARRAY_A , or ARRAY_N
2007-12-14 01:25:39 +01:00
* @ param string $filter Optional , default is raw or no WordPress defined filter will applied .
2007-10-21 19:18:24 +02:00
* @ return mixed | null | WP_Error Term Row from database . Will return null if $term is empty . If taxonomy does not
* exist then WP_Error will be returned .
2007-09-15 19:35:32 +02:00
*/
2012-09-10 19:00:11 +02:00
function get_term ( $term , $taxonomy , $output = OBJECT , $filter = 'raw' ) {
2007-09-15 19:35:32 +02:00
global $wpdb ;
2008-08-14 19:00:37 +02:00
if ( empty ( $term ) ) {
$error = new WP_Error ( 'invalid_term' , __ ( 'Empty Term' ));
return $error ;
}
2007-09-15 19:35:32 +02:00
2010-06-11 17:53:41 +02:00
if ( ! taxonomy_exists ( $taxonomy ) ) {
2012-06-01 21:05:30 +02:00
$error = new WP_Error ( 'invalid_taxonomy' , __ ( 'Invalid taxonomy' ));
2008-08-14 19:00:37 +02:00
return $error ;
}
2007-09-15 19:35:32 +02:00
2008-11-17 21:03:31 +01:00
if ( is_object ( $term ) && empty ( $term -> filter ) ) {
2014-12-16 14:27:22 +01:00
wp_cache_add ( $term -> term_id , $term , $taxonomy );
2007-09-15 19:35:32 +02:00
$_term = $term ;
} else {
2008-11-17 21:03:31 +01:00
if ( is_object ( $term ) )
$term = $term -> term_id ;
2011-08-24 12:39:52 +02:00
if ( ! $term = ( int ) $term )
2014-01-29 07:46:12 +01:00
return null ;
2014-12-16 14:27:22 +01:00
if ( ! $_term = wp_cache_get ( $term , $taxonomy ) ) {
2011-08-24 12:39:52 +02:00
$_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 ) );
2009-11-17 21:51:32 +01:00
if ( ! $_term )
2014-01-29 07:46:12 +01:00
return null ;
2014-12-16 14:27:22 +01:00
wp_cache_add ( $term , $_term , $taxonomy );
2007-09-15 19:35:32 +02:00
}
}
2008-02-05 07:47:27 +01:00
2014-03-28 22:29:13 +01:00
/**
* Filter a term .
*
* @ since 2.3 . 0
*
* @ param int | object $_term Term object or ID .
* @ param string $taxonomy The taxonomy slug .
*/
$_term = apply_filters ( 'get_term' , $_term , $taxonomy );
/**
* Filter a taxonomy .
*
2014-11-30 13:00:23 +01:00
* The dynamic portion of the filter name , `$taxonomy` , refers
2014-03-28 22:29:13 +01:00
* to the taxonomy slug .
*
* @ since 2.3 . 0
*
* @ param int | object $_term Term object or ID .
* @ param string $taxonomy The taxonomy slug .
*/
$_term = apply_filters ( " get_ $taxonomy " , $_term , $taxonomy );
2007-09-15 19:35:32 +02:00
$_term = sanitize_term ( $_term , $taxonomy , $filter );
if ( $output == OBJECT ) {
return $_term ;
} elseif ( $output == ARRAY_A ) {
2008-11-03 00:52:49 +01:00
$__term = get_object_vars ( $_term );
return $__term ;
2007-09-15 19:35:32 +02:00
} elseif ( $output == ARRAY_N ) {
2008-11-03 00:52:49 +01:00
$__term = array_values ( get_object_vars ( $_term ));
return $__term ;
2007-09-15 19:35:32 +02:00
} else {
return $_term ;
}
}
/**
2008-06-22 22:23:23 +02:00
* Get all Term data from database by Term field and data .
2007-09-15 19:35:32 +02:00
*
2008-06-22 22:23:23 +02:00
* Warning : $value is not escaped for 'name' $field . You must do it yourself , if
* required .
2007-09-15 19:35:32 +02:00
*
2008-06-22 22:23:23 +02:00
* The default $field is 'id' , therefore it is possible to also use null for
* field , but not recommended that you do so .
2007-10-16 00:49:31 +02:00
*
2008-06-22 22:23:23 +02:00
* If $value does not exist , the return value will be false . If $taxonomy exists
* and $field and $value combinations exist , the Term will be returned .
2007-10-16 00:49:31 +02:00
*
2015-05-07 22:37:41 +02:00
* @ todo Better formatting for DocBlock .
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2007-10-21 19:18:24 +02:00
*
2014-10-31 18:56:22 +01:00
* @ global wpdb $wpdb WordPress database abstraction object .
2007-12-14 01:25:39 +01:00
* @ see sanitize_term_field () The $context param lists the available values for get_term_by () $filter param .
2007-09-15 19:35:32 +02:00
*
2013-09-11 02:02:08 +02:00
* @ param string $field Either 'slug' , 'name' , 'id' ( term_id ), or 'term_taxonomy_id'
2007-10-16 00:49:31 +02:00
* @ param string | int $value Search for this term value
* @ param string $taxonomy Taxonomy Name
* @ param string $output Constant OBJECT , ARRAY_A , or ARRAY_N
2007-12-14 01:25:39 +01:00
* @ param string $filter Optional , default is raw or no WordPress defined filter will applied .
2007-10-21 19:18:24 +02:00
* @ return mixed Term Row from database . Will return false if $taxonomy does not exist or $term was not found .
2007-09-15 19:35:32 +02:00
*/
function get_term_by ( $field , $value , $taxonomy , $output = OBJECT , $filter = 'raw' ) {
global $wpdb ;
2010-06-11 17:53:41 +02:00
if ( ! taxonomy_exists ( $taxonomy ) )
2007-09-15 19:35:32 +02:00
return false ;
if ( 'slug' == $field ) {
$field = 't.slug' ;
2011-01-24 07:26:38 +01:00
$value = sanitize_title ( $value );
2007-09-15 19:35:32 +02:00
if ( empty ( $value ) )
return false ;
2015-01-08 07:26:23 +01:00
} elseif ( 'name' == $field ) {
2013-03-01 17:28:40 +01:00
// Assume already escaped
2013-03-03 22:11:40 +01:00
$value = wp_unslash ( $value );
2007-09-15 19:35:32 +02:00
$field = 't.name' ;
2015-01-08 07:26:23 +01:00
} elseif ( 'term_taxonomy_id' == $field ) {
2013-09-11 02:02:08 +02:00
$value = ( int ) $value ;
$field = 'tt.term_taxonomy_id' ;
2007-09-15 19:35:32 +02:00
} else {
2014-12-16 14:27:22 +01:00
$term = get_term ( ( int ) $value , $taxonomy , $output , $filter );
if ( is_wp_error ( $term ) )
2011-03-22 21:06:38 +01:00
$term = false ;
2014-12-16 14:27:22 +01:00
return $term ;
2007-09-15 19:35:32 +02:00
}
2014-12-16 14:27:22 +01:00
$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 ) );
if ( ! $term )
2007-09-15 19:35:32 +02:00
return false ;
2014-12-16 14:27:22 +01:00
wp_cache_add ( $term -> term_id , $term , $taxonomy );
2014-03-28 22:29:13 +01:00
/** This filter is documented in wp-includes/taxonomy.php */
$term = apply_filters ( 'get_term' , $term , $taxonomy );
/** This filter is documented in wp-includes/taxonomy.php */
$term = apply_filters ( " get_ $taxonomy " , $term , $taxonomy );
2007-09-15 19:35:32 +02:00
$term = sanitize_term ( $term , $taxonomy , $filter );
if ( $output == OBJECT ) {
return $term ;
} elseif ( $output == ARRAY_A ) {
return get_object_vars ( $term );
} elseif ( $output == ARRAY_N ) {
return array_values ( get_object_vars ( $term ));
} else {
return $term ;
}
}
/**
2009-04-28 21:49:21 +02:00
* Merge all term children into a single array of their IDs .
2007-09-15 19:35:32 +02:00
*
2008-06-22 22:23:23 +02:00
* This recursive function will merge all of the children of $term into the same
2009-04-28 21:49:21 +02:00
* array of term IDs . Only useful for taxonomies which are hierarchical .
2007-09-15 19:35:32 +02:00
*
2007-10-21 19:18:24 +02:00
* Will return an empty array if $term does not exist in $taxonomy .
2008-02-05 07:47:27 +01:00
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2007-10-21 19:18:24 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param string $term_id ID of Term to get children .
* @ param string $taxonomy Taxonomy Name .
* @ return array | WP_Error List of Term IDs . WP_Error returned if `$taxonomy` does not exist .
2007-09-15 19:35:32 +02:00
*/
2009-04-28 21:49:21 +02:00
function get_term_children ( $term_id , $taxonomy ) {
2010-06-11 17:53:41 +02:00
if ( ! taxonomy_exists ( $taxonomy ) )
2012-06-01 21:05:30 +02:00
return new WP_Error ( 'invalid_taxonomy' , __ ( 'Invalid taxonomy' ));
2007-09-15 19:35:32 +02:00
2009-04-28 21:49:21 +02:00
$term_id = intval ( $term_id );
2007-09-15 19:35:32 +02:00
$terms = _get_term_hierarchy ( $taxonomy );
2009-04-28 21:49:21 +02:00
if ( ! isset ( $terms [ $term_id ]) )
2007-09-15 19:35:32 +02:00
return array ();
2009-04-28 21:49:21 +02:00
$children = $terms [ $term_id ];
2007-09-15 19:35:32 +02:00
2009-04-28 21:49:21 +02:00
foreach ( ( array ) $terms [ $term_id ] as $child ) {
2014-03-29 07:08:15 +01:00
if ( $term_id == $child ) {
continue ;
}
2007-09-15 19:35:32 +02:00
if ( isset ( $terms [ $child ]) )
$children = array_merge ( $children , get_term_children ( $child , $taxonomy ));
}
return $children ;
}
/**
2008-06-22 22:23:23 +02:00
* Get sanitized Term field .
2008-02-05 07:47:27 +01:00
*
2008-06-22 22:23:23 +02:00
* Does checks for $term , based on the $taxonomy . The function is for contextual
* reasons and for simplicity of usage . See sanitize_term_field () for more
* information .
2007-09-15 19:35:32 +02:00
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2007-10-21 19:18:24 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param string $field Term field to fetch .
* @ param int $term Term ID .
* @ param string $taxonomy Taxonomy Name .
* @ param string $context Optional , default is display . Look at sanitize_term_field () for available options .
2007-10-21 19:18:24 +02:00
* @ return mixed Will return an empty string if $term is not an object or if $field is not set in $term .
2007-09-15 19:35:32 +02:00
*/
function get_term_field ( $field , $term , $taxonomy , $context = 'display' ) {
$term = ( int ) $term ;
$term = get_term ( $term , $taxonomy );
if ( is_wp_error ( $term ) )
return $term ;
if ( ! is_object ( $term ) )
return '' ;
if ( ! isset ( $term -> $field ) )
return '' ;
return sanitize_term_field ( $field , $term -> $field , $term -> term_id , $taxonomy , $context );
}
/**
2008-06-22 22:23:23 +02:00
* Sanitizes Term for editing .
2007-09-15 19:35:32 +02:00
*
2008-06-22 22:23:23 +02:00
* Return value is sanitize_term () and usage is for sanitizing the term for
* editing . Function is for contextual and simplicity .
2008-02-05 07:47:27 +01:00
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2007-10-21 19:18:24 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param int | object $id Term ID or object .
* @ param string $taxonomy Taxonomy name .
2007-10-21 19:18:24 +02:00
* @ return mixed | null | WP_Error Will return empty string if $term is not an object .
2007-09-15 19:35:32 +02:00
*/
function get_term_to_edit ( $id , $taxonomy ) {
$term = get_term ( $id , $taxonomy );
if ( is_wp_error ( $term ) )
return $term ;
if ( ! is_object ( $term ) )
return '' ;
return sanitize_term ( $term , $taxonomy , 'edit' );
}
/**
2008-11-13 01:20:12 +01:00
* Retrieve the terms in a given taxonomy or list of taxonomies .
2007-10-21 19:18:24 +02:00
*
2008-06-22 22:23:23 +02:00
* You can fully inject any customizations to the query before it is sent , as
* well as control the output with a filter .
2007-10-21 19:18:24 +02:00
*
2015-05-07 22:37:41 +02:00
* The { @ see 'get_terms' } filter will be called when the cache has the term and will
2008-06-22 22:23:23 +02:00
* pass the found term along with the array of $taxonomies and array of $args .
* This filter is also called before the array of terms is passed and will pass
* the array of terms , along with the $taxonomies and $args .
2007-10-21 19:18:24 +02:00
*
2015-05-07 22:37:41 +02:00
* The { @ see 'list_terms_exclusions' } filter passes the compiled exclusions along with
2008-06-22 22:23:23 +02:00
* the $args .
2007-10-21 19:18:24 +02:00
*
2015-05-07 22:37:41 +02:00
* The { @ see 'get_terms_orderby' } filter passes the `ORDER BY` clause for the query
2009-04-22 00:13:44 +02:00
* along with the $args array .
2010-05-26 07:11:46 +02:00
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2015-01-24 19:48:23 +01:00
* @ since 4.2 . 0 Introduced 'name' and 'childless' parameters .
2007-10-16 00:49:31 +02:00
*
2014-10-31 18:56:22 +01:00
* @ global wpdb $wpdb WordPress database abstraction object .
2014-07-13 06:15:16 +02:00
*
* @ param string | array $taxonomies Taxonomy name or list of Taxonomy names .
* @ param array | string $args {
* Optional . Array or string of arguments to get terms .
*
2015-02-24 17:37:26 +01:00
* @ type string $orderby Field ( s ) to order terms by . Accepts term fields ( 'name' , 'slug' ,
* 'term_group' , 'term_id' , 'id' , 'description' ), 'count' for term
* taxonomy count , 'include' to match the 'order' of the $include param ,
* or 'none' to skip ORDER BY . Defaults to 'name' .
* @ type string $order Whether to order terms in ascending or descending order .
2014-07-13 06:18:15 +02:00
* Accepts 'ASC' ( ascending ) or 'DESC' ( descending ) .
* Default 'ASC' .
* @ type bool | int $hide_empty Whether to hide terms not assigned to any posts . Accepts
* 1 | true or 0 | false . Default 1 | true .
* @ type array | string $include Array or comma / space - separated string of term ids to include .
* Default empty array .
* @ type array | string $exclude Array or comma / space - separated string of term ids to exclude .
* If $include is non - empty , $exclude is ignored .
* Default empty array .
* @ type array | string $exclude_tree Array or comma / space - separated string of term ids to exclude
* along with all of their descendant terms . If $include is
* non - empty , $exclude_tree is ignored . Default empty array .
2015-03-06 09:05:25 +01:00
* @ type int | string $number Maximum number of terms to return . Accepts '' | 0 ( all ) or any
* positive number . Default '' | 0 ( all ) .
2014-07-13 06:18:15 +02:00
* @ type int $offset The number by which to offset the terms query . Default empty .
* @ type string $fields Term fields to query for . Accepts 'all' ( returns an array of
* term objects ), 'ids' or 'names' ( returns an array of integers
* or strings , respectively . Default 'all' .
2015-01-02 22:34:23 +01:00
* @ type string | array $name Optional . Name or array of names to return term ( s ) for . Default empty .
2014-10-29 03:35:23 +01:00
* @ type string | array $slug Optional . Slug or array of slugs to return term ( s ) for . Default empty .
2014-07-13 06:18:15 +02:00
* @ type bool $hierarchical Whether to include terms that have non - empty descendants ( even
* if $hide_empty is set to true ) . Default true .
* @ type string $search Search criteria to match terms . Will be SQL - formatted with
* wildcards before and after . Default empty .
* @ type string $name__like Retrieve terms with criteria by which a term is LIKE $name__like .
* Default empty .
* @ type string $description__like Retrieve terms where the description is LIKE $description__like .
* Default empty .
* @ type bool $pad_counts Whether to pad the quantity of a term ' s children in the quantity
* of each term ' s " count " object variable . Default false .
* @ type string $get Whether to return terms regardless of ancestry or whether the terms
* are empty . Accepts 'all' or empty ( disabled ) . Default empty .
* @ type int $child_of Term ID to retrieve child terms of . If multiple taxonomies
* are passed , $child_of is ignored . Default 0.
* @ type int | string $parent Parent term ID to retrieve direct - child terms of . Default empty .
2015-01-24 19:48:23 +01:00
* @ type bool $childless True to limit results to terms that have no children . This parameter has
* no effect on non - hierarchical taxonomies . Default false .
2014-07-13 06:18:15 +02:00
* @ type string $cache_domain Unique cache key to be produced when this query is stored in an
* object cache . Default is 'core' .
2014-07-13 06:15:16 +02:00
* }
* @ return array | WP_Error List of Term Objects and their children . Will return WP_Error , if any of $taxonomies
* do not exist .
2007-09-15 19:35:32 +02:00
*/
2014-05-17 16:47:14 +02:00
function get_terms ( $taxonomies , $args = '' ) {
2007-09-15 19:35:32 +02:00
global $wpdb ;
2008-01-10 21:51:07 +01:00
$empty_array = array ();
2007-09-15 19:35:32 +02:00
2012-11-07 10:03:40 +01:00
$single_taxonomy = ! is_array ( $taxonomies ) || 1 === count ( $taxonomies );
2014-05-17 16:47:14 +02:00
if ( ! is_array ( $taxonomies ) ) {
2012-11-07 10:03:40 +01:00
$taxonomies = array ( $taxonomies );
2014-05-17 16:47:14 +02:00
}
2007-09-15 19:35:32 +02:00
2010-10-28 21:09:18 +02:00
foreach ( $taxonomies as $taxonomy ) {
2010-06-11 17:53:41 +02:00
if ( ! taxonomy_exists ( $taxonomy ) ) {
2012-06-01 21:05:30 +02:00
$error = new WP_Error ( 'invalid_taxonomy' , __ ( 'Invalid taxonomy' ));
2009-05-06 07:03:59 +02:00
return $error ;
}
2007-09-15 19:35:32 +02:00
}
$defaults = array ( 'orderby' => 'name' , 'order' => 'ASC' ,
2010-01-08 09:44:45 +01:00
'hide_empty' => true , 'exclude' => array (), 'exclude_tree' => array (), 'include' => array (),
2015-01-24 19:48:23 +01:00
'number' => '' , 'fields' => 'all' , 'name' => '' , 'slug' => '' , 'parent' => '' , 'childless' => false ,
2013-09-04 21:41:08 +02:00
'hierarchical' => true , 'child_of' => 0 , 'get' => '' , 'name__like' => '' , 'description__like' => '' ,
2011-06-03 17:24:14 +02:00
'pad_counts' => false , 'offset' => '' , 'search' => '' , 'cache_domain' => 'core' );
2007-09-15 19:35:32 +02:00
$args = wp_parse_args ( $args , $defaults );
2007-10-13 05:51:11 +02:00
$args [ 'number' ] = absint ( $args [ 'number' ] );
2008-01-25 20:29:01 +01:00
$args [ 'offset' ] = absint ( $args [ 'offset' ] );
2014-10-30 03:12:22 +01:00
// Save queries by not crawling the tree in the case of multiple taxes or a flat tax.
2015-01-26 19:09:22 +01:00
$has_hierarchical_tax = false ;
foreach ( $taxonomies as $_tax ) {
if ( is_taxonomy_hierarchical ( $_tax ) ) {
$has_hierarchical_tax = true ;
}
}
if ( ! $has_hierarchical_tax ) {
2007-09-15 19:35:32 +02:00
$args [ 'hierarchical' ] = false ;
$args [ 'pad_counts' ] = false ;
}
2014-10-30 03:12:22 +01:00
// 'parent' overrides 'child_of'.
if ( 0 < intval ( $args [ 'parent' ] ) ) {
$args [ 'child_of' ] = false ;
}
2007-09-15 19:35:32 +02:00
if ( 'all' == $args [ 'get' ] ) {
2015-01-24 19:48:23 +01:00
$args [ 'childless' ] = false ;
2007-09-15 19:35:32 +02:00
$args [ 'child_of' ] = 0 ;
$args [ 'hide_empty' ] = 0 ;
$args [ 'hierarchical' ] = false ;
$args [ 'pad_counts' ] = false ;
}
2010-10-28 19:55:30 +02:00
2014-03-28 22:29:13 +01:00
/**
* Filter the terms query arguments .
*
* @ since 3.1 . 0
*
2015-05-07 22:37:41 +02:00
* @ param array $args An array of get_term () arguments .
2014-12-28 02:44:24 +01:00
* @ param array $taxonomies An array of taxonomies .
2014-03-28 22:29:13 +01:00
*/
2010-10-28 21:09:18 +02:00
$args = apply_filters ( 'get_terms_args' , $args , $taxonomies );
2015-01-25 03:46:25 +01:00
// Avoid the query if the queried parent/child_of term has no descendants.
2014-05-17 16:47:14 +02:00
$child_of = $args [ 'child_of' ];
2015-01-25 03:46:25 +01:00
$parent = $args [ 'parent' ];
2007-09-15 19:35:32 +02:00
if ( $child_of ) {
2015-01-25 03:46:25 +01:00
$_parent = $child_of ;
} elseif ( $parent ) {
$_parent = $parent ;
} else {
$_parent = false ;
2007-09-15 19:35:32 +02:00
}
2015-01-25 03:46:25 +01:00
if ( $_parent ) {
$in_hierarchy = false ;
foreach ( $taxonomies as $_tax ) {
$hierarchy = _get_term_hierarchy ( $_tax );
if ( isset ( $hierarchy [ $_parent ] ) ) {
$in_hierarchy = true ;
}
}
if ( ! $in_hierarchy ) {
2008-01-10 21:51:07 +01:00
return $empty_array ;
2014-05-17 16:47:14 +02:00
}
2007-09-15 19:35:32 +02:00
}
2015-05-07 22:37:41 +02:00
// $args can be whatever, only use the args defined in defaults to compute the key.
2008-07-01 17:54:58 +02:00
$filter_key = ( has_filter ( 'list_terms_exclusions' ) ) ? serialize ( $GLOBALS [ 'wp_filter' ][ 'list_terms_exclusions' ]) : '' ;
2014-05-17 16:47:14 +02:00
$key = md5 ( serialize ( wp_array_slice_assoc ( $args , array_keys ( $defaults ) ) ) . serialize ( $taxonomies ) . $filter_key );
2013-02-04 14:48:46 +01:00
$last_changed = wp_cache_get ( 'last_changed' , 'terms' );
if ( ! $last_changed ) {
2014-02-26 23:05:13 +01:00
$last_changed = microtime ();
2013-02-04 14:48:46 +01:00
wp_cache_set ( 'last_changed' , $last_changed , 'terms' );
2008-10-09 00:50:46 +02:00
}
$cache_key = " get_terms: $key : $last_changed " ;
2009-04-30 18:51:45 +02:00
$cache = wp_cache_get ( $cache_key , 'terms' );
if ( false !== $cache ) {
2014-03-28 22:29:13 +01:00
/**
* Filter the given taxonomy ' s terms cache .
*
* @ since 2.3 . 0
*
2014-12-28 02:44:24 +01:00
* @ param array $cache Cached array of terms for the given taxonomy .
* @ param array $taxonomies An array of taxonomies .
2015-05-07 22:37:41 +02:00
* @ param array $args An array of get_terms () arguments .
2014-03-28 22:29:13 +01:00
*/
$cache = apply_filters ( 'get_terms' , $cache , $taxonomies , $args );
2009-04-30 18:51:45 +02:00
return $cache ;
2007-09-15 19:35:32 +02:00
}
2014-05-17 16:47:14 +02:00
$_orderby = strtolower ( $args [ 'orderby' ] );
if ( 'count' == $_orderby ) {
2007-09-15 19:35:32 +02:00
$orderby = 'tt.count' ;
2015-01-08 07:26:23 +01:00
} elseif ( 'name' == $_orderby ) {
2007-09-15 19:35:32 +02:00
$orderby = 't.name' ;
2015-01-08 07:26:23 +01:00
} elseif ( 'slug' == $_orderby ) {
2007-10-23 18:39:03 +02:00
$orderby = 't.slug' ;
2015-01-08 07:26:23 +01:00
} elseif ( 'include' == $_orderby && ! empty ( $args [ 'include' ] ) ) {
2014-10-28 19:13:19 +01:00
$include = implode ( ',' , array_map ( 'absint' , $args [ 'include' ] ) );
$orderby = " FIELD( t.term_id, $include ) " ;
2015-01-08 07:26:23 +01:00
} elseif ( 'term_group' == $_orderby ) {
2007-10-23 18:39:03 +02:00
$orderby = 't.term_group' ;
2015-02-24 17:37:26 +01:00
} elseif ( 'description' == $_orderby ) {
$orderby = 'tt.description' ;
2015-01-08 07:26:23 +01:00
} elseif ( 'none' == $_orderby ) {
2010-05-11 18:50:25 +02:00
$orderby = '' ;
2014-05-17 16:47:14 +02:00
} elseif ( empty ( $_orderby ) || 'id' == $_orderby ) {
2007-09-15 19:35:32 +02:00
$orderby = 't.term_id' ;
2014-05-17 16:47:14 +02:00
} else {
2011-06-27 17:45:12 +02:00
$orderby = 't.name' ;
2014-05-17 16:47:14 +02:00
}
2015-05-07 22:37:41 +02:00
2014-03-28 22:29:13 +01:00
/**
* Filter the ORDERBY clause of the terms query .
*
* @ since 2.8 . 0
*
2015-05-07 22:37:41 +02:00
* @ param string $orderby `ORDERBY` clause of the terms query .
2014-12-28 02:44:24 +01:00
* @ param array $args An array of terms query arguments .
* @ param array $taxonomies An array of taxonomies .
2014-03-28 22:29:13 +01:00
*/
2013-08-27 23:06:09 +02:00
$orderby = apply_filters ( 'get_terms_orderby' , $orderby , $args , $taxonomies );
2007-09-15 19:35:32 +02:00
2014-05-17 16:47:14 +02:00
$order = strtoupper ( $args [ 'order' ] );
if ( ! empty ( $orderby ) ) {
2010-05-11 18:50:25 +02:00
$orderby = " ORDER BY $orderby " ;
2014-05-17 16:47:14 +02:00
} else {
2010-05-11 18:50:25 +02:00
$order = '' ;
2014-05-17 16:47:14 +02:00
}
2010-05-11 18:50:25 +02:00
2014-05-17 16:47:14 +02:00
if ( '' !== $order && ! in_array ( $order , array ( 'ASC' , 'DESC' ) ) ) {
2011-06-27 17:45:12 +02:00
$order = 'ASC' ;
2014-05-17 16:47:14 +02:00
}
2011-06-27 17:45:12 +02:00
2010-10-28 19:55:30 +02:00
$where = " tt.taxonomy IN (' " . implode ( " ', ' " , $taxonomies ) . " ') " ;
2014-05-17 16:47:14 +02:00
$exclude = $args [ 'exclude' ];
$exclude_tree = $args [ 'exclude_tree' ];
$include = $args [ 'include' ];
2007-09-15 19:35:32 +02:00
$inclusions = '' ;
2013-08-29 18:24:09 +02:00
if ( ! empty ( $include ) ) {
2007-09-15 19:35:32 +02:00
$exclude = '' ;
2008-12-30 23:30:36 +01:00
$exclude_tree = '' ;
2013-08-29 20:54:09 +02:00
$inclusions = implode ( ',' , wp_parse_id_list ( $include ) );
2007-09-15 19:35:32 +02:00
}
2013-09-05 19:15:09 +02:00
if ( ! empty ( $inclusions ) ) {
2013-08-29 18:24:09 +02:00
$inclusions = ' AND t.term_id IN ( ' . $inclusions . ' )' ;
2013-09-05 19:15:09 +02:00
$where .= $inclusions ;
}
2007-09-15 19:35:32 +02:00
2015-01-24 19:48:23 +01:00
$exclusions = array ();
2013-08-23 23:29:10 +02:00
if ( ! empty ( $exclude_tree ) ) {
2013-08-29 18:24:09 +02:00
$exclude_tree = wp_parse_id_list ( $exclude_tree );
2013-10-26 17:04:11 +02:00
$excluded_children = $exclude_tree ;
2013-08-29 18:24:09 +02:00
foreach ( $exclude_tree as $extrunk ) {
$excluded_children = array_merge (
$excluded_children ,
( array ) get_terms ( $taxonomies [ 0 ], array ( 'child_of' => intval ( $extrunk ), 'fields' => 'ids' , 'hide_empty' => 0 ) )
);
2008-12-30 23:30:36 +01:00
}
2015-01-24 19:48:23 +01:00
$exclusions = array_merge ( $excluded_children , $exclusions );
2008-12-30 23:30:36 +01:00
}
2010-01-08 09:44:45 +01:00
2013-08-29 18:24:09 +02:00
if ( ! empty ( $exclude ) ) {
2015-01-24 19:48:23 +01:00
$exclusions = array_merge ( wp_parse_id_list ( $exclude ), $exclusions );
}
// 'childless' terms are those without an entry in the flattened term hierarchy.
$childless = ( bool ) $args [ 'childless' ];
if ( $childless ) {
foreach ( $taxonomies as $_tax ) {
$term_hierarchy = _get_term_hierarchy ( $_tax );
$exclusions = array_merge ( array_keys ( $term_hierarchy ), $exclusions );
2014-05-17 16:47:14 +02:00
}
2007-09-15 19:35:32 +02:00
}
2014-05-17 16:47:14 +02:00
if ( ! empty ( $exclusions ) ) {
2015-01-24 19:48:23 +01:00
$exclusions = ' AND t.term_id NOT IN (' . implode ( ',' , array_map ( 'intval' , $exclusions ) ) . ')' ;
2015-03-18 19:23:26 +01:00
} else {
$exclusions = '' ;
2014-05-17 16:47:14 +02:00
}
2013-08-29 18:24:09 +02:00
2014-03-28 22:29:13 +01:00
/**
* Filter the terms to exclude from the terms query .
*
* @ since 2.3 . 0
*
2015-05-07 22:37:41 +02:00
* @ param string $exclusions `NOT IN` clause of the terms query .
2014-12-28 02:44:24 +01:00
* @ param array $args An array of terms query arguments .
* @ param array $taxonomies An array of taxonomies .
2014-03-28 22:29:13 +01:00
*/
2013-09-23 20:39:09 +02:00
$exclusions = apply_filters ( 'list_terms_exclusions' , $exclusions , $args , $taxonomies );
2013-09-05 19:15:09 +02:00
2014-05-17 16:47:14 +02:00
if ( ! empty ( $exclusions ) ) {
2013-09-05 19:15:09 +02:00
$where .= $exclusions ;
2014-05-17 16:47:14 +02:00
}
2007-09-15 19:35:32 +02:00
2015-01-02 22:34:23 +01:00
if ( ! empty ( $args [ 'name' ] ) ) {
2015-05-05 13:14:28 +02:00
$names = ( array ) $args [ 'name' ];
foreach ( $names as & $_name ) {
$_name = sanitize_term_field ( 'name' , $_name , 0 , reset ( $taxonomies ), 'db' );
2015-01-02 22:34:23 +01:00
}
2015-05-05 13:14:28 +02:00
$where .= " AND t.name IN (' " . implode ( " ', ' " , array_map ( 'esc_sql' , $names ) ) . " ') " ;
2015-01-02 22:34:23 +01:00
}
2014-05-17 16:47:14 +02:00
if ( ! empty ( $args [ 'slug' ] ) ) {
2014-10-28 15:57:22 +01:00
if ( is_array ( $args [ 'slug' ] ) ) {
$slug = array_map ( 'sanitize_title' , $args [ 'slug' ] );
$where .= " AND t.slug IN (' " . implode ( " ', ' " , $slug ) . " ') " ;
} else {
$slug = sanitize_title ( $args [ 'slug' ] );
$where .= " AND t.slug = ' $slug ' " ;
}
2007-09-15 19:35:32 +02:00
}
2014-05-17 16:47:14 +02:00
if ( ! empty ( $args [ 'name__like' ] ) ) {
2014-06-10 02:44:15 +02:00
$where .= $wpdb -> prepare ( " AND t.name LIKE %s " , '%' . $wpdb -> esc_like ( $args [ 'name__like' ] ) . '%' );
2013-09-04 21:41:08 +02:00
}
2014-05-17 16:47:14 +02:00
if ( ! empty ( $args [ 'description__like' ] ) ) {
2014-06-10 02:44:15 +02:00
$where .= $wpdb -> prepare ( " AND tt.description LIKE %s " , '%' . $wpdb -> esc_like ( $args [ 'description__like' ] ) . '%' );
2011-05-23 01:22:59 +02:00
}
2007-09-15 19:35:32 +02:00
2009-05-28 20:06:08 +02:00
if ( '' !== $parent ) {
2007-09-15 19:35:32 +02:00
$parent = ( int ) $parent ;
$where .= " AND tt.parent = ' $parent ' " ;
}
2014-05-17 16:47:14 +02:00
$hierarchical = $args [ 'hierarchical' ];
if ( 'count' == $args [ 'fields' ] ) {
2013-09-21 18:48:10 +02:00
$hierarchical = false ;
2014-05-17 16:47:14 +02:00
}
if ( $args [ 'hide_empty' ] && ! $hierarchical ) {
2007-09-15 19:35:32 +02:00
$where .= ' AND tt.count > 0' ;
2014-05-17 16:47:14 +02:00
}
$number = $args [ 'number' ];
$offset = $args [ 'offset' ];
2007-09-15 19:35:32 +02:00
2015-05-07 22:37:41 +02:00
// Don't limit the query results when we have to descend the family tree.
2013-03-04 03:52:43 +01:00
if ( $number && ! $hierarchical && ! $child_of && '' === $parent ) {
2014-05-17 16:47:14 +02:00
if ( $offset ) {
2010-10-28 19:55:30 +02:00
$limits = 'LIMIT ' . $offset . ',' . $number ;
2014-05-17 16:47:14 +02:00
} else {
2010-10-28 19:55:30 +02:00
$limits = 'LIMIT ' . $number ;
2014-05-17 16:47:14 +02:00
}
2010-01-24 12:00:27 +01:00
} else {
2010-10-28 19:55:30 +02:00
$limits = '' ;
2010-01-24 12:00:27 +01:00
}
2007-09-15 19:35:32 +02:00
2014-05-17 16:47:14 +02:00
if ( ! empty ( $args [ 'search' ] ) ) {
2014-06-10 02:44:15 +02:00
$like = '%' . $wpdb -> esc_like ( $args [ 'search' ] ) . '%' ;
$where .= $wpdb -> prepare ( ' AND ((t.name LIKE %s) OR (t.slug LIKE %s))' , $like , $like );
2008-02-12 10:02:02 +01:00
}
2009-04-22 00:13:44 +02:00
$selects = array ();
2014-05-17 16:47:14 +02:00
switch ( $args [ 'fields' ] ) {
2010-06-30 02:05:18 +02:00
case 'all' :
2013-08-29 17:19:10 +02:00
$selects = array ( 't.*' , 'tt.*' );
2010-06-30 02:05:18 +02:00
break ;
case 'ids' :
2010-02-28 08:37:24 +01:00
case 'id=>parent' :
2015-01-26 20:04:21 +01:00
$selects = array ( 't.term_id' , 'tt.parent' , 'tt.count' , 'tt.taxonomy' );
2010-06-30 02:05:18 +02:00
break ;
case 'names' :
2015-01-26 20:04:21 +01:00
$selects = array ( 't.term_id' , 'tt.parent' , 'tt.count' , 't.name' , 'tt.taxonomy' );
2010-06-30 02:05:18 +02:00
break ;
case 'count' :
2010-05-11 18:50:25 +02:00
$orderby = '' ;
$order = '' ;
2013-08-29 17:19:10 +02:00
$selects = array ( 'COUNT(*)' );
break ;
case 'id=>name' :
2015-01-26 20:04:21 +01:00
$selects = array ( 't.term_id' , 't.name' , 'tt.count' , 'tt.taxonomy' );
2013-08-29 17:19:10 +02:00
break ;
case 'id=>slug' :
2015-01-26 20:04:21 +01:00
$selects = array ( 't.term_id' , 't.slug' , 'tt.count' , 'tt.taxonomy' );
2013-08-29 17:19:10 +02:00
break ;
2010-06-30 02:05:18 +02:00
}
2007-09-15 19:35:32 +02:00
2014-05-17 16:47:14 +02:00
$_fields = $args [ 'fields' ];
2010-10-28 19:55:30 +02:00
2014-03-28 22:29:13 +01:00
/**
* Filter the fields to select in the terms query .
*
2015-03-20 21:11:26 +01:00
* Field lists modified using this filter will only modify the term fields returned
* by the function when the `$fields` parameter set to 'count' or 'all' . In all other
* cases , the term fields in the results array will be determined by the `$fields`
* parameter alone .
*
* Use of this filter can result in unpredictable behavior , and is not recommended .
*
2014-03-28 22:29:13 +01:00
* @ since 2.8 . 0
*
2014-12-28 02:44:24 +01:00
* @ param array $selects An array of fields to select for the terms query .
* @ param array $args An array of term query arguments .
* @ param array $taxonomies An array of taxonomies .
2014-03-28 22:29:13 +01:00
*/
2013-09-23 20:39:09 +02:00
$fields = implode ( ', ' , apply_filters ( 'get_terms_fields' , $selects , $args , $taxonomies ) );
2010-10-28 19:55:30 +02:00
$join = " INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id " ;
$pieces = array ( 'fields' , 'join' , 'where' , 'orderby' , 'order' , 'limits' );
2014-03-28 22:29:13 +01:00
/**
* Filter the terms query SQL clauses .
*
* @ since 3.1 . 0
*
2014-12-28 02:44:24 +01:00
* @ param array $pieces Terms query SQL clauses .
* @ param array $taxonomies An array of taxonomies .
* @ param array $args An array of terms query arguments .
2014-03-28 22:29:13 +01:00
*/
2010-10-28 19:55:30 +02:00
$clauses = apply_filters ( 'terms_clauses' , compact ( $pieces ), $taxonomies , $args );
2015-05-07 22:37:41 +02:00
2014-06-11 19:41:14 +02:00
$fields = isset ( $clauses [ 'fields' ] ) ? $clauses [ 'fields' ] : '' ;
$join = isset ( $clauses [ 'join' ] ) ? $clauses [ 'join' ] : '' ;
$where = isset ( $clauses [ 'where' ] ) ? $clauses [ 'where' ] : '' ;
$orderby = isset ( $clauses [ 'orderby' ] ) ? $clauses [ 'orderby' ] : '' ;
$order = isset ( $clauses [ 'order' ] ) ? $clauses [ 'order' ] : '' ;
$limits = isset ( $clauses [ 'limits' ] ) ? $clauses [ 'limits' ] : '' ;
2010-11-17 19:47:34 +01:00
$query = " SELECT $fields FROM $wpdb->terms AS t $join WHERE $where $orderby $order $limits " ;
2010-10-28 19:55:30 +02:00
2014-05-17 16:47:14 +02:00
if ( 'count' == $_fields ) {
2010-02-28 08:37:24 +01:00
$term_count = $wpdb -> get_var ( $query );
return $term_count ;
}
2009-01-22 23:59:29 +01:00
$terms = $wpdb -> get_results ( $query );
2014-12-17 17:39:24 +01:00
if ( 'all' == $_fields ) {
update_term_cache ( $terms );
}
2007-09-15 19:35:32 +02:00
2007-11-02 05:31:44 +01:00
if ( empty ( $terms ) ) {
2012-09-25 07:26:19 +02:00
wp_cache_add ( $cache_key , array (), 'terms' , DAY_IN_SECONDS );
2014-03-28 22:29:13 +01:00
/** This filter is documented in wp-includes/taxonomy.php */
$terms = apply_filters ( 'get_terms' , array (), $taxonomies , $args );
2008-09-21 22:41:25 +02:00
return $terms ;
2007-11-02 05:31:44 +01:00
}
2007-09-15 19:35:32 +02:00
2008-11-13 01:20:12 +01:00
if ( $child_of ) {
2015-01-25 03:46:25 +01:00
foreach ( $taxonomies as $_tax ) {
$children = _get_term_hierarchy ( $_tax );
if ( ! empty ( $children ) ) {
$terms = _get_term_children ( $child_of , $terms , $_tax );
}
2014-05-17 16:47:14 +02:00
}
2007-09-15 19:35:32 +02:00
}
// Update term counts to include children.
2014-05-17 16:47:14 +02:00
if ( $args [ 'pad_counts' ] && 'all' == $_fields ) {
2015-01-26 19:09:22 +01:00
foreach ( $taxonomies as $_tax ) {
_pad_term_counts ( $terms , $_tax );
}
2014-05-17 16:47:14 +02:00
}
2015-01-26 20:04:21 +01:00
2007-09-15 19:35:32 +02:00
// Make sure we show empty categories that have children.
2014-05-17 16:47:14 +02:00
if ( $hierarchical && $args [ 'hide_empty' ] && is_array ( $terms ) ) {
2007-09-15 19:35:32 +02:00
foreach ( $terms as $k => $term ) {
if ( ! $term -> count ) {
2015-01-26 20:04:21 +01:00
$children = get_term_children ( $term -> term_id , $term -> taxonomy );
2014-03-07 20:29:16 +01:00
if ( is_array ( $children ) ) {
foreach ( $children as $child_id ) {
2015-01-26 20:04:21 +01:00
$child = get_term ( $child_id , $term -> taxonomy );
2014-03-07 20:29:16 +01:00
if ( $child -> count ) {
2008-08-06 22:31:54 +02:00
continue 2 ;
2014-03-07 20:29:16 +01:00
}
}
}
2007-09-15 19:35:32 +02:00
2015-05-07 22:37:41 +02:00
// It really is empty.
2007-09-15 19:35:32 +02:00
unset ( $terms [ $k ]);
}
}
}
2008-12-09 19:03:31 +01:00
2008-11-13 01:20:12 +01:00
$_terms = array ();
2014-05-17 16:47:14 +02:00
if ( 'id=>parent' == $_fields ) {
2015-02-07 20:45:25 +01:00
foreach ( $terms as $term ) {
$_terms [ $term -> term_id ] = $term -> parent ;
2014-05-17 16:47:14 +02:00
}
} elseif ( 'ids' == $_fields ) {
2015-02-07 20:45:25 +01:00
foreach ( $terms as $term ) {
2008-11-13 01:20:12 +01:00
$_terms [] = $term -> term_id ;
2014-05-17 16:47:14 +02:00
}
} elseif ( 'names' == $_fields ) {
2015-02-07 20:45:25 +01:00
foreach ( $terms as $term ) {
2008-11-13 01:20:12 +01:00
$_terms [] = $term -> name ;
2014-05-17 16:47:14 +02:00
}
} elseif ( 'id=>name' == $_fields ) {
2015-02-07 20:45:25 +01:00
foreach ( $terms as $term ) {
$_terms [ $term -> term_id ] = $term -> name ;
2014-05-17 16:47:14 +02:00
}
} elseif ( 'id=>slug' == $_fields ) {
2015-02-07 20:45:25 +01:00
foreach ( $terms as $term ) {
$_terms [ $term -> term_id ] = $term -> slug ;
2014-05-17 16:47:14 +02:00
}
2008-11-13 01:20:12 +01:00
}
2007-09-15 19:35:32 +02:00
2014-05-17 16:47:14 +02:00
if ( ! empty ( $_terms ) ) {
2013-08-29 17:19:10 +02:00
$terms = $_terms ;
2014-05-17 16:47:14 +02:00
}
2013-08-29 17:19:10 +02:00
2014-05-17 16:47:14 +02:00
if ( $number && is_array ( $terms ) && count ( $terms ) > $number ) {
2013-03-04 03:52:43 +01:00
$terms = array_slice ( $terms , $offset , $number );
2014-05-17 16:47:14 +02:00
}
2009-01-22 23:59:29 +01:00
2012-09-25 07:26:19 +02:00
wp_cache_add ( $cache_key , $terms , 'terms' , DAY_IN_SECONDS );
2007-09-15 19:35:32 +02:00
2014-03-28 22:29:13 +01:00
/** This filter is documented in wp-includes/taxonomy */
2013-08-29 17:19:10 +02:00
$terms = apply_filters ( 'get_terms' , $terms , $taxonomies , $args );
2007-09-15 19:35:32 +02:00
return $terms ;
}
/**
2008-06-22 22:23:23 +02:00
* Check if Term exists .
2007-09-15 19:35:32 +02:00
*
2010-06-11 17:53:41 +02:00
* Formerly is_term (), introduced in 2.3 . 0.
*
* @ since 3.0 . 0
2007-10-21 19:18:24 +02:00
*
2014-10-31 18:56:22 +01:00
* @ global wpdb $wpdb WordPress database abstraction object .
2007-10-16 00:49:31 +02:00
*
2007-09-15 19:35:32 +02:00
* @ param int | string $term The term to check
* @ param string $taxonomy The taxonomy name to use
2014-10-09 04:49:18 +02:00
* @ param int $parent Optional . ID of parent term under which to confine the exists search .
2014-10-09 05:16:18 +02:00
* @ return mixed Returns null if the term does not exist . Returns the term ID
* if no taxonomy is specified and the term ID exists . Returns
* an array of the term ID and the term taxonomy ID the taxonomy
* is specified and the pairing exists .
2007-09-15 19:35:32 +02:00
*/
2014-10-09 04:49:18 +02:00
function term_exists ( $term , $taxonomy = '' , $parent = null ) {
2007-09-15 19:35:32 +02:00
global $wpdb ;
2008-07-24 21:28:40 +02:00
$select = " SELECT term_id FROM $wpdb->terms as t WHERE " ;
$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 " ;
2007-09-15 19:35:32 +02:00
if ( is_int ( $term ) ) {
if ( 0 == $term )
return 0 ;
2008-07-17 18:59:40 +02:00
$where = 't.term_id = %d' ;
2008-07-24 21:28:40 +02:00
if ( ! empty ( $taxonomy ) )
return $wpdb -> get_row ( $wpdb -> prepare ( $tax_select . $where . " AND tt.taxonomy = %s " , $term , $taxonomy ), ARRAY_A );
else
return $wpdb -> get_var ( $wpdb -> prepare ( $select . $where , $term ) );
}
2013-03-03 22:11:40 +01:00
$term = trim ( wp_unslash ( $term ) );
2014-10-09 05:16:18 +02:00
$slug = sanitize_title ( $term );
2008-07-24 21:28:40 +02:00
$where = 't.slug = %s' ;
$else_where = 't.name = %s' ;
2009-04-10 22:58:25 +02:00
$where_fields = array ( $slug );
$else_where_fields = array ( $term );
2014-11-05 02:09:21 +01:00
$orderby = 'ORDER BY t.term_id ASC' ;
$limit = 'LIMIT 1' ;
2008-07-24 21:28:40 +02:00
if ( ! empty ( $taxonomy ) ) {
2014-10-09 04:49:18 +02:00
if ( is_numeric ( $parent ) ) {
$parent = ( int ) $parent ;
2009-04-10 22:58:25 +02:00
$where_fields [] = $parent ;
$else_where_fields [] = $parent ;
$where .= ' AND tt.parent = %d' ;
$else_where .= ' AND tt.parent = %d' ;
}
$where_fields [] = $taxonomy ;
$else_where_fields [] = $taxonomy ;
2014-11-05 02:09:21 +01:00
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 $orderby $limit " , $where_fields ), ARRAY_A ) )
2008-07-24 21:28:40 +02:00
return $result ;
2008-08-09 07:36:14 +02:00
2014-11-05 02:09:21 +01:00
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 $orderby $limit " , $else_where_fields ), ARRAY_A );
2007-09-15 19:35:32 +02:00
}
2014-11-05 02:09:21 +01:00
if ( $result = $wpdb -> get_var ( $wpdb -> prepare ( " SELECT term_id FROM $wpdb->terms as t WHERE $where $orderby $limit " , $where_fields ) ) )
2008-07-24 21:28:40 +02:00
return $result ;
2007-09-15 19:35:32 +02:00
2014-11-05 02:09:21 +01:00
return $wpdb -> get_var ( $wpdb -> prepare ( " SELECT term_id FROM $wpdb->terms as t WHERE $else_where $orderby $limit " , $else_where_fields ) );
2007-09-15 19:35:32 +02:00
}
2012-01-04 23:44:19 +01:00
/**
* Check if a term is an ancestor of another term .
*
* You can use either an id or the term object for both parameters .
*
* @ since 3.4 . 0
*
2015-05-07 22:37:41 +02:00
* @ param int | object $term1 ID or object to check if this is the parent term .
* @ param int | object $term2 The child term .
* @ param string $taxonomy Taxonomy name that $term1 and `$term2` belong to .
* @ return bool Whether `$term2` is a child of `$term1` .
2012-01-04 23:44:19 +01:00
*/
function term_is_ancestor_of ( $term1 , $term2 , $taxonomy ) {
if ( ! isset ( $term1 -> term_id ) )
$term1 = get_term ( $term1 , $taxonomy );
if ( ! isset ( $term2 -> parent ) )
$term2 = get_term ( $term2 , $taxonomy );
if ( empty ( $term1 -> term_id ) || empty ( $term2 -> parent ) )
return false ;
if ( $term2 -> parent == $term1 -> term_id )
return true ;
return term_is_ancestor_of ( $term1 , get_term ( $term2 -> parent , $taxonomy ), $taxonomy );
}
2007-09-15 19:35:32 +02:00
/**
2008-06-22 22:23:23 +02:00
* Sanitize Term all fields .
2007-09-15 19:35:32 +02:00
*
2011-09-05 21:08:15 +02:00
* Relies on sanitize_term_field () to sanitize the term . The difference is that
2008-06-22 22:23:23 +02:00
* this function will sanitize < strong > all </ strong > fields . The context is based
* on sanitize_term_field () .
2007-09-15 19:35:32 +02:00
*
* The $term is expected to be either an array or an object .
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2007-10-21 19:18:24 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param array | object $term The term to check .
* @ param string $taxonomy The taxonomy name to use .
* @ param string $context Optional . Context in which to sanitize the term . Accepts 'edit' , 'db' ,
* 'display' , 'attribute' , or 'js' . Default 'display' .
* @ return array | object Term with all fields sanitized .
2007-09-15 19:35:32 +02:00
*/
function sanitize_term ( $term , $taxonomy , $context = 'display' ) {
2007-11-07 07:20:08 +01:00
2013-11-05 02:19:11 +01:00
$fields = array ( 'term_id' , 'name' , 'description' , 'slug' , 'count' , 'parent' , 'term_group' , 'term_taxonomy_id' , 'object_id' );
2007-09-15 19:35:32 +02:00
2013-11-05 02:19:11 +01:00
$do_object = is_object ( $term );
2007-09-15 19:35:32 +02:00
2008-11-10 19:54:18 +01:00
$term_id = $do_object ? $term -> term_id : ( isset ( $term [ 'term_id' ]) ? $term [ 'term_id' ] : 0 );
2008-08-06 22:31:54 +02:00
foreach ( ( array ) $fields as $field ) {
2008-11-10 19:54:18 +01:00
if ( $do_object ) {
if ( isset ( $term -> $field ) )
$term -> $field = sanitize_term_field ( $field , $term -> $field , $term_id , $taxonomy , $context );
} else {
if ( isset ( $term [ $field ]) )
$term [ $field ] = sanitize_term_field ( $field , $term [ $field ], $term_id , $taxonomy , $context );
}
2007-09-15 19:35:32 +02:00
}
2008-11-17 21:03:31 +01:00
if ( $do_object )
$term -> filter = $context ;
else
$term [ 'filter' ] = $context ;
2007-09-15 19:35:32 +02:00
return $term ;
}
/**
2008-06-22 22:23:23 +02:00
* Cleanse the field value in the term based on the context .
2007-12-14 01:25:39 +01:00
*
2008-06-22 22:23:23 +02:00
* Passing a term field value through the function should be assumed to have
* cleansed the value for whatever context the term field is going to be used .
2007-12-14 01:25:39 +01:00
*
2008-06-22 22:23:23 +02:00
* If no context or an unsupported context is given , then default filters will
* be applied .
2007-09-15 19:35:32 +02:00
*
2008-06-22 22:23:23 +02:00
* There are enough filters for each context to support a custom filtering
* without creating your own filter function . Simply create a function that
* hooks into the filter you need .
2007-09-15 19:35:32 +02:00
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2007-10-21 19:18:24 +02:00
*
2014-10-31 18:56:22 +01:00
* @ global wpdb $wpdb WordPress database abstraction object .
2007-10-16 00:49:31 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param string $field Term field to sanitize .
* @ param string $value Search for this term value .
* @ param int $term_id Term ID .
* @ param string $taxonomy Taxonomy Name .
* @ param string $context Context in which to sanitize the term field . Accepts 'edit' , 'db' , 'display' ,
* 'attribute' , or 'js' .
* @ return mixed Sanitized field .
2007-09-15 19:35:32 +02:00
*/
function sanitize_term_field ( $field , $value , $term_id , $taxonomy , $context ) {
2013-11-05 02:19:11 +01:00
$int_fields = array ( 'parent' , 'term_id' , 'count' , 'term_group' , 'term_taxonomy_id' , 'object_id' );
2013-11-07 00:41:09 +01:00
if ( in_array ( $field , $int_fields ) ) {
$value = ( int ) $value ;
if ( $value < 0 )
$value = 0 ;
}
2007-09-15 19:35:32 +02:00
2007-11-03 20:06:43 +01:00
if ( 'raw' == $context )
return $value ;
2007-09-15 19:35:32 +02:00
if ( 'edit' == $context ) {
2014-03-28 22:29:13 +01:00
/**
* Filter a term field to edit before it is sanitized .
*
2014-11-30 13:00:23 +01:00
* The dynamic portion of the filter name , `$field` , refers to the term field .
2014-03-28 22:29:13 +01:00
*
* @ since 2.3 . 0
*
* @ param mixed $value Value of the term field .
* @ param int $term_id Term ID .
* @ param string $taxonomy Taxonomy slug .
*/
$value = apply_filters ( " edit_term_ { $field } " , $value , $term_id , $taxonomy );
/**
* Filter the taxonomy field to edit before it is sanitized .
*
2014-11-30 13:00:23 +01:00
* The dynamic portions of the filter name , `$taxonomy` and `$field` , refer
2014-03-28 22:29:13 +01:00
* to the taxonomy slug and taxonomy field , respectively .
*
* @ since 2.3 . 0
*
* @ param mixed $value Value of the taxonomy field to edit .
* @ param int $term_id Term ID .
*/
$value = apply_filters ( " edit_ { $taxonomy } _ { $field } " , $value , $term_id );
2015-05-07 22:37:41 +02:00
2007-09-15 19:35:32 +02:00
if ( 'description' == $field )
2010-12-25 23:45:09 +01:00
$value = esc_html ( $value ); // textarea_escaped
2007-09-15 19:35:32 +02:00
else
2009-05-05 21:43:53 +02:00
$value = esc_attr ( $value );
2015-01-08 07:26:23 +01:00
} elseif ( 'db' == $context ) {
2014-03-28 22:29:13 +01:00
/**
* Filter a term field value before it is sanitized .
*
2014-11-30 13:00:23 +01:00
* The dynamic portion of the filter name , `$field` , refers to the term field .
2014-03-28 22:29:13 +01:00
*
* @ since 2.3 . 0
*
* @ param mixed $value Value of the term field .
* @ param string $taxonomy Taxonomy slug .
*/
$value = apply_filters ( " pre_term_ { $field } " , $value , $taxonomy );
/**
* Filter a taxonomy field before it is sanitized .
*
2014-11-30 13:00:23 +01:00
* The dynamic portions of the filter name , `$taxonomy` and `$field` , refer
2014-03-28 22:29:13 +01:00
* to the taxonomy slug and field name , respectively .
*
* @ since 2.3 . 0
*
* @ param mixed $value Value of the taxonomy field .
*/
$value = apply_filters ( " pre_ { $taxonomy } _ { $field } " , $value );
2015-05-07 22:37:41 +02:00
2007-09-22 20:01:08 +02:00
// Back compat filters
2014-03-28 22:29:13 +01:00
if ( 'slug' == $field ) {
/**
* Filter the category nicename before it is sanitized .
*
* Use the pre_ { $taxonomy } _ { $field } hook instead .
*
* @ since 2.0 . 3
*
* @ param string $value The category nicename .
*/
$value = apply_filters ( 'pre_category_nicename' , $value );
}
2008-02-05 07:47:27 +01:00
2015-01-08 07:26:23 +01:00
} elseif ( 'rss' == $context ) {
2014-03-28 22:29:13 +01:00
/**
* Filter the term field for use in RSS .
*
2014-11-30 13:00:23 +01:00
* The dynamic portion of the filter name , `$field` , refers to the term field .
2014-03-28 22:29:13 +01:00
*
* @ since 2.3 . 0
*
* @ param mixed $value Value of the term field .
* @ param string $taxonomy Taxonomy slug .
*/
$value = apply_filters ( " term_ { $field } _rss " , $value , $taxonomy );
/**
* Filter the taxonomy field for use in RSS .
*
2015-05-07 22:37:41 +02:00
* The dynamic portions of the hook name , `$taxonomy` , and `$field` , refer
2014-03-28 22:29:13 +01:00
* to the taxonomy slug and field name , respectively .
*
* @ since 2.3 . 0
*
* @ param mixed $value Value of the taxonomy field .
*/
$value = apply_filters ( " { $taxonomy } _ { $field } _rss " , $value );
2007-09-15 19:35:32 +02:00
} else {
// Use display filters by default.
2014-03-28 22:29:13 +01:00
/**
* Filter the term field sanitized for display .
*
2014-11-30 13:00:23 +01:00
* The dynamic portion of the filter name , `$field` , refers to the term field name .
2014-03-28 22:29:13 +01:00
*
* @ since 2.3 . 0
*
* @ param mixed $value Value of the term field .
* @ param int $term_id Term ID .
* @ param string $taxonomy Taxonomy slug .
* @ param string $context Context to retrieve the term field value .
*/
$value = apply_filters ( " term_ { $field } " , $value , $term_id , $taxonomy , $context );
/**
* Filter the taxonomy field sanitized for display .
*
2015-05-07 22:37:41 +02:00
* The dynamic portions of the filter name , `$taxonomy` , and `$field` , refer
2014-03-28 22:29:13 +01:00
* to the taxonomy slug and taxonomy field , respectively .
*
* @ since 2.3 . 0
*
* @ param mixed $value Value of the taxonomy field .
* @ param int $term_id Term ID .
* @ param string $context Context to retrieve the taxonomy field value .
*/
$value = apply_filters ( " { $taxonomy } _ { $field } " , $value , $term_id , $context );
2007-09-15 19:35:32 +02:00
}
2015-01-08 07:26:23 +01:00
if ( 'attribute' == $context ) {
2009-05-05 21:43:53 +02:00
$value = esc_attr ( $value );
2015-01-08 07:26:23 +01:00
} elseif ( 'js' == $context ) {
2009-05-09 09:27:22 +02:00
$value = esc_js ( $value );
2015-01-08 07:26:23 +01:00
}
2007-09-15 19:35:32 +02:00
return $value ;
}
/**
2008-06-22 22:23:23 +02:00
* Count how many terms are in Taxonomy .
2007-09-15 19:35:32 +02:00
*
2010-02-28 08:37:24 +01:00
* Default $args is 'hide_empty' which can be 'hide_empty=true' or array ( 'hide_empty' => true ) .
2007-09-15 19:35:32 +02:00
*
2015-05-07 22:37:41 +02:00
* @ todo Document $args as a hash notation .
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2007-10-21 19:18:24 +02:00
*
2007-09-15 19:35:32 +02:00
* @ param string $taxonomy Taxonomy name
2010-02-28 08:37:24 +01:00
* @ param array | string $args Overwrite defaults . See get_terms ()
2012-09-14 18:11:30 +02:00
* @ return int | WP_Error How many terms are in $taxonomy . WP_Error if $taxonomy does not exist .
2007-09-15 19:35:32 +02:00
*/
function wp_count_terms ( $taxonomy , $args = array () ) {
2010-02-28 08:37:24 +01:00
$defaults = array ( 'hide_empty' => false );
2007-09-15 19:35:32 +02:00
$args = wp_parse_args ( $args , $defaults );
2010-02-28 08:37:24 +01:00
// backwards compatibility
if ( isset ( $args [ 'ignore_empty' ]) ) {
$args [ 'hide_empty' ] = $args [ 'ignore_empty' ];
unset ( $args [ 'ignore_empty' ]);
}
$args [ 'fields' ] = 'count' ;
2007-09-15 19:35:32 +02:00
2010-02-28 08:37:24 +01:00
return get_terms ( $taxonomy , $args );
2007-09-15 19:35:32 +02:00
}
/**
2010-11-18 19:46:41 +01:00
* Will unlink the object from the taxonomy or taxonomies .
2007-09-15 19:35:32 +02:00
*
2010-12-13 22:21:50 +01:00
* Will remove all relationships between the object and any terms in
* a particular taxonomy or taxonomies . Does not remove the term or
2010-11-18 19:46:41 +01:00
* taxonomy itself .
2007-09-15 19:35:32 +02:00
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2007-10-16 00:49:31 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param int $object_id The term Object Id that refers to the term .
2010-09-07 13:21:11 +02:00
* @ param string | array $taxonomies List of Taxonomy Names or single Taxonomy name .
2007-09-15 19:35:32 +02:00
*/
function wp_delete_object_term_relationships ( $object_id , $taxonomies ) {
$object_id = ( int ) $object_id ;
if ( ! is_array ( $taxonomies ) )
$taxonomies = array ( $taxonomies );
2008-08-06 22:31:54 +02:00
foreach ( ( array ) $taxonomies as $taxonomy ) {
2013-02-08 19:45:34 +01:00
$term_ids = wp_get_object_terms ( $object_id , $taxonomy , array ( 'fields' => 'ids' ) );
$term_ids = array_map ( 'intval' , $term_ids );
wp_remove_object_terms ( $object_id , $term_ids , $taxonomy );
2007-09-15 19:35:32 +02:00
}
}
/**
2008-06-22 22:23:23 +02:00
* Removes a term from the database .
2007-10-16 00:49:31 +02:00
*
2008-06-22 22:23:23 +02:00
* If the term is a parent of other terms , then the children will be updated to
* that term ' s parent .
2007-12-14 01:25:39 +01:00
*
2015-05-07 22:37:41 +02:00
* The `$args` 'default' will only override the terms found , if there is only one
2007-12-14 01:25:39 +01:00
* term found . Any other and the found terms are used .
2009-04-20 20:18:39 +02:00
*
2009-03-18 22:06:49 +01:00
* The $args 'force_default' will force the term supplied as default to be
* assigned even if the object was not going to be termless
2014-02-25 18:14:14 +01:00
*
2015-05-07 22:37:41 +02:00
* @ todo Document $args as a hash notation .
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2007-12-14 01:25:39 +01:00
*
2014-10-31 18:56:22 +01:00
* @ global wpdb $wpdb WordPress database abstraction object .
2007-10-16 00:49:31 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param int $term Term ID .
* @ param string $taxonomy Taxonomy Name .
* @ param array | string $args Optional . Change 'default' term id and override found term ids .
2007-12-14 01:25:39 +01:00
* @ return bool | WP_Error Returns false if not term ; true if completes delete action .
2007-09-15 19:35:32 +02:00
*/
function wp_delete_term ( $term , $taxonomy , $args = array () ) {
global $wpdb ;
$term = ( int ) $term ;
2010-06-11 17:53:41 +02:00
if ( ! $ids = term_exists ( $term , $taxonomy ) )
2007-09-15 19:35:32 +02:00
return false ;
2007-10-28 22:33:03 +01:00
if ( is_wp_error ( $ids ) )
return $ids ;
2007-09-15 19:35:32 +02:00
$tt_id = $ids [ 'term_taxonomy_id' ];
$defaults = array ();
2010-10-19 09:48:22 +02:00
2010-10-03 09:29:44 +02:00
if ( 'category' == $taxonomy ) {
$defaults [ 'default' ] = get_option ( 'default_category' );
if ( $defaults [ 'default' ] == $term )
return 0 ; // Don't delete the default category
}
2010-10-19 09:48:22 +02:00
2007-09-15 19:35:32 +02:00
$args = wp_parse_args ( $args , $defaults );
2014-05-17 16:55:14 +02:00
if ( isset ( $args [ 'default' ] ) ) {
$default = ( int ) $args [ 'default' ];
if ( ! term_exists ( $default , $taxonomy ) ) {
unset ( $default );
}
}
if ( isset ( $args [ 'force_default' ] ) ) {
$force_default = $args [ 'force_default' ];
2007-09-15 19:35:32 +02:00
}
2014-10-29 03:44:22 +01:00
/**
* Fires when deleting a term , before any modifications are made to posts or terms .
*
* @ since 4.1 . 0
*
2014-11-28 13:26:24 +01:00
* @ param int $term Term ID .
* @ param string $taxonomy Taxonomy Name .
2014-10-29 03:44:22 +01:00
*/
do_action ( 'pre_delete_term' , $term , $taxonomy );
2007-09-15 19:35:32 +02:00
// Update children to point to new parent
if ( is_taxonomy_hierarchical ( $taxonomy ) ) {
$term_obj = get_term ( $term , $taxonomy );
2007-09-18 18:32:22 +02:00
if ( is_wp_error ( $term_obj ) )
return $term_obj ;
2007-09-15 19:35:32 +02:00
$parent = $term_obj -> parent ;
2014-10-17 22:59:20 +02:00
$edit_ids = $wpdb -> get_results ( " SELECT term_id, term_taxonomy_id FROM $wpdb->term_taxonomy WHERE `parent` = " . ( int ) $term_obj -> term_id );
$edit_tt_ids = wp_list_pluck ( $edit_ids , 'term_taxonomy_id' );
2014-03-28 22:29:13 +01:00
/**
* Fires immediately before a term to delete ' s children are reassigned a parent .
*
* @ since 2.9 . 0
*
* @ param array $edit_tt_ids An array of term taxonomy IDs for the given term .
*/
2009-09-17 16:03:57 +02:00
do_action ( 'edit_term_taxonomies' , $edit_tt_ids );
2015-05-07 22:37:41 +02:00
2007-10-25 09:15:02 +02:00
$wpdb -> update ( $wpdb -> term_taxonomy , compact ( 'parent' ), array ( 'parent' => $term_obj -> term_id ) + compact ( 'taxonomy' ) );
2014-03-28 22:29:13 +01:00
2014-10-17 22:59:20 +02:00
// Clean the cache for all child terms.
$edit_term_ids = wp_list_pluck ( $edit_ids , 'term_id' );
clean_term_cache ( $edit_term_ids , $taxonomy );
2014-03-28 22:29:13 +01:00
/**
* Fires immediately after a term to delete ' s children are reassigned a parent .
*
* @ since 2.9 . 0
*
* @ param array $edit_tt_ids An array of term taxonomy IDs for the given term .
*/
2009-09-17 16:03:57 +02:00
do_action ( 'edited_term_taxonomies' , $edit_tt_ids );
2007-09-15 19:35:32 +02:00
}
2007-10-13 05:51:11 +02:00
$objects = $wpdb -> get_col ( $wpdb -> prepare ( " SELECT object_id FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d " , $tt_id ) );
2007-09-15 19:35:32 +02:00
foreach ( ( array ) $objects as $object ) {
2009-05-25 20:18:06 +02:00
$terms = wp_get_object_terms ( $object , $taxonomy , array ( 'fields' => 'ids' , 'orderby' => 'none' ));
2009-03-18 22:06:49 +01:00
if ( 1 == count ( $terms ) && isset ( $default ) ) {
2007-09-15 19:35:32 +02:00
$terms = array ( $default );
2009-03-18 22:06:49 +01:00
} else {
2007-09-15 19:35:32 +02:00
$terms = array_diff ( $terms , array ( $term ));
2009-03-18 22:06:49 +01:00
if ( isset ( $default ) && isset ( $force_default ) && $force_default )
$terms = array_merge ( $terms , array ( $default ));
}
2007-09-15 19:35:32 +02:00
$terms = array_map ( 'intval' , $terms );
wp_set_object_terms ( $object , $terms , $taxonomy );
}
2015-05-07 22:37:41 +02:00
// Clean the relationship caches for all object types using this term.
2010-12-02 18:10:02 +01:00
$tax_object = get_taxonomy ( $taxonomy );
foreach ( $tax_object -> object_type as $object_type )
2010-12-13 22:21:50 +01:00
clean_object_term_cache ( $objects , $object_type );
2012-09-21 15:27:56 +02:00
// Get the object before deletion so we can pass to actions below
$deleted_term = get_term ( $term , $taxonomy );
2014-03-28 22:29:13 +01:00
/**
* Fires immediately before a term taxonomy ID is deleted .
*
* @ since 2.9 . 0
*
* @ param int $tt_id Term taxonomy ID .
*/
2009-09-17 16:03:57 +02:00
do_action ( 'delete_term_taxonomy' , $tt_id );
2012-03-24 16:24:31 +01:00
$wpdb -> delete ( $wpdb -> term_taxonomy , array ( 'term_taxonomy_id' => $tt_id ) );
2014-03-28 22:29:13 +01:00
/**
* Fires immediately after a term taxonomy ID is deleted .
*
* @ since 2.9 . 0
*
* @ param int $tt_id Term taxonomy ID .
*/
2009-09-17 16:03:57 +02:00
do_action ( 'deleted_term_taxonomy' , $tt_id );
2007-09-15 19:35:32 +02:00
// Delete the term if no taxonomies use it.
2007-10-13 05:51:11 +02:00
if ( ! $wpdb -> get_var ( $wpdb -> prepare ( " SELECT COUNT(*) FROM $wpdb->term_taxonomy WHERE term_id = %d " , $term ) ) )
2012-03-24 16:24:31 +01:00
$wpdb -> delete ( $wpdb -> terms , array ( 'term_id' => $term ) );
2007-09-15 19:35:32 +02:00
clean_term_cache ( $term , $taxonomy );
2014-03-28 22:29:13 +01:00
/**
* Fires after a term is deleted from the database and the cache is cleaned .
*
* @ since 2.5 . 0
*
* @ param int $term Term ID .
* @ param int $tt_id Term taxonomy ID .
* @ param string $taxonomy Taxonomy slug .
* @ param mixed $deleted_term Copy of the already - deleted term , in the form specified
* by the parent function . WP_Error otherwise .
*/
2012-09-21 15:27:56 +02:00
do_action ( 'delete_term' , $term , $tt_id , $taxonomy , $deleted_term );
2014-03-28 22:29:13 +01:00
/**
* Fires after a term in a specific taxonomy is deleted .
*
2014-11-30 13:00:23 +01:00
* The dynamic portion of the hook name , `$taxonomy` , refers to the specific
2014-03-28 22:29:13 +01:00
* taxonomy the term belonged to .
*
* @ since 2.3 . 0
*
* @ param int $term Term ID .
* @ param int $tt_id Term taxonomy ID .
* @ param mixed $deleted_term Copy of the already - deleted term , in the form specified
2015-05-07 22:37:41 +02:00
* by the parent function . WP_Error otherwise .
2014-03-28 22:29:13 +01:00
*/
2012-09-21 15:27:56 +02:00
do_action ( " delete_ $taxonomy " , $term , $tt_id , $deleted_term );
2007-09-15 19:35:32 +02:00
return true ;
}
2010-12-16 23:46:13 +01:00
/**
2010-10-04 18:28:01 +02:00
* Deletes one existing category .
*
* @ since 2.0 . 0
*
* @ param int $cat_ID
2011-09-05 21:08:15 +02:00
* @ return mixed Returns true if completes delete action ; false if term doesn ' t exist ;
2010-10-04 18:28:01 +02:00
* Zero on attempted deletion of default Category ; WP_Error object is also a possibility .
*/
function wp_delete_category ( $cat_ID ) {
return wp_delete_term ( $cat_ID , 'category' );
}
2007-09-15 19:35:32 +02:00
/**
2008-06-22 22:23:23 +02:00
* Retrieves the terms associated with the given object ( s ), in the supplied taxonomies .
2015-01-17 21:39:23 +01:00
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2015-01-18 20:05:22 +01:00
* @ since 4.2 . 0 Added support for 'taxonomy' , 'parent' , and 'term_taxonomy_id' values of `$orderby` .
2015-04-05 19:08:26 +02:00
* Introduced `$parent` argument .
2014-10-31 18:56:22 +01:00
*
* @ global wpdb $wpdb WordPress database abstraction object .
2007-10-16 00:49:31 +02:00
*
2015-01-17 21:09:47 +01:00
* @ param int | array $object_ids The ID ( s ) of the object ( s ) to retrieve .
2007-09-15 19:35:32 +02:00
* @ param string | array $taxonomies The taxonomies to retrieve terms from .
2015-01-17 21:09:47 +01:00
* @ param array | string $args {
* Array of arguments .
2015-01-17 21:39:23 +01:00
* @ type string $orderby Field by which results should be sorted . Accepts 'name' , 'count' , 'slug' , 'term_group' ,
2015-01-18 19:57:23 +01:00
* 'term_order' , 'taxonomy' , 'parent' , or 'term_taxonomy_id' . Default 'name' .
2015-01-17 21:09:47 +01:00
* @ type string $order Sort order . Accepts 'ASC' or 'DESC' . Default 'ASC' .
* @ type string $fields Fields to return for matched terms . Accepts 'all' , 'ids' , 'names' , and
* 'all_with_object_id' . Note that 'all' or 'all_with_object_id' will result in an array of
* term objects being returned , 'ids' will return an array of integers , and 'names' an array
* of strings .
2015-01-23 15:57:22 +01:00
* @ type int $parent Optional . Limit results to the direct children of a given term ID .
2015-01-17 21:09:47 +01:00
* }
* @ 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 .
2007-09-15 19:35:32 +02:00
*/
function wp_get_object_terms ( $object_ids , $taxonomies , $args = array ()) {
global $wpdb ;
2012-02-21 21:20:50 +01:00
if ( empty ( $object_ids ) || empty ( $taxonomies ) )
return array ();
2007-09-15 19:35:32 +02:00
if ( ! is_array ( $taxonomies ) )
$taxonomies = array ( $taxonomies );
2014-02-17 22:56:12 +01:00
foreach ( $taxonomies as $taxonomy ) {
2010-06-11 17:53:41 +02:00
if ( ! taxonomy_exists ( $taxonomy ) )
2012-06-01 21:05:30 +02:00
return new WP_Error ( 'invalid_taxonomy' , __ ( 'Invalid taxonomy' ));
2007-09-15 19:35:32 +02:00
}
if ( ! is_array ( $object_ids ) )
$object_ids = array ( $object_ids );
$object_ids = array_map ( 'intval' , $object_ids );
2015-01-23 15:57:22 +01:00
$defaults = array (
'orderby' => 'name' ,
'order' => 'ASC' ,
'fields' => 'all' ,
'parent' => '' ,
);
2007-09-15 19:35:32 +02:00
$args = wp_parse_args ( $args , $defaults );
2008-03-26 07:37:19 +01:00
$terms = array ();
if ( count ( $taxonomies ) > 1 ) {
foreach ( $taxonomies as $index => $taxonomy ) {
$t = get_taxonomy ( $taxonomy );
2008-05-19 20:47:33 +02:00
if ( isset ( $t -> args ) && is_array ( $t -> args ) && $args != array_merge ( $args , $t -> args ) ) {
2008-03-26 07:37:19 +01:00
unset ( $taxonomies [ $index ]);
$terms = array_merge ( $terms , wp_get_object_terms ( $object_ids , $taxonomy , array_merge ( $args , $t -> args )));
}
}
} else {
$t = get_taxonomy ( $taxonomies [ 0 ]);
2008-05-19 20:47:33 +02:00
if ( isset ( $t -> args ) && is_array ( $t -> args ) )
2008-03-26 07:37:19 +01:00
$args = array_merge ( $args , $t -> args );
}
2014-05-15 21:58:15 +02:00
$orderby = $args [ 'orderby' ];
$order = $args [ 'order' ];
$fields = $args [ 'fields' ];
2007-09-15 19:35:32 +02:00
2015-01-18 19:57:23 +01:00
if ( in_array ( $orderby , array ( 'term_id' , 'name' , 'slug' , 'term_group' ) ) ) {
$orderby = " t. $orderby " ;
} else if ( in_array ( $orderby , array ( 'count' , 'parent' , 'taxonomy' , 'term_taxonomy_id' ) ) ) {
$orderby = " tt. $orderby " ;
} else if ( 'term_order' === $orderby ) {
2008-02-14 18:17:57 +01:00
$orderby = 'tr.term_order' ;
2015-01-18 19:57:23 +01:00
} else if ( 'none' === $orderby ) {
2009-05-25 20:18:06 +02:00
$orderby = '' ;
$order = '' ;
} else {
2009-05-27 19:09:19 +02:00
$orderby = 't.term_id' ;
2009-05-25 20:18:06 +02:00
}
2009-05-27 19:09:19 +02:00
// tt_ids queries can only be none or tr.term_taxonomy_id
if ( ( 'tt_ids' == $fields ) && ! empty ( $orderby ) )
$orderby = 'tr.term_taxonomy_id' ;
2009-05-25 20:18:06 +02:00
if ( ! empty ( $orderby ) )
$orderby = " ORDER BY $orderby " ;
2007-09-15 19:35:32 +02:00
2012-09-05 03:23:53 +02:00
$order = strtoupper ( $order );
if ( '' !== $order && ! in_array ( $order , array ( 'ASC' , 'DESC' ) ) )
$order = 'ASC' ;
2015-02-27 21:31:26 +01:00
$taxonomy_array = $taxonomies ;
2015-03-06 14:18:26 +01:00
$object_id_array = $object_ids ;
2007-09-15 19:35:32 +02:00
$taxonomies = " ' " . implode ( " ', ' " , $taxonomies ) . " ' " ;
$object_ids = implode ( ', ' , $object_ids );
2008-02-22 18:43:56 +01:00
$select_this = '' ;
2015-01-08 07:26:23 +01:00
if ( 'all' == $fields ) {
2007-09-15 19:35:32 +02:00
$select_this = 't.*, tt.*' ;
2015-01-08 07:26:23 +01:00
} elseif ( 'ids' == $fields ) {
2007-09-15 19:35:32 +02:00
$select_this = 't.term_id' ;
2015-01-08 07:26:23 +01:00
} elseif ( 'names' == $fields ) {
2007-09-16 04:36:23 +02:00
$select_this = 't.name' ;
2015-01-08 07:26:23 +01:00
} elseif ( 'slugs' == $fields ) {
2011-08-25 20:49:46 +02:00
$select_this = 't.slug' ;
2015-01-08 07:26:23 +01:00
} elseif ( 'all_with_object_id' == $fields ) {
2007-09-15 19:35:32 +02:00
$select_this = 't.*, tt.*, tr.object_id' ;
2015-01-08 07:26:23 +01:00
}
2015-01-23 15:57:22 +01:00
$where = array (
" tt.taxonomy IN ( $taxonomies ) " ,
" tr.object_id IN ( $object_ids ) " ,
);
if ( '' !== $args [ 'parent' ] ) {
$where [] = $wpdb -> prepare ( 'tt.parent = %d' , $args [ 'parent' ] );
}
$where = implode ( ' AND ' , $where );
$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 $where $orderby $order " ;
2007-09-15 19:35:32 +02:00
2014-07-12 05:54:15 +02:00
$objects = false ;
2007-09-15 19:35:32 +02:00
if ( 'all' == $fields || 'all_with_object_id' == $fields ) {
2013-11-05 02:19:11 +01:00
$_terms = $wpdb -> get_results ( $query );
2013-12-02 01:00:10 +01:00
foreach ( $_terms as $key => $term ) {
$_terms [ $key ] = sanitize_term ( $term , $taxonomy , 'raw' );
}
2013-11-05 02:19:11 +01:00
$terms = array_merge ( $terms , $_terms );
update_term_cache ( $terms );
2014-07-12 05:54:15 +02:00
$objects = true ;
2015-01-08 07:26:23 +01:00
} elseif ( 'ids' == $fields || 'names' == $fields || 'slugs' == $fields ) {
2013-11-05 02:19:11 +01:00
$_terms = $wpdb -> get_col ( $query );
$_field = ( 'ids' == $fields ) ? 'term_id' : 'name' ;
2013-12-02 01:00:10 +01:00
foreach ( $_terms as $key => $term ) {
$_terms [ $key ] = sanitize_term_field ( $_field , $term , $term , $taxonomy , 'raw' );
}
2013-11-05 02:19:11 +01:00
$terms = array_merge ( $terms , $_terms );
2015-01-08 07:26:23 +01:00
} elseif ( 'tt_ids' == $fields ) {
2009-05-25 20:18:06 +02:00
$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 " );
2013-12-02 01:00:10 +01:00
foreach ( $terms as $key => $tt_id ) {
$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.
}
2007-09-15 19:35:32 +02:00
}
2014-05-27 05:29:14 +02:00
if ( ! $terms ) {
2009-05-10 11:25:43 +02:00
$terms = array ();
2014-07-12 05:54:15 +02:00
} elseif ( $objects && 'all_with_object_id' !== $fields ) {
$_tt_ids = array ();
$_terms = array ();
foreach ( $terms as $term ) {
if ( in_array ( $term -> term_taxonomy_id , $_tt_ids ) ) {
continue ;
}
$_tt_ids [] = $term -> term_taxonomy_id ;
$_terms [] = $term ;
}
$terms = $_terms ;
} elseif ( ! $objects ) {
$terms = array_values ( array_unique ( $terms ) );
2014-05-27 05:29:14 +02:00
}
2015-02-27 21:31:26 +01:00
/**
* Filter the terms for a given object or objects .
*
* @ since 4.2 . 0
*
2015-03-06 14:18:26 +01:00
* @ param array $terms An array of terms for the given object or objects .
* @ param array $object_id_array Array of object IDs for which `$terms` were retrieved .
* @ param array $taxonomy_array Array of taxonomies from which `$terms` were retrieved .
2015-04-05 19:08:26 +02:00
* @ param array $args An array of arguments for retrieving terms for the given
* object ( s ) . See wp_get_object_terms () for details .
2015-02-27 21:31:26 +01:00
*/
2015-03-06 14:18:26 +01:00
$terms = apply_filters ( 'get_object_terms' , $terms , $object_id_array , $taxonomy_array , $args );
2015-02-27 21:31:26 +01:00
2014-03-28 22:29:13 +01:00
/**
* Filter the terms for a given object or objects .
*
2015-02-27 21:31:26 +01:00
* The `$taxonomies` parameter passed to this filter is formatted as a SQL fragment . The
* { @ see 'get_object_terms' } filter is recommended as an alternative .
*
2014-03-28 22:29:13 +01:00
* @ since 2.8 . 0
*
2015-02-27 21:31:26 +01:00
* @ param array $terms An array of terms for the given object or objects .
* @ param int | array $object_ids Object ID or array of IDs .
* @ param string $taxonomies SQL - formatted ( comma - separated and quoted ) list of taxonomy names .
* @ param array $args An array of arguments for retrieving terms for the given object ( s ) .
* See { @ see wp_get_object_terms ()} for details .
2014-03-28 22:29:13 +01:00
*/
return apply_filters ( 'wp_get_object_terms' , $terms , $object_ids , $taxonomies , $args );
2007-09-15 19:35:32 +02:00
}
/**
2013-09-19 03:57:10 +02:00
* Add a new term to the database .
2007-09-15 19:35:32 +02:00
*
2013-09-19 03:57:10 +02:00
* A non - existent term is inserted in the following sequence :
* 1. The term is added to the term table , then related to the taxonomy .
* 2. If everything is correct , several actions are fired .
* 3. The 'term_id_filter' is evaluated .
* 4. The term cache is cleaned .
* 5. Several more actions are fired .
* 6. An array is returned containing the term_id and term_taxonomy_id .
2007-12-14 01:25:39 +01:00
*
2013-09-19 18:09:10 +02:00
* If the 'slug' argument is not empty , then it is checked to see if the term
* is invalid . If it is not a valid , existing term , it is added and the term_id
* is given .
*
* If the taxonomy is hierarchical , and the 'parent' argument is not empty ,
* the term is inserted and the term_id will be given .
2013-09-19 03:57:10 +02:00
* Error handling :
2013-09-19 18:09:10 +02:00
* If $taxonomy does not exist or $term is empty ,
2013-09-19 03:57:10 +02:00
* a WP_Error object will be returned .
2007-12-14 01:25:39 +01:00
*
2013-09-19 18:09:10 +02:00
* If the term already exists on the same hierarchical level ,
* or the term slug and name are not unique , a WP_Error object will be returned .
2007-09-15 19:35:32 +02:00
*
2014-10-31 18:56:22 +01:00
* @ global wpdb $wpdb WordPress database abstraction object .
2013-09-19 03:57:10 +02:00
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2007-10-16 00:49:31 +02:00
*
2013-09-19 03:57:10 +02:00
* @ param string $term The term to add or update .
2014-12-03 11:17:24 +01:00
* @ param string $taxonomy The taxonomy to which to add the term .
2013-09-19 03:57:10 +02:00
* @ param array | string $args {
2014-12-03 11:17:24 +01:00
* Optional . Array or string of arguments for inserting a term .
*
* @ type string $alias_of Slug of the term to make this term an alias of .
* Default empty string . Accepts a term slug .
* @ type string $description The term description . Default empty string .
* @ type int $parent The id of the parent term . Default 0.
* @ type string $slug The term slug to use . Default empty string .
2013-09-19 03:57:10 +02:00
* }
2014-12-03 11:17:24 +01:00
* @ return array | WP_Error An array containing the `term_id` and `term_taxonomy_id` ,
* { @ see WP_Error } otherwise .
2007-09-15 19:35:32 +02:00
*/
function wp_insert_term ( $term , $taxonomy , $args = array () ) {
global $wpdb ;
2014-05-17 16:16:14 +02:00
if ( ! taxonomy_exists ( $taxonomy ) ) {
2007-09-15 19:35:32 +02:00
return new WP_Error ( 'invalid_taxonomy' , __ ( 'Invalid taxonomy' ));
2014-05-17 16:16:14 +02:00
}
2014-03-28 22:29:13 +01:00
/**
* Filter a term before it is sanitized and inserted into the database .
*
* @ since 3.0 . 0
*
* @ param string $term The term to add or update .
* @ param string $taxonomy Taxonomy slug .
*/
2010-02-26 08:40:35 +01:00
$term = apply_filters ( 'pre_insert_term' , $term , $taxonomy );
2014-05-17 16:16:14 +02:00
if ( is_wp_error ( $term ) ) {
return $term ;
}
if ( is_int ( $term ) && 0 == $term ) {
2007-09-15 19:35:32 +02:00
return new WP_Error ( 'invalid_term_id' , __ ( 'Invalid term ID' ));
2014-05-17 16:16:14 +02:00
}
if ( '' == trim ( $term ) ) {
2008-07-21 23:53:32 +02:00
return new WP_Error ( 'empty_term_name' , __ ( 'A name is required for this term' ));
2014-05-17 16:16:14 +02:00
}
2007-09-15 19:35:32 +02:00
$defaults = array ( 'alias_of' => '' , 'description' => '' , 'parent' => 0 , 'slug' => '' );
2014-07-16 23:52:15 +02:00
$args = wp_parse_args ( $args , $defaults );
if ( $args [ 'parent' ] > 0 && ! term_exists ( ( int ) $args [ 'parent' ] ) ) {
2014-07-19 01:56:14 +02:00
return new WP_Error ( 'missing_parent' , __ ( 'Parent term does not exist.' ) );
2014-07-16 23:52:15 +02:00
}
2007-09-15 19:35:32 +02:00
$args [ 'name' ] = $term ;
2007-09-22 20:01:08 +02:00
$args [ 'taxonomy' ] = $taxonomy ;
2007-09-15 19:35:32 +02:00
$args = sanitize_term ( $args , $taxonomy , 'db' );
2013-03-01 17:28:40 +01:00
// expected_slashed ($name)
2014-05-17 16:16:14 +02:00
$name = wp_unslash ( $args [ 'name' ] );
$description = wp_unslash ( $args [ 'description' ] );
$parent = ( int ) $args [ 'parent' ];
2013-03-01 17:28:40 +01:00
2014-05-17 16:16:14 +02:00
$slug_provided = ! empty ( $args [ 'slug' ] );
2013-12-03 00:06:11 +01:00
if ( ! $slug_provided ) {
2015-03-11 23:55:28 +01:00
$slug = sanitize_title ( $name );
2014-05-17 16:16:14 +02:00
} else {
$slug = $args [ 'slug' ];
2013-12-03 00:06:11 +01:00
}
2007-09-15 19:35:32 +02:00
$term_group = 0 ;
2014-05-17 16:16:14 +02:00
if ( $args [ 'alias_of' ] ) {
2014-10-09 04:32:19 +02:00
$alias = get_term_by ( 'slug' , $args [ 'alias_of' ], $taxonomy );
if ( ! empty ( $alias -> term_group ) ) {
2007-09-15 19:35:32 +02:00
// The alias we want is already in a group, so let's use that one.
$term_group = $alias -> term_group ;
2015-01-08 07:26:23 +01:00
} elseif ( ! empty ( $alias -> term_id ) ) {
2014-10-09 04:32:19 +02:00
/*
* The alias is not in a group , so we create a new one
* and add the alias to it .
2014-03-28 22:29:13 +01:00
*/
2014-10-09 04:32:19 +02:00
$term_group = $wpdb -> get_var ( " SELECT MAX(term_group) FROM $wpdb->terms " ) + 1 ;
2014-03-28 22:29:13 +01:00
2014-10-09 04:32:19 +02:00
wp_update_term ( $alias -> term_id , $taxonomy , array (
'term_group' => $term_group ,
) );
2007-09-15 19:35:32 +02:00
}
}
2015-03-16 12:16:28 +01:00
/*
* Prevent the creation of terms with duplicate names at the same level of a taxonomy hierarchy ,
* unless a unique slug has been explicitly provided .
*/
if ( $name_match = get_term_by ( 'name' , $name , $taxonomy ) ) {
$slug_match = get_term_by ( 'slug' , $slug , $taxonomy );
if ( ! $slug_provided || $name_match -> slug === $slug || $slug_match ) {
if ( is_taxonomy_hierarchical ( $taxonomy ) ) {
$siblings = get_terms ( $taxonomy , array ( 'get' => 'all' , 'parent' => $parent ) );
$existing_term = null ;
if ( $name_match -> slug === $slug && in_array ( $name , wp_list_pluck ( $siblings , 'name' ) ) ) {
$existing_term = $name_match ;
} elseif ( $slug_match && in_array ( $slug , wp_list_pluck ( $siblings , 'slug' ) ) ) {
$existing_term = $slug_match ;
}
if ( $existing_term ) {
2015-04-26 13:50:26 +02:00
return new WP_Error ( 'term_exists' , __ ( 'A term with the name provided already exists with this parent.' ), $existing_term -> term_id );
2015-03-16 12:16:28 +01:00
}
} else {
2015-04-26 13:50:26 +02:00
return new WP_Error ( 'term_exists' , __ ( 'A term with the name provided already exists in this taxonomy.' ), $name_match -> term_id );
2014-05-17 16:16:14 +02:00
}
}
2007-09-15 19:35:32 +02:00
}
2014-11-05 02:42:22 +01:00
$slug = wp_unique_term_slug ( $slug , ( object ) $args );
if ( false === $wpdb -> insert ( $wpdb -> terms , compact ( 'name' , 'slug' , 'term_group' ) ) ) {
return new WP_Error ( 'db_insert_error' , __ ( 'Could not insert term into the database' ), $wpdb -> last_error );
}
$term_id = ( int ) $wpdb -> insert_id ;
2010-04-25 09:35:16 +02:00
// Seems unreachable, However, Is used in the case that a term name is provided, which sanitizes to an empty string.
2010-05-03 22:26:11 +02:00
if ( empty ( $slug ) ) {
2007-09-15 19:35:32 +02:00
$slug = sanitize_title ( $slug , $term_id );
2014-03-28 22:29:13 +01:00
/** This action is documented in wp-includes/taxonomy.php */
2013-07-29 00:15:03 +02:00
do_action ( 'edit_terms' , $term_id , $taxonomy );
2007-10-13 05:51:11 +02:00
$wpdb -> update ( $wpdb -> terms , compact ( 'slug' ), compact ( 'term_id' ) );
2014-03-28 22:29:13 +01:00
/** This action is documented in wp-includes/taxonomy.php */
2013-07-29 00:15:03 +02:00
do_action ( 'edited_terms' , $term_id , $taxonomy );
2007-09-15 19:35:32 +02:00
}
2007-10-13 05:51:11 +02:00
$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 ) );
2007-09-15 19:35:32 +02:00
2014-05-17 16:16:14 +02:00
if ( ! empty ( $tt_id ) ) {
2007-09-15 19:35:32 +02:00
return array ( 'term_id' => $term_id , 'term_taxonomy_id' => $tt_id );
2014-05-17 16:16:14 +02:00
}
2007-10-13 05:51:11 +02:00
$wpdb -> insert ( $wpdb -> term_taxonomy , compact ( 'term_id' , 'taxonomy' , 'description' , 'parent' ) + array ( 'count' => 0 ) );
2007-09-15 19:35:32 +02:00
$tt_id = ( int ) $wpdb -> insert_id ;
In `wp_insert_term()`, clean up accidental duplicate terms after insert.
In [30056], the UNIQUE index was removed from the 'slug' column of `wp_terms`.
While we have numerous checks in place to avoid the creation of unwanted
duplicate term+term_taxonomy pairs, it's possible that in certain edge cases -
such as during the lag caused by database replication, or a race condition
involving near-simultaneous creation of more than one term - we'll end up
unwittingly inserting two identical rows.
The current changeset minimizes this risk by introducing a failsafe mechanism
into `wp_insert_term()`. After a term and term_taxonomy are INSERTed, we check
to see whether the term just created is a duplicate of an existing term; if so,
we delete the new one and keep the old one. This prevents problems caused by
replication lag, because SELECT queries that take place after an INSERT will
hit the master database; it mitigates race conditions by enforcing that the
term that was created first (ie, the one with the lowest `term_id`) is
always the "canonical" one.
Props nacin, markjaquith.
See #22023, #5809.
Built from https://develop.svn.wordpress.org/trunk@30238
git-svn-id: http://core.svn.wordpress.org/trunk@30238 1a063a9b-81f0-0310-95a4-ce76da25c4cd
2014-11-05 02:00:24 +01:00
/*
* Sanity check : if we just created a term with the same parent + taxonomy + slug but a higher term_id than
* an existing term , then we have unwittingly created a duplicate term . Delete the dupe , and use the term_id
* and term_taxonomy_id of the older term instead . Then return out of the function so that the " create " hooks
* are not fired .
*/
$duplicate_term = $wpdb -> get_row ( $wpdb -> prepare ( " SELECT t.term_id, tt.term_taxonomy_id FROM $wpdb->terms t INNER JOIN $wpdb->term_taxonomy tt ON ( tt.term_id = t.term_id ) WHERE t.slug = %s AND tt.parent = %d AND tt.taxonomy = %s AND t.term_id < %d AND tt.term_taxonomy_id != %d " , $slug , $parent , $taxonomy , $term_id , $tt_id ) );
if ( $duplicate_term ) {
$wpdb -> delete ( $wpdb -> terms , array ( 'term_id' => $term_id ) );
$wpdb -> delete ( $wpdb -> term_taxonomy , array ( 'term_taxonomy_id' => $tt_id ) );
$term_id = ( int ) $duplicate_term -> term_id ;
$tt_id = ( int ) $duplicate_term -> term_taxonomy_id ;
clean_term_cache ( $term_id , $taxonomy );
return array ( 'term_id' => $term_id , 'term_taxonomy_id' => $tt_id );
}
2014-03-28 22:29:13 +01:00
/**
* Fires immediately after a new term is created , before the term cache is cleaned .
*
* @ since 2.3 . 0
*
* @ param int $term_id Term ID .
* @ param int $tt_id Term taxonomy ID .
* @ param string $taxonomy Taxonomy slug .
*/
do_action ( " create_term " , $term_id , $tt_id , $taxonomy );
2007-09-15 19:35:32 +02:00
2014-03-28 22:29:13 +01:00
/**
* Fires after a new term is created for a specific taxonomy .
*
2014-11-30 13:00:23 +01:00
* The dynamic portion of the hook name , `$taxonomy` , refers
2014-03-28 22:29:13 +01:00
* to the slug of the taxonomy the term was created for .
*
* @ since 2.3 . 0
*
* @ param int $term_id Term ID .
* @ param int $tt_id Term taxonomy ID .
*/
do_action ( " create_ $taxonomy " , $term_id , $tt_id );
/**
* Filter the term ID after a new term is created .
*
* @ since 2.3 . 0
*
* @ param int $term_id Term ID .
* @ param int $tt_id Taxonomy term ID .
*/
$term_id = apply_filters ( 'term_id_filter' , $term_id , $tt_id );
2007-09-15 19:35:32 +02:00
clean_term_cache ( $term_id , $taxonomy );
2014-03-28 22:29:13 +01:00
/**
* Fires after a new term is created , and after the term cache has been cleaned .
*
* @ since 2.3 . 0
2015-05-07 22:36:29 +02:00
*
* @ param int $term_id Term ID .
* @ param int $tt_id Term taxonomy ID .
* @ param string $taxonomy Taxonomy slug .
2014-03-28 22:29:13 +01:00
*/
2015-05-07 22:36:29 +02:00
do_action ( 'created_term' , $term_id , $tt_id , $taxonomy );
2014-03-28 22:29:13 +01:00
/**
* Fires after a new term in a specific taxonomy is created , and after the term
* cache has been cleaned .
*
2015-05-07 22:36:53 +02:00
* The dynamic portion of the hook name , `$taxonomy` , refers to the taxonomy slug .
*
2014-03-28 22:29:13 +01:00
* @ since 2.3 . 0
*
* @ param int $term_id Term ID .
* @ param int $tt_id Term taxonomy ID .
*/
do_action ( " created_ $taxonomy " , $term_id , $tt_id );
2007-09-15 19:35:32 +02:00
return array ( 'term_id' => $term_id , 'term_taxonomy_id' => $tt_id );
}
/**
2008-06-22 22:23:23 +02:00
* Create Term and Taxonomy Relationships .
2008-02-05 07:47:27 +01:00
*
2008-06-22 22:23:23 +02:00
* Relates an object ( post , link etc ) to a term and taxonomy type . Creates the
* term and taxonomy relationship if it doesn ' t already exist . Creates a term if
* it doesn ' t exist ( using the slug ) .
2007-12-14 01:25:39 +01:00
*
2008-06-22 22:23:23 +02:00
* A relationship means that the term is grouped in or belongs to the taxonomy .
* A term has no meaning until it is given context by defining which taxonomy it
* exists under .
2007-09-15 19:35:32 +02:00
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2007-10-16 00:49:31 +02:00
*
2015-05-05 04:01:25 +02:00
* @ global wpdb $wpdb The WordPress database abstraction object .
*
2014-07-02 03:28:15 +02:00
* @ param int $object_id The object to relate to .
* @ param array | int | string $terms A single term slug , single term id , or array of either term slugs or ids .
* Will replace all existing related terms in this taxonomy .
2015-01-17 00:27:25 +01:00
* @ param string $taxonomy The context in which to relate the term to the object .
2014-07-02 03:39:15 +02:00
* @ param bool $append Optional . If false will delete difference of terms . Default false .
2014-07-02 03:28:15 +02:00
* @ return array | WP_Error Affected Term IDs .
2007-09-15 19:35:32 +02:00
*/
2014-07-02 03:28:15 +02:00
function wp_set_object_terms ( $object_id , $terms , $taxonomy , $append = false ) {
2007-09-15 19:35:32 +02:00
global $wpdb ;
$object_id = ( int ) $object_id ;
2010-06-11 17:53:41 +02:00
if ( ! taxonomy_exists ( $taxonomy ) )
2012-06-01 21:05:30 +02:00
return new WP_Error ( 'invalid_taxonomy' , __ ( 'Invalid taxonomy' ));
2007-09-15 19:35:32 +02:00
if ( ! is_array ( $terms ) )
$terms = array ( $terms );
if ( ! $append )
2009-05-25 20:18:06 +02:00
$old_tt_ids = wp_get_object_terms ( $object_id , $taxonomy , array ( 'fields' => 'tt_ids' , 'orderby' => 'none' ));
2010-02-23 03:37:19 +01:00
else
$old_tt_ids = array ();
2007-09-15 19:35:32 +02:00
$tt_ids = array ();
$term_ids = array ();
2011-10-18 23:01:55 +02:00
$new_tt_ids = array ();
2007-09-15 19:35:32 +02:00
2008-08-06 22:31:54 +02:00
foreach ( ( array ) $terms as $term ) {
2007-12-20 00:25:11 +01:00
if ( ! strlen ( trim ( $term )) )
continue ;
2008-02-05 07:47:27 +01:00
2010-06-11 17:53:41 +02:00
if ( ! $term_info = term_exists ( $term , $taxonomy ) ) {
2010-04-13 16:32:30 +02:00
// Skip if a non-existent term ID is passed.
if ( is_int ( $term ) )
continue ;
2008-10-26 00:56:02 +02:00
$term_info = wp_insert_term ( $term , $taxonomy );
2010-04-13 16:32:30 +02:00
}
2008-10-26 00:56:02 +02:00
if ( is_wp_error ( $term_info ) )
return $term_info ;
$term_ids [] = $term_info [ 'term_id' ];
$tt_id = $term_info [ 'term_taxonomy_id' ];
$tt_ids [] = $tt_id ;
2007-09-15 19:35:32 +02:00
2008-10-26 00:56:02 +02:00
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 ) ) )
2007-09-15 19:35:32 +02:00
continue ;
2014-03-28 22:29:13 +01:00
/**
* Fires immediately before an object - term relationship is added .
*
* @ since 2.9 . 0
*
* @ param int $object_id Object ID .
* @ param int $tt_id Term taxonomy ID .
*/
2009-09-17 16:03:57 +02:00
do_action ( 'add_term_relationship' , $object_id , $tt_id );
2008-10-26 00:56:02 +02:00
$wpdb -> insert ( $wpdb -> term_relationships , array ( 'object_id' => $object_id , 'term_taxonomy_id' => $tt_id ) );
2014-03-28 22:29:13 +01:00
/**
* Fires immediately after an object - term relationship is added .
*
* @ since 2.9 . 0
*
* @ param int $object_id Object ID .
* @ param int $tt_id Term taxonomy ID .
*/
2009-09-17 16:03:57 +02:00
do_action ( 'added_term_relationship' , $object_id , $tt_id );
2011-10-18 23:01:55 +02:00
$new_tt_ids [] = $tt_id ;
2007-09-15 19:35:32 +02:00
}
2011-10-18 23:01:55 +02:00
if ( $new_tt_ids )
wp_update_term_count ( $new_tt_ids , $taxonomy );
2007-09-15 19:35:32 +02:00
if ( ! $append ) {
2013-02-08 19:45:34 +01:00
$delete_tt_ids = array_diff ( $old_tt_ids , $tt_ids );
2013-05-20 14:10:58 +02:00
2013-02-08 19:45:34 +01:00
if ( $delete_tt_ids ) {
$in_delete_tt_ids = " ' " . implode ( " ', ' " , $delete_tt_ids ) . " ' " ;
$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 ) );
$delete_term_ids = array_map ( 'intval' , $delete_term_ids );
2013-05-20 14:10:58 +02:00
2013-02-08 19:45:34 +01:00
$remove = wp_remove_object_terms ( $object_id , $delete_term_ids , $taxonomy );
if ( is_wp_error ( $remove ) ) {
return $remove ;
}
2007-09-15 19:35:32 +02:00
}
}
2008-02-14 18:17:57 +01:00
$t = get_taxonomy ( $taxonomy );
2008-02-22 18:43:56 +01:00
if ( ! $append && isset ( $t -> sort ) && $t -> sort ) {
2008-02-14 18:17:57 +01:00
$values = array ();
$term_order = 0 ;
2009-12-23 16:31:02 +01:00
$final_tt_ids = wp_get_object_terms ( $object_id , $taxonomy , array ( 'fields' => 'tt_ids' ));
2008-05-16 03:43:35 +02:00
foreach ( $tt_ids as $tt_id )
if ( in_array ( $tt_id , $final_tt_ids ) )
$values [] = $wpdb -> prepare ( " (%d, %d, %d) " , $object_id , $tt_id , ++ $term_order );
2008-02-14 18:17:57 +01:00
if ( $values )
2012-09-05 19:57:53 +02:00
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) " ) )
return new WP_Error ( 'db_insert_error' , __ ( 'Could not insert term relationship into the database' ), $wpdb -> last_error );
2008-02-14 18:17:57 +01:00
}
2012-11-27 20:42:38 +01:00
wp_cache_delete ( $object_id , $taxonomy . '_relationships' );
2014-03-28 22:29:13 +01:00
/**
* Fires after an object ' s terms have been set .
*
* @ since 2.8 . 0
*
* @ param int $object_id Object ID .
* @ param array $terms An array of object terms .
* @ param array $tt_ids An array of term taxonomy IDs .
* @ param string $taxonomy Taxonomy slug .
* @ param bool $append Whether to append new terms to the old terms .
* @ param array $old_tt_ids Old array of term taxonomy IDs .
*/
do_action ( 'set_object_terms' , $object_id , $terms , $tt_ids , $taxonomy , $append , $old_tt_ids );
2007-09-15 19:35:32 +02:00
return $tt_ids ;
}
2013-02-08 19:45:34 +01:00
/**
* Add term ( s ) associated with a given object .
*
2013-12-24 19:57:12 +01:00
* @ since 3.6 . 0
2013-02-08 19:45:34 +01:00
*
2015-05-07 22:37:41 +02:00
* @ param int $object_id The ID of the object to which the terms will be added .
* @ param array | int | string $terms The slug ( s ) or ID ( s ) of the term ( s ) to add .
* @ param array | string $taxonomy Taxonomy name .
2013-02-08 19:45:34 +01:00
* @ return array | WP_Error Affected Term IDs
*/
function wp_add_object_terms ( $object_id , $terms , $taxonomy ) {
return wp_set_object_terms ( $object_id , $terms , $taxonomy , true );
}
/**
* Remove term ( s ) associated with a given object .
*
2013-12-24 19:57:12 +01:00
* @ since 3.6 . 0
2014-10-31 18:56:22 +01:00
*
* @ global wpdb $wpdb WordPress database abstraction object .
2013-02-08 19:45:34 +01:00
*
2015-05-07 22:37:41 +02:00
* @ param int $object_id The ID of the object from which the terms will be removed .
* @ param array | int | string $terms The slug ( s ) or ID ( s ) of the term ( s ) to remove .
* @ param array | string $taxonomy Taxonomy name .
2013-02-08 19:45:34 +01:00
* @ return bool | WP_Error True on success , false or WP_Error on failure .
*/
function wp_remove_object_terms ( $object_id , $terms , $taxonomy ) {
global $wpdb ;
$object_id = ( int ) $object_id ;
if ( ! taxonomy_exists ( $taxonomy ) ) {
return new WP_Error ( 'invalid_taxonomy' , __ ( 'Invalid Taxonomy' ) );
}
if ( ! is_array ( $terms ) ) {
$terms = array ( $terms );
}
$tt_ids = array ();
2013-05-20 14:10:58 +02:00
2013-02-08 19:45:34 +01:00
foreach ( ( array ) $terms as $term ) {
if ( ! strlen ( trim ( $term ) ) ) {
continue ;
}
2013-05-20 14:10:58 +02:00
2013-02-08 19:45:34 +01:00
if ( ! $term_info = term_exists ( $term , $taxonomy ) ) {
// Skip if a non-existent term ID is passed.
if ( is_int ( $term ) ) {
continue ;
}
}
2013-05-20 14:10:58 +02:00
2013-02-08 19:45:34 +01:00
if ( is_wp_error ( $term_info ) ) {
return $term_info ;
}
2013-05-20 14:10:58 +02:00
2013-02-08 19:45:34 +01:00
$tt_ids [] = $term_info [ 'term_taxonomy_id' ];
}
2013-05-20 14:10:58 +02:00
2013-02-08 19:45:34 +01:00
if ( $tt_ids ) {
$in_tt_ids = " ' " . implode ( " ', ' " , $tt_ids ) . " ' " ;
2014-03-28 22:29:13 +01:00
/**
* Fires immediately before an object - term relationship is deleted .
*
* @ since 2.9 . 0
*
* @ param int $object_id Object ID .
* @ param array $tt_ids An array of term taxonomy IDs .
*/
2013-02-08 19:45:34 +01:00
do_action ( 'delete_term_relationships' , $object_id , $tt_ids );
2013-03-01 17:22:07 +01:00
$deleted = $wpdb -> query ( $wpdb -> prepare ( " DELETE FROM $wpdb->term_relationships WHERE object_id = %d AND term_taxonomy_id IN ( $in_tt_ids ) " , $object_id ) );
2014-03-28 22:29:13 +01:00
/**
* Fires immediately after an object - term relationship is deleted .
*
* @ since 2.9 . 0
*
* @ param int $object_id Object ID .
* @ param array $tt_ids An array of term taxonomy IDs .
*/
2013-02-08 19:45:34 +01:00
do_action ( 'deleted_term_relationships' , $object_id , $tt_ids );
2015-05-07 22:37:41 +02:00
2013-02-08 19:45:34 +01:00
wp_update_term_count ( $tt_ids , $taxonomy );
2013-05-20 14:10:58 +02:00
2013-03-01 17:22:07 +01:00
return ( bool ) $deleted ;
2013-02-08 19:45:34 +01:00
}
return false ;
}
2007-10-16 00:49:31 +02:00
/**
2008-06-22 22:23:23 +02:00
* Will make slug unique , if it isn ' t already .
2008-02-05 07:47:27 +01:00
*
2015-05-07 22:37:41 +02:00
* The `$slug` has to be unique global to every taxonomy , meaning that one
2008-06-22 22:23:23 +02:00
* taxonomy term can ' t have a matching slug with another taxonomy term . Each
* slug has to be globally unique for every taxonomy .
2007-10-16 00:49:31 +02:00
*
2008-06-22 22:23:23 +02:00
* The way this works is that if the taxonomy that the term belongs to is
2010-01-22 20:30:05 +01:00
* hierarchical and has a parent , it will append that parent to the $slug .
2007-10-16 00:49:31 +02:00
*
2008-06-22 22:23:23 +02:00
* If that still doesn ' t return an unique slug , then it try to append a number
2011-09-05 21:08:15 +02:00
* until it finds a number that is truly unique .
2008-02-05 07:47:27 +01:00
*
2015-05-07 22:37:41 +02:00
* The only purpose for `$term` is for appending a parent , if one exists .
2007-10-16 00:49:31 +02:00
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2014-10-31 18:56:22 +01:00
*
* @ global wpdb $wpdb WordPress database abstraction object .
2007-10-16 00:49:31 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param string $slug The string that will be tried for a unique slug .
* @ param object $term The term object that the $slug will belong too .
2007-10-16 00:49:31 +02:00
* @ return string Will return a true unique slug .
*/
2015-05-07 22:37:41 +02:00
function wp_unique_term_slug ( $slug , $term ) {
2007-09-22 20:01:08 +02:00
global $wpdb ;
2010-06-11 17:53:41 +02:00
if ( ! term_exists ( $slug ) )
2010-03-27 08:56:54 +01:00
return $slug ;
2014-11-05 02:42:22 +01:00
// As of 4.1, duplicate slugs are allowed as long as they're in different taxonomies.
if ( get_option ( 'db_version' ) >= 30133 && ! get_term_by ( 'slug' , $slug , $term -> taxonomy ) ) {
return $slug ;
}
2015-05-07 22:37:41 +02:00
/*
* If the taxonomy supports hierarchy and the term has a parent , make the slug unique
* by incorporating parent slugs .
*/
2007-09-22 20:01:08 +02:00
if ( is_taxonomy_hierarchical ( $term -> taxonomy ) && ! empty ( $term -> parent ) ) {
$the_parent = $term -> parent ;
while ( ! empty ( $the_parent ) ) {
$parent_term = get_term ( $the_parent , $term -> taxonomy );
if ( is_wp_error ( $parent_term ) || empty ( $parent_term ) )
break ;
2010-04-25 17:25:00 +02:00
$slug .= '-' . $parent_term -> slug ;
2010-06-11 17:53:41 +02:00
if ( ! term_exists ( $slug ) )
2010-04-25 17:25:00 +02:00
return $slug ;
2007-09-22 20:01:08 +02:00
if ( empty ( $parent_term -> parent ) )
break ;
$the_parent = $parent_term -> parent ;
}
}
// If we didn't get a unique slug, try appending a number to make it unique.
2013-08-23 23:05:09 +02:00
if ( ! empty ( $term -> term_id ) )
$query = $wpdb -> prepare ( " SELECT slug FROM $wpdb->terms WHERE slug = %s AND term_id != %d " , $slug , $term -> term_id );
2007-11-09 19:34:41 +01:00
else
2007-12-06 20:49:33 +01:00
$query = $wpdb -> prepare ( " SELECT slug FROM $wpdb->terms WHERE slug = %s " , $slug );
2007-11-09 19:34:41 +01:00
if ( $wpdb -> get_var ( $query ) ) {
2007-09-22 20:01:08 +02:00
$num = 2 ;
do {
$alt_slug = $slug . " - $num " ;
$num ++ ;
2007-10-13 05:51:11 +02:00
$slug_check = $wpdb -> get_var ( $wpdb -> prepare ( " SELECT slug FROM $wpdb->terms WHERE slug = %s " , $alt_slug ) );
2007-09-22 20:01:08 +02:00
} while ( $slug_check );
$slug = $alt_slug ;
}
return $slug ;
}
2007-10-16 00:49:31 +02:00
/**
2008-06-22 22:23:23 +02:00
* Update term based on arguments provided .
2007-12-14 01:25:39 +01:00
*
2008-06-22 22:23:23 +02:00
* The $args will indiscriminately override all values with the same field name .
* Care must be taken to not override important information need to update or
* update will fail ( or perhaps create a new term , neither would be acceptable ) .
2007-12-14 01:25:39 +01:00
*
2008-06-22 22:23:23 +02:00
* Defaults will set 'alias_of' , 'description' , 'parent' , and 'slug' if not
* defined in $args already .
2007-12-14 01:25:39 +01:00
*
2008-06-22 22:23:23 +02:00
* 'alias_of' will create a term group , if it doesn ' t already exist , and update
* it for the $term .
2007-12-14 01:25:39 +01:00
*
2008-06-22 22:23:23 +02:00
* If the 'slug' argument in $args is missing , then the 'name' in $args will be
* used . It should also be noted that if you set 'slug' and it isn ' t unique then
* a WP_Error will be passed back . If you don ' t pass any slug , then a unique one
* will be created for you .
2007-10-21 19:18:24 +02:00
*
2015-05-07 22:37:41 +02:00
* For what can be overrode in `$args` , check the term scheme can contain and stay
2008-06-22 22:23:23 +02:00
* away from the term keys .
2007-10-16 00:49:31 +02:00
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2007-12-14 01:25:39 +01:00
*
2014-10-31 18:56:22 +01:00
* @ global wpdb $wpdb WordPress database abstraction object .
2007-10-16 00:49:31 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param int $term_id The ID of the term
* @ param string $taxonomy The context in which to relate the term to the object .
* @ param array | string $args Optional . Array of get_terms () arguments . Default empty array .
2007-12-14 01:25:39 +01:00
* @ return array | WP_Error Returns Term ID and Taxonomy Term ID
2007-10-16 00:49:31 +02:00
*/
2009-04-23 10:05:36 +02:00
function wp_update_term ( $term_id , $taxonomy , $args = array () ) {
2007-09-15 19:35:32 +02:00
global $wpdb ;
2015-04-13 03:21:27 +02:00
if ( ! taxonomy_exists ( $taxonomy ) ) {
return new WP_Error ( 'invalid_taxonomy' , __ ( 'Invalid taxonomy' ) );
}
2007-09-15 19:35:32 +02:00
2009-04-23 10:05:36 +02:00
$term_id = ( int ) $term_id ;
2007-09-15 19:35:32 +02:00
// First, get all of the original args
2015-04-13 03:21:27 +02:00
$term = get_term ( $term_id , $taxonomy , ARRAY_A );
2007-09-15 19:35:32 +02:00
2015-04-13 03:21:27 +02:00
if ( is_wp_error ( $term ) ) {
2009-03-17 17:42:21 +01:00
return $term ;
2015-04-13 03:21:27 +02:00
}
if ( ! $term ) {
return new WP_Error ( 'invalid_term' , __ ( 'Empty Term' ) );
}
2009-03-17 17:42:21 +01:00
2013-03-01 17:28:40 +01:00
// Escape data pulled from DB.
2013-03-03 22:11:40 +01:00
$term = wp_slash ( $term );
2013-03-01 17:28:40 +01:00
2007-09-15 19:35:32 +02:00
// Merge old and new args with new args overwriting old ones.
$args = array_merge ( $term , $args );
$defaults = array ( 'alias_of' => '' , 'description' => '' , 'parent' => 0 , 'slug' => '' );
$args = wp_parse_args ( $args , $defaults );
$args = sanitize_term ( $args , $taxonomy , 'db' );
2014-05-16 23:29:13 +02:00
$parsed_args = $args ;
2007-09-15 19:35:32 +02:00
2013-03-01 17:28:40 +01:00
// expected_slashed ($name)
2014-05-16 23:29:13 +02:00
$name = wp_unslash ( $args [ 'name' ] );
$description = wp_unslash ( $args [ 'description' ] );
$parsed_args [ 'name' ] = $name ;
$parsed_args [ 'description' ] = $description ;
2013-03-01 17:28:40 +01:00
2008-07-21 23:53:32 +02:00
if ( '' == trim ( $name ) )
return new WP_Error ( 'empty_term_name' , __ ( 'A name is required for this term' ));
2014-10-09 20:12:20 +02:00
if ( $parsed_args [ 'parent' ] > 0 && ! term_exists ( ( int ) $parsed_args [ 'parent' ] ) ) {
return new WP_Error ( 'missing_parent' , __ ( 'Parent term does not exist.' ) );
}
2007-09-22 20:01:08 +02:00
$empty_slug = false ;
2014-05-16 23:29:13 +02:00
if ( empty ( $args [ 'slug' ] ) ) {
2007-09-22 20:01:08 +02:00
$empty_slug = true ;
2007-09-15 19:35:32 +02:00
$slug = sanitize_title ( $name );
2014-05-16 23:29:13 +02:00
} else {
$slug = $args [ 'slug' ];
2007-09-22 20:01:08 +02:00
}
2007-09-15 19:35:32 +02:00
2014-05-16 23:29:13 +02:00
$parsed_args [ 'slug' ] = $slug ;
2014-08-20 19:04:18 +02:00
$term_group = isset ( $parsed_args [ 'term_group' ] ) ? $parsed_args [ 'term_group' ] : 0 ;
2014-05-16 23:29:13 +02:00
if ( $args [ 'alias_of' ] ) {
2014-10-09 04:32:19 +02:00
$alias = get_term_by ( 'slug' , $args [ 'alias_of' ], $taxonomy );
if ( ! empty ( $alias -> term_group ) ) {
2007-09-15 19:35:32 +02:00
// The alias we want is already in a group, so let's use that one.
$term_group = $alias -> term_group ;
2015-01-08 07:26:23 +01:00
} elseif ( ! empty ( $alias -> term_id ) ) {
2014-10-09 04:32:19 +02:00
/*
* The alias is not in a group , so we create a new one
* and add the alias to it .
*/
2007-10-23 18:43:15 +02:00
$term_group = $wpdb -> get_var ( " SELECT MAX(term_group) FROM $wpdb->terms " ) + 1 ;
2014-03-28 22:29:13 +01:00
2014-10-09 04:32:19 +02:00
wp_update_term ( $alias -> term_id , $taxonomy , array (
'term_group' => $term_group ,
) );
2007-09-15 19:35:32 +02:00
}
2014-05-16 23:29:13 +02:00
$parsed_args [ 'term_group' ] = $term_group ;
2007-09-15 19:35:32 +02:00
}
2014-03-28 22:29:13 +01:00
/**
* Filter the term parent .
*
* Hook to this filter to see if it will cause a hierarchy loop .
*
* @ since 3.1 . 0
*
2014-05-16 23:29:13 +02:00
* @ param int $parent ID of the parent term .
* @ param int $term_id Term ID .
* @ param string $taxonomy Taxonomy slug .
* @ param array $parsed_args An array of potentially altered update arguments for the given term .
* @ param array $args An array of update arguments for the given term .
2014-03-28 22:29:13 +01:00
*/
2014-05-16 23:29:13 +02:00
$parent = apply_filters ( 'wp_update_term_parent' , $args [ 'parent' ], $term_id , $taxonomy , $parsed_args , $args );
2010-10-14 17:09:04 +02:00
2007-09-22 20:01:08 +02:00
// Check for duplicate slug
2014-12-22 16:33:25 +01:00
$duplicate = get_term_by ( 'slug' , $slug , $taxonomy );
if ( $duplicate && $duplicate -> term_id != $term_id ) {
2007-11-09 19:34:41 +01:00
// If an empty slug was passed or the parent changed, reset the slug to something unique.
2007-09-22 20:01:08 +02:00
// Otherwise, bail.
2010-02-07 07:51:05 +01:00
if ( $empty_slug || ( $parent != $term [ 'parent' ]) )
2007-09-22 20:01:08 +02:00
$slug = wp_unique_term_slug ( $slug , ( object ) $args );
else
2009-05-05 06:28:05 +02:00
return new WP_Error ( 'duplicate_term_slug' , sprintf ( __ ( 'The slug “%s” is already in use by another term' ), $slug ));
2007-09-22 20:01:08 +02:00
}
2014-03-28 22:29:13 +01:00
2014-11-05 03:03:23 +01:00
$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 ) );
2015-02-11 20:42:25 +01:00
// Check whether this is a shared term that needs splitting.
$_term_id = _split_shared_term ( $term_id , $tt_id );
if ( ! is_wp_error ( $_term_id ) ) {
$term_id = $_term_id ;
}
2014-10-09 04:32:19 +02:00
/**
* Fires immediately before the given terms are edited .
*
* @ since 2.9 . 0
*
* @ param int $term_id Term ID .
* @ param string $taxonomy Taxonomy slug .
*/
2013-07-29 00:15:03 +02:00
do_action ( 'edit_terms' , $term_id , $taxonomy );
2007-10-13 05:51:11 +02:00
$wpdb -> update ( $wpdb -> terms , compact ( 'name' , 'slug' , 'term_group' ), compact ( 'term_id' ) );
2007-09-15 19:35:32 +02:00
if ( empty ( $slug ) ) {
$slug = sanitize_title ( $name , $term_id );
2007-10-13 05:51:11 +02:00
$wpdb -> update ( $wpdb -> terms , compact ( 'slug' ), compact ( 'term_id' ) );
2007-09-15 19:35:32 +02:00
}
2014-03-28 22:29:13 +01:00
2014-10-09 04:32:19 +02:00
/**
* Fires immediately after the given terms are edited .
*
* @ since 2.9 . 0
*
* @ param int $term_id Term ID
* @ param string $taxonomy Taxonomy slug .
*/
2013-07-29 00:15:03 +02:00
do_action ( 'edited_terms' , $term_id , $taxonomy );
2007-09-15 19:35:32 +02:00
2014-03-28 22:29:13 +01:00
/**
* Fires immediate before a term - taxonomy relationship is updated .
*
* @ since 2.9 . 0
*
* @ param int $tt_id Term taxonomy ID .
* @ param string $taxonomy Taxonomy slug .
*/
2010-03-09 11:48:18 +01:00
do_action ( 'edit_term_taxonomy' , $tt_id , $taxonomy );
2015-05-07 22:37:41 +02:00
2007-10-15 22:07:29 +02:00
$wpdb -> update ( $wpdb -> term_taxonomy , compact ( 'term_id' , 'taxonomy' , 'description' , 'parent' ), array ( 'term_taxonomy_id' => $tt_id ) );
2014-03-28 22:29:13 +01:00
/**
* Fires immediately after a term - taxonomy relationship is updated .
*
* @ since 2.9 . 0
*
* @ param int $tt_id Term taxonomy ID .
* @ param string $taxonomy Taxonomy slug .
*/
2010-03-09 11:53:02 +01:00
do_action ( 'edited_term_taxonomy' , $tt_id , $taxonomy );
2009-09-24 19:19:13 +02:00
2015-05-07 22:37:41 +02:00
// Clean the relationship caches for all object types using this term.
2014-02-11 17:50:13 +01:00
$objects = $wpdb -> get_col ( $wpdb -> prepare ( " SELECT object_id FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d " , $tt_id ) );
$tax_object = get_taxonomy ( $taxonomy );
2014-03-28 22:29:13 +01:00
foreach ( $tax_object -> object_type as $object_type ) {
2014-02-11 17:50:13 +01:00
clean_object_term_cache ( $objects , $object_type );
2014-03-28 22:29:13 +01:00
}
2014-02-11 17:50:13 +01:00
2014-03-28 22:29:13 +01:00
/**
* Fires after a term has been updated , but before the term cache has been cleaned .
*
* @ since 2.3 . 0
*
* @ param int $term_id Term ID .
* @ param int $tt_id Term taxonomy ID .
* @ param string $taxonomy Taxonomy slug .
*/
do_action ( " edit_term " , $term_id , $tt_id , $taxonomy );
2007-09-15 19:35:32 +02:00
2014-03-28 22:29:13 +01:00
/**
* Fires after a term in a specific taxonomy has been updated , but before the term
* cache has been cleaned .
*
2014-11-30 13:00:23 +01:00
* The dynamic portion of the hook name , `$taxonomy` , refers to the taxonomy slug .
2014-03-28 22:29:13 +01:00
*
* @ since 2.3 . 0
*
* @ param int $term_id Term ID .
* @ param int $tt_id Term taxonomy ID .
*/
do_action ( " edit_ $taxonomy " , $term_id , $tt_id );
/** This filter is documented in wp-includes/taxonomy.php */
$term_id = apply_filters ( 'term_id_filter' , $term_id , $tt_id );
2007-09-15 19:35:32 +02:00
clean_term_cache ( $term_id , $taxonomy );
2014-03-28 22:29:13 +01:00
/**
* Fires after a term has been updated , and the term cache has been cleaned .
*
* @ since 2.3 . 0
*
* @ param int $term_id Term ID .
* @ param int $tt_id Term taxonomy ID .
* @ param string $taxonomy Taxonomy slug .
*/
do_action ( " edited_term " , $term_id , $tt_id , $taxonomy );
/**
* Fires after a term for a specific taxonomy has been updated , and the term
* cache has been cleaned .
*
2014-11-30 13:00:23 +01:00
* The dynamic portion of the hook name , `$taxonomy` , refers to the taxonomy slug .
2014-03-28 22:29:13 +01:00
*
* @ since 2.3 . 0
*
* @ param int $term_id Term ID .
* @ param int $tt_id Term taxonomy ID .
*/
do_action ( " edited_ $taxonomy " , $term_id , $tt_id );
2007-09-15 19:35:32 +02:00
return array ( 'term_id' => $term_id , 'term_taxonomy_id' => $tt_id );
}
2008-06-22 22:23:23 +02:00
/**
* Enable or disable term counting .
*
2008-08-30 23:23:43 +02:00
* @ since 2.5 . 0
2008-06-22 22:23:23 +02:00
*
2008-08-30 23:23:43 +02:00
* @ param bool $defer Optional . Enable if true , disable if false .
* @ return bool Whether term counting is enabled or disabled .
2008-06-22 22:23:23 +02:00
*/
2008-08-30 23:23:43 +02:00
function wp_defer_term_counting ( $defer = null ) {
2007-12-12 06:14:00 +01:00
static $_defer = false ;
2008-02-05 07:47:27 +01:00
2007-12-12 06:14:00 +01:00
if ( is_bool ( $defer ) ) {
$_defer = $defer ;
// flush any deferred counts
if ( ! $defer )
2008-08-30 23:23:43 +02:00
wp_update_term_count ( null , null , true );
2007-12-12 06:14:00 +01:00
}
2008-02-05 07:47:27 +01:00
2007-12-12 06:14:00 +01:00
return $_defer ;
}
2007-10-16 00:49:31 +02:00
/**
2008-06-22 22:23:23 +02:00
* Updates the amount of terms in taxonomy .
2008-02-05 07:47:27 +01:00
*
2011-09-05 21:08:15 +02:00
* If there is a taxonomy callback applied , then it will be called for updating
2008-06-22 22:23:23 +02:00
* the count .
2007-10-16 00:49:31 +02:00
*
2008-06-22 22:23:23 +02:00
* The default action is to count what the amount of terms have the relationship
* of term ID . Once that is done , then update the database .
2007-10-16 00:49:31 +02:00
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2014-10-31 18:56:22 +01:00
*
* @ global wpdb $wpdb WordPress database abstraction object .
2007-10-16 00:49:31 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param int | array $terms The term_taxonomy_id of the terms .
* @ param string $taxonomy The context of the term .
2007-10-16 00:49:31 +02:00
* @ return bool If no terms will return false , and if successful will return true .
*/
2007-12-12 06:14:00 +01:00
function wp_update_term_count ( $terms , $taxonomy , $do_deferred = false ) {
static $_deferred = array ();
if ( $do_deferred ) {
2008-08-06 22:31:54 +02:00
foreach ( ( array ) array_keys ( $_deferred ) as $tax ) {
2007-12-12 06:14:00 +01:00
wp_update_term_count_now ( $_deferred [ $tax ], $tax );
unset ( $_deferred [ $tax ] );
}
}
2007-09-15 19:35:32 +02:00
if ( empty ( $terms ) )
return false ;
if ( ! is_array ( $terms ) )
$terms = array ( $terms );
2007-12-12 06:14:00 +01:00
if ( wp_defer_term_counting () ) {
if ( ! isset ( $_deferred [ $taxonomy ]) )
$_deferred [ $taxonomy ] = array ();
$_deferred [ $taxonomy ] = array_unique ( array_merge ( $_deferred [ $taxonomy ], $terms ) );
return true ;
}
2008-02-05 07:47:27 +01:00
2007-12-12 06:14:00 +01:00
return wp_update_term_count_now ( $terms , $taxonomy );
}
2008-06-22 22:23:23 +02:00
/**
* Perform term count update immediately .
*
2008-08-30 23:23:43 +02:00
* @ since 2.5 . 0
2008-06-22 22:23:23 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param array $terms The term_taxonomy_id of terms to update .
2008-06-22 22:23:23 +02:00
* @ param string $taxonomy The context of the term .
* @ return bool Always true when complete .
*/
2007-12-12 06:14:00 +01:00
function wp_update_term_count_now ( $terms , $taxonomy ) {
2007-09-15 19:35:32 +02:00
$terms = array_map ( 'intval' , $terms );
$taxonomy = get_taxonomy ( $taxonomy );
if ( ! empty ( $taxonomy -> update_count_callback ) ) {
2010-03-09 11:48:18 +01:00
call_user_func ( $taxonomy -> update_count_callback , $terms , $taxonomy );
2007-09-15 19:35:32 +02:00
} else {
2011-10-21 23:38:14 +02:00
$object_types = ( array ) $taxonomy -> object_type ;
foreach ( $object_types as & $object_type ) {
if ( 0 === strpos ( $object_type , 'attachment:' ) )
list ( $object_type ) = explode ( ':' , $object_type );
}
if ( $object_types == array_filter ( $object_types , 'post_type_exists' ) ) {
// Only post types are attached to this taxonomy
_update_post_term_count ( $terms , $taxonomy );
} else {
// Default count updater
_update_generic_term_count ( $terms , $taxonomy );
}
2007-09-15 19:35:32 +02:00
}
2010-01-27 20:42:23 +01:00
clean_term_cache ( $terms , '' , false );
2007-09-15 19:35:32 +02:00
return true ;
}
//
// Cache
//
2007-10-16 00:49:31 +02:00
/**
2008-06-22 22:23:23 +02:00
* Removes the taxonomy relationship to terms from the cache .
2007-10-21 19:18:24 +02:00
*
2015-05-07 22:37:41 +02:00
* Will remove the entire taxonomy relationship containing term `$object_id` . The
* term IDs have to exist within the taxonomy `$object_type` for the deletion to
2008-06-22 22:23:23 +02:00
* take place .
2007-10-16 00:49:31 +02:00
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2007-10-21 19:18:24 +02:00
*
2015-05-07 22:37:41 +02:00
* @ see get_object_taxonomies () for more on $object_type .
2007-10-16 00:49:31 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param int | array $object_ids Single or list of term object ID ( s ) .
* @ param array | string $object_type The taxonomy object type .
2007-10-16 00:49:31 +02:00
*/
2007-09-15 19:35:32 +02:00
function clean_object_term_cache ( $object_ids , $object_type ) {
if ( ! is_array ( $object_ids ) )
$object_ids = array ( $object_ids );
2012-09-22 17:21:30 +02:00
$taxonomies = get_object_taxonomies ( $object_type );
2014-02-06 02:41:12 +01:00
foreach ( $object_ids as $id ) {
foreach ( $taxonomies as $taxonomy ) {
2007-10-24 19:07:04 +02:00
wp_cache_delete ( $id , " { $taxonomy } _relationships " );
2014-02-06 02:41:12 +01:00
}
}
2007-10-14 06:55:33 +02:00
2014-03-28 22:29:13 +01:00
/**
* Fires after the object term cache has been cleaned .
*
* @ since 2.5 . 0
*
* @ param array $object_ids An array of object IDs .
* @ param string $objet_type Object type .
*/
do_action ( 'clean_object_term_cache' , $object_ids , $object_type );
2007-09-15 19:35:32 +02:00
}
2007-10-16 00:49:31 +02:00
/**
2008-06-22 22:23:23 +02:00
* Will remove all of the term ids from the cache .
2007-10-16 00:49:31 +02:00
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2014-10-31 18:56:22 +01:00
*
* @ global wpdb $wpdb WordPress database abstraction object .
2007-10-16 00:49:31 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param int | array $ids Single or list of Term IDs .
* @ param string $taxonomy Optional . Can be empty and will assume `tt_ids` , else will use for context .
* Default empty .
* @ param bool $clean_taxonomy Optional . Whether to clean taxonomy wide caches ( true ), or just individual
* term object caches ( false ) . Default true .
2007-10-16 00:49:31 +02:00
*/
2010-01-27 20:42:23 +01:00
function clean_term_cache ( $ids , $taxonomy = '' , $clean_taxonomy = true ) {
2015-05-12 22:14:26 +02:00
global $wpdb , $_wp_suspend_cache_invalidation ;
if ( ! empty ( $_wp_suspend_cache_invalidation ) ) {
return ;
}
2007-09-15 19:35:32 +02:00
if ( ! is_array ( $ids ) )
$ids = array ( $ids );
$taxonomies = array ();
// If no taxonomy, assume tt_ids.
if ( empty ( $taxonomy ) ) {
2009-12-23 15:37:21 +01:00
$tt_ids = array_map ( 'intval' , $ids );
$tt_ids = implode ( ', ' , $tt_ids );
2007-09-15 19:35:32 +02:00
$terms = $wpdb -> get_results ( " SELECT term_id, taxonomy FROM $wpdb->term_taxonomy WHERE term_taxonomy_id IN ( $tt_ids ) " );
2009-12-23 15:37:21 +01:00
$ids = array ();
2007-09-15 19:35:32 +02:00
foreach ( ( array ) $terms as $term ) {
$taxonomies [] = $term -> taxonomy ;
2009-12-23 15:37:21 +01:00
$ids [] = $term -> term_id ;
2007-09-15 19:35:32 +02:00
wp_cache_delete ( $term -> term_id , $term -> taxonomy );
}
$taxonomies = array_unique ( $taxonomies );
} else {
$taxonomies = array ( $taxonomy );
2009-12-23 15:37:21 +01:00
foreach ( $taxonomies as $taxonomy ) {
foreach ( $ids as $id ) {
wp_cache_delete ( $id , $taxonomy );
}
}
2007-09-15 19:35:32 +02:00
}
foreach ( $taxonomies as $taxonomy ) {
2010-01-27 20:42:23 +01:00
if ( $clean_taxonomy ) {
wp_cache_delete ( 'all_ids' , $taxonomy );
wp_cache_delete ( 'get' , $taxonomy );
delete_option ( " { $taxonomy } _children " );
// Regenerate {$taxonomy}_children
_get_term_hierarchy ( $taxonomy );
}
2014-03-28 22:29:13 +01:00
/**
* Fires once after each taxonomy ' s term cache has been cleaned .
*
* @ since 2.5 . 0
*
* @ param array $ids An array of term IDs .
* @ param string $taxonomy Taxonomy slug .
*/
do_action ( 'clean_term_cache' , $ids , $taxonomy );
2007-09-15 19:35:32 +02:00
}
2014-10-28 22:05:23 +01:00
wp_cache_set ( 'last_changed' , microtime (), 'terms' );
2007-09-15 19:35:32 +02:00
}
2007-10-21 19:18:24 +02:00
/**
2008-06-22 22:23:23 +02:00
* Retrieves the taxonomy relationship to the term object id .
2007-10-21 19:18:24 +02:00
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2007-10-21 19:18:24 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param int $id Term object ID .
* @ param string $taxonomy Taxonomy name .
* @ return bool | array Empty array if $terms found , but not `$taxonomy` . False if nothing is in cache
* for `$taxonomy` and `$id` .
2007-10-21 19:18:24 +02:00
*/
2015-05-07 22:37:41 +02:00
function get_object_term_cache ( $id , $taxonomy ) {
2008-01-10 21:51:07 +01:00
$cache = wp_cache_get ( $id , " { $taxonomy } _relationships " );
return $cache ;
2007-09-15 19:35:32 +02:00
}
2007-10-21 19:18:24 +02:00
/**
2014-12-31 19:12:26 +01:00
* Updates the cache for the given term object ID ( s ) .
2007-12-14 01:25:39 +01:00
*
2014-12-31 19:12:26 +01:00
* Note : Due to performance concerns , great care should be taken to only update
* term caches when necessary . Processing time can increase exponentially depending
* on both the number of passed term IDs and the number of taxonomies those terms
* belong to .
2007-12-14 01:25:39 +01:00
*
2014-12-31 19:12:26 +01:00
* Caches will only be updated for terms not already cached .
2007-10-21 19:18:24 +02:00
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2007-10-21 19:18:24 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param string | array $object_ids Comma - separated list or array of term object IDs .
2014-12-31 19:12:26 +01:00
* @ param array | string $object_type The taxonomy object type .
* @ return null | false Null if `$object_ids` is empty , false if all of the terms in
* `$object_ids` are already cached .
2007-10-21 19:18:24 +02:00
*/
2007-09-15 19:35:32 +02:00
function update_object_term_cache ( $object_ids , $object_type ) {
if ( empty ( $object_ids ) )
return ;
if ( ! is_array ( $object_ids ) )
$object_ids = explode ( ',' , $object_ids );
2007-10-13 20:23:59 +02:00
$object_ids = array_map ( 'intval' , $object_ids );
2007-09-15 19:35:32 +02:00
2007-10-23 22:33:50 +02:00
$taxonomies = get_object_taxonomies ( $object_type );
2007-10-13 20:23:59 +02:00
$ids = array ();
foreach ( ( array ) $object_ids as $id ) {
2007-10-23 22:33:50 +02:00
foreach ( $taxonomies as $taxonomy ) {
if ( false === wp_cache_get ( $id , " { $taxonomy } _relationships " ) ) {
$ids [] = $id ;
break ;
}
}
2007-10-13 20:23:59 +02:00
}
2007-09-15 19:35:32 +02:00
2007-10-13 20:23:59 +02:00
if ( empty ( $ids ) )
return false ;
2007-09-15 19:35:32 +02:00
2009-12-23 16:31:02 +01:00
$terms = wp_get_object_terms ( $ids , $taxonomies , array ( 'fields' => 'all_with_object_id' ));
2007-09-15 19:35:32 +02:00
2007-10-13 20:23:59 +02:00
$object_terms = array ();
foreach ( ( array ) $terms as $term )
2015-01-28 21:43:23 +01:00
$object_terms [ $term -> object_id ][ $term -> taxonomy ][] = $term ;
2007-09-15 19:35:32 +02:00
2007-10-13 20:23:59 +02:00
foreach ( $ids as $id ) {
2012-01-11 22:26:18 +01:00
foreach ( $taxonomies as $taxonomy ) {
2007-10-23 22:33:50 +02:00
if ( ! isset ( $object_terms [ $id ][ $taxonomy ]) ) {
if ( ! isset ( $object_terms [ $id ]) )
$object_terms [ $id ] = array ();
$object_terms [ $id ][ $taxonomy ] = array ();
}
}
2007-09-15 19:35:32 +02:00
}
2007-10-13 20:23:59 +02:00
2007-10-23 22:33:50 +02:00
foreach ( $object_terms as $id => $value ) {
foreach ( $value as $taxonomy => $terms ) {
2012-01-11 22:26:18 +01:00
wp_cache_add ( $id , $terms , " { $taxonomy } _relationships " );
2007-10-23 22:33:50 +02:00
}
}
2007-09-15 19:35:32 +02:00
}
2007-10-21 19:18:24 +02:00
/**
2008-06-22 22:23:23 +02:00
* Updates Terms to Taxonomy in cache .
2007-10-21 19:18:24 +02:00
*
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2007-10-21 19:18:24 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param array $terms List of term objects to change .
* @ param string $taxonomy Optional . Update Term to this taxonomy in cache . Default empty .
2007-10-21 19:18:24 +02:00
*/
2015-05-07 22:37:41 +02:00
function update_term_cache ( $terms , $taxonomy = '' ) {
2008-08-06 22:31:54 +02:00
foreach ( ( array ) $terms as $term ) {
2007-09-15 19:35:32 +02:00
$term_taxonomy = $taxonomy ;
if ( empty ( $term_taxonomy ) )
$term_taxonomy = $term -> taxonomy ;
2014-12-16 14:27:22 +01:00
wp_cache_add ( $term -> term_id , $term , $term_taxonomy );
2007-09-15 19:35:32 +02:00
}
}
//
// Private
//
2007-10-21 19:18:24 +02:00
/**
2009-04-28 21:49:21 +02:00
* Retrieves children of taxonomy as Term IDs .
2007-10-21 19:18:24 +02:00
*
2015-05-07 22:37:41 +02:00
* @ ignore
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2007-10-21 19:18:24 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param string $taxonomy Taxonomy name .
2010-04-01 16:37:38 +02:00
* @ return array Empty if $taxonomy isn ' t hierarchical or returns children as Term IDs .
2007-10-21 19:18:24 +02:00
*/
2015-05-07 22:37:41 +02:00
function _get_term_hierarchy ( $taxonomy ) {
2007-09-15 19:35:32 +02:00
if ( ! is_taxonomy_hierarchical ( $taxonomy ) )
return array ();
2014-02-11 17:50:13 +01:00
$children = get_option ( " { $taxonomy } _children " );
2010-01-27 20:42:23 +01:00
2007-09-15 19:35:32 +02:00
if ( is_array ( $children ) )
return $children ;
$children = array ();
2010-01-15 18:40:37 +01:00
$terms = get_terms ( $taxonomy , array ( 'get' => 'all' , 'orderby' => 'id' , 'fields' => 'id=>parent' ));
foreach ( $terms as $term_id => $parent ) {
if ( $parent > 0 )
$children [ $parent ][] = $term_id ;
2007-09-15 19:35:32 +02:00
}
2010-01-27 20:42:23 +01:00
update_option ( " { $taxonomy } _children " , $children );
2007-09-15 19:35:32 +02:00
return $children ;
}
2007-10-16 00:49:31 +02:00
/**
2008-11-13 01:20:12 +01:00
* Get the subset of $terms that are descendants of $term_id .
2008-02-05 07:47:27 +01:00
*
2015-05-07 22:37:41 +02:00
* If `$terms` is an array of objects , then _get_term_children () returns an array of objects .
* If `$terms` is an array of IDs , then _get_term_children () returns an array of IDs .
2007-10-16 00:49:31 +02:00
*
2007-10-21 19:18:24 +02:00
* @ access private
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2007-10-16 00:49:31 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param int $term_id The ancestor term : all returned terms should be descendants of `$term_id` .
2015-01-16 18:10:22 +01:00
* @ 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 .
* @ param string $taxonomy The taxonomy which determines the hierarchy of the terms .
2015-05-07 22:37:41 +02:00
* @ param array $ancestors Optional . Term ancestors that have already been identified . Passed by reference , to keep
* track of found terms when recursing the hierarchy . The array of located ancestors is used
* to prevent infinite recursion loops . For performance , `term_ids` are used as array keys ,
* with 1 as value . Default empty array .
2008-12-09 19:03:31 +01:00
* @ return array The subset of $terms that are descendants of $term_id .
2007-10-16 00:49:31 +02:00
*/
2015-01-16 18:10:22 +01:00
function _get_term_children ( $term_id , $terms , $taxonomy , & $ancestors = array () ) {
2008-01-10 21:51:07 +01:00
$empty_array = array ();
2007-09-15 19:35:32 +02:00
if ( empty ( $terms ) )
2008-01-10 21:51:07 +01:00
return $empty_array ;
2007-09-15 19:35:32 +02:00
$term_list = array ();
$has_children = _get_term_hierarchy ( $taxonomy );
if ( ( 0 != $term_id ) && ! isset ( $has_children [ $term_id ]) )
2008-01-10 21:51:07 +01:00
return $empty_array ;
2007-09-15 19:35:32 +02:00
2015-01-16 18:10:22 +01:00
// Include the term itself in the ancestors array, so we can properly detect when a loop has occurred.
if ( empty ( $ancestors ) ) {
2015-04-29 14:56:25 +02:00
$ancestors [ $term_id ] = 1 ;
2015-01-16 18:10:22 +01:00
}
2008-08-06 22:31:54 +02:00
foreach ( ( array ) $terms as $term ) {
2007-09-15 19:35:32 +02:00
$use_id = false ;
if ( ! is_object ( $term ) ) {
$term = get_term ( $term , $taxonomy );
2007-09-18 18:32:22 +02:00
if ( is_wp_error ( $term ) )
return $term ;
2007-09-15 19:35:32 +02:00
$use_id = true ;
}
2015-01-16 18:10:22 +01:00
// Don't recurse if we've already identified the term as a child - this indicates a loop.
2015-04-29 14:56:25 +02:00
if ( isset ( $ancestors [ $term -> term_id ] ) ) {
2007-09-15 19:35:32 +02:00
continue ;
2014-02-06 18:45:12 +01:00
}
2007-09-15 19:35:32 +02:00
if ( $term -> parent == $term_id ) {
if ( $use_id )
$term_list [] = $term -> term_id ;
else
$term_list [] = $term ;
if ( ! isset ( $has_children [ $term -> term_id ]) )
continue ;
2015-04-29 14:58:24 +02:00
$ancestors [ $term -> term_id ] = 1 ;
2015-01-16 18:10:22 +01:00
if ( $children = _get_term_children ( $term -> term_id , $terms , $taxonomy , $ancestors ) )
2007-09-15 19:35:32 +02:00
$term_list = array_merge ( $term_list , $children );
}
}
return $term_list ;
}
2007-10-16 00:49:31 +02:00
/**
2008-06-22 22:23:23 +02:00
* Add count of children to parent count .
2008-02-05 07:47:27 +01:00
*
2008-06-22 22:23:23 +02:00
* Recalculates term counts by including items from child terms . Assumes all
* relevant children are already in the $terms argument .
2007-10-16 00:49:31 +02:00
*
2007-10-21 19:18:24 +02:00
* @ access private
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2014-10-31 18:56:22 +01:00
*
* @ global wpdb $wpdb WordPress database abstraction object .
2007-10-16 00:49:31 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param array $terms List of term IDs , passed by reference .
* @ param string $taxonomy Term context .
2007-10-21 19:18:24 +02:00
* @ return null Will break from function if conditions are not met .
2007-10-16 00:49:31 +02:00
*/
2015-05-07 22:37:41 +02:00
function _pad_term_counts ( & $terms , $taxonomy ) {
2007-09-23 02:35:59 +02:00
global $wpdb ;
2010-06-02 17:00:09 +02:00
2009-05-11 07:01:12 +02:00
// This function only works for hierarchical taxonomies like post categories.
if ( ! is_taxonomy_hierarchical ( $taxonomy ) )
2007-09-23 02:35:59 +02:00
return ;
2007-09-15 19:35:32 +02:00
$term_hier = _get_term_hierarchy ( $taxonomy );
if ( empty ( $term_hier ) )
return ;
2007-09-23 02:35:59 +02:00
$term_items = array ();
2014-12-20 23:47:22 +01:00
$terms_by_id = array ();
$term_ids = array ();
2007-09-23 02:35:59 +02:00
2008-08-06 22:31:54 +02:00
foreach ( ( array ) $terms as $key => $term ) {
2007-09-23 02:35:59 +02:00
$terms_by_id [ $term -> term_id ] = & $terms [ $key ];
$term_ids [ $term -> term_taxonomy_id ] = $term -> term_id ;
}
2015-05-07 22:37:41 +02:00
// Get the object and term ids and stick them in a lookup table.
2010-06-02 16:55:33 +02:00
$tax_obj = get_taxonomy ( $taxonomy );
$object_types = esc_sql ( $tax_obj -> object_type );
2010-06-02 22:04:07 +02:00
$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' " );
2007-09-23 02:35:59 +02:00
foreach ( $results as $row ) {
$id = $term_ids [ $row -> term_taxonomy_id ];
2008-11-11 00:03:34 +01:00
$term_items [ $id ][ $row -> object_id ] = isset ( $term_items [ $id ][ $row -> object_id ]) ? ++ $term_items [ $id ][ $row -> object_id ] : 1 ;
2007-09-23 02:35:59 +02:00
}
2008-12-09 19:03:31 +01:00
2015-05-07 22:37:41 +02:00
// Touch every ancestor's lookup row for each post in each term.
2007-09-23 02:35:59 +02:00
foreach ( $term_ids as $term_id ) {
$child = $term_id ;
2015-01-19 17:52:22 +01:00
$ancestors = array ();
2011-10-28 21:52:14 +02:00
while ( ! empty ( $terms_by_id [ $child ] ) && $parent = $terms_by_id [ $child ] -> parent ) {
2015-01-19 17:52:22 +01:00
$ancestors [] = $child ;
2011-10-28 21:52:14 +02:00
if ( ! empty ( $term_items [ $term_id ] ) )
2008-11-11 00:03:34 +01:00
foreach ( $term_items [ $term_id ] as $item_id => $touches ) {
$term_items [ $parent ][ $item_id ] = isset ( $term_items [ $parent ][ $item_id ]) ? ++ $term_items [ $parent ][ $item_id ] : 1 ;
}
2007-09-23 02:35:59 +02:00
$child = $parent ;
2015-01-19 17:52:22 +01:00
if ( in_array ( $parent , $ancestors ) ) {
break ;
}
2007-09-15 19:35:32 +02:00
}
}
2007-09-23 02:35:59 +02:00
2015-05-07 22:37:41 +02:00
// Transfer the touched cells.
2007-09-23 02:35:59 +02:00
foreach ( ( array ) $term_items as $id => $items )
if ( isset ( $terms_by_id [ $id ]) )
$terms_by_id [ $id ] -> count = count ( $items );
2007-09-15 19:35:32 +02:00
}
//
// Default callbacks
//
2007-10-16 00:49:31 +02:00
/**
2010-03-09 11:48:18 +01:00
* Will update term count based on object types of the current taxonomy .
2008-02-05 07:47:27 +01:00
*
2008-06-22 22:23:23 +02:00
* Private function for the default callback for post_tag and category
* taxonomies .
2007-10-16 00:49:31 +02:00
*
2007-10-21 19:18:24 +02:00
* @ access private
2008-08-30 23:23:43 +02:00
* @ since 2.3 . 0
2014-10-31 18:56:22 +01:00
*
* @ global wpdb $wpdb WordPress database abstraction object .
2007-10-16 00:49:31 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param array $terms List of Term taxonomy IDs .
* @ param object $taxonomy Current taxonomy object of terms .
2007-10-16 00:49:31 +02:00
*/
2010-03-09 11:48:18 +01:00
function _update_post_term_count ( $terms , $taxonomy ) {
2007-09-15 19:35:32 +02:00
global $wpdb ;
2011-10-21 23:38:14 +02:00
$object_types = ( array ) $taxonomy -> object_type ;
2011-10-24 21:13:23 +02:00
2011-10-10 22:52:44 +02:00
foreach ( $object_types as & $object_type )
list ( $object_type ) = explode ( ':' , $object_type );
2011-10-21 23:38:14 +02:00
2011-10-10 22:52:44 +02:00
$object_types = array_unique ( $object_types );
2011-10-21 23:38:14 +02:00
if ( false !== ( $check_attachments = array_search ( 'attachment' , $object_types ) ) ) {
unset ( $object_types [ $check_attachments ] );
$check_attachments = true ;
}
if ( $object_types )
$object_types = esc_sql ( array_filter ( $object_types , 'post_type_exists' ) );
2010-03-09 11:48:18 +01:00
2008-08-06 22:31:54 +02:00
foreach ( ( array ) $terms as $term ) {
2011-10-21 23:38:14 +02:00
$count = 0 ;
2011-10-10 22:52:44 +02:00
2015-05-07 22:37:41 +02:00
// Attachments can be 'inherit' status, we need to base count off the parent's status if so.
2011-10-21 23:38:14 +02:00
if ( $check_attachments )
$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 ) );
2011-10-10 22:52:44 +02:00
2011-10-21 23:38:14 +02:00
if ( $object_types )
$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 ) );
2014-03-28 22:29:13 +01:00
/** This action is documented in wp-includes/taxonomy.php */
2015-02-23 22:08:26 +01:00
do_action ( 'edit_term_taxonomy' , $term , $taxonomy -> name );
2007-10-13 20:23:59 +02:00
$wpdb -> update ( $wpdb -> term_taxonomy , compact ( 'count' ), array ( 'term_taxonomy_id' => $term ) );
2014-03-28 22:29:13 +01:00
/** This action is documented in wp-includes/taxonomy.php */
2015-02-23 22:08:26 +01:00
do_action ( 'edited_term_taxonomy' , $term , $taxonomy -> name );
2007-09-15 19:35:32 +02:00
}
}
2011-10-21 23:38:14 +02:00
/**
* Will update term count based on number of objects .
*
2015-05-07 22:37:41 +02:00
* Default callback for the 'link_category' taxonomy .
2011-10-21 23:38:14 +02:00
*
* @ since 3.3 . 0
2014-10-31 18:56:22 +01:00
*
* @ global wpdb $wpdb WordPress database abstraction object .
2011-10-21 23:38:14 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param array $terms List of term taxonomy IDs .
* @ param object $taxonomy Current taxonomy object of terms .
2011-10-21 23:38:14 +02:00
*/
function _update_generic_term_count ( $terms , $taxonomy ) {
global $wpdb ;
foreach ( ( array ) $terms as $term ) {
$count = $wpdb -> get_var ( $wpdb -> prepare ( " SELECT COUNT(*) FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d " , $term ) );
2014-03-28 22:29:13 +01:00
/** This action is documented in wp-includes/taxonomy.php */
2015-02-23 22:08:26 +01:00
do_action ( 'edit_term_taxonomy' , $term , $taxonomy -> name );
2011-10-21 23:38:14 +02:00
$wpdb -> update ( $wpdb -> term_taxonomy , compact ( 'count' ), array ( 'term_taxonomy_id' => $term ) );
2014-03-28 22:29:13 +01:00
/** This action is documented in wp-includes/taxonomy.php */
2015-02-23 22:08:26 +01:00
do_action ( 'edited_term_taxonomy' , $term , $taxonomy -> name );
2011-10-21 23:38:14 +02:00
}
}
2008-06-22 22:23:23 +02:00
2015-02-11 20:42:25 +01:00
/**
* Create a new term for a term_taxonomy item that currently shares its term with another term_taxonomy .
*
2015-04-05 19:08:26 +02:00
* @ ignore
2015-02-11 20:42:25 +01:00
* @ since 4.2 . 0
*
* @ param int $term_id ID of the shared term .
* @ param int $term_taxonomy_id ID of the term_taxonomy item to receive a new term .
2015-04-05 19:08:26 +02:00
* @ return int | WP_Error When the current term does not need to be split ( or cannot be split on the current
* database schema ), `$term_id` is returned . When the term is successfully split , the
* new term_id is returned . A WP_Error is returned for miscellaneous errors .
2015-02-11 20:42:25 +01:00
*/
function _split_shared_term ( $term_id , $term_taxonomy_id ) {
global $wpdb ;
// Don't try to split terms if database schema does not support shared slugs.
$current_db_version = get_option ( 'db_version' );
if ( $current_db_version < 30133 ) {
return $term_id ;
}
// If there are no shared term_taxonomy rows, there's nothing to do here.
$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 ) );
if ( ! $shared_tt_count ) {
return $term_id ;
}
// Pull up data about the currently shared slug, which we'll use to populate the new one.
$shared_term = $wpdb -> get_row ( $wpdb -> prepare ( " SELECT t.* FROM $wpdb->terms t WHERE t.term_id = %d " , $term_id ) );
$new_term_data = array (
'name' => $shared_term -> name ,
'slug' => $shared_term -> slug ,
'term_group' => $shared_term -> term_group ,
);
if ( false === $wpdb -> insert ( $wpdb -> terms , $new_term_data ) ) {
return new WP_Error ( 'db_insert_error' , __ ( 'Could not split shared term.' ), $wpdb -> last_error );
}
$new_term_id = ( int ) $wpdb -> insert_id ;
// Update the existing term_taxonomy to point to the newly created term.
$wpdb -> update ( $wpdb -> term_taxonomy ,
array ( 'term_id' => $new_term_id ),
array ( 'term_taxonomy_id' => $term_taxonomy_id )
);
// Reassign child terms to the new parent.
$term_taxonomy = $wpdb -> get_row ( $wpdb -> prepare ( " SELECT * FROM $wpdb->term_taxonomy WHERE term_taxonomy_id = %d " , $term_taxonomy_id ) );
$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 ) );
if ( ! empty ( $children_tt_ids ) ) {
foreach ( $children_tt_ids as $child_tt_id ) {
$wpdb -> update ( $wpdb -> term_taxonomy ,
array ( 'parent' => $new_term_id ),
array ( 'term_taxonomy_id' => $child_tt_id )
);
clean_term_cache ( $term_id , $term_taxonomy -> taxonomy );
}
} else {
// If the term has no children, we must force its taxonomy cache to be rebuilt separately.
clean_term_cache ( $new_term_id , $term_taxonomy -> taxonomy );
}
// Clean the cache for term taxonomies formerly shared with the current term.
$shared_term_taxonomies = $wpdb -> get_row ( $wpdb -> prepare ( " SELECT taxonomy FROM $wpdb->term_taxonomy WHERE term_id = %d " , $term_id ) );
if ( $shared_term_taxonomies ) {
foreach ( $shared_term_taxonomies as $shared_term_taxonomy ) {
clean_term_cache ( $term_id , $shared_term_taxonomy );
}
}
// Keep a record of term_ids that have been split, keyed by old term_id. See {@see wp_get_split_term()}.
$split_term_data = get_option ( '_split_terms' , array () );
if ( ! isset ( $split_term_data [ $term_id ] ) ) {
$split_term_data [ $term_id ] = array ();
}
$split_term_data [ $term_id ][ $term_taxonomy -> taxonomy ] = $new_term_id ;
update_option ( '_split_terms' , $split_term_data );
/**
* Fires after a previously shared taxonomy term is split into two separate terms .
*
* @ since 4.2 . 0
*
* @ param int $term_id ID of the formerly shared term .
* @ param int $new_term_id ID of the new term created for the $term_taxonomy_id .
* @ param int $term_taxonomy_id ID for the term_taxonomy row affected by the split .
* @ param string $taxonomy Taxonomy for the split term .
*/
do_action ( 'split_shared_term' , $term_id , $new_term_id , $term_taxonomy_id , $term_taxonomy -> taxonomy );
return $new_term_id ;
}
/**
* Check default categories when a term gets split to see if any of them need to be updated .
*
2015-04-05 19:08:26 +02:00
* @ ignore
2015-02-11 20:42:25 +01:00
* @ since 4.2 . 0
*
* @ param int $term_id ID of the formerly shared term .
* @ param int $new_term_id ID of the new term created for the $term_taxonomy_id .
* @ param int $term_taxonomy_id ID for the term_taxonomy row affected by the split .
* @ param string $taxonomy Taxonomy for the split term .
*/
function _wp_check_split_default_terms ( $term_id , $new_term_id , $term_taxonomy_id , $taxonomy ) {
if ( 'category' != $taxonomy ) {
return ;
}
foreach ( array ( 'default_category' , 'default_link_category' , 'default_email_category' ) as $option ) {
if ( $term_id == get_option ( $option , - 1 ) ) {
update_option ( $option , $new_term_id );
}
}
}
/**
* Check menu items when a term gets split to see if any of them need to be updated .
*
2015-04-05 19:08:26 +02:00
* @ ignore
2015-02-11 20:42:25 +01:00
* @ since 4.2 . 0
*
* @ param int $term_id ID of the formerly shared term .
* @ param int $new_term_id ID of the new term created for the $term_taxonomy_id .
* @ param int $term_taxonomy_id ID for the term_taxonomy row affected by the split .
* @ param string $taxonomy Taxonomy for the split term .
*/
function _wp_check_split_terms_in_menus ( $term_id , $new_term_id , $term_taxonomy_id , $taxonomy ) {
global $wpdb ;
$post_ids = $wpdb -> get_col ( $wpdb -> prepare (
" SELECT m1.post_id
FROM { $wpdb -> postmeta } AS m1
INNER JOIN { $wpdb -> postmeta } AS m2 ON ( m2 . post_id = m1 . post_id )
INNER JOIN { $wpdb -> postmeta } AS m3 ON ( m3 . post_id = m1 . post_id )
WHERE ( m1 . meta_key = '_menu_item_type' AND m1 . meta_value = 'taxonomy' )
AND ( m2 . meta_key = '_menu_item_object' AND m2 . meta_value = '%s' )
AND ( m3 . meta_key = '_menu_item_object_id' AND m3 . meta_value = % d ) " ,
$taxonomy ,
$term_id
) );
if ( $post_ids ) {
foreach ( $post_ids as $post_id ) {
update_post_meta ( $post_id , '_menu_item_object_id' , $new_term_id , $term_id );
}
}
}
/**
* Get data about terms that previously shared a single term_id , but have since been split .
*
* @ since 4.2 . 0
*
* @ param int $old_term_id Term ID . This is the old , pre - split term ID .
* @ return array Array of new term IDs , keyed by taxonomy .
*/
function wp_get_split_terms ( $old_term_id ) {
$split_terms = get_option ( '_split_terms' , array () );
$terms = array ();
if ( isset ( $split_terms [ $old_term_id ] ) ) {
$terms = $split_terms [ $old_term_id ];
}
return $terms ;
}
/**
* Get the new term ID corresponding to a previously split term .
*
* @ since 4.2 . 0
*
* @ param int $old_term_id Term ID . This is the old , pre - split term ID .
* @ param string $taxonomy Taxonomy that the term belongs to .
2015-04-05 19:08:26 +02:00
* @ return bool | int If a previously split term is found corresponding to the old term_id and taxonomy ,
* the new term_id will be returned . If no previously split term is found matching
* the parameters , returns false .
2015-02-11 20:42:25 +01:00
*/
function wp_get_split_term ( $old_term_id , $taxonomy ) {
$split_terms = wp_get_split_terms ( $old_term_id );
$term_id = false ;
if ( isset ( $split_terms [ $taxonomy ] ) ) {
$term_id = ( int ) $split_terms [ $taxonomy ];
}
return $term_id ;
}
2008-03-26 07:37:19 +01:00
/**
2014-10-09 17:41:18 +02:00
* Generate a permalink for a taxonomy term archive .
2008-06-22 22:23:23 +02:00
*
2008-08-30 23:23:43 +02:00
* @ since 2.5 . 0
2015-05-23 20:29:26 +02:00
* @ since 4.3 . 0 Introduced `$field` argument .
2008-03-26 07:37:19 +01:00
*
2014-10-09 17:41:18 +02:00
* @ param object | int | string $term The term object , ID , or slug whose link will be retrieved .
* @ param string $taxonomy Optional . Taxonomy . Default empty .
2015-05-23 20:29:26 +02:00
* @ param string $field Optional . The term field that should be matched by the `$term` argument . Accepts
* any `$field` values accepted by `get_term_by()` : 'slug' , 'name' ,
* 'term_taxonomy_id' , or 'id' . Default is 'slug' , unless `$term` is an integer , in
* which case it ' s asssumed to be an ID .
2011-02-10 22:48:40 +01:00
* @ return string | WP_Error HTML link to taxonomy term archive on success , WP_Error if term does not exist .
2008-03-26 07:37:19 +01:00
*/
2015-05-23 20:29:26 +02:00
function get_term_link ( $term , $taxonomy = '' , $field = null ) {
2008-03-26 07:37:19 +01:00
global $wp_rewrite ;
2009-05-14 06:09:01 +02:00
if ( ! is_object ( $term ) ) {
2015-05-23 20:29:26 +02:00
if ( is_null ( $field ) ) {
$field = is_int ( $term ) ? 'id' : 'slug' ;
2009-05-14 06:09:01 +02:00
}
2015-05-23 20:29:26 +02:00
$term = get_term_by ( $field , $term , $taxonomy );
2009-05-14 06:09:01 +02:00
}
2010-02-16 10:08:26 +01:00
if ( ! is_object ( $term ) )
$term = new WP_Error ( 'invalid_term' , __ ( 'Empty Term' ));
2009-05-14 06:09:01 +02:00
if ( is_wp_error ( $term ) )
2011-02-10 22:48:40 +01:00
return $term ;
2008-03-26 07:37:19 +01:00
2010-09-07 06:29:00 +02:00
$taxonomy = $term -> taxonomy ;
2009-05-11 06:45:39 +02:00
$termlink = $wp_rewrite -> get_extra_permastruct ( $taxonomy );
2008-03-26 07:37:19 +01:00
$slug = $term -> slug ;
2010-10-04 12:37:25 +02:00
$t = get_taxonomy ( $taxonomy );
2008-03-26 07:37:19 +01:00
if ( empty ( $termlink ) ) {
2011-03-02 18:29:11 +01:00
if ( 'category' == $taxonomy )
$termlink = '?cat=' . $term -> term_id ;
elseif ( $t -> query_var )
2010-01-04 18:23:29 +01:00
$termlink = " ? $t->query_var = $slug " ;
2008-03-26 07:37:19 +01:00
else
2010-01-04 18:23:29 +01:00
$termlink = " ?taxonomy= $taxonomy &term= $slug " ;
$termlink = home_url ( $termlink );
2008-03-26 07:37:19 +01:00
} else {
2010-10-17 06:36:26 +02:00
if ( $t -> rewrite [ 'hierarchical' ] ) {
2010-10-04 12:37:25 +02:00
$hierarchical_slugs = array ();
2014-11-01 03:58:23 +01:00
$ancestors = get_ancestors ( $term -> term_id , $taxonomy , 'taxonomy' );
2010-10-04 12:37:25 +02:00
foreach ( ( array ) $ancestors as $ancestor ) {
$ancestor_term = get_term ( $ancestor , $taxonomy );
$hierarchical_slugs [] = $ancestor_term -> slug ;
}
$hierarchical_slugs = array_reverse ( $hierarchical_slugs );
$hierarchical_slugs [] = $slug ;
$termlink = str_replace ( " % $taxonomy % " , implode ( '/' , $hierarchical_slugs ), $termlink );
} else {
$termlink = str_replace ( " % $taxonomy % " , $slug , $termlink );
}
2010-01-04 18:23:29 +01:00
$termlink = home_url ( user_trailingslashit ( $termlink , 'category' ) );
2008-03-26 07:37:19 +01:00
}
2010-10-17 07:41:22 +02:00
// Back Compat filters.
2014-03-28 22:29:13 +01:00
if ( 'post_tag' == $taxonomy ) {
/**
* Filter the tag link .
*
* @ since 2.3 . 0
* @ deprecated 2.5 . 0 Use 'term_link' instead .
*
* @ param string $termlink Tag link URL .
* @ param int $term_id Term ID .
*/
2010-10-17 07:41:22 +02:00
$termlink = apply_filters ( 'tag_link' , $termlink , $term -> term_id );
2014-03-28 22:29:13 +01:00
} elseif ( 'category' == $taxonomy ) {
/**
* Filter the category link .
*
* @ since 1.5 . 0
* @ deprecated 2.5 . 0 Use 'term_link' instead .
*
* @ param string $termlink Category link URL .
* @ param int $term_id Term ID .
*/
2010-10-17 07:41:22 +02:00
$termlink = apply_filters ( 'category_link' , $termlink , $term -> term_id );
2014-03-28 22:29:13 +01:00
}
2010-10-17 07:41:22 +02:00
2014-03-28 22:29:13 +01:00
/**
* Filter the term link .
*
* @ since 2.5 . 0
*
* @ param string $termlink Term link URL .
* @ param object $term Term object .
* @ param string $taxonomy Taxonomy slug .
*/
return apply_filters ( 'term_link' , $termlink , $term , $taxonomy );
2008-03-26 07:37:19 +01:00
}
2008-06-22 22:23:23 +02:00
/**
* Display the taxonomies of a post with available options .
*
* This function can be used within the loop to display the taxonomies for a
* post without specifying the Post ID . You can also use it outside the Loop to
* display the taxonomies for a specific post .
*
2008-08-30 23:23:43 +02:00
* @ since 2.5 . 0
2008-06-22 22:23:23 +02:00
*
2014-11-03 19:49:24 +01:00
* @ param array $args {
2015-05-07 22:37:41 +02:00
* Arguments about which post to use and how to format the output . Shares all of the arguments
* supported by get_the_taxonomies (), in addition to the following .
2014-11-03 19:49:45 +01:00
*
* @ type int | WP_Post $post Post ID or object to get taxonomies of . Default current post .
* @ type string $before Displays before the taxonomies . Default empty string .
* @ type string $sep Separates each taxonomy . Default is a space .
* @ type string $after Displays after the taxonomies . Default empty string .
2014-11-03 19:49:24 +01:00
* }
2014-11-03 19:49:45 +01:00
* @ param array $args See { @ link get_the_taxonomies ()} for a description of arguments and their defaults .
2008-06-22 22:23:23 +02:00
*/
2014-05-15 07:25:14 +02:00
function the_taxonomies ( $args = array () ) {
2008-03-26 07:37:19 +01:00
$defaults = array (
'post' => 0 ,
'before' => '' ,
'sep' => ' ' ,
'after' => '' ,
);
$r = wp_parse_args ( $args , $defaults );
2014-05-15 07:25:14 +02:00
echo $r [ 'before' ] . join ( $r [ 'sep' ], get_the_taxonomies ( $r [ 'post' ], $r ) ) . $r [ 'after' ];
2008-03-26 07:37:19 +01:00
}
2008-06-22 22:23:23 +02:00
/**
* Retrieve all taxonomies associated with a post .
*
* This function can be used within the loop . It will also return an array of
* the taxonomies with links to the taxonomy and name .
*
2008-08-30 23:23:43 +02:00
* @ since 2.5 . 0
2008-06-22 22:23:23 +02:00
*
2014-07-03 21:28:14 +02:00
* @ param int | WP_Post $post Optional . Post ID or WP_Post object . Default is global $post .
2014-11-03 19:49:45 +01:00
* @ param array $args {
2015-05-07 22:37:41 +02:00
* Optional . Arguments about how to format the list of taxonomies . Default empty array .
2014-11-03 19:49:45 +01:00
*
* @ type string $template Template for displaying a taxonomy label and list of terms .
* Default is " Label: Terms. "
* @ type string $term_template Template for displaying a single term in the list . Default is the term name
* linked to its archive .
* }
2014-06-03 05:53:17 +02:00
* @ return array List of taxonomies .
2008-06-22 22:23:23 +02:00
*/
2014-05-15 05:51:13 +02:00
function get_the_taxonomies ( $post = 0 , $args = array () ) {
2012-08-23 22:01:10 +02:00
$post = get_post ( $post );
2008-03-26 07:37:19 +01:00
2010-12-17 17:33:16 +01:00
$args = wp_parse_args ( $args , array (
2014-11-03 19:49:24 +01:00
/* translators: %s: taxonomy label, %l: list of terms formatted as per $term_template */
2014-07-02 15:21:16 +02:00
'template' => __ ( '%s: %l.' ),
2014-11-03 19:49:24 +01:00
'term_template' => '<a href="%1$s">%2$s</a>' ,
2011-01-06 05:11:14 +01:00
) );
2010-12-17 17:33:16 +01:00
2008-03-26 07:37:19 +01:00
$taxonomies = array ();
2014-05-15 05:51:13 +02:00
if ( ! $post ) {
2008-03-26 07:37:19 +01:00
return $taxonomies ;
2014-05-15 05:51:13 +02:00
}
2008-03-26 07:37:19 +01:00
2014-05-15 05:51:13 +02:00
foreach ( get_object_taxonomies ( $post ) as $taxonomy ) {
$t = ( array ) get_taxonomy ( $taxonomy );
if ( empty ( $t [ 'label' ] ) ) {
2008-03-26 07:37:19 +01:00
$t [ 'label' ] = $taxonomy ;
2014-05-15 05:51:13 +02:00
}
if ( empty ( $t [ 'args' ] ) ) {
2008-03-26 07:37:19 +01:00
$t [ 'args' ] = array ();
2014-05-15 05:51:13 +02:00
}
if ( empty ( $t [ 'template' ] ) ) {
$t [ 'template' ] = $args [ 'template' ];
}
2014-11-03 19:49:24 +01:00
if ( empty ( $t [ 'term_template' ] ) ) {
$t [ 'term_template' ] = $args [ 'term_template' ];
}
2008-03-26 07:37:19 +01:00
2014-05-15 05:51:13 +02:00
$terms = get_object_term_cache ( $post -> ID , $taxonomy );
if ( false === $terms ) {
$terms = wp_get_object_terms ( $post -> ID , $taxonomy , $t [ 'args' ] );
}
2008-03-26 07:37:19 +01:00
$links = array ();
2014-05-15 05:51:13 +02:00
foreach ( $terms as $term ) {
2014-11-03 19:49:24 +01:00
$links [] = wp_sprintf ( $t [ 'term_template' ], esc_attr ( get_term_link ( $term ) ), $term -> name );
2014-05-15 05:51:13 +02:00
}
if ( $links ) {
$taxonomies [ $taxonomy ] = wp_sprintf ( $t [ 'template' ], $t [ 'label' ], $links , $terms );
}
2008-03-26 07:37:19 +01:00
}
return $taxonomies ;
}
2008-06-22 22:23:23 +02:00
/**
* Retrieve all taxonomies of a post with just the names .
*
2008-08-30 23:23:43 +02:00
* @ since 2.5 . 0
2014-06-03 05:53:17 +02:00
*
2014-07-03 21:28:14 +02:00
* @ param int | WP_Post $post Optional . Post ID or WP_Post object . Default is global $post .
2008-06-22 22:23:23 +02:00
* @ return array
*/
2014-06-03 05:53:17 +02:00
function get_post_taxonomies ( $post = 0 ) {
2012-08-23 22:01:10 +02:00
$post = get_post ( $post );
2008-03-26 07:37:19 +01:00
return get_object_taxonomies ( $post );
}
2008-12-10 00:31:11 +01:00
/**
* Determine if the given object is associated with any of the given terms .
*
* The given terms are checked against the object 's terms' term_ids , names and slugs .
* Terms given as integers will only be checked against the object 's terms' term_ids .
* If no terms are given , determines if object is associated with any terms in the given taxonomy .
*
* @ since 2.7 . 0
*
2015-05-07 22:37:41 +02:00
* @ param int $object_id ID of the object ( post ID , link ID , ... ) .
* @ param string $taxonomy Single taxonomy name .
* @ param int | string | array $terms Optional . Term term_id , name , slug or array of said . Default null .
2015-01-16 23:44:25 +01:00
* @ return bool | WP_Error WP_Error on input error .
2008-12-10 00:31:11 +01:00
*/
function is_object_in_term ( $object_id , $taxonomy , $terms = null ) {
if ( ! $object_id = ( int ) $object_id )
return new WP_Error ( 'invalid_object' , __ ( 'Invalid object ID' ) );
$object_terms = get_object_term_cache ( $object_id , $taxonomy );
2012-11-09 01:16:30 +01:00
if ( false === $object_terms )
2008-12-10 00:31:11 +01:00
$object_terms = wp_get_object_terms ( $object_id , $taxonomy );
if ( is_wp_error ( $object_terms ) )
return $object_terms ;
if ( empty ( $object_terms ) )
return false ;
if ( empty ( $terms ) )
return ( ! empty ( $object_terms ) );
$terms = ( array ) $terms ;
if ( $ints = array_filter ( $terms , 'is_int' ) )
$strs = array_diff ( $terms , $ints );
else
$strs =& $terms ;
foreach ( $object_terms as $object_term ) {
2014-11-03 15:25:44 +01:00
// If term is an int, check against term_ids only.
if ( $ints && in_array ( $object_term -> term_id , $ints ) ) {
return true ;
}
2008-12-10 00:31:11 +01:00
if ( $strs ) {
2014-11-03 15:25:44 +01:00
// Only check numeric strings against term_id, to avoid false matches due to type juggling.
$numeric_strs = array_map ( 'intval' , array_filter ( $strs , 'is_numeric' ) );
if ( in_array ( $object_term -> term_id , $numeric_strs , true ) ) {
return true ;
}
if ( in_array ( $object_term -> name , $strs ) ) return true ;
if ( in_array ( $object_term -> slug , $strs ) ) return true ;
2008-12-10 00:31:11 +01:00
}
}
return false ;
}
2010-01-04 17:58:43 +01:00
/**
* Determine if the given object type is associated with the given taxonomy .
*
2010-03-26 20:13:36 +01:00
* @ since 3.0 . 0
2010-01-04 17:58:43 +01:00
*
2015-05-07 22:37:41 +02:00
* @ param string $object_type Object type string .
* @ param string $taxonomy Single taxonomy name .
2010-01-04 17:58:43 +01:00
* @ return bool True if object is associated with the taxonomy , otherwise false .
*/
function is_object_in_taxonomy ( $object_type , $taxonomy ) {
$taxonomies = get_object_taxonomies ( $object_type );
if ( empty ( $taxonomies ) )
return false ;
if ( in_array ( $taxonomy , $taxonomies ) )
return true ;
return false ;
}
2010-10-19 09:48:22 +02:00
2010-09-18 21:20:16 +02:00
/**
* Get an array of ancestor IDs for a given object .
*
2014-11-01 03:58:23 +01:00
* @ since 3.1 . 0
2014-11-28 13:26:24 +01:00
* @ since 4.1 . 0 Introduced the `$resource_type` argument .
2014-11-01 03:58:23 +01:00
*
2014-11-28 13:26:24 +01:00
* @ param int $object_id Optional . The ID of the object . Default 0.
* @ param string $object_type Optional . The type of object for which we ' ll be retrieving
* ancestors . Accepts a post type or a taxonomy name . Default empty .
* @ param string $resource_type Optional . Type of resource $object_type is . Accepts 'post_type'
* or 'taxonomy' . Default empty .
2014-11-01 03:58:23 +01:00
* @ return array An array of ancestors from lowest to highest in the hierarchy .
2010-09-18 21:20:16 +02:00
*/
2014-11-01 03:58:23 +01:00
function get_ancestors ( $object_id = 0 , $object_type = '' , $resource_type = '' ) {
2010-09-18 21:20:16 +02:00
$object_id = ( int ) $object_id ;
2010-10-19 09:48:22 +02:00
2010-09-18 21:20:16 +02:00
$ancestors = array ();
if ( empty ( $object_id ) ) {
2014-03-28 22:29:13 +01:00
/** This filter is documented in wp-includes/taxonomy.php */
2014-11-01 03:58:23 +01:00
return apply_filters ( 'get_ancestors' , $ancestors , $object_id , $object_type , $resource_type );
}
if ( ! $resource_type ) {
if ( is_taxonomy_hierarchical ( $object_type ) ) {
$resource_type = 'taxonomy' ;
2015-01-08 07:26:23 +01:00
} elseif ( post_type_exists ( $object_type ) ) {
2014-11-01 03:58:23 +01:00
$resource_type = 'post_type' ;
}
2010-09-18 21:20:16 +02:00
}
2010-10-21 21:55:28 +02:00
2014-11-01 03:58:23 +01:00
if ( 'taxonomy' === $resource_type ) {
2010-09-18 21:20:16 +02:00
$term = get_term ( $object_id , $object_type );
while ( ! is_wp_error ( $term ) && ! empty ( $term -> parent ) && ! in_array ( $term -> parent , $ancestors ) ) {
$ancestors [] = ( int ) $term -> parent ;
$term = get_term ( $term -> parent , $object_type );
}
2014-11-01 03:58:23 +01:00
} elseif ( 'post_type' === $resource_type ) {
2012-08-20 21:47:52 +02:00
$ancestors = get_post_ancestors ( $object_id );
2010-09-18 21:20:16 +02:00
}
2014-03-28 22:29:13 +01:00
/**
* Filter a given object ' s ancestors .
*
* @ since 3.1 . 0
2015-05-05 04:17:25 +02:00
* @ since 4.1 . 1 Introduced the `$resource_type` parameter .
2014-03-28 22:29:13 +01:00
*
2014-11-01 03:58:23 +01:00
* @ param array $ancestors An array of object ancestors .
* @ param int $object_id Object ID .
* @ param string $object_type Type of object .
* @ param string $resource_type Type of resource $object_type is .
2014-03-28 22:29:13 +01:00
*/
2014-12-26 22:29:22 +01:00
return apply_filters ( 'get_ancestors' , $ancestors , $object_id , $object_type , $resource_type );
2010-09-18 21:20:16 +02:00
}
2010-10-03 04:58:59 +02:00
2010-10-14 17:09:04 +02:00
/**
2015-05-07 22:37:41 +02:00
* Returns the term 's parent' s term_ID .
2010-10-14 17:09:04 +02:00
*
2010-10-19 09:38:42 +02:00
* @ since 3.1 . 0
2010-10-14 17:09:04 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param int $term_id Term ID .
* @ param string $taxonomy Taxonomy name .
* @ return int | bool False on error .
2010-10-14 17:09:04 +02:00
*/
function wp_get_term_taxonomy_parent_id ( $term_id , $taxonomy ) {
$term = get_term ( $term_id , $taxonomy );
if ( ! $term || is_wp_error ( $term ) )
return false ;
return ( int ) $term -> parent ;
}
/**
* Checks the given subset of the term hierarchy for hierarchy loops .
* Prevents loops from forming and breaks those that it finds .
*
2015-05-07 22:37:41 +02:00
* Attached to the { @ see 'wp_update_term_parent' } filter .
2010-10-14 17:09:04 +02:00
*
2010-10-19 09:38:42 +02:00
* @ since 3.1 . 0
2010-10-14 17:09:04 +02:00
*
2015-05-07 22:37:41 +02:00
* @ param int $parent `term_id` of the parent for the term we ' re checking .
* @ param int $term_id The term we ' re checking .
2010-10-14 17:09:04 +02:00
* @ param string $taxonomy The taxonomy of the term we ' re checking .
*
* @ return int The new parent for the term .
*/
function wp_check_term_hierarchy_for_loops ( $parent , $term_id , $taxonomy ) {
// Nothing fancy here - bail
if ( ! $parent )
return 0 ;
2015-05-07 22:37:41 +02:00
// Can't be its own parent.
2010-10-14 17:09:04 +02:00
if ( $parent == $term_id )
return 0 ;
2015-05-07 22:37:41 +02:00
// Now look for larger loops.
2010-10-14 17:09:04 +02:00
if ( ! $loop = wp_find_hierarchy_loop ( 'wp_get_term_taxonomy_parent_id' , $term_id , $parent , array ( $taxonomy ) ) )
return $parent ; // No loop
2015-05-07 22:37:41 +02:00
// Setting $parent to the given value causes a loop.
2010-10-14 17:09:04 +02:00
if ( isset ( $loop [ $term_id ] ) )
return 0 ;
2011-12-14 00:45:31 +01:00
// There's a loop, but it doesn't contain $term_id. Break the loop.
2010-10-14 17:09:04 +02:00
foreach ( array_keys ( $loop ) as $loop_member )
wp_update_term ( $loop_member , $taxonomy , array ( 'parent' => 0 ) );
return $parent ;
2014-05-29 19:53:15 +02:00
}