PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backup, Restore, Migration & Clone / 4.9.2
WP STAGING – WordPress Backup, Restore, Migration & Clone v4.9.2
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 / Upgrade / Upgrade.php
wp-staging / Backend / Upgrade Last commit date
Upgrade.php 1 day ago
Upgrade.php
422 lines
1 <?php
2
3 /**
4 * Upgrade Class
5 * This must be loaded on every page init to ensure all settings are
6 * adjusted correctly and to run any upgrade process if necessary.
7 */
8
9 namespace WPStaging\Backend\Upgrade;
10
11 use WPStaging\Core\Utils\IISWebConfig;
12 use WPStaging\Core\Utils\Htaccess;
13 use WPStaging\Core\WPStaging;
14 use WPStaging\Framework\BackgroundProcessing\Queue;
15 use WPStaging\Notifications\Notifications;
16 use WPStaging\Staging\Sites;
17 use WPStaging\Staging\Service\StagingEngine;
18 use WPStaging\Backup\BackupScheduler;
19 use WPStaging\Backup\Storage\Providers;
20 use WPStaging\Framework\Notices\NextGenEngineNotice;
21 use WPStaging\Framework\Upgrade\UpgradeFlags;
22
23 // No Direct Access
24 if (!defined("WPINC")) {
25 die;
26 }
27
28 class Upgrade
29 {
30 /**
31 * @var string
32 */
33 const OPTION_UPGRADE_DATE = 'wpstg_free_upgrade_date';
34
35 /**
36 * @var string
37 */
38 const OPTION_INSTALL_DATE = 'wpstg_free_install_date';
39
40 /**
41 * Previous Version number
42 * @var string
43 */
44 private $previousVersion;
45
46 /**
47 * Global settings
48 * @var object
49 */
50 private $settings;
51
52 /**
53 * db object
54 * @var object
55 */
56 private $db;
57
58 /**
59 * @var Sites
60 */
61 private $stagingSitesHelper;
62
63 /**
64 * @var UpgradeFlags
65 */
66 private $upgradeFlags;
67
68 public function __construct()
69 {
70 // Previous version
71 $this->previousVersion = preg_replace('/[^0-9.].*/', '', get_option('wpstg_version'));
72
73 $this->settings = (object) get_option("wpstg_settings", []);
74
75 // db
76 $this->db = WPStaging::getInstance()->get("wpdb");
77
78 /** @var Sites */
79 $this->stagingSitesHelper = WPStaging::make(Sites::class);
80 $this->upgradeFlags = WPStaging::make(UpgradeFlags::class);
81 }
82
83 /**
84 * @return void
85 */
86 public function doUpgrade()
87 {
88 $this->upgrade2_0_3();
89 $this->upgrade2_1_2();
90 $this->upgrade2_2_0();
91 $this->upgrade2_4_4();
92 $this->upgrade2_5_9();
93 $this->upgrade2_8_7();
94 $this->upgrade3_0_7();
95 $this->upgrade3_8_1();
96 $this->migrateRemoteStorageOptionNames();
97 $this->revertNextGenStagingEngine();
98
99 $this->setVersion();
100 }
101
102 /**
103 * Revert users off the Next-Gen staging engine (temporarily disabled, issue #5346)
104 * and, when staging sites exist, warn that they may be corrupted.
105 *
106 * Guarded by a persistent feature flag so it runs exactly once, regardless of
107 * the stored version. Idempotent.
108 *
109 * @return void
110 */
111 private function revertNextGenStagingEngine()
112 {
113 if ($this->upgradeFlags->has('next_gen_engine_disabled')) {
114 return;
115 }
116
117 $stagingEngine = WPStaging::make(StagingEngine::class);
118 if ($stagingEngine->getStoredEngine() === StagingEngine::ENGINE_NEXT_GEN) {
119 $stagingEngine->saveEngine(StagingEngine::ENGINE_LEGACY);
120
121 $hasStagingSites = !empty(get_option(Sites::STAGING_SITES_OPTION, []))
122 || !empty(get_option(Sites::OLD_STAGING_SITES_OPTION, []));
123 if ($hasStagingSites) {
124 WPStaging::make(NextGenEngineNotice::class)->enable();
125 }
126 }
127
128 $this->upgradeFlags->mark('next_gen_engine_disabled');
129 }
130
131 /**
132 * Enable backup notification by default
133 * @return void
134 */
135 private function upgrade3_8_1() // phpcs:ignore
136 {
137 // Early bail: Previous version is greater than 3.8.1
138 if (version_compare($this->previousVersion, '3.8.1', '>')) {
139 return;
140 }
141
142 if (!class_exists('WPStaging\Backup\BackupScheduler')) {
143 return;
144 }
145
146 $optionBackupScheduleReportEmail = get_option(Notifications::OPTION_BACKUP_SCHEDULE_REPORT_EMAIL);
147 if (empty($optionBackupScheduleReportEmail) || !filter_var($optionBackupScheduleReportEmail, FILTER_VALIDATE_EMAIL)) {
148 $wpstgSettings = (array)get_option('wpstg_settings');
149
150 if (!empty($wpstgSettings['schedulesReportEmail'])) {
151 $optionBackupScheduleReportEmail = $wpstgSettings['schedulesReportEmail'];
152 } else {
153 $userObject = wp_get_current_user();
154 if (is_object($userObject) && !empty($userObject->user_email)) {
155 $optionBackupScheduleReportEmail = $userObject->user_email;
156 }
157 }
158
159 update_option(Notifications::OPTION_BACKUP_SCHEDULE_REPORT_EMAIL, $optionBackupScheduleReportEmail);
160 }
161
162 // boolean false: Default value if the option does not exist/created yet
163 if (get_option(BackupScheduler::OPTION_BACKUP_SCHEDULE_ERROR_REPORT) === false && !empty($optionBackupScheduleReportEmail)) {
164 update_option(BackupScheduler::OPTION_BACKUP_SCHEDULE_ERROR_REPORT, 'true');
165 }
166 }
167
168 /**
169 * Rename remote storage options from legacy lowercase to new hyphenated format
170 * (e.g. wpstg_googledrive -> wpstg_google-drive).
171 *
172 * Guarded by a persistent feature flag instead of version_compare so the
173 * migration runs exactly once, independent of how wpstg_version is set.
174 *
175 * @return void
176 */
177 private function migrateRemoteStorageOptionNames()
178 {
179 if ($this->upgradeFlags->has('remote_storage_option_names_migrated')) {
180 return;
181 }
182
183 (new Providers())->migrateRemoteStorageOptions();
184 $this->upgradeFlags->mark('remote_storage_option_names_migrated');
185 }
186
187 /**
188 * Add response field to queue table if not exist
189 * @return void
190 */
191 private function upgrade3_0_7() // phpcs:ignore
192 {
193 // Early bail: Previous version is greater than 3.0.6
194 if (version_compare($this->previousVersion, '3.0.6', '>')) {
195 return;
196 }
197
198 $queueUtil = WPStaging::make(Queue::class);
199 $queueUtil->maybeAddResponseColumnToTable();
200 }
201
202 /**
203 * Move existing staging sites to new option defined in Sites::STAGING_SITES_OPTION
204 * @return void
205 */
206 private function upgrade2_8_7() // phpcs:ignore
207 {
208 $this->stagingSitesHelper->addMissingCloneNameUpgradeStructure();
209 $this->stagingSitesHelper->upgradeStagingSitesOption();
210 }
211
212 /**
213 * Fix array keys of staging sites
214 * @return void
215 */
216 private function upgrade2_5_9() // phpcs:ignore
217 {
218 // Previous version lower than 2.5.9
219 if (version_compare($this->previousVersion, '2.5.9', '<')) {
220 // Current options
221 $sites = $this->stagingSitesHelper->tryGettingStagingSites();
222
223 $new = [];
224
225 // Fix keys. Replace white spaces with dash character
226 foreach ($sites as $oldKey => $site) {
227 $key = preg_replace("#\W+#", '-', strtolower($oldKey));
228 $new[$key] = $sites[$oldKey];
229 }
230
231 if (!empty($new)) {
232 $this->stagingSitesHelper->updateStagingSites($new);
233 }
234 }
235 }
236
237 /**
238 * @return void
239 */
240 private function upgrade2_4_4() // phpcs:ignore
241 {
242 // Previous version lower than 2.4.4
243 if (version_compare($this->previousVersion, '2.4.4', '<')) {
244 // Add htaccess to wp staging uploads folder
245 $htaccess = new Htaccess();
246 $htaccess->create(trailingslashit(WPStaging::getContentDir()) . '.htaccess');
247 $htaccess->create(trailingslashit(WPStaging::getContentDir()) . 'logs/.htaccess');
248
249 // Add litespeed htaccess to wp root folder
250 if (extension_loaded('litespeed')) {
251 $htaccess->createLitespeed(ABSPATH . '.htaccess');
252 }
253
254 // create web.config file for IIS in wp staging uploads folder
255 $webconfig = new IISWebConfig();
256 $webconfig->create(trailingslashit(WPStaging::getContentDir()) . 'web.config');
257 $webconfig->create(trailingslashit(WPStaging::getContentDir()) . 'logs/web.config');
258 }
259 }
260
261 /**
262 * Upgrade method 2.2.0
263 * @return void
264 */
265 public function upgrade2_2_0() // phpcs:ignore
266 {
267 // Previous version lower than 2.2.0
268 if (version_compare($this->previousVersion, '2.2.0', '<')) {
269 $this->upgradeElements();
270 }
271 }
272
273 /**
274 * Add missing elements
275 * @return void
276 */
277 private function upgradeElements()
278 {
279 // Current options
280 $sites = $this->stagingSitesHelper->tryGettingStagingSites();
281
282 if ($sites === false || count($sites) === 0) {
283 return;
284 }
285
286 // Check if key prefix is missing and add it
287 foreach ($sites as $key => $value) {
288 if (empty($sites[$key]['directoryName'])) {
289 continue;
290 }
291
292 !empty($sites[$key]['prefix']) ?
293 $sites[$key]['prefix'] = $value['prefix'] :
294 $sites[$key]['prefix'] = $this->getStagingPrefix($sites[$key]['directoryName']);
295 }
296
297 if (count($sites) > 0) {
298 $this->stagingSitesHelper->updateStagingSites($sites);
299 }
300 }
301
302 /**
303 * Check and return prefix of the staging site
304 * @param string $directory
305 * @return string
306 */
307 private function getStagingPrefix($directory)
308 {
309 // Try to get staging prefix from wp-config.php of staging site
310 $path = ABSPATH . $directory . "/wp-config.php";
311
312 if (($content = @file_get_contents($path)) === false) {
313 $prefix = "";
314 } else {
315 // Get prefix from wp-config.php
316 preg_match("/table_prefix\s*=\s*'(\w*)';/", $content, $matches);
317
318 if (!empty($matches[1])) {
319 $prefix = $matches[1];
320 } else {
321 $prefix = "";
322 }
323 }
324
325 // return result: Check if staging prefix is the same as the live prefix
326 if ($this->db->prefix != $prefix) {
327 return $prefix;
328 } else {
329 return "";
330 }
331 }
332
333 /**
334 * Upgrade method 2.0.3
335 * @return void
336 */
337 public function upgrade2_0_3() // phpcs:ignore
338 {
339 // Previous version lower than 2.0.2
340 if (version_compare($this->previousVersion, '2.0.2', '<')) {
341 $this->initialInstall();
342 $this->upgradeNotices();
343 }
344 }
345
346 /**
347 * Upgrade method 2.1.2
348 * Sanitize the clone key value.
349 * @return void
350 */
351 private function upgrade2_1_2() // phpcs:ignore
352 {
353 if ($this->previousVersion === false || version_compare($this->previousVersion, '2.1.2', '<')) {
354 // Current options
355 $clones = $this->stagingSitesHelper->tryGettingStagingSites();
356
357 foreach ($clones as $key => $value) {
358 unset($clones[$key]);
359 $clones[preg_replace("#\W+#", '-', strtolower($key))] = $value;
360 }
361
362 if (!empty($clones)) {
363 $this->stagingSitesHelper->updateStagingSites($clones);
364 }
365 }
366 }
367
368 /**
369 * Upgrade routine for new install
370 * @return void
371 */
372 private function initialInstall()
373 {
374 // Write some default vars
375 add_option('wpstg_installDate', date('Y-m-d h:i:s')); // Common install date for free or pro version - deprecated. Remove 2023
376 add_option(self::OPTION_INSTALL_DATE, date('Y-m-d h:i:s'));
377 $this->settings->optimizer = "1";
378 update_option('wpstg_settings', $this->settings);
379 }
380
381 /**
382 * Write new version number into db
383 * @return bool
384 */
385 private function setVersion()
386 {
387 // Check if version number in DB is lower than version number in current plugin
388 if (version_compare($this->previousVersion, WPStaging::getVersion(), '<')) {
389 // Update Version number
390 update_option('wpstg_version', preg_replace('/[^0-9.].*/', '', WPStaging::getVersion()));
391 // Update "upgraded from" version number
392 update_option('wpstg_version_upgraded_from', preg_replace('/[^0-9.].*/', '', $this->previousVersion));
393 // Update the time version upgraded at
394 update_option(self::OPTION_UPGRADE_DATE, date('Y-m-d H:i'));
395
396 return true;
397 }
398
399 return false;
400 }
401
402 /**
403 * Upgrade Notices db options from wpstg 1.3 -> 2.0.1
404 * Fix some logical db options
405 * @return void
406 */
407 private function upgradeNotices()
408 {
409 $poll = get_option("wpstg_start_poll", false);
410 $beta = get_option("wpstg_hide_beta", false);
411 $rating = get_option("wpstg_RatingDiv", false);
412
413 if ($beta && $beta === "yes") {
414 update_option('wpstg_beta', 'no');
415 }
416
417 if ($rating && $rating === 'yes') {
418 update_option('wpstg_rating', 'no');
419 }
420 }
421 }
422