acache_worker = $this->plugin_dir . $this->plugin_constant . '-acache.php'; /* WordPress advanced-cache.php file location */ $this->acache = WP_CONTENT_DIR . '/advanced-cache.php'; /* 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'; /* flush button identifier */ $this->button_flush = $this->plugin_constant . '-flush'; /* precache button identifier */ $this->button_precache = $this->plugin_constant . '-precache'; /* global options identifier */ $this->global_option = $this->plugin_constant . '-global'; /* precache log */ $this->precache_logfile = sys_get_temp_dir() . '/' . self::precache_log; /* search for a system function */ $this->shell_possibilities = array ( 'shell_exec', 'exec', 'system', 'passthru' ); $disabled_functions = array_map('trim', explode(',', ini_get('disable_functions') ) ); foreach ( $this->shell_possibilities as $possible ) { if ( function_exists ($possible) && ! ( ini_get('safe_mode') || in_array( $possible, $disabled_functions ) ) ) { /* set shell function */ $this->shell_function = $possible; break; } } /* set global config key; here, because it's needed for migration */ if ( $this->network ) $this->global_config_key = 'network'; else $this->global_config_key = $_SERVER['HTTP_HOST']; /* cache type possible values array */ $this->select_cache_type = array ( 'apc' => __( 'APC' , $this->plugin_constant ), 'memcache' => __( 'PHP Memcache' , $this->plugin_constant ), 'memcached' => __( 'PHP Memcached' , $this->plugin_constant ), ); $this->valid_cache_type = array ( 'apc' => function_exists( 'apc_sma_info' ) ? true : false, 'memcache' => class_exists ( 'Memcache') ? true : false, 'memcached' => class_exists ( 'Memcached') ? true : false, ); /* invalidation method possible values array */ $this->select_invalidation_method = array ( 0 => __( 'flush cache' , $this->plugin_constant ), 1 => __( 'only modified post' , $this->plugin_constant ), ); } /** * additional init, steps that needs the plugin options * */ public function plugin_setup () { /* initiate backend */ $this->backend = new WP_FFPC_Backend ( $this->options ); /* get all available post types */ $post_types = get_post_types( ); /* cache invalidation hooks */ foreach ( $post_types as $post_type ) { add_action( 'new_to_publish_' .$post_type , array( $this->backend , 'clear' ), 0 ); add_action( 'draft_to_publish' .$post_type , array( $this->backend , 'clear' ), 0 ); add_action( 'pending_to_publish' .$post_type , array( $this->backend , 'clear' ), 0 ); add_action( 'private_to_publish' .$post_type , array( $this->backend , 'clear' ), 0 ); add_action( 'publish_' . $post_type , array( $this->backend , 'clear' ), 0 ); } /* invalidation on some other ocasions as well */ add_action( 'switch_theme', array( $this->backend , 'clear' ), 0 ); add_action( 'deleted_post', array( $this->backend , 'clear' ), 0 ); add_action( 'edit_post', array( $this->backend , 'clear' ), 0 ); /* add filter for catching canonical redirects */ add_filter('redirect_canonical', 'wp_ffpc_redirect_callback', 10, 2); } /** * activation hook function, to be extended */ public function plugin_activate() { /* we leave this empty to avoid not detecting WP network correctly */ } /** * deactivation hook function, to be extended */ public function plugin_deactivate () { /* remove current site config from global config */ $this->update_global_config( true ); } /** * uninstall hook function, to be extended */ public function plugin_uninstall( $delete_options = true ) { /* delete advanced-cache.php file */ unlink ( $this->acache ); /* delete site settings */ if ( $delete_options ) { $this->plugin_options_delete (); } } /** * extending admin init * */ public function plugin_hook_admin_init () { /* save parameter updates, if there are any */ if ( isset( $_POST[ $this->button_flush ] ) ) { $this->backend->clear(); $this->status = 3; header( "Location: ". $this->settings_link . self::slug_flush ); } /* save parameter updates, if there are any */ if ( isset( $_POST[ $this->button_precache ] ) ) { if ( $this->shell_function == false ) { $this->status = 5; header( "Location: ". $this->settings_link . self::slug_precache_disabled ); } else { $this->precache_message = $this->precache(); $this->status = 4; header( "Location: ". $this->settings_link . self::slug_precache ); } } } /** * admin panel, the admin page displayed for plugin settings */ public function plugin_admin_panel() { /** * security, if somehow we're running without WordPress security functions */ if( ! function_exists( 'current_user_can' ) || ! current_user_can( 'manage_options' ) ){ die( ); } ?>
plugin_donation_form(); /** * if options were saved, display saved message */ if ( ! empty( $this->broadcast_message ) ) : ?>
broadcast_message; ?>
status == 1) : ?>

plugin_constant ) ?>

status == 2) : ?>

plugin_constant ) ?>

status == 3) : ?>

plugin_constant ); ?>

status == 4) : ?>

plugin_constant ) ?>

plugin_name ; _e( ' settings', $this->plugin_constant ) ; ?>

plugin_constant ); ?>

global_saved ) : ?>

plugin_constant); ?>

plugin_constant ) ?>

acache ) ) : ?>

plugin_constant); ?>

acache , $this->plugin_constant ) ?>

options['cache_type'] == 'memcached' && !class_exists('Memcached') ) : ?>

plugin_constant); ?>

options['cache_type'] == 'memcache' && !class_exists('Memcache') ) : ?>

plugin_constant); ?>

options['cache_type'] == 'memcache' ) { $memcache_protocol = strtolower($memcache_settings['memcache.protocol']['local_value']); if ( $memcached_protocol == 'binary' ) : ?>

Please consider to change either to ASCII mode or to Memcached extension.', $this->plugin_constant ); ?>

plugin_constant); echo $this->options['cache_type']; ?>

options['cache_type'], 'memcache') ) : ?>

Backend status:
', $this->plugin_constant ); /* we need to go through all servers */ $servers = $this->backend->status(); foreach ( $servers as $server_string => $status ) { echo $server_string ." => "; if ( $status == 0 ) _e ( 'down
', $this->plugin_constant ); elseif ( $status == 1 ) _e ( 'up & running
', $this->plugin_constant ); else _e ( 'unknown, please try re-saving settings!
', $this->plugin_constant ); } ?>

plugin_constant ); ?>
plugin_constant); ?>
plugin_constant); ?>
plugin_constant); ?>
Be careful! Selecting "flush cache" will flush the whole cache, including elements that might have been set and used by other applications. Also, invalidating only the post will _not_ clear categories, archive and taxonomy pages, therefore only use this if refreshing after publish can wait until the entries expire on their own.

', $this->plugin_constant); ?>
plugin_constant); ?>
plugin_constant); ?>
plugin_constant ); ?>
options['log'],true); ?> /> plugin_constant); ?>
options['log_info'],true); ?> /> plugin_constant); ?>
options['response_header'],true); ?> /> plugin_constant); ?>
options['generate_time'],true); ?> /> tag.', $this->plugin_constant); ?>
options['sync_protocols'],true); ?> /> plugin_constant); ?>
plugin_constant ); ?>
options['cache_loggedin'],true); ?> /> plugin_constant); ?>
options['nocache_home'],true); ?> /> plugin_constant); ?>
options['nocache_feed'],true); ?> /> plugin_constant); ?>
options['nocache_archive'],true); ?> /> plugin_constant); ?>
options['nocache_single'],true); ?> /> plugin_constant); ?>
options['nocache_page'],true); ?> /> plugin_constant); ?>
plugin_constant); ?>
No spaces are allowed, please stick to use ":" for separating host and port and "," for separating entries. Do not add trailing ",".', $this->plugin_constant); ?>
options['persistent'],true); ?> /> plugin_constant); ?>
plugin_constant); ?>
nginx_example(); ?>
plugin_constant); ?> precache_logfile ) ) : $log = file ( $this->precache_logfile ); $head = explode( "\t", array_shift( $log )); $gentime = filemtime ( $this->precache_logfile ); ?>

plugin_constant); endif; ?>

plugin_constant ); ?>
status == 5 || $this->shell_function == false ) : ?> Since precaching may take a very long time, it's done through a background CLI process in order not to run out of max execution time of PHP. Please enable one of the following functions if you whish to use precaching: " , $this->plugin_constant ) ?>shell_possibilities ); ?>
plugin_constant); ?>
plugin_constant ); ?>
plugin_constant ); ?>
plugin_constant ); ?>
plugin_constant ); ?>
backend->clear(); /* create the to-be-included configuration for advanced-cache.php */ $this->update_global_config(); /* create advanced cache file, needed only once or on activation, because there could be lefover advanced-cache.php from different plugins */ if ( !$activating ) $this->deploy_advanced_cache(); } /** * read hook; needs to be implemented */ public function plugin_hook_options_read( &$options ) { /* read the global options, network compatibility */ $this->global_config = get_site_option( $this->global_option ); /* check if current site present in global config */ if ( !empty ( $this->global_config[ $this->global_config_key ] ) ) $this->global_saved = true; $this->global_config[ $this->global_config_key ] = $options; } /** * options delete hook; needs to be implemented */ public function plugin_hook_options_delete( ) { delete_site_option ( $this->global_option ); } /** * need to do migrations from previous versions of the plugin * */ public function plugin_hook_options_migrate( &$options ) { $migrated = false; if ( $options['version'] != $this->plugin_version || !isset ( $options['version'] ) ) { /* cleanup possible leftover files from previous versions */ $check = array ( 'advanced-cache.php', 'nginx-sample.conf', 'wp-ffpc.admin.css', 'wp-ffpc-common.php' ); foreach ( $check as $fname ) { $fname = $this->plugin_dir . $fname; if ( file_exists ( $fname ) ) unlink ( $fname ); } /* look for previous config leftovers */ $try = get_site_option( $this->plugin_constant ); /* network option key changed, remove & migrate the leftovers if there's any */ if ( !empty ( $try ) && $this->network ) { /* clean it up, we don't use it anymore */ delete_site_option ( $this->plugin_constant ); if ( empty ( $options ) && array_key_exists ( $this->global_config_key, $try ) ) { $options = $try [ $this->global_config_key ]; $migrated = true; } elseif ( empty ( $options ) && array_key_exists ( 'host', $try ) ) { $options = $try; $migrated = true; } } /* updating from version <= 0.4.x */ if ( !empty ( $options['host'] ) ) { $options['hosts'] = $options['host'] . ':' . $options['port']; $migrated = true; } /* migrating from version 0.6.x */ elseif ( is_array ( $options ) && array_key_exists ( $this->global_config_key , $options ) ) { $options = $options[ $this->global_config_key ]; $migrated = true; } /* migrating from something, drop previous config */ else { $options = array(); } if ( $migrated ) { /* renamed options */ if ( isset ( $options['syslog'] ) ) $options['log'] = $options['syslog']; if ( isset ( $options['debug'] ) ) $options['response_header'] = $options['debug']; } } } /** * advanced-cache.php creator function * */ private function deploy_advanced_cache( ) { /* in case advanced-cache.php was already there, remove it */ if ( @file_exists( $this->acache )) unlink ($this->acache); /* is deletion was unsuccessful, die, we have no rights to do that, fail */ if ( @file_exists( $this->acache )) return false; /* if no active site left no need for advanced cache :( */ if ( empty ( $this->global_config ) ) return false; /* add the required includes and generate the needed code */ $string[] = "global_config, true ) . ';' ; $string[] = "include_once ('" . $this->acache_backend . "');"; $string[] = "include_once ('" . $this->acache_worker . "');"; $string[] = "?>"; /* write the file and start caching from this point */ return file_put_contents( $this->acache, join( "\n" , $string ) ); } /** * function to generate working example from the nginx sample file * * @return string nginx config file * */ private function nginx_example () { /* read the sample file */ $nginx = file_get_contents ( $this->nginx_sample ); /* this part is not used when the cache is turned on for logged in users */ $loggedin = '# avoid cache for logged in users if ($http_cookie ~* "comment_author_|wordpressuser_|wp-postpass_" ) { set $memcached_request 0; }'; /* replace the data prefix with the configured one */ $nginx = str_replace ( 'DATAPREFIX' , $this->options['prefix_data'] , $nginx ); /* set upstream servers from configured servers, best to get from the actual backend */ $servers = $this->backend->get_servers(); foreach ( array_keys( $servers ) as $server ) { $nginx_servers .= " server ". $server .";\n"; } $nginx = str_replace ( 'MEMCACHED_SERVERS' , $nginx_servers , $nginx ); /* add logged in cache, if valid */ if ( ! $this->options['cache_loggedin']) $nginx = str_replace ( 'LOGGEDIN_EXCEPTION' , $loggedin , $nginx ); else $nginx = str_replace ( 'LOGGEDIN_EXCEPTION' , '' , $nginx ); return $nginx; } /** * function to update global configuration * * @param boolean $remove_site Bool to remove or add current config to global * */ private function update_global_config ( $remove_site = false ) { /* remove or add current config to global config */ if ( $remove_site ) { unset ( $this->global_config[ $this->global_config_key ] ); } else { $this->global_config[ $this->global_config_key ] = $this->options; } /* deploy advanced-cache.php */ $this->deploy_advanced_cache (); /* save options to database */ update_site_option( $this->global_option , $this->global_config ); } /** * generate cache entry for every available permalink, might be very-very slow, * therefore it starts a background process * */ private function precache () { /* container for links to precache, well be accessed by reference */ $links = array(); /* when plugin is network wide active, we need to pre-cache for all link of all blogs */ if ( $this->network ) { /* list all blogs */ $blog_list = get_blog_list( 0, 'all' ); foreach ($blog_list as $blog) { /* get permalinks for this blog */ $this->precache_list_permalinks ( $links, $blog['blog_id'] ); } } else { /* no network, better */ $this->precache_list_permalinks ( $links, false ); } /* temporary php file, will destroy itself after finish in order to clean up */ $tmpfile = tempnam(sys_get_temp_dir(), 'wp-ffpc'); /* double check if we do have any links to pre-cache */ if ( !empty ( $links ) ) : /* this is the precacher php worker file: logs the links, their generation time and the generated content size * writes the logfile and destroys itself afterwards */ $out .= ''; file_put_contents ( $tmpfile, $out ); /* call the precache worker file in the background */ $shellfunction = $this->shell_function; $shellfunction( 'php '. $tmpfile .' >'. $this->precache_logfile .' 2>&1 &' ); endif; } /** * gets all post-like entry permalinks for a site, returns values in passed-by-reference array * */ private function precache_list_permalinks ( &$links, $site = false ) { /* $post will be populated when running throught the posts */ global $post; include_once ( ABSPATH . "wp-load.php" ); /* if a site id was provided, save current blog and change to the other site */ if ( $site !== false ) { $current_blog = get_current_blog_id(); switch_to_blog( $site ); } /* get all published posts */ $args = array ( 'post_type' => 'any', 'posts_per_page' => -1, 'post_status' => 'publish', ); $posts = new WP_Query( $args ); /* get all the posts, one by one */ while ( $posts->have_posts() ) { $posts->the_post(); /* get the permalink for currently selected post */ switch ($post->post_type) { case 'revision': case 'nav_menu_item': break; case 'page': $permalink = get_page_link( $post->ID ); break; case 'post': $permalink = get_permalink( $post->ID ); break; case 'attachment': $permalink = get_attachment_link( $post->ID ); break; default: $permalink = get_post_permalink( $post->ID ); break; } /* collect permalinks */ $links[] = $permalink; } /* just in case, reset $post */ wp_reset_postdata(); /* switch back to original site if we navigated away */ if ( $site !== false ) { switch_to_blog( $current_blog ); } } } } ?>