index-wp-redis.php 10.1 KB
Newer Older
Benjamin Adams's avatar
Benjamin Adams committed
1
<?php
2 3 4 5 6 7 8 9
/**
 * WP REDIS CACHE
 */

/**
 * GLOBAL CONFIGURATION
 */
$GLOBALS['wp_redis_cache_config'] = array(
10 11 12 13 14 15 16 17
	'debug'          => false,
	'debug_messages' => '',
	'cache'          => false,
	'server_ip'      => '127.0.0.1',
	'redis_server'   => '127.0.0.1',
	'redis_port'     => 6379,
	'redis_db'       => 0,
	'secret_string'  => 'changeme',
18 19
);

20 21 22
// Uncomment either option below to fix the values here and disable the admin UI
// $GLOBALS['wp_redis_cache_config']['cache_duration'] = 43200;
// $GLOBALS['wp_redis_cache_config']['unlimited']      = false;
23

24 25 26 27 28
// Modify this function to introduce custom handling when exceptions occur
function wp_redis_cache_exception_handler( $exception ) {
	return;
}

29
/**
30 31
 * END GLOBAL CONFIGURATION
 *
32 33
 * DO NOT EDIT BELOW THIS LINE!
 */
Erick Hitter's avatar
Erick Hitter committed
34
$GLOBALS['wp_redis_cache_config']['current_url'] = wp_redis_cache_get_clean_url( $GLOBALS['wp_redis_cache_config']['secret_string'] );
35
$GLOBALS['wp_redis_cache_config']['redis_key']   = md5( $GLOBALS['wp_redis_cache_config']['current_url'] );
Benjamin Adams's avatar
Benjamin Adams committed
36

Ulrich Block's avatar
Ulrich Block committed
37
// Start the timer so we can track the page load time
38 39 40
if ( $GLOBALS['wp_redis_cache_config']['debug'] ) {
	$start = microtime();
}
Ulrich Block's avatar
Ulrich Block committed
41

42 43 44 45 46 47 48
/**
 * MOBILE HANDLING
 */
if ( wp_redis_cache_is_mobile_request() ) {
	$GLOBALS['wp_redis_cache_config']['redis_key'] = 'MO-' . $GLOBALS['wp_redis_cache_config']['redis_key'];
}

49 50 51 52 53 54 55 56 57
/**
 * UTILITY FUNCTIONS
 */

/**
 * Compute microtime from a timestamp
 *
 * @return float
 */
Erick Hitter's avatar
Erick Hitter committed
58
function wp_redis_cache_get_micro_time( $time ) {
Erick Hitter's avatar
Erick Hitter committed
59 60
	list( $usec, $sec ) = explode( " ", $time );
	return ( (float) $usec + (float) $sec );
Ulrich Block's avatar
Ulrich Block committed
61 62
}

63 64 65 66 67
/**
 * Is the current request a refresh request with the correct secret key?
 *
 * @return bool
 */
Erick Hitter's avatar
Erick Hitter committed
68
function wp_redis_cache_refresh_has_secret( $secret ) {
Erick Hitter's avatar
Erick Hitter committed
69
	return isset( $_GET['refresh'] ) && $secret == $_GET['refresh'];
Benjamin Adams's avatar
merged  
Benjamin Adams committed
70
}
Ulrich Block's avatar
Ulrich Block committed
71

72 73 74 75 76
/**
 * Does current request include a refresh request?
 *
 * @return bool
 */
Erick Hitter's avatar
Erick Hitter committed
77
function wp_redis_cache_request_has_secret( $secret ) {
Erick Hitter's avatar
Erick Hitter committed
78
	return false !== strpos( $_SERVER['REQUEST_URI'], "refresh=${secret}" );
Benjamin Adams's avatar
merged  
Benjamin Adams committed
79
}
Hendrik Klemp's avatar
Hendrik Klemp committed
80

81 82 83 84 85
/**
 * Determine if request is from a server other than the one running this code
 *
 * @return bool
 */
Erick Hitter's avatar
Erick Hitter committed
86
function wp_redis_cache_is_remote_page_load( $current_url, $server_ip ) {
Erick Hitter's avatar
Erick Hitter committed
87
	return ( isset( $_SERVER['HTTP_REFERER'] )
88
			&& $_SERVER['HTTP_REFERER'] == $current_url
Erick Hitter's avatar
Erick Hitter committed
89
			&& $_SERVER['REQUEST_URI'] != '/'
90
			&& $_SERVER['REMOTE_ADDR'] != $server_ip );
Benjamin Adams's avatar
merged  
Benjamin Adams committed
91
}
Hendrik Klemp's avatar
Hendrik Klemp committed
92

93 94 95 96 97
/**
 * Set proper IP address for proxied requests
 *
 * @return null
 */
Erick Hitter's avatar
Erick Hitter committed
98
function wp_redis_cache_handle_cdn_remote_addressing() {
Erick Hitter's avatar
Erick Hitter committed
99
	// so we don't confuse the cloudflare server
Erick Hitter's avatar
Erick Hitter committed
100
	if ( isset( $_SERVER['HTTP_CF_CONNECTING_IP'] ) ) {
Erick Hitter's avatar
Erick Hitter committed
101 102
		$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_CF_CONNECTING_IP'];
	}
Benjamin Adams's avatar
merged  
Benjamin Adams committed
103
}
104

105 106 107 108 109 110 111 112
/**
 * Prepare a URL for use as a cache key
 *
 * Strips secret key from URL
 *
 * @param string
 * @return string
 */
Erick Hitter's avatar
Erick Hitter committed
113
function wp_redis_cache_get_clean_url( $secret ) {
114
	$replace_keys = array( "?refresh=${secret}","&refresh=${secret}" );
115 116
	$url          = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
	return str_replace( $replace_keys, '', $url );
Benjamin Adams's avatar
Benjamin Adams committed
117
}
Benjamin Adams's avatar
merged  
Benjamin Adams committed
118

119 120 121 122 123 124 125
/**
 *
 */
function wp_redis_cache_is_mobile_request() {
	return false;
}

126
/**
127 128 129 130 131
 * Establish a connection to the Redis server
 *
 * Will try the PECL module first, then fall back to PRedis
 *
 * @return object
132
 */
133
function wp_redis_cache_connect_redis() {
Erick Hitter's avatar
Erick Hitter committed
134
	// check if PECL Extension is available
Erick Hitter's avatar
Erick Hitter committed
135
	if ( class_exists( 'Redis' ) ) {
136
		if ( $GLOBALS['wp_redis_cache_config']['debug'] ) {
137
			$GLOBALS['wp_redis_cache_config']['debug_messages'] .= "<!-- Redis PECL module found -->\n";
Erick Hitter's avatar
Erick Hitter committed
138
		}
Erick Hitter's avatar
Erick Hitter committed
139

Erick Hitter's avatar
Erick Hitter committed
140 141 142
		$redis = new Redis();

		// Sockets can be used as well. Documentation @ https://github.com/nicolasff/phpredis/#connection
143 144
		$redis->connect( $GLOBALS['wp_redis_cache_config']['redis_server'], $GLOBALS['wp_redis_cache_config']['redis_port'] );
		$redis->select( $GLOBALS['wp_redis_cache_config']['redis_db'] );
Erick Hitter's avatar
Erick Hitter committed
145
	} else { // Fallback to predis5.2.php
146
		if ( $GLOBALS['wp_redis_cache_config']['debug'] ) {
147
			$GLOBALS['wp_redis_cache_config']['debug_messages'] .= "<!-- using predis as a backup -->\n";
Erick Hitter's avatar
Erick Hitter committed
148
		}
Erick Hitter's avatar
Erick Hitter committed
149

150
		include_once dirname( __FILE__ ) . '/wp-content/plugins/wp-redis-cache/predis5.2.php'; //we need this to use Redis inside of PHP
151
		$redis = new Predis_Client( array(
152 153 154
			'host'     => $GLOBALS['wp_redis_cache_config']['redis_server'],
			'port'     => $GLOBALS['wp_redis_cache_config']['redis_port'],
			'database' => $GLOBALS['wp_redis_cache_config']['redis_db'],
155
		) );
Erick Hitter's avatar
Erick Hitter committed
156 157
	}

158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
	return $redis;
}

/**
 * BEGIN CACHING LOGIC
 */

// Set proper IP for proxied requests
wp_redis_cache_handle_cdn_remote_addressing();

// Ensure WP uses a theme (this is normally set in index.php)
if ( ! defined( 'WP_USE_THEMES' ) ) {
	define( 'WP_USE_THEMES', true );
}

try {
	// Establish connection with Redis server
	$redis = wp_redis_cache_connect_redis();

177 178 179
	// Whether we need to load WP
	$load_wp = true;

180 181 182 183
	// Relevant details on the current request
	$is_post   = (bool) 'POST' === $_SERVER['REQUEST_METHOD'];
	$logged_in = (bool) preg_match( "#(wordpress_(logged|sec)|comment_author)#", var_export( $_COOKIE, true ) );

184
	if ( $GLOBALS['wp_redis_cache_config']['debug'] ) {
185 186
		$GLOBALS['wp_redis_cache_config']['debug_messages'] .= "<!-- POST request: . " . ( $is_post ? 'yes' : 'no' ) . "-->\n";
		$GLOBALS['wp_redis_cache_config']['debug_messages'] .= "<!-- Logged in: . " . ( $logged_in ? 'yes' : 'no' ) . "-->\n";
187 188 189
	}

	// Refresh request, deletes cache: either manual refresh cache by adding ?refresh=secret_string after the URL or somebody posting a comment
Erick Hitter's avatar
Erick Hitter committed
190
	if ( wp_redis_cache_refresh_has_secret( $GLOBALS['wp_redis_cache_config']['secret_string'] ) || wp_redis_cache_request_has_secret( $GLOBALS['wp_redis_cache_config']['secret_string'] ) || wp_redis_cache_is_remote_page_load( $GLOBALS['wp_redis_cache_config']['current_url'], $GLOBALS['wp_redis_cache_config']['server_ip'] ) ) {
191
		if ( $GLOBALS['wp_redis_cache_config']['debug'] ) {
192
			$GLOBALS['wp_redis_cache_config']['debug_messages'] .= "<!-- manual refresh was required -->\n";
Erick Hitter's avatar
Erick Hitter committed
193
		}
Erick Hitter's avatar
Erick Hitter committed
194

195
		$redis->del( $GLOBALS['wp_redis_cache_config']['redis_key'] );
196
	// This page is cached, the user isn't logged in, and it isn't a POST request, so let's use the cache
197 198
	} elseif ( ! $is_post && ! $logged_in && $redis->exists( $GLOBALS['wp_redis_cache_config']['redis_key'] ) ) {
		if ( $GLOBALS['wp_redis_cache_config']['debug'] ) {
199
			$GLOBALS['wp_redis_cache_config']['debug_messages'] .= "<!-- serving page from cache: key: " . $GLOBALS['wp_redis_cache_config']['redis_key'] . " -->\n";
200 201
		}

202 203
		// Page is served from cache, so we don't need WP
		$load_wp = false;
204 205
		$GLOBALS['wp_redis_cache_config']['cached'] = true;

206
		echo trim( $redis->get( $GLOBALS['wp_redis_cache_config']['redis_key'] ) );
Erick Hitter's avatar
Erick Hitter committed
207
	// If the cache does not exist lets display the user the normal page without cache, and then fetch a new cache page
208 209 210
	} elseif ( $_SERVER['REMOTE_ADDR'] != $GLOBALS['wp_redis_cache_config']['server_ip'] ) {
		if ( false === strstr( $GLOBALS['wp_redis_cache_config']['current_url'], 'preview=true' ) ) {
			if ( $GLOBALS['wp_redis_cache_config']['debug'] ) {
211
				$GLOBALS['wp_redis_cache_config']['debug_messages'] .= "<!-- displaying page without cache -->\n";
212
			}
213

214 215 216 217 218 219 220
			// If user isn't logged in and this isn't a post request, render the requested page and cache if appropriate.
			if ( ! $is_post && ! $logged_in ) {
				// We load WP to generate the cached output, so no need to load again
				$load_wp = false;

				// Render page into an output buffer and display
				ob_start();
221
				require_once dirname( __FILE__ ) . '/wp-blog-header.php';
222 223 224 225 226 227 228 229
				$markup_to_cache = trim( ob_get_clean() );
				echo $markup_to_cache;

				// Cache rendered page if appropriate
				if ( ! is_404() && ! is_search() ) {
					// Is unlimited cache life requested?
					if ( isset( $GLOBALS['wp_redis_cache_config']['unlimited'] ) ) {
						$unlimited = $GLOBALS['wp_redis_cache_config']['unlimited'];
230
					} else {
231 232
						$unlimited = (bool) get_option( 'wp-redis-cache-debug', false );
						$GLOBALS['wp_redis_cache_config']['unlimited'] = $unlimited;
233 234
					}

235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
					// Cache the page for the chosen duration
					if ( $unlimited ) {
						$redis->set( $GLOBALS['wp_redis_cache_config']['redis_key'], $markup_to_cache );
					} else {
						if ( isset( $GLOBALS['wp_redis_cache_config']['cache_duration'] ) ) {
							$cache_duration = $GLOBALS['wp_redis_cache_config']['cache_duration'];
						} else {
							$cache_duration = (int) get_option( 'wp-redis-cache-seconds', 43200 );
							$GLOBALS['wp_redis_cache_config']['cache_duration'] = $cache_duration;
						}

						if ( ! is_numeric( $cache_duration ) ) {
							$cache_duration = $GLOBALS['wp_redis_cache_config']['cache_duration'] = 43200;
						}

						$redis->setex( $GLOBALS['wp_redis_cache_config']['redis_key'], $cache_duration, $markup_to_cache );
251
					}
Erick Hitter's avatar
Erick Hitter committed
252
				}
253 254 255
			}
		}
	}
256 257 258

	// The current request wasn't served from cache or isn't cacheable, so we pass off to WP
	if ( $load_wp ) {
259
		require_once dirname( __FILE__ ) . '/wp-blog-header.php';
Erick Hitter's avatar
Erick Hitter committed
260
	}
Erick Hitter's avatar
Erick Hitter committed
261
} catch ( Exception $e ) {
262
	require_once dirname( __FILE__ ) . '/wp-blog-header.php';
263
	wp_redis_cache_exception_handler( $e );
Benjamin Adams's avatar
Benjamin Adams committed
264 265
}

266 267 268
/**
 * DEBUGGING OUTPUT
 */
269
if ( $GLOBALS['wp_redis_cache_config']['debug'] ) {
270 271 272 273
	$end  = microtime();
	$time = @wp_redis_cache_get_micro_time( $end ) - @wp_redis_cache_get_micro_time( $start );
	$GLOBALS['wp_redis_cache_config']['debug_messages'] .= "<!-- Cache system by Benjamin Adams. Page generated in " . round($time, 5) . " seconds. -->\n";
	$GLOBALS['wp_redis_cache_config']['debug_messages'] .= "<!-- Site was cached = " . $GLOBALS['wp_redis_cache_config']['cached'] . " -->\n";
274
	if ( isset( $GLOBALS['wp_redis_cache_config']['cache_duration'] ) ) {
275
		$GLOBALS['wp_redis_cache_config']['debug_messages'] .= "<!-- wp-redis-cache-seconds = " . $GLOBALS['wp_redis_cache_config']['cache_duration'] . " -->\n";
Erick Hitter's avatar
Erick Hitter committed
276
	}
277
	$GLOBALS['wp_redis_cache_config']['debug_messages'] .= "<!-- wp-redis-cache-ip = " . $GLOBALS['wp_redis_cache_config']['server_ip'] . "-->\n";
278
	if ( isset( $GLOBALS['wp_redis_cache_config']['unlimited'] ) ) {
279
		$GLOBALS['wp_redis_cache_config']['debug_messages'] .= "<!-- wp-redis-cache-unlimited = " . $GLOBALS['wp_redis_cache_config']['unlimited'] . "-->\n";
Erick Hitter's avatar
Erick Hitter committed
280
	}
281 282 283
	$GLOBALS['wp_redis_cache_config']['debug_messages'] .= "<!-- wp-redis-cache-debug = " . $GLOBALS['wp_redis_cache_config']['debug'] . "-->\n";

	echo $GLOBALS['wp_redis_cache_config']['debug_messages'];
Benjamin Adams's avatar
Benjamin Adams committed
284
}