Changeset 54692 for branches/6.1
- Timestamp:
- 10/25/2022 06:31:35 PM (2 years ago)
- Location:
- branches/6.1
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/6.1/src/wp-includes/class-wp-query.php
r54634 r54692 3107 3107 $id_query_is_cacheable = ! str_contains( strtoupper( $orderby ), ' RAND(' ); 3108 3108 if ( $q['cache_results'] && $id_query_is_cacheable ) { 3109 $cache_args = $q;3110 3111 unset(3112 $cache_args['suppress_filters'],3113 $cache_args['cache_results'],3114 $cache_args['fields'],3115 $cache_args['update_post_meta_cache'],3116 $cache_args['update_post_term_cache'],3117 $cache_args['lazy_load_term_meta'],3118 $cache_args['update_menu_item_cache'],3119 $cache_args['search_orderby_title']3120 );3121 3122 3109 $new_request = str_replace( $fields, "{$wpdb->posts}.*", $this->request ); 3123 $new_request = $wpdb->remove_placeholder_escape( $new_request ); 3124 $key = md5( serialize( $cache_args ) . $new_request ); 3125 3126 $last_changed = wp_cache_get_last_changed( 'posts' ); 3127 if ( ! empty( $this->tax_query->queries ) ) { 3128 $last_changed .= wp_cache_get_last_changed( 'terms' ); 3129 } 3130 3131 $cache_key = "wp_query:$key:$last_changed"; 3132 3133 /** 3134 * Filters query cache key. 3135 * 3136 * @since 6.1.0 3137 * 3138 * @param string $cache_key Cache key. 3139 * @param array $cache_args Query args used to generate the cache key. 3140 * @param string $new_request SQL Query. 3141 * @param WP_Query $query The WP_Query instance. 3142 */ 3143 $cache_key = apply_filters( 'wp_query_cache_key', $cache_key, $cache_args, $new_request, $this ); 3110 $cache_key = $this->generate_cache_key( $q, $new_request ); 3144 3111 3145 3112 $cache_found = false; … … 4756 4723 return $elements; 4757 4724 } 4725 4726 /** 4727 * Generate cache key. 4728 * 4729 * @since 6.1.0 4730 * 4731 * @global wpdb $wpdb WordPress database abstraction object. 4732 * 4733 * @param array $args Query arguments. 4734 * @param string $sql SQL statement. 4735 * 4736 * @return string Cache key. 4737 */ 4738 protected function generate_cache_key( array $args, $sql ) { 4739 global $wpdb; 4740 4741 unset( 4742 $args['cache_results'], 4743 $args['fields'], 4744 $args['lazy_load_term_meta'], 4745 $args['update_post_meta_cache'], 4746 $args['update_post_term_cache'], 4747 $args['update_menu_item_cache'], 4748 $args['suppress_filters'] 4749 ); 4750 4751 $placeholder = $wpdb->placeholder_escape(); 4752 array_walk_recursive( 4753 $args, 4754 /* 4755 * Replace wpdb placeholders with the string used in the database 4756 * query to avoid unreachable cache keys. This is necessary because 4757 * the placeholder is randomly generated in each request. 4758 * 4759 * $value is passed by reference to allow it to be modified. 4760 * array_walk_recursive() does not return an array. 4761 */ 4762 function ( &$value ) use ( $wpdb, $placeholder ) { 4763 if ( is_string( $value ) && str_contains( $value, $placeholder ) ) { 4764 $value = $wpdb->remove_placeholder_escape( $value ); 4765 } 4766 } 4767 ); 4768 4769 // Replace wpdb placeholder in the SQL statement used by the cache key. 4770 $sql = $wpdb->remove_placeholder_escape( $sql ); 4771 $key = md5( serialize( $args ) . $sql ); 4772 4773 $last_changed = wp_cache_get_last_changed( 'posts' ); 4774 if ( ! empty( $this->tax_query->queries ) ) { 4775 $last_changed .= wp_cache_get_last_changed( 'terms' ); 4776 } 4777 4778 return "wp_query:$key:$last_changed"; 4779 } 4780 4758 4781 /** 4759 4782 * After looping through a nested query, this function -
branches/6.1/tests/phpunit/tests/query/cacheResults.php
r54634 r54692 35 35 36 36 /** 37 * @var array 38 */ 39 protected $cache_args; 40 41 /** 42 * @var string 43 */ 44 protected $new_request; 37 * For testing test_generate_cache_key() includes a test containing the 38 * placeholder within the generated SQL query. 39 * 40 * @var bool 41 */ 42 public static $sql_placeholder_cache_key_tested = false; 43 44 /** 45 * For testing test_generate_cache_key() includes a test containing the 46 * placeholder within the generated WP_Query variables. 47 * 48 * @var bool 49 */ 50 public static $wp_query_placeholder_cache_key_tested = false; 45 51 46 52 public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) { … … 68 74 } 69 75 70 function set_up() { 71 parent::set_up(); 72 $this->cache_args = null; 73 $this->new_request = null; 74 add_filter( 'wp_query_cache_key', array( $this, 'filter_wp_query_cache_key' ), 15, 3 ); 75 } 76 77 /** 76 /** 77 * Ensure cache keys are generated without WPDB placeholders. 78 * 79 * @ticket 56802 80 * 81 * @covers WP_Query::generate_cache_key 82 * 78 83 * @dataProvider data_query_cache 84 */ 85 public function test_generate_cache_key( $args ) { 86 global $wpdb; 87 $query1 = new WP_Query(); 88 $query1->query( $args ); 89 90 $query_vars = $query1->query_vars; 91 $request = $query1->request; 92 $request_no_placeholder = $wpdb->remove_placeholder_escape( $request ); 93 94 $this->assertStringNotContainsString( $wpdb->placeholder_escape(), $request_no_placeholder, 'Placeholder escape should be removed from the modified request.' ); 95 96 if ( str_contains( $request, $wpdb->placeholder_escape() ) ) { 97 self::$sql_placeholder_cache_key_tested = true; 98 } 99 100 if ( str_contains( serialize( $query_vars ), $wpdb->placeholder_escape() ) ) { 101 self::$wp_query_placeholder_cache_key_tested = true; 102 } 103 104 $reflection = new ReflectionMethod( $query1, 'generate_cache_key' ); 105 $reflection->setAccessible( true ); 106 107 $cache_key_1 = $reflection->invoke( $query1, $query_vars, $request ); 108 $cache_key_2 = $reflection->invoke( $query1, $query_vars, $request_no_placeholder ); 109 110 $this->assertSame( $cache_key_1, $cache_key_2, 'Cache key differs when using wpdb placeholder.' ); 111 } 112 113 /** 114 * Ensure cache keys tests include WPDB placeholder in SQL Query. 115 * 116 * @ticket 56802 117 * 118 * @covers WP_Query::generate_cache_key 119 * 120 * @depends test_generate_cache_key 121 */ 122 public function test_sql_placeholder_cache_key_tested() { 123 $this->assertTrue( self::$sql_placeholder_cache_key_tested, 'Cache key containing WPDB placeholder in SQL query was not tested.' ); 124 } 125 126 /** 127 * Ensure cache keys tests include WPDB placeholder in WP_Query arguments. 128 * 129 * This test mainly covers the search query which generates the `search_orderby_title` 130 * query_var in WP_Query. 131 * 132 * @ticket 56802 133 * 134 * @covers WP_Query::generate_cache_key 135 * 136 * @depends test_generate_cache_key 137 */ 138 public function test_wp_query_placeholder_cache_key_tested() { 139 $this->assertTrue( self::$wp_query_placeholder_cache_key_tested, 'Cache key containing WPDB placeholder in WP_Query arguments was not tested.' ); 140 } 141 142 /** 143 * Ensure cache keys are generated without WPDB placeholders. 144 * 145 * @ticket 56802 146 * 147 * @covers WP_Query::generate_cache_key 148 */ 149 public function test_generate_cache_key_placeholder() { 150 global $wpdb; 151 $query1 = new WP_Query(); 152 $query1->query( array() ); 153 154 $query_vars = $query1->query_vars; 155 $request = $query1->request; 156 $query_vars['test']['nest'] = '%'; 157 $query_vars['test2']['nest']['nest']['nest'] = '%'; 158 $this->assertStringNotContainsString( $wpdb->placeholder_escape(), serialize( $query_vars ), 'Query vars should not contain the wpdb placeholder.' ); 159 160 $reflection = new ReflectionMethod( $query1, 'generate_cache_key' ); 161 $reflection->setAccessible( true ); 162 163 $cache_key_1 = $reflection->invoke( $query1, $query_vars, $request ); 164 165 $query_vars['test']['nest'] = $wpdb->placeholder_escape(); 166 $query_vars['test2']['nest']['nest']['nest'] = $wpdb->placeholder_escape(); 167 $this->assertStringContainsString( $wpdb->placeholder_escape(), serialize( $query_vars ), 'Query vars should not contain the wpdb placeholder.' ); 168 169 $cache_key_2 = $reflection->invoke( $query1, $query_vars, $request ); 170 171 $this->assertSame( $cache_key_1, $cache_key_2, 'Cache key differs when using wpdb placeholder.' ); 172 } 173 174 /** 175 * @dataProvider data_query_cache 79 176 * @ticket 22176 80 177 */ 81 178 public function test_query_cache( $args ) { 82 global $wpdb;83 84 179 $query1 = new WP_Query(); 85 180 $posts1 = $query1->query( $args ); 86 87 $placeholder = $wpdb->placeholder_escape();88 $this->assertNotEmpty( $this->new_request, 'Check new request is not empty' );89 $this->assertStringNotContainsString( $placeholder, $this->new_request, 'Check if request does not contain placeholder' );90 $this->assertStringNotContainsString( $placeholder, wp_json_encode( $this->cache_args ), 'Check if cache arrays does not contain placeholder' );91 181 92 182 $queries_before = get_num_queries(); … … 228 318 ), 229 319 ), 320 'cache nested meta query search' => array( 321 'args' => array( 322 'cache_results' => true, 323 'meta_query' => array( 324 'relation' => 'AND', 325 array( 326 'key' => 'color', 327 'value' => '00', 328 'compare' => 'LIKE', 329 ), 330 array( 331 'relation' => 'OR', 332 array( 333 'key' => 'color', 334 'value' => '00', 335 'compare' => 'LIKE', 336 ), 337 array( 338 'relation' => 'AND', 339 array( 340 'key' => 'wp_test_suite', 341 'value' => '56802', 342 'compare' => 'LIKE', 343 ), 344 array( 345 'key' => 'wp_test_suite_too', 346 'value' => '56802', 347 'compare' => 'LIKE', 348 ), 349 ), 350 ), 351 ), 352 ), 353 ), 230 354 'cache meta query not search' => array( 231 355 'args' => array( … … 888 1012 } 889 1013 890 public function filter_wp_query_cache_key( $cache_key, $cache_args, $new_request ) {891 $this->cache_args = $cache_args;892 $this->new_request = $new_request;893 894 return $cache_key;895 }896 897 1014 /** 898 1015 * @ticket 22176
Note: See TracChangeset
for help on using the changeset viewer.