PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backup, Restore, Migration & Clone / 4.9.3
WP STAGING – WordPress Backup, Restore, Migration & Clone v4.9.3
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 4 days ago
wp-staging-optimizer.php
387 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.1
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.1');
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('wpstgIsExcludedPlugin')) {
61 /**
62 * Check if a plugin should be excluded from the optimizer and still running during wp staging requests
63 * @param string $plugin
64 * @return bool
65 */
66 function wpstgIsExcludedPlugin(string $plugin): bool
67 {
68 $excludedPlugins = get_option('wpstg_optimizer_excluded', []);
69
70 // Check for custom excluded plugins
71 foreach ($excludedPlugins as $excludedPlugin) {
72 if (strpos($plugin, $excludedPlugin) !== false) {
73 return true;
74 }
75 }
76
77 return false;
78 }
79 }
80
81 if (!function_exists('wpstgExcludePlugins')) {
82 /**
83 * Remove all plugins except wp-staging and wp-staging-pro from blog-active plugins
84 *
85 * @param array $plugins numerically keyed array of plugin names (index=>name)
86 *
87 * @return array
88 */
89 function wpstgExcludePlugins($plugins)
90 {
91 if (!is_array($plugins) || empty($plugins)) {
92 return [];
93 }
94
95 if (!wpstgIsOptimizerRequest()) {
96 return $plugins;
97 }
98
99 foreach ($plugins as $key => $plugin) {
100 // Default filter. Must be at the beginning or wp staging plugin will be filtered and killed
101 if (strpos($plugin, 'wp-staging') !== false || wpstgIsExcludedPlugin($plugin)) {
102 continue;
103 }
104
105 unset($plugins[$key]);
106 }
107
108
109 return $plugins;
110 }
111
112 add_filter('option_active_plugins', 'wpstgExcludePlugins');
113 }
114
115 if (!function_exists('wpstgExcludeSitePlugins')) {
116 /**
117 * Remove all plugins except wp-staging and wp-staging-pro from network-active plugins
118 *
119 * @param array $plugins array of plugins keyed by name (name=>timestamp pairs)
120 *
121 * @return array
122 */
123 function wpstgExcludeSitePlugins($plugins)
124 {
125 if (!is_array($plugins) || empty($plugins)) {
126 return [];
127 }
128
129 if (!wpstgIsOptimizerRequest()) {
130 return $plugins;
131 }
132
133 foreach ($plugins as $plugin => $timestamp) {
134 // Default filter. Must be at the beginning or wp staging plugin will be filtered and killed
135 if (strpos($plugin, 'wp-staging') !== false || wpstgIsExcludedPlugin($plugin)) {
136 continue;
137 }
138
139 unset($plugins[$plugin]);
140 }
141
142 return $plugins;
143 }
144
145 if (is_multisite()) {
146 add_filter('site_option_active_sitewide_plugins', 'wpstgExcludeSitePlugins');
147 }
148 }
149
150 if (!function_exists('wpstgDisableActivePluginsFilterAfterLoad')) {
151 /**
152 * Unhook the active_plugins read filters after plugins have loaded.
153 *
154 * They are only needed to stop third-party plugins from loading, which is done by
155 * plugins_loaded. Left registered, activate_plugin()/deactivate_plugins() would persist
156 * their filtered (wp-staging-only) result and deactivate every other plugin (issue #5371).
157 *
158 * @return void
159 */
160 function wpstgDisableActivePluginsFilterAfterLoad()
161 {
162 remove_filter('option_active_plugins', 'wpstgExcludePlugins');
163 remove_filter('site_option_active_sitewide_plugins', 'wpstgExcludeSitePlugins');
164 }
165
166 add_action('plugins_loaded', 'wpstgDisableActivePluginsFilterAfterLoad');
167 }
168
169 if (!function_exists('wpstgDisableTheme')) {
170 /**
171 *
172 * Disables the active theme during WP Staging AJAX requests
173 *
174 *
175 * @param string $dir
176 *
177 * @return string
178 */
179 function wpstgDisableTheme($dir)
180 {
181 $enableTheme = apply_filters('wpstg_optimizer_enable_theme', false);
182
183 if (wpstgIsOptimizerRequest() && $enableTheme === false) {
184 $wpstgRootPro = wpstgGetPluginsDir() . 'wp-staging-pro';
185 $wpstgRoot = wpstgGetPluginsDir() . 'wp-staging';
186
187 $theme = '/resources/blank-theme';
188 $file = $theme . '/functions.php';
189
190 if (file_exists($wpstgRoot . $file)) {
191 return $wpstgRoot . $theme;
192 } elseif (file_exists($wpstgRootPro . $file)) {
193 return $wpstgRootPro . $theme;
194 } else {
195 return '';
196 }
197 }
198
199 return $dir;
200 }
201
202 add_filter('stylesheet_directory', 'wpstgDisableTheme');
203 add_filter('template_directory', 'wpstgDisableTheme');
204 }
205
206 if (!function_exists('wpstgIsOptimizerRequest')) {
207 /**
208 * Should the current request be processed by optimizer?
209 *
210 * For WP STAGING requests that require other plugins to be active, use raw_wpstg_{actionName}
211 *
212 * @return bool
213 */
214 function wpstgIsOptimizerRequest(): bool
215 {
216 if (!wpstgIsEnabledOptimizer()) {
217 return false;
218 }
219
220 if (isset($_POST['wpstg_action']) && sanitize_text_field($_POST['wpstg_action']) === 'bypass_optimizer') {
221 return false;
222 }
223
224 if (
225 defined('DOING_AJAX') &&
226 DOING_AJAX &&
227 isset($_REQUEST['action']) &&
228 strpos(sanitize_text_field($_REQUEST['action']), 'wpstg_send_report') === false &&
229 strpos(sanitize_text_field($_REQUEST['action']), 'wpstg--send--otp') === false &&
230 strpos(sanitize_text_field($_REQUEST['action']), 'wpstg') === 0
231 ) {
232 return true;
233 }
234
235 return false;
236 }
237 }
238
239 if (!function_exists('wpstgTgmpaCompatibility')) {
240 /**
241 * Remove TGM Plugin Activation 'force_activation' admin_init action hook if present.
242 *
243 * This is to stop excluded plugins being deactivated after a migration, when a theme uses TGMPA to require a plugin to be always active.
244 */
245 function wpstgTgmpaCompatibility()
246 {
247 $isFunctionRemoved = false;
248
249 // run on wpstg page
250 if (isset($_GET['page']) && $_GET['page'] == 'wpstg_clone') {
251 $isFunctionRemoved = true;
252 }
253
254 // run on wpstg ajax requests
255 if (defined('DOING_AJAX') && DOING_AJAX && isset($_POST['action']) && strpos(sanitize_text_field($_POST['action']), 'wpstg') !== false) {
256 $isFunctionRemoved = true;
257 }
258
259 if ($isFunctionRemoved) {
260 global $wp_filter;
261
262 $adminInitFunctions = $wp_filter['admin_init'];
263 foreach ($adminInitFunctions as $priority => $functions) {
264 if (!isset($wp_filter['admin_init'][$priority])) {
265 continue;
266 }
267
268 foreach ($functions as $key => $function) {
269 if (!isset($wp_filter['admin_init'][$priority][$key])) {
270 continue;
271 }
272
273 // searching for function this way as can't rely on the calling class being named TGM_Plugin_Activation
274 if (strpos($key, 'force_activation') !== false) {
275 unset($wp_filter['admin_init'][$priority][$key]);
276
277 return;
278 }
279 }
280 }
281 }
282 }
283
284 add_action('admin_init', 'wpstgTgmpaCompatibility', 1);
285 }
286
287 if (!function_exists('wpstgIsStaging')) {
288 /**
289 * @return bool True if it is staging site. False otherwise.
290 */
291 function wpstgIsStaging(): bool
292 {
293 if (defined('WPSTAGING_DEV_SITE') && constant('WPSTAGING_DEV_SITE') === true) {
294 return true;
295 }
296
297 if (get_option("wpstg_is_staging_site") === "true") {
298 return true;
299 }
300
301 if (file_exists(ABSPATH . '.wp-staging')) {
302 return true;
303 }
304
305 return false;
306 }
307 }
308
309 if (!function_exists('wpstgGetCloneSettings')) {
310 /**
311 * Get the value of the given option in clone settings,
312 * If no option given return all clone settings
313 *
314 * @param string|null $option
315 * @return mixed
316 */
317 function wpstgGetCloneSettings($option = null)
318 {
319 $settings = get_option('wpstg_clone_settings', null);
320
321 if (!is_string($option)) {
322 return $settings;
323 }
324
325 if (!is_object($settings)) {
326 return null;
327 }
328
329 if (!property_exists($settings, $option)) {
330 return null;
331 }
332
333 return $settings->{$option};
334 }
335 }
336
337 /**
338 * Disable all outgoing e-mails on Staging site
339 * Will check against both the old and new logic of storing emails disabled option
340 */
341 if (wpstgIsStaging() && (((bool)get_option("wpstg_emails_disabled") === true) || (wpstgGetCloneSettings('wpstg_emails_disabled')))) {
342 if (!function_exists('wp_mail')) {
343 /**
344 * @param array|string $to
345 * @param string $subject
346 * @param string $message
347 * @param array|string $headers
348 * @param array|string $attachments
349 *
350 * @return bool
351 */
352 function wp_mail($to, $subject, $message, $headers = '', $attachments = [])
353 {
354 if (defined('WPSTG_DEBUG') && WPSTG_DEBUG) {
355 // Safely cast everything to string
356 $to = is_string($to) ? $to : wp_json_encode($to);
357 $subject = is_string($subject) ? $subject : wp_json_encode($subject);
358 $message = is_string($message) ? $message : wp_json_encode($message);
359 $headers = is_string($headers) ? $headers : wp_json_encode($headers);
360 $attachments = is_string($attachments) ? $attachments : wp_json_encode($attachments);
361
362 $log_entry = <<<LOG_ENTRY
363 /***
364 * WPSTAGING - Mails are disabled for this Staging site. This e-mail was going to be sent, but was prevented:
365 ***
366 * To: $to
367 ***
368 * Subject: $subject
369 ***
370 * Message: $message
371 ***
372 * Headers: $headers
373 ***
374 * Attachments: $attachments
375 ***/
376 LOG_ENTRY;
377
378 error_log($log_entry);
379 }
380
381 return false;
382 }
383 } elseif (defined('WPSTG_DEBUG') && WPSTG_DEBUG) {
384 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.");
385 }
386 }
387