PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backup, Restore, Migration & Clone / 4.8.1
WP STAGING – WordPress Backup, Restore, Migration & Clone v4.8.1
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 / runtimeRequirements.php
wp-staging Last commit date
Backend 1 month ago Backup 1 month ago Basic 3 months ago Component 1 month ago Core 1 month ago Framework 1 month ago Frontend 5 months ago Notifications 8 months ago Staging 1 month ago assets 1 month ago languages 1 month ago resources 1 year ago vendor_wpstg 1 month ago views 1 month ago CONTRIBUTING.md 1 year ago Deactivate.php 8 months ago README.md 3 months ago SECURITY.md 2 years ago autoloader.php 1 month ago bootstrap.php 1 month ago commonBootstrap.php 1 month ago constantsFree.php 1 month ago freeBootstrap.php 1 month ago install.php 1 year ago opcacheBootstrap.php 1 month ago readme.txt 1 month ago runtimeRequirements.php 3 months ago uninstall.php 1 month ago wp-staging-error-handler.php 6 months ago wp-staging.php 1 month ago
runtimeRequirements.php
415 lines
1 <?php
2
3 /**
4 * @var string $pluginFilePath The absolute path to the main file of this plugin.
5 *
6 */
7 $pluginFilePath = $pluginFilePath ?? '';
8 // TODO: refactor this and implement our own methods to get rid of hard loading wp core functions which is not recommended by WP.
9 require_once(trailingslashit(ABSPATH) . 'wp-admin/includes/plugin.php');
10
11 if (!defined('WPSTGPRO_MINIMUM_FREE_VERSION')) {
12 /**
13 * Expected version number of the free plugin in order to activate it at the same time with pro.
14 *
15 * ⚠️ DO NOT bump this value in CI or automated deploys!
16 * If set too high and a user updates Pro before Free, the dependency check
17 * blocks the Free auto-updater and the user gets stuck. Only change manually
18 * after careful consideration. The CI pipeline intentionally skips this value.
19 */
20 define('WPSTGPRO_MINIMUM_FREE_VERSION', '3.8.0');
21 }
22
23 if (!defined('WPSTG_FREE_VERSION_PLUGIN_FILE')) {
24 define('WPSTG_FREE_VERSION_PLUGIN_FILE', 'wp-staging.php');
25 }
26
27 if (!defined('WPSTG_PRO_VERSION_PLUGIN_FILE')) {
28 define('WPSTG_PRO_VERSION_PLUGIN_FILE', 'wp-staging-pro.php');
29 }
30
31 if (!function_exists('wpstgIsProPluginActive')) {
32 /**
33 * @return bool
34 */
35 function wpstgIsProPluginActive(): bool
36 {
37 return wpstgIsPluginActivated(WPSTG_PRO_VERSION_PLUGIN_FILE);
38 }
39 }
40
41 if (!function_exists('wpstgIsProPluginActiveInNetwork')) {
42 /**
43 * @return bool
44 */
45 function wpstgIsProPluginActiveInNetwork(): bool
46 {
47 return wpstgIsPluginActiveInNetwork(WPSTG_PRO_VERSION_PLUGIN_FILE);
48 }
49 }
50
51 if (!function_exists('wpstgIsFreeVersionRequiredForPro')) {
52 /**
53 * @return bool
54 */
55 function wpstgIsFreeVersionRequiredForPro(): bool
56 {
57 return apply_filters('wpstg.free_required_by_pro', true);
58 }
59 }
60
61 if (!function_exists('wpstgIsProActiveInNetworkOrInCurrentSite')) {
62 /**
63 * @return bool
64 */
65 function wpstgIsProActiveInNetworkOrInCurrentSite(): bool
66 {
67 return wpstgIsProPluginActiveInNetwork() || wpstgIsProPluginActive();
68 }
69 }
70
71 if (!function_exists('wpstgIsFreeVersionActive')) {
72 /**
73 * @return bool
74 */
75 function wpstgIsFreeVersionActive(): bool
76 {
77 return wpstgIsPluginActivated(WPSTG_FREE_VERSION_PLUGIN_FILE);
78 }
79 }
80
81 if (!function_exists('wpstgIsFreeVersionActiveInNetwork')) {
82 /**
83 * @return bool
84 */
85 function wpstgIsFreeVersionActiveInNetwork(): bool
86 {
87 return wpstgIsPluginActiveInNetwork(WPSTG_FREE_VERSION_PLUGIN_FILE);
88 }
89 }
90
91 if (!function_exists('wpstgIsFreeActiveInNetworkOrCurrentSite')) {
92 /**
93 * @return bool
94 */
95 function wpstgIsFreeActiveInNetworkOrCurrentSite(): bool
96 {
97 return wpstgIsFreeVersionActiveInNetwork() || wpstgIsFreeVersionActive();
98 }
99 }
100
101 if (!function_exists('wpstgGetPluginSlug')) {
102 /**
103 * @param string $pluginFileName
104 *
105 * @return bool|string false if plugin is not installed otherwise return the plugin slug/basename.
106 */
107 function wpstgGetPluginSlug(string $pluginFileName)
108 {
109 $allPlugins = get_plugins();
110 foreach ($allPlugins as $key => $value) {
111 if (strpos($key, $pluginFileName) !== false) {
112 return $key;
113 }
114 }
115
116 return false;
117 }
118 }
119
120 if (!function_exists('wpstgGetPluginData')) {
121 /**
122 * @param string $pluginFileName
123 *
124 * @return array
125 */
126 function wpstgGetPluginData(string $pluginFileName): array
127 {
128 $allPlugins = get_plugins();
129 foreach ($allPlugins as $key => $value) {
130 if (strpos($key, $pluginFileName) !== false) {
131 return $value;
132 }
133 }
134
135 return [];
136 }
137 }
138
139 if (!function_exists('wpstgGetFreeVersionNumberIfInstalled')) {
140 /**
141 * @return string returns empty string if free is not installed.
142 */
143 function wpstgGetFreeVersionNumberIfInstalled(): string
144 {
145 $freeData = wpstgGetPluginData(WPSTG_FREE_VERSION_PLUGIN_FILE);
146 $installedFreeVersionNumber = isset($freeData['Version']) ? $freeData['Version'] : '';
147
148 return $installedFreeVersionNumber;
149 }
150 }
151
152 if (!function_exists('wpstgGetProVersionNumberIfInstalled')) {
153 /**
154 * @return string returns empty string if pro is not installed.
155 */
156 function wpstgGetProVersionNumberIfInstalled(): string
157 {
158 $freeData = wpstgGetPluginData(WPSTG_PRO_VERSION_PLUGIN_FILE);
159 $installedFreeVersionNumber = isset($freeData['Version']) ? $freeData['Version'] : '';
160
161 return $installedFreeVersionNumber;
162 }
163 }
164
165 if (!function_exists('wpstgIsFreeVersionCompatible')) {
166 /**
167 * @return bool
168 */
169 function wpstgIsFreeVersionCompatible(): bool
170 {
171 return defined('WPSTGPRO_MINIMUM_FREE_VERSION') && version_compare(wpstgGetFreeVersionNumberIfInstalled(), WPSTGPRO_MINIMUM_FREE_VERSION, '>=');
172 }
173 }
174
175 if (!function_exists('wpstgIsFreeActiveButOutdated')) {
176 /**
177 * @return bool
178 */
179 function wpstgIsFreeActiveButOutdated(): bool
180 {
181 if (wpstgIsFreeActiveInNetworkOrCurrentSite() && !wpstgIsFreeVersionCompatible()) {
182 return true;
183 }
184
185 return false;
186 }
187 }
188
189 if (!function_exists('wpstgDeactivatePlugin')) {
190 /**
191 * @param mixed $pluginFilePath
192 * @return void
193 */
194 function wpstgDeactivatePlugin($pluginFilePath)
195 {
196 if (is_network_admin()) {
197 deactivate_plugins($pluginFilePath, false, true);
198 } else {
199 deactivate_plugins($pluginFilePath);
200 }
201 }
202 }
203
204 if (!function_exists('wpstgCanShowAnotherInstanceRunningNotice')) {
205 /**
206 * @param string $pluginFilePath
207 * @return bool
208 */
209 function wpstgCanShowAnotherInstanceRunningNotice(string $pluginFilePath): bool
210 {
211 if (!current_user_can('activate_plugins')) {
212 return false;
213 }
214
215 if (strpos($pluginFilePath, 'wp-staging-pro.php') !== false && wpstgIsProActiveInNetworkOrInCurrentSite() && !wpstgIsFreeActiveInNetworkOrCurrentSite()) {
216 return true;
217 }
218
219 if (strpos($pluginFilePath, 'wp-staging.php') !== false && !wpstgIsProActiveInNetworkOrInCurrentSite() && wpstgIsFreeActiveInNetworkOrCurrentSite()) {
220 return true;
221 }
222
223 return false;
224 }
225 }
226
227 if (!function_exists('wpstgCanThrowAnotherInstanceLoadedException')) {
228 /**
229 * @param string $pluginFilePath
230 * @return bool
231 */
232 function wpstgCanThrowAnotherInstanceLoadedException(string $pluginFilePath = ''): bool
233 {
234 if (defined('WPSTG_VERSION') && version_compare(WPSTG_VERSION, WPSTGPRO_MINIMUM_FREE_VERSION, '<')) {
235 return true;
236 }
237
238 if (defined('WPSTGPRO_VERSION') && version_compare(WPSTGPRO_VERSION, '5.1.0', '<')) {
239 return true;
240 }
241
242 if (!wpstgIsProActiveInNetworkOrInCurrentSite() && strpos($pluginFilePath, 'wp-staging-pro.php') === false) {
243 return true;
244 }
245
246 return false;
247 }
248 }
249
250 if (!function_exists('wpstgIsPluginActivated')) {
251 /**
252 * This function checks if a plugin is activated on single site.
253 *
254 * @param string $pluginFileName
255 *
256 * @return bool
257 */
258 function wpstgIsPluginActivated(string $pluginFileName): bool
259 {
260 $activePlugins = wp_get_active_and_valid_plugins();
261 foreach ($activePlugins as $sitewidePlugin) {
262 if (strpos($sitewidePlugin, $pluginFileName) !== false) {
263 return true;
264 }
265 }
266
267 return false;
268 }
269 }
270
271 if (!function_exists('wpstgIsPluginActiveInNetwork')) {
272 /**
273 * @param string $pluginFileName
274 *
275 * @return bool
276 */
277 function wpstgIsPluginActiveInNetwork(string $pluginFileName): bool
278 {
279 if (!is_multisite()) {
280 return false;
281 }
282
283 $activePlugins = wp_get_active_network_plugins();
284 foreach ($activePlugins as $sitewidePlugin) {
285 if (strpos($sitewidePlugin, $pluginFileName) !== false) {
286 return true;
287 }
288 }
289
290 return false;
291 }
292 }
293
294 if (!function_exists('wpstgDoLoadPluginAutoLoad')) {
295 /**
296 * @param string $pluginFilePath
297 * @return void
298 */
299 function wpstgDoLoadPluginAutoLoad(string $pluginFilePath): bool
300 {
301 if (class_exists('\WPStaging\Core\WPStaging')) {
302 return false;
303 }
304
305 if (strpos($pluginFilePath, 'wp-staging.php') === false) {
306 return true;
307 }
308
309 if (strpos($pluginFilePath, 'wp-staging.php') !== false && (!is_network_admin() && !wpstgIsProPluginActive())) {
310 return true;
311 }
312
313 if (strpos($pluginFilePath, 'wp-staging.php') !== false && (is_network_admin() && !wpstgIsProPluginActiveInNetwork())) {
314 return true;
315 }
316
317 return false;
318 }
319 }
320
321 /**
322 * Early bail: Deactivate outdated free version.
323 */
324 if (strpos($pluginFilePath, 'wp-staging-pro.php') !== false && wpstgIsFreeActiveButOutdated()) {
325 // Deactivate free plugin.
326 $pluginSlug = wpstgGetPluginSlug(WPSTG_FREE_VERSION_PLUGIN_FILE);
327 wpstgDeactivatePlugin($pluginSlug);
328 }
329
330 /**
331 * Early bail: Activating another WPSTAGING Plugin.
332 * This is the only scenario where the plugin would be included after "plugins_loaded",
333 * therefore we need to detect earlier, from the context of the request, whether this is going to happen,
334 * to disable this plugin early and bail the bootstrap process to not conflict with the one being activated.
335 *
336 * Covers both clicking on the "Activate" button and selecting the "Activate" bulk-action.
337 */
338 if (isset($_REQUEST['action'])) {
339 switch ($_REQUEST['action']) :
340 case 'activate':
341 case 'error_scrape':
342 if (isset($_REQUEST['plugin'])) {
343 $plugin = (string)wp_unslash(sanitize_text_field($_REQUEST['plugin']));
344
345 $isActivatingWpStaging = strpos($plugin, 'wp-staging.php') || strpos($plugin, 'wp-staging-pro.php');
346 $isActivatingAnotherWpStaging = plugin_basename($plugin) !== plugin_basename($pluginFilePath);
347
348 if ($isActivatingWpStaging && $isActivatingAnotherWpStaging && wpstgCanThrowAnotherInstanceLoadedException($plugin) && current_user_can('deactivate_plugin', plugin_basename($pluginFilePath))) {
349 throw new Exception("Activating another WPSTAGING Plugin. Plugin that bailed bootstrapping: $pluginFilePath");
350 }
351 }
352
353 break;
354 case 'activate-selected':
355 case 'activate-multi':
356 if (isset($_REQUEST['checked'])) {
357 $plugins = array_map('sanitize_text_field', (array)wp_unslash($_REQUEST['checked']));
358
359 foreach ($plugins as $i => $plugin) {
360 $isActivatingWpStaging = strpos($plugin, 'wp-staging.php') || strpos($plugin, 'wp-staging-pro.php');
361 $isActivatingAnotherWpStaging = plugin_basename($plugin) !== plugin_basename($pluginFilePath);
362
363 if ($isActivatingWpStaging && $isActivatingAnotherWpStaging && wpstgCanThrowAnotherInstanceLoadedException($plugin) && current_user_can('deactivate_plugin', plugin_basename($pluginFilePath))) {
364 // @todo consider changing this! Leads to populating debug.log with thousands of entries during testing
365 throw new Exception("Activating another WPSTAGING Plugin. Plugin that bailed bootstrapping: $pluginFilePath");
366 }
367 }
368 }
369
370 break;
371 endswitch;
372 }
373
374 /**
375 * Early bail: Another instance of WPSTAGING active.
376 */
377 if (
378 // WPSTAGING <= 2.7.5
379 class_exists('\WPStaging\WPStaging') ||
380 // WPSTAGING >= 2.7.6
381 class_exists('\WPStaging\Core\WPStaging')
382 ) {
383 if (wpstgCanShowAnotherInstanceRunningNotice($pluginFilePath)) {
384 add_action(is_network_admin() ? 'network_admin_notices' : 'admin_notices', function () { // phpcs:ignore WPStaging.Security.FirstArgNotAString, WPStaging.Security.AuthorizationChecked
385 echo '<div class="notice-warning notice is-dismissible another-wpstaging-active">';
386 echo '<p style="font-weight: bold;">' . esc_html__('WP STAGING Already Active', 'wp-staging') . '</p>';
387 echo '<p>' . esc_html__('Another WP STAGING is already activated, please leave only one instance of the WP STAGING plugin active at the same time.', 'wp-staging') . '</p>';
388 echo '</div>';
389 });
390 }
391
392 if (!wpstgCanThrowAnotherInstanceLoadedException($pluginFilePath)) {
393 return;
394 }
395
396 throw new Exception("Another instance of WPSTAGING active. Plugin that bailed bootstrapping: $pluginFilePath");
397 }
398
399 /**
400 * Early bail: Unsupported WordPress version.
401 * We check on runtime instead of activation so we can display the notice.
402 */
403 if (!version_compare($currentWordPressVersion = (string)get_bloginfo('version'), $minimumWordPressVersion = '4.4', '>=')) {
404 if (current_user_can('activate_plugins')) {
405 add_action(is_network_admin() ? 'network_admin_notices' : 'admin_notices', function () use ($currentWordPressVersion, $minimumWordPressVersion) { // phpcs:ignore WPStaging.Security.FirstArgNotAString, WPStaging.Security.AuthorizationChecked
406 echo '<div class="notice-warning notice is-dismissible">';
407 echo '<p style="font-weight: bold;">' . esc_html__('WP STAGING', 'wp-staging') . '</p>';
408 echo '<p>' . sprintf(esc_html__('WP STAGING requires at least WordPress %s to run. You have WordPress %s.', 'wp-staging'), esc_html($minimumWordPressVersion), esc_html($currentWordPressVersion)) . '</p>';
409 echo '</div>';
410 });
411 }
412
413 throw new Exception("Unsupported WordPress version. Plugin that bailed bootstrapping: $pluginFilePath");
414 }
415