Ticket #14162: 14162.diff
File 14162.diff, 16.6 KB (added by , 9 years ago) |
---|
-
src/wp-includes/category-functions.php
diff --git src/wp-includes/category-functions.php src/wp-includes/category-functions.php index 847dd50..193887f 100644
function clean_category_cache( $id ) { 325 325 */ 326 326 function _make_cat_compat( &$category ) { 327 327 if ( is_object( $category ) && ! is_wp_error( $category ) ) { 328 $category->cat_ID = &$category->term_id;329 $category->category_count = &$category->count;330 $category->category_description = &$category->description;331 $category->cat_name = &$category->name;332 $category->category_nicename = &$category->slug;333 $category->category_parent = &$category->parent;328 $category->cat_ID = $category->term_id; 329 $category->category_count = $category->count; 330 $category->category_description = $category->description; 331 $category->cat_name = $category->name; 332 $category->category_nicename = $category->slug; 333 $category->category_parent = $category->parent; 334 334 } elseif ( is_array( $category ) && isset( $category['term_id'] ) ) { 335 335 $category['cat_ID'] = &$category['term_id']; 336 336 $category['category_count'] = &$category['count']; -
new file src/wp-includes/class-wp-term.php
diff --git src/wp-includes/class-wp-term.php src/wp-includes/class-wp-term.php new file mode 100644 index 0000000..68fb187
- + 1 <?php 2 /** 3 * WordPress Term class. 4 * 5 * @since 4.4.0 6 * @package WordPress 7 * @subpackage Taxonomy 8 * 9 */ 10 final class WP_Term { 11 12 /** 13 * Term ID. 14 * 15 * @since 4.4.0 16 * @access public 17 * @var int 18 */ 19 public $term_id; 20 21 /** 22 * The term's name. 23 * 24 * @since 4.4.0 25 * @access public 26 * @var string 27 */ 28 public $name = ''; 29 30 /** 31 * The term's slug. 32 * 33 * @since 4.4.0 34 * @access public 35 * @var string 36 */ 37 public $slug = ''; 38 39 /** 40 * The term's term_group. 41 * 42 * @since 4.4.0 43 * @access public 44 * @var string 45 */ 46 public $term_group = ''; 47 48 /** 49 * Term Taxonomy ID. 50 * 51 * @since 4.4.0 52 * @access public 53 * @var int 54 */ 55 public $term_taxonomy_id = 0; 56 57 /** 58 * The term's taxonomy name. 59 * 60 * @since 4.4.0 61 * @access public 62 * @var string 63 */ 64 public $taxonomy = ''; 65 66 /** 67 * The term's description. 68 * 69 * @since 4.4.0 70 * @access public 71 * @var string 72 */ 73 public $description = ''; 74 75 /** 76 * ID of a term's parent term. 77 * 78 * @since 4.4.0 79 * @access public 80 * @var int 81 */ 82 public $parent = 0; 83 84 /** 85 * Cached object count for this term. 86 * 87 * @since 4.4.0 88 * @access public 89 * @var int 90 */ 91 public $count = 0; 92 93 /** 94 * Stores the term object's sanitization level. 95 * 96 * Does not correspond to a DB field. 97 * 98 * @since 4.4.0 99 * @access public 100 * @var string 101 */ 102 public $filter = 'raw'; 103 104 /** 105 * Retrieve WP_Term instance. 106 * 107 * @since 4.4.0 108 * @access public 109 * @static 110 * 111 * @global wpdb $wpdb 112 * 113 * @param int $term_id Term ID. 114 * @return WP_Term|false Term object, false otherwise. 115 */ 116 public static function get_instance( $term_id ) { 117 global $wpdb; 118 119 $term_id = (int) $term_id; 120 if ( ! $term_id ) { 121 return false; 122 } 123 124 $_term = wp_cache_get( $term_id, 'terms' ); 125 126 if ( ! $_term ) { 127 $_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 t.term_id = %d LIMIT 1", $term_id ) ); 128 if ( ! $_term ) { 129 return false; 130 } 131 132 $_term = sanitize_term( $_term, $_term->taxonomy, 'raw' ); 133 wp_cache_add( $term_id, $_term, 'terms' ); 134 } elseif ( empty( $_term->filter ) ) { 135 $_term = sanitize_term( $_term, $_term->taxonomy, 'raw' ); 136 } 137 138 return new WP_Term( $_term ); 139 } 140 141 /** 142 * Constructor. 143 * 144 * @since 4.4.0 145 * 146 * @param WP_Term|object $term Term object. 147 */ 148 public function __construct( $term ) { 149 foreach ( get_object_vars( $term ) as $key => $value ) { 150 $this->$key = $value; 151 } 152 } 153 154 /** 155 * Sanitize term fields, according to the filter type provided. 156 * 157 * @param string $filter Filter context. Accepts 'edit', 'db', 'display', 'attribute', 'js', 'raw'. 158 * @return WP_Term 159 */ 160 public function filter( $filter ) { 161 if ( isset( $this->filter ) && $this->filter === $filter ) { 162 return $this; 163 } 164 165 return sanitize_term( $this, $this->taxonomy, $filter ); 166 } 167 168 /** 169 * Convert object to array. 170 * 171 * @return array Object as array. 172 */ 173 public function to_array() { 174 return get_object_vars( $this ); 175 } 176 } -
src/wp-includes/taxonomy-functions.php
diff --git src/wp-includes/taxonomy-functions.php src/wp-includes/taxonomy-functions.php index a13424b..afd8a40 100644
function get_tax_sql( $tax_query, $primary_table, $primary_id_column ) { 712 712 * @global wpdb $wpdb WordPress database abstraction object. 713 713 * @see sanitize_term_field() The $context param lists the available values for get_term_by() $filter param. 714 714 * 715 * @param int|object $term If integer, will get from database. If object will apply filters and return $term. 715 * @param int|WP_Term|object $term If integer, term data will be fetched from the database, or from the cache if 716 * available. If stdClass object (as in the results of a database query), will apply 717 * filters and return a `WP_Term` object corresponding to the `$term` data. If `WP_Term`, 718 * will return `$term`. 716 719 * @param string $taxonomy Taxonomy name that $term is part of. 717 720 * @param string $output Constant OBJECT, ARRAY_A, or ARRAY_N 718 721 * @param string $filter Optional, default is raw or no WordPress defined filter will applied. 719 * @return object|array|null|WP_Error Term Row from database. Will return null if $term is empty. If taxonomy does not720 * exist then WP_Error will be returned.722 * @return WP_Term|array|null|WP_Error Type corresponding to $output on success or null on failure. When $output is OBJECT, 723 * a `WP_Term` instance is returned. If taxonomy does not exist then WP_Error will be returned. 721 724 */ 722 function get_term($term, $taxonomy, $output = OBJECT, $filter = 'raw') { 723 global $wpdb; 724 725 function get_term( $term, $taxonomy = '', $output = OBJECT, $filter = 'raw' ) { 725 726 if ( empty( $term ) ) { 726 727 return new WP_Error( 'invalid_term', __( 'Empty Term' ) ); 727 728 } 728 729 729 if ( ! taxonomy_exists( $taxonomy ) ) {730 if ( $taxonomy && ! taxonomy_exists( $taxonomy ) ) { 730 731 return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy' ) ); 731 732 } 732 733 733 if ( is_object($term) && empty($term->filter) ) { 734 wp_cache_add( $term->term_id, $term, $taxonomy ); 734 if ( $term instanceof WP_Term ) { 735 735 $_term = $term; 736 } elseif ( is_object( $term ) ) { 737 if ( empty( $term->filter ) ) { 738 $_term = sanitize_term( $term, $taxonomy, 'raw' ); 739 $_term = new WP_Term( $_term ); 740 } elseif ( 'raw' == $term->filter ) { 741 $_term = new WP_Term( $term ); 742 } else { 743 $_term = WP_Term::get_instance( $term->term_id ); 744 } 736 745 } else { 737 if ( is_object($term) ) 738 $term = $term->term_id; 739 if ( !$term = (int) $term ) 740 return null; 741 if ( ! $_term = wp_cache_get( $term, $taxonomy ) ) { 742 $_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) ); 743 if ( ! $_term ) 744 return null; 745 wp_cache_add( $term, $_term, $taxonomy ); 746 $_term = WP_Term::get_instance( $term ); 747 } 748 749 // If a taxonomy was passed, make sure it matches the taxonomy of the located term. 750 if ( $_term && $taxonomy && $taxonomy !== $_term->taxonomy ) { 751 // If there are two terms with the same ID, split the other one to a new term. 752 $new_term_id = _split_shared_term( $_term->term_id, $_term->term_taxonomy_id ); 753 754 // If no split occurred, this is an invalid request. 755 if ( $new_term_id === $_term->term_id ) { 756 return new WP_Error( 'invalid_term', __( 'Empty Term' ) ); 757 } else { 758 // Refetch the term, now that it's no longer shared. 759 return get_term( $_term->term_id, $taxonomy, $output, $filter ); 746 760 } 747 761 } 748 762 763 if ( ! $_term ) { 764 return null; 765 } 766 749 767 /** 750 768 * Filter a term. 751 769 * … … function get_term($term, $taxonomy, $output = OBJECT, $filter = 'raw') { 768 786 * @param string $taxonomy The taxonomy slug. 769 787 */ 770 788 $_term = apply_filters( "get_$taxonomy", $_term, $taxonomy ); 771 $_term = sanitize_term($_term, $taxonomy, $filter);772 789 773 if ( $output == OBJECT ) {774 return $_term;775 } elseif ( $output == ARRAY_A ) { 776 $__term = get_object_vars($_term);777 return $_ _term;790 // Sanitize term, according to the specified filter. 791 $_term = $_term->filter( $filter ); 792 793 if ( $output == ARRAY_A ) { 794 return $_term->to_array(); 778 795 } elseif ( $output == ARRAY_N ) { 779 $__term = array_values(get_object_vars($_term)); 780 return $__term; 781 } else { 782 return $_term; 796 return array_values( $_term->to_array() ); 783 797 } 798 799 return $_term; 784 800 } 785 801 786 802 /** … … function get_term($term, $taxonomy, $output = OBJECT, $filter = 'raw') { 808 824 * @param string $taxonomy Taxonomy name. Optional, if `$field` is 'term_taxonomy_id'. 809 825 * @param string $output Constant OBJECT, ARRAY_A, or ARRAY_N 810 826 * @param string $filter Optional, default is raw or no WordPress defined filter will applied. 811 * @return object|array|null|WP_Error|false Term Row from database.827 * @return WP_Term|array|null|WP_Error|false Instance of WP_Term. 812 828 * Will return false if $taxonomy does not exist or $term was not found. 813 829 */ 814 830 function get_term_by( $field, $value, $taxonomy = '', $output = OBJECT, $filter = 'raw' ) { … … function get_term_by( $field, $value, $taxonomy = '', $output = OBJECT, $filter 822 838 $tax_clause = $wpdb->prepare( "AND tt.taxonomy = %s", $taxonomy ); 823 839 824 840 if ( 'slug' == $field ) { 825 $ field = 't.slug';841 $_field = 't.slug'; 826 842 $value = sanitize_title($value); 827 843 if ( empty($value) ) 828 844 return false; 829 845 } elseif ( 'name' == $field ) { 830 846 // Assume already escaped 831 847 $value = wp_unslash($value); 832 $ field = 't.name';848 $_field = 't.name'; 833 849 } elseif ( 'term_taxonomy_id' == $field ) { 834 850 $value = (int) $value; 835 $ field = 'tt.term_taxonomy_id';851 $_field = 'tt.term_taxonomy_id'; 836 852 837 853 // No `taxonomy` clause when searching by 'term_taxonomy_id'. 838 854 $tax_clause = ''; … … function get_term_by( $field, $value, $taxonomy = '', $output = OBJECT, $filter 844 860 return $term; 845 861 } 846 862 847 $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 $ field = %s $tax_clause LIMIT 1", $value ) );863 $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 $_field = %s $tax_clause LIMIT 1", $value ) ); 848 864 if ( ! $term ) 849 865 return false; 850 866 … … function get_term_by( $field, $value, $taxonomy = '', $output = OBJECT, $filter 853 869 $taxonomy = $term->taxonomy; 854 870 } 855 871 856 wp_cache_add( $term->term_id, $term, $taxonomy ); 857 858 /** This filter is documented in wp-includes/taxonomy-functions.php */ 859 $term = apply_filters( 'get_term', $term, $taxonomy ); 860 861 /** This filter is documented in wp-includes/taxonomy-functions.php */ 862 $term = apply_filters( "get_$taxonomy", $term, $taxonomy ); 863 864 $term = sanitize_term($term, $taxonomy, $filter); 872 wp_cache_add( $term->term_id, $term, 'terms' ); 865 873 866 if ( $output == OBJECT ) { 867 return $term; 868 } elseif ( $output == ARRAY_A ) { 869 return get_object_vars($term); 870 } elseif ( $output == ARRAY_N ) { 871 return array_values(get_object_vars($term)); 872 } else { 873 return $term; 874 } 874 return get_term( $term, $taxonomy, $output, $filter ); 875 875 } 876 876 877 877 /** … … function get_term_to_edit( $id, $taxonomy ) { 1048 1048 * @type array $meta_query Meta query clauses to limit retrieved terms by. 1049 1049 * See `WP_Meta_Query`. Default empty. 1050 1050 * } 1051 * @return array|int|WP_Error List of Term Objects and their children. Will return WP_Error, if any of $taxonomies1051 * @return array|int|WP_Error List of WP_Term instances and their children. Will return WP_Error, if any of $taxonomies 1052 1052 * do not exist. 1053 1053 */ 1054 1054 function get_terms( $taxonomies, $args = '' ) { … … function get_terms( $taxonomies, $args = '' ) { 1489 1489 foreach ( $terms as $term ) { 1490 1490 $_terms[ $term->term_id ] = $term->slug; 1491 1491 } 1492 } else { 1493 $_terms = array_map( 'get_term', $terms ); 1492 1494 } 1493 1495 1494 1496 if ( ! empty( $_terms ) ) { … … function clean_term_cache($ids, $taxonomy = '', $clean_taxonomy = true) { 3422 3424 foreach ( (array) $terms as $term ) { 3423 3425 $taxonomies[] = $term->taxonomy; 3424 3426 $ids[] = $term->term_id; 3425 wp_cache_delete( $term->term_id, $term->taxonomy);3427 wp_cache_delete( $term->term_id, 'terms' ); 3426 3428 } 3427 3429 $taxonomies = array_unique($taxonomies); 3428 3430 } else { 3429 3431 $taxonomies = array($taxonomy); 3430 3432 foreach ( $taxonomies as $taxonomy ) { 3431 3433 foreach ( $ids as $id ) { 3432 wp_cache_delete( $id, $taxonomy);3434 wp_cache_delete( $id, 'terms' ); 3433 3435 } 3434 3436 } 3435 3437 } … … function update_term_cache( $terms, $taxonomy = '' ) { 3552 3554 if ( empty($term_taxonomy) ) 3553 3555 $term_taxonomy = $term->taxonomy; 3554 3556 3555 wp_cache_add( $term->term_id, $term, $term_taxonomy);3557 wp_cache_add( $term->term_id, $term, 'terms' ); 3556 3558 } 3557 3559 } 3558 3560 -
src/wp-includes/taxonomy.php
diff --git src/wp-includes/taxonomy.php src/wp-includes/taxonomy.php index e29e65c..13b50fd 100644
10 10 /** Core taxonomy functionality */ 11 11 require_once( ABSPATH . WPINC . '/taxonomy-functions.php' ); 12 12 13 /** WP_Term class */ 14 require_once( ABSPATH . WPINC . '/class-wp-term.php' ); 15 13 16 /** WP_Tax_Query class */ 14 17 require_once( ABSPATH . WPINC . '/class-wp-tax-query.php' ); -
tests/phpunit/tests/term/cache.php
diff --git tests/phpunit/tests/term/cache.php tests/phpunit/tests/term/cache.php index 1a31df0..a620986 100644
class Tests_Term_Cache extends WP_UnitTestCase { 103 103 ) ); 104 104 105 105 $term_object = get_term( $term, 'wptests_tax' ); 106 wp_cache_delete( $term, ' wptests_tax' );106 wp_cache_delete( $term, 'terms' ); 107 107 108 108 // Affirm that the cache is empty. 109 $this->assertEmpty( wp_cache_get( $term, ' wptests_tax' ) );109 $this->assertEmpty( wp_cache_get( $term, 'terms' ) ); 110 110 111 111 $num_queries = $wpdb->num_queries; 112 112 … … class Tests_Term_Cache extends WP_UnitTestCase { 128 128 'taxonomy' => 'wptests_tax', 129 129 ) ); 130 130 131 wp_cache_delete( $term, ' wptests_tax' );131 wp_cache_delete( $term, 'terms' ); 132 132 133 133 // Affirm that the cache is empty. 134 $this->assertEmpty( wp_cache_get( $term, ' wptests_tax' ) );134 $this->assertEmpty( wp_cache_get( $term, 'terms' ) ); 135 135 136 136 $num_queries = $wpdb->num_queries; 137 137 138 138 // Prime cache. 139 139 $term_object = get_term( $term, 'wptests_tax' ); 140 $this->assertNotEmpty( wp_cache_get( $term, ' wptests_tax' ) );140 $this->assertNotEmpty( wp_cache_get( $term, 'terms' ) ); 141 141 $this->assertSame( $num_queries + 1, $wpdb->num_queries ); 142 142 143 143 $term_object_2 = get_term( $term, 'wptests_tax' ); … … class Tests_Term_Cache extends WP_UnitTestCase { 155 155 'taxonomy' => 'wptests_tax', 156 156 ) ); 157 157 158 wp_cache_delete( $term, ' wptests_tax' );158 wp_cache_delete( $term, 'terms' ); 159 159 160 160 // Affirm that the cache is empty. 161 $this->assertEmpty( wp_cache_get( $term, ' wptests_tax' ) );161 $this->assertEmpty( wp_cache_get( $term, 'terms' ) ); 162 162 163 163 $num_queries = $wpdb->num_queries; 164 164 165 165 // Prime cache. 166 166 $term_object = get_term_by( 'id', $term, 'wptests_tax' ); 167 $this->assertNotEmpty( wp_cache_get( $term, ' wptests_tax' ) );167 $this->assertNotEmpty( wp_cache_get( $term, 'terms' ) ); 168 168 $this->assertSame( $num_queries + 1, $wpdb->num_queries ); 169 169 170 170 $term_object_2 = get_term( $term, 'wptests_tax' ); -
tests/phpunit/tests/term/getTerm.php
diff --git tests/phpunit/tests/term/getTerm.php tests/phpunit/tests/term/getTerm.php index 6c84d68..db895a0 100644
class Tests_Term_GetTerm extends WP_UnitTestCase { 35 35 $this->assertSame( $num_queries, $wpdb->num_queries ); 36 36 } 37 37 38 public function test_passing_term_object_should_not_skip_database_query_when_filter_property_is_set() {39 global $wpdb;40 41 $term = $this->factory->term->create_and_get( array( 'taxonomy' => 'wptests_tax' ) );42 clean_term_cache( $term->term_id, 'wptests_tax' );43 44 $num_queries = $wpdb->num_queries;45 46 $term_a = get_term( $term, 'wptests_tax' );47 48 $this->assertSame( $num_queries + 1, $wpdb->num_queries );49 }50 51 38 public function test_passing_term_string_that_casts_to_int_0_should_return_null() { 52 39 $this->assertSame( null, get_term( 'abc', 'wptests_tax' ) ); 53 40 }