PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backups, Restore, Migration & Clone / 4.9.4
WP STAGING – WordPress Backups, Restore, Migration & Clone v4.9.4
4.9.4 4.9.3 4.9.2 4.9.1 4.9.0 4.8.1 trunk 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.10.0 3.2.0 3.3.1 3.3.2 3.3.3 3.4.1 3.4.3 3.5.0 3.6.0 3.7.1 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.8.7 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4 4.0.0 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.7.2 4.7.3 4.8.0
wp-staging / Backend / Optimizer / wp-staging-optimizer.php
wp-staging / Backend / Optimizer Last commit date
Optimizer.php 2 months ago wp-staging-optimizer.php 3 days ago
wp-staging-optimizer.php
407 lines
1 <?php
2
3 /*
4 * Plugin Name: WP STAGING Optimizer
5 * Plugin URI: https://wp-staging.com
6 * Description: Prevents 3rd party plugins from being loaded during WP STAGING specific operations.
7 *
8 * This is a must-use standalone plugin -
9 * Do not use any of these methods in WP STAGING code base as this mu-plugin can be missing!
10 *
11 * Do not implement PHP type declarations into this file!
12 * This can lead to fatal errors due to mixed return results in the used wp core functions.
13 * See https://github.com/wp-staging/wp-staging-pro/issues/2830
14 *
15 * Author: WP STAGING
16 * Version: 1.6.2
17 * Author URI: https://wp-staging.com
18 * Text Domain: wp-staging
19 */
20
21 // Version number of this mu-plugin. Important for automatic updates
22 // Important: Update WPSTG_OPTIMIZER_MUVERSION in /bootstrap.php to the same version!
23
24 if (!defined('WPSTG_OPTIMIZER_VERSION')) {
25 define('WPSTG_OPTIMIZER_VERSION', '1.6.2');
26 }
27
28 if (!function_exists('wpstgGetPluginsDir')) {
29 /** @return string */
30 function wpstgGetPluginsDir(): string
31 {
32 $pluginsDir = '';
33 if (defined('WP_PLUGIN_DIR')) {
34 $pluginsDir = trailingslashit(WP_PLUGIN_DIR);
35 } elseif (defined('WP_CONTENT_DIR')) {
36 $pluginsDir = trailingslashit(WP_CONTENT_DIR) . 'plugins/';
37 }
38
39 return $pluginsDir;
40 }
41 }
42
43 if (!function_exists('wpstgIsEnabledOptimizer')) {
44 /**
45 * Check if optimizer is enabled
46 * @return bool
47 */
48 function wpstgIsEnabledOptimizer(): bool
49 {
50 $status = (object)get_option('wpstg_settings');
51
52 if ($status && isset($status->optimizer) && $status->optimizer == 1) {
53 return true;
54 }
55
56 return false;
57 }
58 }
59
60 if (!function_exists('wpstgIsGoDaddyManagedSite')) {
61 /**
62 * GoDaddy's must-use plugin calls WooCommerce's Action Scheduler, so those plugins must stay loaded.
63 * @return bool
64 */
65 function wpstgIsGoDaddyManagedSite(): bool
66 {
67 $muPluginDir = defined('WPMU_PLUGIN_DIR') ? WPMU_PLUGIN_DIR : WP_CONTENT_DIR . '/mu-plugins';
68 $isGoDaddy = is_dir($muPluginDir . '/vendor/godaddy/') || is_dir($muPluginDir . '/gd-system-plugin');
69
70 return $isGoDaddy;
71 }
72 }
73
74 if (!function_exists('wpstgIsExcludedPlugin')) {
75 /**
76 * Check if a plugin should be excluded from the optimizer and still running during wp staging requests
77 * @param string $plugin
78 * @return bool
79 */
80 function wpstgIsExcludedPlugin(string $plugin): bool
81 {
82 // GoDaddy's must-use plugin needs WooCommerce's Action Scheduler, so keep only those exact plugins
83 // active. Match the plugin file exactly so WooCommerce extensions are still disabled as usual.
84 if (wpstgIsGoDaddyManagedSite() && in_array($plugin, ['woocommerce/woocommerce.php', 'action-scheduler/action-scheduler.php'], true)) {
85 return true;
86 }
87
88 $excludedPlugins = get_option('wpstg_optimizer_excluded', []);
89
90 // Check for custom excluded plugins
91 foreach ($excludedPlugins as $excludedPlugin) {
92 if (strpos($plugin, $excludedPlugin) !== false) {
93 return true;
94 }
95 }
96
97 return false;
98 }
99 }
100
101 if (!function_exists('wpstgExcludePlugins')) {
102 /**
103 * Remove all plugins except wp-staging and wp-staging-pro from blog-active plugins
104 *
105 * @param array $plugins numerically keyed array of plugin names (index=>name)
106 *
107 * @return array
108 */
109 function wpstgExcludePlugins($plugins)
110 {
111 if (!is_array($plugins) || empty($plugins)) {
112 return [];
113 }
114
115 if (!wpstgIsOptimizerRequest()) {
116 return $plugins;
117 }
118
119 foreach ($plugins as $key => $plugin) {
120 // Default filter. Must be at the beginning or wp staging plugin will be filtered and killed
121 if (strpos($plugin, 'wp-staging') !== false || wpstgIsExcludedPlugin($plugin)) {
122 continue;
123 }
124
125 unset($plugins[$key]);
126 }
127
128
129 return $plugins;
130 }
131
132 add_filter('option_active_plugins', 'wpstgExcludePlugins');
133 }
134
135 if (!function_exists('wpstgExcludeSitePlugins')) {
136 /**
137 * Remove all plugins except wp-staging and wp-staging-pro from network-active plugins
138 *
139 * @param array $plugins array of plugins keyed by name (name=>timestamp pairs)
140 *
141 * @return array
142 */
143 function wpstgExcludeSitePlugins($plugins)
144 {
145 if (!is_array($plugins) || empty($plugins)) {
146 return [];
147 }
148
149 if (!wpstgIsOptimizerRequest()) {
150 return $plugins;
151 }
152
153 foreach ($plugins as $plugin => $timestamp) {
154 // Default filter. Must be at the beginning or wp staging plugin will be filtered and killed
155 if (strpos($plugin, 'wp-staging') !== false || wpstgIsExcludedPlugin($plugin)) {
156 continue;
157 }
158
159 unset($plugins[$plugin]);
160 }
161
162 return $plugins;
163 }
164
165 if (is_multisite()) {
166 add_filter('site_option_active_sitewide_plugins', 'wpstgExcludeSitePlugins');
167 }
168 }
169
170 if (!function_exists('wpstgDisableActivePluginsFilterAfterLoad')) {
171 /**
172 * Unhook the active_plugins read filters after plugins have loaded.
173 *
174 * They are only needed to stop third-party plugins from loading, which is done by
175 * plugins_loaded. Left registered, activate_plugin()/deactivate_plugins() would persist
176 * their filtered (wp-staging-only) result and deactivate every other plugin (issue #5371).
177 *
178 * @return void
179 */
180 function wpstgDisableActivePluginsFilterAfterLoad()
181 {
182 remove_filter('option_active_plugins', 'wpstgExcludePlugins');
183 remove_filter('site_option_active_sitewide_plugins', 'wpstgExcludeSitePlugins');
184 }
185
186 add_action('plugins_loaded', 'wpstgDisableActivePluginsFilterAfterLoad');
187 }
188
189 if (!function_exists('wpstgDisableTheme')) {
190 /**
191 *
192 * Disables the active theme during WP Staging AJAX requests
193 *
194 *
195 * @param string $dir
196 *
197 * @return string
198 */
199 function wpstgDisableTheme($dir)
200 {
201 $enableTheme = apply_filters('wpstg_optimizer_enable_theme', false);
202
203 if (wpstgIsOptimizerRequest() && $enableTheme === false) {
204 $wpstgRootPro = wpstgGetPluginsDir() . 'wp-staging-pro';
205 $wpstgRoot = wpstgGetPluginsDir() . 'wp-staging';
206
207 $theme = '/resources/blank-theme';
208 $file = $theme . '/functions.php';
209
210 if (file_exists($wpstgRoot . $file)) {
211 return $wpstgRoot . $theme;
212 } elseif (file_exists($wpstgRootPro . $file)) {
213 return $wpstgRootPro . $theme;
214 } else {
215 return '';
216 }
217 }
218
219 return $dir;
220 }
221
222 add_filter('stylesheet_directory', 'wpstgDisableTheme');
223 add_filter('template_directory', 'wpstgDisableTheme');
224 }
225
226 if (!function_exists('wpstgIsOptimizerRequest')) {
227 /**
228 * Should the current request be processed by optimizer?
229 *
230 * For WP STAGING requests that require other plugins to be active, use raw_wpstg_{actionName}
231 *
232 * @return bool
233 */
234 function wpstgIsOptimizerRequest(): bool
235 {
236 if (!wpstgIsEnabledOptimizer()) {
237 return false;
238 }
239
240 if (isset($_POST['wpstg_action']) && sanitize_text_field($_POST['wpstg_action']) === 'bypass_optimizer') {
241 return false;
242 }
243
244 if (
245 defined('DOING_AJAX') &&
246 DOING_AJAX &&
247 isset($_REQUEST['action']) &&
248 strpos(sanitize_text_field($_REQUEST['action']), 'wpstg_send_report') === false &&
249 strpos(sanitize_text_field($_REQUEST['action']), 'wpstg--send--otp') === false &&
250 strpos(sanitize_text_field($_REQUEST['action']), 'wpstg') === 0
251 ) {
252 return true;
253 }
254
255 return false;
256 }
257 }
258
259 if (!function_exists('wpstgTgmpaCompatibility')) {
260 /**
261 * Remove TGM Plugin Activation 'force_activation' admin_init action hook if present.
262 *
263 * This is to stop excluded plugins being deactivated after a migration, when a theme uses TGMPA to require a plugin to be always active.
264 */
265 function wpstgTgmpaCompatibility()
266 {
267 $isFunctionRemoved = false;
268
269 // run on wpstg page
270 if (isset($_GET['page']) && $_GET['page'] == 'wpstg_clone') {
271 $isFunctionRemoved = true;
272 }
273
274 // run on wpstg ajax requests
275 if (defined('DOING_AJAX') && DOING_AJAX && isset($_POST['action']) && strpos(sanitize_text_field($_POST['action']), 'wpstg') !== false) {
276 $isFunctionRemoved = true;
277 }
278
279 if ($isFunctionRemoved) {
280 global $wp_filter;
281
282 $adminInitFunctions = $wp_filter['admin_init'];
283 foreach ($adminInitFunctions as $priority => $functions) {
284 if (!isset($wp_filter['admin_init'][$priority])) {
285 continue;
286 }
287
288 foreach ($functions as $key => $function) {
289 if (!isset($wp_filter['admin_init'][$priority][$key])) {
290 continue;
291 }
292
293 // searching for function this way as can't rely on the calling class being named TGM_Plugin_Activation
294 if (strpos($key, 'force_activation') !== false) {
295 unset($wp_filter['admin_init'][$priority][$key]);
296
297 return;
298 }
299 }
300 }
301 }
302 }
303
304 add_action('admin_init', 'wpstgTgmpaCompatibility', 1);
305 }
306
307 if (!function_exists('wpstgIsStaging')) {
308 /**
309 * @return bool True if it is staging site. False otherwise.
310 */
311 function wpstgIsStaging(): bool
312 {
313 if (defined('WPSTAGING_DEV_SITE') && constant('WPSTAGING_DEV_SITE') === true) {
314 return true;
315 }
316
317 if (get_option("wpstg_is_staging_site") === "true") {
318 return true;
319 }
320
321 if (file_exists(ABSPATH . '.wp-staging')) {
322 return true;
323 }
324
325 return false;
326 }
327 }
328
329 if (!function_exists('wpstgGetCloneSettings')) {
330 /**
331 * Get the value of the given option in clone settings,
332 * If no option given return all clone settings
333 *
334 * @param string|null $option
335 * @return mixed
336 */
337 function wpstgGetCloneSettings($option = null)
338 {
339 $settings = get_option('wpstg_clone_settings', null);
340
341 if (!is_string($option)) {
342 return $settings;
343 }
344
345 if (!is_object($settings)) {
346 return null;
347 }
348
349 if (!property_exists($settings, $option)) {
350 return null;
351 }
352
353 return $settings->{$option};
354 }
355 }
356
357 /**
358 * Disable all outgoing e-mails on Staging site
359 * Will check against both the old and new logic of storing emails disabled option
360 */
361 if (wpstgIsStaging() && (((bool)get_option("wpstg_emails_disabled") === true) || (wpstgGetCloneSettings('wpstg_emails_disabled')))) {
362 if (!function_exists('wp_mail')) {
363 /**
364 * @param array|string $to
365 * @param string $subject
366 * @param string $message
367 * @param array|string $headers
368 * @param array|string $attachments
369 *
370 * @return bool
371 */
372 function wp_mail($to, $subject, $message, $headers = '', $attachments = [])
373 {
374 if (defined('WPSTG_DEBUG') && WPSTG_DEBUG) {
375 // Safely cast everything to string
376 $to = is_string($to) ? $to : wp_json_encode($to);
377 $subject = is_string($subject) ? $subject : wp_json_encode($subject);
378 $message = is_string($message) ? $message : wp_json_encode($message);
379 $headers = is_string($headers) ? $headers : wp_json_encode($headers);
380 $attachments = is_string($attachments) ? $attachments : wp_json_encode($attachments);
381
382 $log_entry = <<<LOG_ENTRY
383 /***
384 * WPSTAGING - Mails are disabled for this Staging site. This e-mail was going to be sent, but was prevented:
385 ***
386 * To: $to
387 ***
388 * Subject: $subject
389 ***
390 * Message: $message
391 ***
392 * Headers: $headers
393 ***
394 * Attachments: $attachments
395 ***/
396 LOG_ENTRY;
397
398 error_log($log_entry);
399 }
400
401 return false;
402 }
403 } elseif (defined('WPSTG_DEBUG') && WPSTG_DEBUG) {
404 error_log("WP STAGING: Could not override the wp_mail() function to disable e-mails on staging site, as it was already defined before the optimizer mu-plugin was loaded.");
405 }
406 }
407