WP_Taxonomy

Core class used for interacting with taxonomies.

Defined (1)

The class is defined in the following location(s).

/bp-forums/bbpress/bb-includes/backpress/class.wp-taxonomy.php  
  1. class WP_Taxonomy { 
  2. /** 
  3. * Stores the database. 
  4. * @var unknown_type 
  5. */ 
  6. var $db; 
  7. var $taxonomies = array(); 
  8.  
  9. function WP_Taxonomy( &$db ) { 
  10. $this->__construct( $db ); 
  11. register_shutdown_function( array(&$this, '__destruct') ); 
  12.  
  13. /** 
  14. * PHP5 constructor - Assigns the database to an attribute of the class. 
  15. * @param unknown_type $db 
  16. */ 
  17. function __construct( &$db ) { 
  18. $this->db =& $db; 
  19.  
  20. /** 
  21. * Does nothing. 
  22. * @package BackPress 
  23. * @subpackage Taxonomy 
  24. */ 
  25. function __destruct() { 
  26.  
  27. /** 
  28. * Return all of the taxonomy names that are of $object_type. 
  29. * It appears that this function can be used to find all of the names inside of 
  30. * $this->taxonomies variable. 
  31. * <code><?php $taxonomies = $this->get_object_taxonomies('post'); ?></code> Should 
  32. * result in <code>Array('category', 'post_tag')</code> 
  33. * @package WordPress 
  34. * @subpackage Taxonomy 
  35. * @since 2.3.0 
  36. * @uses $this->taxonomies 
  37. * @param array|string|object $object_type Name of the type of taxonomy object, or an object (row from posts) 
  38. * @return array The names of all taxonomy of $object_type. 
  39. */ 
  40. function get_object_taxonomies($object_type) { 
  41. $object_type = (array) $object_type; 
  42.  
  43. // WP DIFF 
  44. $taxonomies = array(); 
  45. foreach ( (array) $this->taxonomies as $taxonomy ) { 
  46. if ( array_intersect($object_type, (array) $taxonomy->object_type) ) 
  47. $taxonomies[] = $taxonomy->name; 
  48.  
  49. return $taxonomies; 
  50.  
  51. /** 
  52. * Retrieves the taxonomy object of $taxonomy. 
  53. * The get_taxonomy function will first check that the parameter string given 
  54. * is a taxonomy object and if it is, it will return it. 
  55. * @package WordPress 
  56. * @subpackage Taxonomy 
  57. * @since 2.3.0 
  58. * @uses $this->taxonomies 
  59. * @uses $this->is_taxonomy() Checks whether taxonomy exists 
  60. * @param string $taxonomy Name of taxonomy object to return 
  61. * @return object|bool The Taxonomy Object or false if $taxonomy doesn't exist 
  62. */ 
  63. function get_taxonomy( $taxonomy ) { 
  64. if ( !$this->is_taxonomy($taxonomy) ) 
  65. return false; 
  66.  
  67. return $this->taxonomies[$taxonomy]; 
  68.  
  69. /** 
  70. * Checks that the taxonomy name exists. 
  71. * @package WordPress 
  72. * @subpackage Taxonomy 
  73. * @since 2.3.0 
  74. *  
  75. * @uses $this->taxonomies 
  76. * @param string $taxonomy Name of taxonomy object 
  77. * @return bool Whether the taxonomy exists or not. 
  78. */ 
  79. function is_taxonomy( $taxonomy ) { 
  80. return isset($this->taxonomies[$taxonomy]); 
  81.  
  82. /** 
  83. * Whether the taxonomy object is hierarchical. 
  84. * Checks to make sure that the taxonomy is an object first. Then Gets the 
  85. * object, and finally returns the hierarchical value in the object. 
  86. * A false return value might also mean that the taxonomy does not exist. 
  87. * @package WordPress 
  88. * @subpackage Taxonomy 
  89. * @since 2.3.0 
  90. * @uses $this->is_taxonomy() Checks whether taxonomy exists 
  91. * @uses $this->get_taxonomy() Used to get the taxonomy object 
  92. * @param string $taxonomy Name of taxonomy object 
  93. * @return bool Whether the taxonomy is hierarchical 
  94. */ 
  95. function is_taxonomy_hierarchical($taxonomy) { 
  96. if ( !$this->is_taxonomy($taxonomy) ) 
  97. return false; 
  98.  
  99. $taxonomy = $this->get_taxonomy($taxonomy); 
  100. return $taxonomy->hierarchical; 
  101.  
  102. /** 
  103. * Create or modify a taxonomy object. Do not use before init. 
  104. * A simple function for creating or modifying a taxonomy object based on the 
  105. * parameters given. The function will accept an array (third optional 
  106. * parameter), along with strings for the taxonomy name and another string for 
  107. * the object type. 
  108. * The function keeps a default set, allowing for the $args to be optional but 
  109. * allow the other functions to still work. It is possible to overwrite the 
  110. * default set, which contains two keys: hierarchical and update_count_callback. 
  111. * Nothing is returned, so expect error maybe or use is_taxonomy() to check 
  112. * whether taxonomy exists. 
  113. * Optional $args contents: 
  114. * hierarachical - has some defined purpose at other parts of the API and is a 
  115. * boolean value. 
  116. * update_count_callback - works much like a hook, in that it will be called 
  117. * when the count is updated. 
  118. * @package WordPress 
  119. * @subpackage Taxonomy 
  120. * @since 2.3.0 
  121. * @uses $this->taxonomies Inserts new taxonomy object into the list 
  122. *  
  123. * @param string $taxonomy Name of taxonomy object 
  124. * @param string $object_type Name of the object type for the taxonomy object. 
  125. * @param array|string $args See above description for the two keys values. 
  126. */ 
  127. function register_taxonomy( $taxonomy, $object_type, $args = array() ) { 
  128. $defaults = array('hierarchical' => false, 'update_count_callback' => ''); 
  129. $args = wp_parse_args($args, $defaults); 
  130.  
  131. $args['name'] = $taxonomy; 
  132. $args['object_type'] = $object_type; 
  133. $this->taxonomies[$taxonomy] = (object) $args; 
  134.  
  135. // 
  136. // Term API 
  137. // 
  138.   
  139. /** 
  140. * Retrieve object_ids of valid taxonomy and term. 
  141. * The strings of $taxonomies must exist before this function will continue. On 
  142. * failure of finding a valid taxonomy, it will return an WP_Error class, kind 
  143. * of like Exceptions in PHP 5, except you can't catch them. Even so, you can 
  144. * still test for the WP_Error class and get the error message. 
  145. * The $terms aren't checked the same as $taxonomies, but still need to exist 
  146. * for $object_ids to be returned. 
  147. * It is possible to change the order that object_ids is returned by either 
  148. * using PHP sort family functions or using the database by using $args with 
  149. * either ASC or DESC array. The value should be in the key named 'order'. 
  150. * @package WordPress 
  151. * @subpackage Taxonomy 
  152. * @since 2.3.0 
  153. * @uses wp_parse_args() Creates an array from string $args. 
  154. * @param string|array $terms String of term or array of string values of terms that will be used 
  155. * @param string|array $taxonomies String of taxonomy name or Array of string values of taxonomy names 
  156. * @param array|string $args Change the order of the object_ids, either ASC or DESC 
  157. * @return WP_Error|array If the taxonomy does not exist, then WP_Error will be returned. On success 
  158. * the array can be empty meaning that there are no $object_ids found or it will return the $object_ids found. 
  159. */ 
  160. function get_objects_in_term( $terms, $taxonomies, $args = null ) { 
  161. if ( !is_array($terms) ) 
  162. $terms = array($terms); 
  163.  
  164. if ( !is_array($taxonomies) ) 
  165. $taxonomies = array($taxonomies); 
  166.  
  167. foreach ( (array) $taxonomies as $taxonomy ) { 
  168. if ( !$this->is_taxonomy($taxonomy) ) 
  169. return new WP_Error('invalid_taxonomy', __('Invalid Taxonomy')); 
  170.  
  171. $defaults = array('order' => 'ASC', 'field' => 'term_id'); 
  172. $args = wp_parse_args( $args, $defaults ); 
  173. extract($args, EXTR_SKIP); 
  174.  
  175. if ( 'tt_id' == $field ) 
  176. $field = 'tt.term_taxonomy_id'; 
  177. else 
  178. $field = 'tt.term_id'; 
  179.  
  180. $order = ( 'desc' == strtolower($order) ) ? 'DESC' : 'ASC'; 
  181.  
  182. $terms = array_map('intval', $terms); 
  183.  
  184. $taxonomies = "'" . implode("', '", $taxonomies) . "'"; 
  185. $terms = "'" . implode("', '", $terms) . "'"; 
  186.  
  187. $object_ids = $this->db->get_col("SELECT tr.object_id FROM {$this->db->term_relationships} AS tr INNER JOIN {$this->db->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ($taxonomies) AND $field IN ($terms) ORDER BY tr.object_id $order"); 
  188.  
  189. if ( ! $object_ids ) 
  190. return array(); 
  191.  
  192. return $object_ids; 
  193.  
  194. /** 
  195. * Get all Term data from database by Term ID. 
  196. * The usage of the get_term function is to apply filters to a term object. It 
  197. * is possible to get a term object from the database before applying the 
  198. * filters. 
  199. * $term ID must be part of $taxonomy, to get from the database. Failure, might 
  200. * be able to be captured by the hooks. Failure would be the same value as $this->db 
  201. * returns for the get_row method. 
  202. * There are two hooks, one is specifically for each term, named 'get_term', and 
  203. * the second is for the taxonomy name, 'term_$taxonomy'. Both hooks gets the 
  204. * term object, and the taxonomy name as parameters. Both hooks are expected to 
  205. * return a Term object. 
  206. * 'get_term' hook - Takes two parameters the term Object and the taxonomy name. 
  207. * Must return term object. Used in get_term() as a catch-all filter for every 
  208. * $term. 
  209. * 'get_$taxonomy' hook - Takes two parameters the term Object and the taxonomy 
  210. * name. Must return term object. $taxonomy will be the taxonomy name, so for 
  211. * example, if 'category', it would be 'get_category' as the filter name. Useful 
  212. * for custom taxonomies or plugging into default taxonomies. 
  213. * @package WordPress 
  214. * @subpackage Taxonomy 
  215. * @since 2.3.0 
  216. * @uses $this->sanitize_term() Cleanses the term based on $filter context before returning. 
  217. * @see $this->sanitize_term_field() The $context param lists the available values for get_term_by() $filter param. 
  218. * @param int|object $term If integer, will get from database. If object will apply filters and return $term. 
  219. * @param string $taxonomy Taxonomy name that $term is part of. 
  220. * @param string $output Constant OBJECT, ARRAY_A, or ARRAY_N 
  221. * @param string $filter Optional, default is raw or no WordPress defined filter will applied. 
  222. * @return mixed|null|WP_Error Term Row from database. Will return null if $term is empty. If taxonomy does not 
  223. * exist then WP_Error will be returned. 
  224. */ 
  225. function &get_term($term, $taxonomy, $output = OBJECT, $filter = 'raw') { 
  226. if ( empty($term) ) { 
  227. $error = new WP_Error('invalid_term', __('Empty Term')); 
  228. return $error; 
  229.  
  230. if ( !$this->is_taxonomy($taxonomy) ) { 
  231. $error = new WP_Error('invalid_taxonomy', __('Invalid Taxonomy')); 
  232. return $error; 
  233.  
  234. if ( is_object($term) ) { 
  235. wp_cache_add($term->term_id, $term, $taxonomy); 
  236. wp_cache_add($term->term_taxonomy_id, $term->term_id, "$taxonomy:tt_id" ); 
  237. $_term = $term; 
  238. } else { 
  239. $term = (int) $term; 
  240. if ( ! $_term = wp_cache_get($term, $taxonomy) ) { 
  241. $_term = $this->db->get_row( $this->db->prepare( "SELECT t.*, tt.* FROM {$this->db->terms} AS t INNER JOIN {$this->db->term_taxonomy} AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy = %s AND t.term_id = %s LIMIT 1", $taxonomy, $term) ); 
  242. wp_cache_add($term, $_term, $taxonomy); 
  243. wp_cache_add($_term->term_taxonomy_id, $_term->term_id, "$taxonomy:tt_id" ); 
  244.  
  245. $_term = apply_filters('get_term', $_term, $taxonomy); 
  246. $_term = apply_filters("get_$taxonomy", $_term, $taxonomy); 
  247. $_term = $this->sanitize_term($_term, $taxonomy, $filter); 
  248.  
  249. backpress_convert_object( $_term, $output ); 
  250.  
  251. return $_term; 
  252.  
  253. /** 
  254. * Get all Term data from database by Term field and data. 
  255. * Warning: $value is not escaped for 'name' $field. You must do it yourself, if 
  256. * required. 
  257. * The default $field is 'id', therefore it is possible to also use null for 
  258. * field, but not recommended that you do so. 
  259. * If $value does not exist, the return value will be false. If $taxonomy exists 
  260. * and $field and $value combinations exist, the Term will be returned. 
  261. * @package WordPress 
  262. * @subpackage Taxonomy 
  263. * @since 2.3.0 
  264. * @uses $this->sanitize_term() Cleanses the term based on $filter context before returning. 
  265. * @see $this->sanitize_term_field() The $context param lists the available values for get_term_by() $filter param. 
  266. * @param string $field Either 'slug', 'name', 'id', or 'tt_id' 
  267. * @param string|int $value Search for this term value 
  268. * @param string $taxonomy Taxonomy Name 
  269. * @param string $output Constant OBJECT, ARRAY_A, or ARRAY_N 
  270. * @param string $filter Optional, default is raw or no WordPress defined filter will applied. 
  271. * @return mixed Term Row from database. Will return false if $taxonomy does not exist or $term was not found. 
  272. */ 
  273. function get_term_by($field, $value, $taxonomy, $output = OBJECT, $filter = 'raw') { 
  274. if ( !$this->is_taxonomy($taxonomy) ) 
  275. return false; 
  276.  
  277. if ( 'slug' == $field ) { 
  278. $field = 't.slug'; 
  279. $value = $this->sanitize_term_slug($value, $taxonomy); 
  280. if ( empty($value) ) 
  281. return false; 
  282. } else if ( 'name' == $field ) { 
  283. // Assume already escaped 
  284. $field = 't.name'; 
  285. } else if ( 'tt_id' == $field ) { 
  286. $field = 'tt.term_taxonomy_id'; 
  287. $value = (int) $value; 
  288. if ( $_term_id = wp_cache_get( $value, "$taxonomy:tt_id" ) ) 
  289. return $this->get_term( $_term_id, $taxonomy, $output, $filter ); 
  290. } else { 
  291. $field = 't.term_id'; 
  292. $value = (int) $value; 
  293.  
  294. $term = $this->db->get_row( $this->db->prepare( "SELECT t.*, tt.* FROM {$this->db->terms} AS t INNER JOIN {$this->db->term_taxonomy} AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy = %s AND $field = %s LIMIT 1", $taxonomy, $value) ); 
  295. if ( !$term ) 
  296. return false; 
  297.  
  298. wp_cache_add($term->term_id, $term, $taxonomy); 
  299. wp_cache_add($term->term_taxonomy_id, $term->term_id, "$taxonomy:tt_id" ); 
  300.  
  301. $term = $this->sanitize_term($term, $taxonomy, $filter); 
  302.  
  303. backpress_convert_object( $term, $output ); 
  304.  
  305. return $term; 
  306.  
  307. /** 
  308. * Merge all term children into a single array of their IDs. 
  309. * This recursive function will merge all of the children of $term into the same 
  310. * array of term IDs. Only useful for taxonomies which are hierarchical. 
  311. * Will return an empty array if $term does not exist in $taxonomy. 
  312. *  
  313. * @package WordPress 
  314. * @subpackage Taxonomy 
  315. * @since 2.3.0 
  316. * @uses $this->_get_term_hierarchy() 
  317. * @uses $this->get_term_children() Used to get the children of both $taxonomy and the parent $term 
  318. * @param string $term ID of Term to get children 
  319. * @param string $taxonomy Taxonomy Name 
  320. * @return array|WP_Error List of Term Objects. WP_Error returned if $taxonomy does not exist 
  321. */ 
  322. function get_term_children( $term_id, $taxonomy ) { 
  323. if ( !$this->is_taxonomy($taxonomy) ) 
  324. return new WP_Error('invalid_taxonomy', __('Invalid Taxonomy')); 
  325.  
  326. $term_id = intval( $term_id ); 
  327.  
  328. $terms = $this->_get_term_hierarchy($taxonomy); 
  329.  
  330. if ( ! isset($terms[$term_id]) ) 
  331. return array(); 
  332.  
  333. $children = $terms[$term_id]; 
  334.  
  335. foreach ( (array) $terms[$term_id] as $child ) { 
  336. if ( isset($terms[$child]) ) 
  337. $children = array_merge($children, $this->get_term_children($child, $taxonomy)); 
  338.  
  339. return $children; 
  340.  
  341. /** 
  342. * Get sanitized Term field. 
  343. * Does checks for $term, based on the $taxonomy. The function is for contextual 
  344. * reasons and for simplicity of usage. See sanitize_term_field() for more 
  345. * information. 
  346. * @package WordPress 
  347. * @subpackage Taxonomy 
  348. * @since 2.3.0 
  349. * @uses $this->sanitize_term_field() Passes the return value in sanitize_term_field on success. 
  350. * @param string $field Term field to fetch 
  351. * @param int $term Term ID 
  352. * @param string $taxonomy Taxonomy Name 
  353. * @param string $context Optional, default is display. Look at sanitize_term_field() for available options. 
  354. * @return mixed Will return an empty string if $term is not an object or if $field is not set in $term. 
  355. */ 
  356. function get_term_field( $field, $term, $taxonomy, $context = 'display' ) { 
  357. $term = (int) $term; 
  358. $term = $this->get_term( $term, $taxonomy ); 
  359. if ( is_wp_error($term) ) 
  360. return $term; 
  361.  
  362. if ( !is_object($term) ) 
  363. return ''; 
  364.  
  365. if ( !isset($term->$field) ) 
  366. return ''; 
  367.  
  368. return $this->sanitize_term_field($field, $term->$field, $term->term_id, $taxonomy, $context); 
  369.  
  370. /** 
  371. * Sanitizes Term for editing. 
  372. * Return value is sanitize_term() and usage is for sanitizing the term for 
  373. * editing. Function is for contextual and simplicity. 
  374. *  
  375. * @package WordPress 
  376. * @subpackage Taxonomy 
  377. * @since 2.3.0 
  378. * @uses $this->sanitize_term() Passes the return value on success 
  379. * @param int|object $id Term ID or Object 
  380. * @param string $taxonomy Taxonomy Name 
  381. * @return mixed|null|WP_Error Will return empty string if $term is not an object. 
  382. */ 
  383. function get_term_to_edit( $id, $taxonomy ) { 
  384. $term = $this->get_term( $id, $taxonomy ); 
  385.  
  386. if ( is_wp_error($term) ) 
  387. return $term; 
  388.  
  389. if ( !is_object($term) ) 
  390. return ''; 
  391.  
  392. return $this->sanitize_term($term, $taxonomy, 'edit'); 
  393.  
  394. /** 
  395. * Retrieve the terms in a given taxonomy or list of taxonomies. 
  396. * You can fully inject any customizations to the query before it is sent, as 
  397. * well as control the output with a filter. 
  398. * The 'get_terms' filter will be called when the cache has the term and will 
  399. * pass the found term along with the array of $taxonomies and array of $args. 
  400. * This filter is also called before the array of terms is passed and will pass 
  401. * the array of terms, along with the $taxonomies and $args. 
  402. * The 'list_terms_exclusions' filter passes the compiled exclusions along with 
  403. * the $args. 
  404. * The 'get_terms_orderby' filter passes the ORDER BY clause for the query 
  405. * along with the $args array. 
  406. * The 'get_terms_fields' filter passes the fields for the SELECT query 
  407. * along with the $args array. 
  408. * The list of arguments that $args can contain, which will overwrite the defaults: 
  409. * orderby - Default is 'name'. Can be name, count, term_group, slug or nothing 
  410. * (will use term_id), Passing a custom value other than these will cause it to 
  411. * order based on the custom value. 
  412. * order - Default is ASC. Can use DESC. 
  413. * hide_empty - Default is true. Will not return empty terms, which means 
  414. * terms whose count is 0 according to the given taxonomy. 
  415. * exclude - Default is an empty string. A comma- or space-delimited string 
  416. * of term ids to exclude from the return array. If 'include' is non-empty,  
  417. * 'exclude' is ignored. 
  418. * include - Default is an empty string. A comma- or space-delimited string 
  419. * of term ids to include in the return array. 
  420. * number - The maximum number of terms to return. Default is empty. 
  421. * offset - The number by which to offset the terms query. 
  422. * fields - Default is 'all', which returns an array of term objects. 
  423. * If 'fields' is 'ids' or 'names', returns an array of 
  424. * integers or strings, respectively. 
  425. * slug - Returns terms whose "slug" matches this value. Default is empty string. 
  426. * hierarchical - Whether to include terms that have non-empty descendants 
  427. * (even if 'hide_empty' is set to true). 
  428. * search - Returned terms' names will contain the value of 'search',  
  429. * case-insensitive. Default is an empty string. 
  430. * name__like - Returned terms' names will begin with the value of 'name__like',  
  431. * case-insensitive. Default is empty string. 
  432. * The argument 'pad_counts', if set to true will include the quantity of a term's 
  433. * children in the quantity of each term's "count" object variable. 
  434. * The 'get' argument, if set to 'all' instead of its default empty string,  
  435. * returns terms regardless of ancestry or whether the terms are empty. 
  436. * The 'child_of' argument, when used, should be set to the integer of a term ID. Its default 
  437. * is 0. If set to a non-zero value, all returned terms will be descendants 
  438. * of that term according to the given taxonomy. Hence 'child_of' is set to 0 
  439. * if more than one taxonomy is passed in $taxonomies, because multiple taxonomies 
  440. * make term ancestry ambiguous. 
  441. * The 'parent' argument, when used, should be set to the integer of a term ID. Its default is 
  442. * the empty string '', which has a different meaning from the integer 0. 
  443. * If set to an integer value, all returned terms will have as an immediate 
  444. * ancestor the term whose ID is specified by that integer according to the given taxonomy. 
  445. * The 'parent' argument is different from 'child_of' in that a term X is considered a 'parent' 
  446. * of term Y only if term X is the father of term Y, not its grandfather or great-grandfather, etc. 
  447. * @package WordPress 
  448. * @subpackage Taxonomy 
  449. * @since 2.3.0 
  450. * @uses wp_parse_args() Merges the defaults with those defined by $args and allows for strings. 
  451. * @param string|array Taxonomy name or list of Taxonomy names 
  452. * @param string|array $args The values of what to search for when returning terms 
  453. * @return array|WP_Error List of Term Objects and their children. Will return WP_Error, if any of $taxonomies do not exist. 
  454. */ 
  455. function &get_terms($taxonomies, $args = '') { 
  456. $empty_array = array(); 
  457.  
  458. $single_taxonomy = false; 
  459. if ( !is_array($taxonomies) ) { 
  460. $single_taxonomy = true; 
  461. $taxonomies = array($taxonomies); 
  462.  
  463. foreach ( (array) $taxonomies as $taxonomy ) { 
  464. if ( ! $this->is_taxonomy($taxonomy) ) { 
  465. $error = new WP_Error('invalid_taxonomy', __('Invalid Taxonomy')); 
  466. return $error; 
  467.  
  468. $in_taxonomies = "'" . implode("', '", $taxonomies) . "'"; 
  469.  
  470. $defaults = array('orderby' => 'name', 'order' => 'ASC',  
  471. 'hide_empty' => true, 'exclude' => '', 'exclude_tree' => '', 'include' => '',  
  472. 'number' => '', 'fields' => 'all', 'slug' => '', 'parent' => '',  
  473. 'hierarchical' => true, 'child_of' => 0, 'get' => '', 'name__like' => '',  
  474. 'pad_counts' => false, 'offset' => '', 'search' => ''); 
  475. $args = wp_parse_args( $args, $defaults ); 
  476. $args['number'] = absint( $args['number'] ); 
  477. $args['offset'] = absint( $args['offset'] ); 
  478. if ( !$single_taxonomy || !$this->is_taxonomy_hierarchical($taxonomies[0]) || 
  479. '' !== $args['parent'] ) { 
  480. $args['child_of'] = 0; 
  481. $args['hierarchical'] = false; 
  482. $args['pad_counts'] = false; 
  483.  
  484. if ( 'all' == $args['get'] ) { 
  485. $args['child_of'] = 0; 
  486. $args['hide_empty'] = 0; 
  487. $args['hierarchical'] = false; 
  488. $args['pad_counts'] = false; 
  489. extract($args, EXTR_SKIP); 
  490.  
  491. if ( $child_of ) { 
  492. $hierarchy = $this->_get_term_hierarchy($taxonomies[0]); 
  493. if ( !isset($hierarchy[$child_of]) ) 
  494. return $empty_array; 
  495.  
  496. if ( $parent ) { 
  497. $hierarchy = $this->_get_term_hierarchy($taxonomies[0]); 
  498. if ( !isset($hierarchy[$parent]) ) 
  499. return $empty_array; 
  500.  
  501. // $args can be whatever, only use the args defined in defaults to compute the key 
  502. $filter_key = ( has_filter('list_terms_exclusions') ) ? serialize($GLOBALS['wp_filter']['list_terms_exclusions']) : ''; 
  503. $key = md5( serialize( compact(array_keys($defaults)) ) . serialize( $taxonomies ) . $filter_key ); 
  504. $last_changed = wp_cache_get('last_changed', 'terms'); 
  505. if ( !$last_changed ) { 
  506. $last_changed = time(); 
  507. wp_cache_set('last_changed', $last_changed, 'terms'); 
  508. $cache_key = "get_terms:$key:$last_changed"; 
  509. $cache = wp_cache_get( $cache_key, 'terms' ); 
  510. if ( false !== $cache ) { 
  511. $cache = apply_filters('get_terms', $cache, $taxonomies, $args); 
  512. return $cache; 
  513.  
  514. $_orderby = strtolower($orderby); 
  515. if ( 'count' == $_orderby ) 
  516. $orderby = 'tt.count'; 
  517. else if ( 'name' == $_orderby ) 
  518. $orderby = 't.name'; 
  519. else if ( 'slug' == $_orderby ) 
  520. $orderby = 't.slug'; 
  521. else if ( 'term_group' == $_orderby ) 
  522. $orderby = 't.term_group'; 
  523. elseif ( empty($_orderby) || 'id' == $_orderby ) 
  524. $orderby = 't.term_id'; 
  525.  
  526. $orderby = apply_filters( 'get_terms_orderby', $orderby, $args ); 
  527.  
  528. $where = ''; 
  529. $inclusions = ''; 
  530. if ( !empty($include) ) { 
  531. $exclude = ''; 
  532. $exclude_tree = ''; 
  533. $interms = preg_split('/[\s, ]+/', $include); 
  534. if ( count($interms) ) { 
  535. foreach ( (array) $interms as $interm ) { 
  536. if (empty($inclusions)) 
  537. $inclusions = ' AND ( t.term_id = ' . intval($interm) . ' '; 
  538. else 
  539. $inclusions .= ' OR t.term_id = ' . intval($interm) . ' '; 
  540.  
  541. if ( !empty($inclusions) ) 
  542. $inclusions .= ')'; 
  543. $where .= $inclusions; 
  544.  
  545. $exclusions = ''; 
  546. if ( ! empty( $exclude_tree ) ) { 
  547. $excluded_trunks = preg_split('/[\s, ]+/', $exclude_tree); 
  548. foreach( (array) $excluded_trunks as $extrunk ) { 
  549. $excluded_children = (array) $this->get_terms($taxonomies[0], array('child_of' => intval($extrunk), 'fields' => 'ids')); 
  550. $excluded_children[] = $extrunk; 
  551. foreach( (array) $excluded_children as $exterm ) { 
  552. if ( empty($exclusions) ) 
  553. $exclusions = ' AND ( t.term_id <> ' . intval($exterm) . ' '; 
  554. else 
  555. $exclusions .= ' AND t.term_id <> ' . intval($exterm) . ' '; 
  556.  
  557. if ( !empty($exclude) ) { 
  558. $exterms = preg_split('/[\s, ]+/', $exclude); 
  559. if ( count($exterms) ) { 
  560. foreach ( (array) $exterms as $exterm ) { 
  561. if ( empty($exclusions) ) 
  562. $exclusions = ' AND ( t.term_id <> ' . intval($exterm) . ' '; 
  563. else 
  564. $exclusions .= ' AND t.term_id <> ' . intval($exterm) . ' '; 
  565.  
  566. if ( !empty($exclusions) ) 
  567. $exclusions .= ')'; 
  568. $exclusions = apply_filters('list_terms_exclusions', $exclusions, $args ); 
  569. $where .= $exclusions; 
  570.  
  571. if ( !empty($slug) ) { 
  572. $slug = $this->sanitize_term_slug($slug); 
  573. $where .= " AND t.slug = '$slug'"; 
  574.  
  575. if ( !empty($name__like) ) 
  576. $where .= " AND t.name LIKE '{$name__like}%'"; 
  577.  
  578. if ( '' !== $parent ) { 
  579. $parent = (int) $parent; 
  580. $where .= " AND tt.parent = '$parent'"; 
  581.  
  582. if ( $hide_empty && !$hierarchical ) 
  583. $where .= ' AND tt.count > 0'; 
  584.  
  585. // don't limit the query results when we have to descend the family tree 
  586. if ( ! empty($number) && ! $hierarchical && empty( $child_of ) && '' === $parent ) { 
  587. if( $offset ) 
  588. $limit = 'LIMIT ' . $offset . ', ' . $number; 
  589. else 
  590. $limit = 'LIMIT ' . $number; 
  591.  
  592. } else 
  593. $limit = ''; 
  594.  
  595. if ( !empty($search) ) { 
  596. $search = like_escape($search); 
  597. $where .= " AND (t.name LIKE '%$search%')"; 
  598.  
  599. if ( !in_array( $fields, array( 'all', 'ids', 'names', 'tt_ids' ) ) ) 
  600. $fields = 'all'; 
  601.  
  602. $selects = array(); 
  603. if ( 'all' == $fields ) 
  604. $selects = array('t.*', 'tt.*'); 
  605. else if ( 'ids' == $fields ) 
  606. $selects = array('t.term_id', 'tt.parent', 'tt.count'); 
  607. else if ( 'names' == $fields ) 
  608. $selects = array('t.term_id', 'tt.parent', 'tt.count', 't.name'); 
  609. $select_this = implode(', ', apply_filters( 'get_terms_fields', $selects, $args )); 
  610.  
  611. $query = "SELECT $select_this FROM {$this->db->terms} AS t INNER JOIN {$this->db->term_taxonomy} AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy IN ($in_taxonomies) $where ORDER BY $orderby $order $limit"; 
  612.  
  613. $terms = $this->db->get_results($query); 
  614. if ( 'all' == $fields ) { 
  615. $this->update_term_cache($terms); 
  616.  
  617. if ( empty($terms) ) { 
  618. wp_cache_add( $cache_key, array(), 'terms' ); 
  619. $terms = apply_filters('get_terms', array(), $taxonomies, $args); 
  620. return $terms; 
  621.  
  622. if ( $child_of || $hierarchical ) { 
  623. $children = $this->_get_term_hierarchy($taxonomies[0]); 
  624. if ( ! empty($children) ) 
  625. $terms = & $this->_get_term_children($child_of, $terms, $taxonomies[0]); 
  626.  
  627. // Update term counts to include children. 
  628. if ( $pad_counts ) 
  629. $this->_pad_term_counts($terms, $taxonomies[0]); 
  630.  
  631. // Make sure we show empty categories that have children. 
  632. if ( $hierarchical && $hide_empty && is_array($terms) ) { 
  633. foreach ( $terms as $k => $term ) { 
  634. if ( ! $term->count ) { 
  635. $children = $this->_get_term_children($term->term_id, $terms, $taxonomies[0]); 
  636. if( is_array($children) ) 
  637. foreach ( $children as $child ) 
  638. if ( $child->count ) 
  639. continue 2; 
  640.  
  641. // It really is empty 
  642. unset($terms[$k]); 
  643. reset ( $terms ); 
  644.  
  645. $_terms = array(); 
  646. if ( 'ids' == $fields ) { 
  647. while ( $term = array_shift($terms) ) 
  648. $_terms[] = $term->term_id; 
  649. $terms = $_terms; 
  650. } elseif ( 'names' == $fields ) { 
  651. while ( $term = array_shift($terms) ) 
  652. $_terms[] = $term->name; 
  653. $terms = $_terms; 
  654.  
  655. if ( 0 < $number && intval(@count($terms)) > $number ) { 
  656. $terms = array_slice($terms, $offset, $number); 
  657.  
  658. wp_cache_add( $cache_key, $terms, 'terms' ); 
  659.  
  660. $terms = apply_filters('get_terms', $terms, $taxonomies, $args); 
  661. return $terms; 
  662.  
  663. /** 
  664. * Check if Term exists. 
  665. * Returns the index of a defined term, or 0 (false) if the term doesn't exist. 
  666. * @package WordPress 
  667. * @subpackage Taxonomy 
  668. * @since 2.3.0 
  669. * @param int|string $term The term to check 
  670. * @param string $taxonomy The taxonomy name to use 
  671. * @param int $parent ID of parent term under which to confine the exists search. 
  672. * @return mixed Get the term id or Term Object, if exists. 
  673. */ 
  674. function is_term($term, $taxonomy = '', $parent = 0) { 
  675. $select = "SELECT term_id FROM {$this->db->terms} as t WHERE "; 
  676. $tax_select = "SELECT tt.term_id, tt.term_taxonomy_id FROM {$this->db->terms} AS t INNER JOIN {$this->db->term_taxonomy} as tt ON tt.term_id = t.term_id WHERE "; 
  677.  
  678. if ( is_int($term) ) { 
  679. if ( 0 == $term ) 
  680. return 0; 
  681. $where = 't.term_id = %d'; 
  682. if ( !empty($taxonomy) ) 
  683. return $this->db->get_row( $this->db->prepare( $tax_select . $where . " AND tt.taxonomy = %s", $term, $taxonomy ), ARRAY_A ); 
  684. else 
  685. return $this->db->get_var( $this->db->prepare( $select . $where, $term ) ); 
  686.  
  687. $term = trim( stripslashes( $term ) ); 
  688.  
  689. if ( '' === $slug = $this->sanitize_term_slug($term) ) 
  690. return 0; 
  691.  
  692. $where = 't.slug = %s'; 
  693. $else_where = 't.name = %s'; 
  694. $where_fields = array($slug); 
  695. $else_where_fields = array($term); 
  696. if ( !empty($taxonomy) ) { 
  697. $parent = (int) $parent; 
  698. if ( $parent > 0 ) { 
  699. $where_fields[] = $parent; 
  700. $else_where_fields[] = $parent; 
  701. $where .= ' AND tt.parent = %d'; 
  702. $else_where .= ' AND tt.parent = %d'; 
  703.  
  704. $where_fields[] = $taxonomy; 
  705. $else_where_fields[] = $taxonomy; 
  706.  
  707. if ( $result = $this->db->get_row( $this->db->prepare("SELECT tt.term_id, tt.term_taxonomy_id FROM {$this->db->terms} AS t INNER JOIN {$this->db->term_taxonomy} as tt ON tt.term_id = t.term_id WHERE $where AND tt.taxonomy = %s", $where_fields), ARRAY_A) ) 
  708. return $result; 
  709.  
  710. return $this->db->get_row( $this->db->prepare("SELECT tt.term_id, tt.term_taxonomy_id FROM {$this->db->terms} AS t INNER JOIN {$this->db->term_taxonomy} as tt ON tt.term_id = t.term_id WHERE $else_where AND tt.taxonomy = %s", $else_where_fields), ARRAY_A); 
  711.  
  712. if ( $result = $this->db->get_var( $this->db->prepare("SELECT term_id FROM {$this->db->terms} as t WHERE $where", $where_fields) ) ) 
  713. return $result; 
  714.  
  715. return $this->db->get_var( $this->db->prepare("SELECT term_id FROM {$this->db->terms} as t WHERE $else_where", $else_where_fields) ); 
  716.  
  717. function sanitize_term_slug( $title, $taxonomy = '', $term_id = 0 ) { 
  718. return apply_filters( 'pre_term_slug', $title, $taxonomy, $term_id ); 
  719.  
  720. function format_to_edit( $text ) { 
  721. return format_to_edit( $text ); 
  722.  
  723. /** 
  724. * Sanitize Term all fields 
  725. * Relies on sanitize_term_field() to sanitize the term. The difference 
  726. * is that this function will sanitize <strong>all</strong> fields. The 
  727. * context is based on sanitize_term_field(). 
  728. * The $term is expected to be either an array or an object. 
  729. * @package WordPress 
  730. * @subpackage Taxonomy 
  731. * @since 2.3.0 
  732. * @uses $this->sanitize_term_field Used to sanitize all fields in a term 
  733. * @param array|object $term The term to check 
  734. * @param string $taxonomy The taxonomy name to use 
  735. * @param string $context Default is 'display'. 
  736. * @return array|object Term with all fields sanitized 
  737. */ 
  738. function sanitize_term($term, $taxonomy, $context = 'display') { 
  739.  
  740. if ( 'raw' == $context ) 
  741. return $term; 
  742.  
  743. $fields = array('term_id', 'name', 'description', 'slug', 'count', 'parent', 'term_group'); 
  744.  
  745. $do_object = false; 
  746. if ( is_object($term) ) 
  747. $do_object = true; 
  748.  
  749. $term_id = $do_object ? $term->term_id : (isset($term['term_id']) ? $term['term_id'] : 0); 
  750.  
  751. foreach ( (array) $fields as $field ) { 
  752. if ( $do_object ) { 
  753. if ( isset($term->$field) ) 
  754. $term->$field = $this->sanitize_term_field($field, $term->$field, $term_id, $taxonomy, $context); 
  755. } else { 
  756. if ( isset($term[$field]) ) 
  757. $term[$field] = $this->sanitize_term_field($field, $term[$field], $term_id, $taxonomy, $context); 
  758.  
  759. if ( $do_object ) 
  760. $term->filter = $context; 
  761. else 
  762. $term['filter'] = $context; 
  763.  
  764. return $term; 
  765.  
  766. /** 
  767. * Cleanse the field value in the term based on the context. 
  768. * Passing a term field value through the function should be assumed to have 
  769. * cleansed the value for whatever context the term field is going to be used. 
  770. * If no context or an unsupported context is given, then default filters will 
  771. * be applied. 
  772. * There are enough filters for each context to support a custom filtering 
  773. * without creating your own filter function. Simply create a function that 
  774. * hooks into the filter you need. 
  775. * @package WordPress 
  776. * @subpackage Taxonomy 
  777. * @since 2.3.0 
  778. * @param string $field Term field to sanitize 
  779. * @param string $value Search for this term value 
  780. * @param int $term_id Term ID 
  781. * @param string $taxonomy Taxonomy Name 
  782. * @param string $context Either edit, db, display, attribute, or js. 
  783. * @return mixed sanitized field 
  784. */ 
  785. function sanitize_term_field($field, $value, $term_id, $taxonomy, $context) { 
  786. if ( 'parent' == $field || 'term_id' == $field || 'count' == $field || 'term_group' == $field ) { 
  787. $value = (int) $value; 
  788. if ( $value < 0 ) 
  789. $value = 0; 
  790.  
  791. if ( 'raw' == $context ) 
  792. return $value; 
  793.  
  794. if ( 'edit' == $context ) { 
  795. $value = apply_filters("edit_term_$field", $value, $term_id, $taxonomy); 
  796. $value = apply_filters("edit_${taxonomy}_$field", $value, $term_id); 
  797. if ( 'description' == $field ) 
  798. $value = $this->format_to_edit($value); 
  799. else 
  800. $value = esc_attr($value); 
  801. } else if ( 'db' == $context ) { 
  802. $value = apply_filters("pre_term_$field", $value, $taxonomy); 
  803. $value = apply_filters("pre_${taxonomy}_$field", $value); 
  804. // WP DIFF 
  805. } else if ( 'rss' == $context ) { 
  806. $value = apply_filters("term_${field}_rss", $value, $taxonomy); 
  807. $value = apply_filters("${taxonomy}_${field}_rss", $value); 
  808. } else { 
  809. // Use display filters by default. 
  810. $value = apply_filters("term_$field", $value, $term_id, $taxonomy, $context); 
  811. $value = apply_filters("${taxonomy}_$field", $value, $term_id, $context); 
  812.  
  813. if ( 'attribute' == $context ) 
  814. $value = esc_attr($value); 
  815. else if ( 'js' == $context ) 
  816. $value = esc_js($value); 
  817.  
  818. return $value; 
  819.  
  820. /** 
  821. * Count how many terms are in Taxonomy. 
  822. * Default $args is 'ignore_empty' which can be <code>'ignore_empty=true'</code> 
  823. * or <code>array('ignore_empty' => true);</code>. 
  824. * @package WordPress 
  825. * @subpackage Taxonomy 
  826. * @since 2.3.0 
  827. * @uses wp_parse_args() Turns strings into arrays and merges defaults into an array. 
  828. * @param string $taxonomy Taxonomy name 
  829. * @param array|string $args Overwrite defaults 
  830. * @return int How many terms are in $taxonomy 
  831. */ 
  832. function count_terms( $taxonomy, $args = array() ) { 
  833. $defaults = array('ignore_empty' => false); 
  834. $args = wp_parse_args($args, $defaults); 
  835. extract($args, EXTR_SKIP); 
  836.  
  837. $where = ''; 
  838. if ( $ignore_empty ) 
  839. $where = 'AND count > 0'; 
  840.  
  841. return $this->db->get_var( $this->db->prepare( "SELECT COUNT(*) FROM {$this->db->term_taxonomy} WHERE taxonomy = %s $where", $taxonomy ) ); 
  842.  
  843. /** 
  844. * Will unlink the term from the taxonomy. 
  845. * Will remove the term's relationship to the taxonomy, not the term or taxonomy 
  846. * itself. The term and taxonomy will still exist. Will require the term's 
  847. * object ID to perform the operation. 
  848. * @package WordPress 
  849. * @subpackage Taxonomy 
  850. * @since 2.3.0 
  851. * @param int $object_id The term Object Id that refers to the term 
  852. * @param string|array $taxonomy List of Taxonomy Names or single Taxonomy name. 
  853. */ 
  854. function delete_object_term_relationships( $object_id, $taxonomies ) { 
  855. $object_id = (int) $object_id; 
  856.  
  857. if ( !is_array($taxonomies) ) 
  858. $taxonomies = array($taxonomies); 
  859.  
  860. foreach ( (array) $taxonomies as $taxonomy ) { 
  861. $terms = $this->get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids')); 
  862. $in_terms = "'" . implode("', '", $terms) . "'"; 
  863. $this->db->query( $this->db->prepare( "DELETE FROM {$this->db->term_relationships} WHERE object_id = %d AND term_taxonomy_id IN ($in_terms)", $object_id ) ); 
  864. $this->update_term_count($terms, $taxonomy); 
  865.  
  866. /** 
  867. * Removes a term from the database. 
  868. * If the term is a parent of other terms, then the children will be updated to 
  869. * that term's parent. 
  870. * The $args 'default' will only override the terms found, if there is only one 
  871. * term found. Any other and the found terms are used. 
  872. * The $args 'force_default' will force the term supplied as default to be 
  873. * assigned even if the object was not going to be termless 
  874. * @package WordPress 
  875. * @subpackage Taxonomy 
  876. * @since 2.3.0 
  877. * @uses do_action() Calls both 'delete_term' and 'delete_$taxonomy' action 
  878. * hooks, passing term object, term id. 'delete_term' gets an additional 
  879. * parameter with the $taxonomy parameter. 
  880. * @param int $term Term ID 
  881. * @param string $taxonomy Taxonomy Name 
  882. * @param array|string $args Optional. Change 'default' term id and override found term ids. 
  883. * @return bool|WP_Error Returns false if not term; true if completes delete action. 
  884. */ 
  885. function delete_term( $term, $taxonomy, $args = array() ) { 
  886. $term = (int) $term; 
  887.  
  888. if ( ! $ids = $this->is_term($term, $taxonomy) ) 
  889. return false; 
  890. if ( is_wp_error( $ids ) ) 
  891. return $ids; 
  892.  
  893. $tt_id = $ids['term_taxonomy_id']; 
  894.  
  895. $defaults = array(); 
  896. $args = wp_parse_args($args, $defaults); 
  897. extract($args, EXTR_SKIP); 
  898.  
  899. if ( isset($default) ) { 
  900. $default = (int) $default; 
  901. if ( !$this->is_term($default, $taxonomy) ) 
  902. unset($default); 
  903.  
  904. // Update children to point to new parent 
  905. if ( $this->is_taxonomy_hierarchical($taxonomy) ) { 
  906. $term_obj = $this->get_term($term, $taxonomy); 
  907. if ( is_wp_error( $term_obj ) ) 
  908. return $term_obj; 
  909. $parent = $term_obj->parent; 
  910.  
  911. $this->db->update( $this->db->term_taxonomy, compact( 'parent' ), array( 'parent' => $term_obj->term_id ) + compact( 'taxonomy' ) ); 
  912.  
  913. $objects = $this->db->get_col( $this->db->prepare( "SELECT object_id FROM {$this->db->term_relationships} WHERE term_taxonomy_id = %d", $tt_id ) ); 
  914.  
  915. foreach ( (array) $objects as $object ) { 
  916. $terms = $this->get_object_terms($object, $taxonomy, array('fields' => 'ids', 'orderby' => 'none')); 
  917. if ( 1 == count($terms) && isset($default) ) { 
  918. $terms = array($default); 
  919. } else { 
  920. $terms = array_diff($terms, array($term)); 
  921. if (isset($default) && isset($force_default) && $force_default) 
  922. $terms = array_merge($terms, array($default)); 
  923. $terms = array_map('intval', $terms); 
  924. $this->set_object_terms($object, $terms, $taxonomy); 
  925.  
  926. $this->db->query( $this->db->prepare( "DELETE FROM {$this->db->term_taxonomy} WHERE term_taxonomy_id = %d", $tt_id ) ); 
  927.  
  928. // Delete the term if no taxonomies use it. 
  929. if ( !$this->db->get_var( $this->db->prepare( "SELECT COUNT(*) FROM {$this->db->term_taxonomy} WHERE term_id = %d", $term) ) ) 
  930. $this->db->query( $this->db->prepare( "DELETE FROM {$this->db->terms} WHERE term_id = %d", $term) ); 
  931.  
  932. $this->clean_term_cache($term, $taxonomy); 
  933.  
  934. do_action('delete_term', $term, $tt_id, $taxonomy); 
  935. do_action("delete_$taxonomy", $term, $tt_id); 
  936.  
  937. return true; 
  938.  
  939. /** 
  940. * Retrieves the terms associated with the given object(s), in the supplied taxonomies. 
  941. * The following information has to do the $args parameter and for what can be 
  942. * contained in the string or array of that parameter, if it exists. 
  943. * The first argument is called, 'orderby' and has the default value of 'name'. 
  944. * The other value that is supported is 'count'. 
  945. * The second argument is called, 'order' and has the default value of 'ASC'. 
  946. * The only other value that will be acceptable is 'DESC'. 
  947. * The final argument supported is called, 'fields' and has the default value of 
  948. * 'all'. There are multiple other options that can be used instead. Supported 
  949. * values are as follows: 'all', 'ids', 'names', and finally 
  950. * 'all_with_object_id'. 
  951. * The fields argument also decides what will be returned. If 'all' or 
  952. * 'all_with_object_id' is choosen or the default kept intact, then all matching 
  953. * terms objects will be returned. If either 'ids' or 'names' is used, then an 
  954. * array of all matching term ids or term names will be returned respectively. 
  955. * @package WordPress 
  956. * @subpackage Taxonomy 
  957. * @since 2.3.0 
  958. * @param int|array $object_id The id of the object(s) to retrieve. 
  959. * @param string|array $taxonomies The taxonomies to retrieve terms from. 
  960. * @param array|string $args Change what is returned 
  961. * @return array|WP_Error The requested term data or empty array if no terms found. WP_Error if $taxonomy does not exist. 
  962. */ 
  963. function get_object_terms($object_ids, $taxonomies, $args = array()) { 
  964. if ( !is_array($taxonomies) ) 
  965. $taxonomies = array($taxonomies); 
  966.  
  967. foreach ( (array) $taxonomies as $taxonomy ) { 
  968. if ( !$this->is_taxonomy($taxonomy) ) 
  969. return new WP_Error('invalid_taxonomy', __('Invalid Taxonomy')); 
  970.  
  971. if ( !is_array($object_ids) ) 
  972. $object_ids = array($object_ids); 
  973. $object_ids = array_map('intval', $object_ids); 
  974.  
  975. $defaults = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all'); 
  976. $args = wp_parse_args( $args, $defaults ); 
  977.  
  978. $terms = array(); 
  979. if ( count($taxonomies) > 1 ) { 
  980. foreach ( $taxonomies as $index => $taxonomy ) { 
  981. $t = $this->get_taxonomy($taxonomy); 
  982. if ( isset($t->args) && is_array($t->args) && $args != array_merge($args, $t->args) ) { 
  983. unset($taxonomies[$index]); 
  984. $terms = array_merge($terms, $this->get_object_terms($object_ids, $taxonomy, array_merge($args, $t->args))); 
  985. } else { 
  986. $t = $this->get_taxonomy($taxonomies[0]); 
  987. if ( isset($t->args) && is_array($t->args) ) 
  988. $args = array_merge($args, $t->args); 
  989.  
  990. extract($args, EXTR_SKIP); 
  991.  
  992. if ( 'count' == $orderby ) 
  993. $orderby = 'tt.count'; 
  994. else if ( 'name' == $orderby ) 
  995. $orderby = 't.name'; 
  996. else if ( 'slug' == $orderby ) 
  997. $orderby = 't.slug'; 
  998. else if ( 'term_group' == $orderby ) 
  999. $orderby = 't.term_group'; 
  1000. else if ( 'term_order' == $orderby ) 
  1001. $orderby = 'tr.term_order'; 
  1002. else if ( 'none' == $orderby ) { 
  1003. $orderby = ''; 
  1004. $order = ''; 
  1005. } else { 
  1006. $orderby = 't.term_id'; 
  1007.  
  1008. // tt_ids queries can only be none or tr.term_taxonomy_id 
  1009. if ( ('tt_ids' == $fields) && !empty($orderby) ) 
  1010. $orderby = 'tr.term_taxonomy_id'; 
  1011.  
  1012. if ( !empty($orderby) ) 
  1013. $orderby = "ORDER BY $orderby"; 
  1014.  
  1015. $taxonomies = "'" . implode("', '", $taxonomies) . "'"; 
  1016. $object_ids = implode(', ', $object_ids); 
  1017.  
  1018. $select_this = ''; 
  1019. if ( 'all' == $fields ) 
  1020. $select_this = 't.*, tt.*'; 
  1021. else if ( 'ids' == $fields ) 
  1022. $select_this = 't.term_id'; 
  1023. else if ( 'names' == $fields ) 
  1024. $select_this = 't.name'; 
  1025. else if ( 'all_with_object_id' == $fields ) 
  1026. $select_this = 't.*, tt.*, tr.object_id'; 
  1027.  
  1028. $query = "SELECT $select_this FROM {$this->db->terms} AS t INNER JOIN {$this->db->term_taxonomy} AS tt ON tt.term_id = t.term_id INNER JOIN {$this->db->term_relationships} AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ($taxonomies) AND tr.object_id IN ($object_ids) $orderby $order"; 
  1029.  
  1030. if ( 'all' == $fields || 'all_with_object_id' == $fields ) { 
  1031. $terms = array_merge($terms, $this->db->get_results($query)); 
  1032. $this->update_term_cache($terms); 
  1033. } else if ( 'ids' == $fields || 'names' == $fields ) { 
  1034. $terms = array_merge($terms, $this->db->get_col($query)); 
  1035. } else if ( 'tt_ids' == $fields ) { 
  1036. $terms = $this->db->get_col("SELECT tr.term_taxonomy_id FROM {$this->db->term_relationships} AS tr INNER JOIN {$this->db->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"); 
  1037.  
  1038. if ( ! $terms ) 
  1039. $terms = array(); 
  1040.  
  1041. return apply_filters('wp_get_object_terms', $terms, $object_ids, $taxonomies, $args); 
  1042.  
  1043. /** 
  1044. * Adds a new term to the database. Optionally marks it as an alias of an existing term. 
  1045. * Error handling is assigned for the nonexistance of the $taxonomy and $term 
  1046. * parameters before inserting. If both the term id and taxonomy exist 
  1047. * previously, then an array will be returned that contains the term id and the 
  1048. * contents of what is returned. The keys of the array are 'term_id' and 
  1049. * 'term_taxonomy_id' containing numeric values. 
  1050. * It is assumed that the term does not yet exist or the above will apply. The 
  1051. * term will be first added to the term table and then related to the taxonomy 
  1052. * if everything is well. If everything is correct, then several actions will be 
  1053. * run prior to a filter and then several actions will be run after the filter 
  1054. * is run. 
  1055. * The arguments decide how the term is handled based on the $args parameter. 
  1056. * The following is a list of the available overrides and the defaults. 
  1057. * 'alias_of'. There is no default, but if added, expected is the slug that the 
  1058. * term will be an alias of. Expected to be a string. 
  1059. * 'description'. There is no default. If exists, will be added to the database 
  1060. * along with the term. Expected to be a string. 
  1061. * 'parent'. Expected to be numeric and default is 0 (zero). Will assign value 
  1062. * of 'parent' to the term. 
  1063. * 'slug'. Expected to be a string. There is no default. 
  1064. * If 'slug' argument exists then the slug will be checked to see if it is not 
  1065. * a valid term. If that check succeeds (it is not a valid term), then it is 
  1066. * added and the term id is given. If it fails, then a check is made to whether 
  1067. * the taxonomy is hierarchical and the parent argument is not empty. If the 
  1068. * second check succeeds, the term will be inserted and the term id will be 
  1069. * given. 
  1070. * @package WordPress 
  1071. * @subpackage Taxonomy 
  1072. * @since 2.3.0 
  1073. * @uses do_action() Calls 'create_term' hook with the term id and taxonomy id as parameters. 
  1074. * @uses do_action() Calls 'create_$taxonomy' hook with term id and taxonomy id as parameters. 
  1075. * @uses apply_filters() Calls 'term_id_filter' hook with term id and taxonomy id as parameters. 
  1076. * @uses do_action() Calls 'created_term' hook with the term id and taxonomy id as parameters. 
  1077. * @uses do_action() Calls 'created_$taxonomy' hook with term id and taxonomy id as parameters. 
  1078. * @param int|string $term The term to add or update. 
  1079. * @param string $taxonomy The taxonomy to which to add the term 
  1080. * @param array|string $args Change the values of the inserted term 
  1081. * @return array|WP_Error The Term ID and Term Taxonomy ID 
  1082. */ 
  1083. function insert_term( $term, $taxonomy, $args = array() ) { 
  1084. if ( !$this->is_taxonomy($taxonomy) ) 
  1085. return new WP_Error('invalid_taxonomy', __('Invalid taxonomy')); 
  1086.  
  1087. if ( is_int($term) && 0 == $term ) 
  1088. return new WP_Error('invalid_term_id', __('Invalid term ID')); 
  1089.  
  1090. if ( '' == trim($term) ) 
  1091. return new WP_Error('empty_term_name', __('A name is required for this term')); 
  1092.  
  1093. $defaults = array( 'alias_of' => '', 'description' => '', 'parent' => 0, 'slug' => ''); 
  1094. $args = wp_parse_args($args, $defaults); 
  1095. $args['name'] = $term; 
  1096. $args['taxonomy'] = $taxonomy; 
  1097. $args = $this->sanitize_term($args, $taxonomy, 'db'); 
  1098. extract($args, EXTR_SKIP); 
  1099.  
  1100. // expected_slashed ($name) 
  1101. $name = stripslashes($name); 
  1102. $description = stripslashes($description); 
  1103.  
  1104. if ( empty($slug) ) 
  1105. $slug = $this->sanitize_term_slug($name, $taxonomy); 
  1106.  
  1107. $term_group = 0; 
  1108. if ( $alias_of ) { 
  1109. $alias = $this->db->get_row( $this->db->prepare( "SELECT term_id, term_group FROM {$this->db->terms} WHERE slug = %s", $alias_of) ); 
  1110. if ( $alias->term_group ) { 
  1111. // The alias we want is already in a group, so let's use that one. 
  1112. $term_group = $alias->term_group; 
  1113. } else { 
  1114. // The alias isn't in a group, so let's create a new one and firstly add the alias term to it. 
  1115. $term_group = $this->db->get_var("SELECT MAX(term_group) FROM {$this->db->terms}") + 1; 
  1116. $this->db->query( $this->db->prepare( "UPDATE {$this->db->terms} SET term_group = %d WHERE term_id = %d", $term_group, $alias->term_id ) ); 
  1117.  
  1118. if ( ! $term_id = $this->is_term($slug) ) { 
  1119. if ( false === $this->db->insert( $this->db->terms, compact( 'name', 'slug', 'term_group' ) ) ) 
  1120. return new WP_Error('db_insert_error', __('Could not insert term into the database'), $this->db->last_error); 
  1121. $term_id = (int) $this->db->insert_id; 
  1122. } else if ( $this->is_taxonomy_hierarchical($taxonomy) && !empty($parent) ) { 
  1123. // If the taxonomy supports hierarchy and the term has a parent, make the slug unique 
  1124. // by incorporating parent slugs. 
  1125. $slug = $this->unique_term_slug($slug, (object) $args); 
  1126. if ( false === $this->db->insert( $this->db->terms, compact( 'name', 'slug', 'term_group' ) ) ) 
  1127. return new WP_Error('db_insert_error', __('Could not insert term into the database'), $this->db->last_error); 
  1128. $term_id = (int) $this->db->insert_id; 
  1129.  
  1130. if ( empty($slug) ) { 
  1131. $slug = $this->sanitize_term_slug($slug, $taxonomy, $term_id); 
  1132. $this->db->update( $this->db->terms, compact( 'slug' ), compact( 'term_id' ) ); 
  1133.  
  1134. $tt_id = $this->db->get_var( $this->db->prepare( "SELECT tt.term_taxonomy_id FROM {$this->db->term_taxonomy} AS tt INNER JOIN {$this->db->terms} AS t ON tt.term_id = t.term_id WHERE tt.taxonomy = %s AND t.term_id = %d", $taxonomy, $term_id ) ); 
  1135.  
  1136. if ( !empty($tt_id) ) 
  1137. return array('term_id' => $term_id, 'term_taxonomy_id' => $tt_id); 
  1138.  
  1139. $this->db->insert( $this->db->term_taxonomy, compact( 'term_id', 'taxonomy', 'description', 'parent') + array( 'count' => 0 ) ); 
  1140. $tt_id = (int) $this->db->insert_id; 
  1141.  
  1142. do_action("create_term", $term_id, $tt_id); 
  1143. do_action("create_$taxonomy", $term_id, $tt_id); 
  1144.  
  1145. $term_id = apply_filters('term_id_filter', $term_id, $tt_id); 
  1146.  
  1147. $this->clean_term_cache($term_id, $taxonomy); 
  1148.  
  1149. do_action("created_term", $term_id, $tt_id); 
  1150. do_action("created_$taxonomy", $term_id, $tt_id); 
  1151.  
  1152. return array('term_id' => $term_id, 'term_taxonomy_id' => $tt_id); 
  1153.  
  1154. /** 
  1155. * Create Term and Taxonomy Relationships. 
  1156. * Relates an object (post, link etc) to a term and taxonomy type. Creates the 
  1157. * term and taxonomy relationship if it doesn't already exist. Creates a term if 
  1158. * it doesn't exist (using the slug). 
  1159. * A relationship means that the term is grouped in or belongs to the taxonomy. 
  1160. * A term has no meaning until it is given context by defining which taxonomy it 
  1161. * exists under. 
  1162. * @package WordPress 
  1163. * @subpackage Taxonomy 
  1164. * @since 2.3.0 
  1165. * @param int $object_id The object to relate to. 
  1166. * @param array|int|string $term The slug or id of the term, will replace all existing 
  1167. * related terms in this taxonomy. 
  1168. * @param array|string $taxonomy The context in which to relate the term to the object. 
  1169. * @param bool $append If false will delete difference of terms. 
  1170. * @return array|WP_Error Affected Term IDs 
  1171. */ 
  1172. function set_object_terms($object_id, $terms, $taxonomy, $append = false) { 
  1173. $object_id = (int) $object_id; 
  1174.  
  1175. if ( !$this->is_taxonomy($taxonomy) ) 
  1176. return new WP_Error('invalid_taxonomy', __('Invalid Taxonomy')); 
  1177.  
  1178. if ( !is_array($terms) ) 
  1179. $terms = array($terms); 
  1180.  
  1181. if ( ! $append ) 
  1182. $old_tt_ids = $this->get_object_terms($object_id, $taxonomy, array('fields' => 'tt_ids', 'orderby' => 'none')); 
  1183.  
  1184. $tt_ids = array(); 
  1185. $term_ids = array(); 
  1186.  
  1187. foreach ( (array) $terms as $term ) { 
  1188. if ( !strlen(trim($term)) ) 
  1189. continue; 
  1190.  
  1191. if ( !$id = $this->is_term($term, $taxonomy) ) 
  1192. $id = $this->insert_term($term, $taxonomy); 
  1193. if ( is_wp_error($id) ) 
  1194. return $id; 
  1195. $term_ids[] = $id['term_id']; 
  1196. $id = $id['term_taxonomy_id']; 
  1197. $tt_ids[] = $id; 
  1198.  
  1199. if ( $this->db->get_var( $this->db->prepare( "SELECT term_taxonomy_id FROM {$this->db->term_relationships} WHERE object_id = %d AND term_taxonomy_id = %d", $object_id, $id ) ) ) 
  1200. continue; 
  1201. $this->db->insert( $this->db->term_relationships, array( 'object_id' => $object_id, 'term_taxonomy_id' => $id ) ); 
  1202.  
  1203. $this->update_term_count($tt_ids, $taxonomy); 
  1204.  
  1205. if ( ! $append ) { 
  1206. $delete_terms = array_diff($old_tt_ids, $tt_ids); 
  1207. if ( $delete_terms ) { 
  1208. $in_delete_terms = "'" . implode("', '", $delete_terms) . "'"; 
  1209. $this->db->query( $this->db->prepare("DELETE FROM {$this->db->term_relationships} WHERE object_id = %d AND term_taxonomy_id IN ($in_delete_terms)", $object_id) ); 
  1210. $this->update_term_count($delete_terms, $taxonomy); 
  1211.  
  1212. $t = $this->get_taxonomy($taxonomy); 
  1213. if ( ! $append && isset($t->sort) && $t->sort ) { 
  1214. $values = array(); 
  1215. $term_order = 0; 
  1216. $final_tt_ids = $this->get_object_terms($object_id, $taxonomy, 'fields=tt_ids'); 
  1217. foreach ( $tt_ids as $tt_id ) 
  1218. if ( in_array($tt_id, $final_tt_ids) ) 
  1219. $values[] = $this->db->prepare( "(%d, %d, %d)", $object_id, $tt_id, ++$term_order); 
  1220. if ( $values ) 
  1221. $this->db->query("INSERT INTO {$this->db->term_relationships} (object_id, term_taxonomy_id, term_order) VALUES " . join(', ', $values) . " ON DUPLICATE KEY UPDATE term_order = VALUES(term_order)"); 
  1222.  
  1223. do_action('set_object_terms', $object_id, $terms, $tt_ids, $taxonomy, $append); 
  1224. return $tt_ids; 
  1225.  
  1226. /** 
  1227. * Will make slug unique, if it isn't already. 
  1228. * The $slug has to be unique global to every taxonomy, meaning that one 
  1229. * taxonomy term can't have a matching slug with another taxonomy term. Each 
  1230. * slug has to be globally unique for every taxonomy. 
  1231. * The way this works is that if the taxonomy that the term belongs to is 
  1232. * heirarchical and has a parent, it will append that parent to the $slug. 
  1233. * If that still doesn't return an unique slug, then it try to append a number 
  1234. * until it finds a number that is truely unique. 
  1235. * The only purpose for $term is for appending a parent, if one exists. 
  1236. * @package WordPress 
  1237. * @subpackage Taxonomy 
  1238. * @since 2.3.0 
  1239. * @param string $slug The string that will be tried for a unique slug 
  1240. * @param object $term The term object that the $slug will belong too 
  1241. * @return string Will return a true unique slug. 
  1242. */ 
  1243. function unique_term_slug($slug, $term) { 
  1244. // If the taxonomy supports hierarchy and the term has a parent, make the slug unique 
  1245. // by incorporating parent slugs. 
  1246. if ( $this->is_taxonomy_hierarchical($term->taxonomy) && !empty($term->parent) ) { 
  1247. $the_parent = $term->parent; 
  1248. while ( ! empty($the_parent) ) { 
  1249. $parent_term = $this->get_term($the_parent, $term->taxonomy); 
  1250. if ( is_wp_error($parent_term) || empty($parent_term) ) 
  1251. break; 
  1252. $slug .= '-' . $parent_term->slug; 
  1253. if ( empty($parent_term->parent) ) 
  1254. break; 
  1255. $the_parent = $parent_term->parent; 
  1256.  
  1257. // If we didn't get a unique slug, try appending a number to make it unique. 
  1258. if ( !empty($args['term_id']) ) 
  1259. $query = $this->db->prepare( "SELECT slug FROM {$this->db->terms} WHERE slug = %s AND term_id != %d", $slug, $args['term_id'] ); 
  1260. else 
  1261. $query = $this->db->prepare( "SELECT slug FROM {$this->db->terms} WHERE slug = %s", $slug ); 
  1262.  
  1263. if ( $this->db->get_var( $query ) ) { 
  1264. $num = 2; 
  1265. do { 
  1266. $alt_slug = $slug . "-$num"; 
  1267. $num++; 
  1268. $slug_check = $this->db->get_var( $this->db->prepare( "SELECT slug FROM {$this->db->terms} WHERE slug = %s", $alt_slug ) ); 
  1269. } while ( $slug_check ); 
  1270. $slug = $alt_slug; 
  1271.  
  1272. return $slug; 
  1273.  
  1274. /** 
  1275. * Update term based on arguments provided. 
  1276. * The $args will indiscriminately override all values with the same field name. 
  1277. * Care must be taken to not override important information need to update or 
  1278. * update will fail (or perhaps create a new term, neither would be acceptable). 
  1279. * Defaults will set 'alias_of', 'description', 'parent', and 'slug' if not 
  1280. * defined in $args already. 
  1281. * 'alias_of' will create a term group, if it doesn't already exist, and update 
  1282. * it for the $term. 
  1283. * If the 'slug' argument in $args is missing, then the 'name' in $args will be 
  1284. * used. It should also be noted that if you set 'slug' and it isn't unique then 
  1285. * a WP_Error will be passed back. If you don't pass any slug, then a unique one 
  1286. * will be created for you. 
  1287. * For what can be overrode in $args, check the term scheme can contain and stay 
  1288. * away from the term keys. 
  1289. * @package WordPress 
  1290. * @subpackage Taxonomy 
  1291. * @since 2.3.0 
  1292. * @uses do_action() Will call both 'edit_term' and 'edit_$taxonomy' twice. 
  1293. * @uses apply_filters() Will call the 'term_id_filter' filter and pass the term 
  1294. * id and taxonomy id. 
  1295. * @param int $term_id The ID of the term 
  1296. * @param string $taxonomy The context in which to relate the term to the object. 
  1297. * @param array|string $args Overwrite term field values 
  1298. * @return array|WP_Error Returns Term ID and Taxonomy Term ID 
  1299. */ 
  1300. function update_term( $term_id, $taxonomy, $args = array() ) { 
  1301. if ( !$this->is_taxonomy($taxonomy) ) 
  1302. return new WP_Error('invalid_taxonomy', __('Invalid taxonomy')); 
  1303.  
  1304. $term_id = (int) $term_id; 
  1305.  
  1306. // First, get all of the original args 
  1307. $term = $this->get_term($term_id, $taxonomy, ARRAY_A); 
  1308.  
  1309. if ( is_wp_error( $term ) ) 
  1310. return $term; 
  1311.  
  1312. // Merge old and new args with new args overwriting old ones. 
  1313. $args = array_merge($term, $args); 
  1314.  
  1315. $defaults = array( 'alias_of' => '', 'description' => '', 'parent' => 0, 'slug' => ''); 
  1316. $args = wp_parse_args($args, $defaults); 
  1317. $args = $this->sanitize_term($args, $taxonomy, 'db'); 
  1318. extract($args, EXTR_SKIP); 
  1319.  
  1320. // expected_slashed ($name) 
  1321. $name = stripslashes($name); 
  1322. $description = stripslashes($description); 
  1323.  
  1324. if ( '' == trim($name) ) 
  1325. return new WP_Error('empty_term_name', __('A name is required for this term')); 
  1326.  
  1327. $empty_slug = false; 
  1328. if ( empty($slug) ) { 
  1329. $empty_slug = true; 
  1330. $slug = $this->sanitize_term_slug($name, $taxonomy, $term_id); 
  1331.  
  1332. if ( $alias_of ) { 
  1333. $alias = $this->db->get_row( $this->db->prepare( "SELECT term_id, term_group FROM {$this->db->terms} WHERE slug = %s", $alias_of) ); 
  1334. if ( $alias->term_group ) { 
  1335. // The alias we want is already in a group, so let's use that one. 
  1336. $term_group = $alias->term_group; 
  1337. } else { 
  1338. // The alias isn't in a group, so let's create a new one and firstly add the alias term to it. 
  1339. $term_group = $this->db->get_var("SELECT MAX(term_group) FROM {$this->db->terms}") + 1; 
  1340. $this->db->update( $this->db->terms, compact('term_group'), array( 'term_id' => $alias->term_id ) ); 
  1341.  
  1342. // Check for duplicate slug 
  1343. $id = $this->db->get_var( $this->db->prepare( "SELECT term_id FROM {$this->db->terms} WHERE slug = %s", $slug ) ); 
  1344. if ( $id && ($id != $term_id) ) { 
  1345. // If an empty slug was passed or the parent changed, reset the slug to something unique. 
  1346. // Otherwise, bail. 
  1347. if ( $empty_slug || ( $parent != $term->parent) ) 
  1348. $slug = $this->unique_term_slug($slug, (object) $args); 
  1349. else 
  1350. return new WP_Error('duplicate_term_slug', sprintf(__('The slug “%s” is already in use by another term'), $slug)); 
  1351.  
  1352. $this->db->update($this->db->terms, compact( 'name', 'slug', 'term_group' ), compact( 'term_id' ) ); 
  1353.  
  1354. if ( empty($slug) ) { 
  1355. $slug = $this->sanitize_term_slug($name, $taxonomy, $term_id); 
  1356. $this->db->update( $this->db->terms, compact( 'slug' ), compact( 'term_id' ) ); 
  1357.  
  1358. $tt_id = $this->db->get_var( $this->db->prepare( "SELECT tt.term_taxonomy_id FROM {$this->db->term_taxonomy} AS tt INNER JOIN {$this->db->terms} AS t ON tt.term_id = t.term_id WHERE tt.taxonomy = %s AND t.term_id = %d", $taxonomy, $term_id) ); 
  1359.  
  1360. $this->db->update( $this->db->term_taxonomy, compact( 'term_id', 'taxonomy', 'description', 'parent' ), array( 'term_taxonomy_id' => $tt_id ) ); 
  1361.  
  1362. do_action("edit_term", $term_id, $tt_id); 
  1363. do_action("edit_$taxonomy", $term_id, $tt_id); 
  1364.  
  1365. $term_id = apply_filters('term_id_filter', $term_id, $tt_id); 
  1366.  
  1367. $this->clean_term_cache($term_id, $taxonomy); 
  1368.  
  1369. do_action("edited_term", $term_id, $tt_id); 
  1370. do_action("edited_$taxonomy", $term_id, $tt_id); 
  1371.  
  1372. return array('term_id' => $term_id, 'term_taxonomy_id' => $tt_id); 
  1373.  
  1374. /** 
  1375. * Enable or disable term counting. 
  1376. * @since 2.5.0 
  1377. * @param bool $defer Optional. Enable if true, disable if false. 
  1378. * @return bool Whether term counting is enabled or disabled. 
  1379. */ 
  1380. function defer_term_counting($defer=NULL) { 
  1381. static $_defer = false; 
  1382.  
  1383. if ( is_bool($defer) ) { 
  1384. $_defer = $defer; 
  1385. // flush any deferred counts 
  1386. if ( !$defer ) 
  1387. $this->update_term_count( NULL, NULL, true ); 
  1388.  
  1389. return $_defer; 
  1390.  
  1391. /** 
  1392. * Updates the amount of terms in taxonomy. 
  1393. * If there is a taxonomy callback applied, then it will be called for updating 
  1394. * the count. 
  1395. * The default action is to count what the amount of terms have the relationship 
  1396. * of term ID. Once that is done, then update the database. 
  1397. * @package WordPress 
  1398. * @subpackage Taxonomy 
  1399. * @since 2.3.0 
  1400. * @uses $this->db 
  1401. * @param int|array $terms The ID of the terms 
  1402. * @param string $taxonomy The context of the term. 
  1403. * @return bool If no terms will return false, and if successful will return true. 
  1404. */ 
  1405. function update_term_count( $terms, $taxonomy, $do_deferred=false ) { 
  1406. static $_deferred = array(); 
  1407.  
  1408. if ( $do_deferred ) { 
  1409. foreach ( (array) array_keys($_deferred) as $tax ) { 
  1410. $this->update_term_count_now( $_deferred[$tax], $tax ); 
  1411. unset( $_deferred[$tax] ); 
  1412.  
  1413. if ( empty($terms) ) 
  1414. return false; 
  1415.  
  1416. if ( !is_array($terms) ) 
  1417. $terms = array($terms); 
  1418.  
  1419. if ( $this->defer_term_counting() ) { 
  1420. if ( !isset($_deferred[$taxonomy]) ) 
  1421. $_deferred[$taxonomy] = array(); 
  1422. $_deferred[$taxonomy] = array_unique( array_merge($_deferred[$taxonomy], $terms) ); 
  1423. return true; 
  1424.  
  1425. return $this->update_term_count_now( $terms, $taxonomy ); 
  1426.  
  1427. /** 
  1428. * Perform term count update immediately. 
  1429. * @since 2.5.0 
  1430. * @param array $terms The term_taxonomy_id of terms to update. 
  1431. * @param string $taxonomy The context of the term. 
  1432. * @return bool Always true when complete. 
  1433. */ 
  1434. function update_term_count_now( $terms, $taxonomy ) { 
  1435. $terms = array_map('intval', $terms); 
  1436.  
  1437. $taxonomy = $this->get_taxonomy($taxonomy); 
  1438. if ( !empty($taxonomy->update_count_callback) ) { 
  1439. call_user_func($taxonomy->update_count_callback, $terms); 
  1440. } else { 
  1441. // Default count updater 
  1442. foreach ( (array) $terms as $term ) { 
  1443. $count = $this->db->get_var( $this->db->prepare( "SELECT COUNT(*) FROM {$this->db->term_relationships} WHERE term_taxonomy_id = %d", $term) ); 
  1444. $this->db->update( $this->db->term_taxonomy, compact( 'count' ), array( 'term_taxonomy_id' => $term ) ); 
  1445.  
  1446.  
  1447. $this->clean_term_cache($terms); 
  1448.  
  1449. return true; 
  1450.  
  1451. // 
  1452.   // Cache 
  1453. // 
  1454.   
  1455. /** 
  1456. * Removes the taxonomy relationship to terms from the cache. 
  1457. * Will remove the entire taxonomy relationship containing term $object_id. The 
  1458. * term IDs have to exist within the taxonomy $object_type for the deletion to 
  1459. * take place. 
  1460. * @package WordPress 
  1461. * @subpackage Taxonomy 
  1462. * @since 2.3 
  1463. * @see $this->get_object_taxonomies() for more on $object_type 
  1464. * @uses do_action() Will call action hook named, 'clean_object_term_cache' after completion. 
  1465. * Passes, function params in same order. 
  1466. * @param int|array $object_ids Single or list of term object ID(s) 
  1467. * @param string $object_type The taxonomy object type 
  1468. */ 
  1469. function clean_object_term_cache($object_ids, $object_type) { 
  1470. if ( !is_array($object_ids) ) 
  1471. $object_ids = array($object_ids); 
  1472.  
  1473. foreach ( $object_ids as $id ) 
  1474. foreach ( $this->get_object_taxonomies($object_type) as $taxonomy ) 
  1475. wp_cache_delete($id, "{$taxonomy}_relationships"); 
  1476.  
  1477. do_action('clean_object_term_cache', $object_ids, $object_type); 
  1478.  
  1479. /** 
  1480. * Will remove all of the term ids from the cache. 
  1481. * @package WordPress 
  1482. * @subpackage Taxonomy 
  1483. * @since 2.3.0 
  1484. * @param int|array $ids Single or list of Term IDs 
  1485. * @param string $taxonomy Can be empty and will assume tt_ids, else will use for context. 
  1486. */ 
  1487. function clean_term_cache($ids, $taxonomy = '') { 
  1488. static $cleaned = array(); 
  1489.  
  1490. if ( !is_array($ids) ) 
  1491. $ids = array($ids); 
  1492.  
  1493. $taxonomies = array(); 
  1494. // If no taxonomy, assume tt_ids. 
  1495. if ( empty($taxonomy) ) { 
  1496. $tt_ids = implode( ', ', array_map( 'intval', $ids ) ); 
  1497. $terms = $this->db->get_results("SELECT term_id, term_taxonomy_id, taxonomy FROM {$this->db->term_taxonomy} WHERE term_taxonomy_id IN ($tt_ids)"); 
  1498. foreach ( (array) $terms as $term ) { 
  1499. $taxonomies[] = $term->taxonomy; 
  1500. wp_cache_delete($term->term_id, $term->taxonomy); 
  1501. wp_cache_delete($term->term_taxonomy_id, "{$term->taxonomy}:tt_id"); 
  1502. $taxonomies = array_unique($taxonomies); 
  1503. } else { 
  1504. $tt_ids = implode( ', ', array_map( 'intval', $ids ) ); 
  1505. $terms = $this->db->get_results("SELECT term_id, term_taxonomy_id FROM {$this->db->term_taxonomy} WHERE term_id IN ($tt_ids)"); 
  1506. foreach ( (array) $terms as $term ) { 
  1507. wp_cache_delete($term->term_id, $taxonomy); 
  1508. wp_cache_delete($term->term_taxonomy_id, "$taxonomy:tt_id"); 
  1509. $taxonomies = array($taxonomy); 
  1510.  
  1511. foreach ( $taxonomies as $taxonomy ) { 
  1512. if ( isset($cleaned[$taxonomy]) ) 
  1513. continue; 
  1514. $cleaned[$taxonomy] = true; 
  1515. wp_cache_delete('all_ids', $taxonomy); 
  1516. wp_cache_delete('get', $taxonomy); 
  1517. $this->delete_children_cache($taxonomy); 
  1518.  
  1519. wp_cache_delete('get_terms', 'terms'); 
  1520.  
  1521. do_action('clean_term_cache', $ids, $taxonomy); 
  1522.  
  1523. /** 
  1524. * Retrieves the taxonomy relationship to the term object id. 
  1525. * @package WordPress 
  1526. * @subpackage Taxonomy 
  1527. * @since 2.3.0 
  1528. * @uses wp_cache_get() Retrieves taxonomy relationship from cache 
  1529. * @param int|array $id Term object ID 
  1530. * @param string $taxonomy Taxonomy Name 
  1531. * @return bool|array Empty array if $terms found, but not $taxonomy. False if nothing is in cache for $taxonomy and $id. 
  1532. */ 
  1533. function &get_object_term_cache($id, $taxonomy) { 
  1534. $cache = wp_cache_get($id, "{$taxonomy}_relationships"); 
  1535. return $cache; 
  1536.  
  1537. /** 
  1538. * Updates the cache for Term ID(s). 
  1539. * Will only update the cache for terms not already cached. 
  1540. * The $object_ids expects that the ids be separated by commas, if it is a 
  1541. * string. 
  1542. * It should be noted that update_object_term_cache() is very time extensive. It 
  1543. * is advised that the function is not called very often or at least not for a 
  1544. * lot of terms that exist in a lot of taxonomies. The amount of time increases 
  1545. * for each term and it also increases for each taxonomy the term belongs to. 
  1546. * @package WordPress 
  1547. * @subpackage Taxonomy 
  1548. * @since 2.3.0 
  1549. * @uses $this->get_object_terms() Used to get terms from the database to update 
  1550. * @param string|array $object_ids Single or list of term object ID(s) 
  1551. * @param string $object_type The taxonomy object type 
  1552. * @return null|bool Null value is given with empty $object_ids. False if  
  1553. */ 
  1554. function update_object_term_cache($object_ids, $object_type) { 
  1555. if ( empty($object_ids) ) 
  1556. return; 
  1557.  
  1558. if ( !is_array($object_ids) ) 
  1559. $object_ids = explode(', ', $object_ids); 
  1560.  
  1561. $object_ids = array_map('intval', $object_ids); 
  1562.  
  1563. $taxonomies = $this->get_object_taxonomies($object_type); 
  1564.  
  1565. $ids = array(); 
  1566. foreach ( (array) $object_ids as $id ) { 
  1567. foreach ( $taxonomies as $taxonomy ) { 
  1568. if ( false === wp_cache_get($id, "{$taxonomy}_relationships") ) { 
  1569. $ids[] = $id; 
  1570. break; 
  1571.  
  1572. if ( empty( $ids ) ) 
  1573. return false; 
  1574.  
  1575. $terms = $this->get_object_terms($ids, $taxonomies, 'fields=all_with_object_id'); 
  1576.  
  1577. $object_terms = array(); 
  1578. foreach ( (array) $terms as $term ) 
  1579. $object_terms[$term->object_id][$term->taxonomy][$term->term_id] = $term; 
  1580.  
  1581. foreach ( $ids as $id ) { 
  1582. foreach ( $taxonomies as $taxonomy ) { 
  1583. if ( ! isset($object_terms[$id][$taxonomy]) ) { 
  1584. if ( !isset($object_terms[$id]) ) 
  1585. $object_terms[$id] = array(); 
  1586. $object_terms[$id][$taxonomy] = array(); 
  1587.  
  1588. foreach ( $object_terms as $id => $value ) { 
  1589. foreach ( $value as $taxonomy => $terms ) { 
  1590. wp_cache_set($id, $terms, "{$taxonomy}_relationships"); 
  1591.  
  1592. /** 
  1593. * Updates Terms to Taxonomy in cache. 
  1594. * @package WordPress 
  1595. * @subpackage Taxonomy 
  1596. * @since 2.3.0 
  1597. * @param array $terms List of Term objects to change 
  1598. * @param string $taxonomy Optional. Update Term to this taxonomy in cache 
  1599. */ 
  1600. function update_term_cache($terms, $taxonomy = '') { 
  1601. foreach ( (array) $terms as $term ) { 
  1602. $term_taxonomy = $taxonomy; 
  1603. if ( empty($term_taxonomy) ) 
  1604. $term_taxonomy = $term->taxonomy; 
  1605.  
  1606. wp_cache_add($term->term_id, $term, $term_taxonomy); 
  1607. wp_cache_add($term->term_taxonomy_id, $term->term_id, "$term_taxonomy:tt_id"); 
  1608.  
  1609. // 
  1610.   // Private 
  1611. // 
  1612.   
  1613. /** 
  1614. * Retrieves children of taxonomy as Term IDs. 
  1615. * @package WordPress 
  1616. * @subpackage Taxonomy 
  1617. * @access private 
  1618. * @since 2.3.0 
  1619. * @uses backpress_update_option() Stores all of the children in "$taxonomy_children" 
  1620. * option. That is the name of the taxonomy, immediately followed by '_children'. 
  1621. * @param string $taxonomy Taxonomy Name 
  1622. * @return array Empty if $taxonomy isn't hierarachical or returns children as Term IDs. 
  1623. */ 
  1624. function _get_term_hierarchy($taxonomy) { 
  1625. if ( !$this->is_taxonomy_hierarchical($taxonomy) ) 
  1626. return array(); 
  1627. $children = $this->get_children_cache($taxonomy); 
  1628. if ( is_array($children) ) 
  1629. return $children; 
  1630.  
  1631. $children = array(); 
  1632. $terms = $this->get_terms($taxonomy, 'get=all'); 
  1633. foreach ( $terms as $term ) { 
  1634. if ( $term->parent > 0 ) 
  1635. $children[$term->parent][] = $term->term_id; 
  1636. $this->set_children_cache($taxonomy, $children); 
  1637.  
  1638. return $children; 
  1639.  
  1640. /** 
  1641. * Get the subset of $terms that are descendants of $term_id. 
  1642. * If $terms is an array of objects, then _get_term_children returns an array of objects. 
  1643. * If $terms is an array of IDs, then _get_term_children returns an array of IDs. 
  1644. * @package WordPress 
  1645. * @subpackage Taxonomy 
  1646. * @access private 
  1647. * @since 2.3.0 
  1648. * @param int $term_id The ancestor term: all returned terms should be descendants of $term_id. 
  1649. * @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. 
  1650. * @param string $taxonomy The taxonomy which determines the hierarchy of the terms. 
  1651. * @return array The subset of $terms that are descendants of $term_id. 
  1652. */ 
  1653. function &_get_term_children($term_id, $terms, $taxonomy) { 
  1654. $empty_array = array(); 
  1655. if ( empty($terms) ) 
  1656. return $empty_array; 
  1657.  
  1658. $term_list = array(); 
  1659. $has_children = $this->_get_term_hierarchy($taxonomy); 
  1660.  
  1661. if ( ( 0 != $term_id ) && ! isset($has_children[$term_id]) ) 
  1662. return $empty_array; 
  1663.  
  1664. foreach ( (array) $terms as $term ) { 
  1665. $use_id = false; 
  1666. if ( !is_object($term) ) { 
  1667. $term = $this->get_term($term, $taxonomy); 
  1668. if ( is_wp_error( $term ) ) 
  1669. return $term; 
  1670. $use_id = true; 
  1671.  
  1672. if ( $term->term_id == $term_id ) 
  1673. continue; 
  1674.  
  1675. if ( $term->parent == $term_id ) { 
  1676. if ( $use_id ) 
  1677. $term_list[] = $term->term_id; 
  1678. else 
  1679. $term_list[] = $term; 
  1680.  
  1681. if ( !isset($has_children[$term->term_id]) ) 
  1682. continue; 
  1683.  
  1684. if ( $children = $this->_get_term_children($term->term_id, $terms, $taxonomy) ) 
  1685. $term_list = array_merge($term_list, $children); 
  1686.  
  1687. return $term_list; 
  1688.  
  1689. /** 
  1690. * Add count of children to parent count. 
  1691. * Recalculates term counts by including items from child terms. Assumes all 
  1692. * relevant children are already in the $terms argument. 
  1693. * @package WordPress 
  1694. * @subpackage Taxonomy 
  1695. * @access private 
  1696. * @since 2.3 
  1697. * @param array $terms List of Term IDs 
  1698. * @param string $taxonomy Term Context 
  1699. * @return null Will break from function if conditions are not met. 
  1700. */ 
  1701. function _pad_term_counts(&$terms, $taxonomy) { 
  1702. return; 
  1703.  
  1704. /** 
  1705. * Determine if the given object is associated with any of the given terms. 
  1706. * The given terms are checked against the object's terms' term_ids, names and slugs. 
  1707. * Terms given as integers will only be checked against the object's terms' term_ids. 
  1708. * If no terms are given, determines if object is associated with any terms in the given taxonomy. 
  1709. * @since 2.7.0 
  1710. * @uses WP_Taxonomy::get_object_term_cache() 
  1711. * @uses WP_Taxonomy::get_object_terms() 
  1712. * @param int $object_id. ID of the object (post ID, link ID, ...) 
  1713. * @param string $taxonomy. Single taxonomy name 
  1714. * @param int|string|array $terms Optional. Term term_id, name, slug or array of said 
  1715. * @return bool|WP_Error. WP_Error on input error. 
  1716. */ 
  1717. function is_object_in_term( $object_id, $taxonomy, $terms = null ) { 
  1718. if ( !$object_id = (int) $object_id ) 
  1719. return new WP_Error( 'invalid_object', __( 'Invalid object ID' ) ); 
  1720.  
  1721. $object_terms = $this->get_object_term_cache( $object_id, $taxonomy ); 
  1722. if ( empty( $object_terms ) ) 
  1723. $object_terms = $this->get_object_terms( $object_id, $taxonomy ); 
  1724.  
  1725. if ( is_wp_error( $object_terms ) ) 
  1726. return $object_terms; 
  1727. if ( empty( $object_terms ) ) 
  1728. return false; 
  1729. if ( empty( $terms ) ) 
  1730. return ( !empty( $object_terms ) ); 
  1731.  
  1732. $terms = (array) $terms; 
  1733.  
  1734. if ( $ints = array_filter( $terms, 'is_int' ) ) 
  1735. $strs = array_diff( $terms, $ints ); 
  1736. else 
  1737. $strs =& $terms; 
  1738.  
  1739. foreach ( $object_terms as $object_term ) { 
  1740. if ( $ints && in_array( $object_term->term_id, $ints ) ) return true; // If int, check against term_id 
  1741. if ( $strs ) { 
  1742. if ( in_array( $object_term->term_id, $strs ) ) return true; 
  1743. if ( in_array( $object_term->name, $strs ) ) return true; 
  1744. if ( in_array( $object_term->slug, $strs ) ) return true; 
  1745.  
  1746. return false; 
  1747.  
  1748. function get_children_cache( $taxonomy ) { return false; } 
  1749. function set_children_cache( $taxonomy, $children ) {} 
  1750. function delete_children_cache( $taxonomy ) {}