WP Clone by WP Academy - Version 2.2.1

Version Description

  • 2015-12-29 =
  • Fixed: Backup names will use the time zone selected in general settings.
  • Added: basic backup/restore logs.
  • Added: An option to exclude files based on size (files larger than 25MB will be excluded by default)
  • Added: An option to ignore the wordpress table prefix during backup/restore.
  • Added: An option to check the mysql connection during restore.
  • Added: A search and replace tool into the plugin dashboard.
  • Changed: A .htaccess file will be placed in the temporary directories to prevent external access to the files.
  • Changed: Files are no longer copied to a temporary location during backup.
  • Changed: Database import is done before the rest of the files are extracted.
  • Changed: siteurl option is updated during the database import.
  • Changed: search and replace will not run when the URLs are similar.
  • Changed: Increased the default values for memory_limit and max_execution_time from 512MB/300 to 1024MB/600.
  • Removed: The use of wordpress' unzip_file (ziparchive will be used when available with pclzip as fallback)
Download this release

Release Info

Developer wpacademy
Plugin Icon 128x128 WP Clone by WP Academy
Version 2.2.1
Comparing to
See all releases

Code changes from version 2.2 to 2.2.1

Files changed (6) hide show
  1. lib/css/style.css +19 -1
  2. lib/functions.php +590 -190
  3. lib/js/backupmanager.js +58 -6
  4. lib/view.php +57 -11
  5. readme.txt +35 -17
  6. wpclone.php +42 -4
lib/css/style.css CHANGED
@@ -52,10 +52,12 @@
52
  display: none;
53
  }
54
 
 
 
 
55
  div.info {
56
  padding: 15px;
57
  margin: 30px 0;
58
- max-width: 60%;
59
  background: #e1e1ea;
60
  border-radius: 5px;
61
  -moz-box-shadow: 5px 5px 15px #aaa;
@@ -98,6 +100,22 @@ table.restore-backup-options td, table.restore-backup-options th {
98
  background: #fff0b3;
99
  }
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  a.copy-button {
102
  }
103
 
52
  display: none;
53
  }
54
 
55
+ .width-60 {
56
+ max-width: 60%;
57
+ }
58
  div.info {
59
  padding: 15px;
60
  margin: 30px 0;
 
61
  background: #e1e1ea;
62
  border-radius: 5px;
63
  -moz-box-shadow: 5px 5px 15px #aaa;
100
  background: #fff0b3;
101
  }
102
 
103
+ a#close-thickbox {
104
+ position: absolute;
105
+ top: 0;
106
+ right: 0;
107
+ font-weight: bold;
108
+ }
109
+
110
+ div#search-n-replace {
111
+ display: none;
112
+ position: relative;
113
+ }
114
+
115
+ div#search-n-replace-info{
116
+ min-height: 20px;
117
+ }
118
+
119
  a.copy-button {
120
  }
121
 
lib/functions.php CHANGED
@@ -23,7 +23,18 @@ function wpa_db_backup_wpdb($destination)
23
  $return = '';
24
 
25
  // Get all of the tables
26
- $tables = $wpdb->get_col('SHOW TABLES LIKE "' . $wpdb->prefix . '%"');
 
 
 
 
 
 
 
 
 
 
 
27
  // Cycle through each provided table
28
  foreach ($tables as $table) {
29
 
@@ -69,46 +80,50 @@ function wpa_db_backup_wpdb($destination)
69
  /**
70
  * @link http://davidwalsh.name/backup-mysql-database-php
71
  */
72
- function wpa_db_backup_direct($destination,$tables = '*')
73
  {
74
 
75
  global $wpdb;
76
- $link = mysql_connect( DB_HOST, DB_USER, DB_PASSWORD );
 
77
  if ( false === $link ) {
78
  wpa_backup_error('db', mysql_error() );
79
  }
80
- mysql_select_db( DB_NAME, $link );
81
- mysql_set_charset(DB_CHARSET, $link);
82
- //get all of the tables
83
- if($tables == '*')
84
- {
85
- $tables = array();
86
- $result = mysql_query('SHOW TABLES LIKE "' . $wpdb->prefix . '%"');
87
- if ( false === $result ) {
88
- wpa_backup_error('db', mysql_error() );
89
- }
90
- while($row = mysql_fetch_row($result))
91
- {
92
- $tables[] = $row[0];
93
- }
94
  }
95
- else
96
- {
97
- $tables = is_array($tables) ? $tables : explode(',',$tables);
 
 
 
 
98
  }
 
 
99
  $return = '';
100
- //cycle through
101
  foreach($tables as $table)
102
  {
103
 
104
- $result = mysql_query('SELECT * FROM '.$table);
105
  if ( false === $result ) {
106
  wpa_backup_error('db', mysql_error() );
107
  }
108
  $num_fields = mysql_num_fields($result);
109
 
110
  $return.= 'DROP TABLE IF EXISTS '.$table.';';
111
- $row2 = mysql_fetch_row(mysql_query('SHOW CREATE TABLE '.$table));
112
  $return.= "\n\n".$row2[1].";\n\n";
113
 
114
  for ($i = 0; $i < $num_fields; $i++)
@@ -141,9 +156,10 @@ function wpa_insert_data($name, $size)
141
  global $current_user;
142
  $backup = array(
143
  $time => array(
144
- 'name' => $name,
145
- 'creator' => $current_user->user_login,
146
- 'size' => $size
 
147
  )
148
  );
149
 
@@ -162,30 +178,65 @@ function wpa_insert_data($name, $size)
162
  function CreateWPFullBackupZip($backupName, $zipmode, $use_wpdb = false )
163
  {
164
  $folderToBeZipped = WPCLONE_DIR_BACKUP . 'wpclone_backup';
165
- $destinationPath = $folderToBeZipped . '/' . basename(WPCLONE_WP_CONTENT);
166
- $zipFileName = WPCLONE_DIR_BACKUP . $backupName . '.zip';
167
- $exclude = wpa_excluded_dirs();
168
- $dbonly = isset( $_POST['dbonly'] ) && 'true' == $_POST['dbonly'] ? true : false;
 
 
 
 
 
 
169
 
170
- if( false === mkdir( $folderToBeZipped ) )
 
 
 
 
 
 
 
171
  wpa_backup_error ( 'file', sprintf( __( 'Unable to create the temporary backup directory,please make sure that PHP has permission to write into the <code>%s</code> directory.' ), WPCLONE_DIR_BACKUP ) );
 
 
 
 
 
 
 
172
 
173
- if( false === $dbonly )
174
- wpa_copy_dir( untrailingslashit( WPCLONE_WP_CONTENT ), $destinationPath, $exclude);
 
 
 
 
 
 
175
 
176
  wpa_save_prefix($folderToBeZipped);
177
  /* error handler is called from within the db backup functions */
178
  if ( $use_wpdb ) {
 
179
  wpa_db_backup_wpdb( $folderToBeZipped );
180
  } else {
 
181
  wpa_db_backup_direct( $folderToBeZipped );
182
  }
 
183
 
184
  /* error haldler is called from within the wpa_zip function */
 
185
  wpa_zip($zipFileName, $folderToBeZipped, $zipmode);
186
- $zipSize = filesize($zipFileName);
187
  wpa_delete_dir( $folderToBeZipped );
188
- return array($backupName . '.zip', $zipSize);
 
 
 
 
 
189
  }
190
 
191
  function DeleteWPBackupZip($nm)
@@ -195,7 +246,12 @@ function DeleteWPBackupZip($nm)
195
  if( empty( $backups ) || ! isset( $backups[$nm] ) ) {
196
  return array(
197
  'status' => 'failed',
198
- 'msg' => 'Something is not quite right here, please try again later.' );
 
 
 
 
 
199
  }
200
 
201
  if ( file_exists( WPCLONE_DIR_BACKUP . $backups[$nm]['name'] ) ) {
@@ -243,48 +299,31 @@ function bytesToSize($bytes, $precision = 2)
243
  }
244
  }
245
 
246
- function replaceSiteUrlFromDatabaseFile($databaseFile)
247
- {
248
- global $wp_filesystem;
249
- $fileContent = $wp_filesystem->get_contents($databaseFile);
250
- $pos = strpos($fileContent, 'siteurl') + 8;
251
- $urlStartPos = strpos($fileContent, '"', $pos) + 1;
252
- $urlEndPos = strpos($fileContent, '"', $urlStartPos);
253
- $backupSiteUrl = substr($fileContent, $urlStartPos, $urlEndPos - $urlStartPos);
254
  return $backupSiteUrl;
 
255
  }
256
 
257
- function processConfigAndDatabaseFile($databaseFileInZip)
258
- {
259
- global $wp_filesystem;
260
- $dbFileContent = $wp_filesystem->get_contents($databaseFileInZip);
261
- /* we don't want to nuke the curret database if if something went wrong with the above operation */
262
- if ( false === $dbFileContent ) {
263
- wpa_backup_error( 'dbrest', sprintf ( __( 'Cannot read <code>%s</code>' ), $databaseFileInZip ) , true );
264
- }
265
 
 
266
 
267
- $conn = mysql_connect( DB_HOST, DB_USER, DB_PASSWORD );
268
- /* and we cannot nuke the db if the connection failed now can we */
269
- if ( false === $conn ) {
270
- wpa_backup_error('dbrest', __( 'database connection failed' ), true );
271
  }
272
 
273
- mysql_select_db( DB_NAME, $conn);
274
- mysql_set_charset(DB_CHARSET, $conn);
275
 
276
- $res = explode(";\n", $dbFileContent);
277
- foreach ($res AS $query) {
278
- mysql_query($query, $conn);
279
- }
280
- mysql_close($conn);
281
- $backupSiteUrl = replaceSiteUrlFromDatabaseFile($databaseFileInZip); /* don't let the name fool you,it just returns the old site's url */
282
- $currentSiteUrl = site_url();
283
- $backupSiteUrl = untrailingslashit($backupSiteUrl);
284
- $currentSiteUrl = untrailingslashit($currentSiteUrl);
285
- $report = wpa_safe_replace_wrapper ( $backupSiteUrl, $currentSiteUrl );
286
 
287
- return array( 'url' => $currentSiteUrl, 'report' => $report );
288
  }
289
 
290
  /**
@@ -292,114 +331,142 @@ function processConfigAndDatabaseFile($databaseFileInZip)
292
  * @param type $replace URL of the current site.
293
  * @return type total time it took for the operation.
294
  */
295
- function wpa_safe_replace_wrapper ( $search, $replace ) {
296
  if ( !function_exists( 'icit_srdb_replacer' ) && !function_exists( 'recursive_unserialize_replace' ) ) {
297
  require_once 'icit_srdb_replacer.php';
298
  }
299
- global $wpdb;
300
- $connection = @mysql_connect( DB_HOST, DB_USER, DB_PASSWORD );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
301
  $all_tables = array();
302
- @mysql_select_db( DB_NAME, $connection );
303
- mysql_set_charset( DB_CHARSET, $connection );
304
- $all_tables_mysql = @mysql_query( 'SHOW TABLES LIKE "' . $wpdb->prefix . '%"', $connection );
305
 
306
- if ( ! $all_tables_mysql ) {
307
- wpa_backup_error( 'dbrest', mysql_error(), true );
 
 
308
  } else {
309
- while ( $table = mysql_fetch_array( $all_tables_mysql ) ) {
310
- $all_tables[] = $table[ 0 ];
311
- }
312
  }
313
 
 
 
 
 
 
 
314
  $report = icit_srdb_replacer( $connection, $search, $replace, $all_tables );
 
 
315
  return $report;
316
  }
317
 
318
-
319
- function processRestoringBackup($url, $zipmode) {
320
- wpa_cleanup( true );
321
- if (!is_string($url) || '' == $url) {
322
- wpa_backup_error( 'restore', sprintf( __( 'The provided URL "<code>%s</code>" is either not valid or empty' ), $url ), true );
323
- }
324
 
325
  global $wp_filesystem;
326
  $temp_dir = trailingslashit( WPCLONE_WP_CONTENT ) . 'wpclone-temp';
327
- $temp_dir_err = $wp_filesystem->mkdir( $temp_dir );
328
- if ( is_wp_error($temp_dir_err) ) {
329
- wpa_backup_error('dirrest', $temp_dir_err->get_error_message(), true );
330
- }
331
- $pathParts = pathinfo($url);
332
- $zipFilename = wpa_fetch_file($url);
333
 
334
- $result = wpa_unzip($zipFilename, $temp_dir, $zipmode);
335
- if ($result) {
336
- $unzippedFolderPath = wpCloneSafePathMode( trailingslashit( $temp_dir ) . 'wpclone_backup' );
337
- if ( ! $wp_filesystem->is_dir( $unzippedFolderPath ) ) {
338
- $unzippedFolderPath = wpCloneSafePathMode( trailingslashit( $temp_dir ) . $pathParts['filename'] );
339
- }
340
 
341
- /* if we're here then the file extraction worked,but let's make doubly sure */
342
- if( ! $wp_filesystem->is_dir( $unzippedFolderPath ) ) {
343
- wpa_backup_error( 'restore', sprintf( __( 'Cannot find <code>%s<code>' ), $unzippedFolderPath ), true );
344
- }
345
- /* check the table prefixes */
346
- $old_db_prefix = $unzippedFolderPath . '/prefix.txt';
347
- $prefix = wpa_check_prefix($old_db_prefix);
348
- if ($prefix) {
349
- wpa_replace_prefix( $prefix );
350
- }
351
- $wp_filesystem->delete( $old_db_prefix );
352
- /* import db */
353
- $databaseFile = $unzippedFolderPath . '/database.sql';
354
- $currentSiteUrl = processConfigAndDatabaseFile($databaseFile);
355
- /* */
356
- $wp_filesystem->delete( $databaseFile );
357
 
358
- wpa_copy( $unzippedFolderPath . '/wp-content', WPCLONE_WP_CONTENT );
359
 
 
360
 
361
- $wp_filesystem->delete( $temp_dir, true );
362
- /* remove the zip file only if it was downloaded from an external location. */
363
- $wptmp = explode('.', $zipFilename);
364
- if ( in_array( 'tmp', $wptmp ) ) {
365
- $wp_filesystem->delete( $zipFilename );
366
- }
367
 
368
- echo "<div><h1>Restore Successful!</h1>";
 
369
 
370
- echo "Visit your restored site [ <a href='{$currentSiteUrl['url']}' target=blank>here</a> ]<br><br>";
371
 
372
- echo "<strong>You may need to re-save your permalink structure <a href='{$currentSiteUrl['url']}/wp-admin/options-permalink.php' target=blank>Here</a></strong>";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
373
 
374
- $report = $currentSiteUrl['report'];
375
- /* copy pasta (more or less) from serialized search and replace script by interconnectit */
376
- $time = array_sum( explode( ' ', $report[ 'end' ] ) ) - array_sum( explode( ' ', $report[ 'start' ] ) );
377
- printf( '<div class="info"><p>Search and replace scanned <strong>%d</strong> tables with a total of <strong>%d</strong> rows, ' , $report['tables'], $report['rows'] );
378
- printf( '<strong>%d</strong> cells were changed and <strong>%d</strong> db updates were performed. it took <strong>%f</strong> seconds.</p></div>', $report['change'], $report['updates'], $time );
379
 
 
 
 
 
 
 
380
 
381
- if ( ! empty( $report['errors'] ) && is_array( $report['errors'] ) ) {
382
- echo '<div class="error">';
383
- echo '<h3>The following errors were encountered during the search and replace process.</h3>';
384
- foreach( $report['errors'] as $error )
385
- echo '<p>' . $error . '</p>';
386
- echo '</div>';
387
- }
388
 
389
- echo '</div>';
390
 
391
- } else {
 
 
 
 
392
 
393
- echo "<h1>Restore unsuccessful!!!</h1>";
 
 
394
 
395
- echo "Please try again.";
 
 
 
 
 
 
396
  }
397
 
 
 
398
  }
399
 
400
  function wpa_save_prefix($path) {
401
  global $wpdb;
402
- $prefix = $wpdb->prefix;
403
  $file = $path . '/prefix.txt';
404
  if ( is_dir($path) && is_writable($path) ) {
405
  file_put_contents($file, $prefix);
@@ -434,32 +501,36 @@ function wpa_check_prefix($file) {
434
  * @return as false in the event of failure.
435
  */
436
  function wpa_unzip($zipfile, $path, $zipmode = false){
437
- if ( $zipmode ) {
 
 
 
438
 
439
  if ( ini_get('mbstring.func_overload') && function_exists('mb_internal_encoding') ) {
440
  $previous_encoding = mb_internal_encoding();
441
  mb_internal_encoding('ISO-8859-1');
442
  }
443
 
444
- define('PCLZIP_TEMPORARY_DIR', WPCLONE_DIR_BACKUP);
445
  require_once ( ABSPATH . 'wp-admin/includes/class-pclzip.php' );
446
  $z = new PclZip($zipfile);
447
- $files = $z->extract(PCLZIP_OPT_PATH, $path);
 
448
 
449
- if ( isset($previous_encoding) ) mb_internal_encoding($previous_encoding);
 
 
 
450
 
451
- if ( $files == 0 ) {
452
  wpa_backup_error( 'pclunzip', $z->errorInfo(true), true );
453
  }
454
- return true;
455
- }
456
- else {
457
- $z= unzip_file($zipfile, $path);
458
- if (is_wp_error($z)) {
459
- wpa_backup_error( 'unzip', $z->get_error_message(), true );
460
- }
461
- return true;
462
  }
 
463
  }
464
  /**
465
  * @since 2.0.6
@@ -469,21 +540,37 @@ function wpa_unzip($zipfile, $path, $zipmode = false){
469
  */
470
  function wpa_zip($zip_name, $folder, $zipmode = false){
471
  if ( $zipmode || (!in_array('ZipArchive', get_declared_classes()) || !class_exists('ZipArchive')) ) {
 
472
  define('PCLZIP_TEMPORARY_DIR', WPCLONE_DIR_BACKUP);
473
  require_once ( ABSPATH . 'wp-admin/includes/class-pclzip.php');
474
  $z = new PclZip($zip_name);
475
- $v_list = $z->create($folder, PCLZIP_OPT_REMOVE_PATH, WPCLONE_DIR_BACKUP);
476
  if ($v_list == 0) {
477
  wpa_backup_error( 'pclzip', $z->errorInfo(true) );
478
  }
 
 
 
 
 
 
 
 
479
  } else {
 
480
  $z = new ZipArchive();
481
  if ( true !== $z->open( $zip_name, ZIPARCHIVE::CREATE ) ) {
482
- wpa_backup_error( 'zip', $z );
483
  }
484
  wpa_ziparc($z, $folder, WPCLONE_DIR_BACKUP);
 
 
 
485
  $z->close();
 
486
  }
 
 
487
  }
488
 
489
  function wpa_ziparc($zip, $dir, $base) {
@@ -503,11 +590,16 @@ function wpa_ziparc($zip, $dir, $base) {
503
  * @since 2.0.6
504
  */
505
  function wpa_bump_limits(){
506
- $time = isset( $_POST['maxexec'] ) && '' != $_POST['maxexec'] ? $_POST['maxexec'] : 300; /*300 seconds = 5 minutes*/
507
- $mem = isset ( $_POST['maxmem'] ) && '' != $_POST['maxmem'] ? $_POST['maxmem'] . 'M' : '512M';
508
- @ini_set('memory_limit', $mem);
509
- @ini_set('max_execution_time', $time);
 
 
 
 
510
  }
 
511
  /**
512
  * @since 2.0.6
513
  */
@@ -527,7 +619,7 @@ function wpa_wpfs_init(){
527
  }
528
 
529
  $form_post = wp_nonce_url('admin.php?page=wp-clone', 'wpclone-submit');
530
- $extra_fields = array( 'restore_from_url', 'maxmem', 'maxexec', 'zipmode', 'restoreBackup', 'createBackup' );
531
  $type = '';
532
  if ( false === ($creds = request_filesystem_credentials($form_post, $type, false, false, $extra_fields)) ){
533
  return true;
@@ -574,25 +666,36 @@ function wpa_copy($source, $target) {
574
  /**
575
  * @since 2.0.6
576
  */
577
- function wpa_replace_prefix($newPrefix){
 
578
  $wpconfig = wpa_wpconfig_path();
579
  global $wp_filesystem;
580
 
581
  if ( ! $wp_filesystem->is_writable($wpconfig) ) {
582
  if( false === $wp_filesystem->chmod( $wpconfig ) )
583
  wpa_backup_error('wpconfig', sprintf( __( "<code>%s</code> is not writable and wpclone was unable to change the file permissions." ), $wpconfig ), true );
 
 
 
 
 
 
 
 
 
 
 
584
  }
585
 
586
- $fileContent = $wp_filesystem->get_contents($wpconfig);
587
- $pos = strpos($fileContent, '$table_prefix');
588
- $str = substr($fileContent, $pos, strpos($fileContent, PHP_EOL, $pos) - $pos);
589
- $fileContent = str_replace($str, '$table_prefix = "' . $newPrefix . '";', $fileContent);
590
- $wp_filesystem->put_contents($wpconfig, $fileContent, 0600);
591
  }
592
  /**
593
  * @since 2.0.6
594
  */
595
  function wpa_create_backup (){
 
596
  if( true === is_multisite() )
597
  die( 'wpclone does not work on multisite installs.' );
598
  if ( !file_exists(WPCLONE_DIR_BACKUP) ) {
@@ -601,13 +704,18 @@ function wpa_create_backup (){
601
  wpa_cleanup();
602
  $use_wpdb = isset( $_POST['use_wpdb'] ) && 'true' == $_POST['use_wpdb'] ? true : false;
603
  $backupName = wpa_backup_name();
 
 
 
604
 
605
  $zipmode = isset($_POST['zipmode']) ? true : false;
606
  list($zipFileName, $zipSize) = CreateWPFullBackupZip($backupName, $zipmode, $use_wpdb);
607
 
608
  wpa_insert_data($zipFileName, $zipSize);
609
- $backZipPath = convertPathIntoUrl(WPCLONE_DIR_BACKUP . $zipFileName);
610
  $zipSize = bytesToSize($zipSize);
 
 
611
  echo <<<EOF
612
 
613
  <h1>Backup Successful!</h1>
@@ -622,6 +730,8 @@ Here is your backup file : <br />
622
 
623
  (Copy that link and paste it into the "Restore URL" of your new WordPress installation to clone this site)
624
  EOF;
 
 
625
  }
626
  /**
627
  * @since 2.0.6
@@ -639,23 +749,23 @@ function wpa_remove_backup(){
639
  */
640
  function wpa_wpconfig_path () {
641
 
642
- if ( file_exists( ABSPATH . 'wp-config.php') ) {
643
 
644
- /** The config file resides in ABSPATH */
645
- return ABSPATH . 'wp-config.php';
646
 
647
- }
648
- elseif ( file_exists( dirname(ABSPATH) . '/wp-config.php' ) && ! file_exists( dirname(ABSPATH) . '/wp-settings.php' ) ) {
649
 
650
- /** The config file resides one level above ABSPATH but is not part of another install */
651
- return dirname(ABSPATH) . '/wp-config.php';
652
 
653
- }
654
- else {
655
 
656
- return false;
657
 
658
- }
659
 
660
  }
661
 
@@ -663,17 +773,22 @@ function wpa_fetch_file($path){
663
  $z = pathinfo($path);
664
  global $wp_filesystem;
665
  if ( $wp_filesystem->is_file(WPCLONE_DIR_BACKUP . $z['basename']) ) {
 
666
  return WPCLONE_DIR_BACKUP . $z['basename'];
667
  }
668
  else {
 
669
  $url = download_url($path, 750);
670
- if ( is_wp_error($url) ) wpa_backup_error( 'url', $url->get_error_message(), true );
 
 
 
671
  return $url;
672
  }
673
  }
674
 
675
  function wpa_backup_name() {
676
- $backup_name = 'wpclone_backup_' . date( 'dS_M_Y_h-iA' ) . '_' . get_option( 'blogname' );
677
  $backup_name = substr( str_replace( ' ', '', $backup_name ), 0, 40 );
678
  $rand_str = substr( str_shuffle( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" ), 0, 10 );
679
  $backup_name = sanitize_file_name( $backup_name ) . '_' . $rand_str;
@@ -683,11 +798,12 @@ function wpa_backup_name() {
683
  function wpa_backup_error($error, $data, $restore = false) {
684
 
685
  $temp_dir = $restore ? trailingslashit( WPCLONE_WP_CONTENT ) . 'wpclone-temp' : trailingslashit( WPCLONE_DIR_BACKUP ) . 'wpclone_backup';
 
686
 
687
  if( !file_exists( $temp_dir ) ) {
688
  unset($temp_dir);
689
  }
690
-
691
  switch ( $error ) :
692
  /* during backup */
693
  case 'file' :
@@ -713,7 +829,7 @@ function wpa_backup_error($error, $data, $restore = false) {
713
  $error = __( 'while cloning the database' );
714
  break;
715
  case 'unzip' :
716
- $error = __( 'while extracting the zip file using WP\'s zip file extractor' );
717
  break;
718
  case 'pclunzip' :
719
  $error = __( 'while extracting the zip file using the PclZip library' );
@@ -733,7 +849,7 @@ function wpa_backup_error($error, $data, $restore = false) {
733
  printf( __( 'The plugin encountered an error %s,the following error message was returned:</br>' ), $error );
734
  echo '<div class="error">' . __( 'Error Message : ' ) . $data . '</div></br>';
735
  if( isset( $temp_dir ) ) {
736
- printf( __( 'Temporary files created in <code>%s</code> will be deleted.' ), $temp_dir );
737
  echo '</div>';
738
  if( $restore ) {
739
  global $wp_filesystem;
@@ -813,7 +929,8 @@ function wpa_excluded_dirs() {
813
  $ex = trim( $ex );
814
  if( '' !== $ex ) {
815
  $ex = trim( $ex, "/\\" );
816
- $exclude[] = trailingslashit( WPCLONE_WP_CONTENT ) . str_replace( '\\', '/', $ex ) ;
 
817
  }
818
  }
819
  }
@@ -828,7 +945,7 @@ function wpa_wpc_dir_size( $path ) {
828
 
829
  foreach( $i as $file => $info ) {
830
 
831
- if( ! strpos( $file, 'wp-clone' ) ) {
832
  $size += $info->getSize();
833
  $files++;
834
 
@@ -836,7 +953,16 @@ function wpa_wpc_dir_size( $path ) {
836
 
837
  }
838
 
839
- return array( 'size' => size_format( $size ), 'files' => $files );
 
 
 
 
 
 
 
 
 
840
 
841
  }
842
 
@@ -845,7 +971,7 @@ function wpa_wpc_db_size() {
845
  global $wpdb;
846
  $sql = 'SELECT sum(data_length + index_length) FROM information_schema.TABLES WHERE table_schema = "' . DB_NAME . '"';
847
  $size = $wpdb->get_var( $sql );
848
- return size_format( $size );
849
 
850
  }
851
 
@@ -906,11 +1032,285 @@ function wpa_wpc_scan_dir() {
906
  function wpa_wpc_filter_list( $a, $b ) {
907
 
908
  $return = array();
909
- foreach( $a as $v ) $return[$v] = '';
910
- foreach( $b as $v ) unset( $return[$v] );
 
 
 
 
911
  return array_keys( $return );
912
 
913
  }
914
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
915
 
916
  /* end of file */
23
  $return = '';
24
 
25
  // Get all of the tables
26
+ if( isset( $_POST['ignore_prefix'] ) && 'true' === $_POST['ignore_prefix'] ) {
27
+ wpa_wpc_log( 'ignore prefix enabled, backing up all the tables' );
28
+ $tables = $wpdb->get_col('SHOW TABLES');
29
+
30
+ } else {
31
+ wpa_wpc_log( sprintf( 'backing up tables with "%s" prefix', $wpdb->prefix ) );
32
+ $tables = $wpdb->get_col('SHOW TABLES LIKE "' . $wpdb->prefix . '%"');
33
+
34
+ }
35
+
36
+ wpa_wpc_log( sprintf( 'number of tables to backup - %d', count( $tables ) ) );
37
+
38
  // Cycle through each provided table
39
  foreach ($tables as $table) {
40
 
80
  /**
81
  * @link http://davidwalsh.name/backup-mysql-database-php
82
  */
83
+ function wpa_db_backup_direct($destination)
84
  {
85
 
86
  global $wpdb;
87
+ $prefix = $wpdb->prefix;
88
+ $link = wpa_wpc_mysql_connect();
89
  if ( false === $link ) {
90
  wpa_backup_error('db', mysql_error() );
91
  }
92
+
93
+ $tables = array();
94
+
95
+ if( isset( $_POST['ignore_prefix'] ) && 'true' === $_POST['ignore_prefix'] ) {
96
+ wpa_wpc_log( 'ignore prefix enabled, backing up all the tables' );
97
+ $result = mysql_query('SHOW TABLES');
98
+
99
+ } else {
100
+ wpa_wpc_log( sprintf( 'backing up tables with "%s" prefix', $prefix ) );
101
+ $result = mysql_query('SHOW TABLES LIKE "' . $prefix . '%"');
102
+
 
 
 
103
  }
104
+
105
+ if ( false === $result ) {
106
+ wpa_backup_error('db', mysql_error() );
107
+ }
108
+
109
+ while( $row = mysql_fetch_row( $result ) ) {
110
+ $tables[] = $row[0];
111
  }
112
+
113
+ wpa_wpc_log( sprintf( 'number of tables to backup - %d', count( $tables ) ) );
114
  $return = '';
115
+
116
  foreach($tables as $table)
117
  {
118
 
119
+ $result = mysql_query( 'SELECT * FROM ' . $table, $link );
120
  if ( false === $result ) {
121
  wpa_backup_error('db', mysql_error() );
122
  }
123
  $num_fields = mysql_num_fields($result);
124
 
125
  $return.= 'DROP TABLE IF EXISTS '.$table.';';
126
+ $row2 = mysql_fetch_row( mysql_query( 'SHOW CREATE TABLE ' . $table, $link ) );
127
  $return.= "\n\n".$row2[1].";\n\n";
128
 
129
  for ($i = 0; $i < $num_fields; $i++)
156
  global $current_user;
157
  $backup = array(
158
  $time => array(
159
+ 'name' => $name . '.zip',
160
+ 'log' => $name . '.log',
161
+ 'creator' => $current_user->user_login,
162
+ 'size' => $size
163
  )
164
  );
165
 
178
  function CreateWPFullBackupZip($backupName, $zipmode, $use_wpdb = false )
179
  {
180
  $folderToBeZipped = WPCLONE_DIR_BACKUP . 'wpclone_backup';
181
+ $htaccess = "<Files>\r\n\tOrder allow,deny\r\n\tDeny from all\r\n\tSatisfy all\r\n</Files>";
182
+ $zipFileName = WPCLONE_DIR_BACKUP . $backupName . '.zip';
183
+ $exclude = wpa_excluded_dirs();
184
+ $dbonly = isset( $_POST['dbonly'] ) && 'true' == $_POST['dbonly'] ? true : false;
185
+ $skip = 25 * 1024 * 1024;
186
+
187
+ if( isset( $_POST['skipfiles'] ) && '' !== $_POST['skipfiles'] ) {
188
+
189
+ if( 0 === $_POST['skipfiles'] ) {
190
+ $skip = false;
191
 
192
+ } else {
193
+ $skip = $_POST['skipfiles'] * 1024 * 1024;
194
+
195
+ }
196
+
197
+ }
198
+
199
+ if( false === mkdir( $folderToBeZipped ) ) {
200
  wpa_backup_error ( 'file', sprintf( __( 'Unable to create the temporary backup directory,please make sure that PHP has permission to write into the <code>%s</code> directory.' ), WPCLONE_DIR_BACKUP ) );
201
+ }
202
+
203
+ file_put_contents( $folderToBeZipped . '/.htaccess', $htaccess );
204
+
205
+ if( $dbonly ) {
206
+ wpa_wpc_log ( 'database only backup, no files will be copied' );
207
+ }
208
 
209
+ if( false === $dbonly ) {
210
+ if( $skip ) {
211
+ wpa_wpc_log( sprintf( 'files larger than %s will be excluded from the backup', bytesToSize( $skip ) ) );
212
+ }
213
+ wpa_wpc_log( 'generating file list' );
214
+ file_put_contents( $folderToBeZipped . '/file.list', serialize( wpa_wpc_get_filelist( WPCLONE_WP_CONTENT, $exclude, $skip ) ) );
215
+ wpa_wpc_log( 'finished generating file list' );
216
+ }
217
 
218
  wpa_save_prefix($folderToBeZipped);
219
  /* error handler is called from within the db backup functions */
220
  if ( $use_wpdb ) {
221
+ wpa_wpc_log ( 'database backup started [wpdb]' );
222
  wpa_db_backup_wpdb( $folderToBeZipped );
223
  } else {
224
+ wpa_wpc_log ( 'database backup started' );
225
  wpa_db_backup_direct( $folderToBeZipped );
226
  }
227
+ wpa_wpc_log ( 'database backup finished' );
228
 
229
  /* error haldler is called from within the wpa_zip function */
230
+
231
  wpa_zip($zipFileName, $folderToBeZipped, $zipmode);
232
+
233
  wpa_delete_dir( $folderToBeZipped );
234
+
235
+ if( ! file_exists( $zipFileName ) ) {
236
+ wpa_backup_error( 'backup', 'possibly out of free disk space' );
237
+ }
238
+ $zipSize = filesize($zipFileName);
239
+ return array($backupName, $zipSize);
240
  }
241
 
242
  function DeleteWPBackupZip($nm)
246
  if( empty( $backups ) || ! isset( $backups[$nm] ) ) {
247
  return array(
248
  'status' => 'failed',
249
+ 'msg' => 'Something is not quite right here, refresh the backup list and try again later.' );
250
+ }
251
+
252
+ if( isset( $backups[$nm]['log'] ) && file_exists( WPCLONE_DIR_BACKUP . $backups[$nm]['log'] ) ) {
253
+ @unlink( WPCLONE_DIR_BACKUP . $backups[$nm]['log'] );
254
+
255
  }
256
 
257
  if ( file_exists( WPCLONE_DIR_BACKUP . $backups[$nm]['name'] ) ) {
299
  }
300
  }
301
 
302
+ function wpa_wpc_get_url( $db ) {
303
+
304
+ $pos = strpos( $db, 'siteurl' ) + 8;
305
+ $urlStartPos = strpos( $db, '"', $pos ) + 1;
306
+ $urlEndPos = strpos( $db, '"', $urlStartPos );
307
+ $backupSiteUrl = substr( $db, $urlStartPos, $urlEndPos - $urlStartPos );
 
 
308
  return $backupSiteUrl;
309
+
310
  }
311
 
312
+ function wpa_wpc_mysql_connect() {
 
 
 
 
 
 
 
313
 
314
+ $link = mysql_connect( DB_HOST, DB_USER, DB_PASSWORD );
315
 
316
+ if ( false === $link ) {
317
+ mysql_close( $link );
318
+ sleep(2);
319
+ $link = mysql_connect( DB_HOST, DB_USER, DB_PASSWORD, true );
320
  }
321
 
322
+ mysql_select_db( DB_NAME, $link );
323
+ mysql_set_charset( DB_CHARSET, $link );
324
 
325
+ return $link;
 
 
 
 
 
 
 
 
 
326
 
 
327
  }
328
 
329
  /**
331
  * @param type $replace URL of the current site.
332
  * @return type total time it took for the operation.
333
  */
334
+ function wpa_safe_replace_wrapper ( $search, $replace, $prefix ) {
335
  if ( !function_exists( 'icit_srdb_replacer' ) && !function_exists( 'recursive_unserialize_replace' ) ) {
336
  require_once 'icit_srdb_replacer.php';
337
  }
338
+
339
+ wpa_wpc_log( 'search and replace started' );
340
+
341
+ $connection = wpa_wpc_mysql_connect();
342
+
343
+
344
+ if ( false === $connection ) {
345
+
346
+ wpa_wpc_log( 'mysql connection failure @ safe replace wrapper - error : "' . mysql_error( $connection ) . '" retrying..' );
347
+
348
+ mysql_close( $connection );
349
+ sleep(1);
350
+ $connection = wpa_wpc_mysql_connect();
351
+
352
+ }
353
+
354
  $all_tables = array();
 
 
 
355
 
356
+ if( isset( $_POST['ignore_prefix'] ) && 'true' === $_POST['ignore_prefix'] ) {
357
+ wpa_wpc_log( 'ignore table prefix enabled, search and replace will scan all the tables in the database' );
358
+ $all_tables_mysql = @mysql_query( 'SHOW TABLES', $connection );
359
+
360
  } else {
361
+ $all_tables_mysql = @mysql_query( 'SHOW TABLES LIKE "' . $prefix . '%"', $connection );
362
+
 
363
  }
364
 
365
+ while ( $table = mysql_fetch_array( $all_tables_mysql ) ) {
366
+ $all_tables[] = $table[ 0 ];
367
+ }
368
+
369
+ wpa_wpc_log( sprintf( 'there are %d tables to scan', count( $all_tables ) ) );
370
+
371
  $report = icit_srdb_replacer( $connection, $search, $replace, $all_tables );
372
+ mysql_close( $connection );
373
+ wpa_wpc_log( 'search and replace finished' );
374
  return $report;
375
  }
376
 
377
+ function wpa_wpc_temp_dir() {
 
 
 
 
 
378
 
379
  global $wp_filesystem;
380
  $temp_dir = trailingslashit( WPCLONE_WP_CONTENT ) . 'wpclone-temp';
381
+ $err = $wp_filesystem->mkdir( $temp_dir );
 
 
 
 
 
382
 
383
+ if ( is_wp_error( $err ) ) {
384
+ wpa_backup_error('dirrest', $err->get_error_message(), true );
385
+ }
 
 
 
386
 
387
+ $content = "<Files>\r\n\tOrder allow,deny\r\n\tDeny from all\r\n\tSatisfy all\r\n</Files>";
388
+ $file = trailingslashit( $temp_dir ) . '.htaccess';
389
+ $wp_filesystem->put_contents( $file, $content, 0644 );
 
 
 
 
 
 
 
 
 
 
 
 
 
390
 
391
+ return $temp_dir;
392
 
393
+ }
394
 
395
+ function processRestoringBackup($url, $zipmode) {
396
+ wpa_cleanup( true );
397
+ if (!is_string($url) || '' == $url) {
398
+ wpa_backup_error( 'restore', sprintf( __( 'The provided URL "<code>%s</code>" is either not valid or empty' ), $url ), true );
399
+ }
 
400
 
401
+ global $wp_filesystem;
402
+ $GLOBALS['wpclone']['logfile'] = 'wpclone_restore_' . current_time( 'dS_M_Y_h-iA', false ) . '_' . wp_generate_password( 10, false ) . '.log';
403
 
404
+ wpa_wpc_log_start( 'restore' );
405
 
406
+ if( $zipmode ) {
407
+ define( 'PCLZIP_TEMPORARY_DIR', WPCLONE_DIR_BACKUP );
408
+
409
+ }
410
+
411
+ $temp_dir = wpa_wpc_temp_dir();
412
+ $site_url = site_url();
413
+ $permalink_url = admin_url( 'options-permalink.php' );
414
+ $zipfile = wpa_fetch_file($url);
415
+ $report = wpa_wpc_process_db( $zipfile, $zipmode );
416
+ $unzipped_folder = wpCloneSafePathMode( trailingslashit( $temp_dir ) . 'wpclone_backup' );
417
+
418
+
419
+ wpa_unzip( $zipfile, $temp_dir, $zipmode );
420
+ wpa_wpc_log( 'copying files..' );
421
+ wpa_copy( $unzipped_folder . '/wp-content', WPCLONE_WP_CONTENT );
422
+
423
+ wpa_wpc_log( 'deleting temp directory..' );
424
+ $wp_filesystem->delete( $temp_dir, true );
425
+ /* remove the zip file only if it was downloaded from an external location. */
426
+ $wptmp = explode( '.', $zipfile );
427
+ if ( in_array( 'tmp', $wptmp ) ) {
428
+ wpa_wpc_log( 'deleting downloaded zip file..' );
429
+ $wp_filesystem->delete( $zipfile );
430
+ }
431
 
432
+ wpa_wpc_log( 'restore finished' );
 
 
 
 
433
 
434
+ echo '<div class="width-60"><h1>Restore Successful!</h1>';
435
+ printf( 'Visit your restored site [ <a href="%s" target=blank>here</a> ]<br><br>', $site_url );
436
+ printf( '<strong>You may need to re-save your permalink structure <a href="%s" target=blank>Here</a></strong>', $permalink_url );
437
+ printf( '</br><a href="%s">log</a>', convertPathIntoUrl( WPCLONE_DIR_BACKUP . $GLOBALS['wpclone']['logfile'] ) );
438
+ unset( $GLOBALS['wpclone'] );
439
+ echo wpa_wpc_search_n_replace_report( $report );
440
 
 
 
 
 
 
 
 
441
 
442
+ }
443
 
444
+ function wpa_wpc_search_n_replace_report( $report ) {
445
+
446
+ if( is_string( $report ) ) {
447
+ return sprintf( '<div class="info"><p>%s</p></div>', $report );
448
+ }
449
 
450
+ $time = array_sum( explode( ' ', $report[ 'end' ] ) ) - array_sum( explode( ' ', $report[ 'start' ] ) );
451
+ $return = sprintf( '<div class="info"><p>Search and replace scanned <strong>%d</strong> tables with a total of <strong>%d</strong> rows. ' , $report['tables'], $report['rows'] );
452
+ $return .= sprintf( '<strong>%d</strong> cells were changed and <strong>%d</strong> db updates were performed in <strong>%f</strong> seconds.</p></div>', $report['change'], $report['updates'], $time );
453
 
454
+ if ( ! empty( $report['errors'] ) && is_array( $report['errors'] ) ) {
455
+ $return .= '<div>';
456
+ $return .= '<h4>search and replace returned the following errors.</h4>';
457
+ foreach( $report['errors'] as $error ) {
458
+ $return .= '<p class="error">' . $error . '</p>';
459
+ }
460
+ $return .= '</div>';
461
  }
462
 
463
+ return $return;
464
+
465
  }
466
 
467
  function wpa_save_prefix($path) {
468
  global $wpdb;
469
+ $prefix = $wpdb->prefix;
470
  $file = $path . '/prefix.txt';
471
  if ( is_dir($path) && is_writable($path) ) {
472
  file_put_contents($file, $prefix);
501
  * @return as false in the event of failure.
502
  */
503
  function wpa_unzip($zipfile, $path, $zipmode = false){
504
+
505
+ if ( $zipmode || ( ! in_array('ZipArchive', get_declared_classes() ) || ! class_exists( 'ZipArchive' ) ) ) {
506
+
507
+ wpa_wpc_log( 'extracting archive using pclzip' );
508
 
509
  if ( ini_get('mbstring.func_overload') && function_exists('mb_internal_encoding') ) {
510
  $previous_encoding = mb_internal_encoding();
511
  mb_internal_encoding('ISO-8859-1');
512
  }
513
 
 
514
  require_once ( ABSPATH . 'wp-admin/includes/class-pclzip.php' );
515
  $z = new PclZip($zipfile);
516
+
517
+ $files = $z->extract( PCLZIP_OPT_PATH, $path );
518
 
519
+ if ( isset( $previous_encoding ) ) {
520
+ mb_internal_encoding( $previous_encoding );
521
+
522
+ }
523
 
524
+ if ( $files === 0 ) {
525
  wpa_backup_error( 'pclunzip', $z->errorInfo(true), true );
526
  }
527
+
528
+ } else {
529
+ wpa_wpc_log( 'extracting archive using ziparchive' );
530
+ wpa_wpc_unzip( $zipfile, $path );
531
+
 
 
 
532
  }
533
+
534
  }
535
  /**
536
  * @since 2.0.6
540
  */
541
  function wpa_zip($zip_name, $folder, $zipmode = false){
542
  if ( $zipmode || (!in_array('ZipArchive', get_declared_classes()) || !class_exists('ZipArchive')) ) {
543
+ wpa_wpc_log( 'archiving files using pclzip' );
544
  define('PCLZIP_TEMPORARY_DIR', WPCLONE_DIR_BACKUP);
545
  require_once ( ABSPATH . 'wp-admin/includes/class-pclzip.php');
546
  $z = new PclZip($zip_name);
547
+ $v_list = $z->create($folder, PCLZIP_OPT_REMOVE_PATH, WPCLONE_DIR_BACKUP );
548
  if ($v_list == 0) {
549
  wpa_backup_error( 'pclzip', $z->errorInfo(true) );
550
  }
551
+ $file_list = wpa_wpc_zip( $z, $zipmode );
552
+
553
+ if( $file_list ) {
554
+ $z->add( $file_list, PCLZIP_OPT_REMOVE_PATH, WPCLONE_ROOT, PCLZIP_OPT_ADD_PATH, 'wpclone_backup' );
555
+ }
556
+
557
+ $z->delete( PCLZIP_OPT_BY_NAME, 'wpclone_backup/file.list' );
558
+
559
  } else {
560
+ wpa_wpc_log( 'archiving files using ziparchive' );
561
  $z = new ZipArchive();
562
  if ( true !== $z->open( $zip_name, ZIPARCHIVE::CREATE ) ) {
563
+ wpa_backup_error( 'zip', $z->getStatusString() );
564
  }
565
  wpa_ziparc($z, $folder, WPCLONE_DIR_BACKUP);
566
+
567
+ wpa_wpc_zip( $z, $zipmode );
568
+ $z->deleteName( 'wpclone_backup/file.list' );
569
  $z->close();
570
+
571
  }
572
+
573
+
574
  }
575
 
576
  function wpa_ziparc($zip, $dir, $base) {
590
  * @since 2.0.6
591
  */
592
  function wpa_bump_limits(){
593
+ $GLOBALS['wpclone'] = array();
594
+ $GLOBALS['wpclone']['time'] = isset( $_POST['maxexec'] ) && '' != $_POST['maxexec'] ? $_POST['maxexec'] : 600; /* 10 minutes */
595
+ $GLOBALS['wpclone']['mem'] = isset ( $_POST['maxmem'] ) && '' != $_POST['maxmem'] ? $_POST['maxmem'] . 'M' : '1024M';
596
+
597
+ @ini_set('memory_limit', $GLOBALS['wpclone']['mem']);
598
+ @ini_set('max_execution_time', $GLOBALS['wpclone']['time']);
599
+ @ini_set('mysql.connect_timeout', $GLOBALS['wpclone']['time']);
600
+ @ini_set('default_socket_timeout', $GLOBALS['wpclone']['time']);
601
  }
602
+
603
  /**
604
  * @since 2.0.6
605
  */
619
  }
620
 
621
  $form_post = wp_nonce_url('admin.php?page=wp-clone', 'wpclone-submit');
622
+ $extra_fields = array( 'restore_from_url', 'maxmem', 'maxexec', 'zipmode', 'ignore_prefix', 'wipedb', 'mysql_check', 'restoreBackup', 'createBackup' );
623
  $type = '';
624
  if ( false === ($creds = request_filesystem_credentials($form_post, $type, false, false, $extra_fields)) ){
625
  return true;
666
  /**
667
  * @since 2.0.6
668
  */
669
+ function wpa_replace_prefix( $current, $new ){
670
+
671
  $wpconfig = wpa_wpconfig_path();
672
  global $wp_filesystem;
673
 
674
  if ( ! $wp_filesystem->is_writable($wpconfig) ) {
675
  if( false === $wp_filesystem->chmod( $wpconfig ) )
676
  wpa_backup_error('wpconfig', sprintf( __( "<code>%s</code> is not writable and wpclone was unable to change the file permissions." ), $wpconfig ), true );
677
+
678
+ }
679
+
680
+ $content = file( $wpconfig );
681
+
682
+ foreach( $content as $key => $value ) {
683
+
684
+ if( false !== strpos( $value, '$table_prefix' ) ) {
685
+ $content[$key] = str_replace( $current, $new, $value );
686
+ }
687
+
688
  }
689
 
690
+ $content = implode( $content );
691
+ $wp_filesystem->put_contents( $wpconfig, $content, 0600 );
692
+
 
 
693
  }
694
  /**
695
  * @since 2.0.6
696
  */
697
  function wpa_create_backup (){
698
+
699
  if( true === is_multisite() )
700
  die( 'wpclone does not work on multisite installs.' );
701
  if ( !file_exists(WPCLONE_DIR_BACKUP) ) {
704
  wpa_cleanup();
705
  $use_wpdb = isset( $_POST['use_wpdb'] ) && 'true' == $_POST['use_wpdb'] ? true : false;
706
  $backupName = wpa_backup_name();
707
+ $GLOBALS['wpclone']['logfile'] = $backupName . '.log';
708
+
709
+ wpa_wpc_log_start( 'backup' );
710
 
711
  $zipmode = isset($_POST['zipmode']) ? true : false;
712
  list($zipFileName, $zipSize) = CreateWPFullBackupZip($backupName, $zipmode, $use_wpdb);
713
 
714
  wpa_insert_data($zipFileName, $zipSize);
715
+ $backZipPath = convertPathIntoUrl(WPCLONE_DIR_BACKUP . $zipFileName . '.zip');
716
  $zipSize = bytesToSize($zipSize);
717
+ wpa_wpc_log( 'backup finished');
718
+
719
  echo <<<EOF
720
 
721
  <h1>Backup Successful!</h1>
730
 
731
  (Copy that link and paste it into the "Restore URL" of your new WordPress installation to clone this site)
732
  EOF;
733
+ printf( '</br><a href="%s">log</a>', convertPathIntoUrl( WPCLONE_DIR_BACKUP . $GLOBALS['wpclone']['logfile'] ) );
734
+ unset( $GLOBALS['wpclone'] );
735
  }
736
  /**
737
  * @since 2.0.6
749
  */
750
  function wpa_wpconfig_path () {
751
 
752
+ if ( file_exists( ABSPATH . 'wp-config.php') ) {
753
 
754
+ /** The config file resides in ABSPATH */
755
+ return ABSPATH . 'wp-config.php';
756
 
757
+ }
758
+ elseif ( file_exists( dirname(ABSPATH) . '/wp-config.php' ) && ! file_exists( dirname(ABSPATH) . '/wp-settings.php' ) ) {
759
 
760
+ /** The config file resides one level above ABSPATH but is not part of another install */
761
+ return dirname(ABSPATH) . '/wp-config.php';
762
 
763
+ }
764
+ else {
765
 
766
+ return false;
767
 
768
+ }
769
 
770
  }
771
 
773
  $z = pathinfo($path);
774
  global $wp_filesystem;
775
  if ( $wp_filesystem->is_file(WPCLONE_DIR_BACKUP . $z['basename']) ) {
776
+ wpa_wpc_log( 'file exists in the backup folder, filesize - ' . bytesToSize( filesize( WPCLONE_DIR_BACKUP . $z['basename'] ) ) );
777
  return WPCLONE_DIR_BACKUP . $z['basename'];
778
  }
779
  else {
780
+ wpa_wpc_log( 'file download started' );
781
  $url = download_url($path, 750);
782
+ if ( is_wp_error($url) ) {
783
+ wpa_backup_error( 'url', $url->get_error_message(), true );
784
+ }
785
+ wpa_wpc_log( 'download finished, filesize - ' . bytesToSize( filesize( $url ) ) );
786
  return $url;
787
  }
788
  }
789
 
790
  function wpa_backup_name() {
791
+ $backup_name = 'wpclone_backup_' . current_time( 'dS_M_Y_h-iA', false ) . '_' . get_option( 'blogname' );
792
  $backup_name = substr( str_replace( ' ', '', $backup_name ), 0, 40 );
793
  $rand_str = substr( str_shuffle( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" ), 0, 10 );
794
  $backup_name = sanitize_file_name( $backup_name ) . '_' . $rand_str;
798
  function wpa_backup_error($error, $data, $restore = false) {
799
 
800
  $temp_dir = $restore ? trailingslashit( WPCLONE_WP_CONTENT ) . 'wpclone-temp' : trailingslashit( WPCLONE_DIR_BACKUP ) . 'wpclone_backup';
801
+ $disp_dir = str_replace( WPCLONE_ROOT, '**SITE-ROOT**/', wpCloneSafePathMode( $temp_dir ) );
802
 
803
  if( !file_exists( $temp_dir ) ) {
804
  unset($temp_dir);
805
  }
806
+
807
  switch ( $error ) :
808
  /* during backup */
809
  case 'file' :
829
  $error = __( 'while cloning the database' );
830
  break;
831
  case 'unzip' :
832
+ $error = __( 'while extracting the zip file using php ziparchive' );
833
  break;
834
  case 'pclunzip' :
835
  $error = __( 'while extracting the zip file using the PclZip library' );
849
  printf( __( 'The plugin encountered an error %s,the following error message was returned:</br>' ), $error );
850
  echo '<div class="error">' . __( 'Error Message : ' ) . $data . '</div></br>';
851
  if( isset( $temp_dir ) ) {
852
+ printf( __( 'Temporary files created in <code>%s</code> will be deleted.' ), $disp_dir );
853
  echo '</div>';
854
  if( $restore ) {
855
  global $wp_filesystem;
929
  $ex = trim( $ex );
930
  if( '' !== $ex ) {
931
  $ex = trim( $ex, "/\\" );
932
+ wpa_wpc_log( sprintf( 'files inside "**SITE_ROOT**/wp-content/%s/" will not be included in the backup', $ex ) );
933
+ $exclude[] = wpCloneSafePathMode( trailingslashit( WPCLONE_WP_CONTENT ) . $ex ) ;
934
  }
935
  }
936
  }
945
 
946
  foreach( $i as $file => $info ) {
947
 
948
+ if( false === strpos( wpCloneSafePathMode( $file ), WPCLONE_DIR_BACKUP ) ) {
949
  $size += $info->getSize();
950
  $files++;
951
 
953
 
954
  }
955
 
956
+ $ret = array(
957
+ 'dbsize' => wpa_wpc_db_size(),
958
+ 'size' => bytesToSize( $size ),
959
+ 'files' => $files,
960
+ 'time' => time()
961
+ );
962
+
963
+ update_option( 'wpclone_directory_scan', $ret );
964
+ unset( $ret['time'] );
965
+ return $ret;
966
 
967
  }
968
 
971
  global $wpdb;
972
  $sql = 'SELECT sum(data_length + index_length) FROM information_schema.TABLES WHERE table_schema = "' . DB_NAME . '"';
973
  $size = $wpdb->get_var( $sql );
974
+ return bytesToSize( $size );
975
 
976
  }
977
 
1032
  function wpa_wpc_filter_list( $a, $b ) {
1033
 
1034
  $return = array();
1035
+ foreach( $a as $v ) {
1036
+ $return[$v] = '';
1037
+ }
1038
+ foreach( $b as $v ) {
1039
+ unset( $return[$v] );
1040
+ }
1041
  return array_keys( $return );
1042
 
1043
  }
1044
 
1045
+ function wpa_wpc_log( $msg ) {
1046
+
1047
+ if( ! isset( $GLOBALS['wpclone']['logfile'] ) ) {
1048
+ return;
1049
+ }
1050
+ $file = WPCLONE_DIR_BACKUP . $GLOBALS['wpclone']['logfile'];
1051
+ $time = date( 'l, d-M-Y H:i:s', time() + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) );
1052
+ $msg = $time . ' - ' . $msg . "\r\n";
1053
+ file_put_contents( $file, $msg, FILE_APPEND );
1054
+
1055
+ }
1056
+
1057
+ function wpa_wpc_log_start( $action ) {
1058
+
1059
+ global $wp_version;
1060
+ global $wpdb;
1061
+
1062
+ wpa_wpc_log( sprintf( '%s started', $action ) );
1063
+ wpa_wpc_log( 'wp version : ' . $wp_version );
1064
+ wpa_wpc_log( 'php version : ' . phpversion() );
1065
+ wpa_wpc_log( 'mysql version : ' . $wpdb->db_version() );
1066
+ wpa_wpc_log( 'memory limit : ' . ini_get( 'memory_limit' ) );
1067
+ wpa_wpc_log( 'execution time : ' . ini_get( 'max_execution_time' ) );
1068
+ wpa_wpc_log( 'mysql timeout : ' . ini_get( 'mysql.connect_timeout' ) );
1069
+ wpa_wpc_log( 'socket timeout : ' . ini_get( 'default_socket_timeout' ) );
1070
+
1071
+ }
1072
+
1073
+ function wpa_wpc_strpos_array( $array, $haystack ) {
1074
+
1075
+ foreach( $array as $needle ) {
1076
+ if( false !== strpos( $haystack, $needle ) ) {
1077
+ return true;
1078
+
1079
+ }
1080
+
1081
+ }
1082
+
1083
+ }
1084
+
1085
+ function wpa_wpc_get_filelist( $path, $exclude, $skip = false ) {
1086
+
1087
+ $i = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $path, FilesystemIterator::CURRENT_AS_SELF | FilesystemIterator::UNIX_PATHS | FilesystemIterator::SKIP_DOTS ) );
1088
+ $skipped = 0;
1089
+ $size = 0;
1090
+ $files = 0;
1091
+ $list = array();
1092
+
1093
+ foreach( $i as $file => $info ) {
1094
+
1095
+ $file = wpCloneSafePathMode( $file );
1096
+
1097
+ if( false !== strpos( $file, WPCLONE_DIR_BACKUP ) ) {
1098
+ continue;
1099
+ }
1100
+
1101
+ if( false !== strpos( $file, WPCLONE_DIR_PLUGIN ) ) {
1102
+ continue;
1103
+ }
1104
+
1105
+ if( ! empty( $exclude ) && wpa_wpc_strpos_array( $exclude, $file ) ) {
1106
+ $skipped++;
1107
+ wpa_wpc_log( sprintf( 'file is inside an excluded directory, and it will not be included in the backup - "%s"',
1108
+ str_replace( WPCLONE_ROOT, '**SITE-ROOT**/', $file ) ) );
1109
+ continue;
1110
+
1111
+ }
1112
+
1113
+ if( $skip && $info->getSize() > $skip ) {
1114
+ $skipped++;
1115
+ wpa_wpc_log( sprintf( 'file skipped, file is larger than %s - "%s" %s',
1116
+ bytesToSize( $skip ), str_replace( WPCLONE_ROOT, '**SITE-ROOT**/', $file ), bytesToSize( $info->getSize() ) ) );
1117
+ continue;
1118
+
1119
+ }
1120
+
1121
+ if( $info->isFile() ) {
1122
+ $list[] = $file;
1123
+ $files++;
1124
+ $size += $info->getSize();
1125
+
1126
+ }
1127
+
1128
+ }
1129
+
1130
+ if( $skipped > 0 ) {
1131
+ wpa_wpc_log( sprintf( '%d files were excluded from the backup', $skipped ) );
1132
+ }
1133
+
1134
+ wpa_wpc_log( sprintf( 'number of files to include in the archive is %d, and their uncompressed size is %s',
1135
+ $files, bytesToSize( $size ) ) );
1136
+
1137
+ return $list;
1138
+
1139
+ }
1140
+
1141
+
1142
+ function wpa_wpc_zip( $zh, $zipmode ) {
1143
+
1144
+ $file = WPCLONE_DIR_BACKUP . 'wpclone_backup/file.list';
1145
+
1146
+ if( is_readable( $file ) ) {
1147
+ $filelist = unserialize( file_get_contents( $file ) );
1148
+
1149
+ } else {
1150
+ return false;
1151
+
1152
+ }
1153
+
1154
+ if( $zipmode ) {
1155
+ return $filelist;
1156
+
1157
+ }
1158
+
1159
+ foreach( $filelist as $file ) {
1160
+ $zh->addFile( $file, str_replace( WPCLONE_ROOT, 'wpclone_backup/', $file ) );
1161
+
1162
+ }
1163
+
1164
+ $zh->deleteName( 'wpclone_backup/file.list' );
1165
+
1166
+ }
1167
+
1168
+ function wpa_wpc_unzip( $zipfile, $temp_dir ) {
1169
+
1170
+ $z = new ZipArchive();
1171
+
1172
+ if( true === $z->open( $zipfile ) ) {
1173
+ $z->extractTo( $temp_dir );
1174
+
1175
+ } else {
1176
+ wpa_wpc_log( sprintf( 'failed to open the zip file : %s', $z->getStatusString() ) );
1177
+ wpa_backup_error( 'unzip', $z->getStatusString(), true );
1178
+
1179
+ }
1180
+
1181
+ }
1182
+
1183
+ function wpa_wpc_get_db( $zipfile, $zipmode ) {
1184
+
1185
+ $ret = array();
1186
+ if( $zipmode || ( ! in_array( 'ZipArchive', get_declared_classes() ) || ! class_exists( 'ZipArchive' ) ) ) {
1187
+
1188
+ wpa_wpc_log( 'extracting database using pclzip' );
1189
+
1190
+ if ( ini_get('mbstring.func_overload') && function_exists('mb_internal_encoding') ) {
1191
+ $previous_encoding = mb_internal_encoding();
1192
+ mb_internal_encoding('ISO-8859-1');
1193
+ }
1194
+
1195
+ require_once ( ABSPATH . 'wp-admin/includes/class-pclzip.php' );
1196
+ $z = new PclZip($zipfile);
1197
+ $database = $z->extract( PCLZIP_OPT_BY_NAME, 'wpclone_backup/database.sql', PCLZIP_OPT_EXTRACT_AS_STRING );
1198
+ $prefix = $z->extract( PCLZIP_OPT_BY_NAME, 'wpclone_backup/prefix.txt', PCLZIP_OPT_EXTRACT_AS_STRING );
1199
+
1200
+ if ( isset( $previous_encoding ) ) {
1201
+ mb_internal_encoding($previous_encoding);
1202
+
1203
+ }
1204
+
1205
+ if( 'ok' === $database[0]['status'] && 'ok' === $prefix[0]['status'] ) {
1206
+ $ret['database'] = $database[0]['content'];
1207
+ $ret['prefix'] = $prefix[0]['content'];
1208
+
1209
+ } else {
1210
+ wpa_backup_error( 'pclunzip', $z->errorInfo(true), true );
1211
+
1212
+ }
1213
+
1214
+ return $ret;
1215
+
1216
+ } else {
1217
+
1218
+ $z = new ZipArchive();
1219
+
1220
+ if( true === $z->open( $zipfile ) ) {
1221
+
1222
+ wpa_wpc_log( 'extracting database using ziparchive' );
1223
+ $ret['database'] = $z->getFromName( 'wpclone_backup/database.sql' );
1224
+ $ret['prefix'] = $z->getFromName( 'wpclone_backup/prefix.txt' );
1225
+ if( false === $ret['database'] || false === $ret['prefix'] ) {
1226
+ wpa_backup_error( 'unzip', $z->getStatusString(), true );
1227
+
1228
+ }
1229
+
1230
+ $z->close();
1231
+ return $ret;
1232
+
1233
+ } else {
1234
+ wpa_backup_error( 'unzip', $z->getStatusString(), true );
1235
+
1236
+ }
1237
+
1238
+ }
1239
+
1240
+ }
1241
+
1242
+ function wpa_wpc_process_db( $zipfile, $zipmode = false ) {
1243
+
1244
+ $files = wpa_wpc_get_db( $zipfile, $zipmode );
1245
+
1246
+ $prefix = wpa_wpc_get_prefix( $files['prefix'] );
1247
+ $old_url = untrailingslashit( wpa_wpc_get_url( $files['database'] ) );
1248
+ $cur_url = untrailingslashit( site_url() );
1249
+ $found = false;
1250
+ $db = explode( ";\n", $files['database'] );
1251
+ $link = wpa_wpc_mysql_connect();
1252
+
1253
+ wpa_wpc_log( 'database import started' );
1254
+ foreach( $db as $query ) {
1255
+
1256
+ if( ! $found && false !== strpos( $query, '"siteurl",' ) ) {
1257
+ $query = str_replace( $old_url, $cur_url, $query, $count );
1258
+ wpa_wpc_log( sprintf( 'updating mysql query with current site\'s url - new query : "%s"', ltrim( $query ) ) );
1259
+ if( $count > 0 ) {
1260
+ $found = true;
1261
+
1262
+ }
1263
+
1264
+ }
1265
+
1266
+ if( isset( $_POST['mysql_check'] ) && 'true' === $_POST['mysql_check'] ) {
1267
+ if( ! mysql_ping( $link ) ) {
1268
+ mysql_close( $link );
1269
+ $link = wpa_wpc_mysql_connect();
1270
+
1271
+ }
1272
+
1273
+ }
1274
+
1275
+ $status = mysql_query( $query, $link );
1276
+
1277
+ if( false === $status ) {
1278
+ wpa_wpc_log( sprintf( 'mysql query failed. error : %d %s - query : "%s"', mysql_errno(), mysql_error(), ltrim( $query ) ) );
1279
+
1280
+ }
1281
+
1282
+ }
1283
+ wpa_wpc_log( 'database import finished' );
1284
+
1285
+ if( $cur_url === $old_url ) {
1286
+ wpa_wpc_log( 'URLs are similar, skipping search and replace' );
1287
+ $report = 'Search and replace did not run because the URLs are similar';
1288
+
1289
+ } else {
1290
+ $report = wpa_safe_replace_wrapper( $old_url, $cur_url, $prefix );
1291
+
1292
+ }
1293
+
1294
+ return $report;
1295
+
1296
+
1297
+ }
1298
+
1299
+ function wpa_wpc_get_prefix( $prev_prefix ) {
1300
+
1301
+ global $wpdb;
1302
+ $cur_prefix = $wpdb->prefix;
1303
+
1304
+ if ( $cur_prefix !== $prev_prefix ) {
1305
+ wpa_wpc_log( sprintf( 'changing prefix from "%s" to "%s"', $cur_prefix, $prev_prefix ) );
1306
+ wpa_replace_prefix( $cur_prefix, $prev_prefix );
1307
+ $cur_prefix = $prev_prefix;
1308
+
1309
+ }
1310
+
1311
+ return $cur_prefix;
1312
+
1313
+ }
1314
+
1315
 
1316
  /* end of file */
lib/js/backupmanager.js CHANGED
@@ -1,4 +1,3 @@
1
-
2
  jQuery(function($) {
3
 
4
  initialize();
@@ -15,6 +14,22 @@ jQuery(function($) {
15
 
16
  function bindActions() {
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  $("input[id='fullBackup']").click(function() {
19
 
20
  $("#RestoreOptions").hide("fast");
@@ -58,12 +73,12 @@ jQuery(function($) {
58
 
59
  $("input[name$='backupUrl']").click(function() {
60
  prepareBackUrlOption();
61
- $("input#submit").removeClass("btn-primary").addClass("btn-warning");
62
  });
63
 
64
  $("input[name$='restore_from_url']").focus(function() {
65
  prepareBackUrlOption();
66
- $("input#submit").removeClass("btn-primary").addClass("btn-warning");
67
  });
68
 
69
  $("input#submit").click(function() {
@@ -118,7 +133,7 @@ jQuery(function($) {
118
  $("#backupChoices").show("fast");
119
  $("input#submit").val("Create Backup").removeClass("btn-warning").addClass("btn-primary");
120
  $("input[id='fullBackup']").attr('checked',
121
- $("input[name$='createBackup']").is(':checked') && !$("input[id$='customBackup']").is(':checked'));
122
  }
123
 
124
  function getSize() {
@@ -132,11 +147,15 @@ jQuery(function($) {
132
  },
133
  success: function(data){
134
  data = $.parseJSON(data);
135
- $("span#filesize").html( "There are <code>" + data.files + "</code> files to backup, and their total size is <code>" + data.size + "</code>. Database size is <code>" + data.dbsize + "</code>." );
 
 
 
 
136
  },
137
  error: function(e){
138
  $("span#filesize").html( "Unable to calculate size." );
139
- }
140
  });
141
 
142
  }
@@ -227,4 +246,37 @@ jQuery(function($) {
227
 
228
  }
229
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  });
 
1
  jQuery(function($) {
2
 
3
  initialize();
14
 
15
  function bindActions() {
16
 
17
+ $("a#close-thickbox").click(function(e) {
18
+ e.preventDefault();
19
+ tb_remove();
20
+ $("div#search-n-replace-info").html('');
21
+ $("input[name='searchfor'], input[name='replacewith']").val('');
22
+ $("input[name='ignoreprefix']").attr('checked', false);
23
+ });
24
+
25
+ $("input[name='search-n-replace-submit']").click(function(e) {
26
+ e.preventDefault();
27
+ if( $(this).data("working") ) return;
28
+ $("#search-n-replace-info").html('').css( 'background', 'url(' + wpclone.spinner + ') no-repeat center' )
29
+ $(this).data("working", true);
30
+ search_and_replace();
31
+ });
32
+
33
  $("input[id='fullBackup']").click(function() {
34
 
35
  $("#RestoreOptions").hide("fast");
73
 
74
  $("input[name$='backupUrl']").click(function() {
75
  prepareBackUrlOption();
76
+ $("input#submit").removeClass("btn-primary").addClass("btn-warning");
77
  });
78
 
79
  $("input[name$='restore_from_url']").focus(function() {
80
  prepareBackUrlOption();
81
+ $("input#submit").removeClass("btn-primary").addClass("btn-warning");
82
  });
83
 
84
  $("input#submit").click(function() {
133
  $("#backupChoices").show("fast");
134
  $("input#submit").val("Create Backup").removeClass("btn-warning").addClass("btn-primary");
135
  $("input[id='fullBackup']").attr('checked',
136
+ $("input[name$='createBackup']").is(':checked') && !$("input[id$='customBackup']").is(':checked'));
137
  }
138
 
139
  function getSize() {
147
  },
148
  success: function(data){
149
  data = $.parseJSON(data);
150
+ var cache = '';
151
+ if( 'undefined' !== typeof data.time ) {
152
+ cache = '</br>(calculated ' + data.time + ' minute[s] ago.)';
153
+ }
154
+ $("span#filesize").html( "Number of files in wp-content directory - <code>" + data.files + "</code>, and their total size - <code>" + data.size + "</code> (files larger than 25MB will be excluded from the backup, you can change it from advanced settings) </br>Database size is <code>" + data.dbsize + "</code>." + cache );
155
  },
156
  error: function(e){
157
  $("span#filesize").html( "Unable to calculate size." );
158
+ }
159
  });
160
 
161
  }
246
 
247
  }
248
 
249
+ function search_and_replace() {
250
+
251
+ var prefix = '';
252
+
253
+ if( $("input[name='ignoreprefix']").prop("checked") ) {
254
+ prefix = 'true';
255
+ }
256
+
257
+ $.ajax({
258
+ url: ajaxurl,
259
+ type: 'post',
260
+ data: {
261
+ action : 'wpclone-search-n-replace',
262
+ search : $("input[name='searchfor']").val(),
263
+ replace: $("input[name='replacewith']").val(),
264
+ ignore_prefix : prefix,
265
+ nonce : wpclone.nonce
266
+ },
267
+ success: function(data) {
268
+ $("div#search-n-replace-info").css('background', '').append(data);
269
+ },
270
+ error: function(e){
271
+ console.log(e);
272
+ },
273
+ complete: function(){
274
+ $("input[name='search-n-replace-submit']").removeData("working");
275
+ }
276
+
277
+ });
278
+
279
+ }
280
+
281
+
282
  });
lib/view.php CHANGED
@@ -41,6 +41,18 @@ if (wpa_wpfs_init()) return;
41
  if( false === get_option( 'wpclone_backups' ) ) wpa_wpc_import_db();
42
  $backups = get_option( 'wpclone_backups' );
43
  ?>
 
 
 
 
 
 
 
 
 
 
 
 
44
  <div id="wrapper">
45
  <div id="MainView">
46
 
@@ -60,26 +72,43 @@ $backups = get_option( 'wpclone_backups' );
60
  <form id="backupForm" name="backupForm" action="#" method="post">
61
  <?php
62
  if ( isset($_GET['mode']) && 'advanced' == $_GET['mode'] ) { ?>
63
- <div class="info">
64
  <table>
65
  <tr align="left"><th colspan=""><label for="zipmode">Alternate zip method</label></th><td colspan="2"><input type="checkbox" name="zipmode" value="alt" /></td></tr>
66
  <tr align="left"><th><label for="use_wpdb">Use wpdb to backup the database</label></th><td colspan="2"><input type="checkbox" name="use_wpdb" value="true" /></td></tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  <tr><td colspan="4"><h3>Overriding the Maximum memory and Execution time</h3></td></tr>
68
  <tr><td colspan="4"><p>You can use these two fields to override the maximum memory and execution time on most hosts.</br>
69
- For example, if you want to increase the RAM to 1GB, enter <code>1024</code> into the Maximum memory limit field.</br>
70
- And if you want to increase the execution time to 10 minutes, enter <code>600</code> into the Script execution time field.</br>
71
- Default values will be used if you leave them blank. The default value for RAM is 512MB and the default value for execution time is 300 seconds (five minutes).</p></td></tr>
72
  <tr align="left"><th><label for="maxmem">Maximum memory limit</label></th><td colspan="2"><input type="text" name="maxmem" /></td></tr>
73
  <tr align="left"><th><label for="maxexec">Script execution time</label></th><td><input type="text" name="maxexec" /></td></tr>
74
  <tr><td colspan="4"><h3>Exclude directories from backup, and backup database only</h3></td></tr>
75
  <tr><td colspan="4"><p>Depending on your web host, WP Clone may not work for large sites.
76
  You may, however, exclude all of your 'wp-content' directory from the backup (use "Backup database only" option below), or exclude specific directories.
77
- You would then copy these files over to the new site via FTP before restoring the backup with WP Clone.</p></td></tr>
 
 
78
  <tr align="left"><th><label for="dbonly">Backup database only</label></th><td colspan="2"><input type="checkbox" name="dbonly" value="true" /></td></tr>
 
79
  <tr align="left"><th><label for="exclude">Excluded directories</label></th><td><textarea cols="70" rows="5" name="exclude" ></textarea></td></tr>
80
  <tr><th></th><td colspan="5"><p>Enter one per line, i.e. <code>uploads/backups</code>,use the forward slash <code>/</code> as the directory separator. Directories start at 'wp-content' level.</br>
81
  </br>For example, BackWPup saves its backups into <code>/wp-content/uploads/backwpup-abc123-backups/</code> (the middle part, 'abc123' in this case, is random characters).
82
- If you wanted to exclude that directory, you have to enter <code>uploads/backwpup-abc123-backups</code> into the above field.</p></td></tr>
83
  </table>
84
  </div>
85
  <?php
@@ -111,9 +140,16 @@ $backups = get_option( 'wpclone_backups' );
111
  <a href="<?php echo $filename ?>" class="zclip"> (<?php echo bytesToSize($backup['size']);?>)&nbsp;&nbsp;<?php echo $backup['name'] ?></a>
112
  <input type="hidden" name="backup_name" value="<?php echo $filename ?>" />
113
  </td>
114
-
 
 
 
 
 
 
115
  <td><a class="copy-button" href="#" data-clipboard-text="<?php echo $filename ?>" >Copy URL</a></td>
116
  <td><a href="<?php echo $url; ?>" class="delete" data-fileid="<?php echo $key; ?>">Delete</a></td>
 
117
  </tr>
118
 
119
  <?php endforeach ?>
@@ -141,7 +177,9 @@ $backups = get_option( 'wpclone_backups' );
141
  </div>
142
 
143
  <input id="submit" name="submit" class="btn-primary btn" type="submit" value="Create Backup"/>
144
- <?php wp_nonce_field('wpclone-submit')?>
 
 
145
  </form>
146
  <?php
147
  if(!isset($_GET['mode'])){
@@ -158,6 +196,8 @@ $backups = get_option( 'wpclone_backups' );
158
  echo "<p><a href='#' id='uninstall' class='button' style='margin-top:10px'>Delete backups and remove database entries</a>"
159
  . "</br>WP Clone does not remove backups when you deactivate the plugin. Use the above button if you want to remove all the backups.</p>";
160
 
 
 
161
 
162
  ?>
163
  </div>
@@ -196,18 +236,24 @@ $backups = get_option( 'wpclone_backups' );
196
 
197
  function wpa_wpc_sysinfo(){
198
  global $wpdb;
199
- echo '<div class="info">';
200
  echo '<h3>System Info:</h3><p>';
201
- echo 'Memory limit: ' . ini_get('memory_limit') . '</br>';
 
 
 
 
 
202
  echo 'Maximum execution time: ' . ini_get('max_execution_time') . ' seconds</br>';
203
  echo 'PHP version : ' . phpversion() . '</br>';
204
  echo 'MySQL version : ' . $wpdb->db_version() . '</br>';
205
  if (ini_get('safe_mode')) { echo '<span style="color:#f11">PHP is running in safemode!</span></br>'; }
 
206
  if ( ! file_exists( WPCLONE_DIR_BACKUP ) ) {
207
  echo 'Backup path :<span style="color:#660000">Backup directory not found. '
208
  . 'Unless there is a permissions or ownership issue, refreshing the backup list should create the directory.</span></br>';
209
  } else {
210
- echo 'Backup path : <code>' . WPCLONE_DIR_BACKUP . '</code></br>';
211
  }
212
  echo 'Files : <span id="filesize"><img src="' . esc_url( admin_url( 'images/spinner.gif' ) ) . '"></span></br>';
213
  if ( file_exists( WPCLONE_DIR_BACKUP ) && !is_writable(WPCLONE_DIR_BACKUP)) { echo '<span style="color:#f11">Backup directory is not writable, please change its permissions.</span></br>'; }
41
  if( false === get_option( 'wpclone_backups' ) ) wpa_wpc_import_db();
42
  $backups = get_option( 'wpclone_backups' );
43
  ?>
44
+ <div id="search-n-replace">
45
+ <a href="#" id="close-thickbox" class="button">X</a>
46
+ <form name="searchnreplace" action="#" method="post">
47
+ <table class="searchnreplace">
48
+ <tr><th><label for="searchfor">Search for</label></th><td colspan="5"><input type="text" name="searchfor" /></td></tr>
49
+ <tr><th><label for="replacewith">Replace with</label></th><td colspan="5"><input type="text" name="replacewith" /></td></tr>
50
+ <tr><th><label for="ignoreprefix">Ignore table prefix</label></th><td colspan="2"><input type="checkbox" name="ignoreprefix" value="true" /></td></tr>
51
+ </table>
52
+ <input type="submit" class="button" name="search-n-replace-submit" value="Run">
53
+ </form>
54
+ <div id="search-n-replace-info"></div>
55
+ </div>
56
  <div id="wrapper">
57
  <div id="MainView">
58
 
72
  <form id="backupForm" name="backupForm" action="#" method="post">
73
  <?php
74
  if ( isset($_GET['mode']) && 'advanced' == $_GET['mode'] ) { ?>
75
+ <div class="info width-60">
76
  <table>
77
  <tr align="left"><th colspan=""><label for="zipmode">Alternate zip method</label></th><td colspan="2"><input type="checkbox" name="zipmode" value="alt" /></td></tr>
78
  <tr align="left"><th><label for="use_wpdb">Use wpdb to backup the database</label></th><td colspan="2"><input type="checkbox" name="use_wpdb" value="true" /></td></tr>
79
+ <tr align="left"><th><label for="ignore_prefix">Ignore table prefix</label></th><td colspan="2"><input type="checkbox" name="ignore_prefix" value="true" /></td></tr>
80
+ <tr>
81
+ <td colspan="4">
82
+ <p>If enabled during a backup, all the tables in the database will be included in the backup.</br>
83
+ If enabled during a restore, search and replace will alter all the tables in the database.</br>
84
+ By default, only the tables that share the wordpress table prefix are included/altered during a backup/restore.</p>
85
+ </td>
86
+ </tr>
87
+ <tr align="left"><th><label for="mysql_check">Refresh MySQL connection during Restore</label></th><td colspan="2"><input type="checkbox" name="mysql_check" value="true" /></td></tr>
88
+ <tr>
89
+ <td colspan="4">
90
+ <p>This will check the MySQL connection inside the main loop before each database query during restore. Enable this if the restored site is incomplete.</p>
91
+ </td>
92
+ </tr>
93
  <tr><td colspan="4"><h3>Overriding the Maximum memory and Execution time</h3></td></tr>
94
  <tr><td colspan="4"><p>You can use these two fields to override the maximum memory and execution time on most hosts.</br>
95
+ For example, if you want to increase the RAM to 2GB, enter <code>2048</code> into the Maximum memory limit field.</br>
96
+ And if you want to increase the execution time to 15 minutes, enter <code>900</code> into the Script execution time field.</br>
97
+ Default values will be used if you leave them blank. The default value for RAM is 1024MB and the default value for execution time is 600 seconds (ten minutes).</p></td></tr>
98
  <tr align="left"><th><label for="maxmem">Maximum memory limit</label></th><td colspan="2"><input type="text" name="maxmem" /></td></tr>
99
  <tr align="left"><th><label for="maxexec">Script execution time</label></th><td><input type="text" name="maxexec" /></td></tr>
100
  <tr><td colspan="4"><h3>Exclude directories from backup, and backup database only</h3></td></tr>
101
  <tr><td colspan="4"><p>Depending on your web host, WP Clone may not work for large sites.
102
  You may, however, exclude all of your 'wp-content' directory from the backup (use "Backup database only" option below), or exclude specific directories.
103
+ You would then copy these files over to the new site via FTP before restoring the backup with WP Clone.</p>
104
+ <p>You could also skip files that are larger than the value entered into the below field. For example, enter <code>100</code> if you want to skip files larger than 100MB.
105
+ The default value of 25MB will be used If you leave it blank. Enter <code>0</code> if you want to disable it.</p></td></tr>
106
  <tr align="left"><th><label for="dbonly">Backup database only</label></th><td colspan="2"><input type="checkbox" name="dbonly" value="true" /></td></tr>
107
+ <tr align="left"><th><label for="skipfiles">Skip files larger than</label></th><td><input type="text" name="skipfiles" />&nbsp;<strong>MB</strong></td></tr>
108
  <tr align="left"><th><label for="exclude">Excluded directories</label></th><td><textarea cols="70" rows="5" name="exclude" ></textarea></td></tr>
109
  <tr><th></th><td colspan="5"><p>Enter one per line, i.e. <code>uploads/backups</code>,use the forward slash <code>/</code> as the directory separator. Directories start at 'wp-content' level.</br>
110
  </br>For example, BackWPup saves its backups into <code>/wp-content/uploads/backwpup-abc123-backups/</code> (the middle part, 'abc123' in this case, is random characters).
111
+ If you wanted to exclude that directory, you have to enter <code>uploads/backwpup-abc123-backups</code> into the above field.</p></td></tr>
112
  </table>
113
  </div>
114
  <?php
140
  <a href="<?php echo $filename ?>" class="zclip"> (<?php echo bytesToSize($backup['size']);?>)&nbsp;&nbsp;<?php echo $backup['name'] ?></a>
141
  <input type="hidden" name="backup_name" value="<?php echo $filename ?>" />
142
  </td>
143
+ <?php
144
+ if( isset( $backup['log'] ) ){
145
+ printf( '<td><a href="%s">log</a></td>', convertPathIntoUrl(WPCLONE_DIR_BACKUP . $backup['log'] ) );
146
+ } else {
147
+ echo '<td>&mdash;</td>';
148
+ }
149
+ ?>
150
  <td><a class="copy-button" href="#" data-clipboard-text="<?php echo $filename ?>" >Copy URL</a></td>
151
  <td><a href="<?php echo $url; ?>" class="delete" data-fileid="<?php echo $key; ?>">Delete</a></td>
152
+
153
  </tr>
154
 
155
  <?php endforeach ?>
177
  </div>
178
 
179
  <input id="submit" name="submit" class="btn-primary btn" type="submit" value="Create Backup"/>
180
+
181
+
182
+ <?php wp_nonce_field('wpclone-submit')?>
183
  </form>
184
  <?php
185
  if(!isset($_GET['mode'])){
196
  echo "<p><a href='#' id='uninstall' class='button' style='margin-top:10px'>Delete backups and remove database entries</a>"
197
  . "</br>WP Clone does not remove backups when you deactivate the plugin. Use the above button if you want to remove all the backups.</p>";
198
 
199
+ echo '<p><a href="#TB_inline?height=200&width=600&inlineId=search-n-replace&modal=true" class="thickbox">Search and Replace</a></p>';
200
+
201
 
202
  ?>
203
  </div>
236
 
237
  function wpa_wpc_sysinfo(){
238
  global $wpdb;
239
+ echo '<div class="info width-60">';
240
  echo '<h3>System Info:</h3><p>';
241
+ echo 'Memory limit: ' . ini_get('memory_limit');
242
+ if( false === ini_set( 'memory_limit', '257M' ) ) {
243
+ echo '&nbsp;<span style="color:#660000">memory limit cannot be increased</span></br>';
244
+ } else {
245
+ echo '</br>';
246
+ }
247
  echo 'Maximum execution time: ' . ini_get('max_execution_time') . ' seconds</br>';
248
  echo 'PHP version : ' . phpversion() . '</br>';
249
  echo 'MySQL version : ' . $wpdb->db_version() . '</br>';
250
  if (ini_get('safe_mode')) { echo '<span style="color:#f11">PHP is running in safemode!</span></br>'; }
251
+ printf( 'Root directory : <code>%s</code></br>', WPCLONE_ROOT );
252
  if ( ! file_exists( WPCLONE_DIR_BACKUP ) ) {
253
  echo 'Backup path :<span style="color:#660000">Backup directory not found. '
254
  . 'Unless there is a permissions or ownership issue, refreshing the backup list should create the directory.</span></br>';
255
  } else {
256
+ echo 'Backup directory : <code>' . WPCLONE_DIR_BACKUP . '</code></br>';
257
  }
258
  echo 'Files : <span id="filesize"><img src="' . esc_url( admin_url( 'images/spinner.gif' ) ) . '"></span></br>';
259
  if ( file_exists( WPCLONE_DIR_BACKUP ) && !is_writable(WPCLONE_DIR_BACKUP)) { echo '<span style="color:#f11">Backup directory is not writable, please change its permissions.</span></br>'; }
readme.txt CHANGED
@@ -5,8 +5,8 @@ Tags: wp academy, wpacademy, move wordpress, copy wordpress, clone wordpress, in
5
  Author URI: http://wpacademy.com
6
  Plugin URI: http://wpacademy.com/software
7
  Requires at least: 3.0
8
- Tested up to: 4.3
9
- Stable tag: 2.2
10
  License: GPLv2 or later
11
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
12
 
@@ -24,28 +24,30 @@ WP Clone is a superior solution to even commercial WordPress cloning plugins for
24
  * It uses the WordPress internal zip archive function, which makes it compatible with virtually 100% of hosts that support WordPress (no special PHP libraries are required)
25
 
26
  <blockquote>
27
- = Update September 2015 =
28
- As mentioned below, WP Clone fails in 10-20% of installations, as reflected in the negative reviews (although note that negative reviews are not representative of the failure rate, as more people will leave negative reviews for failure than those people who will leave positive reviews for success. We have reports of successful transfers of 3GB sites). We are working to correct these failures, and we would love some assistance here, so please let us know (at marc@wpacademy.com) if you would like to help out with plugin development.
29
- <br />Note also that WP Clone should NOT be used on WP Engine or any hosting system with proprietary operating system. Instead, use their built-in tools.<br />
30
-
31
- = Update April 2015 =
32
- WP Clone fails to restore in about 10-20% of installations. This appears to be related to the hosting platform rather than the WordPress version. We are attempting to isolate this problem and determine the types of installations that fail in order to update the plugin. Under no circumstances should the source (origin) site ever be damaged or destroyed.
33
- Feel free to leave a negative review and details of your failure on the support forum, but please be polite as we do not receive any remuneration for writing and supporting this plugin. We will investigate as we can. As a reminder also to never overwrite an installation for which you do not have a backup -- in normal usage this plugin would be used only to overwrite a new (or blank) WordPress installation. Thanks -- WP Academy Support
34
  </blockquote>
35
 
36
  = Help Video =
37
  [youtube http://www.youtube.com/watch?v=xN5Ffhyn4Ao]
38
 
39
- = New features (July 2013): Exclude directories and Database-only backup =
40
- We have implemented exclude-directories on the backup, and also database-only backup! By transferring the contents of 'wp-content' directory with FTP from your old site to new site, you should now be able to migrate sites of any size.
 
 
 
 
 
 
 
 
41
 
42
- = Support and Disclaimer =
43
- No WordPress backup plugin will work reliably on all hosts. If you have any problems, try doing a "Database Only" backup (use "Advanced Options"), transfer the wp-content directory over with FTP, and then restore new site. You should also deactivate and delete any page caching plugins (i.e. W3 Total Cache) before backup.
44
- If you still have an issue, please post to the WordPress.org support forum where we support this plugin for free, and we'll respond on a "best-effort" basis. You can also try the Duplicator plugin http://wordpress.org/plugins/duplicator/ or All-in-One WP Migration https://wordpress.org/plugins/all-in-one-wp-migration/, both of which work pretty good, but are not as fast as WP Clone to migrate sites; or use the manual method described here http://members.wpacademy.com/ww3.htm?moving-wordpress.htm
45
 
46
- = Please donate to support plugin development & ongoing support =
47
- WP Clone is provided free of charge to the community and supported through the plugin forums on WordPress.org. Please help defray our development expenses and help with support costs through the [Donations Page](http://wpacademy.com/software "Donations page")
48
- Donation page.
49
 
50
  = Additional documentation =
51
  Additional documentation, including supported hosts, at the [WP Clone FAQ Page](http://members.wpacademy.com/wpclone-faq "WP Clone FAQ")
@@ -54,6 +56,7 @@ Additional documentation, including supported hosts, at the [WP Clone FAQ Page](
54
  WP Clone uses functions from the "Safe Search and Replace on Database with Serialized Data" script first written by David Coveney of Interconnect IT Ltd (UK) http://www.davidcoveney.com or http://www.interconnectit.com and
55
  released under the WTFPL http://sam.zoy.org/wtfpl/. Partial script with full changelog is placed inside 'lib/files' directory.
56
 
 
57
 
58
  == Installation ==
59
 
@@ -66,6 +69,21 @@ released under the WTFPL http://sam.zoy.org/wtfpl/. Partial script with full cha
66
  Review FAQ's and Help Video at the [WP Clone FAQ Page](http://members.wpacademy.com/wpclone-faq "WP Clone FAQ")
67
 
68
  == Changelog ==
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  = 2.2 - 2015-11-16 =
70
  * Fixed: Missing backups that some users encountered after upgrading to 2.1.9
71
  * Added: An option to refresh the backup list.
5
  Author URI: http://wpacademy.com
6
  Plugin URI: http://wpacademy.com/software
7
  Requires at least: 3.0
8
+ Tested up to: 4.4
9
+ Stable tag: 2.2.1
10
  License: GPLv2 or later
11
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
12
 
24
  * It uses the WordPress internal zip archive function, which makes it compatible with virtually 100% of hosts that support WordPress (no special PHP libraries are required)
25
 
26
  <blockquote>
27
+ = Update December 2015 =
28
+ Prior to the latest update, WP Clone was failing in 10-20% of installations (particularly larger installations), as reflected in the negative reviews.
29
+ Since the latest update, we have successfully restored 2GB sites, but we cannot guarantee the reliability on all installations.
30
+ <strong>Please carefully read the section below NO SUPPORT AND DISCLAIMER before you attempt to use this plugin.</strong>
 
 
 
31
  </blockquote>
32
 
33
  = Help Video =
34
  [youtube http://www.youtube.com/watch?v=xN5Ffhyn4Ao]
35
 
36
+ = NO SUPPORT AND DISCLAIMER =
37
+ As mentioned above, WP Clone fails in 10-20% of installations. As such it is NOT intended as a regular backup method, its strength consists in migrating WordPress installations. The failures appear to be related to the multiplicity of WordPress hosting platforms and the size of the installation rather than the WordPress version (so please don't feedback "WP Clone does not work for my version of WordPress", this is most probably false). Do however, leave negative reviews and open a discussion on the support forum if you get a failure, providing as much detail as possible, including your hosting system and the size of your site. We will likely not be able to respond, but the information will be useful in helping to isolate the problems with the different hosting systems. Thank you.
38
+
39
+ = Recommendations for using (or not) WP Clone =
40
+ * NEVER overwrite an installation for which you do not have an alternate backup source (i.e. a cPanel backup). Normally you would restore onto a fresh WP installation on another host or on a subdomain. If the restore fails your destination site might become unusable, so be prepared to enter cPanel and then destroy / recreate the new installation if necessary.
41
+ * There is never an issue in damaging the source installation. So backup sites at your pleasure. If your backup succeeds it is probable that your restore will also succeed. But don't take any chances.
42
+ * Large sites (>2GB) might take as long as an hour to backup. Sites of 250 MB or less should take no more than a minute or two, depending on your server.
43
+ * We recommend you deactivate and delete page caching, security and maybe redirection plugins and re-install them on the new site, if necessary. In general, delete all unnecessary plugins and data from your site before you backup. You can also use the "Exclude directories" option if you have large media files, which you can then copy back to the new site with FTP.
44
+ * An alternate method that should work in 99% of installations is to do a "Database Only" backup (use "Advanced Settings"), transfer the wp-content directory over with FTP, and then restore new site.
45
+ * Note also that WP Clone should NOT be used on WP Engine or any hosting system with proprietary operating system. Instead, use their built-in tools.
46
 
47
+ You can also try the [Duplicator plugin](https://wordpress.org/plugins/duplicator/) or [All-in-One WP Migration](https://wordpress.org/plugins/all-in-one-wp-migration/), both of which work pretty good, but are not as fast as WP Clone to migrate sites; or use the manual method described here http://wpencyclopedia.com/enc/index.htm?moving-wordpress.htm
 
 
48
 
49
+ = Donations =
50
+ Although we are not able to provide support to every installation, we have spent countless hours improving the plugin and responding to user feedback. We believe that WP Clone is far and away the easiest WordPress restoration plugin and intend to continue to develop it. If you are able to support our efforts, use the Donations Page.
 
51
 
52
  = Additional documentation =
53
  Additional documentation, including supported hosts, at the [WP Clone FAQ Page](http://members.wpacademy.com/wpclone-faq "WP Clone FAQ")
56
  WP Clone uses functions from the "Safe Search and Replace on Database with Serialized Data" script first written by David Coveney of Interconnect IT Ltd (UK) http://www.davidcoveney.com or http://www.interconnectit.com and
57
  released under the WTFPL http://sam.zoy.org/wtfpl/. Partial script with full changelog is placed inside 'lib/files' directory.
58
 
59
+ If you are able to help out with plugin development or wish to contribute insights into improving the product, we would also appreciate that very much. Write to marc@wpacademy.com.
60
 
61
  == Installation ==
62
 
69
  Review FAQ's and Help Video at the [WP Clone FAQ Page](http://members.wpacademy.com/wpclone-faq "WP Clone FAQ")
70
 
71
  == Changelog ==
72
+ = 2.2.1 - 2015-12-29 =
73
+ * Fixed: Backup names will use the time zone selected in general settings.
74
+ * Added: basic backup/restore logs.
75
+ * Added: An option to exclude files based on size (files larger than 25MB will be excluded by default)
76
+ * Added: An option to ignore the wordpress table prefix during backup/restore.
77
+ * Added: An option to check the mysql connection during restore.
78
+ * Added: A search and replace tool into the plugin dashboard.
79
+ * Changed: A .htaccess file will be placed in the temporary directories to prevent external access to the files.
80
+ * Changed: Files are no longer copied to a temporary location during backup.
81
+ * Changed: Database import is done before the rest of the files are extracted.
82
+ * Changed: siteurl option is updated during the database import.
83
+ * Changed: search and replace will not run when the URLs are similar.
84
+ * Changed: Increased the default values for memory_limit and max_execution_time from 512MB/300 to 1024MB/600.
85
+ * Removed: The use of wordpress' unzip_file (ziparchive will be used when available with pclzip as fallback)
86
+
87
  = 2.2 - 2015-11-16 =
88
  * Fixed: Missing backups that some users encountered after upgrading to 2.1.9
89
  * Added: An option to refresh the backup list.
wpclone.php CHANGED
@@ -4,7 +4,7 @@ Plugin name: WP Clone by WP Academy
4
  Plugin URI: http://wpacademy.com/software/
5
  Description: Move or copy a WordPress site to another server or to another domain name, move to/from local server hosting, and backup sites.
6
  Author: WP Academy
7
- Version: 2.2
8
  Author URI: http://wpacademy.com/
9
  */
10
 
@@ -32,6 +32,7 @@ add_action( 'wp_ajax_wpclone-ajax-size', 'wpa_wpc_ajax_size' );
32
  add_action( 'wp_ajax_wpclone-ajax-dir', 'wpa_wpc_ajax_dir' );
33
  add_action( 'wp_ajax_wpclone-ajax-delete', 'wpa_wpc_ajax_delete' );
34
  add_action( 'wp_ajax_wpclone-ajax-uninstall', 'wpa_wpc_ajax_uninstall' );
 
35
 
36
  function wpclone_plugin_menu() {
37
  add_menu_page (
@@ -46,8 +47,17 @@ function wpclone_plugin_menu() {
46
  function wpa_wpc_ajax_size() {
47
 
48
  check_ajax_referer( 'wpclone-ajax-submit', 'nonce' );
49
- $size = wpa_wpc_dir_size( WP_CONTENT_DIR );
50
- $size['dbsize'] = wpa_wpc_db_size();
 
 
 
 
 
 
 
 
 
51
  echo json_encode( $size );
52
  wp_die();
53
 
@@ -80,13 +90,40 @@ function wpa_wpc_ajax_delete() {
80
  function wpa_wpc_ajax_uninstall() {
81
 
82
  check_ajax_referer( 'wpclone-ajax-submit', 'nonce' );
83
- if( file_exists( WPCLONE_DIR_BACKUP ) ) wpa_delete_dir( WPCLONE_DIR_BACKUP );
 
 
 
 
 
 
 
 
 
84
  delete_option( 'wpclone_backups' );
85
  wpa_wpc_remove_table();
86
  wp_die();
87
 
88
  }
89
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  function wpclone_plugin_options() {
91
  include_once 'lib/view.php';
92
  }
@@ -100,6 +137,7 @@ function wpa_enqueue_scripts(){
100
  wp_enqueue_script('wpclone');
101
  wp_enqueue_style('wpclone');
102
  wp_deregister_script('heartbeat');
 
103
  }
104
  if( isset($_GET['page']) && 'wp-clone' == $_GET['page'] ) add_action('admin_enqueue_scripts', 'wpa_enqueue_scripts');
105
 
4
  Plugin URI: http://wpacademy.com/software/
5
  Description: Move or copy a WordPress site to another server or to another domain name, move to/from local server hosting, and backup sites.
6
  Author: WP Academy
7
+ Version: 2.2.1
8
  Author URI: http://wpacademy.com/
9
  */
10
 
32
  add_action( 'wp_ajax_wpclone-ajax-dir', 'wpa_wpc_ajax_dir' );
33
  add_action( 'wp_ajax_wpclone-ajax-delete', 'wpa_wpc_ajax_delete' );
34
  add_action( 'wp_ajax_wpclone-ajax-uninstall', 'wpa_wpc_ajax_uninstall' );
35
+ add_action( 'wp_ajax_wpclone-search-n-replace', 'wpa_wpc_ajax_search_n_replace' );
36
 
37
  function wpclone_plugin_menu() {
38
  add_menu_page (
47
  function wpa_wpc_ajax_size() {
48
 
49
  check_ajax_referer( 'wpclone-ajax-submit', 'nonce' );
50
+
51
+ $cached = get_option( 'wpclone_directory_scan' );
52
+ $interval = 600; /* 10 minutes */
53
+
54
+ if( false !== $cached && time() - $cached['time'] < $interval ) {
55
+ $size = $cached;
56
+ $size['time'] = date( 'i', time() - $size['time'] );
57
+ } else {
58
+ $size = wpa_wpc_dir_size( WP_CONTENT_DIR );
59
+ }
60
+
61
  echo json_encode( $size );
62
  wp_die();
63
 
90
  function wpa_wpc_ajax_uninstall() {
91
 
92
  check_ajax_referer( 'wpclone-ajax-submit', 'nonce' );
93
+ if( file_exists( WPCLONE_DIR_BACKUP ) ) {
94
+ wpa_delete_dir( WPCLONE_DIR_BACKUP );
95
+
96
+ }
97
+
98
+ if( file_exists( WPCLONE_WP_CONTENT . 'wpclone-temp' ) ) {
99
+ wpa_delete_dir( WPCLONE_WP_CONTENT . 'wpclone-temp' );
100
+
101
+ }
102
+
103
  delete_option( 'wpclone_backups' );
104
  wpa_wpc_remove_table();
105
  wp_die();
106
 
107
  }
108
 
109
+ function wpa_wpc_ajax_search_n_replace() {
110
+ check_ajax_referer( 'wpclone-ajax-submit', 'nonce' );
111
+ global $wpdb;
112
+ $search = isset( $_POST['search'] ) ? $_POST['search'] : '';
113
+ $replace = isset( $_POST['replace'] ) ? $_POST['replace'] : '';
114
+
115
+ if( empty( $search ) || empty( $replace ) ) {
116
+ echo '<p class="error">Search and Replace values cannot be empty.</p>';
117
+ wp_die();
118
+ }
119
+
120
+ wpa_bump_limits();
121
+ $report = wpa_safe_replace_wrapper( $search, $replace, $wpdb->prefix );
122
+ echo wpa_wpc_search_n_replace_report( $report );
123
+
124
+ wp_die();
125
+ }
126
+
127
  function wpclone_plugin_options() {
128
  include_once 'lib/view.php';
129
  }
137
  wp_enqueue_script('wpclone');
138
  wp_enqueue_style('wpclone');
139
  wp_deregister_script('heartbeat');
140
+ add_thickbox();
141
  }
142
  if( isset($_GET['page']) && 'wp-clone' == $_GET['page'] ) add_action('admin_enqueue_scripts', 'wpa_enqueue_scripts');
143