WordPress.org

Make WordPress Core

Opened 6 years ago

Last modified 5 months ago

#27276 new defect (bug)

wp_rewrite_rule does not update option when it's empty

Reported by: mainpart Owned by:
Milestone: Priority: normal
Severity: normal Version: 3.7
Component: Rewrite Rules Keywords: needs-patch
Focuses: Cc:
PR Number:

Description

This bug report about possible problems with situation when deleted options still present in cache. I'm using memcache so my cache is transistient.

i've been adding rewrite_rule

function duke_add_endpoints() {  
add_rewrite_rule('...','...');
global $wp_rewrite;
$wp_rewrite->flush_rules();
}  
add_action( 'init', 'duke_add_endpoints');  

and discovered that i can't get it work because of it completely absence in further $wp_rewrite references.

Intrigued by that fact (especialy with hard flushing) i've been lead to parse_requestof class-wp and due to it's

$rewrite = $wp_rewrite->wp_rewrite_rules();

i guided to wp_rewrite_rules method of wp-includes/rewrite.php where discovered that rewrite_rules option is loaded from wp_options but if it's not there - it loaded from cache (bacause of get_option behaviour).

$alloptions = wp_load_alloptions();
if ( isset( $alloptions[$option] ) ) {
 $value = $alloptions[$option];
} else {
 $value = wp_cache_get( $option, 'options' );
 if ( false === $value ) {
	$row = $wpdb->get_row(.... 

Wondering why it was not overriden by flush_rules both in wp_options and in cache i've dig into flush_rules and discovered that it operates the same method

	function flush_rules($hard = true) {
		delete_option('rewrite_rules');
		$this->wp_rewrite_rules();
                .......

but wait... IF THE REWRITE_RULES IS NOT IN THE WP_OPTION then it still taken from cache with previous value.

	function wp_rewrite_rules() {
		$this->rules = get_option('rewrite_rules');
                ///at this point the value already deleted from table but still remains in cache so get_option returns OLD value till it remain in cache for indefinite time
		if ( empty($this->rules) ) {
			$this->matches = 'matches';
                        
			$this->rewrite_rules();
			update_option('rewrite_rules', $this->rules);
		}

		return $this->rules;
	}

so if your rewrite rules not in table but in cache - they probably stuck there forever till cache gets cleared. i guess it has something to infere with delete_option and situation when cache is not cleared. but i guess it's next bug to catch.

Change History (4)

#1 @SergeyBiryukov
6 years ago

  • Component changed from Cache API to Rewrite Rules

#2 @SergeyBiryukov
6 years ago

delete_option() specifically clears the deleted value from cache: tags/3.8.1/src/wp-includes/option.php#L370. Looks like it failed here. Might be related to #25773.

#4 @chriscct7
4 years ago

  • Keywords needs-patch added
Note: See TracTickets for help on using tickets.