Go Live Update URLS - Version 5.2.0

Version Description

  • Support URL Encoded URLS within serialized data
  • Support JSON Encoded URLS within serialized data
Download this release

Release Info

Developer Mat Lipe
Plugin Icon 128x128 Go Live Update URLS
Version 5.2.0
Comparing to
See all releases

Code changes from version 5.1.2 to 5.2.0

go-live-update-urls.php CHANGED
@@ -5,11 +5,11 @@ Plugin URI: https://matlipe.com/go-live-update-urls/
5
  Description: Updates all the URLs in the database to point to a new URL when making your site live or changing domains.
6
  Author: Mat Lipe
7
  Author URI: https://matlipe.com/
8
- Version: 5.1.2
9
  Text Domain: go-live-update-urls
10
  */
11
 
12
- define( 'GO_LIVE_UPDATE_URLS_VERSION', '5.1.2' );
13
 
14
  function go_live_update_urls_load() {
15
  load_plugin_textdomain( 'go-live-update-urls', false, 'go-live-update-urls/languages' );
@@ -35,6 +35,7 @@ function go_live_update_urls_autoload( $class ) {
35
  'Go_Live_Update_Urls_Admin_Page' => 'Admin_Page.php',
36
  'Go_Live_Update_Urls_Core' => 'Core.php',
37
  'Go_Live_Update_Urls_Database' => 'Database.php',
 
38
  //updaters
39
  'Go_Live_Update_Urls__Updaters__Abstract' => 'Updaters/Abstract.php',
40
  'Go_Live_Update_Urls__Updaters__JSON' => 'Updaters/JSON.php',
5
  Description: Updates all the URLs in the database to point to a new URL when making your site live or changing domains.
6
  Author: Mat Lipe
7
  Author URI: https://matlipe.com/
8
+ Version: 5.2.0
9
  Text Domain: go-live-update-urls
10
  */
11
 
12
+ define( 'GO_LIVE_UPDATE_URLS_VERSION', '5.2.0' );
13
 
14
  function go_live_update_urls_load() {
15
  load_plugin_textdomain( 'go-live-update-urls', false, 'go-live-update-urls/languages' );
35
  'Go_Live_Update_Urls_Admin_Page' => 'Admin_Page.php',
36
  'Go_Live_Update_Urls_Core' => 'Core.php',
37
  'Go_Live_Update_Urls_Database' => 'Database.php',
38
+ 'Go_Live_Update_Urls_Serialized' => 'Serialized.php',
39
  //updaters
40
  'Go_Live_Update_Urls__Updaters__Abstract' => 'Updaters/Abstract.php',
41
  'Go_Live_Update_Urls__Updaters__JSON' => 'Updaters/JSON.php',
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: Go Live, Urls, Domain Changes
5
  Requires at least: 4.6.0
6
  Tested up to: 4.9.8
7
  Requires PHP: 5.2.4
8
- Stable tag: 5.1.2
9
 
10
  == Description ==
11
 
@@ -88,6 +88,10 @@ If you wish to try to update tables mentioned as not safe anyway, you may make a
88
  1. Typical settings page. The verbiage will change slightly depending on your database structure
89
 
90
  == Changelog ==
 
 
 
 
91
  = 5.1.0 =
92
  * Added new languages including French, German, and Spanish
93
  * Support upcoming blogmeta table in WP 5.0.0+
5
  Requires at least: 4.6.0
6
  Tested up to: 4.9.8
7
  Requires PHP: 5.2.4
8
+ Stable tag: 5.2.0
9
 
10
  == Description ==
11
 
88
  1. Typical settings page. The verbiage will change slightly depending on your database structure
89
 
90
  == Changelog ==
91
+ = 5.2.0 =
92
+ * Support URL Encoded URLS within serialized data
93
+ * Support JSON Encoded URLS within serialized data
94
+
95
  = 5.1.0 =
96
  * Added new languages including French, German, and Spanish
97
  * Support upcoming blogmeta table in WP 5.0.0+
src/Database.php CHANGED
@@ -181,7 +181,6 @@ class Go_Live_Update_Urls_Database {
181
  $this->double_subdomain = $subdomain . '.' . $this->new_url;
182
  }
183
 
184
- $serialized_tables = $this->get_serialized_tables();
185
  $tables = apply_filters( 'go-live-update-urls/database/update-tables', $tables, $this );
186
 
187
  // Backward compatibility
@@ -189,18 +188,15 @@ class Go_Live_Update_Urls_Database {
189
  $tables = (array) array_flip( $tables );
190
  }
191
 
 
 
 
 
 
 
 
192
  //Go through each table sent to be updated
193
  foreach ( (array) $tables as $table ) {
194
- if ( isset( $serialized_tables[ $table ] ) ) {
195
- if ( is_array( $serialized_tables[ $table ] ) ) {
196
- foreach ( $serialized_tables[ $table ] as $column ) {
197
- $this->update_serialized_table( $table, $column );
198
- }
199
- } else {
200
- $this->update_serialized_table( $table, $serialized_tables[ $table ] );
201
- }
202
- }
203
-
204
  $column_query = "SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='{$wpdb->dbname}' AND TABLE_NAME=%s";
205
  $columns = $wpdb->get_col( $wpdb->prepare( $column_query, $table ) );
206
 
@@ -208,9 +204,7 @@ class Go_Live_Update_Urls_Database {
208
  $update_query = 'UPDATE ' . $table . ' SET ' . $_column . ' = replace(' . $_column . ', %s, %s)';
209
  $wpdb->query( $wpdb->prepare( $update_query, array( $this->old_url, $this->new_url ) ) );
210
 
211
-
212
  //Run each updater
213
- //@todo convert all the steps to their own updater class
214
  foreach ( $updaters as $_updater_class ) {
215
  if ( class_exists( $_updater_class ) ) {
216
  /** @var Go_Live_Update_Urls__Updaters__Abstract $_updater */
@@ -248,94 +242,6 @@ class Go_Live_Update_Urls_Database {
248
  }
249
 
250
 
251
- /**
252
- * Goes through a table line by line and updates it
253
- *
254
- * @uses for tables which may contain serialized arrays
255
- *
256
- * @since 5.0.0
257
- *
258
- * @param string $table the table
259
- * @param string $column to column in the table
260
- *
261
- * @return void
262
- */
263
- protected function update_serialized_table( $table, $column ) {
264
- global $wpdb;
265
- $pk = $wpdb->get_results( "SHOW KEYS FROM $table WHERE Key_name = 'PRIMARY'" );
266
- if ( empty( $pk[0] ) ) {
267
- $pk = $wpdb->get_results( "SHOW KEYS FROM $table" );
268
- if ( empty( $pk[0] ) ) {
269
- //fail
270
- return;
271
- }
272
- }
273
-
274
- $primary_key_column = $pk[0]->Column_name;
275
-
276
- //Get all the Serialized Rows and Replace them properly
277
- $rows = $wpdb->get_results( "SELECT $primary_key_column, $column FROM $table WHERE $column LIKE 'a:%' OR $column LIKE 'O:%'" );
278
-
279
- foreach ( $rows as $row ) {
280
- if ( ! is_serialized( $row->{$column} ) ) {
281
- continue;
282
- }
283
-
284
- if ( strpos( $row->{$column}, $this->old_url ) === false ) {
285
- continue;
286
- }
287
-
288
- $data = @unserialize( $row->{$column} );
289
-
290
- $clean = $this->replace_tree( $data, $this->old_url, $this->new_url );
291
- //If we switch to a submain we have to run this again to remove the doubles
292
- if ( $this->double_subdomain ) {
293
- $clean = $this->replace_tree( $clean, $this->double_subdomain, $this->new_url );
294
- }
295
-
296
- $clean = @serialize( $clean );
297
-
298
- $wpdb->query( $wpdb->prepare( "UPDATE $table SET $column=%s WHERE $primary_key_column=%s", $clean, $row->{$primary_key_column} ) );
299
-
300
- }
301
- }
302
-
303
-
304
- /**
305
- * Replaces all the occurrences of a string in a multi-dimensional array or Object
306
- *
307
- * @uses itself to call each level of the array
308
- *
309
- * @param iterable|string $data to change
310
- * @param string $old the old string
311
- * @param string $new the new string
312
- *
313
- * @since 5.0.0
314
- *
315
- * @return mixed
316
- *
317
- */
318
- protected function replace_tree( $data, $old, $new ) {
319
- if ( is_string( $data ) ) {
320
- return trim( str_replace( $old, $new, $data ) );
321
- }
322
-
323
- if ( ! is_array( $data ) && ! is_object( $data ) ) {
324
- return $data;
325
- }
326
-
327
- foreach ( $data as $key => $item ) {
328
- if ( is_array( $data ) ) {
329
- $data[ $key ] = $this->replace_tree( $item, $old, $new );
330
- } else {
331
- $data->{$key} = $this->replace_tree( $item, $old, $new );
332
- }
333
- }
334
-
335
- return $data;
336
- }
337
-
338
-
339
  protected function hook() {
340
 
341
  }
181
  $this->double_subdomain = $subdomain . '.' . $this->new_url;
182
  }
183
 
 
184
  $tables = apply_filters( 'go-live-update-urls/database/update-tables', $tables, $this );
185
 
186
  // Backward compatibility
188
  $tables = (array) array_flip( $tables );
189
  }
190
 
191
+ $serialized = new Go_Live_Update_Urls_Serialized( $this->old_url, $this->new_url );
192
+ $serialized->update_all_serialized_tables();
193
+ if ( $this->double_subdomain ) {
194
+ $serialized = new Go_Live_Update_Urls_Serialized( $this->double_subdomain, $this->new_url );
195
+ $serialized->update_all_serialized_tables();
196
+ }
197
+
198
  //Go through each table sent to be updated
199
  foreach ( (array) $tables as $table ) {
 
 
 
 
 
 
 
 
 
 
200
  $column_query = "SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='{$wpdb->dbname}' AND TABLE_NAME=%s";
201
  $columns = $wpdb->get_col( $wpdb->prepare( $column_query, $table ) );
202
 
204
  $update_query = 'UPDATE ' . $table . ' SET ' . $_column . ' = replace(' . $_column . ', %s, %s)';
205
  $wpdb->query( $wpdb->prepare( $update_query, array( $this->old_url, $this->new_url ) ) );
206
 
 
207
  //Run each updater
 
208
  foreach ( $updaters as $_updater_class ) {
209
  if ( class_exists( $_updater_class ) ) {
210
  /** @var Go_Live_Update_Urls__Updaters__Abstract $_updater */
242
  }
243
 
244
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  protected function hook() {
246
 
247
  }
src/Serialized.php ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * @author Mat Lipe
5
+ * @since 5.2.0
6
+ *
7
+ */
8
+ class Go_Live_Update_Urls_Serialized {
9
+ protected $column;
10
+ protected $new;
11
+ protected $old;
12
+ protected $table;
13
+
14
+
15
+ public function __construct( $old, $new ) {
16
+ $this->new = $new;
17
+ $this->old = $old;
18
+ }
19
+
20
+
21
+ /**
22
+ * Go through every registered serialized table and update them one by one
23
+ *
24
+ * @return void
25
+ */
26
+ public function update_all_serialized_tables() {
27
+ $serialized_tables = Go_Live_Update_Urls_Database::instance()->get_serialized_tables();
28
+
29
+ foreach ( $serialized_tables as $table => $columns ) {
30
+ foreach ( (array) $columns as $_column ) {
31
+ $this->update_table( $table, $_column );
32
+ }
33
+ }
34
+ }
35
+
36
+
37
+ /**
38
+ * Query all serialized rows from a database table and update them one by one
39
+ *
40
+ * @param $table
41
+ * @param $column
42
+ *
43
+ * @return void
44
+ */
45
+ protected function update_table( $table, $column ) {
46
+ global $wpdb;
47
+ $pk = $wpdb->get_results( "SHOW KEYS FROM {$table} WHERE Key_name = 'PRIMARY'" );
48
+ if ( empty( $pk[0] ) ) {
49
+ $pk = $wpdb->get_results( "SHOW KEYS FROM {$table}" );
50
+ if ( empty( $pk[0] ) ) {
51
+ //fail
52
+ return;
53
+ }
54
+ }
55
+
56
+ $primary_key_column = $pk[0]->Column_name;
57
+
58
+ //Get all the Serialized Rows and Replace them properly
59
+ $rows = $wpdb->get_results( "SELECT $primary_key_column, {$column} FROM {$table} WHERE {$column} LIKE 'a:%' OR {$column} LIKE 'O:%'" );
60
+
61
+ foreach ( $rows as $row ) {
62
+ //skip the overhead of updating things that have nothing to update
63
+ if ( ! $this->has_data_to_update( $row->{$column} ) ) {
64
+ continue;
65
+ }
66
+
67
+ $clean = $this->replace_tree( @unserialize( $row->{$column} ) );
68
+ $clean = @serialize( $clean );
69
+
70
+ $wpdb->query( $wpdb->prepare( "UPDATE {$table} SET {$column}=%s WHERE {$primary_key_column}=%s", $clean, $row->{$primary_key_column} ) );
71
+
72
+ }
73
+ }
74
+
75
+
76
+ /**
77
+ * Replaces all the occurrences of a string in a multi-dimensional array or Object
78
+ *
79
+ * @uses itself to call each level of the array
80
+ *
81
+ * @param iterable|string $data to change
82
+ *
83
+ * @since 5.2.0
84
+ *
85
+ * @return mixed
86
+ *
87
+ */
88
+ public function replace_tree( $data ) {
89
+ if ( is_string( $data ) ) {
90
+ return $this->replace( $data );
91
+ }
92
+
93
+ if ( ! is_array( $data ) && ! is_object( $data ) ) {
94
+ return $data;
95
+ }
96
+
97
+ foreach ( $data as $key => $item ) {
98
+ if ( is_array( $data ) ) {
99
+ $data[ $key ] = $this->replace_tree( $item );
100
+ } else {
101
+ $data->{$key} = $this->replace_tree( $item );
102
+ }
103
+ }
104
+
105
+ return $data;
106
+ }
107
+
108
+
109
+ /**
110
+ * Replace occurrences of an old url with a new url
111
+ * within a string.
112
+ *
113
+ * Also replace occurrences of an old url formatted using
114
+ * all available updaters
115
+ *
116
+ * @param string $data
117
+ *
118
+ * @return string
119
+ */
120
+ protected function replace( $data ) {
121
+ foreach ( $this->get_updater_objects() as $_updater ) {
122
+ /** @var Go_Live_Update_Urls__Updaters__Abstract $_updater */
123
+ $data = str_replace( $_updater->apply_rule_to_url( $this->old ), $_updater->apply_rule_to_url( $this->new ), $data );
124
+ }
125
+
126
+ return trim( str_replace( $this->old, $this->new, $data ) );
127
+ }
128
+
129
+
130
+ /**
131
+ * Do we have any urls to actually update?
132
+ * Check first for serialized data,
133
+ * Then check for occurrences of any urls formatted by an updater
134
+ *
135
+ * @param string $data
136
+ *
137
+ * @return bool
138
+ */
139
+ protected function has_data_to_update( $data ) {
140
+ if ( ! is_serialized( $data ) ) {
141
+ return false;
142
+ }
143
+
144
+ if ( strpos( $data, $this->old ) !== false ) {
145
+ return true;
146
+ }
147
+
148
+ foreach ( $this->get_updater_objects() as $_updater ) {
149
+ if ( strpos( $data, $_updater->apply_rule_to_url( $this->old ) ) !== false ) {
150
+ return true;
151
+ }
152
+ }
153
+
154
+ return false;
155
+ }
156
+
157
+
158
+ /**
159
+ * Get an array of all available url updaters
160
+ *
161
+ * @todo The current updater architecture uses object with 4 arguments passed to the class
162
+ * Come up with a better architecture which gives us access to apply_url_to_url() without
163
+ * empty constructing an object.
164
+ *
165
+ * @return Go_Live_Update_Urls__Updaters__Abstract[]
166
+ */
167
+ protected function get_updater_objects() {
168
+ static $updaters;
169
+ if ( null === $updaters ) {
170
+ $updaters = (array) Go_Live_Update_Urls__Updaters__Repo::instance()->get_updaters();
171
+ foreach ( $updaters as $k => $_class ) {
172
+ $updaters[ $k ] = new $_class( null, null, null, null );
173
+ }
174
+ }
175
+
176
+ return $updaters;
177
+ }
178
+
179
+ }
src/Updaters/Abstract.php CHANGED
@@ -33,5 +33,7 @@ abstract class Go_Live_Update_Urls__Updaters__Abstract {
33
  }
34
 
35
 
 
 
36
  abstract public function update_data();
37
  }
33
  }
34
 
35
 
36
+ abstract public function apply_rule_to_url( $url );
37
+
38
  abstract public function update_data();
39
  }
src/Updaters/JSON.php CHANGED
@@ -20,15 +20,17 @@
20
  * @package Gluu\Updates
21
  */
22
  class Go_Live_Update_Urls__Updaters__JSON extends Go_Live_Update_Urls__Updaters__Abstract {
 
 
 
 
23
 
24
  public function update_data() {
25
  if ( ! strpos( $this->new, '/' ) && ! strpos( $this->old, '/' ) ) {
26
  return false;
27
  }
28
 
29
- $old = substr( wp_json_encode( $this->old ), 1, - 1 );
30
- $new = substr( wp_json_encode( $this->new ), 1, - 1 );
31
- $this->update_column( $old, $new );
32
 
33
  return true;
34
  }
20
  * @package Gluu\Updates
21
  */
22
  class Go_Live_Update_Urls__Updaters__JSON extends Go_Live_Update_Urls__Updaters__Abstract {
23
+ public function apply_rule_to_url( $url ) {
24
+ return substr( wp_json_encode( $url ), 1, - 1 );
25
+ }
26
+
27
 
28
  public function update_data() {
29
  if ( ! strpos( $this->new, '/' ) && ! strpos( $this->old, '/' ) ) {
30
  return false;
31
  }
32
 
33
+ $this->update_column( $this->apply_rule_to_url( $this->old ), $this->apply_rule_to_url( $this->new ) );
 
 
34
 
35
  return true;
36
  }
src/Updaters/Url_Encoded.php CHANGED
@@ -8,14 +8,19 @@
8
  *
9
  */
10
  class Go_Live_Update_Urls__Updaters__Url_Encoded extends Go_Live_Update_Urls__Updaters__Abstract {
 
 
 
 
 
 
11
  public function update_data() {
12
- $old = rawurlencode( $this->old );
13
  if ( $old === $this->old ) {
14
  return false;
15
  }
16
 
17
- $new = rawurlencode( $this->new );
18
- $this->update_column( $old, $new );
19
 
20
  return true;
21
  }
8
  *
9
  */
10
  class Go_Live_Update_Urls__Updaters__Url_Encoded extends Go_Live_Update_Urls__Updaters__Abstract {
11
+
12
+ public function apply_rule_to_url( $url ) {
13
+ return rawurlencode( $url );
14
+ }
15
+
16
+
17
  public function update_data() {
18
+ $old = $this->apply_rule_to_url( $this->old );
19
  if ( $old === $this->old ) {
20
  return false;
21
  }
22
 
23
+ $this->update_column( $old, $this->apply_rule_to_url( $this->new ) );
 
24
 
25
  return true;
26
  }