WP Staging – DB & File Duplicator & Migration - Version 2.5.6

Version Description

  • New: Compatible to WordPress 5.2
  • New: Allow adding file .wp-staging to root of website to determine if it's a staging or production website
  • New: Add extended data about a staging site in list overview of staging sites
  • New: Show unfinished or interrupted clones and allow deletion of them
  • Tweak: Move admin notices templates to views/notices
  • Fix: Rating notice appears again after using review later button
  • Fix: Can not find staging site when staging site has been created with old version of wp staging
  • Fix: Do not search & replace over incomplete classes in database to prevent warnings
Download this release

Release Info

Developer ReneHermi
Plugin Icon 128x128 WP Staging – DB & File Duplicator & Migration
Version 2.5.6
Comparing to
See all releases

Code changes from version 2.5.5 to 2.5.6

Files changed (27) hide show
  1. apps/Backend/Administrator.php +7 -6
  2. apps/Backend/Modules/Jobs/Cloning.php +64 -11
  3. apps/Backend/Modules/Jobs/Finish.php +3 -1
  4. apps/Backend/Modules/Jobs/Multisite/Finish.php +11 -35
  5. apps/Backend/Modules/Jobs/ProcessLock.php +61 -61
  6. apps/Backend/Modules/Jobs/SearchReplace.php +27 -21
  7. apps/Backend/Modules/Jobs/Updating.php +0 -9
  8. apps/Backend/Modules/SystemInfo.php +1 -1
  9. apps/Backend/Notices/Notices.php +31 -17
  10. apps/Backend/public/js/wpstg-admin-rating.js +7 -7
  11. apps/Backend/views/clone/ajax/single-overview.php +16 -7
  12. apps/Backend/views/{_includes/messages → notices}/beta.php +0 -0
  13. apps/Backend/views/{_includes/messages → notices}/cache-directory-permission-problem.php +0 -0
  14. apps/Backend/views/{_includes/messages → notices}/logs-directory-permission-problem.php +0 -0
  15. apps/Backend/views/{_includes/messages → notices}/poll.php +0 -0
  16. apps/Backend/views/{_includes/messages → notices}/rating.php +0 -0
  17. apps/Backend/views/{_includes/messages → notices}/staging-directory-permission-problem.php +0 -0
  18. apps/Backend/views/{_includes/messages → notices}/transient.php +0 -0
  19. apps/Backend/views/{_includes/messages → notices}/uploads-cache-directory-permission-problem.php +0 -0
  20. apps/Backend/views/{_includes/messages → notices}/vars-directory-permission-problem.php +0 -0
  21. apps/Backend/views/{_includes/messages → notices}/wp-version-compatible-message.php +0 -0
  22. apps/Backend/views/{_includes/messages → notices}/wrong-scheme.php +0 -0
  23. apps/Core/Utils/functions.php +28 -13
  24. apps/Core/WPStaging.php +5 -5
  25. apps/Frontend/Frontend.php +3 -2
  26. readme.txt +18 -4
  27. wp-staging.php +2 -2
apps/Backend/Administrator.php CHANGED
@@ -238,8 +238,8 @@ class Administrator extends InjectionAware {
238
  public function getToolsPage() {
239
  // Tabs
240
  $tabs = new Tabs( array(
241
- "system_info" => __( "System Info", "wp-staging" ),
242
- "import_export" => __( "Import/Export", "wp-staging" )
243
  ) );
244
 
245
  $this->di->set( "tabs", $tabs );
@@ -636,8 +636,8 @@ class Administrator extends InjectionAware {
636
  * @return mixed bool | json
637
  */
638
  public function ajaxHideLaterRating() {
639
- if( false !== update_option( 'wpstg_rating', date( 'Y-m-d' ) )
640
- ) {
641
  wp_send_json( true );
642
  }
643
  return wp_send_json( false );
@@ -695,7 +695,7 @@ class Administrator extends InjectionAware {
695
  }
696
 
697
  /**
698
- * Ajax Start Pushing. Needs wp quads pro
699
  */
700
  public function ajaxPushProcessing() {
701
  check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
@@ -792,7 +792,8 @@ class Administrator extends InjectionAware {
792
  // }
793
  $db->select( $database );
794
  if( !$db->ready ) {
795
- echo json_encode( array('errors' => "Error: Can't select {$database} [" . print_r( $db->error, true ) . "] Either it does not exist or you don't have privileges to access it. ") );
 
796
  exit;
797
  }
798
  echo json_encode( array('success' => 'true') );
238
  public function getToolsPage() {
239
  // Tabs
240
  $tabs = new Tabs( array(
241
+ "import_export" => __( "Import/Export", "wp-staging" ),
242
+ "system_info" => __( "System Info", "wp-staging" )
243
  ) );
244
 
245
  $this->di->set( "tabs", $tabs );
636
  * @return mixed bool | json
637
  */
638
  public function ajaxHideLaterRating() {
639
+ $date = date('Y-m-d', strtotime(date('Y-m-d'). ' + 7 days'));
640
+ if( false !== update_option( 'wpstg_rating',$date )) {
641
  wp_send_json( true );
642
  }
643
  return wp_send_json( false );
695
  }
696
 
697
  /**
698
+ * Ajax Start Pushing. Needs WP Staging Pro
699
  */
700
  public function ajaxPushProcessing() {
701
  check_ajax_referer( "wpstg_ajax_nonce", "nonce" );
792
  // }
793
  $db->select( $database );
794
  if( !$db->ready ) {
795
+ $error = isset($db->error->errors['db_select_fail']) ? $db->error->errors['db_select_fail'] : "Error: Can't select {database} Either it does not exist or you don't have privileges to access it.";
796
+ echo json_encode( array('errors' => $error ) );
797
  exit;
798
  }
799
  echo json_encode( array('success' => 'true') );
apps/Backend/Modules/Jobs/Cloning.php CHANGED
@@ -49,7 +49,8 @@ class Cloning extends Job {
49
  'desktop.ini',
50
  '.gitignore',
51
  '.log',
52
- 'web.config' // Important: Windows IIS configuartion file. Must not be in the staging site!
 
53
  );
54
  $this->options->excludedFilesFullPath = array(
55
  'wp-content' . DIRECTORY_SEPARATOR . 'db.php',
@@ -74,7 +75,7 @@ class Cloning extends Job {
74
  // Get data and increment it
75
  elseif( !empty( $this->options->existingClones ) ) {
76
  $this->options->cloneNumber = count( $this->options->existingClones ) + 1;
77
- $this->options->prefix = $this->setStagingPrefix();
78
  }
79
 
80
  // Included Tables
@@ -86,7 +87,7 @@ class Cloning extends Job {
86
 
87
  // Excluded Directories
88
  if( isset( $_POST["excludedDirectories"] ) && is_array( $_POST["excludedDirectories"] ) ) {
89
- $this->options->excludedDirectories = wpstg_urldecode($_POST["excludedDirectories"]);
90
  }
91
 
92
  // Excluded Directories TOTAL
@@ -99,18 +100,18 @@ class Cloning extends Job {
99
  \WPStaging\WPStaging::getWPpath() . 'wp-content' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'wp-spamshield',
100
  );
101
 
102
- $this->options->excludedDirectories = array_merge( $excludedDirectories, wpstg_urldecode($this->options->excludedDirectories ));
103
 
104
  array_unshift( $this->options->directoriesToCopy, \WPStaging\WPStaging::getWPpath() );
105
 
106
  // Included Directories
107
  if( isset( $_POST["includedDirectories"] ) && is_array( $_POST["includedDirectories"] ) ) {
108
- $this->options->includedDirectories = wpstg_urldecode($_POST["includedDirectories"]);
109
  }
110
 
111
  // Extra Directories
112
  if( isset( $_POST["extraDirectories"] ) && !empty( $_POST["extraDirectories"] ) ) {
113
- $this->options->extraDirectories = wpstg_urldecode($_POST["extraDirectories"]);
114
  }
115
 
116
  // Directories to Copy
@@ -137,11 +138,11 @@ class Cloning extends Job {
137
  }
138
  $this->options->databasePrefix = '';
139
  if( isset( $_POST["databasePrefix"] ) && !empty( $_POST["databasePrefix"] ) ) {
140
- $this->options->databasePrefix = $this->sanitizePrefix( $_POST["databasePrefix"] );
141
  }
142
  $this->options->cloneDir = '';
143
  if( isset( $_POST["cloneDir"] ) && !empty( $_POST["cloneDir"] ) ) {
144
- $this->options->cloneDir = wpstg_urldecode(trailingslashit( $_POST["cloneDir"] ));
145
  }
146
  $this->options->cloneHostname = '';
147
  if( isset( $_POST["cloneHostname"] ) && !empty( $_POST["cloneHostname"] ) ) {
@@ -157,9 +158,61 @@ class Cloning extends Job {
157
  // Process lock state
158
  $this->options->isRunning = true;
159
 
 
 
 
 
160
  return $this->saveOptions();
161
  }
162
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  /**
164
  * Return target hostname
165
  * @return string
@@ -187,7 +240,7 @@ class Cloning extends Job {
187
  */
188
  private function getDestinationDir() {
189
  // No custom clone dir or clone dir equals abspath of main wordpress site
190
- if( empty( $this->options->cloneDir ) || $this->options->cloneDir == (string)\WPStaging\WPStaging::getWPpath()) {
191
  return trailingslashit( \WPStaging\WPStaging::getWPpath() . $this->options->cloneDirectoryName );
192
  }
193
  return trailingslashit( $this->options->cloneDir );
@@ -224,7 +277,7 @@ class Cloning extends Job {
224
 
225
  // Prefix does not exist. We can use it
226
  if( !$tables ) {
227
- return $this->options->prefix;
228
  }
229
  }
230
  $this->returnException( "Fatal Error: Can not create staging prefix. '{$this->options->prefix}' already exists! Stopping for security reasons. Contact support@wp-staging.com" );
@@ -251,7 +304,7 @@ class Cloning extends Job {
251
  * Start the cloning job
252
  */
253
  public function start() {
254
- if( !property_exists($this->options, 'currentJob') || null === $this->options->currentJob ) {
255
  $this->log( "Cloning job finished" );
256
  return true;
257
  }
49
  'desktop.ini',
50
  '.gitignore',
51
  '.log',
52
+ 'web.config', // Important: Windows IIS configuration file. Must not be in the staging site!
53
+ '.wp-staging' // Determines if a site is a staging site
54
  );
55
  $this->options->excludedFilesFullPath = array(
56
  'wp-content' . DIRECTORY_SEPARATOR . 'db.php',
75
  // Get data and increment it
76
  elseif( !empty( $this->options->existingClones ) ) {
77
  $this->options->cloneNumber = count( $this->options->existingClones ) + 1;
78
+ //$this->options->prefix = $this->setStagingPrefix();
79
  }
80
 
81
  // Included Tables
87
 
88
  // Excluded Directories
89
  if( isset( $_POST["excludedDirectories"] ) && is_array( $_POST["excludedDirectories"] ) ) {
90
+ $this->options->excludedDirectories = wpstg_urldecode( $_POST["excludedDirectories"] );
91
  }
92
 
93
  // Excluded Directories TOTAL
100
  \WPStaging\WPStaging::getWPpath() . 'wp-content' . DIRECTORY_SEPARATOR . 'plugins' . DIRECTORY_SEPARATOR . 'wp-spamshield',
101
  );
102
 
103
+ $this->options->excludedDirectories = array_merge( $excludedDirectories, wpstg_urldecode( $this->options->excludedDirectories ) );
104
 
105
  array_unshift( $this->options->directoriesToCopy, \WPStaging\WPStaging::getWPpath() );
106
 
107
  // Included Directories
108
  if( isset( $_POST["includedDirectories"] ) && is_array( $_POST["includedDirectories"] ) ) {
109
+ $this->options->includedDirectories = wpstg_urldecode( $_POST["includedDirectories"] );
110
  }
111
 
112
  // Extra Directories
113
  if( isset( $_POST["extraDirectories"] ) && !empty( $_POST["extraDirectories"] ) ) {
114
+ $this->options->extraDirectories = wpstg_urldecode( $_POST["extraDirectories"] );
115
  }
116
 
117
  // Directories to Copy
138
  }
139
  $this->options->databasePrefix = '';
140
  if( isset( $_POST["databasePrefix"] ) && !empty( $_POST["databasePrefix"] ) ) {
141
+ $this->options->databasePrefix = strtolower( $this->sanitizePrefix( $_POST["databasePrefix"] ) );
142
  }
143
  $this->options->cloneDir = '';
144
  if( isset( $_POST["cloneDir"] ) && !empty( $_POST["cloneDir"] ) ) {
145
+ $this->options->cloneDir = wpstg_urldecode( trailingslashit( $_POST["cloneDir"] ) );
146
  }
147
  $this->options->cloneHostname = '';
148
  if( isset( $_POST["cloneHostname"] ) && !empty( $_POST["cloneHostname"] ) ) {
158
  // Process lock state
159
  $this->options->isRunning = true;
160
 
161
+
162
+ // Save Clone data
163
+ $this->saveClone();
164
+
165
  return $this->saveOptions();
166
  }
167
 
168
+ /**
169
+ * Save clone data initially
170
+ * @return boolean
171
+ */
172
+ private function saveClone(){
173
+ // Save new clone data
174
+ $this->log( "Cloning: {$this->options->clone}'s clone job's data is not in database, generating data" );
175
+
176
+ $this->options->existingClones[$this->options->clone] = array(
177
+ "directoryName" => $this->options->cloneDirectoryName,
178
+ "path" => trailingslashit( $this->options->destinationDir ),
179
+ "url" => $this->getDestinationUrl(),
180
+ "number" => $this->options->cloneNumber,
181
+ "version" => \WPStaging\WPStaging::VERSION,
182
+ //"status" => false,
183
+ "status" => "unfinished or broken",
184
+ "prefix" => $this->options->prefix,
185
+ "datetime" => time(),
186
+ "databaseUser" => $this->options->databaseUser,
187
+ "databasePassword" => $this->options->databasePassword,
188
+ "databaseDatabase" => $this->options->databaseDatabase,
189
+ "databaseServer" => $this->options->databaseServer,
190
+ "databasePrefix" => $this->options->databasePrefix
191
+ );
192
+
193
+ if( false === update_option( "wpstg_existing_clones_beta", $this->options->existingClones ) ) {
194
+ $this->log( "Cloning: Failed to save {$this->options->clone}'s clone job data to database'" );
195
+ return false;
196
+ }
197
+
198
+ return true;
199
+ }
200
+
201
+
202
+ /**
203
+ * Get destination Hostname depending on wheather WP has been installed in sub dir or not
204
+ * @return type
205
+ */
206
+ private function getDestinationUrl() {
207
+
208
+ if( !empty( $this->options->cloneHostname ) ) {
209
+ return $this->options->cloneHostname;
210
+ }
211
+
212
+ return trailingslashit( get_site_url() ) . $this->options->cloneDirectoryName;
213
+ }
214
+
215
+
216
  /**
217
  * Return target hostname
218
  * @return string
240
  */
241
  private function getDestinationDir() {
242
  // No custom clone dir or clone dir equals abspath of main wordpress site
243
+ if( empty( $this->options->cloneDir ) || $this->options->cloneDir == ( string ) \WPStaging\WPStaging::getWPpath() ) {
244
  return trailingslashit( \WPStaging\WPStaging::getWPpath() . $this->options->cloneDirectoryName );
245
  }
246
  return trailingslashit( $this->options->cloneDir );
277
 
278
  // Prefix does not exist. We can use it
279
  if( !$tables ) {
280
+ return strtolower( $this->options->prefix );
281
  }
282
  }
283
  $this->returnException( "Fatal Error: Can not create staging prefix. '{$this->options->prefix}' already exists! Stopping for security reasons. Contact support@wp-staging.com" );
304
  * Start the cloning job
305
  */
306
  public function start() {
307
+ if( !property_exists( $this->options, 'currentJob' ) || null === $this->options->currentJob ) {
308
  $this->log( "Cloning job finished" );
309
  return true;
310
  }
apps/Backend/Modules/Jobs/Finish.php CHANGED
@@ -74,6 +74,7 @@ class Finish extends Job {
74
  // Clone data already exists
75
  if( isset( $this->options->existingClones[$this->options->clone] ) ) {
76
  $this->options->existingClones[$this->options->clone]['datetime'] = time();
 
77
  update_option( "wpstg_existing_clones_beta", $this->options->existingClones );
78
  $this->log( "Finish: The job finished!" );
79
  return true;
@@ -91,7 +92,8 @@ class Finish extends Job {
91
  "url" => $this->getDestinationUrl(),
92
  "number" => $this->options->cloneNumber,
93
  "version" => \WPStaging\WPStaging::VERSION,
94
- "status" => false,
 
95
  "prefix" => $this->options->prefix,
96
  "datetime" => time(),
97
  "databaseUser" => $this->options->databaseUser,
74
  // Clone data already exists
75
  if( isset( $this->options->existingClones[$this->options->clone] ) ) {
76
  $this->options->existingClones[$this->options->clone]['datetime'] = time();
77
+ $this->options->existingClones[$this->options->clone]['status'] = 'finished';
78
  update_option( "wpstg_existing_clones_beta", $this->options->existingClones );
79
  $this->log( "Finish: The job finished!" );
80
  return true;
92
  "url" => $this->getDestinationUrl(),
93
  "number" => $this->options->cloneNumber,
94
  "version" => \WPStaging\WPStaging::VERSION,
95
+ //"status" => false,
96
+ "status" => "finished",
97
  "prefix" => $this->options->prefix,
98
  "datetime" => time(),
99
  "databaseUser" => $this->options->databaseUser,
apps/Backend/Modules/Jobs/Multisite/Finish.php CHANGED
@@ -32,6 +32,8 @@ class Finish extends Job {
32
  // Prepare clone records & save scanned directories for delete job later
33
  $this->prepareCloneDataRecords();
34
 
 
 
35
  $multisite = new Multisite;
36
 
37
 
@@ -79,6 +81,7 @@ class Finish extends Job {
79
  if( isset( $this->options->existingClones[$this->options->clone] ) ) {
80
  $this->options->existingClones[$this->options->clone]['datetime'] = time();
81
  $this->options->existingClones[$this->options->clone]['url'] = $this->getDestinationUrl();
 
82
  update_option( "wpstg_existing_clones_beta", $this->options->existingClones );
83
  $this->log( "Finish: The job finished!" );
84
  return true;
@@ -96,7 +99,7 @@ class Finish extends Job {
96
  "url" => $this->getDestinationUrl(),
97
  "number" => $this->options->cloneNumber,
98
  "version" => \WPStaging\WPStaging::VERSION,
99
- "status" => false,
100
  "prefix" => $this->options->prefix,
101
  "datetime" => time(),
102
  "databaseUser" => $this->options->databaseUser,
@@ -114,7 +117,6 @@ class Finish extends Job {
114
  return true;
115
  }
116
 
117
-
118
  /**
119
  * Get destination Hostname depending on wheather WP has been installed in sub dir or not
120
  * @return type
@@ -125,39 +127,13 @@ class Finish extends Job {
125
  return $this->options->cloneHostname;
126
  }
127
 
128
- return trailingslashit( $this->multisiteHomeDomain ) . $this->options->cloneDirectoryName;
129
- }
 
 
 
130
 
131
- /**
132
- * Check if WP is installed in subdir
133
- * @return boolean
134
- */
135
- // private function isSubDir() {
136
- // // Compare names without scheme to bypass cases where siteurl and home have different schemes http / https
137
- // // This is happening much more often than you would expect
138
- // $siteurl = preg_replace( '#^https?://#', '', rtrim( get_option( 'siteurl' ), '/' ) );
139
- // $home = preg_replace( '#^https?://#', '', rtrim( get_option( 'home' ), '/' ) );
140
- //
141
- // if( $home !== $siteurl ) {
142
- // return true;
143
- // }
144
- // return false;
145
- // }
146
-
147
- /**
148
- * Get the install sub directory if WP is installed in sub directory
149
- * @return string
150
- */
151
- // private function getSubDir() {
152
- // $home = get_option( 'home' );
153
- // $siteurl = get_option( 'siteurl' );
154
- //
155
- // if( empty( $home ) || empty( $siteurl ) ) {
156
- // return '';
157
- // }
158
- //
159
- // $dir = str_replace( $home, '', $siteurl );
160
- // return str_replace( '/', '', $dir );
161
- // }
162
 
163
  }
32
  // Prepare clone records & save scanned directories for delete job later
33
  $this->prepareCloneDataRecords();
34
 
35
+ $this->options->isRunning = false;
36
+
37
  $multisite = new Multisite;
38
 
39
 
81
  if( isset( $this->options->existingClones[$this->options->clone] ) ) {
82
  $this->options->existingClones[$this->options->clone]['datetime'] = time();
83
  $this->options->existingClones[$this->options->clone]['url'] = $this->getDestinationUrl();
84
+ $this->options->existingClones[$this->options->clone]['status'] = 'finished';
85
  update_option( "wpstg_existing_clones_beta", $this->options->existingClones );
86
  $this->log( "Finish: The job finished!" );
87
  return true;
99
  "url" => $this->getDestinationUrl(),
100
  "number" => $this->options->cloneNumber,
101
  "version" => \WPStaging\WPStaging::VERSION,
102
+ "status" => "finished",
103
  "prefix" => $this->options->prefix,
104
  "datetime" => time(),
105
  "databaseUser" => $this->options->databaseUser,
117
  return true;
118
  }
119
 
 
120
  /**
121
  * Get destination Hostname depending on wheather WP has been installed in sub dir or not
122
  * @return type
127
  return $this->options->cloneHostname;
128
  }
129
 
130
+ //return trailingslashit( $this->multisiteHomeDomain ) . $this->options->cloneDirectoryName;
131
+ // Get the path to the main multisite without appending and trailingslash e.g. wordpress
132
+ $multisitePath = defined( 'PATH_CURRENT_SITE') ? PATH_CURRENT_SITE : '/';
133
+ return rtrim( $this->multisiteHomeDomain, '/\\' ) . $multisitePath . $this->options->cloneDirectoryName;
134
+ //$multisitePath = defined( 'PATH_CURRENT_SITE' ) ? str_replace( '/', '', PATH_CURRENT_SITE ) : '';
135
 
136
+ //return trailingslashit( $this->multisiteHomeDomain ) . $multisitePath . '/' . $this->options->cloneDirectoryName;
137
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
 
139
  }
apps/Backend/Modules/Jobs/ProcessLock.php CHANGED
@@ -1,61 +1,61 @@
1
- <?php
2
-
3
- namespace WPStaging\Backend\Modules\Jobs;
4
-
5
- use WPStaging\WPStaging;
6
-
7
- //use WPStaging\Utils\Cache;
8
-
9
- /**
10
- * Class Cloning
11
- * @package WPStaging\Backend\Modules\Jobs
12
- */
13
- class ProcessLock extends JobExecutable {
14
-
15
- /**
16
- * Check if any process is already running
17
- * @return boolean
18
- */
19
- public function isRunning() {
20
- // Another process is running
21
- if( isset( $this->options->isRunning ) ) {
22
-
23
- $this->log( "Another process is running" );
24
-
25
- $message = __( 'Hold on, another WP Staging process is already running...', 'wp-staging' );
26
-
27
- require_once WPSTG_PLUGIN_DIR . "apps/Backend/views/clone/ajax/process-lock.php";
28
-
29
- wp_die();
30
- }
31
- // No other process running
32
-
33
- return false;
34
- }
35
-
36
- /**
37
- * remove process lock value
38
- */
39
- public function restart() {
40
- unset( $this->options->isRunning );
41
- $this->cache->delete( "clone_options" );
42
- $this->cache->delete( "files_to_copy" );
43
- }
44
-
45
- /**
46
- * abstract
47
- * @return void
48
- */
49
- protected function calculateTotalSteps() {
50
-
51
- }
52
-
53
- /**
54
- * abstract
55
- * @return bool
56
- */
57
- protected function execute() {
58
-
59
- }
60
-
61
- }
1
+ <?php
2
+
3
+ namespace WPStaging\Backend\Modules\Jobs;
4
+
5
+ use WPStaging\WPStaging;
6
+
7
+ //use WPStaging\Utils\Cache;
8
+
9
+ /**
10
+ * Class Cloning
11
+ * @package WPStaging\Backend\Modules\Jobs
12
+ */
13
+ class ProcessLock extends JobExecutable {
14
+
15
+ /**
16
+ * Check if any process is already running
17
+ * @return boolean
18
+ */
19
+ public function isRunning() {
20
+ // Another process is running
21
+ if( isset( $this->options->isRunning ) ) {
22
+
23
+ $this->log( "Another process is running" );
24
+
25
+ $message = __( 'Hold on, another WP Staging process is already running...', 'wp-staging' );
26
+
27
+ require_once WPSTG_PLUGIN_DIR . "apps/Backend/views/clone/ajax/process-lock.php";
28
+
29
+ wp_die();
30
+ }
31
+ // No other process running
32
+
33
+ return false;
34
+ }
35
+
36
+ /**
37
+ * remove process lock value
38
+ */
39
+ public function restart() {
40
+ unset( $this->options->isRunning );
41
+ $this->cache->delete( "clone_options" );
42
+ $this->cache->delete( "files_to_copy" );
43
+ }
44
+
45
+ /**
46
+ * abstract
47
+ * @return void
48
+ */
49
+ protected function calculateTotalSteps() {
50
+
51
+ }
52
+
53
+ /**
54
+ * abstract
55
+ * @return bool
56
+ */
57
+ protected function execute() {
58
+
59
+ }
60
+
61
+ }
apps/Backend/Modules/Jobs/SearchReplace.php CHANGED
@@ -514,6 +514,12 @@ class SearchReplace extends JobExecutable {
514
  $data = $tmp;
515
  unset( $tmp );
516
  } elseif( is_object( $data ) ) {
 
 
 
 
 
 
517
  $tmp = $data;
518
  $props = get_object_vars( $data );
519
  foreach ( $props as $key => $value ) {
@@ -548,27 +554,27 @@ class SearchReplace extends JobExecutable {
548
  * Can not use is_object alone because in php 7.2 it's returning true even though object is __PHP_Incomplete_Class_Name
549
  * @return boolean
550
  */
551
- // private function isValidObject($data){
552
- // if( !is_object( $data ) || gettype( $data ) != 'object' ) {
553
- // return false;
554
- // }
555
- //
556
- // $invalid_class_props = get_object_vars( $data );
557
- //
558
- // if (!isset($invalid_class_props['__PHP_Incomplete_Class_Name'])){
559
- // // Assume it must be an valid object
560
- // return true;
561
- // }
562
- //
563
- // $invalid_object_class = $invalid_class_props['__PHP_Incomplete_Class_Name'];
564
- //
565
- // if( !empty( $invalid_object_class ) ) {
566
- // return false;
567
- // }
568
- //
569
- // // Assume it must be an valid object
570
- // return true;
571
- // }
572
 
573
  /**
574
  * Mimics the mysql_real_escape_string function. Adapted from a post by 'feedr' on php.net.
514
  $data = $tmp;
515
  unset( $tmp );
516
  } elseif( is_object( $data ) ) {
517
+
518
+ // Is no valid or is incomplete object
519
+ if (!$this->isValidObject($data)){
520
+ return $data;
521
+ }
522
+
523
  $tmp = $data;
524
  $props = get_object_vars( $data );
525
  foreach ( $props as $key => $value ) {
554
  * Can not use is_object alone because in php 7.2 it's returning true even though object is __PHP_Incomplete_Class_Name
555
  * @return boolean
556
  */
557
+ private function isValidObject($data){
558
+ if( !is_object( $data ) || gettype( $data ) != 'object' ) {
559
+ return false;
560
+ }
561
+
562
+ $invalid_class_props = get_object_vars( $data );
563
+
564
+ if (!isset($invalid_class_props['__PHP_Incomplete_Class_Name'])){
565
+ // Assume it must be an valid object
566
+ return true;
567
+ }
568
+
569
+ $invalid_object_class = $invalid_class_props['__PHP_Incomplete_Class_Name'];
570
+
571
+ if( !empty( $invalid_object_class ) ) {
572
+ return false;
573
+ }
574
+
575
+ // Assume it must be an valid object
576
+ return true;
577
+ }
578
 
579
  /**
580
  * Mimics the mysql_real_escape_string function. Adapted from a post by 'feedr' on php.net.
apps/Backend/Modules/Jobs/Updating.php CHANGED
@@ -2,14 +2,7 @@
2
 
3
  namespace WPStaging\Backend\Modules\Jobs;
4
 
5
- //use WPStaging\Backend\Modules\Jobs\Exceptions\JobNotFoundException;
6
  use WPStaging\WPStaging;
7
- //use WPStaging\Backend\Modules\Jobs\Multisite\Database as muDatabase;
8
- //use WPStaging\Backend\Modules\Jobs\Multisite\SearchReplace as muSearchReplace;
9
- //use WPStaging\Backend\Modules\Jobs\Multisite\Data as muData;
10
- //use WPStaging\Backend\Modules\Jobs\Multisite\Finish as muFinish;
11
- //use WPStaging\Backend\Modules\Jobs\Multisite\Directories as muDirectories;
12
- //use WPStaging\Backend\Modules\Jobs\Multisite\Files as muFiles;
13
  use WPStaging\Utils\Helper;
14
 
15
  /**
@@ -133,8 +126,6 @@ class Updating extends Job {
133
  $this->options->cloneDir = wpstg_urldecode(trailingslashit( $_POST["cloneDir"] ));
134
  }
135
 
136
- //$this->options->destinationDir = !empty( $this->options->cloneDir ) ? trailingslashit( $this->options->cloneDir ) : trailingslashit( $this->options->existingClones[$this->options->clone]['path'] );
137
-
138
  $this->options->destinationDir = $this->getDestinationDir();
139
 
140
  $this->options->cloneHostname = '';
2
 
3
  namespace WPStaging\Backend\Modules\Jobs;
4
 
 
5
  use WPStaging\WPStaging;
 
 
 
 
 
 
6
  use WPStaging\Utils\Helper;
7
 
8
  /**
126
  $this->options->cloneDir = wpstg_urldecode(trailingslashit( $_POST["cloneDir"] ));
127
  }
128
 
 
 
129
  $this->options->destinationDir = $this->getDestinationDir();
130
 
131
  $this->options->cloneHostname = '';
apps/Backend/Modules/SystemInfo.php CHANGED
@@ -200,7 +200,7 @@ class SystemInfo extends InjectionAware {
200
  $output .= $this->info( "Plugin Version:", get_option( 'wpstg_version', 'undefined' ) );
201
  $output .= $this->info( "Install Date:", get_option( 'wpstg_installDate', 'undefined' ) );
202
  $output .= $this->info( "Upgraded from:", get_option( 'wpstg_version_upgraded_from', 'undefined' ) );
203
- $output .= $this->info( "Is Staging Site:", get_option( 'wpstg_is_staging_site', 'undefined' ) ) . PHP_EOL . PHP_EOL;
204
 
205
 
206
  return apply_filters( "wpstg_sysinfo_after_wpstaging_info", $output );
200
  $output .= $this->info( "Plugin Version:", get_option( 'wpstg_version', 'undefined' ) );
201
  $output .= $this->info( "Install Date:", get_option( 'wpstg_installDate', 'undefined' ) );
202
  $output .= $this->info( "Upgraded from:", get_option( 'wpstg_version_upgraded_from', 'undefined' ) );
203
+ $output .= $this->info( "Is Staging Site:", wpstg_is_stagingsite() ? 'true' : 'false' ) . PHP_EOL . PHP_EOL;
204
 
205
 
206
  return apply_filters( "wpstg_sysinfo_after_wpstaging_info", $output );
apps/Backend/Notices/Notices.php CHANGED
@@ -35,7 +35,7 @@ class Notices {
35
  }
36
 
37
  /**
38
- * Check whether the page is an WP QUADS admin settings page or not
39
  * @return bool
40
  */
41
  private function isAdminPage() {
@@ -60,33 +60,43 @@ class Notices {
60
  */
61
  private function canShow( $option, $days = 10 ) {
62
 
 
63
  if( empty( $option ) ) {
64
  return false;
65
  }
66
 
67
  $dbOption = get_option( $option );
 
 
 
 
 
68
 
69
  $now = new \DateTime( "now" );
70
 
71
-
72
- // Check if user clicked on "rate later" button
73
- if( "no" !== $dbOption && wpstg_validate_date( $dbOption ) ) {
74
  // Get days difference
75
- $hideDate = new \DateTime( $dbOption );
76
- $difference = $now->diff( $hideDate )->days;
77
-
78
- if( $days <= $difference )
79
- return true;
 
 
 
 
 
80
  }
81
 
82
 
83
  // Show X days after installation
84
  $installDate = new \DateTime( get_option( "wpstg_installDate" ) );
85
 
86
- // Get days difference
87
  $difference = $now->diff( $installDate )->days;
88
 
89
- if( $days <= $difference && "no" !== $dbOption ) {
90
  return true;
91
  }
92
 
@@ -103,21 +113,25 @@ class Notices {
103
  }
104
  }
105
 
 
 
 
 
106
  public function messages() {
107
 
108
- $viewsNoticesPath = "{$this->path}views/_includes/messages/";
109
 
110
  // Show notice when free and pro version have been activated at the same time
111
  $this->plugin_deactivated_notice();
112
 
113
 
114
- // Show rating review message on all admin pages
115
  if( $this->canShow( "wpstg_rating", 7 ) && $this->getCurrentScreen() !== 'page' && $this->getCurrentScreen() !== 'post' ) {
116
  require_once "{$viewsNoticesPath}rating.php";
117
  }
118
 
119
 
120
- // Display messages below to admins only, only on admin panel
121
  if( !current_user_can( "update_plugins" ) || !$this->isAdminPage() ) {
122
  return;
123
  }
@@ -148,9 +162,9 @@ class Notices {
148
  delete_transient( "wp_staging_deactivated_notice_id" );
149
  }
150
  // Rating
151
- if( $this->canShow( "wpstg_rating", 7 ) ) {
152
- require_once "{$viewsNoticesPath}rating.php";
153
- }
154
 
155
  // Different scheme in home and siteurl
156
  if( $this->isDifferentScheme() ) {
35
  }
36
 
37
  /**
38
+ * Check whether the page is admin page or not
39
  * @return bool
40
  */
41
  private function isAdminPage() {
60
  */
61
  private function canShow( $option, $days = 10 ) {
62
 
63
+ // Do not show notice
64
  if( empty( $option ) ) {
65
  return false;
66
  }
67
 
68
  $dbOption = get_option( $option );
69
+
70
+ // Do not show notice
71
+ if ("no" === $dbOption){
72
+ return false;
73
+ }
74
 
75
  $now = new \DateTime( "now" );
76
 
77
+ // Check if user clicked on "rate later" button and if there is a valid 'later' date
78
+ if( wpstg_is_valid_date( $dbOption ) ) {
 
79
  // Get days difference
80
+ // $hideDate = new \DateTime( $dbOption );
81
+ // $difference = $now->diff( $hideDate )->days;
82
+ //
83
+ // if( $days >= $difference )
84
+ // return true;
85
+ // Do not show before this date
86
+ $show = new \DateTime( $dbOption );
87
+ if ($now < $show){
88
+ return false;
89
+ }
90
  }
91
 
92
 
93
  // Show X days after installation
94
  $installDate = new \DateTime( get_option( "wpstg_installDate" ) );
95
 
96
+ // get number of days between installation date and today
97
  $difference = $now->diff( $installDate )->days;
98
 
99
+ if( $days <= $difference ) {
100
  return true;
101
  }
102
 
113
  }
114
  }
115
 
116
+ /**
117
+ * Load admin notices
118
+ * @return string
119
+ */
120
  public function messages() {
121
 
122
+ $viewsNoticesPath = "{$this->path}views/notices/";
123
 
124
  // Show notice when free and pro version have been activated at the same time
125
  $this->plugin_deactivated_notice();
126
 
127
 
128
+ // Show rating review message on all admin pages except pages and posts
129
  if( $this->canShow( "wpstg_rating", 7 ) && $this->getCurrentScreen() !== 'page' && $this->getCurrentScreen() !== 'post' ) {
130
  require_once "{$viewsNoticesPath}rating.php";
131
  }
132
 
133
 
134
+ // Display notices below to admins only, only on admin panel
135
  if( !current_user_can( "update_plugins" ) || !$this->isAdminPage() ) {
136
  return;
137
  }
162
  delete_transient( "wp_staging_deactivated_notice_id" );
163
  }
164
  // Rating
165
+ // if( $this->canShow( "wpstg_rating", 7 ) ) {
166
+ // require_once "{$viewsNoticesPath}rating.php";
167
+ // }
168
 
169
  // Different scheme in home and siteurl
170
  if( $this->isDifferentScheme() ) {
apps/Backend/public/js/wpstg-admin-rating.js CHANGED
@@ -1,4 +1,5 @@
1
  jQuery(document).ready(function ($) {
 
2
  $(".wpstg_hide_rating").click(function (e) {
3
  e.preventDefault();
4
 
@@ -10,9 +11,8 @@ jQuery(document).ready(function ($) {
10
  console.log(xhr.status + ' ' + xhr.statusText + '---' + textStatus);
11
  console.log(textStatus);
12
 
13
-
14
  alert(
15
- "Unknown error"
16
  );
17
  },
18
  success: function (data) {
@@ -21,10 +21,10 @@ jQuery(document).ready(function ($) {
21
  },
22
  statusCode: {
23
  404: function () {
24
- alert("Something went wrong; can't find ajax request URL!");
25
  },
26
  500: function () {
27
- alert("Something went wrong; internal server error while processing the request!");
28
  }
29
  }
30
  });
@@ -43,7 +43,7 @@ jQuery(document).ready(function ($) {
43
 
44
 
45
  alert(
46
- "Unknown error"
47
  );
48
  },
49
  success: function (data) {
@@ -52,10 +52,10 @@ jQuery(document).ready(function ($) {
52
  },
53
  statusCode: {
54
  404: function () {
55
- alert("Something went wrong; can't find ajax request URL!");
56
  },
57
  500: function () {
58
- alert("Something went wrong; internal server error while processing the request!");
59
  }
60
  }
61
  });
1
  jQuery(document).ready(function ($) {
2
+
3
  $(".wpstg_hide_rating").click(function (e) {
4
  e.preventDefault();
5
 
11
  console.log(xhr.status + ' ' + xhr.statusText + '---' + textStatus);
12
  console.log(textStatus);
13
 
 
14
  alert(
15
+ "Unknown error. Please get in contact with us to solve it support@wp-staging.com"
16
  );
17
  },
18
  success: function (data) {
21
  },
22
  statusCode: {
23
  404: function () {
24
+ alert("Something went wrong; can't find ajax request URL! Please get in contact with us to solve it support@wp-staging.com");
25
  },
26
  500: function () {
27
+ alert("Something went wrong; internal server error while processing the request! Please get in contact with us to solve it support@wp-staging.com");
28
  }
29
  }
30
  });
43
 
44
 
45
  alert(
46
+ "Unknown error. Please get in contact with us to solve it support@wp-staging.com"
47
  );
48
  },
49
  success: function (data) {
52
  },
53
  statusCode: {
54
  404: function () {
55
+ alert("Something went wrong; can't find ajax request URL! Please get in contact with us to solve it support@wp-staging.com");
56
  },
57
  500: function () {
58
+ alert("Something went wrong; internal server error while processing the request! Please get in contact with us to solve it support@wp-staging.com");
59
  }
60
  }
61
  });
apps/Backend/views/clone/ajax/single-overview.php CHANGED
@@ -37,16 +37,25 @@
37
 
38
  <?php echo apply_filters("wpstg_after_stage_buttons", $html = '', $name, $data)?>
39
  <div class="wpstg-staging-info">
40
- <?php
41
- $prefix = !empty ($data['prefix']) ? __("DB Prefix: <span class='wpstg-bold'>" . $data['prefix'], "wp-staging") . '</span> ' : '&nbsp;&nbsp;&nbsp;';
 
 
 
 
 
 
 
 
42
  echo $prefix;
43
  echo '</br>';
44
- $dbname = !empty ($data['databaseDatabase']) ? __("DB Name: <span class='wpstg-bold'>" . $data['databaseDatabase'], "wp-staging") . '</span></br> ' : '';
45
- echo $dbname;
46
- $datetime = !empty ($data['datetime']) ? __("Updated: <span>" . date("D, d M Y H:i:s T",$data['datetime']) , "wp-staging") . '</span> ' : '&nbsp;&nbsp;&nbsp;';
 
 
 
47
  echo $datetime;
48
-
49
-
50
  ?>
51
  </div>
52
  </div>
37
 
38
  <?php echo apply_filters("wpstg_after_stage_buttons", $html = '', $name, $data)?>
39
  <div class="wpstg-staging-info">
40
+ <?php
41
+ $dbname = !empty( $data['databaseDatabase'] ) ? __( "Database: <span class='wpstg-bold'>" . $data['databaseDatabase'], "wp-staging" ) . '</span>' : 'Database: <span class="wpstg-bold">' . DB_NAME . '</span>';
42
+ $prefix = !empty( $data['prefix'] ) ? __( "Database Prefix: <span class='wpstg-bold'>" . $data['prefix'], "wp-staging" ) . '</span> ' : '';
43
+ $cloneDir = !empty( $data['path'] ) ? __( "Directory: <span class='wpstg-bold'>" . $data['path'], "wp-staging" ) . '</span> ' : 'Directory: ';
44
+ $url = !empty( $data['url'] ) ? __( "URL: <span class='wpstg-bold'>" . $data['url'], "wp-staging" ) . '</span> ' : 'URL: ';
45
+ $datetime = !empty( $data['datetime'] ) ? __( "Updated: <span>" . date( "D, d M Y H:i:s T", $data['datetime'] ), "wp-staging" ) . '</span> ' : '&nbsp;&nbsp;&nbsp;';
46
+ $status = !empty( $data['status'] ) && $data['status'] !== 'finished' ? "Status: <span class='wpstg-bold'>" . $data['status'] . "</span>" : '&nbsp;&nbsp;&nbsp;';
47
+
48
+ echo $dbname;
49
+ echo '</br>';
50
  echo $prefix;
51
  echo '</br>';
52
+ echo $cloneDir;
53
+ echo '</br>';
54
+ echo $url;
55
+ echo '</br>';
56
+ echo $status;
57
+ echo '</br>';
58
  echo $datetime;
 
 
59
  ?>
60
  </div>
61
  </div>
apps/Backend/views/{_includes/messages → notices}/beta.php RENAMED
File without changes
apps/Backend/views/{_includes/messages → notices}/cache-directory-permission-problem.php RENAMED
File without changes
apps/Backend/views/{_includes/messages → notices}/logs-directory-permission-problem.php RENAMED
File without changes
apps/Backend/views/{_includes/messages → notices}/poll.php RENAMED
File without changes
apps/Backend/views/{_includes/messages → notices}/rating.php RENAMED
File without changes
apps/Backend/views/{_includes/messages → notices}/staging-directory-permission-problem.php RENAMED
File without changes
apps/Backend/views/{_includes/messages → notices}/transient.php RENAMED
File without changes
apps/Backend/views/{_includes/messages → notices}/uploads-cache-directory-permission-problem.php RENAMED
File without changes
apps/Backend/views/{_includes/messages → notices}/vars-directory-permission-problem.php RENAMED
File without changes
apps/Backend/views/{_includes/messages → notices}/wp-version-compatible-message.php RENAMED
File without changes
apps/Backend/views/{_includes/messages → notices}/wrong-scheme.php RENAMED
File without changes
apps/Core/Utils/functions.php CHANGED
@@ -128,7 +128,7 @@ function wpstg_replace_last_match( $needle, $replace, $haystack ) {
128
  * @param type $format
129
  * @return bool
130
  */
131
- function wpstg_validate_date( $date, $format = 'Y-m-d' ) {
132
  $d = DateTime::createFromFormat( $format, $date );
133
  // The Y ( 4 digits year ) returns TRUE for any integer with any number of digits so changing the comparison from == to === fixes the issue.
134
  return $d && $d->format( $format ) === $date;
@@ -140,23 +140,38 @@ function wpstg_validate_date( $date, $format = 'Y-m-d' ) {
140
  * @param miced string | array $data
141
  * @return mixed string | array
142
  */
143
- function wpstg_urldecode($data){
144
- if (empty($data)){
145
  return $data;
146
  }
147
-
148
- if ( is_string( $data)){
149
- return urldecode($data);
150
  }
151
-
152
- if( is_array( $data )){
153
  $array = array();
154
- foreach ($data as $string){
155
- $array[] = urldecode($string);
156
- }
157
  return $array;
158
  }
159
-
160
  return $data;
161
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  }
128
  * @param type $format
129
  * @return bool
130
  */
131
+ function wpstg_is_valid_date( $date, $format = 'Y-m-d' ) {
132
  $d = DateTime::createFromFormat( $format, $date );
133
  // The Y ( 4 digits year ) returns TRUE for any integer with any number of digits so changing the comparison from == to === fixes the issue.
134
  return $d && $d->format( $format ) === $date;
140
  * @param miced string | array $data
141
  * @return mixed string | array
142
  */
143
+ function wpstg_urldecode( $data ) {
144
+ if( empty( $data ) ) {
145
  return $data;
146
  }
147
+
148
+ if( is_string( $data ) ) {
149
+ return urldecode( $data );
150
  }
151
+
152
+ if( is_array( $data ) ) {
153
  $array = array();
154
+ foreach ( $data as $string ) {
155
+ $array[] = urldecode( $string );
156
+ }
157
  return $array;
158
  }
159
+
160
  return $data;
161
+ }
162
+
163
+ /**
164
+ * Check if it is a staging site
165
+ * @return bool
166
+ */
167
+ function wpstg_is_stagingsite() {
168
+ if( "true" === get_option( "wpstg_is_staging_site" ) ) {
169
+ return true;
170
+ }
171
+
172
+ if( file_exists( ABSPATH . '.wp-staging' ) ) {
173
+ return true;
174
+ }
175
+
176
+ return false;
177
  }
apps/Core/WPStaging.php CHANGED
@@ -29,7 +29,7 @@ final class WPStaging {
29
  /**
30
  * Plugin version
31
  */
32
- const VERSION = "2.5.5";
33
 
34
  /**
35
  * Plugin name
@@ -167,7 +167,7 @@ final class WPStaging {
167
  public function enqueueElements( $hook ) {
168
 
169
  // Load this css file on frontend and backend on all pages if current site is a staging site
170
- if( $this->isStagingSite() ) {
171
  wp_enqueue_style( "wpstg-admin-bar", $this->backend_url . "css/wpstg-admin-bar.css", array(), $this->getVersion() );
172
  }
173
 
@@ -444,9 +444,9 @@ final class WPStaging {
444
  * Check if it is a staging site
445
  * @return bool
446
  */
447
- private function isStagingSite() {
448
- return ("true" === get_option( "wpstg_is_staging_site" ));
449
- }
450
 
451
  /**
452
  * Initialize licensing functions
29
  /**
30
  * Plugin version
31
  */
32
+ const VERSION = "2.5.6";
33
 
34
  /**
35
  * Plugin name
167
  public function enqueueElements( $hook ) {
168
 
169
  // Load this css file on frontend and backend on all pages if current site is a staging site
170
+ if( wpstg_is_stagingsite() ) {
171
  wp_enqueue_style( "wpstg-admin-bar", $this->backend_url . "css/wpstg-admin-bar.css", array(), $this->getVersion() );
172
  }
173
 
444
  * Check if it is a staging site
445
  * @return bool
446
  */
447
+ // private function isStagingSite() {
448
+ // return ("true" === get_option( "wpstg_is_staging_site" ));
449
+ // }
450
 
451
  /**
452
  * Initialize licensing functions
apps/Frontend/Frontend.php CHANGED
@@ -114,11 +114,11 @@ class Frontend extends InjectionAware {
114
  */
115
  private function disableLogin() {
116
  // Is not staging site
117
- if( !$this->isStagingSite() ) {
118
  return false;
119
  }
120
 
121
- // Allow access for users with certain capabilitie only
122
  if( current_user_can( 'manage_options' ) ) {
123
  //if( current_user_can( 'administrator' ) ) {
124
  return false;
@@ -156,6 +156,7 @@ class Frontend extends InjectionAware {
156
  * Reset permalink structure of the clone to default; index.php?p=123
157
  */
158
  private function resetPermaLinks() {
 
159
  if( !$this->isStagingSite() || "true" === get_option( "wpstg_rmpermalinks_executed" ) ) {
160
  return;
161
  }
114
  */
115
  private function disableLogin() {
116
  // Is not staging site
117
+ if( !wpstg_is_stagingsite() ) {
118
  return false;
119
  }
120
 
121
+ // Allow access for user role administrator in any case
122
  if( current_user_can( 'manage_options' ) ) {
123
  //if( current_user_can( 'administrator' ) ) {
124
  return false;
156
  * Reset permalink structure of the clone to default; index.php?p=123
157
  */
158
  private function resetPermaLinks() {
159
+ // Do nothing
160
  if( !$this->isStagingSite() || "true" === get_option( "wpstg_rmpermalinks_executed" ) ) {
161
  return;
162
  }
readme.txt CHANGED
@@ -9,7 +9,7 @@ License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
  Tags: staging, duplication, cloning, clone, migration, sandbox, test site, testing, backup, post, admin, administration, duplicate posts
10
  Requires at least: 3.6+
11
  Tested up to: 5.1
12
- Stable tag: 2.5.5
13
  Requires PHP: 5.3
14
 
15
  A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators.
@@ -151,6 +151,16 @@ https://wp-staging.com
151
 
152
  == Changelog ==
153
 
 
 
 
 
 
 
 
 
 
 
154
  = 2.5.5 =
155
  * Fix: Fatal error, undefined function wpstg_validate_data()
156
 
@@ -227,6 +237,10 @@ Complete changelog: [https://wp-staging.com/wp-staging-changelog](https://wp-sta
227
 
228
  == Upgrade Notice ==
229
 
230
- = 2.5.4 =
231
- * Fix: WordFence firewall rule 'local file inclusion' blocks wp staging initial starting cloning sequence
232
- * Fix: Values of form Extra directories to copy are ignored
 
 
 
 
9
  Tags: staging, duplication, cloning, clone, migration, sandbox, test site, testing, backup, post, admin, administration, duplicate posts
10
  Requires at least: 3.6+
11
  Tested up to: 5.1
12
+ Stable tag: 2.5.6
13
  Requires PHP: 5.3
14
 
15
  A duplicator plugin! Clone, duplicate and migrate live sites to independent staging and development sites that are available only to administrators.
151
 
152
  == Changelog ==
153
 
154
+ = 2.5.6 =
155
+ * New: Compatible to WordPress 5.2
156
+ * New: Allow adding file .wp-staging to root of website to determine if it's a staging or production website
157
+ * New: Add extended data about a staging site in list overview of staging sites
158
+ * New: Show unfinished or interrupted clones and allow deletion of them
159
+ * Tweak: Move admin notices templates to views/notices
160
+ * Fix: Rating notice appears again after using review later button
161
+ * Fix: Can not find staging site when staging site has been created with old version of wp staging
162
+ * Fix: Do not search & replace over incomplete classes in database to prevent warnings
163
+
164
  = 2.5.5 =
165
  * Fix: Fatal error, undefined function wpstg_validate_data()
166
 
237
 
238
  == Upgrade Notice ==
239
 
240
+ = 2.5.6 =
241
+ * New: compatible to WordPress 5.2
242
+ * New: Allow adding file .wp-staging to root of website to determine if it's a staging or production website
243
+ * Tweak: Move admin notices templates to views/notices
244
+ * Fix: Rating notice appears again immediately after using review later button
245
+ * Fix: Convert staging site table prefix to lowercase
246
+ * New: Show unfinished or interrupted clones and allow deletion of them
wp-staging.php CHANGED
@@ -7,7 +7,7 @@
7
  * Author: WP-Staging
8
  * Author URI: https://wp-staging.com
9
  * Contributors: ReneHermi, ilgityildirim
10
- * Version: 2.5.5
11
  * Text Domain: wp-staging
12
  * Domain Path: /languages/
13
 
@@ -51,7 +51,7 @@ if( !defined( 'WPSTG_PLUGIN_URL' ) ) {
51
 
52
  // Version
53
  if( !defined( 'WPSTG_VERSION' ) ) {
54
- define( 'WPSTG_VERSION', '2.5.5' );
55
  }
56
 
57
  // Must use version of the optimizer
7
  * Author: WP-Staging
8
  * Author URI: https://wp-staging.com
9
  * Contributors: ReneHermi, ilgityildirim
10
+ * Version: 2.5.6
11
  * Text Domain: wp-staging
12
  * Domain Path: /languages/
13
 
51
 
52
  // Version
53
  if( !defined( 'WPSTG_VERSION' ) ) {
54
+ define( 'WPSTG_VERSION', '2.5.6' );
55
  }
56
 
57
  // Must use version of the optimizer