SG Optimizer - Version 2.2.10

Version Description

Download this release

Release Info

Developer Hristo Sg
Plugin Icon 128x128 SG Optimizer
Version 2.2.10
Comparing to
See all releases

Version 2.2.10

class-sg-cachepress-admin.php ADDED
@@ -0,0 +1,314 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SG CachePress
4
+ *
5
+ * @package SG_CachePress
6
+ * @author SiteGround
7
+ * @author George Penkov
8
+ * @author Gary Jones <gamajo@gamajo.com>
9
+ * @link http://www.siteground.com/
10
+ * @copyright 2014 SiteGround
11
+ */
12
+
13
+ /** SG CachePress purge cache admin class */
14
+
15
+
16
+
17
+ class SG_CachePress_Admin {
18
+
19
+ /**
20
+ * Slug of the plugin screen.
21
+ *
22
+ * @since 1.1.0
23
+ *
24
+ * @var string
25
+ */
26
+ protected $page_hook = null;
27
+
28
+ /**
29
+ * Holds the options object
30
+ *
31
+ * @since 1.1.0
32
+ *
33
+ * @type SG_CachePress_Options
34
+ */
35
+ protected $options_handler;
36
+
37
+ /**
38
+ * Assign dependencies.
39
+ *
40
+ * @since 1.1.0
41
+ *
42
+ * @param SG_CachePress_Options $options_handler
43
+ */
44
+ public function __construct( $options_handler ) {
45
+ $this->options_handler = $options_handler;
46
+ }
47
+
48
+ /**
49
+ * Initialize the administration functions.
50
+ *
51
+ * @since 1.1.0
52
+ */
53
+ public function run() {
54
+ // Add the admin page and menu item.
55
+ add_action( 'admin_menu', array( $this, 'add_plugin_admin_menu' ));
56
+
57
+ // Admin Init
58
+ add_action( 'admin_init', array( $this, 'load_admin_global_js' ));
59
+
60
+ // Add admin notification notices, so it can display when there is a problem with the plugin
61
+ add_action( 'admin_notices', array( $this, 'plugin_admin_notices'));
62
+
63
+ // Add the admin bar purge button
64
+ add_action( 'admin_bar_menu', array( $this, 'add_admin_bar_purge' ), PHP_INT_MAX );
65
+
66
+ // Load admin assets.
67
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_styles' ) );
68
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
69
+
70
+ // Ajax callback
71
+ add_action( 'wp_ajax_sg-cachepress-purge', array( 'SG_CachePress_Supercacher', 'purge_cache' ) );
72
+ add_action( 'wp_ajax_sg-cachepress-blacklist-update', array( $this, 'update_blacklist' ) );
73
+ add_action( 'wp_ajax_sg-cachepress-parameter-update', array( $this, 'update_parameter' ) );
74
+ add_action( 'wp_ajax_sg-cachepress-cache-test', array( $this, 'cache_test_callback' ) );
75
+ add_action( 'wp_ajax_sg-cachepress-cache-test-message-hide', array( $this, 'cache_test_message_hide' ) );
76
+
77
+
78
+ // Add the admin bar purge button handler
79
+ add_action( 'admin_post_sg-cachepress-purge', array( 'SG_CachePress_Supercacher', 'purge_cache_admin_bar' ) );
80
+ }
81
+
82
+ /**
83
+ * Displays the notice on the top of admin panel if it has caching issues
84
+ *
85
+ * @since 2.2.7
86
+ */
87
+ function plugin_admin_notices() {
88
+ $options = new SG_CachePress_Options();
89
+
90
+ if( $options->get_option('show_notice') == 1 )
91
+ {
92
+ $html = '<div id="ajax-notification" class="updated sg-cachepress-notification">';
93
+ $html .= '<p>';
94
+ $html .= __( '<strong>SG CachePress:</strong> Your site '.get_site_url().' is <strong>not cached</strong>! Make sure the Dynamic Cache is enabled in the SuperCacher tool in cPanel. <a href="javascript:;" id="dismiss-sg-cahepress-notification">Click here to hide this notice</a>.', 'ajax-notification' );
95
+ $html .= '</p>';
96
+ $html .= '<span id="ajax-notification-nonce" class="hidden">' . wp_create_nonce( 'ajax-notification-nonce' ) . '</span>';
97
+ $html .= '</div>';
98
+ echo $html;
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Loads the global admin js
104
+ *
105
+ * @since 2.2.7
106
+ */
107
+ function load_admin_global_js()
108
+ {
109
+ wp_enqueue_script( '', plugins_url( 'js/admin_global.js', __FILE__ ), array( 'jquery' ), SG_CachePress::VERSION, true );
110
+ }
111
+
112
+ /**
113
+ * This make test if the cache is on returning the value of the x-proxy-cache header from the desired page by $_POST['url'] parameter
114
+ *
115
+ * @since 2.2.7
116
+ */
117
+ function cache_test_callback()
118
+ {
119
+ $urlToCheck = get_site_url()."/".$_POST['url'];
120
+ $result = SG_CachePress_Supercacher::return_cache_result($urlToCheck);
121
+
122
+ if($result == 1 && empty($_POST['url']))
123
+ {
124
+ $options = new SG_CachePress_Options();
125
+ $options->disable_option('show_notice');
126
+ }
127
+
128
+ echo $result;
129
+ wp_die();
130
+ }
131
+
132
+ /**
133
+ * This function hides the notice from displaying when it is manually closed
134
+ *
135
+ * @since 2.2.7
136
+ */
137
+ function cache_test_message_hide()
138
+ {
139
+ $options = new SG_CachePress_Options();
140
+ $options->disable_option('show_notice');
141
+
142
+ echo 1;
143
+ wp_die();
144
+ }
145
+
146
+ /**
147
+ * Preloads and caches the server type so it wont have to make query each time when is needed
148
+ */
149
+ public static function return_and_cache_server_type()
150
+ {
151
+ $sgcachepress_options = new SG_CachePress_Options();
152
+ if( !$sgcachepress_options->is_enabled('checked_nginx') )
153
+ {
154
+ $sgcachepress_options->enable_option('checked_nginx');
155
+ if( SG_CachePress_Supercacher::return_check_is_nginx() )
156
+ {
157
+ $sgcachepress_options->enable_option('is_nginx');
158
+ return true;
159
+ }
160
+ else
161
+ {
162
+ $sgcachepress_options->disable_option('is_nginx');
163
+ return false;
164
+ }
165
+ }
166
+
167
+ if( $sgcachepress_options->is_enabled('is_nginx') )
168
+ return true;
169
+
170
+ return false;
171
+ }
172
+
173
+ /**
174
+ * Adds a purge buttion in the admin bar menu
175
+ *
176
+ * @param $wp_admin_bar WP_Admin_Bar
177
+ * @since 2.2.1
178
+ */
179
+ function add_admin_bar_purge( $wp_admin_bar ){
180
+ $args = array(
181
+ 'id' => 'SG_CachePress_Supercacher_Purge',
182
+ 'title' => 'Purge SG Cache',
183
+ 'href' => wp_nonce_url( admin_url( 'admin-post.php?action=sg-cachepress-purge' ),'sg-cachepress-purge' ),
184
+ 'meta' => array( 'class' => 'sg-cachepress-admin-bar-purge' )
185
+ );
186
+ if ( current_user_can('manage_options') ) {
187
+ $wp_admin_bar->add_node( $args );
188
+ }
189
+ }
190
+
191
+ /**
192
+ * Updates a param from ajax request
193
+ *
194
+ * @since 1.1.0
195
+ */
196
+ public function update_parameter() {
197
+ $paramTranslator = array(
198
+ 'dynamic-cache' => 'enable_cache',
199
+ 'memcached' => 'enable_memcached',
200
+ 'autoflush-cache' => 'autoflush_cache',
201
+ );
202
+
203
+ $paramName = $paramTranslator[$_POST['parameterName']];
204
+ $currentValue = (int)$this->options_handler->get_option($paramName);
205
+ $toggledValue = (int)!$currentValue;
206
+
207
+ //if cache is turned on or off it's a good idea to flush it on right away
208
+ if ($paramName == 'enable_cache') {
209
+ SG_CachePress_Supercacher::purge_cache();
210
+ }
211
+
212
+ if ($paramName == 'enable_memcached') {
213
+ global $sg_cachepress_memcache;
214
+ //check if we can actually enable memcached and display error if not
215
+ if ($toggledValue == 1) {
216
+ if (!$sg_cachepress_memcache->check_and_create_memcached_dropin())
217
+ die( "Please, first enable Memcached from your cPanel!" );
218
+ }
219
+ else {
220
+ if (!$sg_cachepress_memcache->remove_memcached_dropin())
221
+ die( "Could not disable memcache!" );
222
+ }
223
+ }
224
+
225
+ if ($this->options_handler->update_option($paramName,$toggledValue))
226
+ {
227
+ if($paramName == 'enable_cache' && $toggledValue == 1)
228
+ {
229
+ SG_CachePress::check_if_plugin_caches();
230
+ }
231
+ else if($paramName == 'enable_cache' && $toggledValue == 0)
232
+ {
233
+ $sg_cachepress_options = new SG_CachePress_Options();
234
+ $sg_cachepress_options->disable_option('show_notice');
235
+ }
236
+ die((string)$toggledValue);
237
+ }
238
+ else
239
+ die((string)$currentValue);
240
+ }
241
+ /**
242
+ * Updates the blacklist from ajax request
243
+ *
244
+ * @since 1.1.0
245
+ */
246
+ public function update_blacklist() {
247
+ die((int)$this->options_handler->update_option('blacklist',$_POST['blacklist']));
248
+ }
249
+
250
+ /**
251
+ * Register and enqueue admin-specific style sheet.
252
+ *
253
+ * @since 1.1.0
254
+ */
255
+ public function enqueue_admin_styles() {
256
+ if ( ! isset( $this->page_hook ) )
257
+ return;
258
+
259
+ $screen = get_current_screen();
260
+ if ( $screen->id == $this->page_hook )
261
+ wp_enqueue_style( SG_CachePress::PLUGIN_SLUG . '-admin', plugins_url( 'css/admin.css', __FILE__ ), array(), SG_CachePress::VERSION );
262
+ }
263
+
264
+ /**
265
+ * Register and enqueue admin-specific JavaScript.
266
+ *
267
+ * @since 1.1.0
268
+ *
269
+ * @return null Return early if no settings page is registered.
270
+ */
271
+ public function enqueue_admin_scripts() {
272
+ if ( ! isset( $this->page_hook ) )
273
+ return;
274
+
275
+ $screen = get_current_screen();
276
+ if ( $screen->id == $this->page_hook ) {
277
+ wp_enqueue_script( SG_CachePress::PLUGIN_SLUG . '-admin', plugins_url( 'js/admin.js', __FILE__ ), array( 'jquery' ), SG_CachePress::VERSION, true );
278
+ $strings = array(
279
+ 'purge' => __( 'Purge the Cache', 'sg-cachepress' ),
280
+ 'purging' => __( 'Purging, please wait...', 'sg-cachepress' ),
281
+ 'updating' => __( 'Updating, please wait...', 'sg-cachepress' ),
282
+ 'updated' => __( 'Update the Exclude List' ),
283
+ 'purged' => __( 'Successfully Purged', 'sg-cachepress' ),
284
+ 'ajax_url' => admin_url( 'admin-ajax.php' )
285
+ );
286
+ wp_localize_script( SG_CachePress::PLUGIN_SLUG . '-admin', 'sgCachePressL10n', $strings );
287
+ }
288
+ }
289
+
290
+ /**
291
+ * Register the top level page into the WordPress admin menu.
292
+ *
293
+ * @since 1.1.0
294
+ */
295
+ public function add_plugin_admin_menu() {
296
+ $this->page_hook = add_menu_page(
297
+ __( 'SuperCacher', 'sg-cachepress' ), // Page title
298
+ __( 'SuperCacher', 'sg-cachepress' ), // Menu item title
299
+ 'manage_options',
300
+ SG_CachePress::PLUGIN_SLUG, // Page slug
301
+ array( $this, 'display_plugin_admin_page' ),
302
+ plugins_url('sg-cachepress/css/logo-white.svg')
303
+ );
304
+ }
305
+
306
+ /**
307
+ * Render the settings page for this plugin.
308
+ *
309
+ * @since 1.1.0
310
+ */
311
+ public function display_plugin_admin_page() {
312
+ include 'views/sg-cache.php';
313
+ }
314
+ }
class-sg-cachepress-environment.php ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SG CachePress
4
+ *
5
+ * @package SG_CachePress
6
+ * @author SiteGround
7
+ * @author George Penkov
8
+ * @author Gary Jones <gamajo@gamajo.com>
9
+ * @link http://www.siteground.com/
10
+ * @copyright 2014 SiteGround
11
+ */
12
+
13
+ /** SG CachePress environment class */
14
+
15
+ class SG_CachePress_Environment {
16
+
17
+ /**
18
+ * Holds the options object.
19
+ *
20
+ * @since 1.1.0
21
+ *
22
+ * @type SG_CachePress_Options
23
+ */
24
+ protected $options_handler;
25
+
26
+ /**
27
+ * Hold environment data.
28
+ *
29
+ * @todo Make this class implement ArrayAccess so it can grab values direct from this property.
30
+ *
31
+ * @type array
32
+ */
33
+ protected $data = array();
34
+
35
+ /**
36
+ * Assign dependencies.
37
+ *
38
+ * @since 1.1.0
39
+ *
40
+ * @param SG_CachePress_Options $options_handler
41
+ */
42
+ public function __construct( $options_handler ) {
43
+ $this->options_handler = $options_handler;
44
+ }
45
+
46
+ /**
47
+ * Obtain and set application's path and URL for further usage.
48
+ *
49
+ * @since 1.1.0
50
+ *
51
+ * @return string
52
+ */
53
+ public function get_application_path() {
54
+ if ( ! isset( $this->data['application_path'] ) ) {
55
+ $homeUrl = home_url( '/' );
56
+
57
+ if( isset( $_SERVER['HTTP_HOST'] ) )
58
+ $httpHost = $_SERVER['HTTP_HOST'];
59
+ else
60
+ $httpHost = get_home_url();
61
+
62
+ $urlExplode = explode( $httpHost, $homeUrl );
63
+ $this->data['application_path'] = $urlExplode[1];
64
+ }
65
+ return $this->data['application_path'];
66
+ }
67
+
68
+ /**
69
+ * Crude check to see if the script is being called via CLI or not.
70
+ *
71
+ * @since 1.1.0
72
+ *
73
+ * @return boolean True is a remote address from server superglobal could be found, false otherwise.
74
+ */
75
+ public function is_using_cli() {
76
+ if ( ! isset( $this->data['cli'] ) ) {
77
+ $this->data['cli'] = false;
78
+ if ( ! isset( $_SERVER['REMOTE_ADDR'] ) || ! $_SERVER['REMOTE_ADDR'] )
79
+ $this->data['cli'] = true;
80
+ }
81
+
82
+ return $this->data['cli'];
83
+ }
84
+
85
+ /**
86
+ * Check if the SG Cache is enabled.
87
+ *
88
+ * @since 1.1.0
89
+ *
90
+ * @return bool True is enabled, false otherwise.
91
+ */
92
+ public function cache_is_enabled() {
93
+ return $this->options_handler->is_enabled( 'enable_cache' );
94
+ }
95
+
96
+ /**
97
+ * Check if the autoflush setting is enabled.
98
+ *
99
+ * @since 1.1.0
100
+ *
101
+ * @return bool True is autoflush enabled, false otherwise.
102
+ */
103
+ public function autoflush_enabled() {
104
+ return $this->options_handler->is_enabled( 'autoflush_cache' );
105
+ }
106
+
107
+ /**
108
+ * Check if memcached setting is enable.
109
+ *
110
+ * @todo Probably want to check if Memcached is actually responding or not as well.
111
+ *
112
+ * @since 1.1.0
113
+ *
114
+ * @return bool True if enabled, false otherwise.
115
+ */
116
+ public function memcached_is_enabled() {
117
+ return $this->options_handler->is_enabled( 'enable_memcached' );
118
+ }
119
+
120
+ /**
121
+ * Helper function to check if a key in the $_POST superglobal is both set and a certain value.
122
+ *
123
+ * Args here are reversed from usual to better match the action_data_is() method.
124
+ *
125
+ * @since 1.1.0
126
+ *
127
+ * @param string $value Post data value
128
+ * @param string $key Post data key
129
+ *
130
+ * @return bool True is key exists and has a matching value.
131
+ */
132
+ public function post_data_is( $value, $key ) {
133
+ return isset( $_POST[ $key ] ) && $value === $_POST[ $key ];
134
+ }
135
+
136
+ /**
137
+ * Helper function to check if the action key in the $_POST superglobal is both set and a certain value.
138
+ *
139
+ * @since 1.1.0
140
+ *
141
+ * @param string $value Post data value
142
+ *
143
+ * @return bool True is key exists and has a matching value.
144
+ */
145
+ public function action_data_is( $value ) {
146
+ return $this->post_data_is( $value, 'action' );
147
+ }
148
+ }
class-sg-cachepress-memcache.php ADDED
@@ -0,0 +1,235 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SG CachePress
4
+ *
5
+ * @package SG_CachePress
6
+ * @author SiteGround
7
+ * @author George Penkov
8
+ * @author Gary Jones <gamajo@gamajo.com>
9
+ * @link http://www.siteground.com/
10
+ * @copyright 2014 SiteGround
11
+ */
12
+
13
+
14
+ /** SG CachePress main plugin class */
15
+
16
+ class SG_CachePress_Memcache {
17
+
18
+ /**
19
+ * Flag which raises when we already flushed on this page exec.
20
+ *
21
+ * @since Unknown
22
+ *
23
+ * @type bool
24
+ */
25
+ private static $_flushed = false;
26
+
27
+ /**
28
+ * Holds the options object.
29
+ *
30
+ * @since 1.1.0
31
+ *
32
+ * @type SG_CachePress_Options
33
+ */
34
+ protected $options_handler;
35
+
36
+ /**
37
+ * Holds the environment object.
38
+ *
39
+ * @since 1.1.0
40
+ *
41
+ * @type SG_CachePress_Environment
42
+ */
43
+ protected $environment;
44
+
45
+ /**
46
+ * Assign depdndencies.
47
+ *
48
+ * @since 1.1.0
49
+ *
50
+ * @param SG_CachePress_Options $options_handler
51
+ * @param SG_CachePress_Environment $environment
52
+ */
53
+ public function __construct( $options_handler, $environment ) {
54
+ $this->options_handler = $options_handler;
55
+ $this->environment = $environment;
56
+ }
57
+
58
+ /**
59
+ * Initialize the class by hooking and running methods.
60
+ *
61
+ * @since 1.1.0
62
+ *
63
+ * @return null Return early and avoid any further interaction if accessing the script via CLI.
64
+ */
65
+ public function run() {
66
+ if ( $this->options_handler->is_enabled( 'enable_memcached' ) && !$this->check_if_dropin_exists()){
67
+ if (!$this->check_and_create_memcached_dropin()){
68
+ $this->options_handler->disable_option('enable_memcached');
69
+ }
70
+ }
71
+
72
+ if ( !$this->options_handler->is_enabled( 'enable_memcached' ) && $this->check_if_dropin_exists())
73
+ {
74
+ if (!$this->remove_memcached_dropin()){
75
+ $this->options_handler->enable_option('enable_memcached');
76
+ }
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Check if the object-cache.php dropin file exists (is readable).
82
+ *
83
+ * @since 1.2.0
84
+ *
85
+ * @return bool
86
+ */
87
+ protected function check_if_dropin_exists(){
88
+ return is_readable( $this->get_object_cache_file() );
89
+ }
90
+
91
+ /**
92
+ * Get the path to where the object cache dropin should be.
93
+ *
94
+ * @since 1.1.0
95
+ */
96
+ protected function get_object_cache_file() {
97
+ return trailingslashit( WP_CONTENT_DIR ) . 'object-cache.php';
98
+ }
99
+
100
+ /**
101
+ * Get the contents of a port file specific to an account.
102
+ *
103
+ * @since 1.1.0
104
+ *
105
+ * @param string $account_name Name of the account (bit after /home/).
106
+ *
107
+ * @return string|false Contents of the port file, or empty string if it couldn't be read.
108
+ */
109
+ protected function get_port_file_contents( $account_name ) {
110
+ $port_file = "/home/{$account_name}/.SGCache/cache_status";
111
+ if ( ! is_readable( $port_file ) )
112
+ return '';
113
+ return file_get_contents( $port_file );
114
+ }
115
+
116
+ /**
117
+ * Search a string for what looks like a Memcached port.
118
+ *
119
+ * @since 1.1.0
120
+ *
121
+ * @param string $string Any string, but likely the contents of a port file.
122
+ *
123
+ * @return string Port number, or empty string if it couldn't be determined.
124
+ */
125
+ protected function get_memcached_port_from_string( $string ) {
126
+ if ( ! preg_match( '#memcache\|\|([0-9]+)#', $string, $matches ) )
127
+ return '';
128
+ if ( ! isset( $matches[1] ) || ! $matches[1] )
129
+ return '';
130
+ return $matches[1];
131
+ }
132
+
133
+ /**
134
+ * Get the Memcached port for the current account.
135
+ *
136
+ * @since Unknown
137
+ *
138
+ * @return string Memcached port number, or empty string if error.
139
+ */
140
+ protected function get_memcached_port() {
141
+ $account_name = get_current_user();
142
+
143
+ $port_file_content = $this->get_port_file_contents( $account_name );
144
+ if ( ! $port_file_content )
145
+ return '';
146
+
147
+ return $this->get_memcached_port_from_string( $port_file_content );
148
+ }
149
+
150
+ /**
151
+ * Check and create a Memcached dropin.
152
+ *
153
+ *
154
+ * @since Unknown
155
+ *
156
+ * @return bool True on dropin creation, false otherwise.
157
+ */
158
+ public function check_and_create_memcached_dropin() {
159
+ $ip = '127.0.0.1';
160
+ $port = $this->get_memcached_port();
161
+ if ( ! $port )
162
+ return false;
163
+
164
+ $object_cache_file = $this->get_object_cache_file();
165
+
166
+ $memcache = new Memcache;
167
+ @$memcache->connect( $ip, $port );
168
+
169
+ if ( $this->memcached_connection_is_working( $memcache ) )
170
+ return $this->create_memcached_dropin( $ip, $port );
171
+
172
+ $this->remove_memcached_dropin();
173
+
174
+ return false;
175
+ }
176
+
177
+ /**
178
+ * Check if a Memcached connection is working by setting and immediately getting a value.
179
+ *
180
+ * @since 1.1.0
181
+ *
182
+ * @param object $connection Memcache object.
183
+ *
184
+ * @return bool True on retrieving exactly the value set, false otherwise.
185
+ */
186
+ protected function memcached_connection_is_working( $connection ) {
187
+ if ( ! $connection )
188
+ return false;
189
+ @$connection->set( 'SGCP_Memcached_Test', 'Test!1', MEMCACHE_COMPRESSED, 50 );
190
+ if ( @$connection->get( 'SGCP_Memcached_Test' ) === 'Test!1' )
191
+ {
192
+ $connection->flush();
193
+ return true;
194
+ }
195
+ return false;
196
+ }
197
+
198
+ /**
199
+ * Copy the Memcache template contents into object-cache.php, replacing IP and Port where needed.
200
+ *
201
+ * @since 1.1.0
202
+ *
203
+ * @param string $ip Memcached IP.
204
+ * @param string $port Memcached Port.
205
+ *
206
+ * @return bool True if the template was successfully copied, false otherwise.
207
+ */
208
+ protected function create_memcached_dropin( $ip, $port ) {
209
+ $object_cache_file = $this->get_object_cache_file();
210
+ $template = file_get_contents( dirname( __FILE__ ) . '/memcache.tpl' );
211
+ $find = '@changedefaults@';
212
+ $replace = "{$ip}:{$port}";
213
+ $new_object_cache = str_replace( $find, $replace, $template );
214
+ if ( file_put_contents( $object_cache_file, $new_object_cache ) )
215
+ return true;
216
+ return false;
217
+ }
218
+
219
+ /**
220
+ * Remove the object-cache.php file.
221
+ *
222
+ * @since Unknown
223
+ *
224
+ * @return bool True on successful removal, false otherwise.
225
+ */
226
+ public function remove_memcached_dropin() {
227
+ $object_cache_file = $this->get_object_cache_file();
228
+
229
+ if ( is_readable( $object_cache_file ) ) {
230
+ unlink( $object_cache_file );
231
+ return true;
232
+ }
233
+ return false;
234
+ }
235
+ }
class-sg-cachepress-options.php ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SG CachePress
4
+ *
5
+ * @package SG_CachePress
6
+ * @author SiteGround
7
+ * @author George Penkov
8
+ * @author Gary Jones <gamajo@gamajo.com>
9
+ * @link http://www.siteground.com/
10
+ * @copyright 2014 SiteGround
11
+ */
12
+
13
+ /** SG CachePress options class */
14
+
15
+ class SG_CachePress_Options {
16
+
17
+ /**
18
+ * Holds the options key, under which all SGCP settings are stored.
19
+ *
20
+ * @since 1.1.0
21
+ *
22
+ * @type string
23
+ */
24
+ protected $options_key = 'sg_cachepress';
25
+
26
+ /**
27
+ * Retrieve the whole array of settings, or one individual value.
28
+ *
29
+ * @since 1.1.0
30
+ *
31
+ * @todo Could implement an extra layer of caching here, to avoid calls to get_option().
32
+ *
33
+ * @todo Split get_option() out to get_all_options(), so return type is consistent?
34
+ *
35
+ * @param string $key Optional. Setting field key.
36
+ *
37
+ * @return array|int
38
+ */
39
+ public function get_option( $key = null ) {
40
+ $options = get_option( $this->options_key );
41
+
42
+ if ( $key && isset( $options[ $key ] ) )
43
+ return (int) $options[ $key ];
44
+ return $options;
45
+ }
46
+
47
+ /**
48
+ * Enable a single boolean setting.
49
+ *
50
+ * @since 1.1.0
51
+ *
52
+ * @param string $key Setting field key.
53
+ *
54
+ * @return bool True on success, false otherwise.
55
+ */
56
+ public function enable_option( $key ) {
57
+ return $this->update_option( $key, 1 );
58
+ }
59
+
60
+ /**
61
+ * Disable a single boolean setting.
62
+ *
63
+ * @since 1.1.0
64
+ *
65
+ * @param string $key Setting field key.
66
+ *
67
+ * @return bool True on success, false otherwise.
68
+ */
69
+ public function disable_option( $key ) {
70
+ return $this->update_option( $key, 0 );
71
+ }
72
+
73
+ /**
74
+ * Update a single setting.
75
+ *
76
+ * @since 1.1.0
77
+ *
78
+ * @param string $key Setting field key.
79
+ * @param mixed $value Setting field value.
80
+ *
81
+ * @return bool True on success, false otherwise.
82
+ */
83
+ public function update_option( $key, $value ) {
84
+ $options = $this->get_option();
85
+ $options[ $key ] = $value;
86
+ return update_option( $this->options_key, $options );
87
+ }
88
+
89
+ /**
90
+ * Check if a single boolean setting is enabled.
91
+ *
92
+ * @since 1.1.0
93
+ *
94
+ * @param string $key Setting field key.
95
+ *
96
+ * @return boolean True if the setting is enabled, false otherwise.
97
+ */
98
+ public function is_enabled( $key ) {
99
+ if ( 1 === $this->get_option( $key ) )
100
+ return true;
101
+ return false;
102
+ }
103
+
104
+ /**
105
+ * Handle upgrade from old individual settings to new single array setting.
106
+ *
107
+ * @since 1.1.0
108
+ */
109
+ public function upgrade() {
110
+ // If the new key already exists, then we've either already upgraded, or saved some settings, so abort now.
111
+ if ( $this->get_option() )
112
+ return;
113
+ // Set the defaults
114
+ $this->init_options();
115
+ $this->remove_old_options();
116
+ }
117
+
118
+ /**
119
+ * Initialize the values in the single setting array.
120
+ *
121
+ * @since 1.1.0
122
+ */
123
+ public function init_options() {
124
+ add_option( $this->options_key, $this->get_defaults() );
125
+ }
126
+
127
+ /**
128
+ * Get all of the setting field keys and the default values.
129
+ *
130
+ * Tries to use the old settings if they still exist.
131
+ *
132
+ * @since 1.1.0
133
+ */
134
+ public function get_defaults() {
135
+ return array(
136
+ 'enable_cache' => get_option( 'SGCP_Use_SG_Cache', 0 ),
137
+ 'autoflush_cache' => get_option( 'SGCP_Autoflush', 1 ),
138
+ 'enable_memcached' => get_option( 'SGCP_Memcached', 1 ),
139
+ 'show_notice' => get_option( 'SGCP_ShowNotice', 0 ),
140
+ 'is_nginx' => get_option( 'SGCP_IsNginx', 0),
141
+ 'checked_nginx' => get_option( 'SGCP_CheckedNginx', 0),
142
+ 'first_run' => get_option( 'SGCP_FristRun', 0)
143
+ );
144
+ }
145
+
146
+ /**
147
+ * Remove the old settings.
148
+ *
149
+ * @since 1.1.0
150
+ */
151
+ protected function remove_old_options() {
152
+ delete_option( 'SGCP_Use_SG_Cache' );
153
+ delete_option( 'SGCP_Autoflush' );
154
+ delete_option( 'SGCP_Memcached' );
155
+ delete_option( 'SGCP_ShowNotice' );
156
+ delete_option( 'SGCP_IsNginx' );
157
+ delete_option( 'SGCP_CheckedNginx' );
158
+ delete_option( 'SGCP_FirstRun' );
159
+ }
160
+
161
+ /**
162
+ * Gets the blacklisted urls
163
+ *
164
+ * @since 1.1.1
165
+ * @return string The blacklist
166
+ */
167
+ public function get_blacklist()
168
+ {
169
+ $options = get_option( $this->options_key );
170
+
171
+ if ( isset( $options[ 'blacklist' ] ) && strlen($options[ 'blacklist' ]) )
172
+ return $options[ 'blacklist' ];
173
+
174
+ return '';
175
+ }
176
+ }
class-sg-cachepress-supercacher.php ADDED
@@ -0,0 +1,574 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package SG_CachePress
4
+ * @author SiteGround
5
+ * @author George Penkov
6
+ * @author Gary Jones <gamajo@gamajo.com>
7
+ * @link http://www.siteground.com/
8
+ * @copyright 2014 SiteGround
9
+ */
10
+
11
+ /** SG CachePress main plugin class */
12
+
13
+ class SG_CachePress_Supercacher {
14
+
15
+ /**
16
+ * Flag which raises when we already flushed on this page exec.
17
+ *
18
+ * @since Unknown
19
+ *
20
+ * @type bool
21
+ */
22
+ private static $_flushed = false;
23
+
24
+ /**
25
+ * Holds the options object.
26
+ *
27
+ * @since 1.1.0
28
+ *
29
+ * @type SG_CachePress_Options
30
+ */
31
+ protected $options_handler;
32
+
33
+ /**
34
+ * Holds the environment object.
35
+ *
36
+ * @since 1.1.0
37
+ *
38
+ * @type SG_CachePress_Environment
39
+ */
40
+ protected $environment;
41
+
42
+ /**
43
+ * Assign dependencies.
44
+ *
45
+ * @since 1.1.0
46
+ *
47
+ * @param SG_CachePress_Options $options_handler
48
+ * @param SG_CachePress_Environment $environment
49
+ */
50
+ public function __construct( $options_handler, $environment ) {
51
+ $this->options_handler = $options_handler;
52
+ $this->environment = $environment;
53
+ }
54
+
55
+ /**
56
+ * Initialize the class by hooking and running methods.
57
+ *
58
+ * @since 1.1.0
59
+ *
60
+ * @return null Return early and avoid any further interaction if accessing the script via CLI.
61
+ */
62
+ public function run() {
63
+ if ( $this->environment->is_using_cli() )
64
+ return;
65
+
66
+ $this->assign_hooks_for_autoflush();
67
+ }
68
+
69
+ /**
70
+ * Call the cache server to purge the cache.
71
+ *
72
+ * Since this method is also called via Ajax (where $this doesn't exist --it does not exist because the method is invoked as static--), we replace the usual $this with the global
73
+ * variable that contains an instance of this class. Not ideal but apparently works.
74
+ *
75
+ *
76
+ * @since Unknown
77
+ *
78
+ * @return null
79
+ */
80
+ public static function purge_cache($dontDie = false) {
81
+ global $sg_cachepress_supercacher;
82
+ if ( $sg_cachepress_supercacher->environment->is_using_cli() )
83
+ return;
84
+
85
+ if ( self::$_flushed )
86
+ return;
87
+
88
+ $purge_request = $sg_cachepress_supercacher->environment->get_application_path() . '(.*)';
89
+
90
+ // Check if caching server is varnish or nginx.
91
+ $sgcache_ip = '/etc/sgcache_ip';
92
+ $hostname = $_SERVER['SERVER_ADDR'];
93
+ $purge_method = "PURGE";
94
+
95
+ if (file_exists($sgcache_ip) && !self::is_nginx_server()) {
96
+ $hostname = trim( file_get_contents( $sgcache_ip, true ) );
97
+ $purge_method = "BAN";
98
+ }
99
+
100
+ $cache_server_socket = fsockopen( $hostname, 80, $errno, $errstr, 2 );
101
+ if( ! $cache_server_socket ) {
102
+ $sg_cachepress_supercacher->SGCP_Notify( 'Connection to cache server failed!' );
103
+ return;
104
+ }
105
+
106
+ $request = "$purge_method {$purge_request} HTTP/1.0\r\n";
107
+ $request .= "Host: {$_SERVER['SERVER_NAME']}\r\n";
108
+ $request .= "Connection: Close\r\n\r\n";
109
+
110
+ fwrite( $cache_server_socket, $request );
111
+ $response = fgets( $cache_server_socket );
112
+
113
+ fclose( $cache_server_socket );
114
+
115
+ // Only die (or notify) if doing an Ajax request
116
+ if ( $sg_cachepress_supercacher->environment->action_data_is( 'sg-cachepress-purge' ) ) {
117
+ if ( preg_match( '/200/', $response ) )
118
+ {
119
+ if ($dontDie)
120
+ return true;
121
+
122
+ wp_die( 1 );
123
+ }
124
+ else
125
+ {
126
+ if ($dontDie)
127
+ return false;
128
+
129
+ wp_die( 0 );
130
+ }
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Returns if the server is using Nginx
136
+ * @return boolean
137
+ */
138
+ private static function is_nginx_server()
139
+ {
140
+ return SG_CachePress_Admin::return_and_cache_server_type();
141
+ }
142
+
143
+ /**
144
+ * Purges the cache and redirects to referrer (admin bar button)
145
+ *
146
+ * @since 2.2.1
147
+ */
148
+ public static function purge_cache_admin_bar()
149
+ {
150
+ if ( isset( $_GET['_wpnonce'] ) )
151
+ {
152
+ if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'sg-cachepress-purge' ) )
153
+ {
154
+ wp_nonce_ays( '' );
155
+ }
156
+
157
+ self::purge_cache(true);
158
+ wp_redirect( wp_get_referer() );
159
+ die();
160
+ }
161
+ }
162
+ /**
163
+ * Print notification in the admin section, or via AJAX
164
+ *
165
+ * @since Unknown
166
+ *
167
+ * @param string|bool $message Message to be displayed if purge is successful. If this param is false no output would be done
168
+ * @return null
169
+ */
170
+ public static function notify( $message ) {
171
+ add_action( 'muplugins_loaded', SG_CachePress_Memcache::notice( $message ) );
172
+ }
173
+
174
+ /**
175
+ * Add autoflush-related hooks.
176
+ *
177
+ * The check for autoflush disabled is down here, instead of within each callback - autoflush being enabled or not
178
+ * is unlikely to change between when plugin_loaded hook, and each of the listed hooks.
179
+ *
180
+ * @since Unknown
181
+ *
182
+ * @return null Return early if cache is not enabled, or autoflush is disabled.
183
+ */
184
+ public function assign_hooks_for_autoflush() {
185
+
186
+ add_action( 'save_post', array( $this,'hook_add_post' ) );
187
+ add_action( 'edit_post', array( $this,'hook_add_post' ) );
188
+ add_action( 'publish_phone', array( $this,'hook_add_post' ) );
189
+ add_action( 'publish_future_post', array( $this,'hook_add_post' ) );
190
+ add_action( 'xmlrpc_publish_post', array( $this,'hook_add_post' ) );
191
+ add_action( 'before_delete_post', array( $this,'hook_delete_post' ) );
192
+ add_action( 'trash_post', array( $this,'hook_delete_post' ) );
193
+ add_action( 'add_category', array( $this,'hook_add_category' ) );
194
+ add_action( 'edit_category', array( $this,'hook_edit_category' ) );
195
+ add_action( 'delete_category', array( $this,'hook_delete_category' ) );
196
+ add_action( 'add_link', array( $this,'hook_add_link' ) );
197
+ add_action( 'edit_link', array( $this,'hook_edit_link' ) );
198
+ add_action( 'delete_link', array( $this,'hook_delete_link' ) );
199
+ add_action( 'comment_post', array( $this,'hook_add_comment' ),10,2 );
200
+ add_action( 'comment_unapproved_to_approved', array( $this,'hook_approve_unapprove_comment' ) );
201
+ add_action( 'comment_approved_to_unapproved', array( $this,'hook_approve_unapprove_comment' ) );
202
+ add_action( 'delete_comment', array( $this,'hook_delete_comment' ) );
203
+ add_action( 'trash_comment', array( $this,'hook_delete_comment' ) );
204
+ add_action( 'switch_theme', array( $this,'hook_switch_theme' ) );
205
+ add_action( 'customize_save', array( $this,'hook_switch_theme' ) );
206
+ add_action( 'automatic_updates_complete', array( $this,'hook_atomatic_update' ) );
207
+ add_action( 'future_to_publish', array( $this,'scheduled_goes_live' ) );
208
+ add_action( '_core_updated_successfully', array( $this,'core_update_hook' ) );
209
+
210
+ // @todo Move the rest of this to a new method - and document what events it is capturing!
211
+
212
+ if ( ! empty( $_POST ) ) {
213
+
214
+ if (isset($_POST['save-header-options']) || isset($_POST['removeheader'])
215
+ || isset($_POST['skip-cropping']) || (isset($_POST['submit']) && $_POST['submit'] == 'Crop and Publish')
216
+ || isset($_POST['remove-background']) || (isset($_POST['submit']) && $_POST['submit'] == 'Upload')
217
+ || isset($_POST['save-background-options']))
218
+ self::purge_cache();
219
+
220
+ if ( isset( $_POST['action'] ) ) {
221
+ if ( in_array( $_POST['action'], array( 'widgets-order','save-widget','delete-selected' ) ) )
222
+ self::purge_cache();
223
+
224
+ if ( isset( $_POST['submit'] ) && 'update' === $_POST['action'] ) {
225
+ if ( in_array( $_POST['submit'], array( 'Update File', 'Save Changes' ) ) )
226
+ self::purge_cache();
227
+ }
228
+
229
+ }
230
+
231
+ // Settings -> Permalinks
232
+ if ( isset( $_POST['submit'] ) && 'Save Change' === $_POST['submit'] && isset( $_POST['_wp_http_referer'] ) ) {
233
+ $ref = explode( '/', $_POST['_wp_http_referer'] );
234
+ $ref = array_pop( $ref );
235
+
236
+ if ( 'options-permalink.php' === $ref ) {
237
+ if ( 'update' === $_POST['action'] && 'Save Changes' === $_POST['submit'] && 'permalinks' === $_POST['option_page'] )
238
+ self::purge_cache();
239
+ }
240
+ }
241
+
242
+ if( isset( $_POST['save_menu'] ) ) {
243
+ // Add Menu
244
+ if( in_array( $_POST['save_menu'], array( 'Create Menu', 'Save Menu' ) ) )
245
+ self::purge_cache();
246
+
247
+ }
248
+ }
249
+
250
+ if ( ! empty( $_GET ) && isset( $_GET['action'] ) ) {
251
+ if ( isset( $_GET['menu'] ) && 'delete' === $_GET['action'] )
252
+ self::purge_cache();
253
+ if ( isset( $_GET['plugin'] ) && 'activate' === $_GET['action'] )
254
+ self::purge_cache();
255
+ }
256
+ }
257
+
258
+ /**
259
+ * Purge cache when a post is potentially made live.
260
+ *
261
+ * @since Unknown
262
+ *
263
+ * @param int $post_id
264
+ */
265
+ public function hook_add_post( $post_id ) {
266
+ if ( $this->environment->post_data_is( 'Publish', 'publish' ) || $this->environment->action_data_is( 'editpost' ) || $this->environment->action_data_is( 'inline-save' ) )
267
+ self::purge_cache();
268
+ }
269
+
270
+ /**
271
+ * Purge cache when a post is deleted.
272
+ *
273
+ * @since Unknown
274
+ *
275
+ * @param int $post_id
276
+ */
277
+ public function hook_delete_post( $post_id ) {
278
+ if( isset( $_GET['action'] ) && ( 'delete' === $_GET['action'] || 'trash' === $_GET['action'] ) )
279
+ self::purge_cache();
280
+ }
281
+
282
+ /**
283
+ * Purge cache when a category is added.
284
+ *
285
+ * @since Unknown
286
+ *
287
+ * @param int $cat_id
288
+ */
289
+ public function hook_add_category( $cat_id ) {
290
+ if ( $this->environment->action_data_is( 'add-tag' ) )
291
+ self::purge_cache();
292
+ }
293
+
294
+ /**
295
+ * Purge cache when a category is edited.
296
+ *
297
+ * @since Unknown
298
+ *
299
+ * @param int $cat_id
300
+ */
301
+ public function hook_edit_category( $cat_id ) {
302
+ if ( $this->environment->action_data_is( 'editedtag' ) )
303
+ self::purge_cache();
304
+ }
305
+
306
+ /**
307
+ * Purge cache when a category is deleted.
308
+ *
309
+ * @since Unknown
310
+ *
311
+ * @param int $cat_id
312
+ */
313
+ public function hook_delete_category( $cat_id ) {
314
+ if ( $this->environment->action_data_is( 'delete-tag' ) )
315
+ self::purge_cache();
316
+ }
317
+
318
+ /**
319
+ * Purge cache when a link is added.
320
+ *
321
+ * @since Unknown
322
+ *
323
+ * @param int $link_id
324
+ */
325
+ public function hook_add_link( $link_id ) {
326
+ if ( $this->environment->action_data_is( 'add' ) && $this->environment->post_data_is( 'Add Link', 'save' ) )
327
+ self::purge_cache();
328
+ }
329
+
330
+ /**
331
+ * Purge cache when a link is edited.
332
+ *
333
+ * @since Unknown
334
+ *
335
+ * @param int $link_id
336
+ */
337
+ public function hook_edit_link( $link_id ) {
338
+ if ( $this->environment->action_data_is( 'editedtag' ) && $this->environment->post_data_is( 'Update', 'submit' ) )
339
+ self::purge_cache();
340
+ }
341
+
342
+ /**
343
+ * Purge cache when a link is deleted.
344
+ *
345
+ * @since Unknown
346
+ *
347
+ * @param int $link_id
348
+ */
349
+ public function hook_delete_link( $link_id ) {
350
+ if ( $this->environment->action_data_is( 'delete-tag' ) && $this->environment->post_data_is( 'link_category', 'taxonomy' ) )
351
+ self::purge_cache();
352
+ }
353
+
354
+ /**
355
+ * Purge cache when a comment is added.
356
+ *
357
+ * @since Unknown
358
+ *
359
+ * @param int $comment_id
360
+ * @param string $status
361
+ */
362
+ public function hook_add_comment( $comment_id, $status = null ) {
363
+ if ( isset( $_POST['comment_post_ID'] ) ) {
364
+ $comment = get_comment( $comment_id );
365
+
366
+ // Purge post page
367
+ if ( $comment )
368
+ self::purge_cache();
369
+ }
370
+ }
371
+
372
+ /**
373
+ * Purge cache when a comment is approved or unapproved.
374
+ *
375
+ * @since Unknown
376
+ *
377
+ * @param int $comment_id
378
+ * @param string $status
379
+ */
380
+ public function hook_approve_unapprove_comment( $comment_id, $status = null ) {
381
+ if ( isset( $_POST['id'] ) ) {
382
+ $comment = get_comment( $comment_id );
383
+
384
+ // Purge post page
385
+ if( $comment )
386
+ self::purge_cache();
387
+ }
388
+ }
389
+
390
+ /**
391
+ * Purge cache when a comment is deleted.
392
+ *
393
+ * @since Unknown
394
+ *
395
+ * @param int $comment_id
396
+ */
397
+ public function hook_delete_comment( $comment_id ) {
398
+ $comment_actions = array( 'dim-comment','delete-comment' );
399
+
400
+ if ( ( isset( $_POST['action'] ) && isset( $_POST['id'] ) && in_array( $_POST['action'], $comment_actions ) )
401
+ || ( isset( $_GET['action'] ) && isset( $_GET['c'] ) && 'trashcomment' === $_GET['action'] ) ) {
402
+ $comment = get_comment( $_POST['id'] );
403
+ if ( $comment )
404
+ self::purge_cache();
405
+ }
406
+ }
407
+
408
+ /**
409
+ * Purge cache when the theme is switched.
410
+ *
411
+ * @since Unknown
412
+ */
413
+ public function hook_switch_theme() {
414
+ self::purge_cache();
415
+ }
416
+
417
+ /**
418
+ * Purge cache when the Automatic Updates are completd.
419
+ *
420
+ * @since 3.8.1
421
+ */
422
+ public function hook_atomatic_update() {
423
+ self::purge_cache();
424
+ }
425
+
426
+ /**
427
+ * Purge cache when Scheduled post becomes Published
428
+ *
429
+ * @since 3.8.1
430
+ */
431
+ public function scheduled_goes_live() {
432
+ self::purge_cache();
433
+ }
434
+
435
+ /**
436
+ * Purge cache when after successful WordPress core update
437
+ *
438
+ * @since 3.8.1
439
+ */
440
+ public function core_update_hook() {
441
+ self::purge_cache();
442
+ }
443
+
444
+ /**
445
+ * Checks the header returned by calling the home url and determine if the server is nginx
446
+ */
447
+ public static function return_check_is_nginx()
448
+ {
449
+ $url = get_site_url();
450
+ $headers = self::request_data( $url );
451
+
452
+ if( isset($headers['server']) && !empty($headers['server']) )
453
+ {
454
+ if( preg_match('#(nginx)#', $headers['server'] ) )
455
+ return true;
456
+ }
457
+
458
+ return false;
459
+ }
460
+
461
+ /**
462
+ * Returns if the cache header is on
463
+ * @param string $url
464
+ * @return bool
465
+ */
466
+ public static function return_cache_result( $url )
467
+ {
468
+ $headers = self::request_data( $url );
469
+ //Status 0: Cache is not working, 1: Cache is working, 2: Unable to connect
470
+ if( !$headers || !is_array($headers) )
471
+ $status = 2;
472
+ else
473
+ {
474
+ if( isset($headers['x-proxy-cache']) && mb_strtoupper( $headers['x-proxy-cache'] ) == 'HIT' )
475
+ $status = 1;
476
+ else if( isset($headers['x-cache']) && mb_strtoupper( $headers['x-cache'] ) == 'SGCACHE-HIT' )
477
+ $status = 1;
478
+ else
479
+ $status = 0;
480
+ }
481
+
482
+ return $status;
483
+ }
484
+
485
+ /**
486
+ * Defines the function used to initial the cURL library.
487
+ *
488
+ * @param string $url To URL to which the request is being made
489
+ * @return string $response The response, if available; otherwise, null
490
+ */
491
+ private static function curl( $url )
492
+ {
493
+ $curl = curl_init( $url );
494
+
495
+ curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
496
+ curl_setopt( $curl, CURLOPT_HEADER, true );
497
+ curl_setopt( $curl, CURLOPT_NOBODY, true);
498
+ curl_setopt( $curl, CURLOPT_TIMEOUT, 10 );
499
+
500
+ $response = curl_exec( $curl );
501
+ if( 0 !== curl_errno( $curl ) || 200 !== curl_getinfo( $curl, CURLINFO_HTTP_CODE ) ) {
502
+ $response = null;
503
+ } // end if
504
+ curl_close( $curl );
505
+
506
+ return $response;
507
+ }
508
+
509
+ /**
510
+ * Retrieves the headers from the specified URL using one of PHPs requests methods
511
+ * @param $url | URL to retrieve headers from
512
+ * @return array $headers | Returns headers as array
513
+ */
514
+ private static function request_data( $url )
515
+ {
516
+ $response = null;
517
+ $returnHeaders = array();
518
+
519
+ //First, we try wp_remote_get
520
+ $response = wp_remote_get( $url );
521
+ if( !is_wp_error( $response ) )
522
+ {
523
+ $returnHeaders = wp_remote_retrieve_headers( $response );
524
+ $returnHeaders['method'] = 'wp_remote_get';
525
+ }
526
+ else
527
+ {
528
+ //If that doesn't work, then we'll try file_get_contents
529
+ $response = file_get_contents( $url );
530
+ if( $response && isset($http_response_header) ) {
531
+ $returnHeaders = self::parse_headers($http_response_header);
532
+ $returnHeaders['method'] = 'file_get_contents';
533
+ }
534
+ else
535
+ {
536
+ //And if that doesn't work, then we'll try curl
537
+ $response = self::curl( $url );
538
+ if( $response )
539
+ {
540
+ $returnHeaders = self::parse_headers( $response );
541
+ $returnHeaders['method_requested'] = 'curl';
542
+ }
543
+ }
544
+ }
545
+
546
+ return $returnHeaders;
547
+ }
548
+
549
+ /**
550
+ * Parses the header to array from string on array input
551
+ * @param array|string $headers
552
+ * @return array $head
553
+ */
554
+ private static function parse_headers( $headers )
555
+ {
556
+ $head = array();
557
+
558
+ if( !is_array($headers) )
559
+ $headers = explode("\n", $headers);
560
+
561
+ if( is_array($headers) && count($headers) > 0 )
562
+ {
563
+ foreach( $headers as $v )
564
+ {
565
+ $t = explode( ':', $v, 2 );
566
+ if( isset( $t[1] ) )
567
+ $head[ mb_strtolower( trim($t[0]) ) ] = trim( $t[1] );
568
+ }
569
+ }
570
+
571
+ return $head;
572
+ }
573
+
574
+ }
class-sg-cachepress.php ADDED
@@ -0,0 +1,344 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * SG CachePress
5
+ *
6
+ * @package SG_CachePress
7
+ * @author SiteGround
8
+ * @author George Penkov
9
+ * @author Gary Jones <gamajo@gamajo.com>
10
+ * @link http://www.siteground.com/
11
+ * @copyright 2014 SiteGround
12
+ */
13
+
14
+ /** SG CachePress main plugin class */
15
+
16
+ class SG_CachePress {
17
+
18
+ /**
19
+ * Plugin version, used for cache-busting of style and script file references.
20
+ *
21
+ * @since 1.1.0
22
+ *
23
+ * @type string
24
+ */
25
+ const VERSION = '1.1.0';
26
+
27
+ /**
28
+ * Unique identifier for your plugin.
29
+ *
30
+ * Use this value (not the variable name) as the text domain when internationalizing strings of text. It should
31
+ * match the Text Domain file header in the main plugin file.
32
+ *
33
+ * @since 1.1.0
34
+ *
35
+ * @type string
36
+ */
37
+ const PLUGIN_SLUG = 'sg-cachepress';
38
+
39
+ /**
40
+ * Holds the options object
41
+ *
42
+ * @since 1.1.0
43
+ *
44
+ * @type SG_CachePress_Options
45
+ */
46
+ protected $options_handler;
47
+
48
+ /**
49
+ * Assign dependencies.
50
+ *
51
+ * @since 1.1.0
52
+ */
53
+ public function __construct( $options_handler ) {
54
+ $this->options_handler = $options_handler;
55
+ }
56
+
57
+ /**
58
+ * Initialize the class by hooking and running methods.
59
+ *
60
+ * @since 1.1.0
61
+ *
62
+ * @uses SG_CachePress::load_plugin_textdomain() Allow localised language files to be applied.
63
+ * @uses SG_CachePress::activate_new_site() Handle activation on multisite.
64
+ * @uses SG_CachePress_Options::upgrade() Convert old saved settings to new settings.
65
+ * @uses SG_CachePress::set_headers_cookies() Set headers and cookies.
66
+ */
67
+ public function run() {
68
+ // Load plugin text domain
69
+ add_action( 'init', array( $this, 'load_plugin_textdomain' ) );
70
+
71
+ // Activate plugin when new blog is added
72
+ add_action( 'wpmu_new_blog', array( $this, 'activate_new_site' ) );
73
+
74
+ // Allow a check to see if this plugin is running
75
+ // curl -s http://domain.com/?sgCacheCheck=022870ae06716782ce17e4f6e7f69cc2
76
+ if ( isset( $_GET['sgCacheCheck'] ) && md5( 'wpCheck' ) === $_GET['sgCacheCheck'] )
77
+ die( 'OK' );
78
+
79
+ $this->options_handler->upgrade();
80
+
81
+ $this->set_headers_cookies();
82
+ }
83
+
84
+ /**
85
+ * Fired when the plugin is activated.
86
+ *
87
+ * @since 1.1.0
88
+ *
89
+ * @param boolean $network_wide True if WPMU superadmin uses "Network Activate" action, false if WPMU is
90
+ * disabled or plugin is activated on an individual blog.
91
+ */
92
+ public static function activate( $network_wide ) {
93
+ if ( function_exists( 'is_multisite' ) && is_multisite() ) {
94
+ if ( $network_wide ) {
95
+ // Get all blog ids
96
+ $blog_ids = self::get_blog_ids();
97
+
98
+ foreach ( $blog_ids as $blog_id ) {
99
+ switch_to_blog( $blog_id );
100
+ self::single_activate();
101
+ }
102
+ restore_current_blog();
103
+ } else {
104
+ self::single_activate();
105
+ }
106
+ } else {
107
+ self::single_activate();
108
+ }
109
+ self::disable_first_run_option();
110
+ }
111
+
112
+ /**
113
+ * Fired when the plugin is deactivated.
114
+ *
115
+ * @since 1.1.0
116
+ *
117
+ * @param boolean $network_wide True if WPMU superadmin uses "Network Deactivate" action, false if WPMU is
118
+ * disabled or plugin is deactivated on an individual blog.
119
+ */
120
+ public static function deactivate( $network_wide ) {
121
+ if ( function_exists( 'is_multisite' ) && is_multisite() ) {
122
+ if ( $network_wide ) {
123
+ // Get all blog ids
124
+ $blog_ids = self::get_blog_ids();
125
+
126
+ foreach ( $blog_ids as $blog_id ) {
127
+ switch_to_blog( $blog_id );
128
+ self::single_deactivate();
129
+ }
130
+ restore_current_blog();
131
+ } else {
132
+ self::single_deactivate();
133
+ }
134
+ } else {
135
+ self::single_deactivate();
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Fired when a new site is activated with a WPMU environment.
141
+ *
142
+ * @since 1.1.0
143
+ *
144
+ * @param int $blog_id ID of the new blog.
145
+ */
146
+ public function activate_new_site( $blog_id ) {
147
+ if ( 1 !== did_action( 'wpmu_new_blog' ) )
148
+ return;
149
+
150
+ switch_to_blog( $blog_id );
151
+ self::single_activate();
152
+ restore_current_blog();
153
+ }
154
+
155
+ /**
156
+ * Fired when admin is initialised, currently used to make one time check if the plugin runs correctly.
157
+ */
158
+ public static function admin_init_cachepress()
159
+ {
160
+ if( current_user_can('activate_plugins') )
161
+ {
162
+ $sg_cachepress_options = new SG_CachePress_Options;
163
+ if(!$sg_cachepress_options->is_enabled('first_run'))
164
+ {
165
+ self::enable_first_run_option();
166
+ self::check_if_plugin_caches();
167
+ }
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Resets the first run counter, so it can be called once on the first run
173
+ */
174
+ private static function disable_first_run_option()
175
+ {
176
+ $sg_cachepress_options = new SG_CachePress_Options;
177
+ $sg_cachepress_options->disable_option('first_run');
178
+ }
179
+
180
+ /**
181
+ * Sets the first run counter to enabled, to prevent running commands more than once when admin panel is initialised
182
+ */
183
+ private static function enable_first_run_option()
184
+ {
185
+ $sg_cachepress_options = new SG_CachePress_Options;
186
+ $sg_cachepress_options->enable_option('first_run');
187
+ }
188
+
189
+ /**
190
+ * Get all blog ids of blogs in the current network that are:
191
+ * * not archived
192
+ * * not spam
193
+ * * not deleted
194
+ *
195
+ * @since 1.1.0
196
+ *
197
+ * @return array|false The blog ids, false if no matches.
198
+ */
199
+ private static function get_blog_ids() {
200
+ global $wpdb;
201
+
202
+ $sql = "SELECT blog_id FROM $wpdb->blogs WHERE archived = '0' AND spam = '0' AND deleted = '0'";
203
+
204
+ return $wpdb->get_col( $sql );
205
+ }
206
+
207
+ /**
208
+ * Fired for each blog when the plugin is activated.
209
+ *
210
+ * @since 1.1.0
211
+ */
212
+ private static function single_activate() {
213
+ $sg_cachepress_options = new SG_CachePress_Options;
214
+ $sg_cachepress = new SG_CachePress( $sg_cachepress_options );
215
+ if ( ! $sg_cachepress_options->get_option() )
216
+ $sg_cachepress_options->init_options();
217
+ }
218
+
219
+ /**
220
+ * Checks if the plugin caches correctly and shows notice when it does not
221
+ *
222
+ * @since 2.2.7
223
+ */
224
+ public static function check_if_plugin_caches()
225
+ {
226
+ $sg_cachepress_options = new SG_CachePress_Options();
227
+ $urlToCheck = get_site_url();
228
+
229
+ if( $sg_cachepress_options->is_enabled('enable_cache') )
230
+ {
231
+ if( SG_CachePress_Supercacher::return_cache_result($urlToCheck) == 0 )
232
+ {
233
+ if( SG_CachePress_Supercacher::return_cache_result($urlToCheck) == 0 )
234
+ {
235
+ $sg_cachepress_options->enable_option('show_notice');
236
+ return false;
237
+ }
238
+ else
239
+ {
240
+ $sg_cachepress_options->disable_option('show_notice');
241
+ return true;
242
+ }
243
+ }
244
+ else
245
+ {
246
+ $sg_cachepress_options->disable_option('show_notice');
247
+ return true;
248
+ }
249
+ }
250
+ else
251
+ {
252
+ $sg_cachepress_options->disable_option('show_notice');
253
+ return true;
254
+ }
255
+ }
256
+
257
+ /**
258
+ * Fired for each blog when the plugin is deactivated.
259
+ *
260
+ * @since 1.1.0
261
+ */
262
+ private static function single_deactivate() {
263
+ // TODO: Define deactivation functionality here?
264
+ $sg_cachepress_options = new SG_CachePress_Options();
265
+ $sg_cachepress_options->disable_option('show_notice');
266
+ }
267
+
268
+ /**
269
+ * Load the plugin text domain for translation.
270
+ *
271
+ * @since 1.1.0
272
+ */
273
+ public function load_plugin_textdomain() {
274
+ $domain = self::PLUGIN_SLUG;
275
+ $locale = apply_filters( 'plugin_locale', get_locale(), $domain );
276
+
277
+ load_textdomain( $domain, trailingslashit( WP_LANG_DIR ) . $domain . '/' . $domain . '-' . $locale . '.mo' );
278
+ load_plugin_textdomain( $domain, FALSE, basename( dirname( __FILE__ ) ) . '/languages' );
279
+ }
280
+
281
+ /**
282
+ * Check if url is in caching blacklist
283
+ *
284
+ * @since 1.1.1
285
+ * @return bool
286
+ */
287
+ protected function is_url_blacklisted() {
288
+ global $sg_cachepress_environment;
289
+ $blacklistArray = explode("\n",$this->options_handler->get_blacklist());
290
+
291
+ $blacklistRegexArray = array();
292
+ $indexIsBlacklisted = false;
293
+ foreach($blacklistArray as $key=>$row)
294
+ {
295
+ $row = trim($row);
296
+
297
+ if ($row != '/' && $quoted = preg_quote($row,'/'))
298
+ $blacklistRegexArray[$key] = $quoted;
299
+
300
+ if ($row == '/')
301
+ $indexIsBlacklisted = true;
302
+ }
303
+
304
+ if ($indexIsBlacklisted && $_SERVER['REQUEST_URI'] == $sg_cachepress_environment->get_application_path())
305
+ return true;
306
+
307
+ if (empty($blacklistRegexArray))
308
+ return false;
309
+
310
+ $blacklistRegex = '/('.implode('|',$blacklistRegexArray) . ')/i';
311
+
312
+ return preg_match($blacklistRegex, $_SERVER['REQUEST_URI']);
313
+ }
314
+
315
+ /**
316
+ * Set headers and cookies.
317
+ *
318
+ * @since 1.1.0
319
+ */
320
+ protected function set_headers_cookies() {
321
+ if ( ! $this->options_handler->is_enabled( 'enable_cache' ) || $this->is_url_blacklisted()) {
322
+ header( 'X-Cache-Enabled: False' );
323
+ return;
324
+ }
325
+
326
+ header( 'X-Cache-Enabled: True' );
327
+
328
+ // Check if WP LOGGED_IN_COOKIE is set, validate it and define $userIsLoggedIn
329
+ if ( isset( $_COOKIE[LOGGED_IN_COOKIE] ) ) {
330
+ $userIsLoggedIn = wp_validate_auth_cookie( $_COOKIE[LOGGED_IN_COOKIE], 'logged_in' );
331
+ } else {
332
+ $userIsLoggedIn = false;
333
+ }
334
+
335
+ // Logged In Users
336
+ if ( $userIsLoggedIn || ( ! empty( $_POST['wp-submit'] ) && 'Log In' === $_POST['wp-submit'] ) ) {
337
+ // Enable the cache bypass for logged users by setting a cache bypass cookie
338
+ setcookie( 'wpSGCacheBypass', 1, time() + 100 * MINUTE_IN_SECONDS, '/' );
339
+ } elseif ( ! $userIsLoggedIn || 'logout' === $_GET['action'] ) {
340
+ setcookie( 'wpSGCacheBypass', 0, time() - HOUR_IN_SECONDS, '/' );
341
+ }
342
+ }
343
+
344
+ }
css/admin.css ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* HELPERS */
2
+ * { box-sizing: border-box; -moz-box-sizing: border-box; }
3
+ img { display: block; }
4
+ p { display: block; }
5
+ h3 { margin: 0 0 10px; }
6
+ .m0 { margin: 0 !important; }
7
+ .clr { clear: both; display: block; height: 0; line-height: 0; font-size: 0; }
8
+ .clear:before, .clear:after { content: ""; display: table; }
9
+ .clear:after { clear: both;}
10
+ .clear { zoom: 1; }
11
+ .error, .notcached { color: red; text-align: center;}
12
+ .sgwrap p.error { border: none !important;}
13
+ .cached { color: green; font-weight:700 }
14
+ input[type="name"] {box-shadow: none !important; height: 10px}
15
+
16
+ .wp-core-ui .button-primary { background: #3D4A69; color: #fff; border: none; border-color: #3D4A69; box-shadow: none; height: 40px; line-height: 40px; text-align: center; }
17
+ .wp-core-ui .button-primary:hover,
18
+ .wp-core-ui .button-primary:active,
19
+ .wp-core-ui .button-primary:focus,
20
+ .wp-core-ui .button-primary[disabled],
21
+ .wp-core-ui .button-primary:disabled { background: #49587c !important; border-color: !important; box-shadow: none !important; color: #fff !important; }
22
+
23
+ /* LAYOUT */
24
+ .sgwrap { max-width: 800px; margin: 20px 20px 20px 15px; }
25
+ .sgwrap h2 { margin: 0 0 15px; padding: 0; line-height: 29px; }
26
+ .box { margin: 20px 0 0; background: #fff; border: 1px solid #dbdbdb; padding: 20px; }
27
+ .greybox { margin: 10px 0 0; background: #f9f9f9; border: 1px solid #dbdbdb; padding: 20px; }
28
+ .greybox p { font-style: italic; color: #999;}
29
+
30
+ /* BOX 2 */
31
+ .box:nth-of-type(2) .greybox > div:nth-of-type(1) { float: left; width: 70%; margin: 0 2% 0 0; }
32
+ .box:nth-of-type(2) .greybox > div:nth-of-type(2) { float: left; width: 28%; }
33
+ .box:nth-of-type(2) .greybox > div input { width: 100%; height: 40px; padding: 0 10px; margin: 0; }
34
+ .box:nth-of-type(2) .three { margin: 10px 0 0; }
35
+ .box:nth-of-type(2) .three > .greybox { float: left; width: 32%; min-height: 90px; margin: 0 0 0 2%; text-align: center; }
36
+ .box:nth-of-type(2) .three > .greybox:first-of-type { margin: 0; }
37
+ .box:nth-of-type(2) .three > .greybox .button-primary { display: block; height: 24px; line-height: 24px; background: #e37755; margin: 10px auto; padding: 0 20px; }
38
+ .box:nth-of-type(2) .three > .greybox .button-primary:hover { background: #f28462 !important;; }
39
+ .box:nth-of-type(2) > .greybox:last-of-type p { margin: 0 0 10px; }
40
+ .box:nth-of-type(2) > .greybox:last-of-type form { text-align: center; }
41
+ .box:nth-of-type(2) > .greybox:last-of-type textarea { display: block; width: 100%; height: 100px; }
42
+ .box:nth-of-type(2) > .greybox:last-of-type .button-primary { margin: 10px 0 0; padding: 0 20px; }
43
+
44
+ /* BOX 3 */
45
+ .box:nth-of-type(3) form > div { float: left; width: 48%; }
46
+ .box:nth-of-type(3) form > div:first-of-type { margin: 0 4% 0 0; }
47
+ .box:nth-of-type(3) form > div > input { width: 100%; }
48
+ .box:nth-of-type(3) form input { margin: 0; }
49
+ .box:nth-of-type(3) > .greybox > p { float: left; margin: 1em 0 1em 10px; }
50
+ .box:nth-of-type(3) > .greybox > a { float: left; }
51
+ .box:nth-of-type(3) > .greybox:last-of-type p { text-align: left; }
52
+ .box:nth-of-type(3) > .greybox:last-of-type form { margin: 20px 0 0; text-align: center; }
53
+ .box:nth-of-type(3) > .greybox:last-of-type .button-primary { margin: 10px 0 0; padding: 0 20px; }
54
+ .toggleon, .toggleoff { overflow: hidden; display: block; margin: 10px auto; width: 72px; height: 24px; background: url(onoff.jpg) 0 0 no-repeat; }
55
+ .toggleoff { background: url(onoff.jpg) -72px 0 no-repeat; }
56
+
57
+ #sg-cachepress-blacklist-textarea { resize: vertical; }
58
+
59
+ @media screen and (max-width: 782px), screen and (max-device-width: 782px) {
60
+ .wp-core-ui .button { padding: 0; font-size: 13px; }
61
+ .box:nth-of-type(2) .three > .greybox { width: 100%; margin: 10px 0 0; }
62
+ }
63
+
64
+ @media screen and (max-width: 360px), screen and (max-device-width: 360px) {
65
+ .sgwrap { margin: 10px 10px 10px 0; }
66
+ .sgwrap h2 { font-size: 20px; }
67
+ .box { margin: 10px 0 0; padding: 10px; }
68
+ .box:nth-of-type(2) .greybox:first-of-type > div { float: none; width: 100%; }
69
+ .box:nth-of-type(2) .greybox > div:nth-of-type(1) { margin: 0 0 20px; }
70
+ }
71
+
72
+ #adminmenu .wp-menu-image img {
73
+ padding-left: 9px !important;
74
+ }
75
+
76
+ input#testurl {
77
+ width: 50%;
78
+ height: 38px;
79
+ margin-right: 20px;
80
+ border: 1px solid #dbdbdb;
81
+ }
css/logo-white.svg ADDED
@@ -0,0 +1 @@
 
1
+ <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="Layer_1" x="0px" y="0px" width="13px" height="18px" viewBox="0 0 42.6 58.1" enable-background="new 0 0 42.6 58.1" xml:space="preserve"><path fill-rule="evenodd" clip-rule="evenodd" fill="#fff" d="M13.2 45.3C6.4 43.1 1.5 36.5 0.4 29.6 -2.9 10.4 17.4-6.9 37.8 2.7 38 7 36 13.2 30.5 15 57.8 32.2 34.5 67.3 6 55.8c-5.2-2.7-2.4-7.5 3.1-4.7 6.2 2.1 14.3 2.1 19.4-0.7 3.3-1.8 6.2-4.2 8.3-7.4 0.6-0.9 1.4-2.2 2-3.6 0.4-1 1.8-5.2 0.7-5.7 -0.3-0.1-0.4 0.2-0.5 0.5 -0.7 2.8-2 5.2-3.9 7.4 -2.2 2.5-4.9 4.5-8.4 5.7 -4.1 1.5-8.8 1.7-15.3 0.3C11.9 47.2 12.7 45.9 13.2 45.3L13.2 45.3zM32 4.5c0 0 0.1 0.8 0.2 1.9 0.1 3.2-0.8 5.2-3 7.5 -0.5 0.5-1 0.9-1.6 1.4 7.7 4.8 11.7 15.2 7.2 22.5 -6 9.8-17.9 7.6-24.5 0.9 -6.8-7.1-5.9-16.2-1-22.9C14.4 8.7 23.7 4.2 32 4.5L32 4.5zM8.8 26c1.5-14.6 18.3-17.5 24.5 2C38.4 48 6.5 43.7 8.8 26L8.8 26zM22.5 35.6c13.3 0.5 6.9-13.1-1.8-16.1C12.1 16.6 7.3 35.6 22.5 35.6L22.5 35.6z"/></svg>
css/onoff.jpg ADDED
Binary file
js/admin.js ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery( function ($) {
2
+ 'use strict';
3
+ // Bind behaviour to event
4
+ jQuery('#sg-cachepress-purge').on('click.sg-cachepress', sg_cachepress_purge);
5
+ jQuery('#sg-cachepress-dynamic-cache-toggle').on('click.sg-cachepress', function(event){event.preventDefault();sg_cachepress_toggle_option('dynamic-cache');});
6
+ jQuery('#sg-cachepress-memcached-toggle').on('click.sg-cachepress', function(event){event.preventDefault();sg_cachepress_toggle_option('memcached');});
7
+ jQuery('#sg-cachepress-autoflush-cache-toggle').on('click.sg-cachepress', function(event){event.preventDefault();sg_cachepress_toggle_option('autoflush-cache');});
8
+ jQuery('#sg-cachepress-blacklist').on('click.sg-cachepress', sg_cachepress_save_blacklist);
9
+ });
10
+ var sg_cachepress_toggle_in_progress = false;
11
+ /**
12
+ * Update a setting parameter
13
+ *
14
+ * @since 1.1.0
15
+ *
16
+ * @function
17
+ *
18
+ * @param {jQuery.event} event
19
+ */
20
+ function sg_cachepress_toggle_option(optionName) {
21
+ if (sg_cachepress_toggle_in_progress)
22
+ return;
23
+
24
+ sg_cachepress_toggle_in_progress = true;
25
+ var $ajaxArgs;
26
+ $ajaxArgs = {
27
+ action: 'sg-cachepress-parameter-update',
28
+ parameterName: optionName,
29
+ objects: 'all'
30
+ };
31
+ jQuery.post(ajaxurl, $ajaxArgs).done(function(data){
32
+ sg_cachepress_toggle_in_progress = false;
33
+ jQuery('#sg-cachepress-'+optionName+'-text').show();
34
+ jQuery('#sg-cachepress-'+optionName+'-error').hide();
35
+ if (data == 1)
36
+ {
37
+ jQuery('#sg-cachepress-'+optionName+'-toggle').removeClass('toggleoff').addClass('toggleon', 1000);
38
+ return;
39
+ }
40
+ if (data == 0)
41
+ {
42
+ jQuery('#sg-cachepress-'+optionName+'-toggle').removeClass('toggleon').addClass('toggleoff', 1000);
43
+ return;
44
+ }
45
+
46
+ jQuery('#sg-cachepress-'+optionName+'-text').hide();
47
+ jQuery('#sg-cachepress-'+optionName+'-error').html(data).show();
48
+ });
49
+ }
50
+
51
+ /**
52
+ * Update the blacklist
53
+ *
54
+ * @since 1.1.0
55
+ *
56
+ * @function
57
+ *
58
+ * @param {jQuery.event} event
59
+ */
60
+ function sg_cachepress_save_blacklist(event) {
61
+ event.preventDefault();
62
+ var $ajaxArgs;
63
+ $ajaxArgs = {
64
+ action: 'sg-cachepress-blacklist-update',
65
+ blacklist: jQuery('#sg-cachepress-blacklist-textarea').val(),
66
+ objects: 'all'
67
+ };
68
+ jQuery(event.target).attr('disabled','disabled').attr('value', sgCachePressL10n.updating);
69
+ jQuery('#sg-cachepress-spinner-blacklist').show();
70
+ jQuery.post(ajaxurl, $ajaxArgs).done(function(){
71
+ jQuery('#sg-cachepress-spinner-blacklist').hide();
72
+ jQuery('#sg-cachepress-blacklist').removeAttr('disabled').attr('value', sgCachePressL10n.updated);
73
+ });
74
+ }
75
+ /**
76
+ * Start the purge procedure from a button click.
77
+ *
78
+ * @since 1.1.0
79
+ *
80
+ * @function
81
+ *
82
+ * @param {jQuery.event} event
83
+ */
84
+ function sg_cachepress_purge(event) {
85
+ jQuery('#sg-cachepress-purgesuccess').hide();
86
+ jQuery('#sg-cachepress-purgefailure').hide();
87
+ event.preventDefault();
88
+ 'use strict';
89
+ var $ajaxArgs;
90
+ $ajaxArgs = {
91
+ action: 'sg-cachepress-purge',
92
+ objects: 'all'
93
+ };
94
+ jQuery(event.target).attr('disabled','disabled').attr('value', sgCachePressL10n.purging);
95
+ jQuery('#sg-cachepress-spinner').css({'visibility': 'visible'});
96
+ jQuery.post(ajaxurl, $ajaxArgs).done(sg_cachepress_purged);
97
+ }
98
+
99
+ /**
100
+ * Tidy-up the UI after purge has successfully completed.
101
+ *
102
+ * @since 1.1.0
103
+ *
104
+ * @function
105
+ *
106
+ * @param {string} data
107
+ */
108
+ function sg_cachepress_purged(data) {
109
+ 'use strict';
110
+ jQuery('#sg-cachepress-purge').removeAttr('disabled').attr('value', sgCachePressL10n.purge);
111
+ jQuery('#sg-cachepress-spinner').css({'visibility':'hidden'});
112
+ if ('1' == data){
113
+ jQuery('#sg-cachepress-purgesuccess').fadeIn();
114
+ } else {
115
+ jQuery('#sg-cachepress-purgefailure').fadeIn();
116
+ }
117
+ }
118
+
119
+
120
+ jQuery("#cachetest").submit(function( event ) { sg_cachepress_test_submit(); event.preventDefault(); });
121
+
122
+ var cachepress_test_counter = 0;
123
+ function sg_cachepress_test_submit( )
124
+ {
125
+ jQuery('.status_test').slideUp();
126
+ jQuery('#sg-cachepress-test').prop('disabled',true).attr('value','Testing...');
127
+ jQuery('#testurl').prop('disabled',true);
128
+ var postUrl = jQuery("#testurl").val();
129
+
130
+ var ajaxUrl = sgCachePressL10n.ajax_url;
131
+ jQuery.post(ajaxUrl,{action:'sg-cachepress-cache-test',url:postUrl},function(result){ sg_cachepress_test_result(result); });
132
+ }
133
+
134
+ function sg_cachepress_test_result(result)
135
+ {
136
+ cachepress_test_counter = cachepress_test_counter + 1;
137
+
138
+ if(result == 1)
139
+ sg_cachepress_test_result_display_output( 'CACHED', 'cached' );
140
+
141
+ if(result == 0 && cachepress_test_counter == 1)
142
+ setTimeout("sg_cachepress_test_submit();",2000);
143
+ else if(result == 0)
144
+ sg_cachepress_test_result_display_output( 'NOT CACHED', 'notcached' );
145
+ else if(result == 2)
146
+ sg_cachepress_test_result_display_output( 'CANT GET HEADERS', 'notcached' );
147
+
148
+ if(result == 1 || cachepress_test_counter == 2)
149
+ cachepress_test_counter = 0;
150
+ }
151
+
152
+ function sg_cachepress_test_result_display_output( text, classText )
153
+ {
154
+ jQuery('#sg-cachepress-test').prop('disabled',false).attr('value','Test URL');
155
+ jQuery('#testurl').prop('disabled',false);
156
+
157
+ jQuery('#status_test_value').html('<span class="'+classText+'">'+text+'</span>');
158
+ jQuery('.status_test').slideDown();
159
+ }
js/admin_global.js ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function(){
2
+ if(jQuery('#dismiss-sg-cahepress-notification').length)
3
+ jQuery('#dismiss-sg-cahepress-notification').click(function(){ sg_cachepress_notice_hide(); });
4
+ });
5
+
6
+ function sg_cachepress_notice_hide()
7
+ {
8
+ jQuery('.sg-cachepress-notification').slideUp();
9
+ jQuery.post(ajaxurl,{action:'sg-cachepress-cache-test-message-hide'});
10
+ }
memcache.tpl ADDED
@@ -0,0 +1,407 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ Plugin Name: Memcached
5
+ Description: Memcached backend for the WP Object Cache.
6
+ Version: 2.0.2
7
+ Plugin URI: http://wordpress.org/extend/plugins/memcached/
8
+ Author: Ryan Boren, Denis de Bernardy, Matt Martz
9
+
10
+ Install this file to wp-content/object-cache.php
11
+ */
12
+
13
+ // Users with setups where multiple installs share a common wp-config.php or $table_prefix
14
+ // can use this to guarantee uniqueness for the keys generated by this object cache
15
+ if ( !defined( 'WP_CACHE_KEY_SALT' ) )
16
+ define( 'WP_CACHE_KEY_SALT', substr(md5(dirname(__FILE__)),7));
17
+
18
+ function wp_cache_add($key, $data, $group = '', $expire = 0) {
19
+ global $wp_object_cache;
20
+
21
+ return $wp_object_cache->add($key, $data, $group, $expire);
22
+ }
23
+
24
+ function wp_cache_incr($key, $n = 1, $group = '') {
25
+ global $wp_object_cache;
26
+
27
+ return $wp_object_cache->incr($key, $n, $group);
28
+ }
29
+
30
+ function wp_cache_decr($key, $n = 1, $group = '') {
31
+ global $wp_object_cache;
32
+
33
+ return $wp_object_cache->decr($key, $n, $group);
34
+ }
35
+
36
+ function wp_cache_close() {
37
+ global $wp_object_cache;
38
+
39
+ return $wp_object_cache->close();
40
+ }
41
+
42
+ function wp_cache_delete($key, $group = '') {
43
+ global $wp_object_cache;
44
+
45
+ return $wp_object_cache->delete($key, $group);
46
+ }
47
+
48
+ function wp_cache_flush() {
49
+ global $wp_object_cache;
50
+
51
+ return $wp_object_cache->flush();
52
+ }
53
+
54
+ function wp_cache_get($key, $group = '', $force = false) {
55
+ global $wp_object_cache;
56
+
57
+ return $wp_object_cache->get($key, $group, $force);
58
+ }
59
+
60
+ function wp_cache_init() {
61
+ global $wp_object_cache;
62
+
63
+ $wp_object_cache = new WP_Object_Cache();
64
+ }
65
+
66
+ function wp_cache_replace($key, $data, $group = '', $expire = 0) {
67
+ global $wp_object_cache;
68
+
69
+ return $wp_object_cache->replace($key, $data, $group, $expire);
70
+ }
71
+
72
+ function wp_cache_set($key, $data, $group = '', $expire = 0) {
73
+ global $wp_object_cache;
74
+
75
+ if ( defined('WP_INSTALLING') == false )
76
+ return $wp_object_cache->set($key, $data, $group, $expire);
77
+ else
78
+ return $wp_object_cache->delete($key, $group);
79
+ }
80
+
81
+ function wp_cache_add_global_groups( $groups ) {
82
+ global $wp_object_cache;
83
+
84
+ $wp_object_cache->add_global_groups($groups);
85
+ }
86
+
87
+ function wp_cache_add_non_persistent_groups( $groups ) {
88
+ global $wp_object_cache;
89
+
90
+ $wp_object_cache->add_non_persistent_groups($groups);
91
+ }
92
+
93
+ class WP_Object_Cache {
94
+ var $global_groups = array();
95
+
96
+ var $no_mc_groups = array();
97
+
98
+ var $cache = array();
99
+ var $mc = array();
100
+ var $stats = array();
101
+ var $group_ops = array();
102
+
103
+ var $cache_enabled = true;
104
+ var $default_expiration = 0;
105
+
106
+ function add($id, $data, $group = 'default', $expire = 0) {
107
+ $key = $this->key($id, $group);
108
+
109
+ if ( is_object( $data ) )
110
+ $data = clone $data;
111
+
112
+ if ( in_array($group, $this->no_mc_groups) ) {
113
+ $this->cache[$key] = $data;
114
+ return true;
115
+ } elseif ( isset($this->cache[$key]) && $this->cache[$key] !== false ) {
116
+ return false;
117
+ }
118
+
119
+ $mc =& $this->get_mc($group);
120
+ $expire = ($expire == 0) ? $this->default_expiration : $expire;
121
+ $result = $mc->add($key, $data, false, $expire);
122
+
123
+ if ( false !== $result ) {
124
+ @ ++$this->stats['add'];
125
+ $this->group_ops[$group][] = "add $id";
126
+ $this->cache[$key] = $data;
127
+ }
128
+
129
+ return $result;
130
+ }
131
+
132
+ function add_global_groups($groups) {
133
+ if ( ! is_array($groups) )
134
+ $groups = (array) $groups;
135
+
136
+ $this->global_groups = array_merge($this->global_groups, $groups);
137
+ $this->global_groups = array_unique($this->global_groups);
138
+ }
139
+
140
+ function add_non_persistent_groups($groups) {
141
+ if ( ! is_array($groups) )
142
+ $groups = (array) $groups;
143
+
144
+ $this->no_mc_groups = array_merge($this->no_mc_groups, $groups);
145
+ $this->no_mc_groups = array_unique($this->no_mc_groups);
146
+ }
147
+
148
+ function incr($id, $n = 1, $group = 'default' ) {
149
+ $key = $this->key($id, $group);
150
+ $mc =& $this->get_mc($group);
151
+ $this->cache[ $key ] = $mc->increment( $key, $n );
152
+ return $this->cache[ $key ];
153
+ }
154
+
155
+ function decr($id, $n = 1, $group = 'default' ) {
156
+ $key = $this->key($id, $group);
157
+ $mc =& $this->get_mc($group);
158
+ $this->cache[ $key ] = $mc->decrement( $key, $n );
159
+ return $this->cache[ $key ];
160
+ }
161
+
162
+ function close() {
163
+
164
+ foreach ( $this->mc as $bucket => $mc )
165
+ $mc->close();
166
+ }
167
+
168
+ function delete($id, $group = 'default') {
169
+ $key = $this->key($id, $group);
170
+
171
+ if ( in_array($group, $this->no_mc_groups) ) {
172
+ unset($this->cache[$key]);
173
+ return true;
174
+ }
175
+
176
+ $mc =& $this->get_mc($group);
177
+
178
+ $result = $mc->delete($key);
179
+
180
+ @ ++$this->stats['delete'];
181
+ $this->group_ops[$group][] = "delete $id";
182
+
183
+ if ( false !== $result )
184
+ unset($this->cache[$key]);
185
+
186
+ return $result;
187
+ }
188
+
189
+ function flush() {
190
+ // Don't flush if multi-blog.
191
+ if ( function_exists('is_site_admin') || defined('CUSTOM_USER_TABLE') && defined('CUSTOM_USER_META_TABLE') )
192
+ return true;
193
+
194
+ $ret = true;
195
+ foreach ( array_keys($this->mc) as $group )
196
+ $ret &= $this->mc[$group]->flush();
197
+ return $ret;
198
+ }
199
+
200
+ function get($id, $group = 'default', $force = false) {
201
+ $key = $this->key($id, $group);
202
+ $mc =& $this->get_mc($group);
203
+
204
+ if ( isset($this->cache[$key]) && ( !$force || in_array($group, $this->no_mc_groups) ) ) {
205
+ if ( is_object( $this->cache[$key] ) )
206
+ $value = clone $this->cache[$key];
207
+ else
208
+ $value = $this->cache[$key];
209
+ } else if ( in_array($group, $this->no_mc_groups) ) {
210
+ $this->cache[$key] = $value = false;
211
+ } else {
212
+ $value = $mc->get($key);
213
+ if ( NULL === $value )
214
+ $value = false;
215
+ $this->cache[$key] = $value;
216
+ }
217
+
218
+ @ ++$this->stats['get'];
219
+ $this->group_ops[$group][] = "get $id";
220
+
221
+ if ( 'checkthedatabaseplease' === $value ) {
222
+ unset( $this->cache[$key] );
223
+ $value = false;
224
+ }
225
+
226
+ return $value;
227
+ }
228
+
229
+ function get_multi( $groups ) {
230
+ /*
231
+ format: $get['group-name'] = array( 'key1', 'key2' );
232
+ */
233
+ $return = array();
234
+ foreach ( $groups as $group => $ids ) {
235
+ $mc =& $this->get_mc($group);
236
+ foreach ( $ids as $id ) {
237
+ $key = $this->key($id, $group);
238
+ if ( isset($this->cache[$key]) ) {
239
+ if ( is_object( $this->cache[$key] ) )
240
+ $return[$key] = clone $this->cache[$key];
241
+ else
242
+ $return[$key] = $this->cache[$key];
243
+ continue;
244
+ } else if ( in_array($group, $this->no_mc_groups) ) {
245
+ $return[$key] = false;
246
+ continue;
247
+ } else {
248
+ $return[$key] = $mc->get($key);
249
+ }
250
+ }
251
+ if ( $to_get ) {
252
+ $vals = $mc->get_multi( $to_get );
253
+ $return = array_merge( $return, $vals );
254
+ }
255
+ }
256
+ @ ++$this->stats['get_multi'];
257
+ $this->group_ops[$group][] = "get_multi $id";
258
+ $this->cache = array_merge( $this->cache, $return );
259
+ return $return;
260
+ }
261
+
262
+ function key($key, $group) {
263
+ if ( empty($group) )
264
+ $group = 'default';
265
+
266
+ if ( false !== array_search($group, $this->global_groups) )
267
+ $prefix = $this->global_prefix;
268
+ else
269
+ $prefix = $this->blog_prefix;
270
+
271
+ return preg_replace('/\s+/', '', WP_CACHE_KEY_SALT . "$prefix$group:$key");
272
+ }
273
+
274
+ function replace($id, $data, $group = 'default', $expire = 0) {
275
+ $key = $this->key($id, $group);
276
+ $expire = ($expire == 0) ? $this->default_expiration : $expire;
277
+ $mc =& $this->get_mc($group);
278
+
279
+ if ( is_object( $data ) )
280
+ $data = clone $data;
281
+
282
+ $result = $mc->replace($key, $data, false, $expire);
283
+ if ( false !== $result )
284
+ $this->cache[$key] = $data;
285
+ return $result;
286
+ }
287
+
288
+ function set($id, $data, $group = 'default', $expire = 0) {
289
+ $key = $this->key($id, $group);
290
+ if ( isset($this->cache[$key]) && ('checkthedatabaseplease' === $this->cache[$key]) )
291
+ return false;
292
+
293
+ if ( is_object($data) )
294
+ $data = clone $data;
295
+
296
+ $this->cache[$key] = $data;
297
+
298
+ if ( in_array($group, $this->no_mc_groups) )
299
+ return true;
300
+
301
+ $expire = ($expire == 0) ? $this->default_expiration : $expire;
302
+ $mc =& $this->get_mc($group);
303
+ $result = $mc->set($key, $data, false, $expire);
304
+
305
+ return $result;
306
+ }
307
+
308
+ function colorize_debug_line($line) {
309
+ $colors = array(
310
+ 'get' => 'green',
311
+ 'set' => 'purple',
312
+ 'add' => 'blue',
313
+ 'delete' => 'red');
314
+
315
+ $cmd = substr($line, 0, strpos($line, ' '));
316
+
317
+ $cmd2 = "<span style='color:{$colors[$cmd]}'>$cmd</span>";
318
+
319
+ return $cmd2 . substr($line, strlen($cmd)) . "\n";
320
+ }
321
+
322
+ function stats() {
323
+ echo "<p>\n";
324
+ foreach ( $this->stats as $stat => $n ) {
325
+ echo "<strong>$stat</strong> $n";
326
+ echo "<br/>\n";
327
+ }
328
+ echo "</p>\n";
329
+ echo "<h3>Memcached:</h3>";
330
+ foreach ( $this->group_ops as $group => $ops ) {
331
+ if ( !isset($_GET['debug_queries']) && 500 < count($ops) ) {
332
+ $ops = array_slice( $ops, 0, 500 );
333
+ echo "<big>Too many to show! <a href='" . add_query_arg( 'debug_queries', 'true' ) . "'>Show them anyway</a>.</big>\n";
334
+ }
335
+ echo "<h4>$group commands</h4>";
336
+ echo "<pre>\n";
337
+ $lines = array();
338
+ foreach ( $ops as $op ) {
339
+ $lines[] = $this->colorize_debug_line($op);
340
+ }
341
+ print_r($lines);
342
+ echo "</pre>\n";
343
+ }
344
+
345
+ if ( $this->debug )
346
+ var_dump($this->memcache_debug);
347
+ }
348
+
349
+ function &get_mc($group) {
350
+ if ( isset($this->mc[$group]) )
351
+ return $this->mc[$group];
352
+ return $this->mc['default'];
353
+ }
354
+
355
+ function failure_callback($host, $port) {
356
+ $dropInLocation = dirname(__FILE__). '/object-cache.php';
357
+ if (is_readable($dropInLocation))
358
+ {
359
+ unlink($dropInLocation);
360
+ return;
361
+ }
362
+ }
363
+
364
+ function WP_Object_Cache() {
365
+
366
+ $memcached_servers = array(
367
+ 'default' => array(
368
+ '@changedefaults@'
369
+ )
370
+ );
371
+
372
+ if ( isset($memcached_servers) )
373
+ $buckets = $memcached_servers;
374
+ else
375
+ $buckets = array('127.0.0.1');
376
+
377
+ reset($buckets);
378
+ if ( is_int( key($buckets) ) )
379
+ $buckets = array('default' => $buckets);
380
+
381
+ foreach ( $buckets as $bucket => $servers) {
382
+ $this->mc[$bucket] = new Memcache();
383
+ foreach ( $servers as $server ) {
384
+ list ( $node, $port ) = explode(':', $server);
385
+ if ( !$port )
386
+ $port = ini_get('memcache.default_port');
387
+ $port = intval($port);
388
+ if ( !$port )
389
+ $port = 11211;
390
+ $this->mc[$bucket]->addServer($node, $port, true, 1, 1, 15, true, array($this, 'failure_callback'));
391
+ $this->mc[$bucket]->setCompressThreshold(20000, 0.2);
392
+ }
393
+ }
394
+
395
+ global $blog_id, $table_prefix;
396
+ $this->global_prefix = '';
397
+ $this->blog_prefix = '';
398
+ if ( function_exists( 'is_multisite' ) ) {
399
+ $this->global_prefix = ( is_multisite() || defined('CUSTOM_USER_TABLE') && defined('CUSTOM_USER_META_TABLE') ) ? '' : $table_prefix;
400
+ $this->blog_prefix = ( is_multisite() ? $blog_id : $table_prefix ) . ':';
401
+ }
402
+
403
+ $this->cache_hits =& $this->stats['get'];
404
+ $this->cache_misses =& $this->stats['add'];
405
+ }
406
+ }
407
+ ?>
readme.txt ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === SG CachePress ===
2
+ Contributors: Hristo Sg
3
+ Tags: nginx, caching, speed, memcache, memcached, performance, siteground, nginx, supercacher
4
+ Requires at least: 3.0.1
5
+ Tested up to: 4.2
6
+ Stable tag: 1.0
7
+ License: GPLv2 or later
8
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
+
10
+ The SG CachePress is a plugin that allows you to use the SiteGround dynamic cache and Memcached to optimize the performance of your WordPress.
11
+
12
+ == Description ==
13
+
14
+ The main functionality of SG CachePress is to purge your dynamic cache whenever your content updates. For example, when you create a new post, someone comments your articles, etc. In addition to that, if you have a working Memcached service on your server, the plugin will allow you to easily configure and enable WordPress to use it.
15
+
16
+ = Requirements =
17
+
18
+ In order to work correctly, this plugin requires that your server meets the following criteria:
19
+
20
+ * Your SiteGround SuperCacher enabled
21
+ * If you're not hosted with SiteGround this plugin may not work because it relies on a specific server configuration
22
+
23
+ == Installation ==
24
+
25
+ = Automatic Installation =
26
+
27
+ 1. Go to Plugins -> Add New
28
+ 1. Search for "SG CachePress"
29
+ 1. Click on the Install button under the SG CachePress plugin
30
+ 1. Once the plugin is installed, click on the Activate plugin link
31
+
32
+ = Manual Installation =
33
+
34
+ 1. Login to the WordPress admin panel and go to Plugins -> Add New
35
+ 1. Select the 'Upload' menu
36
+ 1. Click the 'Choose File' button and point your browser to the SGCachePress.zip file you've downloaded
37
+ 1. Click the 'Install Now' button
38
+ 1. Go to Plugins -> Installed Plugins and click the 'Activate' link under the WordPress SG CachePress listing
39
+
40
+
41
+ == Configuration ==
42
+
43
+ = Dynamic Cache Settings =
44
+
45
+ * Dynamic Cache ON/OFF - enable or disable the SiteGround Dynamic caching system
46
+ * AutoFlush Cache ON/OFF - automatically flush the Dynamic cache when you edit your content
47
+ * Purge Cache - Manually purge all cached data from the dynamic cache
48
+
49
+ = Exclude URLs From Dynamic Caching =
50
+
51
+ This field allows you to exclude URLs from the cache. This means that if you need certain parts of your site to be completely dynamic, you need to add them into this list. Type in the last part of the URL that you want to be excluded. For example, if you type in 'url', then '/path/to/url/' will be excluded but '/path/to/' and '/path/to/url/else/' won't.
52
+
53
+ = Memcached Settings =
54
+ * Enable Memcached - Store in the server's memory (using Memcached) frequently executed queries to the database for a faster access on a later use.
55
+
56
+ == Changelog ==
57
+
58
+ = Version 2.2.10 =
59
+ * Revamped notices work
60
+ * Bug fixes
61
+
62
+ = Version 2.2.9 =
63
+ * Bug fixes
64
+
65
+ = Version 2.2.8 =
66
+ * Bug fixing and improved notification behaviour
67
+ * Fixed issues with MS installations
68
+
69
+ = Version 2.2.7 =
70
+ * Added testing box and notification if Dynamic Cache is not enabled in cPanel
71
+
72
+ = Version 2.2.6 =
73
+ * Fixed bug with Memcached causing issues after WP Database update
74
+
75
+ = Version 2.2.5 =
76
+ * Minor system improvements
77
+
78
+ = Version 2.2.4 =
79
+ * Minor system improvements
80
+
81
+ = Version 2.2.3 =
82
+ * Admin bar link visible only for admin users
83
+
84
+ = Version 2.2.2 =
85
+ * Minor bug fixes
86
+
87
+ = Version 2.2.1 =
88
+ * Added Purge SG Cache button
89
+ * Redesigned mobile-friendly interface
90
+
91
+ = Version 2.2.0 =
92
+ * Added NGINX support
93
+
94
+ = Version 2.1.7 =
95
+ * Fixed plugin activation bug
96
+
97
+ = Version 2.1.6 =
98
+ * The purge button will now clear the Static cache even if Dynamic cache is not enabled
99
+ * Better and more clear button labeling
100
+
101
+ = Version 2.1.5 =
102
+ * Better plugin activation and added to the wordpress.org repo
103
+
104
+ = Version 2.1.2 =
105
+ * Fixed bug that prevents you from enabling Memcached if using a wildcard SSL Certificate
106
+
107
+ = Version 2.1.1 =
108
+ * Cache will flush when scheduled posts become live
109
+
110
+ = Version 2.1.0 =
111
+ * Cache will be purged if WordPress autoupdates
112
+
113
+ = Version 2.0.3 =
114
+ * Minor bug fixes
115
+
116
+ = Version 2.0.2 =
117
+ * 3.8 support added
118
+
119
+ = Version 2.0.1 =
120
+ * Interface improvements
121
+ * Minor bug fixes
122
+
123
+ = Version 2.0 =
124
+ * New interface
125
+ * Minor bug fixes
126
+ * Settings and Purge pages combined into one
127
+
128
+ = Version 1.2.3 =
129
+ * Minor bug fixes
130
+ * SiteGround Memcached support added
131
+ * URL Exclude from caching list added
132
+
133
+ = 1.0 =
134
+ * Plugin created.
sg-cachepress.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SG CachePress
4
+ *
5
+ * @package SG_CachePress
6
+ * @author SiteGround
7
+ * @link http://www.siteground.com/
8
+ *
9
+ * @wordpress-plugin
10
+ * Plugin Name: SG CachePress
11
+ * Description: Through the settings of this plugin you can manage how your Wordpress interracts with NGINX and Memcached.
12
+ * Version: 2.2.10
13
+ * Author: SiteGround
14
+ * Text Domain: sg-cachepress
15
+ * Domain Path: /languages
16
+ */
17
+
18
+ // If this file is called directly, abort.
19
+ if ( ! defined( 'WPINC' ) ) {
20
+ die;
21
+ }
22
+
23
+ // @todo Consider an autoloader?
24
+ require plugin_dir_path( __FILE__ ) . 'class-sg-cachepress.php';
25
+ require plugin_dir_path( __FILE__ ) . 'class-sg-cachepress-options.php';
26
+ require plugin_dir_path( __FILE__ ) . 'class-sg-cachepress-environment.php';
27
+ require plugin_dir_path( __FILE__ ) . 'class-sg-cachepress-supercacher.php';
28
+ require plugin_dir_path( __FILE__ ) . 'class-sg-cachepress-memcache.php';
29
+ require plugin_dir_path( __FILE__ ) . 'class-sg-cachepress-admin.php';
30
+
31
+
32
+ // Register hooks that are fired when the plugin is activated, deactivated, and uninstalled, respectively.
33
+ register_activation_hook( __FILE__, array( 'SG_CachePress', 'activate' ) );
34
+ register_deactivation_hook( __FILE__, array( 'SG_CachePress', 'deactivate' ) );
35
+
36
+ add_action( 'plugins_loaded','sg_cachepress_start' );
37
+ add_action( 'admin_init', array('SG_CachePress','admin_init_cachepress') );
38
+
39
+ /**
40
+ * Initialise the classes in this plugin.
41
+ *
42
+ * @since 1.1.0
43
+ *
44
+ * @todo Consider moving this to a dependency injection container, so we can avoid globals?
45
+ */
46
+ function sg_cachepress_start() {
47
+
48
+ global $sg_cachepress, $sg_cachepress_options, $sg_cachepress_environment, $sg_cachepress_memcache,
49
+ $sg_cachepress_admin, $sg_cachepress_supercacher;
50
+
51
+ $sg_cachepress_options = new SG_CachePress_Options;
52
+ $sg_cachepress = new SG_CachePress( $sg_cachepress_options );
53
+ $sg_cachepress_environment = new SG_CachePress_Environment( $sg_cachepress_options );
54
+ $sg_cachepress_admin = new SG_CachePress_Admin( $sg_cachepress_options );
55
+ $sg_cachepress_memcache = new SG_CachePress_Memcache( $sg_cachepress_options, $sg_cachepress_environment );
56
+ $sg_cachepress_supercacher = new SG_CachePress_Supercacher( $sg_cachepress_options, $sg_cachepress_environment );
57
+
58
+ $sg_cachepress->run();
59
+ $sg_cachepress_admin->run();
60
+
61
+ if ( $sg_cachepress_environment->cache_is_enabled() ){
62
+ if ( $sg_cachepress_environment->autoflush_enabled() ){
63
+ $sg_cachepress_supercacher->run();
64
+ }
65
+ }
66
+
67
+ if ( $sg_cachepress_environment->memcached_is_enabled() ){
68
+ $sg_cachepress_memcache->run();
69
+ }
70
+ }
views/sg-cache.php ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="sgwrap">
2
+ <div class="box">
3
+ <h2>SuperCacher for WordPress by SiteGround</h2>
4
+ <p>The SuperCacher is a system that allows you to use the SitGround dynamic cache and Memcached to optimize the performance of your WordPress. In order to take advantage of the system you should have the SuperCacher enabled at your web host plus the required cache options turned on below. For more information on the different caching options refer to the <a href="http://www.siteground.com/tutorials/supercacher/" target="_blank">SuperCacher Tutorial</a>! </p>
5
+ </div>
6
+
7
+ <div class="box clear">
8
+ <h2>Dynamic Cache Settings</h2>
9
+
10
+ <div class="three clear">
11
+ <div class="greybox">
12
+ <h3>Dynamic Cache</h3>
13
+ <a href="" id="sg-cachepress-dynamic-cache-toggle" class="<?php if ( $this->options_handler->get_option('enable_cache') ==1 ) echo 'toggleon'; else echo 'toggleoff'; ?>"></a>
14
+ <p id="sg-cachepress-dynamic-cache-text">Enable the Dynamic caching system</p>
15
+ <p id="sg-cachepress-dynamic-cache-error" class="error"></p>
16
+ </div>
17
+
18
+ <div class="greybox">
19
+ <h3>AutoFlush Cache</h3>
20
+ <a href="" id="sg-cachepress-autoflush-cache-toggle" class="<?php if ( $this->options_handler->get_option('autoflush_cache') ==1 ) echo 'toggleon'; else echo 'toggleoff'; ?>"></a>
21
+ <p id="nginxcacheoptimizer-autoflush-cache-text">Automatically flush the Dynamic cache when you edit your content.</p>
22
+ <p id="nginxcacheoptimizer-autoflush-cache-error" class="error"></p>
23
+ </div>
24
+
25
+ <div class="greybox">
26
+ <h3>Purge Cache</h3>
27
+ <form class="purgebtn" method="post" action="<?php menu_page_url( 'sg-cachepress-purge' ); ?>">
28
+ <?php submit_button( __( 'Purge the Cache', 'sg-cachepress' ), 'primary', 'sg-cachepress-purge', false );?>
29
+ </form>
30
+ <p>Purge all the data cached by the Dynamic cache.</p>
31
+ </div>
32
+
33
+ </div>
34
+ <div class="greybox">
35
+ <h3>Exclude URLs From Dynamic Caching</h3>
36
+ <p>Provide a list of your website's URLs you would like to exclude from the cache. For example if you'd like to exclude: <strong>http://domain.com/path/to/url</strong><br>
37
+ You can provide only a part of the URL. If you input the "path" string part of the URL, then each URL that consists of it will be excluded. Divide each URL by a new line.</p>
38
+
39
+ <form method="post" action="<?php menu_page_url( 'sg-cachepress-purge' ); ?>">
40
+ <textarea id="sg-cachepress-blacklist-textarea"><?php echo esc_textarea($this->options_handler->get_blacklist()); ?></textarea>
41
+ <?php submit_button( __( 'Update the Exclude List', 'sg-cachepress' ), 'primary', 'sg-cachepress-blacklist', false );?>
42
+ </form>
43
+ </div>
44
+ </div>
45
+ <div class="box">
46
+ <h2>Memcached Settings</h2>
47
+ <div class="greybox">
48
+
49
+ <a href="" id="sg-cachepress-memcached-toggle" class="<?php if ( $this->options_handler->get_option('enable_memcached') ==1 ) echo 'toggleon'; else echo 'toggleoff'; ?>"></a>
50
+
51
+ <p id="sg-cachepress-memcached-text">Enable Memcached</p>
52
+ <p class="error" id="sg-cachepress-memcached-error"></p>
53
+
54
+ <div class="clr"></div>
55
+ <p>Store in the server's memory frequently executed queries to the database for a faster access on a later use.</p>
56
+ <div class="clr"></div>
57
+ </div>
58
+ </div>
59
+
60
+ <div class="box clear">
61
+ <h2>Dynamic Cache Status</h2>
62
+ <div class="greybox">
63
+
64
+ <form class="purgebtn" method="post" action="<?php menu_page_url( 'sg-cachepress-test' ); ?>" id="cachetest">
65
+ <?php echo get_site_url()?>/&nbsp;<input id="testurl" type="" name="" value="" />
66
+ <?php submit_button( __( 'Test URL', 'sg-cachepress' ), 'primary', 'sg-cachepress-test', false );?>
67
+ </form>
68
+
69
+ <div class="status_test" style="display:none;">Status: <span id="status_test_value"></span></div>
70
+
71
+ <div class="clr"></div>
72
+ <p>Check if this URL is dynamic or cached. Leave empty for your index or <strong>/example/</strong> for another page.</p>
73
+ <div class="clr"></div>
74
+ </div>
75
+ </div>
76
+ </div>