= 1.8.4 =

*2015-10-13*

* changes in HTML debug comment: instead of the former, single comment, now 2 comments are added. The first is added when the cache entry is generated; the second only appears if the page was served from the cached entry. Please note that this last bit will - should - change with every single refresh.
* backend code is now split into separate files
* more debug code
This commit is contained in:
Peter Molnar 2015-10-13 11:13:13 +01:00
parent 7b16741af8
commit 457ad184c4
9 changed files with 756 additions and 684 deletions

92
backends/apc.php Normal file
View file

@ -0,0 +1,92 @@
<?php
if (!class_exists('WP_FFPC_Backend_apc')):
class WP_FFPC_Backend_apc extends WP_FFPC_Backend {
/**
* init apc backend: test APC availability and set alive status
*/
protected function _init () {
/* verify apc functions exist, apc extension is loaded */
if ( ! function_exists( 'apc_cache_info' ) ) {
$this->log ( __translate__('APC extension missing', $this->plugin_constant ) );
return false;
}
/* verify apc is working */
if ( apc_cache_info("user",true) ) {
$this->log ( __translate__('backend OK', $this->plugin_constant ) );
$this->alive = true;
}
}
/**
* health checker for APC
*
* @return boolean Aliveness status
*
*/
protected function _status () {
$this->status = true;
return $this->alive;
}
/**
* get function for APC backend
*
* @param string $key Key to get values for
*
* @return mixed Fetched data based on key
*
*/
protected function _get ( &$key ) {
return apc_fetch( $key );
}
/**
* Set function for APC backend
*
* @param string $key Key to set with
* @param mixed $data Data to set
*
* @return boolean APC store outcome
*/
protected function _set ( &$key, &$data, &$expire ) {
return apc_store( $key , $data , $expire );
}
/**
* Flushes APC user entry storage
*
* @return boolean APC flush outcome status
*
*/
protected function _flush ( ) {
return apc_clear_cache('user');
}
/**
* Removes entry from APC or flushes APC user entry storage
*
* @param mixed $keys Keys to clear, string or array
*/
protected function _clear ( &$keys ) {
/* make an array if only one string is present, easier processing */
if ( !is_array ( $keys ) )
$keys = array ( $keys => true );
foreach ( $keys as $key => $dummy ) {
if ( ! apc_delete ( $key ) ) {
$this->log ( sprintf( __translate__( 'Failed to delete APC entry: %s', $this->plugin_constant ), $key ), LOG_WARNING );
//throw new Exception ( __translate__('Deleting APC entry failed with key ', $this->plugin_constant ) . $key );
}
else {
$this->log ( sprintf( __translate__( 'APC entry delete: %s', $this->plugin_constant ), $key ) );
}
}
}
}
endif;

92
backends/apcu.php Normal file
View file

@ -0,0 +1,92 @@
<?php
if (!class_exists('WP_FFPC_Backend_apcu')):
class WP_FFPC_Backend_apcu extends WP_FFPC_Backend {
/**
* init apcu backend: test APCu availability and set alive status
*/
protected function _init () {
/* verify apcu functions exist, apcu extension is loaded */
if ( ! function_exists( 'apcu_cache_info' ) ) {
$this->log ( __translate__('APCu extension missing', $this->plugin_constant ) );
return false;
}
/* verify apcu is working */
if ( @apcu_cache_info("user") != false ) {
$this->log ( __translate__('backend OK', $this->plugin_constant ) );
$this->alive = true;
}
}
/**
* health checker for APC
*
* @return boolean Aliveness status
*
*/
protected function _status () {
$this->status = true;
return $this->alive;
}
/**
* get function for APC backend
*
* @param string $key Key to get values for
*
* @return mixed Fetched data based on key
*
*/
protected function _get ( &$key ) {
return apcu_fetch( $key );
}
/**
* Set function for APC backend
*
* @param string $key Key to set with
* @param mixed $data Data to set
*
* @return boolean APC store outcome
*/
protected function _set ( &$key, &$data, &$expire ) {
return apcu_store( $key , $data , $expire );
}
/**
* Flushes APC user entry storage
*
* @return boolean APC flush outcome status
*
*/
protected function _flush ( ) {
return apcu_clear_cache();
}
/**
* Removes entry from APC or flushes APC user entry storage
*
* @param mixed $keys Keys to clear, string or array
*/
protected function _clear ( &$keys ) {
/* make an array if only one string is present, easier processing */
if ( !is_array ( $keys ) )
$keys = array ( $keys => true );
foreach ( $keys as $key => $dummy ) {
if ( ! apcu_delete ( $key ) ) {
$this->log ( sprintf( __translate__( 'Failed to delete APC entry: %s', $this->plugin_constant ), $key ), LOG_WARNING );
//throw new Exception ( __translate__('Deleting APC entry failed with key ', $this->plugin_constant ) . $key );
}
else {
$this->log ( sprintf( __translate__( 'APC entry delete: %s', $this->plugin_constant ), $key ) );
}
}
}
}
endif;

122
backends/memcache.php Normal file
View file

@ -0,0 +1,122 @@
<?php
if (!class_exists('WP_FFPC_Backend_memcache')):
class WP_FFPC_Backend_memcache extends WP_FFPC_Backend {
/**
* init memcache backend
*/
protected function _init () {
/* Memcached class does not exist, Memcache extension is not available */
if (!class_exists('Memcache')) {
$this->log ( __translate__('PHP Memcache extension missing', $this->plugin_constant ), LOG_WARNING );
return false;
}
/* check for existing server list, otherwise we cannot add backends */
if ( empty ( $this->options['servers'] ) && ! $this->alive ) {
$this->log ( __translate__("servers list is empty, init failed", $this->plugin_constant ), LOG_WARNING );
return false;
}
/* check is there's no backend connection yet */
if ( $this->connection === NULL )
$this->connection = new Memcache();
/* check if initialization was success or not */
if ( $this->connection === NULL ) {
$this->log ( __translate__( 'error initializing Memcache PHP extension, exiting', $this->plugin_constant ) );
return false;
}
/* adding servers */
foreach ( $this->options['servers'] as $server_id => $server ) {
/* in case of unix socket */
if ( $server['port'] === 0 )
$this->status[$server_id] = $this->connection->connect ( 'unix:/' . $server['host'] );
else
$this->status[$server_id] = $this->connection->connect ( $server['host'] , $server['port'] );
$this->log ( sprintf( __translate__( '%s added', $this->plugin_constant ), $server_id ) );
}
/* backend is now alive */
$this->alive = true;
$this->_status();
}
/**
* check current backend alive status for Memcached
*
*/
protected function _status () {
/* server status will be calculated by getting server stats */
$this->log ( __translate__("checking server statuses", $this->plugin_constant ));
/* get servers statistic from connection */
foreach ( $this->options['servers'] as $server_id => $server ) {
if ( $server['port'] === 0 )
$this->status[$server_id] = $this->connection->getServerStatus( $server['host'], 11211 );
else
$this->status[$server_id] = $this->connection->getServerStatus( $server['host'], $server['port'] );
if ( $this->status[$server_id] == 0 )
$this->log ( sprintf( __translate__( '%s server is down', $this->plugin_constant ), $server_id ) );
else
$this->log ( sprintf( __translate__( '%s server is up & running', $this->plugin_constant ), $server_id ) );
}
}
/**
* get function for Memcached backend
*
* @param string $key Key to get values for
*
*/
protected function _get ( &$key ) {
return $this->connection->get($key);
}
/**
* Set function for Memcached backend
*
* @param string $key Key to set with
* @param mixed $data Data to set
*
*/
protected function _set ( &$key, &$data, &$expire ) {
$result = $this->connection->set ( $key, $data , 0 , $expire );
return $result;
}
/**
*
* Flush memcached entries
*/
protected function _flush ( ) {
return $this->connection->flush();
}
/**
* Removes entry from Memcached or flushes Memcached storage
*
* @param mixed $keys String / array of string of keys to delete entries with
*/
protected function _clear ( &$keys ) {
/* make an array if only one string is present, easier processing */
if ( !is_array ( $keys ) )
$keys = array ( $keys => true );
foreach ( $keys as $key => $dummy ) {
$kresult = $this->connection->delete( $key );
if ( $kresult === false ) {
$this->log ( sprintf( __translate__( 'unable to delete entry: %s', $this->plugin_constant ), $key ) );
}
else {
$this->log ( sprintf( __translate__( 'entry deleted: %s', $this->plugin_constant ), $key ) );
}
}
}
}
endif;

159
backends/memcached.php Normal file
View file

@ -0,0 +1,159 @@
<?php
if (!class_exists('WP_FFPC_Backend_memcached')):
class WP_FFPC_Backend_memcached extends WP_FFPC_Backend {
protected function _init () {
/* Memcached class does not exist, Memcached extension is not available */
if (!class_exists('Memcached')) {
$this->log ( __translate__(' Memcached extension missing, wp-ffpc will not be able to function correctly!', $this->plugin_constant ), LOG_WARNING );
return false;
}
/* check for existing server list, otherwise we cannot add backends */
if ( empty ( $this->options['servers'] ) && ! $this->alive ) {
$this->log ( __translate__("Memcached servers list is empty, init failed", $this->plugin_constant ), LOG_WARNING );
return false;
}
/* check is there's no backend connection yet */
if ( $this->connection === NULL ) {
$this->connection = new Memcached();
/* use binary and not compressed format, good for nginx and still fast */
$this->connection->setOption( Memcached::OPT_COMPRESSION , false );
if ($this->options['memcached_binary']){
$this->connection->setOption( Memcached::OPT_BINARY_PROTOCOL , true );
}
if ( version_compare( phpversion( 'memcached' ) , '2.0.0', '>=' ) && ini_get( 'memcached.use_sasl' ) == 1 && isset($this->options['authpass']) && !empty($this->options['authpass']) && isset($this->options['authuser']) && !empty($this->options['authuser']) ) {
$this->connection->setSaslAuthData ( $this->options['authuser'], $this->options['authpass']);
}
}
/* check if initialization was success or not */
if ( $this->connection === NULL ) {
$this->log ( __translate__( 'error initializing Memcached PHP extension, exiting', $this->plugin_constant ) );
return false;
}
/* check if we already have list of servers, only add server(s) if it's not already connected */
$servers_alive = array();
if ( !empty ( $this->status ) ) {
$servers_alive = $this->connection->getServerList();
/* create check array if backend servers are already connected */
if ( !empty ( $servers ) ) {
foreach ( $servers_alive as $skey => $server ) {
$skey = $server['host'] . ":" . $server['port'];
$servers_alive[ $skey ] = true;
}
}
}
/* adding servers */
foreach ( $this->options['servers'] as $server_id => $server ) {
/* reset server status to unknown */
//$this->status[$server_id] = -1;
/* only add servers that does not exists already in connection pool */
if ( !@array_key_exists($server_id , $servers_alive ) ) {
$this->connection->addServer( $server['host'], $server['port'] );
$this->log ( sprintf( __translate__( '%s added', $this->plugin_constant ), $server_id ) );
}
}
/* backend is now alive */
$this->alive = true;
$this->_status();
}
/**
* sets current backend alive status for Memcached servers
*
*/
protected function _status () {
/* server status will be calculated by getting server stats */
$this->log ( __translate__("checking server statuses", $this->plugin_constant ));
/* get server list from connection */
$servers = $this->connection->getServerList();
foreach ( $servers as $server ) {
$server_id = $server['host'] . self::port_separator . $server['port'];
/* reset server status to offline */
$this->status[$server_id] = 0;
if ($this->connection->set($this->plugin_constant, time())) {
$this->log ( sprintf( __translate__( '%s server is up & running', $this->plugin_constant ), $server_id ) );
$this->status[$server_id] = 1;
}
}
}
/**
* get function for Memcached backend
*
* @param string $key Key to get values for
*
*/
protected function _get ( &$key ) {
return $this->connection->get($key);
}
/**
* Set function for Memcached backend
*
* @param string $key Key to set with
* @param mixed $data Data to set
*
*/
protected function _set ( &$key, &$data, &$expire ) {
$result = $this->connection->set ( $key, $data , $expire );
/* if storing failed, log the error code */
if ( $result === false ) {
$code = $this->connection->getResultCode();
$this->log ( sprintf( __translate__( 'unable to set entry: %s', $this->plugin_constant ), $key ) );
$this->log ( sprintf( __translate__( 'Memcached error code: %s', $this->plugin_constant ), $code ) );
//throw new Exception ( __translate__('Unable to store Memcached entry ', $this->plugin_constant ) . $key . __translate__( ', error code: ', $this->plugin_constant ) . $code );
}
return $result;
}
/**
*
* Flush memcached entries
*/
protected function _flush ( ) {
return $this->connection->flush();
}
/**
* Removes entry from Memcached or flushes Memcached storage
*
* @param mixed $keys String / array of string of keys to delete entries with
*/
protected function _clear ( &$keys ) {
/* make an array if only one string is present, easier processing */
if ( !is_array ( $keys ) )
$keys = array ( $keys => true );
foreach ( $keys as $key => $dummy ) {
$kresult = $this->connection->delete( $key );
if ( $kresult === false ) {
$code = $this->connection->getResultCode();
$this->log ( sprintf( __translate__( 'unable to delete entry: %s', $this->plugin_constant ), $key ) );
$this->log ( sprintf( __translate__( 'Memcached error code: %s', $this->plugin_constant ), $code ) );
}
else {
$this->log ( sprintf( __translate__( 'entry deleted: %s', $this->plugin_constant ), $key ) );
}
}
}
}
endif;

156
backends/redis.php Normal file
View file

@ -0,0 +1,156 @@
<?php
if (!class_exists('WP_FFPC_Backend_redis')):
class WP_FFPC_Backend_redis extends WP_FFPC_Backend {
protected function _init () {
/* Memcached class does not exist, Memcached extension is not available */
if (!class_exists('Redis')) {
$this->log ( __translate__('Redis extension missing, wp-ffpc will not be able to function correctly!', $this->plugin_constant ), LOG_WARNING );
return false;
}
/* check for existing server list, otherwise we cannot add backends */
if ( empty ( $this->options['servers'] ) && ! $this->alive ) {
$this->log ( __translate__("Redis servers list is empty, init failed", $this->plugin_constant ), LOG_WARNING );
return false;
}
/* check is there's no backend connection yet */
if ( $this->connection === NULL ) {
$this->connection = new Redis();
}
/* check if initialization was success or not */
if ( $this->connection === NULL ) {
$this->log ( __translate__( 'error initializing Redis PHP extension, exiting', $this->plugin_constant ) );
return false;
}
/* check if we already have list of servers, only add server(s) if it's not already connected *
$servers_alive = array();
if ( !empty ( $this->status ) ) {
$servers_alive = $this->connection->getServerList();
/* create check array if backend servers are already connected *
if ( !empty ( $servers ) ) {
foreach ( $servers_alive as $skey => $server ) {
$skey = $server['host'] . ":" . $server['port'];
$servers_alive[ $skey ] = true;
}
}
}
/* adding servers */
foreach ( $this->options['servers'] as $server_id => $server ) {
/* only add servers that does not exists already in connection pool */
if ( !@array_key_exists($server_id , $servers_alive ) ) {
if ( $server['port'] != 0)
$this->connection->connect($server['host'], $server['port'] );
else
$this->connection->connect($server['host'] );
if ( isset($this->options['authpass']) && !empty($this->options['authpass']) )
$this->connection->auth ( $this->options['authpass'] );
$this->log ( sprintf( __translate__( '%s added', $this->plugin_constant ), $server_id ) );
}
}
/* backend is now alive */
$this->alive = true;
$this->_status();
}
/**
* sets current backend alive status for Memcached servers
*
*/
protected function _status () {
/* server status will be calculated by getting server stats */
$this->log ( __translate__("checking server status", $this->plugin_constant ));
try {
$info = $this->connection->ping();
} catch ( Exception $e ) {
$this->log ( __translate__("Exception occured: " . json_encode($e), $this->plugin_constant ));
}
$status = empty( $info ) ? 0 : 1;
foreach ( $this->options['servers'] as $server_id => $server ) {
/* reset server status to offline */
$this->status[$server_id] = $status;
}
}
/**
* get function for Memcached backend
*
* @param string $key Key to get values for
*
*/
protected function _get ( &$key ) {
return $this->connection->get($key);
}
/**
* Set function for Memcached backend
*
* @param string $key Key to set with
* @param mixed $data Data to set
*
*/
protected function _set ( &$key, &$data, &$expire ) {
$result = $this->connection->set ( $key, $data, $expire );
/* if storing failed, log the error code */
//if ( $result === false ) {
$this->log ( sprintf( __translate__( 'set entry returned: %s', $this->plugin_constant ), $result ) );
//}
return $result;
}
/**
*
* Flush memcached entries
*/
protected function _flush ( ) {
try {
$r = $this->connection->flushDB();
} catch ( Exception $e ) {
$this->log ( sprintf( __translate__( 'unable to flush, error: %s', $this->plugin_constant ), json_encode($r) ) );
}
return $r;
}
/**
* Removes entry from Memcached or flushes Memcached storage
*
* @param mixed $keys String / array of string of keys to delete entries with
*/
protected function _clear ( &$keys ) {
/* make an array if only one string is present, easier processing */
if ( !is_array ( $keys ) )
$keys = array ( $keys => true );
try {
$kresult = $this->connection->delete( $keys );
} catch ( Exception $e ) {
$this->log ( sprintf( __translate__( 'unable to delete entry(s): %s', $this->plugin_constant ), json_encode($key) ) );
$this->log ( sprintf( __translate__( 'Redis error: %s', $this->plugin_constant ), json_encode($e) ) );
}
finally {
$this->log ( sprintf( __translate__( 'entry(s) deleted: %s', $this->plugin_constant ), json_encode($keys) ) );
}
}
}
endif;

View file

@ -3,7 +3,7 @@ Contributors: cadeyrn, ameir, haroldkyle, plescheff, dkcwd, IgorCode
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=XU3DG7LLA76WC
Tags: cache, page cache, full page cache, nginx, memcached, apc, speed
Requires at least: 3.0
Tested up to: 4.2.1
Tested up to: 4.3.1
Stable tag: 1.8.4
License: GPLv3
License URI: http://www.gnu.org/licenses/gpl-3.0.html
@ -78,6 +78,7 @@ Many thanks for donations, contributors, supporters, testers & bug reporters:
* Meint Post
* Knut Sparhell
* Christian Kernbeis
* Gausden Barry
== Installation ==
@ -128,9 +129,11 @@ Version numbering logic:
* every ..C indicates bugfixes for A.B version.
= 1.8.4 =
*2015-*
*2015-10-13*
* changes in HTML debug comment: instead of the former, single comment, now 2 comments are added. The first is added when the cache entry is generated; the second only appears if the page was served from the cached entry. Please note that this last bit will - should - change with every single refresh.
* backend code is now split into separate files
* more debug code
= 1.8.3 =
*2015-05-07*

View file

@ -3,6 +3,15 @@
* advanced cache worker of WordPress plugin WP-FFPC
*/
if ( !function_exists ('__debug__') ) {
/* __ only availabe if we're running from the inside of wordpress, not in advanced-cache.php phase */
function __debug__ ( $text ) {
if ( defined('WP_FFPC__DEBUG_MODE') && WP_FFPC__DEBUG_MODE == true)
error_log ( __FILE__ . ': ' . $text );
}
}
/* check for WP cache enabled*/
if ( !WP_CACHE )
return false;
@ -26,12 +35,16 @@ if (!isset($wp_ffpc_config))
$wp_ffpc_uri = $_SERVER['REQUEST_URI'];
/* no cache for robots.txt */
if ( stripos($wp_ffpc_uri, 'robots.txt') )
if ( stripos($wp_ffpc_uri, 'robots.txt') ) {
__debug__ ( 'Skippings robots.txt hit');
return false;
}
/* multisite files can be too large for memcached */
if ( function_exists('is_multisite') && stripos($wp_ffpc_uri, '/files/') && is_multisite() )
if ( function_exists('is_multisite') && stripos($wp_ffpc_uri, '/files/') && is_multisite() ) {
__debug__ ( 'Skippings multisite /files/ hit');
return false;
}
/* check if config is network active: use network config */
if (!empty ( $wp_ffpc_config['network'] ) )
@ -44,8 +57,10 @@ else
return false;
/* no cache for uri with query strings, things usually go bad that way */
if ( isset($wp_ffpc_config['nocache_dyn']) && !empty($wp_ffpc_config['nocache_dyn']) && stripos($wp_ffpc_uri, '?') !== false )
if ( isset($wp_ffpc_config['nocache_dyn']) && !empty($wp_ffpc_config['nocache_dyn']) && stripos($wp_ffpc_uri, '?') !== false ) {
__debug__ ( 'Dynamic url cache is disabled ( url with "?" ), skipping');
return false;
}
/* check for cookies that will make us not cache the content, like logged in WordPress cookie */
if ( isset($wp_ffpc_config['nocache_cookies']) && !empty($wp_ffpc_config['nocache_cookies']) ) {
@ -56,6 +71,7 @@ if ( isset($wp_ffpc_config['nocache_cookies']) && !empty($wp_ffpc_config['nocach
/* check for any matches to user-added cookies to no-cache */
foreach ( $nocache_cookies as $nocache_cookie ) {
if( strpos( $n, $nocache_cookie ) === 0 ) {
__debug__ ( "Cookie exception matched: $n, skipping");
return false;
}
}
@ -67,6 +83,7 @@ if ( isset($wp_ffpc_config['nocache_cookies']) && !empty($wp_ffpc_config['nocach
if ( isset($wp_ffpc_config['nocache_url']) && trim($wp_ffpc_config['nocache_url']) ) {
$pattern = sprintf('#%s#', trim($wp_ffpc_config['nocache_url']));
if ( preg_match($pattern, $wp_ffpc_uri) ) {
__debug__ ( "Cache exceptions matched, skipping");
return false;
}
}
@ -75,7 +92,10 @@ if ( isset($wp_ffpc_config['nocache_url']) && trim($wp_ffpc_config['nocache_url'
$wp_ffpc_redirect = null;
/* fires up the backend storage array with current config */
include_once ('wp-ffpc-backend.php');
$wp_ffpc_backend = new WP_FFPC_Backend( $wp_ffpc_config );
$backend_class = 'WP_FFPC_Backend_' . $wp_ffpc_config['cache_type'];
$wp_ffpc_backend = new $backend_class ( $wp_ffpc_config );
//$wp_ffpc_backend = new WP_FFPC_Backend( $wp_ffpc_config );
/* no cache for for logged in users unless it's set
identifier cookies are listed in backend as var for easier usage
@ -85,6 +105,7 @@ if ( !isset($wp_ffpc_config['cache_loggedin']) || $wp_ffpc_config['cache_loggedi
foreach ($_COOKIE as $n=>$v) {
foreach ( $wp_ffpc_backend->cookies as $nocache_cookie ) {
if( strpos( $n, $nocache_cookie ) === 0 ) {
__debug__ ( "No cache for cookie: $n, skipping");
return false;
}
}
@ -95,13 +116,17 @@ if ( !isset($wp_ffpc_config['cache_loggedin']) || $wp_ffpc_config['cache_loggedi
$wp_ffpc_gentime = 0;
/* backend connection failed, no caching :( */
if ( $wp_ffpc_backend->status() === false )
if ( $wp_ffpc_backend->status() === false ) {
__debug__ ( "Backend offline, skipping");
return false;
}
/* try to get data & meta keys for current page */
$wp_ffpc_keys = array ( 'meta' => $wp_ffpc_config['prefix_meta'], 'data' => $wp_ffpc_config['prefix_data'] );
$wp_ffpc_values = array();
__debug__ ( "Trying to fetch entries");
foreach ( $wp_ffpc_keys as $internal => $key ) {
$key = $wp_ffpc_backend->key ( $key );
$value = $wp_ffpc_backend->get ( $key );
@ -309,6 +334,8 @@ function wp_ffpc_callback( $buffer ) {
if ( get_option ( 'default_ping_status' ) == 'open' )
$meta['pingback'] = get_bloginfo('pingback_url');
$to_store = $buffer;
/* add generation info is option is set, but only to HTML */
if ( $wp_ffpc_config['generate_time'] == '1' && stripos($buffer, '</body>') ) {
global $wp_ffpc_gentime;

View file

@ -11,39 +11,29 @@ if ( !function_exists ('__translate__') ) {
}
}
/* this is the base class for all backends; the actual workers
* are included at the end of the file from backends/ directory */
if (!class_exists('WP_FFPC_Backend')) :
//include_once ( 'wp-common/plugin_utils.php');
/**
*
* @var string $plugin_constant Namespace of the plugin
* @var mixed $connection Backend object storage variable
* @var boolean $alive Alive flag of backend connection
* @var array $options Configuration settings array
* @var array $status Backends status storage
* @var array $cookies Logged in cookies to search for
* @var array $urimap Map to render key with
* @var object $utilities Utilities singleton
*
*/
class WP_FFPC_Backend {
abstract class WP_FFPC_Backend {
const host_separator = ',';
const port_separator = ':';
private $plugin_constant = 'wp-ffpc';
private $connection = NULL;
private $alive = false;
private $options = array();
private $status = array();
protected $plugin_constant = 'wp-ffpc';
protected $connection = NULL;
protected $alive = false;
protected $options = array();
protected $status = array();
public $cookies = array();
private $urimap = array();
protected $urimap = array();
/**
* constructor
*
* @param mixed $config Configuration options
* @param boolean $network WordPress Network indicator flah
*
*/
public function __construct( $config ) {
@ -54,7 +44,6 @@ class WP_FFPC_Backend {
//die ( __translate__ ( 'WP-FFPC Backend class received empty configuration array, the plugin will not work this way', $this->plugin_constant ) );
}
/* set config */
$this->options = $config;
/* these are the list of the cookies to look for when looking for logged in user */
@ -79,16 +68,14 @@ class WP_FFPC_Backend {
'$cookie_PHPSESSID' => $scookie,
);
/* split hosts entry to servers */
/* split single line hosts entry */
$this->set_servers();
/* call backend initiator based on cache type */
$init = $this->proxy( 'init' );
/* info level */
$this->log ( __translate__('init starting', $this->plugin_constant ));
$this->$init();
/* call backend initiator based on cache type */
$init = $this->_init();
if (is_admin() && function_exists('add_filter')) {
add_filter('wp_ffpc_clear_keys_array', function($to_clear, $options) {
@ -105,7 +92,10 @@ class WP_FFPC_Backend {
}
}
/*
* @param string $uri
* @param mixed $default_urimap
*/
public static function parse_urimap($uri, $default_urimap=null) {
$uri_parts = parse_url( $uri );
@ -122,11 +112,14 @@ class WP_FFPC_Backend {
return $uri_map;
}
/**
* @param array $urimap
* @param string $subject
*/
public static function map_urimap($urimap, $subject) {
return str_replace(array_keys($urimap), $urimap, $subject);
}
/*********************** PUBLIC / PROXY FUNCTIONS ***********************/
/**
* build key to make requests with
@ -140,7 +133,7 @@ class WP_FFPC_Backend {
$key_base = self::map_urimap($urimap, $this->options['key']);
if ( isset($this->options['hashkey']) && $this->options['hashkey'] == true)
if (( isset($this->options['hashkey']) && $this->options['hashkey'] == true) || $this->options['cache_type'] == 'redis' )
$key_base = sha1($key_base);
$key = $prefix . $key_base;
@ -161,17 +154,17 @@ class WP_FFPC_Backend {
*/
public function get ( &$key ) {
/* look for backend aliveness, exit on inactive backend */
if ( ! $this->is_alive() )
if ( ! $this->is_alive() ) {
$this->log ('WARNING: Backend offline');
return false;
}
/* log the current action */
$this->log ( sprintf( __translate__( 'get %s', $this->plugin_constant ), $key ) );
$this->log ( sprintf( __translate__( 'GET %s', $this->plugin_constant ), $key ) );
/* proxy to internal function */
$internal = $this->proxy( 'get' );
$result = $this->$internal( $key );
$result = $this->_get( $key );
if ( $result === false )
if ( $result === false || $result === null )
$this->log ( sprintf( __translate__( 'failed to get entry: %s', $this->plugin_constant ), $key ) );
return $result;
@ -203,18 +196,23 @@ class WP_FFPC_Backend {
elseif (( is_tax() || is_category() || is_tag() || is_archive() ) && isset($this->options['expire_taxonomy']))
$expire = (int) $this->options['expire_taxonomy'];
/* log the current action */
$this->log ( sprintf( __translate__( 'SET %s', $this->plugin_constant ), $key ) );
/* proxy to internal function */
$internal = $this->proxy( 'set' );
$result = $this->$internal( $key, $data, $expire );
$result = $this->_set( $key, $data, $expire );
/* check result validity */
if ( $result === false )
if ( $result === false || $result === null )
$this->log ( sprintf( __translate__( 'failed to set entry: %s', $this->plugin_constant ), $key ), LOG_WARNING );
return $result;
}
/*
* next generation clean
*
*
*/
public function clear_ng ( $new_status, $old_status, $post ) {
$this->clear ( $post->ID );
}
@ -224,7 +222,6 @@ class WP_FFPC_Backend {
*
* @param string $post_id ID of post to invalidate
* @param boolean $force Force flush cache
* @param boolean $comment Clear a single page based on comment trigger
*
*/
public function clear ( $post_id = false, $force = false ) {
@ -245,8 +242,7 @@ class WP_FFPC_Backend {
$this->log ( __translate__('flushing cache', $this->plugin_constant ) );
/* proxy to internal function */
$internal = $this->proxy ( 'flush' );
$result = $this->$internal();
$internal = $this->_flush();
if ( $result === false )
$this->log ( __translate__('failed to flush cache', $this->plugin_constant ), LOG_WARNING );
@ -320,10 +316,13 @@ class WP_FFPC_Backend {
$this->clear_keys( $to_clear );
}
/*
* unset entries by key
* @param array $keys
*/
public function clear_keys( $keys ) {
$to_clear = apply_filters('wp_ffpc_clear_keys_array', $keys, $this->options);
$internal = $this->proxy ( 'clear' );
$this->$internal ( $to_clear );
$this->_clear ( $to_clear );
}
/**
@ -422,28 +421,17 @@ class WP_FFPC_Backend {
if ( ! $this->is_alive() )
return false;
$internal = $this->proxy ( 'status' );
$this->$internal();
$internal = $this->_status();
return $this->status;
}
/**
* backend proxy function name generator
*
* @return string Name of internal function based on cache_type
*
*/
private function proxy ( $method ) {
return $this->options['cache_type'] . '_' . $method;
}
/**
* function to check backend aliveness
*
* @return boolean true if backend is alive, false if not
*
*/
private function is_alive() {
protected function is_alive() {
if ( ! $this->alive ) {
$this->log ( __translate__("backend is not active, exiting function ", $this->plugin_constant ) . __FUNCTION__, LOG_WARNING );
return false;
@ -457,7 +445,10 @@ class WP_FFPC_Backend {
*
*
*/
private function set_servers () {
protected function set_servers () {
if ( empty ($this->options['hosts']) )
return false;
/* replace servers array in config according to hosts field */
$servers = explode( self::host_separator , $this->options['hosts']);
@ -465,11 +456,15 @@ class WP_FFPC_Backend {
foreach ( $servers as $snum => $sstring ) {
$separator = strpos( $sstring , self::port_separator );
$host = substr( $sstring, 0, $separator );
$port = substr( $sstring, $separator + 1 );
// unix socket failsafe
if ( empty ($port) ) $port = 0;
if ( stristr($sstring, 'unix://' ) ) {
$host = str_replace('unix:/','',$sstring);
$port = 0;
}
else {
$separator = strpos( $sstring , self::port_separator );
$host = substr( $sstring, 0, $separator );
$port = substr( $sstring, $separator + 1 );
}
$this->options['servers'][$sstring] = array (
'host' => $host,
@ -496,7 +491,7 @@ class WP_FFPC_Backend {
* @var mixed $message Message to log
* @var int $log_level Log level
*/
private function log ( $message, $level = LOG_NOTICE ) {
protected function log ( $message, $level = LOG_NOTICE ) {
if ( @is_array( $message ) || @is_object ( $message ) )
$message = json_encode($message);
@ -514,601 +509,19 @@ class WP_FFPC_Backend {
error_log( __CLASS__ . ": " . $message );
}
/*********************** END PUBLIC FUNCTIONS ***********************/
/*********************** APC FUNCTIONS ***********************/
/**
* init apc backend: test APC availability and set alive status
*/
private function apc_init () {
/* verify apc functions exist, apc extension is loaded */
if ( ! function_exists( 'apc_cache_info' ) ) {
$this->log ( __translate__('APC extension missing', $this->plugin_constant ) );
return false;
}
/* verify apc is working */
if ( apc_cache_info("user",true) ) {
$this->log ( __translate__('backend OK', $this->plugin_constant ) );
$this->alive = true;
}
}
/**
* health checker for APC
*
* @return boolean Aliveness status
*
*/
private function apc_status () {
$this->status = true;
return $this->alive;
}
/**
* get function for APC backend
*
* @param string $key Key to get values for
*
* @return mixed Fetched data based on key
*
*/
private function apc_get ( &$key ) {
return apc_fetch( $key );
}
/**
* Set function for APC backend
*
* @param string $key Key to set with
* @param mixed $data Data to set
*
* @return boolean APC store outcome
*/
private function apc_set ( &$key, &$data, &$expire ) {
return apc_store( $key , $data , $expire );
}
/**
* Flushes APC user entry storage
*
* @return boolean APC flush outcome status
*
*/
private function apc_flush ( ) {
return apc_clear_cache('user');
}
/**
* Removes entry from APC or flushes APC user entry storage
*
* @param mixed $keys Keys to clear, string or array
*/
private function apc_clear ( &$keys ) {
/* make an array if only one string is present, easier processing */
if ( !is_array ( $keys ) )
$keys = array ( $keys => true );
foreach ( $keys as $key => $dummy ) {
if ( ! apc_delete ( $key ) ) {
$this->log ( sprintf( __translate__( 'Failed to delete APC entry: %s', $this->plugin_constant ), $key ), LOG_WARNING );
//throw new Exception ( __translate__('Deleting APC entry failed with key ', $this->plugin_constant ) . $key );
}
else {
$this->log ( sprintf( __translate__( 'APC entry delete: %s', $this->plugin_constant ), $key ) );
}
}
}
/*********************** END APC FUNCTIONS ***********************/
/*********************** APCu FUNCTIONS ***********************/
/**
* init apcu backend: test APCu availability and set alive status
*/
private function apcu_init () {
/* verify apcu functions exist, apcu extension is loaded */
if ( ! function_exists( 'apcu_cache_info' ) ) {
$this->log ( __translate__('APCu extension missing', $this->plugin_constant ) );
return false;
}
/* verify apcu is working */
if ( apcu_cache_info("user") ) {
$this->log ( __translate__('backend OK', $this->plugin_constant ) );
$this->alive = true;
}
}
/**
* health checker for APC
*
* @return boolean Aliveness status
*
*/
private function apcu_status () {
$this->status = true;
return $this->alive;
}
/**
* get function for APC backend
*
* @param string $key Key to get values for
*
* @return mixed Fetched data based on key
*
*/
private function apcu_get ( &$key ) {
return apcu_fetch( $key );
}
/**
* Set function for APC backend
*
* @param string $key Key to set with
* @param mixed $data Data to set
*
* @return boolean APC store outcome
*/
private function apcu_set ( &$key, &$data, &$expire ) {
return apcu_store( $key , $data , $expire );
}
/**
* Flushes APC user entry storage
*
* @return boolean APC flush outcome status
*
*/
private function apcu_flush ( ) {
return apcu_clear_cache();
}
/**
* Removes entry from APC or flushes APC user entry storage
*
* @param mixed $keys Keys to clear, string or array
*/
private function apcu_clear ( &$keys ) {
/* make an array if only one string is present, easier processing */
if ( !is_array ( $keys ) )
$keys = array ( $keys => true );
foreach ( $keys as $key => $dummy ) {
if ( ! apcu_delete ( $key ) ) {
$this->log ( sprintf( __translate__( 'Failed to delete APC entry: %s', $this->plugin_constant ), $key ), LOG_WARNING );
//throw new Exception ( __translate__('Deleting APC entry failed with key ', $this->plugin_constant ) . $key );
}
else {
$this->log ( sprintf( __translate__( 'APC entry delete: %s', $this->plugin_constant ), $key ) );
}
}
}
/*********************** END APC FUNCTIONS ***********************/
/*********************** MEMCACHED FUNCTIONS ***********************/
/**
* init memcached backend
*/
private function memcached_init () {
/* Memcached class does not exist, Memcached extension is not available */
if (!class_exists('Memcached')) {
$this->log ( __translate__(' Memcached extension missing, wp-ffpc will not be able to function correctly!', $this->plugin_constant ), LOG_WARNING );
return false;
}
/* check for existing server list, otherwise we cannot add backends */
if ( empty ( $this->options['servers'] ) && ! $this->alive ) {
$this->log ( __translate__("Memcached servers list is empty, init failed", $this->plugin_constant ), LOG_WARNING );
return false;
}
/* check is there's no backend connection yet */
if ( $this->connection === NULL ) {
$this->connection = new Memcached();
/* use binary and not compressed format, good for nginx and still fast */
$this->connection->setOption( Memcached::OPT_COMPRESSION , false );
if ($this->options['memcached_binary']){
$this->connection->setOption( Memcached::OPT_BINARY_PROTOCOL , true );
}
if ( version_compare( phpversion( 'memcached' ) , '2.0.0', '>=' ) && ini_get( 'memcached.use_sasl' ) == 1 && isset($this->options['authpass']) && !empty($this->options['authpass']) && isset($this->options['authuser']) && !empty($this->options['authuser']) ) {
$this->connection->setSaslAuthData ( $this->options['authuser'], $this->options['authpass']);
}
}
/* check if initialization was success or not */
if ( $this->connection === NULL ) {
$this->log ( __translate__( 'error initializing Memcached PHP extension, exiting', $this->plugin_constant ) );
return false;
}
/* check if we already have list of servers, only add server(s) if it's not already connected */
$servers_alive = array();
if ( !empty ( $this->status ) ) {
$servers_alive = $this->connection->getServerList();
/* create check array if backend servers are already connected */
if ( !empty ( $servers ) ) {
foreach ( $servers_alive as $skey => $server ) {
$skey = $server['host'] . ":" . $server['port'];
$servers_alive[ $skey ] = true;
}
}
}
/* adding servers */
foreach ( $this->options['servers'] as $server_id => $server ) {
/* reset server status to unknown */
$this->status[$server_id] = -1;
/* only add servers that does not exists already in connection pool */
if ( !@array_key_exists($server_id , $servers_alive ) ) {
$this->connection->addServer( $server['host'], $server['port'] );
$this->log ( sprintf( __translate__( '%s added', $this->plugin_constant ), $server_id ) );
}
}
/* backend is now alive */
$this->alive = true;
$this->memcached_status();
}
/**
* sets current backend alive status for Memcached servers
*
*/
private function memcached_status () {
/* server status will be calculated by getting server stats */
$this->log ( __translate__("checking server statuses", $this->plugin_constant ));
/* get server list from connection */
$servers = $this->connection->getServerList();
foreach ( $servers as $server ) {
$server_id = $server['host'] . self::port_separator . $server['port'];
/* reset server status to offline */
$this->status[$server_id] = 0;
if ($this->connection->set($this->plugin_constant, time())) {
$this->log ( sprintf( __translate__( '%s server is up & running', $this->plugin_constant ), $server_id ) );
$this->status[$server_id] = 1;
}
}
}
/**
* get function for Memcached backend
*
* @param string $key Key to get values for
*
*/
private function memcached_get ( &$key ) {
return $this->connection->get($key);
}
/**
* Set function for Memcached backend
*
* @param string $key Key to set with
* @param mixed $data Data to set
*
*/
private function memcached_set ( &$key, &$data, &$expire ) {
$result = $this->connection->set ( $key, $data , $expire );
/* if storing failed, log the error code */
if ( $result === false ) {
$code = $this->connection->getResultCode();
$this->log ( sprintf( __translate__( 'unable to set entry: %s', $this->plugin_constant ), $key ) );
$this->log ( sprintf( __translate__( 'Memcached error code: %s', $this->plugin_constant ), $code ) );
//throw new Exception ( __translate__('Unable to store Memcached entry ', $this->plugin_constant ) . $key . __translate__( ', error code: ', $this->plugin_constant ) . $code );
}
return $result;
}
/**
*
* Flush memcached entries
*/
private function memcached_flush ( ) {
return $this->connection->flush();
}
/**
* Removes entry from Memcached or flushes Memcached storage
*
* @param mixed $keys String / array of string of keys to delete entries with
*/
private function memcached_clear ( &$keys ) {
/* make an array if only one string is present, easier processing */
if ( !is_array ( $keys ) )
$keys = array ( $keys => true );
foreach ( $keys as $key => $dummy ) {
$kresult = $this->connection->delete( $key );
if ( $kresult === false ) {
$code = $this->connection->getResultCode();
$this->log ( sprintf( __translate__( 'unable to delete entry: %s', $this->plugin_constant ), $key ) );
$this->log ( sprintf( __translate__( 'Memcached error code: %s', $this->plugin_constant ), $code ) );
}
else {
$this->log ( sprintf( __translate__( 'entry deleted: %s', $this->plugin_constant ), $key ) );
}
}
}
/*********************** END MEMCACHED FUNCTIONS ***********************/
/*********************** MEMCACHE FUNCTIONS ***********************/
/**
* init memcache backend
*/
private function memcache_init () {
/* Memcached class does not exist, Memcache extension is not available */
if (!class_exists('Memcache')) {
$this->log ( __translate__('PHP Memcache extension missing', $this->plugin_constant ), LOG_WARNING );
return false;
}
/* check for existing server list, otherwise we cannot add backends */
if ( empty ( $this->options['servers'] ) && ! $this->alive ) {
$this->log ( __translate__("servers list is empty, init failed", $this->plugin_constant ), LOG_WARNING );
return false;
}
/* check is there's no backend connection yet */
if ( $this->connection === NULL )
$this->connection = new Memcache();
/* check if initialization was success or not */
if ( $this->connection === NULL ) {
$this->log ( __translate__( 'error initializing Memcache PHP extension, exiting', $this->plugin_constant ) );
return false;
}
/* adding servers */
foreach ( $this->options['servers'] as $server_id => $server ) {
/* in case of unix socket */
if ( $server['port'] === 0 )
$this->status[$server_id] = $this->connection->connect ( 'unix:/' . $server['host'] );
else
$this->status[$server_id] = $this->connection->connect ( $server['host'] , $server['port'] );
$this->log ( sprintf( __translate__( '%s added', $this->plugin_constant ), $server_id ) );
}
/* backend is now alive */
$this->alive = true;
$this->memcache_status();
}
/**
* check current backend alive status for Memcached
*
*/
private function memcache_status () {
/* server status will be calculated by getting server stats */
$this->log ( __translate__("checking server statuses", $this->plugin_constant ));
/* get servers statistic from connection */
foreach ( $this->options['servers'] as $server_id => $server ) {
if ( $server['port'] === 0 )
$this->status[$server_id] = $this->connection->getServerStatus( $server['host'], 11211 );
else
$this->status[$server_id] = $this->connection->getServerStatus( $server['host'], $server['port'] );
if ( $this->status[$server_id] == 0 )
$this->log ( sprintf( __translate__( '%s server is down', $this->plugin_constant ), $server_id ) );
else
$this->log ( sprintf( __translate__( '%s server is up & running', $this->plugin_constant ), $server_id ) );
}
}
/**
* get function for Memcached backend
*
* @param string $key Key to get values for
*
*/
private function memcache_get ( &$key ) {
return $this->connection->get($key);
}
/**
* Set function for Memcached backend
*
* @param string $key Key to set with
* @param mixed $data Data to set
*
*/
private function memcache_set ( &$key, &$data, &$expire ) {
$result = $this->connection->set ( $key, $data , 0 , $expire );
return $result;
}
/**
*
* Flush memcached entries
*/
private function memcache_flush ( ) {
return $this->connection->flush();
}
/**
* Removes entry from Memcached or flushes Memcached storage
*
* @param mixed $keys String / array of string of keys to delete entries with
*/
private function memcache_clear ( &$keys ) {
/* make an array if only one string is present, easier processing */
if ( !is_array ( $keys ) )
$keys = array ( $keys => true );
foreach ( $keys as $key => $dummy ) {
$kresult = $this->connection->delete( $key );
if ( $kresult === false ) {
$this->log ( sprintf( __translate__( 'unable to delete entry: %s', $this->plugin_constant ), $key ) );
}
else {
$this->log ( sprintf( __translate__( 'entry deleted: %s', $this->plugin_constant ), $key ) );
}
}
}
/*********************** END MEMCACHE FUNCTIONS ***********************/
/*********************** REDIS FUNCTIONS ***********************/
/**
* init memcache backend
*/
private function redis_init () {
if (!class_exists('Redis')) {
$this->log ( __translate__('PHP Redis extension missing', $this->plugin_constant ), LOG_WARNING );
return false;
}
/* check for existing server list, otherwise we cannot add backends */
if ( empty ( $this->options['servers'] ) && ! $this->alive ) {
$this->log ( __translate__("servers list is empty, init failed", $this->plugin_constant ), LOG_WARNING );
return false;
}
/* check is there's no backend connection yet */
if ( $this->connection === NULL )
$this->connection = new Redis();
/* check if initialization was success or not */
if ( $this->connection === NULL ) {
$this->log ( __translate__( 'error initializing Redis extension, exiting', $this->plugin_constant ) );
return false;
}
//$this->connection->setOption(Redis::OPT_PREFIX, $this->plugin_constant );
/* adding server *
foreach ( $this->options['servers'] as $server_id => $server ) {
/* in case of unix socket *
if ( $server['port'] === 0 ) {
try {
$this->status[$server_id] = $this->connection->connect ( $server['host'] );
} catch ( RedisException $e ) {
$this->log ( sprintf( __translate__( 'adding %s to the Redis pool failed, error: %s', $this->plugin_constant ), $server['host'], $e ) );
}
}
else {
try {
$this->status[$server_id] = $this->connection->connect ( $server['host'] , $server['port'] );
} catch ( RedisException $e ) {
$this->log ( sprintf( __translate__( 'adding %s:%s to the Redis pool failed, error: %s', $this->plugin_constant ), $server['host'] , $server['port'], $e ) );
}
}
$this->log ( sprintf( __translate__( 'server #%s added', $this->plugin_constant ), $server_id ) );
}*/
/* adding server */
$key = array_unshift ( array_keys ( $this->options['servers'] ));
$server = array_unshift( $this->options['servers'] );
try {
if ( $server['port'] === 0 )
$this->status[$key] = $this->connection->connect ( $server['host'] );
else
$this->status[$key] = $this->connection->connect ( $server['host'], $server['port'] );
} catch ( RedisException $e ) {
$this->log ( sprintf( __translate__( 'adding %s to the Redis pool failed, error: %s', $this->plugin_constant ), $server['host'], $e ) );
}
$this->log ( sprintf( __translate__( 'server #%s added', $this->plugin_constant ), $server_id ) );
if ( !empty( $this->options['authpass'])) {
$auth = $this->connection->auth( $this->options['authpass'] );
if ( $auth == false ) {
$this->log ( __translate__( 'Redis authentication failed, exiting', $this->plugin_constant ), LOG_WARNING );
return false;
}
}
/* backend is now alive */
$this->alive = true;
$this->redis_status();
}
/**
* check current backend alive status for Memcached
*
*/
private function redis_status () {
/* server status will be calculated by getting server stats */
$this->log ( __translate__("checking server statuses", $this->plugin_constant ));
/* get servers statistic from connection */
try {
$this->connection->ping();
} catch ( RedisException $e ) {
$this->log ( sprintf( __translate__( 'Redis status check failed, error: %s', $this->plugin_constant ), $e ) );
}
$this->log ( sprintf( __translate__( 'Redis is up', $this->plugin_constant ), $server_id ) );
}
/**
* get function for Memcached backend
*
* @param string $key Key to get values for
*
*/
private function redis_get ( &$key ) {
return $this->connection->get($key);
}
/**
* Set function for Memcached backend
*
* @param string $key Key to set with
* @param mixed $data Data to set
*
*/
private function redis_set ( &$key, &$data, &$expire ) {
$result = $this->connection->set ( $key, $data , Array('nx', 'ex' => $expire) );
return $result;
}
/**
*
* Flush memcached entries
*/
private function redis_flush ( ) {
return $this->connection->flushDB();
}
/**
* Removes entry from Memcached or flushes Memcached storage
*
* @param mixed $keys String / array of string of keys to delete entries with
*/
private function redis_clear ( &$keys ) {
/* make an array if only one string is present, easier processing */
if ( !is_array ( $keys ) )
$keys = array ( $keys => true );
$kresults = $this->connection->delete( $keys );
foreach ( $kresults as $key => $value ) {
$this->log ( sprintf( __translate__( 'entry deleted: %s', $this->plugin_constant ), $value ) );
}
}
/*********************** END REDIS FUNCTIONS ***********************/
abstract protected function _init ();
abstract protected function _status ();
abstract protected function _get ( &$key );
abstract protected function _set ( &$key, &$data, &$expire );
abstract protected function _flush ();
abstract protected function _clear ( &$keys );
}
endif;
$wp_ffpc_backends = glob( dirname( __FILE__ ) . "/backends/*.php" );
foreach ( $wp_ffpc_backends as $backend )
include_once $backend;
unset( $wp_ffpc_backends, $backend );

View file

@ -85,7 +85,7 @@ class WP_FFPC extends WP_FFPC_ABSTRACT {
/* nginx sample config file */
$this->nginx_sample = $this->plugin_dir . $this->plugin_constant . '-nginx-sample.conf';
/* backend driver file */
$this->acache_backend = $this->plugin_dir . $this->plugin_constant . '-backend.php';
$this->acache_backend = $this->plugin_dir . $this->plugin_constant . '-engine.php';
/* flush button identifier */
$this->button_flush = $this->plugin_constant . '-flush';
/* precache button identifier */
@ -181,7 +181,8 @@ class WP_FFPC extends WP_FFPC_ABSTRACT {
public function plugin_post_init () {
/* initiate backend */
$this->backend = new WP_FFPC_Backend ( $this->options );
$backend_class = 'WP_FFPC_Backend_' . $this->options['cache_type'];
$this->backend = new $backend_class ( $this->options );
/* re-save settings after update */
add_action( 'upgrader_process_complete', array ( &$this->plugin_upgrade ), 10, 2 );
@ -439,6 +440,7 @@ class WP_FFPC extends WP_FFPC_ABSTRACT {
/* we need to go through all servers */
$servers = $this->backend->status();
error_log(__CLASS__ . ':' .json_encode($servers));
if ( is_array( $servers ) && !empty ( $servers ) ) {
foreach ( $servers as $server_string => $status ) {
echo $server_string ." => ";
@ -705,19 +707,10 @@ class WP_FFPC extends WP_FFPC_ABSTRACT {
<dd>
<input type="text" name="hosts" id="hosts" value="<?php echo $this->options['hosts']; ?>" />
<span class="description">
<?php _e('List of backends, with the following syntax: <br />- in case of TCP based connections, list the servers as host1:port1,host2:port2,... . Do not add trailing , and always separate host and port with : .<br />- in2.0.0b1 case using unix sockets with the Memcache driver: unix:// ', $this->plugin_constant); ?></span>
<?php _e('List of backends, with the following syntax: <br />- in case of TCP based connections, list the servers as host1:port1,host2:port2,... . Do not add trailing , and always separate host and port with : .<br />- for a unix socket enter: unix://[socket_path]', $this->plugin_constant); ?></span>
</dd>
<dt>
<label for="memcached_binary"><?php _e('Enable memcached binary mode', $this->plugin_constant); ?></label>
</dt>
<dd>
<input type="checkbox" name="memcached_binary" id="memcached_binary" value="1" <?php checked($this->options['memcached_binary'],true); ?> />
<span class="description"><?php _e('Some memcached proxies and implementations only support the ASCII protocol.', $this->plugin_constant); ?></span>
</dd>
<?php
if ( strstr ( $this->options['cache_type'], 'memcached') && extension_loaded ( 'memcached' ) && version_compare( phpversion( 'memcached' ) , '2.0.0', '>=' ) || ( $this->options['cache_type'] == 'redis' ) ) { ?>
<h3><?php _e('Authentication ( only for SASL enabled Memcached or Redis')?></h3>
<?php
if ( ! ini_get('memcached.use_sasl') && ( !empty( $this->options['authuser'] ) || !empty( $this->options['authpass'] ) ) ) { ?>
<div class="error"><p><strong><?php _e( 'WARNING: you\'ve entered username and/or password for memcached authentication ( or your browser\'s autocomplete did ) which will not work unless you enable memcached sasl in the PHP settings: add `memcached.use_sasl=1` to php.ini' , $this->plugin_constant ) ?></strong></p></div>
@ -728,7 +721,7 @@ class WP_FFPC extends WP_FFPC_ABSTRACT {
<dd>
<input type="text" autocomplete="off" name="authuser" id="authuser" value="<?php echo $this->options['authuser']; ?>" />
<span class="description">
<?php _e('Username for authentication with memcached backends', $this->plugin_constant); ?></span>
<?php _e('Username for authentication with backends', $this->plugin_constant); ?></span>
</dd>
<dt>
@ -737,9 +730,19 @@ class WP_FFPC extends WP_FFPC_ABSTRACT {
<dd>
<input type="password" autocomplete="off" name="authpass" id="authpass" value="<?php echo $this->options['authpass']; ?>" />
<span class="description">
<?php _e('Password for authentication with memcached backends - WARNING, the password will be stored plain-text since it needs to be used!', $this->plugin_constant); ?></span>
<?php _e('Password for authentication with for backends - WARNING, the password will be stored in an unsecure format!', $this->plugin_constant); ?></span>
</dd>
<?php } ?>
<h3><?php _e('Memcached specific settings')?></h3>
<dt>
<label for="memcached_binary"><?php _e('Enable memcached binary mode', $this->plugin_constant); ?></label>
</dt>
<dd>
<input type="checkbox" name="memcached_binary" id="memcached_binary" value="1" <?php checked($this->options['memcached_binary'],true); ?> />
<span class="description"><?php _e('Some memcached proxies and implementations only support the ASCII protocol.', $this->plugin_constant); ?></span>
</dd>
</dl>
</fieldset>
@ -988,12 +991,16 @@ class WP_FFPC extends WP_FFPC_ABSTRACT {
*/
private function deploy_advanced_cache( ) {
if ( @is_writable( $this->acache ))
if ( !is_writable( $this->acache )) {
error_log('Generating advanced-cache.php failed: '.$this->acache.' is not writable');
return false;
}
/* if no active site left no need for advanced cache :( */
if ( empty ( $this->global_config ) )
if ( empty ( $this->global_config ) ) {
error_log('Generating advanced-cache.php failed: Global config is empty');
return false;
}
/* add the required includes and generate the needed code */
$string[] = "<?php";
@ -1003,6 +1010,7 @@ class WP_FFPC extends WP_FFPC_ABSTRACT {
/* write the file and start caching from this point */
return file_put_contents( $this->acache, join( "\n" , $string ) );
}
/**