WP Migrate DB - Version 0.4.4

Version Description

  • 2013-05-19 =
  • Pro version has arrived! Added some info to the sidebar.
  • Updated required version to WordPress 3.0+
  • Bug fix: Does not handle serialized objects
  • Bug fix: Admin menu disappears when DISALLOW_FILE_MODS is true
  • Bug fix: Duplicate records on export
  • Bug fix: Updated spinner image for HiDPI displays
Download this release

Release Info

Developer bradt
Plugin Icon 128x128 WP Migrate DB
Version 0.4.4
Comparing to
See all releases

Code changes from version 0.4.3 to 0.4.4

asset/config.rb CHANGED
@@ -6,6 +6,7 @@ css_dir = "css"
6
  sass_dir = "sass"
7
  images_dir = "img"
8
  javascripts_dir = "js"
 
9
 
10
  # You can select your preferred output style here (can be overridden via the command line):
11
  # output_style = :expanded or :nested or :compact or :compressed
6
  sass_dir = "sass"
7
  images_dir = "img"
8
  javascripts_dir = "js"
9
+ line_comments = false
10
 
11
  # You can select your preferred output style here (can be overridden via the command line):
12
  # output_style = :expanded or :nested or :compact or :compressed
asset/css/styles.css CHANGED
@@ -1,9 +1,7 @@
1
- /* line 1, ../sass/styles.scss */
2
  #migrate-form {
3
  padding-top: 10px;
4
  }
5
 
6
- /* line 9, ../sass/styles.scss */
7
  .form-table .row-new-url th, .form-table .row-new-url td,
8
  .form-table .row-new-path th,
9
  .form-table .row-new-path td,
@@ -12,7 +10,6 @@
12
  padding-bottom: 20px;
13
  border-bottom: 1px solid #ccc;
14
  }
15
- /* line 18, ../sass/styles.scss */
16
  .form-table .row-old-path th, .form-table .row-old-path td,
17
  .form-table .row-save-file th,
18
  .form-table .row-save-file td,
@@ -21,35 +18,29 @@
21
  padding-top: 20px;
22
  }
23
 
24
- /* line 24, ../sass/styles.scss */
25
  p.submit {
26
  overflow: hidden;
27
  padding-top: 20px;
28
  border-top: 1px solid #ccc;
29
  margin-top: 20px;
30
  }
31
- /* line 30, ../sass/styles.scss */
32
  p.submit input {
33
  float: left;
34
  }
35
- /* line 34, ../sass/styles.scss */
36
  p.submit img {
37
  float: left;
38
  margin: 3px 0 0 5px;
39
  }
40
 
41
- /* line 40, ../sass/styles.scss */
42
  #wpmdb-container {
43
  position: relative;
44
  }
45
 
46
- /* line 44, ../sass/styles.scss */
47
  #wpmdb-main {
48
  margin-right: 320px;
49
  min-height: 1200px;
50
  }
51
 
52
- /* line 49, ../sass/styles.scss */
53
  #wpmdb-sidebar {
54
  position: absolute;
55
  top: 0;
@@ -58,53 +49,38 @@ p.submit img {
58
  border: 1px solid #ccc;
59
  padding: 20px;
60
  }
61
- /* line 57, ../sass/styles.scss */
62
  #wpmdb-sidebar .author {
63
  padding-bottom: 20px;
64
  margin-bottom: 20px;
65
  border-bottom: 1px solid #ccc;
66
  overflow: hidden;
67
  }
68
- /* line 63, ../sass/styles.scss */
69
  #wpmdb-sidebar .author img {
70
  float: left;
71
  margin-right: 20px;
72
  }
73
- /* line 68, ../sass/styles.scss */
74
  #wpmdb-sidebar .author .desc {
75
  float: left;
76
  }
77
- /* line 72, ../sass/styles.scss */
78
  #wpmdb-sidebar .author h3 {
79
  font-size: 12px;
80
  margin: 0;
81
  }
82
- /* line 77, ../sass/styles.scss */
83
  #wpmdb-sidebar .author h2 {
84
  font-size: 18px;
85
  margin: 0;
86
  padding: 0;
87
  }
88
- /* line 82, ../sass/styles.scss */
89
  #wpmdb-sidebar .author h2 a {
90
  color: #464646;
91
  text-decoration: none;
92
  }
93
- /* line 86, ../sass/styles.scss */
94
  #wpmdb-sidebar .author h2 a:hover {
95
  color: #000;
96
  }
97
- /* line 92, ../sass/styles.scss */
98
  #wpmdb-sidebar .author p {
99
  margin: 0;
100
  }
101
- /* line 97, ../sass/styles.scss */
102
- #wpmdb-sidebar .subscribe {
103
- padding-bottom: 20px;
104
- margin-bottom: 20px;
105
- border-bottom: 1px solid #ccc;
106
- }
107
- /* line 102, ../sass/styles.scss */
108
  #wpmdb-sidebar .subscribe h2 {
109
  padding: 0;
110
  margin: 0;
@@ -112,73 +88,31 @@ p.submit img {
112
  color: #666;
113
  font-size: 20px;
114
  }
115
- /* line 110, ../sass/styles.scss */
116
- #wpmdb-sidebar .subscribe ul {
117
- list-style-type: disc;
118
- }
119
- /* line 114, ../sass/styles.scss */
120
- #wpmdb-sidebar .subscribe li {
121
- margin-left: 1.5em;
122
- color: #666;
123
  }
124
- /* line 119, ../sass/styles.scss */
125
  #wpmdb-sidebar .subscribe p {
126
  margin: 0;
127
  }
128
- /* line 123, ../sass/styles.scss */
129
  #wpmdb-sidebar .subscribe p.interesting {
130
  margin-bottom: 1em;
131
  }
132
- /* line 127, ../sass/styles.scss */
133
- #wpmdb-sidebar .subscribe .error {
134
- color: red;
135
- font-weight: bold;
136
- margin-bottom: 1em;
137
  }
138
- /* line 133, ../sass/styles.scss */
139
- #wpmdb-sidebar .subscribe .thanks {
140
- color: #333;
141
- font-weight: bold;
142
- font-size: 14px;
143
  }
144
- /* line 139, ../sass/styles.scss */
145
  #wpmdb-sidebar .subscribe .field {
146
  margin-bottom: 1em;
147
  }
148
- /* line 142, ../sass/styles.scss */
149
  #wpmdb-sidebar .subscribe .field p {
150
  margin-bottom: 0.3em;
151
  }
152
- /* line 146, ../sass/styles.scss */
153
- #wpmdb-sidebar .subscribe .field .willing-copy {
154
- font-weight: bold;
155
- font-size: 14px;
156
- line-height: 1.4em;
157
- margin-bottom: 1em;
158
- }
159
- /* line 154, ../sass/styles.scss */
160
- #wpmdb-sidebar .subscribe .field.how-much input {
161
- width: 50px;
162
- }
163
- /* line 160, ../sass/styles.scss */
164
- #wpmdb-sidebar .subscribe .field.notify-me input {
165
- position: absolute;
166
- }
167
- /* line 164, ../sass/styles.scss */
168
- #wpmdb-sidebar .subscribe .field.notify-me label {
169
- display: block;
170
- padding-left: 20px;
171
- }
172
- /* line 172, ../sass/styles.scss */
173
- #wpmdb-sidebar .subscribe .field.comments textarea {
174
- width: 230px;
175
- height: 3em;
176
- }
177
- /* line 177, ../sass/styles.scss */
178
- #wpmdb-sidebar .subscribe .field.comments textarea.has-content, #wpmdb-sidebar .subscribe .field.comments textarea:focus {
179
- height: 5em;
180
- }
181
- /* line 183, ../sass/styles.scss */
182
  #wpmdb-sidebar .subscribe .field.submit-button {
183
- margin-bottom: 0;
184
  }
 
1
  #migrate-form {
2
  padding-top: 10px;
3
  }
4
 
 
5
  .form-table .row-new-url th, .form-table .row-new-url td,
6
  .form-table .row-new-path th,
7
  .form-table .row-new-path td,
10
  padding-bottom: 20px;
11
  border-bottom: 1px solid #ccc;
12
  }
 
13
  .form-table .row-old-path th, .form-table .row-old-path td,
14
  .form-table .row-save-file th,
15
  .form-table .row-save-file td,
18
  padding-top: 20px;
19
  }
20
 
 
21
  p.submit {
22
  overflow: hidden;
23
  padding-top: 20px;
24
  border-top: 1px solid #ccc;
25
  margin-top: 20px;
26
  }
 
27
  p.submit input {
28
  float: left;
29
  }
 
30
  p.submit img {
31
  float: left;
32
  margin: 3px 0 0 5px;
33
  }
34
 
 
35
  #wpmdb-container {
36
  position: relative;
37
  }
38
 
 
39
  #wpmdb-main {
40
  margin-right: 320px;
41
  min-height: 1200px;
42
  }
43
 
 
44
  #wpmdb-sidebar {
45
  position: absolute;
46
  top: 0;
49
  border: 1px solid #ccc;
50
  padding: 20px;
51
  }
 
52
  #wpmdb-sidebar .author {
53
  padding-bottom: 20px;
54
  margin-bottom: 20px;
55
  border-bottom: 1px solid #ccc;
56
  overflow: hidden;
57
  }
 
58
  #wpmdb-sidebar .author img {
59
  float: left;
60
  margin-right: 20px;
61
  }
 
62
  #wpmdb-sidebar .author .desc {
63
  float: left;
64
  }
 
65
  #wpmdb-sidebar .author h3 {
66
  font-size: 12px;
67
  margin: 0;
68
  }
 
69
  #wpmdb-sidebar .author h2 {
70
  font-size: 18px;
71
  margin: 0;
72
  padding: 0;
73
  }
 
74
  #wpmdb-sidebar .author h2 a {
75
  color: #464646;
76
  text-decoration: none;
77
  }
 
78
  #wpmdb-sidebar .author h2 a:hover {
79
  color: #000;
80
  }
 
81
  #wpmdb-sidebar .author p {
82
  margin: 0;
83
  }
 
 
 
 
 
 
 
84
  #wpmdb-sidebar .subscribe h2 {
85
  padding: 0;
86
  margin: 0;
88
  color: #666;
89
  font-size: 20px;
90
  }
91
+ #wpmdb-sidebar .subscribe h3 {
92
+ font-size: 16px;
93
+ margin: 0;
 
 
 
 
 
94
  }
 
95
  #wpmdb-sidebar .subscribe p {
96
  margin: 0;
97
  }
 
98
  #wpmdb-sidebar .subscribe p.interesting {
99
  margin-bottom: 1em;
100
  }
101
+ #wpmdb-sidebar .subscribe .links {
102
+ margin-bottom: 2em;
103
+ }
104
+ #wpmdb-sidebar .subscribe .links a {
105
+ text-decoration: none;
106
  }
107
+ #wpmdb-sidebar .subscribe .promise {
108
+ color: #999;
 
 
 
109
  }
 
110
  #wpmdb-sidebar .subscribe .field {
111
  margin-bottom: 1em;
112
  }
 
113
  #wpmdb-sidebar .subscribe .field p {
114
  margin-bottom: 0.3em;
115
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  #wpmdb-sidebar .subscribe .field.submit-button {
117
+ margin-bottom: 1em;
118
  }
asset/img/video@2x.jpg ADDED
Binary file
asset/img/wpappstore-logo.png DELETED
Binary file
asset/js/script.js CHANGED
@@ -13,50 +13,15 @@
13
  return false;
14
  }
15
  });
16
-
17
- $('#wpmdb-sidebar').each(function() {
18
- var $sidebar = $(this);
19
-
20
- $('form', $sidebar).submit(function() {
21
- var $form = $(this),
22
- data = $(this).serializeArray();
23
-
24
- $('.button', $form).attr('disabled', 'true');
25
-
26
- data.push({name: 'action', value: 'subscribe_submission'});
27
-
28
- $.post( ajaxurl, data, function(result) {
29
- if (result) {
30
- $('.error', $sidebar).remove();
31
- $('.field.submit-button', $sidebar).before('<p class="error" style="display: none;">' + result + '</p>');
32
- $('.error', $sidebar).fadeIn();
33
- }
34
- else {
35
- $form.html('<p class="thanks">Thanks for subscribing. We promise to protect your email from weasels.</p>').fadeIn();
36
- document.location.hash = '#top';
37
- }
38
- });
39
- return false;
40
- });
41
-
42
- $('.field.comments textarea', $sidebar).blur(function() {
43
- if ($(this).val()) {
44
- $(this).addClass('has-content');
45
- }
46
- else {
47
- $(this).removeClass('has-content');
48
- }
49
- });
50
- });
51
  });
52
 
53
  var admin_url = ajaxurl.replace( '/admin-ajax.php', '' ),
54
- spinner_url = admin_url + '/images/wpspin_light.gif';
55
-
56
  var spinner = new Image();
57
  spinner.src = spinner_url;
58
 
59
  $('#migrate-form').submit(function() {
60
- $('p.submit', this).append('<img src="' + spinner_url + '" alt="" />');
61
  });
62
  })(jQuery);
13
  return false;
14
  }
15
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  });
17
 
18
  var admin_url = ajaxurl.replace( '/admin-ajax.php', '' ),
19
+ spinner_url = admin_url + '/images/wpspin_light-2x.gif';
20
+
21
  var spinner = new Image();
22
  spinner.src = spinner_url;
23
 
24
  $('#migrate-form').submit(function() {
25
+ $('p.submit', this).append('<img src="' + spinner_url + '" width="16" alt="" />');
26
  });
27
  })(jQuery);
asset/sass/styles.scss CHANGED
@@ -95,10 +95,6 @@ p.submit {
95
  }
96
 
97
  .subscribe {
98
- padding-bottom: 20px;
99
- margin-bottom: 20px;
100
- border-bottom: 1px solid #ccc;
101
-
102
  h2 {
103
  padding: 0;
104
  margin: 0;
@@ -107,13 +103,9 @@ p.submit {
107
  font-size: 20px;
108
  }
109
 
110
- ul {
111
- list-style-type: disc;
112
- }
113
-
114
- li {
115
- margin-left: 1.5em;
116
- color: #666;
117
  }
118
 
119
  p {
@@ -124,16 +116,16 @@ p.submit {
124
  margin-bottom: 1em;
125
  }
126
 
127
- .error {
128
- color: red;
129
- font-weight: bold;
130
- margin-bottom: 1em;
 
 
131
  }
132
 
133
- .thanks {
134
- color: #333;
135
- font-weight: bold;
136
- font-size: 14px;
137
  }
138
 
139
  .field {
@@ -143,45 +135,8 @@ p.submit {
143
  margin-bottom: 0.3em;
144
  }
145
 
146
- .willing-copy {
147
- font-weight: bold;
148
- font-size: 14px;
149
- line-height: 1.4em;
150
- margin-bottom: 1em;
151
- }
152
-
153
- &.how-much {
154
- input {
155
- width: 50px;
156
- }
157
- }
158
-
159
- &.notify-me {
160
- input {
161
- position: absolute;
162
- }
163
-
164
- label {
165
- display: block;
166
- padding-left: 20px;
167
- }
168
-
169
- }
170
-
171
- &.comments {
172
- textarea {
173
- width: 230px;
174
- height: 3em;
175
-
176
- &.has-content,
177
- &:focus {
178
- height: 5em;
179
- }
180
- }
181
- }
182
-
183
  &.submit-button {
184
- margin-bottom: 0;
185
  }
186
  }
187
  }
95
  }
96
 
97
  .subscribe {
 
 
 
 
98
  h2 {
99
  padding: 0;
100
  margin: 0;
103
  font-size: 20px;
104
  }
105
 
106
+ h3 {
107
+ font-size: 16px;
108
+ margin: 0;
 
 
 
 
109
  }
110
 
111
  p {
116
  margin-bottom: 1em;
117
  }
118
 
119
+ .links {
120
+ margin-bottom: 2em;
121
+
122
+ a {
123
+ text-decoration: none;
124
+ }
125
  }
126
 
127
+ .promise {
128
+ color: #999;
 
 
129
  }
130
 
131
  .field {
135
  margin-bottom: 0.3em;
136
  }
137
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  &.submit-button {
139
+ margin-bottom: 1em;
140
  }
141
  }
142
  }
readme.txt CHANGED
@@ -2,27 +2,56 @@
2
  Contributors: bradt
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5VPMGLLK94XJC
4
  Tags: database, migrate, backup, mysql
5
- Requires at least: 2.0.3
6
- Tested up to: 3.5
7
- Stable tag: 0.4.3
8
  License: GPLv2
9
 
10
  Exports your database, does a find and replace on URLs and file paths, then allows you to save it to your computer.
11
 
12
  == Description ==
13
 
14
- WP Migrate DB exports your database as a MySQL data dump (much like phpMyAdmin), does a find and replace on URLs and file paths, then allows you to save it to your computer. It is perfect for developers who develop locally and need to move their Wordpress site to a staging or production server.
15
 
16
- It even takes into account serialized data and updates the string length values.
17
 
18
  Example: <code>s:5:"hello"</code> becomes <code>s:11:"hello world"</code>
19
 
20
- [**Contribute on Github**](https://github.com/bradt/wp-migrate-db)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
  == Installation ==
23
 
24
  1. Use WordPress' built-in installer
25
- 2. Access the WP Migrate DB menu option under Tools
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
  == Screenshots ==
28
 
@@ -31,6 +60,14 @@ Example: <code>s:5:"hello"</code> becomes <code>s:11:"hello world"</code>
31
 
32
  == Changelog ==
33
 
 
 
 
 
 
 
 
 
34
  = 0.4.3 - 2012-12-18 =
35
  * Fixed deprecated error notices when debug mode is on
36
  * Bug fix: [Exports views as tables](https://github.com/bradt/wp-migrate-db/issues/3)
@@ -62,7 +99,7 @@ Example: <code>s:5:"hello"</code> becomes <code>s:11:"hello world"</code>
62
  * Bug fix: [Breaks Export](http://wordpress.org/support/topic/plugin-wp-migrate-db-breaks-export?replies=1)
63
 
64
  = 0.2.1 - 2009-12-13 =
65
- * Moved to Wordpress.org hosting
66
 
67
  = 0.2 - 2009-04-03 =
68
  * Moved menu link from "Settings" to "Tools"
@@ -77,4 +114,4 @@ Example: <code>s:5:"hello"</code> becomes <code>s:11:"hello world"</code>
77
  Runs export over 4x faster and adds some nice new features often requested. Upgrade recommended.
78
 
79
  = 0.2.2 =
80
- This version fixes a bug that breaks the WordPress core export feature. It is highly recommended that everyone upgrade.
2
  Contributors: bradt
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5VPMGLLK94XJC
4
  Tags: database, migrate, backup, mysql
5
+ Requires at least: 3.0
6
+ Tested up to: 3.6
7
+ Stable tag: 0.4.4
8
  License: GPLv2
9
 
10
  Exports your database, does a find and replace on URLs and file paths, then allows you to save it to your computer.
11
 
12
  == Description ==
13
 
14
+ WP Migrate DB exports your database as a MySQL data dump (much like phpMyAdmin), does a find and replace on URLs and file paths, then allows you to save it to your computer. It is perfect for developers who need to update their local install with fresh data from the production site, or copy their locally developed site to a staging or production server.
15
 
16
+ It even takes into account serialized data (both arrays and objects) and updates the string length values.
17
 
18
  Example: <code>s:5:"hello"</code> becomes <code>s:11:"hello world"</code>
19
 
20
+ Looking to contribute some code? The project is [on Github](https://github.com/bradt/wp-migrate-db) and I'm more than happy to accept pull requests.
21
+
22
+ **\*NEW\* Pro Version with Email Support and More Features**
23
+
24
+ * Select the tables you want to migrate
25
+ * Pull production db down and replace local db
26
+ * Push local db up and replace production/staging db
27
+ * Unlimited find & replaces (free is limited to 2)
28
+ * Multisite support
29
+ * Video walkthroughs and howtos
30
+ * More frequent bug fixes and improvements
31
+ * And more features on the way!
32
+
33
+ See the video below or [visit the web site](http://deliciousbrains.com/wp-migrate-db-pro/?utm_source=wordpressorg&utm_medium=web&utm_content=faq&utm_campaign=freeplugin) to learn more about the pro version.
34
+
35
+ http://www.youtube.com/watch?v=IFdHIpf6jjc
36
 
37
  == Installation ==
38
 
39
  1. Use WordPress' built-in installer
40
+ 2. Access the "Migrate DB" menu option under Tools
41
+
42
+ == Frequently Asked Questions ==
43
+
44
+ = Does this plugin support multisite? =
45
+
46
+ Not at this time. The Developer license of the [pro version](http://deliciousbrains.com/wp-migrate-db-pro/?utm_source=wordpressorg&utm_medium=web&utm_content=faq&utm_campaign=freeplugin) does support multisite.
47
+
48
+ = Does the plugin migrate files as well? =
49
+
50
+ No, it only operates on the database.
51
+
52
+ = Why do I end up with a wp-login.php download instead of the exported SQL file? =
53
+
54
+ It is likely you have a download manager plugin or extension installed in your web browser. You will need to disable it for the SQL download to work properly.
55
 
56
  == Screenshots ==
57
 
60
 
61
  == Changelog ==
62
 
63
+ = 0.4.4 - 2013-05-19 =
64
+ * [Pro version has arrived!](http://deliciousbrains.com/wp-migrate-db-pro/?utm_source=wordpressorg&utm_medium=web&utm_content=changelog&utm_campaign=freeplugin) Added some info to the sidebar.
65
+ * Updated required version to WordPress 3.0+
66
+ * Bug fix: [Does not handle serialized objects](https://github.com/bradt/wp-migrate-db/issues/11)
67
+ * Bug fix: [Admin menu disappears when DISALLOW_FILE_MODS is true](https://github.com/bradt/wp-migrate-db/issues/8)
68
+ * Bug fix: [Duplicate records on export](https://github.com/bradt/wp-migrate-db/issues/5)
69
+ * Bug fix: Updated spinner image for HiDPI displays
70
+
71
  = 0.4.3 - 2012-12-18 =
72
  * Fixed deprecated error notices when debug mode is on
73
  * Bug fix: [Exports views as tables](https://github.com/bradt/wp-migrate-db/issues/3)
99
  * Bug fix: [Breaks Export](http://wordpress.org/support/topic/plugin-wp-migrate-db-breaks-export?replies=1)
100
 
101
  = 0.2.1 - 2009-12-13 =
102
+ * Moved to WordPress.org hosting
103
 
104
  = 0.2 - 2009-04-03 =
105
  * Moved menu link from "Settings" to "Tools"
114
  Runs export over 4x faster and adds some nice new features often requested. Upgrade recommended.
115
 
116
  = 0.2.2 =
117
+ This version fixes a bug that breaks the WordPress core export feature. It is highly recommended that everyone upgrade.
wp-migrate-db.php CHANGED
@@ -1,10 +1,10 @@
1
  <?php
2
  /*
3
- Plugin Name: WP-Migrate-DB
4
  Plugin URI: http://wordpress.org/extend/plugins/wp-migrate-db/
5
  Description: Exports your database as a MySQL data dump (much like phpMyAdmin), does a find and replace on URLs and file paths, then allows you to save it to your computer.
6
  Author: Brad Touesnard
7
- Version: 0.4.3
8
  Author URI: http://bradt.ca/
9
  */
10
 
@@ -25,17 +25,17 @@ Author URI: http://bradt.ca/
25
 
26
 
27
  // Define the directory seperator if it isn't already
28
- if (!defined('DS')) {
29
- if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') {
30
- define('DS', '\\');
31
  }
32
  else {
33
- define('DS', '/');
34
  }
35
  }
36
 
37
- if ( ! defined('ROWS_PER_SEGMENT') ) {
38
- define('ROWS_PER_SEGMENT', 100);
39
  }
40
 
41
  class WP_Migrate_DB {
@@ -45,13 +45,14 @@ class WP_Migrate_DB {
45
  var $fp;
46
  var $replaced;
47
  var $datetime;
 
48
 
49
  function __construct() {
50
  $this->errors = array();
51
- $this->upload_dir = ( defined('WP_CONTENT_DIR') ) ? WP_CONTENT_DIR . '/uploads' : ABSPATH . 'wp-content' . DS . 'uploads';
52
- $this->upload_url = ( defined('WP_CONTENT_URL') ) ? WP_CONTENT_URL . '/uploads' : get_option('siteurl') . '/wp-content/uploads';
53
 
54
- $this->datetime = date('YmdHis');
55
 
56
  $this->replaced['serialized']['count'] = 0;
57
  $this->replaced['serialized']['strings'] = '';
@@ -59,19 +60,17 @@ class WP_Migrate_DB {
59
 
60
  add_action( 'admin_menu', array( $this, 'admin_menu' ) );
61
  add_action( 'wp_ajax_subscribe_submission', array( $this, 'subscribe_submission' ) );
62
-
63
- $this->handle_request();
64
  }
65
 
66
  function subscribe_submission() {
67
  $response = wp_remote_post( 'http://bradt.ca/wpmdb-subscribe.php', array(
68
- 'timeout' => 60,
69
- 'body' => $_POST
70
- ));
71
 
72
  if ( is_wp_error( $response ) ) {
73
  echo "Error attempting to save your submission.";
74
- }
75
  else {
76
  echo $response['body'];
77
  }
@@ -80,20 +79,22 @@ class WP_Migrate_DB {
80
  }
81
 
82
  function handle_request() {
83
- if ( !isset( $_GET['page'] ) || 'wp-migrate-db' != $_GET['page'] )
84
- return;
85
-
86
- if (isset($_POST['Submit'])) {
87
  $this->options_validate();
88
  }
89
 
90
  if ( empty( $this->errors ) && isset( $_POST['savefile'] ) && $_POST['savefile'] ) {
91
- add_action( 'admin_head-tools_page_wp-migrate-db', array( $this, 'admin_head' ) );
92
  }
93
-
94
- if ( isset( $_GET['download'] ) && $_GET['download']) {
95
- add_action( 'admin_init', array( $this, 'download_file' ) );
96
  }
 
 
 
 
 
97
  }
98
 
99
  function get_filename( $datetime, $gzip ) {
@@ -110,25 +111,25 @@ class WP_Migrate_DB {
110
  }
111
 
112
  function options_validate() {
113
- if (!isset($_POST['old_url']) || !$_POST['old_url']) {
114
- $this->errors['old_url'] = __('Please enter the current URL.', 'wp-migrate-db');
115
  }
116
 
117
- if (!isset($_POST['new_url']) || !$_POST['new_url']) {
118
- $this->errors['new_url'] = __('Please enter a new URL.', 'wp-migrate-db');
119
  }
120
 
121
- if (!isset($_POST['old_path']) || !$_POST['old_path']) {
122
- $this->errors['old_path'] = __('Please enter the current file path.', 'wp-migrate-db');
123
  }
124
 
125
- if (!isset($_POST['new_path']) || !$_POST['new_path']) {
126
- $this->errors['new_path'] = __('Please enter a new file path.', 'wp-migrate-db');
127
  }
128
  }
129
 
130
- function show_error($key) {
131
- if (isset($this->errors[$key])) {
132
  echo '<br /><span style="color: #cc0000; font-weight: bold;">', $this->errors[$key], '</span>';
133
  }
134
  }
@@ -137,349 +138,283 @@ class WP_Migrate_DB {
137
  ?>
138
 
139
  <div class="wrap">
140
- <div id="icon-tools" class="icon32"><br /></div><h2>WP Migrate DB</h2>
141
 
142
  <div id="wpmdb-container">
143
 
144
  <div id="wpmdb-main">
145
 
146
- <?php
147
- if (isset($_POST['Submit'])) {
148
- if (empty($this->errors)) {
149
- $this->fp = $this->open($this->upload_dir . DS . $this->get_filename( $this->datetime, isset( $_POST['gzipfile'] ) ) );
150
- $this->db_backup_header();
151
- $this->db_backup();
152
- $this->close($this->fp);
153
- }
154
 
155
- if (empty($this->errors)) {
156
- ?>
157
 
158
- <div class="message updated">
159
 
 
 
 
 
 
 
 
 
160
  <?php
161
- if (isset($_POST['savefile']) && $_POST['savefile']) {
162
- add_action('admin_head-settings_page_wp-migrate-db', array($this, 'admin_head'));
163
- ?>
164
- <p>
165
- Your database (SQL) file has been successfully generated.
166
- Your download should begin any second.
167
- </p>
168
- <?php
169
- }
170
- else {
171
- ?>
172
- <p>
173
- Your database (SQL) file has been successfully generated and
174
- saved to <br /><?php echo $this->upload_dir . DS . $this->get_filename( $this->datetime, isset( $_POST['gzipfile'] ) ); ?>.
175
- <a href="<?php echo $this->upload_url, '/', $this->get_filename( $this->datetime, isset( $_POST['gzipfile'] ) ); ?>">Click
176
- here to download.</a>
177
- </p>
178
- <?php
179
- }
180
  ?>
181
-
182
- </div>
183
-
184
  <p>
185
- <b>Non-Serialized Strings Replaced: <?php echo $this->replaced['nonserialized']['count']; ?></b><br />
186
- <b>Serialized Strings Replaced: <?php echo $this->replaced['serialized']['count']; ?></b><br />
187
- <textarea style="width: 100%; height: 200px;" wrap="off"><?php echo $this->replaced['serialized']['strings']; ?></textarea>
 
188
  </p>
189
  <?php
190
  }
 
 
 
191
 
192
- $form_values = $_POST;
 
 
 
 
 
193
  }
194
- else {
195
- $form_values['old_url'] = get_bloginfo('url');
196
 
197
- $form_values['old_path'] = dirname(__FILE__);
198
- $form_values['old_path'] = str_replace(DS . 'wp-migrate-db', '', $form_values['old_path']);
199
- $form_values['old_path'] = realpath($form_values['old_path'] . '/../..');
 
200
 
201
- if (get_bloginfo('url') != get_bloginfo('wpurl')) {
202
- $wp_dir = str_replace(get_bloginfo('url'), '', get_bloginfo('wpurl'));
203
- $wp_dir = str_replace('/', DS, $wp_dir);
204
- $form_values['old_path'] = str_replace($wp_dir, '', $form_values['old_path']);
205
- }
206
 
207
- $form_values['new_path'] = $form_values['new_url'] = '';
 
 
 
208
  }
209
 
210
- if (!isset($_POST['Submit']) || (isset($_POST['Submit']) && !empty($this->errors))) {
211
- if (!is_writable($this->upload_dir)) {
212
- ?>
213
-
214
- <div id="message" class="message error">
215
- <p>
216
- The directory <?php echo $this->upload_dir; ?> needs
217
- to be writable.
218
- </p>
219
- </div>
220
 
221
- <?php
222
- }
 
223
 
224
- if (!empty($this->errors)) {
225
- ?>
 
 
 
 
226
 
227
- <div id="message" class="message error">
228
- <p>
229
- Sorry, there were errors with your form submission.
230
- Please correct them below and try again.
231
- </p>
232
- </div>
233
 
234
- <?php
235
- }
236
  ?>
237
 
238
- <p>
239
- WP Migrate DB exports your database as a MySQL data dump (much like phpMyAdmin),
240
- does a find and replace on URLs and file paths, then allows you to save
241
- it to your computer. It even takes into account serialized data and updates the
242
- string length values.
243
- </p>
244
- <p>
245
- Example: <code>s:5:"hello"</code> becomes <code>s:11:"hello world"</code>
246
- </p>
247
-
248
- <form method="post" id="migrate-form">
249
- <table class="form-table">
250
- <tbody>
251
- <tr valign="top" class="row-old-url">
252
- <th scope="row">
253
- <label for="old_url">Current address (URL)</label>
254
- </th>
255
- <td>
256
- <input type="text" size="40" name="old_url" class="code" id="old_url" value="<?php echo htmlentities($form_values['old_url']); ?>" />
257
- <?php $this->show_error('old_url'); ?>
258
- </td>
259
- </tr>
260
- <tr valign="top" class="row-new-url">
261
- <th scope="row">
262
- <label for="new_url">New address (URL)</label>
263
- </th>
264
- <td>
265
- <input type="text" size="40" name="new_url" class="code" id="new_url" value="<?php echo htmlentities($form_values['new_url']); ?>" />
266
- <?php $this->show_error('new_url'); ?>
267
- </td>
268
- </tr>
269
- <tr valign="top" class="row-old-path">
270
- <th scope="row">
271
- <label for="old_path">Current file path</label>
272
- </th>
273
- <td>
274
- <input type="text" size="40" name="old_path" class="code" id="old_path" value="<?php echo htmlentities($form_values['old_path']); ?>" />
275
- <?php $this->show_error('old_path'); ?>
276
- </td>
277
- </tr>
278
- <tr valign="top" class="row-new-path">
279
- <th scope="row">
280
- <label for="new_path">New file path</label>
281
- </th>
282
- <td>
283
- <input type="text" size="40" name="new_path" class="code" id="new_path" value="<?php echo htmlentities($form_values['new_path']); ?>" />
284
- <?php $this->show_error('new_path'); ?>
285
- </td>
286
- </tr>
287
- <tr valign="top" class="row-guids">
288
- <th scope="row">Data Options</th>
289
- <td>
290
- <label for="replace-guids">
291
- <input id="replace-guids" type="checkbox" checked="checked" value="1" name="replaceguids"/>
292
- Replace GUIDs</label>
293
-
294
- <a href="" id="replace-guids-info-link">show more</a>
295
-
296
- <div id="replace-guids-info" style="display: none;">
297
- <p>
298
- Although the <a href="http://codex.wordpress.org/Changing_The_Site_URL#Important_GUID_Note" target="_blank">WordPress Codex emphasizes</a>
299
- that GUIDs should not be changed, this is limited to sites that are already live.
300
- If the site has never been live, I recommend replacing the GUIDs. For example, you may be
301
- developing a new site locally at dev.somedomain.com and want to
302
- migrate the site live to somedomain.com.
303
- </p>
304
- </div>
305
- </td>
306
- </tr>
307
- <tr valign="top" class="row-spam">
308
- <th scope="row">&nbsp;</th>
309
- <td>
310
- <label for="exclude-spam">
311
- <input id="exclude-spam" type="checkbox" value="1" name="exclude-spam" />
312
- Do not export spam comments
313
- </label>
314
- </td>
315
- </tr>
316
- <tr valign="top" class="row-revisions">
317
- <th scope="row">&nbsp;</th>
318
- <td>
319
- <label for="exclude-revisions">
320
- <input id="exclude-revisions" type="checkbox" value="1" name="exclude-revisions" />
321
- Do not export post revisions
322
- </label>
323
- </td>
324
- </tr>
325
- <tr valign="top" class="row-save-file">
326
- <th scope="row">File Options</th>
327
- <td>
328
- <label for="savefile">
329
- <input id="savefile" type="checkbox" checked="checked" value="1" name="savefile"/>
330
- Save as file to your computer
331
- </label>
332
- </td>
333
- </tr>
334
- <?php if ( $this->gzip() ) : ?>
335
- <tr valign="top" class="row-gzip">
336
- <th scope="row">&nbsp;</th>
337
- <td>
338
- <label for="gzipfile">
339
- <input id="gzipfile" type="checkbox" value="1" name="gzipfile" />
340
- Compress file with gzip
341
- </label>
342
- </td>
343
- </tr>
344
- <?php endif; ?>
345
- </tbody>
346
- </table>
347
-
348
- <p class="submit">
349
- <input class="button" type="submit" value="Export Database" name="Submit"/>
350
  </p>
351
- </form>
352
 
353
  <?php
354
  }
355
  ?>
356
- </div>
357
 
358
- <div id="wpmdb-sidebar">
359
-
360
- <div class="author">
361
- <img src="http://www.gravatar.com/avatar/e538ca4cb34839d4e5e3ccf20c37c67b?s=128&amp;d" width="64" height="64" />
362
- <div class="desc">
363
- <h3>Created &amp; maintained by</h3>
364
- <h2>Brad Touesnard</h2>
365
- <p>
366
- <a href="http://profiles.wordpress.org/bradt/">Profile</a>
367
- &nbsp;&nbsp;
368
- <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=5VPMGLLK94XJC">Donate</a>
369
- </p>
370
- </div>
371
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
372
 
373
- <form method="post" action="http://bradt.ca/wpmdb-subscribe.php" class="subscribe">
374
- <h2>Pro Version</h2>
375
- <p>
376
- We're working on a PRO version of this plugin that will include...
377
- </p>
 
378
 
379
- <ul>
380
- <li>
381
- Pull production/staging db down and replace local db
382
- </li>
383
- <li>
384
- Push local db up and replace production/staging db
385
- </li>
386
- <li>
387
- Select tables to export
388
- </li>
389
- <li>
390
- Unlimited find &amp; replaces (currently you can
391
- only do 2)
392
- </li>
393
- <li>
394
- Compatibility with multi-site
395
- </li>
396
- <li>
397
- Priority email support
398
- </li>
399
- </ul>
400
-
401
- <?php $user = wp_get_current_user(); ?>
402
-
403
- <p class="interesting">Interested? Send us your email and we'll let you know when a beta is available.</p>
404
-
405
- <div class="field notify-email">
406
- <p>Your Email</p>
407
- <input type="email" name="notify-email" value="<?php echo esc_attr( $user->user_email ); ?>" />
408
- </div>
409
-
410
- <div class="field notify-email">
411
- <p>Your Name (optional)</p>
412
- <input type="text" name="notify-name" value="<?php echo trim( esc_attr( $user->first_name ) . ' ' . esc_attr( $user->last_name ) ); ?>" />
413
- </div>
414
-
415
- <div class="field comments">
416
- <p>Comments (optional)</p>
417
- <textarea name="comments"></textarea>
418
- </div>
419
-
420
- <div class="field submit-button">
421
- <input type="submit" class="button" value="Submit" />
422
- </div>
423
- </form>
424
-
425
- <?php $url = 'http://wpappstore.com/?utm_source=plugin&amp;utm_medium=wordpress&amp;utm_campaign=wpmigratedb'; ?>
426
- <div class="wpas-promo">
427
- <a href="<?php echo $url; ?>"><img src="<?php echo plugins_url( 'asset/img/wpappstore-logo.png', __FILE__ ); ?>" alt="WP App Store" width="220" /></a>
428
  <p>
429
- Purchase &amp; install themes and plugins from top brands directly from your WordPress dashboard.
430
- <a href="<?php echo $url; ?>">Check&nbsp;it&nbsp;out&nbsp;&raquo;</a>
 
431
  </p>
432
  </div>
433
-
434
  </div>
435
 
436
- </div>
437
- </div>
438
- <?php
439
- }
440
 
441
- function replace_sql_strings($search, $replace, $subject) {
442
- $search_esc = mysql_real_escape_string($search);
443
- $replace_esc = mysql_real_escape_string($replace);
444
-
445
- $regex = '@s:([0-9]+):"(.*?)' . preg_quote($search_esc, '@') . '(.*?)";@';
446
-
447
- if ( preg_match_all( $regex, $subject, $matches, PREG_SET_ORDER ) ) {
448
- foreach ( $matches as $match ) {
449
- /*
450
- For some reason, the ungreedy regex above is not working as
451
- you'd expect ungreedy to work and is matching strings with
452
- multiple serialized strings (PHP 5.3.2). So we need to to
453
- isolate each.
454
- */
455
- if ( preg_match_all( '@s:([0-9]+):"(.*?)";@', $match[0], $finds, PREG_SET_ORDER ) ) {
456
- foreach ( $finds as $find ) {
457
- if ( false === strpos( $find[0], $search_esc ) ) continue;
458
-
459
- list( $old_line, $old_strlen, $old_str) = $find;
460
-
461
- $new_str = str_replace( $search_esc, $replace_esc, $old_str);
462
- $new_strlen = strlen($new_str) - strlen($old_str) + $old_strlen;
463
- $new_line = sprintf('s:%s:"%s";', $new_strlen, $new_str);
464
-
465
- $subject = str_replace($old_line, $new_line, $subject, $count);
466
-
467
- if ($count) {
468
- $this->replaced['serialized']['strings'] .= $old_line . "\n";
469
- $this->replaced['serialized']['strings'] .= $new_line . "\n\n";
470
-
471
- $this->replaced['serialized']['count'] += $count;
472
- }
473
- }
474
- }
475
- }
476
- }
477
 
478
- $subject = str_replace($search_esc, $replace_esc, $subject, $count);
 
 
 
 
 
 
 
 
 
 
 
 
 
479
 
480
- $this->replaced['nonserialized']['count'] += $count;
 
 
 
 
 
 
 
 
 
 
481
 
482
- return $subject;
 
 
483
  }
484
 
485
  function apply_replaces( $subject, $is_serialized = false ) {
@@ -501,298 +436,335 @@ class WP_Migrate_DB {
501
  return $new;
502
  }
503
 
504
- /**
505
- * Taken partially from phpMyAdmin and partially from
506
- * Alain Wolf, Zurich - Switzerland
507
- * Website: http://restkultur.ch/personal/wolf/scripts/db_backup/
508
-
509
- * Modified by Scott Merrill (http://www.skippy.net/)
510
- * to use the WordPress $wpdb object
511
- * @param string $table
512
- * @param string $segment
513
- * @return void
514
- */
515
- function backup_table($table, $segment = 'none') {
516
- global $wpdb;
517
-
518
- $table_structure = $wpdb->get_results("DESCRIBE $table");
519
- if (! $table_structure) {
520
- $this->error(__('Error getting table details','wp-migrate-db') . ": $table");
521
- return false;
522
- }
523
-
524
- if(($segment == 'none') || ($segment == 0)) {
525
- // Add SQL statement to drop existing table
526
- $this->stow("\n\n");
527
- $this->stow("#\n");
528
- $this->stow("# " . sprintf(__('Delete any existing table %s','wp-migrate-db'),$this->backquote($table)) . "\n");
529
- $this->stow("#\n");
530
- $this->stow("\n");
531
- $this->stow("DROP TABLE IF EXISTS " . $this->backquote($table) . ";\n");
532
-
533
- // Table structure
534
- // Comment in SQL-file
535
- $this->stow("\n\n");
536
- $this->stow("#\n");
537
- $this->stow("# " . sprintf(__('Table structure of table %s','wp-migrate-db'),$this->backquote($table)) . "\n");
538
- $this->stow("#\n");
539
- $this->stow("\n");
540
-
541
- $create_table = $wpdb->get_results("SHOW CREATE TABLE $table", ARRAY_N);
542
- if (false === $create_table) {
543
- $err_msg = sprintf(__('Error with SHOW CREATE TABLE for %s.','wp-migrate-db'), $table);
544
- $this->error($err_msg);
545
- $this->stow("#\n# $err_msg\n#\n");
546
- }
547
- $this->stow($create_table[0][1] . ' ;');
548
-
549
- if (false === $table_structure) {
550
- $err_msg = sprintf(__('Error getting table structure of %s','wp-migrate-db'), $table);
551
- $this->error($err_msg);
552
- $this->stow("#\n# $err_msg\n#\n");
553
- }
554
-
555
- // Comment in SQL-file
556
- $this->stow("\n\n");
557
- $this->stow("#\n");
558
- $this->stow('# ' . sprintf(__('Data contents of table %s','wp-migrate-db'),$this->backquote($table)) . "\n");
559
- $this->stow("#\n");
560
- }
561
-
562
- if(($segment == 'none') || ($segment >= 0)) {
563
- $defs = array();
564
- $ints = array();
565
- foreach ($table_structure as $struct) {
566
- if ( (0 === strpos($struct->Type, 'tinyint')) ||
567
- (0 === strpos(strtolower($struct->Type), 'smallint')) ||
568
- (0 === strpos(strtolower($struct->Type), 'mediumint')) ||
569
- (0 === strpos(strtolower($struct->Type), 'int')) ||
570
- (0 === strpos(strtolower($struct->Type), 'bigint')) ) {
571
- $defs[strtolower($struct->Field)] = ( null === $struct->Default ) ? 'NULL' : $struct->Default;
572
- $ints[strtolower($struct->Field)] = "1";
573
- }
574
- }
575
-
576
-
577
- // Batch by $row_inc
578
-
579
- if($segment == 'none') {
580
- $row_start = 0;
581
- $row_inc = ROWS_PER_SEGMENT;
582
- } else {
583
- $row_start = $segment * ROWS_PER_SEGMENT;
584
- $row_inc = ROWS_PER_SEGMENT;
585
- }
586
-
587
- do {
588
- $where = '';
589
- if ( isset( $_POST['exclude-spam'] ) && $wpdb->comments == $table ) {
590
- $where = ' WHERE comment_approved != "spam"';
591
- } elseif ( isset( $_POST['exclude-revisions'] ) && $wpdb->posts == $table ) {
592
- $where = ' WHERE post_type != "revision"';
593
- }
594
-
595
- if ( !ini_get('safe_mode')) @set_time_limit(15*60);
596
- $table_data = $wpdb->get_results("SELECT * FROM $table $where LIMIT {$row_start}, {$row_inc}", ARRAY_A);
597
-
598
- $entries = 'INSERT INTO ' . $this->backquote($table) . ' VALUES (';
599
- // \x08\\x09, not required
600
- $search = array("\x00", "\x0a", "\x0d", "\x1a");
601
- $replace = array('\0', '\n', '\r', '\Z');
602
- if($table_data) {
603
- foreach ($table_data as $row) {
604
- $values = array();
605
- foreach ($row as $key => $value) {
606
- if (isset( $ints[strtolower($key)] ) && $ints[strtolower($key)]) {
607
- // make sure there are no blank spots in the insert syntax,
608
- // yet try to avoid quotation marks around integers
609
- $value = ( null === $value || '' === $value) ? $defs[strtolower($key)] : $value;
610
- $values[] = ( '' === $value ) ? "''" : $value;
611
- } else {
612
- if (null === $value) {
 
 
 
613
  $values[] = 'NULL';
614
  }
615
- else {
616
- if ( is_serialized( $value ) && false !== ( $data = @unserialize( $value ) ) ) {
617
- if ( is_array( $data ) ) {
618
- array_walk_recursive( $data, array( $this, 'replace_array_values' ) );
619
- }
620
- elseif ( is_string( $data ) ) {
621
- $data = $this->apply_replaces( $data, true );
622
- }
623
-
624
- $value = serialize( $data );
625
- }
626
  // Skip replacing GUID if the option is set
627
- elseif ( 'guid' != $key || isset( $_POST['replaceguids'] ) ) {
628
- $value = $this->apply_replaces( $value );
629
  }
630
 
631
  $values[] = "'" . str_replace( $search, $replace, $this->sql_addslashes( $value ) ) . "'";
632
  }
633
- }
634
- }
635
- $this->stow(" \n" . $entries . implode(', ', $values) . ') ;');
636
- }
637
- $row_start += $row_inc;
638
- }
639
- } while((count($table_data) > 0) and ($segment=='none'));
640
- }
641
-
642
- if(($segment == 'none') || ($segment < 0)) {
643
- // Create footer/closing comment in SQL-file
644
- $this->stow("\n");
645
- $this->stow("#\n");
646
- $this->stow("# " . sprintf(__('End of data contents of table %s','wp-migrate-db'),$this->backquote($table)) . "\n");
647
- $this->stow("# --------------------------------------------------------\n");
648
- $this->stow("\n");
649
- }
650
- } // end backup_table()
651
-
652
- function replace_array_values( &$value, $key ) {
653
- if ( !is_string( $value ) ) return;
654
- $value = $this->apply_replaces( $value, true );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
655
  }
656
 
657
- function db_backup() {
658
- global $table_prefix, $wpdb;
659
 
660
- $tables = $wpdb->get_results("SHOW FULL TABLES", ARRAY_N);
661
 
662
- /*
663
  if (is_writable($this->backup_dir)) {
664
- $this->fp = $this->open($this->backup_dir . $this->backup_filename);
665
- if(!$this->fp) {
666
- $this->error(__('Could not open the backup file for writing!','wp-migrate-db'));
667
- return false;
668
- }
669
- } else {
670
- $this->error(__('The backup directory is not writeable!','wp-migrate-db'));
671
- return false;
672
- }*/
673
-
674
- foreach ($tables as $table) {
675
  if ( 'VIEW' == $table[1] ) continue;
676
  $table = $table[0];
677
- // Increase script execution time-limit to 15 min for every table.
678
- if ( !ini_get('safe_mode')) @set_time_limit(15*60);
679
- // Create the SQL statements
680
- $this->stow("# --------------------------------------------------------\n");
681
- $this->stow("# " . sprintf(__('Table: %s','wp-migrate-db'),$this->backquote($table)) . "\n");
682
- $this->stow("# --------------------------------------------------------\n");
683
- $this->backup_table($table);
684
- }
685
-
686
- //$this->close($this->fp);
687
-
688
- if (count($this->errors)) {
689
- return false;
690
- } else {
691
- //return $this->backup_filename;
692
  return true;
693
- }
694
 
695
- } //wp_db_backup
696
 
697
  function db_backup_header() {
698
- $this->stow("# " . __('WordPress MySQL database migration','wp-migrate-db') . "\n", false);
699
- $this->stow("# " . sprintf(__('From %s to %s','wp-migrate-db'), $_POST['old_url'], $_POST['new_url']) . "\n", false);
700
- $this->stow("#\n", false);
701
- $this->stow("# " . sprintf(__('Generated: %s','wp-migrate-db'),date("l j. F Y H:i T")) . "\n", false);
702
- $this->stow("# " . sprintf(__('Hostname: %s','wp-migrate-db'),DB_HOST) . "\n", false);
703
- $this->stow("# " . sprintf(__('Database: %s','wp-migrate-db'),$this->backquote(DB_NAME)) . "\n", false);
704
- $this->stow("# --------------------------------------------------------\n\n", false);
705
  }
706
 
707
- function gzip() {
708
- return function_exists('gzopen');
709
- }
710
-
711
- function open($filename = '', $mode = 'w') {
712
- if ('' == $filename) return false;
713
- if ($this->gzip() && isset( $_POST['gzipfile'] ))
714
- $fp = gzopen($filename, $mode);
715
- else
716
- $fp = fopen($filename, $mode);
717
- return $fp;
718
- }
719
-
720
- function close($fp) {
721
- if ($this->gzip() && isset( $_POST['gzipfile'] )) gzclose($fp);
722
- else fclose($fp);
723
- }
724
-
725
- function stow($query_line, $replace = true) {
726
- if ($this->gzip() && isset( $_POST['gzipfile'] )) {
727
- if(! @gzwrite($this->fp, $query_line))
728
- $this->errors['file_write'] = __('There was an error writing a line to the backup script:','wp-db-backup') . ' ' . $query_line . ' ' . $php_errormsg;
729
  } else {
730
- if(false === @fwrite($this->fp, $query_line))
731
- $this->error['file_write'] = __('There was an error writing a line to the backup script:','wp-db-backup') . ' ' . $query_line . ' ' . $php_errormsg;
732
  }
733
- }
734
-
735
- /**
736
- * Add backquotes to tables and db-names in
737
- * SQL queries. Taken from phpMyAdmin.
738
- */
739
- function backquote($a_name) {
740
- if (!empty($a_name) && $a_name != '*') {
741
- if (is_array($a_name)) {
742
- $result = array();
743
- reset($a_name);
744
- while(list($key, $val) = each($a_name))
745
- $result[$key] = '`' . $val . '`';
746
- return $result;
747
- } else {
748
- return '`' . $a_name . '`';
749
- }
750
- } else {
751
- return $a_name;
752
- }
753
- }
754
-
755
- /**
756
- * Better addslashes for SQL queries.
757
- * Taken from phpMyAdmin.
758
- */
759
- function sql_addslashes($a_string = '', $is_like = false) {
760
- if ($is_like) $a_string = str_replace('\\', '\\\\\\\\', $a_string);
761
- else $a_string = str_replace('\\', '\\\\', $a_string);
762
- return str_replace('\'', '\\\'', $a_string);
763
- }
764
 
765
  function download_file() {
766
- set_time_limit(0);
767
  $datetime = preg_replace( '@[^0-9]@', '', $_GET['download'] );
768
  $diskfile = $this->upload_dir . DS . $this->get_filename( $datetime, isset( $_GET['gz'] ) );
769
- if (file_exists($diskfile)) {
770
- header('Content-Description: File Transfer');
771
- header('Content-Type: application/octet-stream');
772
- header('Content-Length: ' . filesize($diskfile));
773
- header('Content-Disposition: attachment; filename=' . $this->get_nicename( $datetime, isset( $_GET['gz'] ) ) );
774
- $success = readfile($diskfile);
775
- unlink($diskfile);
776
  exit;
777
  }
778
  else {
779
- wp_die("Could not find the file to download:<br />$diskfile.");
780
  }
781
  }
782
 
783
  function admin_menu() {
784
- if (function_exists('add_management_page')) {
785
- add_management_page('WP Migrate DB','WP Migrate DB','update_core','wp-migrate-db',array($this, 'options_page'));
786
- }
787
 
788
- $src = plugins_url( 'asset/css/styles.css', __FILE__ );
789
- wp_enqueue_style( 'wp-migrate-db-styles', $src );
790
- $src = plugins_url( 'asset/js/script.js', __FILE__ );
791
- wp_enqueue_script( 'wp-migrate-db-script', $src, array( 'jquery' ), false, true );
792
  }
793
 
794
  function admin_head() {
795
- $url = admin_url('tools.php?page=wp-migrate-db&download=' . urlencode( $this->datetime ) );
796
  if ( isset( $_POST['gzipfile'] ) ) $url .= '&gz=1';
797
  ?>
798
  <meta http-equiv="refresh" content="1;url=<?php echo $url; ?>"/>
1
  <?php
2
  /*
3
+ Plugin Name: WP Migrate DB
4
  Plugin URI: http://wordpress.org/extend/plugins/wp-migrate-db/
5
  Description: Exports your database as a MySQL data dump (much like phpMyAdmin), does a find and replace on URLs and file paths, then allows you to save it to your computer.
6
  Author: Brad Touesnard
7
+ Version: 0.4.4
8
  Author URI: http://bradt.ca/
9
  */
10
 
25
 
26
 
27
  // Define the directory seperator if it isn't already
28
+ if ( !defined( 'DS' ) ) {
29
+ if ( strtoupper( substr( PHP_OS, 0, 3 ) ) == 'WIN' ) {
30
+ define( 'DS', '\\' );
31
  }
32
  else {
33
+ define( 'DS', '/' );
34
  }
35
  }
36
 
37
+ if ( ! defined( 'ROWS_PER_SEGMENT' ) ) {
38
+ define( 'ROWS_PER_SEGMENT', 100 );
39
  }
40
 
41
  class WP_Migrate_DB {
45
  var $fp;
46
  var $replaced;
47
  var $datetime;
48
+ var $hookname;
49
 
50
  function __construct() {
51
  $this->errors = array();
52
+ $this->upload_dir = ( defined( 'WP_CONTENT_DIR' ) ) ? WP_CONTENT_DIR . '/uploads' : ABSPATH . 'wp-content' . DS . 'uploads';
53
+ $this->upload_url = ( defined( 'WP_CONTENT_URL' ) ) ? WP_CONTENT_URL . '/uploads' : get_option( 'siteurl' ) . '/wp-content/uploads';
54
 
55
+ $this->datetime = date( 'YmdHis' );
56
 
57
  $this->replaced['serialized']['count'] = 0;
58
  $this->replaced['serialized']['strings'] = '';
60
 
61
  add_action( 'admin_menu', array( $this, 'admin_menu' ) );
62
  add_action( 'wp_ajax_subscribe_submission', array( $this, 'subscribe_submission' ) );
 
 
63
  }
64
 
65
  function subscribe_submission() {
66
  $response = wp_remote_post( 'http://bradt.ca/wpmdb-subscribe.php', array(
67
+ 'timeout' => 60,
68
+ 'body' => $_POST
69
+ ) );
70
 
71
  if ( is_wp_error( $response ) ) {
72
  echo "Error attempting to save your submission.";
73
+ }
74
  else {
75
  echo $response['body'];
76
  }
79
  }
80
 
81
  function handle_request() {
82
+ if ( isset( $_POST['Submit'] ) ) {
 
 
 
83
  $this->options_validate();
84
  }
85
 
86
  if ( empty( $this->errors ) && isset( $_POST['savefile'] ) && $_POST['savefile'] ) {
87
+ add_action( 'admin_head-' . $this->hookname, array( $this, 'admin_head' ) );
88
  }
89
+
90
+ if ( isset( $_GET['download'] ) && $_GET['download'] ) {
91
+ $this->download_file();
92
  }
93
+
94
+ $src = plugins_url( 'asset/css/styles.css', __FILE__ );
95
+ wp_enqueue_style( 'wp-migrate-db-styles', $src );
96
+ $src = plugins_url( 'asset/js/script.js', __FILE__ );
97
+ wp_enqueue_script( 'wp-migrate-db-script', $src, array( 'jquery' ), false, true );
98
  }
99
 
100
  function get_filename( $datetime, $gzip ) {
111
  }
112
 
113
  function options_validate() {
114
+ if ( !isset( $_POST['old_url'] ) || !$_POST['old_url'] ) {
115
+ $this->errors['old_url'] = __( 'Please enter the current URL.', 'wp-migrate-db' );
116
  }
117
 
118
+ if ( !isset( $_POST['new_url'] ) || !$_POST['new_url'] ) {
119
+ $this->errors['new_url'] = __( 'Please enter a new URL.', 'wp-migrate-db' );
120
  }
121
 
122
+ if ( !isset( $_POST['old_path'] ) || !$_POST['old_path'] ) {
123
+ $this->errors['old_path'] = __( 'Please enter the current file path.', 'wp-migrate-db' );
124
  }
125
 
126
+ if ( !isset( $_POST['new_path'] ) || !$_POST['new_path'] ) {
127
+ $this->errors['new_path'] = __( 'Please enter a new file path.', 'wp-migrate-db' );
128
  }
129
  }
130
 
131
+ function show_error( $key ) {
132
+ if ( isset( $this->errors[$key] ) ) {
133
  echo '<br /><span style="color: #cc0000; font-weight: bold;">', $this->errors[$key], '</span>';
134
  }
135
  }
138
  ?>
139
 
140
  <div class="wrap">
141
+ <div id="icon-tools" class="icon32"><br /></div><h2>Migrate DB</h2>
142
 
143
  <div id="wpmdb-container">
144
 
145
  <div id="wpmdb-main">
146
 
147
+ <?php
148
+ if ( isset( $_POST['Submit'] ) ) {
149
+ if ( empty( $this->errors ) ) {
150
+ $this->fp = $this->open( $this->upload_dir . DS . $this->get_filename( $this->datetime, isset( $_POST['gzipfile'] ) ) );
151
+ $this->db_backup_header();
152
+ $this->db_backup();
153
+ $this->close( $this->fp );
154
+ }
155
 
156
+ if ( empty( $this->errors ) ) {
157
+ ?>
158
 
159
+ <div class="message updated">
160
 
161
+ <?php
162
+ if ( isset( $_POST['savefile'] ) && $_POST['savefile'] ) {
163
+ add_action( 'admin_head-settings_page_wp-migrate-db', array( $this, 'admin_head' ) );
164
+ ?>
165
+ <p>
166
+ Your database (SQL) file has been successfully generated.
167
+ Your download should begin any second.
168
+ </p>
169
  <?php
170
+ }
171
+ else {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
  ?>
 
 
 
173
  <p>
174
+ Your database (SQL) file has been successfully generated and
175
+ saved to <br /><?php echo $this->upload_dir . DS . $this->get_filename( $this->datetime, isset( $_POST['gzipfile'] ) ); ?>.
176
+ <a href="<?php echo $this->upload_url, '/', $this->get_filename( $this->datetime, isset( $_POST['gzipfile'] ) ); ?>">Click
177
+ here to download.</a>
178
  </p>
179
  <?php
180
  }
181
+ ?>
182
+
183
+ </div>
184
 
185
+ <p>
186
+ <b>Non-Serialized Strings Replaced: <?php echo $this->replaced['nonserialized']['count']; ?></b><br />
187
+ <b>Serialized Strings Replaced: <?php echo $this->replaced['serialized']['count']; ?></b><br />
188
+ <textarea style="width: 100%; height: 200px;" wrap="off"><?php echo $this->replaced['serialized']['strings']; ?></textarea>
189
+ </p>
190
+ <?php
191
  }
 
 
192
 
193
+ $form_values = $_POST;
194
+ }
195
+ else {
196
+ $form_values['old_url'] = get_bloginfo( 'url' );
197
 
198
+ $form_values['old_path'] = dirname( __FILE__ );
199
+ $form_values['old_path'] = str_replace( DS . 'wp-migrate-db', '', $form_values['old_path'] );
200
+ $form_values['old_path'] = realpath( $form_values['old_path'] . '/../..' );
 
 
201
 
202
+ if ( get_bloginfo( 'url' ) != get_bloginfo( 'wpurl' ) ) {
203
+ $wp_dir = str_replace( get_bloginfo( 'url' ), '', get_bloginfo( 'wpurl' ) );
204
+ $wp_dir = str_replace( '/', DS, $wp_dir );
205
+ $form_values['old_path'] = str_replace( $wp_dir, '', $form_values['old_path'] );
206
  }
207
 
208
+ $form_values['new_path'] = $form_values['new_url'] = '';
209
+ }
 
 
 
 
 
 
 
 
210
 
211
+ if ( !isset( $_POST['Submit'] ) || ( isset( $_POST['Submit'] ) && !empty( $this->errors ) ) ) {
212
+ if ( !is_writable( $this->upload_dir ) ) {
213
+ ?>
214
 
215
+ <div id="message" class="message error">
216
+ <p>
217
+ The directory <?php echo $this->upload_dir; ?> needs
218
+ to be writable.
219
+ </p>
220
+ </div>
221
 
222
+ <?php
223
+ }
 
 
 
 
224
 
225
+ if ( !empty( $this->errors ) ) {
 
226
  ?>
227
 
228
+ <div id="message" class="message error">
229
+ <p>
230
+ Sorry, there were errors with your form submission.
231
+ Please correct them below and try again.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
  </p>
233
+ </div>
234
 
235
  <?php
236
  }
237
  ?>
 
238
 
239
+ <p>
240
+ WP Migrate DB exports your database as a MySQL data dump (much like phpMyAdmin),
241
+ does a find and replace on URLs and file paths, then allows you to save
242
+ it to your computer. It even takes into account serialized data and updates the
243
+ string length values.
244
+ </p>
245
+ <p>
246
+ Example: <code>s:5:"hello"</code> becomes <code>s:11:"hello world"</code>
247
+ </p>
248
+
249
+ <form method="post" id="migrate-form">
250
+ <table class="form-table">
251
+ <tbody>
252
+ <tr valign="top" class="row-old-url">
253
+ <th scope="row">
254
+ <label for="old_url">Current address (URL)</label>
255
+ </th>
256
+ <td>
257
+ <input type="text" size="40" name="old_url" class="code" id="old_url" value="<?php echo htmlentities( $form_values['old_url'] ); ?>" />
258
+ <?php $this->show_error( 'old_url' ); ?>
259
+ </td>
260
+ </tr>
261
+ <tr valign="top" class="row-new-url">
262
+ <th scope="row">
263
+ <label for="new_url">New address (URL)</label>
264
+ </th>
265
+ <td>
266
+ <input type="text" size="40" name="new_url" class="code" id="new_url" value="<?php echo htmlentities( $form_values['new_url'] ); ?>" />
267
+ <?php $this->show_error( 'new_url' ); ?>
268
+ </td>
269
+ </tr>
270
+ <tr valign="top" class="row-old-path">
271
+ <th scope="row">
272
+ <label for="old_path">Current file path</label>
273
+ </th>
274
+ <td>
275
+ <input type="text" size="40" name="old_path" class="code" id="old_path" value="<?php echo htmlentities( $form_values['old_path'] ); ?>" />
276
+ <?php $this->show_error( 'old_path' ); ?>
277
+ </td>
278
+ </tr>
279
+ <tr valign="top" class="row-new-path">
280
+ <th scope="row">
281
+ <label for="new_path">New file path</label>
282
+ </th>
283
+ <td>
284
+ <input type="text" size="40" name="new_path" class="code" id="new_path" value="<?php echo htmlentities( $form_values['new_path'] ); ?>" />
285
+ <?php $this->show_error( 'new_path' ); ?>
286
+ </td>
287
+ </tr>
288
+ <tr valign="top" class="row-guids">
289
+ <th scope="row">Data Options</th>
290
+ <td>
291
+ <label for="replace-guids">
292
+ <input id="replace-guids" type="checkbox" checked="checked" value="1" name="replaceguids"/>
293
+ Replace GUIDs</label>
294
+
295
+ <a href="" id="replace-guids-info-link">show more</a>
296
+
297
+ <div id="replace-guids-info" style="display: none;">
298
+ <p>
299
+ Although the <a href="http://codex.wordpress.org/Changing_The_Site_URL#Important_GUID_Note" target="_blank">WordPress Codex emphasizes</a>
300
+ that GUIDs should not be changed, this is limited to sites that are already live.
301
+ If the site has never been live, I recommend replacing the GUIDs. For example, you may be
302
+ developing a new site locally at dev.somedomain.com and want to
303
+ migrate the site live to somedomain.com.
304
+ </p>
305
+ </div>
306
+ </td>
307
+ </tr>
308
+ <tr valign="top" class="row-spam">
309
+ <th scope="row">&nbsp;</th>
310
+ <td>
311
+ <label for="exclude-spam">
312
+ <input id="exclude-spam" type="checkbox" value="1" name="exclude-spam" />
313
+ Do not export spam comments
314
+ </label>
315
+ </td>
316
+ </tr>
317
+ <tr valign="top" class="row-revisions">
318
+ <th scope="row">&nbsp;</th>
319
+ <td>
320
+ <label for="exclude-revisions">
321
+ <input id="exclude-revisions" type="checkbox" value="1" name="exclude-revisions" />
322
+ Do not export post revisions
323
+ </label>
324
+ </td>
325
+ </tr>
326
+ <tr valign="top" class="row-save-file">
327
+ <th scope="row">File Options</th>
328
+ <td>
329
+ <label for="savefile">
330
+ <input id="savefile" type="checkbox" checked="checked" value="1" name="savefile"/>
331
+ Save as file to your computer
332
+ </label>
333
+ </td>
334
+ </tr>
335
+ <?php if ( $this->gzip() ) : ?>
336
+ <tr valign="top" class="row-gzip">
337
+ <th scope="row">&nbsp;</th>
338
+ <td>
339
+ <label for="gzipfile">
340
+ <input id="gzipfile" type="checkbox" value="1" name="gzipfile" />
341
+ Compress file with gzip
342
+ </label>
343
+ </td>
344
+ </tr>
345
+ <?php endif; ?>
346
+ </tbody>
347
+ </table>
348
+
349
+ <p class="submit">
350
+ <input class="button" type="submit" value="Export Database" name="Submit"/>
351
+ </p>
352
+ </form>
353
 
354
+ <?php
355
+ }
356
+ ?>
357
+ </div>
358
+
359
+ <div id="wpmdb-sidebar">
360
 
361
+ <div class="author">
362
+ <img src="http://www.gravatar.com/avatar/e538ca4cb34839d4e5e3ccf20c37c67b?s=128&amp;d" width="64" height="64" />
363
+ <div class="desc">
364
+ <h3>Created &amp; maintained by</h3>
365
+ <h2>Brad Touesnard</h2>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
366
  <p>
367
+ <a href="http://profiles.wordpress.org/bradt/">Profile</a>
368
+ &nbsp;&nbsp;
369
+ <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=5VPMGLLK94XJC">Donate</a>
370
  </p>
371
  </div>
 
372
  </div>
373
 
374
+ <form method="post" action="http://deliciousbrains.createsend.com/t/t/s/virn/" target="_blank" class="subscribe">
375
+ <h2>Pro Version Has Arrived!</h2>
 
 
376
 
377
+ <a class="video" target="_blank" href="http://deliciousbrains.com/wp-migrate-db-pro/?utm_source=insideplugin&utm_medium=web&utm_campaign=freeplugin#play-intro"><img src="<?php echo plugins_url( 'asset/img/video@2x.jpg', __FILE__ ); ?>" width="250" height="164" alt="" /></a>
378
+
379
+ <p class="links">
380
+ <a href="http://deliciousbrains.com/wp-migrate-db-pro/?utm_source=insideplugin&utm_medium=web&utm_campaign=freeplugin" target="_blank">View Features &rarr;</a>
381
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://deliciousbrains.com/wp-migrate-db-pro/pricing/?utm_source=insideplugin&utm_medium=web&utm_campaign=freeplugin" target="_blank">View Pricing &rarr;</a>
382
+ </p>
383
+
384
+ <?php $user = wp_get_current_user(); ?>
385
+
386
+ <h3><em>Get 20% Off!</em></h3>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387
 
388
+ <p class="interesting">
389
+ Subscribe to receive news &amp; updates below and we'll
390
+ instantly send you a coupon code to get 20% off any WP Migrate DB Pro license.
391
+ </p>
392
+
393
+ <div class="field notify-name">
394
+ <p>Your Name</p>
395
+ <input type="text" name="cm-name" value="<?php echo trim( esc_attr( $user->first_name ) . ' ' . esc_attr( $user->last_name ) ); ?>" />
396
+ </div>
397
+
398
+ <div class="field notify-email">
399
+ <p>Your Email</p>
400
+ <input type="email" name="cm-virn-virn" value="<?php echo esc_attr( $user->user_email ); ?>" />
401
+ </div>
402
 
403
+ <div class="field submit-button">
404
+ <input type="submit" class="button" value="Subscribe" />
405
+ </div>
406
+
407
+ <p class="promise">
408
+ I promise I will not use your email for anything else
409
+ and you can unsubscribe with <span style="white-space: nowrap;">1-click anytime</span>.
410
+ </p>
411
+ </form>
412
+
413
+ </div>
414
 
415
+ </div>
416
+ </div>
417
+ <?php
418
  }
419
 
420
  function apply_replaces( $subject, $is_serialized = false ) {
436
  return $new;
437
  }
438
 
439
+ /**
440
+ * Taken partially from phpMyAdmin and partially from
441
+ * Alain Wolf, Zurich - Switzerland
442
+ * Website: http://restkultur.ch/personal/wolf/scripts/db_backup/
443
+ *
444
+ * Modified by Scott Merrill (http://www.skippy.net/)
445
+ * to use the WordPress $wpdb object
446
+ *
447
+ * @param string $table
448
+ * @param string $segment
449
+ * @return void
450
+ */
451
+ function backup_table( $table, $segment = 'none' ) {
452
+ global $wpdb;
453
+
454
+ $table_structure = $wpdb->get_results( "DESCRIBE $table" );
455
+ if ( ! $table_structure ) {
456
+ $this->error( __( 'Error getting table details', 'wp-migrate-db' ) . ": $table" );
457
+ return false;
458
+ }
459
+
460
+ if ( ( $segment == 'none' ) || ( $segment == 0 ) ) {
461
+ // Add SQL statement to drop existing table
462
+ $this->stow( "\n\n" );
463
+ $this->stow( "#\n" );
464
+ $this->stow( "# " . sprintf( __( 'Delete any existing table %s', 'wp-migrate-db' ), $this->backquote( $table ) ) . "\n" );
465
+ $this->stow( "#\n" );
466
+ $this->stow( "\n" );
467
+ $this->stow( "DROP TABLE IF EXISTS " . $this->backquote( $table ) . ";\n" );
468
+
469
+ // Table structure
470
+ // Comment in SQL-file
471
+ $this->stow( "\n\n" );
472
+ $this->stow( "#\n" );
473
+ $this->stow( "# " . sprintf( __( 'Table structure of table %s', 'wp-migrate-db' ), $this->backquote( $table ) ) . "\n" );
474
+ $this->stow( "#\n" );
475
+ $this->stow( "\n" );
476
+
477
+ $create_table = $wpdb->get_results( "SHOW CREATE TABLE $table", ARRAY_N );
478
+ if ( false === $create_table ) {
479
+ $err_msg = sprintf( __( 'Error with SHOW CREATE TABLE for %s.', 'wp-migrate-db' ), $table );
480
+ $this->error( $err_msg );
481
+ $this->stow( "#\n# $err_msg\n#\n" );
482
+ }
483
+ $this->stow( $create_table[0][1] . ' ;' );
484
+
485
+ if ( false === $table_structure ) {
486
+ $err_msg = sprintf( __( 'Error getting table structure of %s', 'wp-migrate-db' ), $table );
487
+ $this->error( $err_msg );
488
+ $this->stow( "#\n# $err_msg\n#\n" );
489
+ }
490
+
491
+ // Comment in SQL-file
492
+ $this->stow( "\n\n" );
493
+ $this->stow( "#\n" );
494
+ $this->stow( '# ' . sprintf( __( 'Data contents of table %s', 'wp-migrate-db' ), $this->backquote( $table ) ) . "\n" );
495
+ $this->stow( "#\n" );
496
+ }
497
+
498
+ if ( ( $segment == 'none' ) || ( $segment >= 0 ) ) {
499
+ $defs = array();
500
+ $ints = array();
501
+ foreach ( $table_structure as $struct ) {
502
+ if ( ( 0 === strpos( $struct->Type, 'tinyint' ) ) ||
503
+ ( 0 === strpos( strtolower( $struct->Type ), 'smallint' ) ) ||
504
+ ( 0 === strpos( strtolower( $struct->Type ), 'mediumint' ) ) ||
505
+ ( 0 === strpos( strtolower( $struct->Type ), 'int' ) ) ||
506
+ ( 0 === strpos( strtolower( $struct->Type ), 'bigint' ) ) ) {
507
+ $defs[strtolower( $struct->Field )] = ( null === $struct->Default ) ? 'NULL' : $struct->Default;
508
+ $ints[strtolower( $struct->Field )] = "1";
509
+ }
510
+ }
511
+
512
+
513
+ // Batch by $row_inc
514
+
515
+ if ( $segment == 'none' ) {
516
+ $row_start = 0;
517
+ $row_inc = ROWS_PER_SEGMENT;
518
+ } else {
519
+ $row_start = $segment * ROWS_PER_SEGMENT;
520
+ $row_inc = ROWS_PER_SEGMENT;
521
+ }
522
+
523
+ do {
524
+ $where = '';
525
+ // We need ORDER BY here because with LIMIT, sometimes it will return
526
+ // the same results from the previous query and we'll have duplicate insert statements
527
+ if ( isset( $_POST['exclude-spam'] ) && $wpdb->comments == $table ) {
528
+ $where = ' WHERE comment_approved != "spam" ORDER BY comment_ID';
529
+ } elseif ( isset( $_POST['exclude-revisions'] ) && $wpdb->posts == $table ) {
530
+ $where = ' WHERE post_type != "revision" ORDER BY ID';
531
+ }
532
+
533
+ if ( !ini_get( 'safe_mode' ) ) @set_time_limit( 15*60 );
534
+ $table_data = $wpdb->get_results( "SELECT * FROM $table $where LIMIT {$row_start}, {$row_inc}", ARRAY_A );
535
+
536
+ $entries = 'INSERT INTO ' . $this->backquote( $table ) . ' VALUES (';
537
+ // \x08\\x09, not required
538
+ $search = array( "\x00", "\x0a", "\x0d", "\x1a" );
539
+ $replace = array( '\0', '\n', '\r', '\Z' );
540
+ if ( $table_data ) {
541
+ foreach ( $table_data as $row ) {
542
+ $values = array();
543
+ foreach ( $row as $key => $value ) {
544
+ if ( isset( $ints[strtolower( $key )] ) && $ints[strtolower( $key )] ) {
545
+ // make sure there are no blank spots in the insert syntax,
546
+ // yet try to avoid quotation marks around integers
547
+ $value = ( null === $value || '' === $value ) ? $defs[strtolower( $key )] : $value;
548
+ $values[] = ( '' === $value ) ? "''" : $value;
549
+ } else {
550
+ if ( null === $value ) {
551
  $values[] = 'NULL';
552
  }
553
+ else {
 
 
 
 
 
 
 
 
 
 
554
  // Skip replacing GUID if the option is set
555
+ if ( 'guid' != $key || isset( $_POST['replaceguids'] ) ) {
556
+ $value = $this->recursive_unserialize_replace( $value );
557
  }
558
 
559
  $values[] = "'" . str_replace( $search, $replace, $this->sql_addslashes( $value ) ) . "'";
560
  }
561
+ }
562
+ }
563
+ $this->stow( " \n" . $entries . implode( ', ', $values ) . ') ;' );
564
+ }
565
+ $row_start += $row_inc;
566
+ }
567
+ } while ( ( count( $table_data ) > 0 ) and ( $segment=='none' ) );
568
+ }
569
+
570
+ if ( ( $segment == 'none' ) || ( $segment < 0 ) ) {
571
+ // Create footer/closing comment in SQL-file
572
+ $this->stow( "\n" );
573
+ $this->stow( "#\n" );
574
+ $this->stow( "# " . sprintf( __( 'End of data contents of table %s', 'wp-migrate-db' ), $this->backquote( $table ) ) . "\n" );
575
+ $this->stow( "# --------------------------------------------------------\n" );
576
+ $this->stow( "\n" );
577
+ }
578
+ } // end backup_table()
579
+
580
+ /**
581
+ * Take a serialized array and unserialize it replacing elements as needed and
582
+ * unserialising any subordinate arrays and performing the replace on those too.
583
+ *
584
+ * Mostly from https://github.com/interconnectit/Search-Replace-DB
585
+ *
586
+ * @param array $data Used to pass any subordinate arrays back to in.
587
+ * @param bool $serialized Does the array passed via $data need serialising.
588
+ * @param bool $parent_serialized Passes whether the original data passed in was serialized
589
+ *
590
+ * @return array The original array with all elements replaced as needed.
591
+ */
592
+ function recursive_unserialize_replace( $data, $serialized = false, $parent_serialized = false ) {
593
+
594
+ // some unseriliased data cannot be re-serialized eg. SimpleXMLElements
595
+ try {
596
+
597
+ if ( is_string( $data ) && ( $unserialized = @unserialize( $data ) ) !== false ) {
598
+ $data = $this->recursive_unserialize_replace( $unserialized, true, true );
599
+ }
600
+ elseif ( is_array( $data ) ) {
601
+ $_tmp = array( );
602
+ foreach ( $data as $key => $value ) {
603
+ $_tmp[ $key ] = $this->recursive_unserialize_replace( $value, false, $parent_serialized );
604
+ }
605
+
606
+ $data = $_tmp;
607
+ unset( $_tmp );
608
+ }
609
+ // Submitted by Tina Matter
610
+ elseif ( is_object( $data ) ) {
611
+ $dataClass = get_class( $data );
612
+ $_tmp = new $dataClass( );
613
+ foreach ( $data as $key => $value ) {
614
+ $_tmp->$key = $this->recursive_unserialize_replace( $value, false, $parent_serialized );
615
+ }
616
+
617
+ $data = $_tmp;
618
+ unset( $_tmp );
619
+ }
620
+ elseif ( is_string( $data ) ) {
621
+ $data = $this->apply_replaces( $data, $parent_serialized );
622
+ }
623
+
624
+ if ( $serialized )
625
+ return serialize( $data );
626
+
627
+ } catch( Exception $error ) {
628
+
629
+ }
630
+
631
+ return $data;
632
  }
633
 
634
+ function db_backup() {
635
+ global $table_prefix, $wpdb;
636
 
637
+ $tables = $wpdb->get_results( "SHOW FULL TABLES", ARRAY_N );
638
 
639
+ /*
640
  if (is_writable($this->backup_dir)) {
641
+ $this->fp = $this->open($this->backup_dir . $this->backup_filename);
642
+ if(!$this->fp) {
643
+ $this->error(__('Could not open the backup file for writing!','wp-migrate-db'));
644
+ return false;
645
+ }
646
+ } else {
647
+ $this->error(__('The backup directory is not writeable!','wp-migrate-db'));
648
+ return false;
649
+ }*/
650
+
651
+ foreach ( $tables as $table ) {
652
  if ( 'VIEW' == $table[1] ) continue;
653
  $table = $table[0];
654
+ // Increase script execution time-limit to 15 min for every table.
655
+ if ( !ini_get( 'safe_mode' ) ) @set_time_limit( 15*60 );
656
+ // Create the SQL statements
657
+ $this->stow( "# --------------------------------------------------------\n" );
658
+ $this->stow( "# " . sprintf( __( 'Table: %s', 'wp-migrate-db' ), $this->backquote( $table ) ) . "\n" );
659
+ $this->stow( "# --------------------------------------------------------\n" );
660
+ $this->backup_table( $table );
661
+ }
662
+
663
+ //$this->close($this->fp);
664
+
665
+ if ( count( $this->errors ) ) {
666
+ return false;
667
+ } else {
668
+ //return $this->backup_filename;
669
  return true;
670
+ }
671
 
672
+ } //wp_db_backup
673
 
674
  function db_backup_header() {
675
+ $this->stow( "# " . __( 'WordPress MySQL database migration', 'wp-migrate-db' ) . "\n", false );
676
+ $this->stow( "# " . sprintf( __( 'From %s to %s', 'wp-migrate-db' ), $_POST['old_url'], $_POST['new_url'] ) . "\n", false );
677
+ $this->stow( "#\n", false );
678
+ $this->stow( "# " . sprintf( __( 'Generated: %s', 'wp-migrate-db' ), date( "l j. F Y H:i T" ) ) . "\n", false );
679
+ $this->stow( "# " . sprintf( __( 'Hostname: %s', 'wp-migrate-db' ), DB_HOST ) . "\n", false );
680
+ $this->stow( "# " . sprintf( __( 'Database: %s', 'wp-migrate-db' ), $this->backquote( DB_NAME ) ) . "\n", false );
681
+ $this->stow( "# --------------------------------------------------------\n\n", false );
682
  }
683
 
684
+ function gzip() {
685
+ return function_exists( 'gzopen' );
686
+ }
687
+
688
+ function open( $filename = '', $mode = 'w' ) {
689
+ if ( '' == $filename ) return false;
690
+ if ( $this->gzip() && isset( $_POST['gzipfile'] ) )
691
+ $fp = gzopen( $filename, $mode );
692
+ else
693
+ $fp = fopen( $filename, $mode );
694
+ return $fp;
695
+ }
696
+
697
+ function close( $fp ) {
698
+ if ( $this->gzip() && isset( $_POST['gzipfile'] ) ) gzclose( $fp );
699
+ else fclose( $fp );
700
+ }
701
+
702
+ function stow( $query_line, $replace = true ) {
703
+ if ( $this->gzip() && isset( $_POST['gzipfile'] ) ) {
704
+ if ( ! @gzwrite( $this->fp, $query_line ) )
705
+ $this->errors['file_write'] = __( 'There was an error writing a line to the backup script:', 'wp-db-backup' ) . ' ' . $query_line . ' ' . $php_errormsg;
706
  } else {
707
+ if ( false === @fwrite( $this->fp, $query_line ) )
708
+ $this->error['file_write'] = __( 'There was an error writing a line to the backup script:', 'wp-db-backup' ) . ' ' . $query_line . ' ' . $php_errormsg;
709
  }
710
+ }
711
+
712
+ /**
713
+ * Add backquotes to tables and db-names in
714
+ * SQL queries. Taken from phpMyAdmin.
715
+ */
716
+ function backquote( $a_name ) {
717
+ if ( !empty( $a_name ) && $a_name != '*' ) {
718
+ if ( is_array( $a_name ) ) {
719
+ $result = array();
720
+ reset( $a_name );
721
+ while ( list( $key, $val ) = each( $a_name ) )
722
+ $result[$key] = '`' . $val . '`';
723
+ return $result;
724
+ } else {
725
+ return '`' . $a_name . '`';
726
+ }
727
+ } else {
728
+ return $a_name;
729
+ }
730
+ }
731
+
732
+ /**
733
+ * Better addslashes for SQL queries.
734
+ * Taken from phpMyAdmin.
735
+ */
736
+ function sql_addslashes( $a_string = '', $is_like = false ) {
737
+ if ( $is_like ) $a_string = str_replace( '\\', '\\\\\\\\', $a_string );
738
+ else $a_string = str_replace( '\\', '\\\\', $a_string );
739
+ return str_replace( '\'', '\\\'', $a_string );
740
+ }
741
 
742
  function download_file() {
743
+ set_time_limit( 0 );
744
  $datetime = preg_replace( '@[^0-9]@', '', $_GET['download'] );
745
  $diskfile = $this->upload_dir . DS . $this->get_filename( $datetime, isset( $_GET['gz'] ) );
746
+ if ( file_exists( $diskfile ) ) {
747
+ header( 'Content-Description: File Transfer' );
748
+ header( 'Content-Type: application/octet-stream' );
749
+ header( 'Content-Length: ' . filesize( $diskfile ) );
750
+ header( 'Content-Disposition: attachment; filename=' . $this->get_nicename( $datetime, isset( $_GET['gz'] ) ) );
751
+ $success = readfile( $diskfile );
752
+ unlink( $diskfile );
753
  exit;
754
  }
755
  else {
756
+ wp_die( "Could not find the file to download:<br />$diskfile." );
757
  }
758
  }
759
 
760
  function admin_menu() {
761
+ $this->hookname = add_management_page( 'Migrate DB', 'Migrate DB', 'export', 'wp-migrate-db', array( $this, 'options_page' ) );
 
 
762
 
763
+ add_action( 'load-' . $this->hookname , array( $this, 'handle_request' ) );
 
 
 
764
  }
765
 
766
  function admin_head() {
767
+ $url = admin_url( 'tools.php?page=wp-migrate-db&download=' . urlencode( $this->datetime ) );
768
  if ( isset( $_POST['gzipfile'] ) ) $url .= '&gz=1';
769
  ?>
770
  <meta http-equiv="refresh" content="1;url=<?php echo $url; ?>"/>