All-in-One WP Migration - Version 3.4

Version Description

  • Made export/import processes more reliable
  • Allow the plugin to work with non-default name
  • Preserve backups during plugin updates
  • Improved find & replace functionality on the serialized data
  • Removed backup file name restrictions
Download this release

Release Info

Developer bangelov
Plugin Icon 128x128 All-in-One WP Migration
Version 3.4
Comparing to
See all releases

Code changes from version 3.3 to 3.4

all-in-one-wp-migration.php CHANGED
@@ -5,7 +5,7 @@
5
* Description: Migration tool for all your blog data. Import or Export your blog content with a single click.
6
* Author: ServMask
7
* Author URI: https://servmask.com/
8
- * Version: 3.3
9
* Text Domain: all-in-one-wp-migration
10
* Domain Path: /languages
11
* Network: True
@@ -48,7 +48,10 @@ define( 'AI1WM_URL', plugins_url( '', __FILE__ ) );
48
define( 'AI1WM_STORAGE_URL', plugins_url( 'storage', __FILE__ ) );
49
50
// Plugin Backups Url
51
- define( 'AI1WM_BACKUPS_URL', plugins_url( 'backups', __FILE__ ) );
52
53
// include constants
54
require_once dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'constants.php';
5
* Description: Migration tool for all your blog data. Import or Export your blog content with a single click.
6
* Author: ServMask
7
* Author URI: https://servmask.com/
8
+ * Version: 3.4
9
* Text Domain: all-in-one-wp-migration
10
* Domain Path: /languages
11
* Network: True
48
define( 'AI1WM_STORAGE_URL', plugins_url( 'storage', __FILE__ ) );
49
50
// Plugin Backups Url
51
+ define( 'AI1WM_BACKUPS_URL', content_url( 'ai1wm-backups', __FILE__ ) );
52
+
53
+ // Themes Absolute Path
54
+ define( 'AI1WM_THEMES_PATH', get_theme_root() );
55
56
// include constants
57
require_once dirname( __FILE__ ) . DIRECTORY_SEPARATOR . 'constants.php';
constants.php CHANGED
@@ -38,7 +38,7 @@ if ( function_exists( 'gethostname' ) && in_array( gethostname(), $local ) ) {
38
// ==================
39
// = Plugin Version =
40
// ==================
41
- define( 'AI1WM_VERSION', '3.3' );
42
43
// ===============
44
// = Plugin Name =
@@ -63,12 +63,7 @@ define( 'AI1WM_LOG_FILE', AI1WM_STORAGE_PATH . DIRECTORY_SEPARATOR . 'error.log'
63
// ===============
64
// = Status Path =
65
// ===============
66
- define( 'AI1WM_STATUS_FILE', AI1WM_STORAGE_PATH . DIRECTORY_SEPARATOR . 'status.log' );
67
-
68
- // ================
69
- // = Backups Path =
70
- // ================
71
- define( 'AI1WM_BACKUPS_PATH', AI1WM_PATH . DIRECTORY_SEPARATOR . 'backups' );
72
73
// ============
74
// = Lib Path =
@@ -143,7 +138,7 @@ define( 'AI1WM_PACKAGE_NAME', 'package.json' );
143
// ========================
144
// = Archive Status Name =
145
// ========================
146
- define( 'AI1WM_STATUS_NAME', 'status.log' );
147
148
// ========================
149
// = Archive FileMap Name =
@@ -217,10 +212,17 @@ if ( ! defined( 'WP_CONTENT_DIR' ) ) {
217
define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' );
218
}
219
220
- // ==========================
221
- // = WP_PLUGIN_DIR Constant =
222
- // ==========================
223
- if ( ! defined( 'WP_PLUGIN_DIR' ) ) {
224
- define( 'WP_PLUGIN_DIR', WP_CONTENT_DIR . '/plugins' );
225
- }
226
38
// ==================
39
// = Plugin Version =
40
// ==================
41
+ define( 'AI1WM_VERSION', '3.4' );
42
43
// ===============
44
// = Plugin Name =
63
// ===============
64
// = Status Path =
65
// ===============
66
+ define( 'AI1WM_STATUS_FILE', AI1WM_STORAGE_PATH . DIRECTORY_SEPARATOR . 'status.html' );
67
68
// ============
69
// = Lib Path =
138
// ========================
139
// = Archive Status Name =
140
// ========================
141
+ define( 'AI1WM_STATUS_NAME', 'status.html' );
142
143
// ========================
144
// = Archive FileMap Name =
212
define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' );
213
}
214
215
+ // ================
216
+ // = Backups Path =
217
+ // ================
218
+ define( 'AI1WM_BACKUPS_PATH', WP_CONTENT_DIR . DIRECTORY_SEPARATOR . 'ai1wm-backups' );
219
+
220
+ // ======================
221
+ // = Storage Index File =
222
+ // ======================
223
+ define( 'AI1WM_STORAGE_INDEX', AI1WM_STORAGE_PATH . DIRECTORY_SEPARATOR . 'index.php' );
224
225
+ // ======================
226
+ // = Backups Index File =
227
+ // ======================
228
+ define( 'AI1WM_BACKUPS_INDEX', AI1WM_BACKUPS_PATH . DIRECTORY_SEPARATOR . 'index.php' );
lib/controller/class-ai1wm-main-controller.php CHANGED
@@ -292,7 +292,7 @@ class Ai1wm_Main_Controller {
292
}
293
294
// Create index.php in storage folder
295
- $this->create_index_file( AI1WM_STORAGE_PATH );
296
297
// Check if backups folder exist
298
if ( ! file_exists( AI1WM_BACKUPS_PATH ) ) {
@@ -308,7 +308,7 @@ class Ai1wm_Main_Controller {
308
}
309
310
// Create index.php in backups folder
311
- $this->create_index_file( AI1WM_BACKUPS_PATH );
312
}
313
314
/**
292
}
293
294
// Create index.php in storage folder
295
+ Ai1wm_File_Index::create( AI1WM_STORAGE_INDEX );
296
297
// Check if backups folder exist
298
if ( ! file_exists( AI1WM_BACKUPS_PATH ) ) {
308
}
309
310
// Create index.php in backups folder
311
+ Ai1wm_File_Index::create( AI1WM_BACKUPS_INDEX );
312
}
313
314
/**
lib/model/class-ai1wm-backup.php CHANGED
@@ -31,35 +31,23 @@ class Ai1wm_Backup {
31
* @return array
32
*/
33
public function get_files() {
34
- $backups = array();
35
36
- try {
37
- $iterator = new RegexIterator(
38
- new DirectoryIterator( AI1WM_BACKUPS_PATH ),
39
- '/^(.+)-(\d+)-(\d+)-(\d+)\.wpress#x2F;',
40
- RegexIterator::GET_MATCH
41
- );
42
-
43
- foreach ( $iterator as $item ) {
44
- try {
45
- $backup = new Ai1wm_File;
46
- $backup->setFile( $item[0] );
47
- $backup->setName( $item[1] );
48
- $backup->setSize( $iterator->getSize() );
49
- $backup->setCreatedAt( strtotime( "{$item[2]} {$item[3]}" ) );
50
51
- // Add backup file
52
- $backups[] = $backup;
53
- } catch ( Exception $e ) {
54
- // Log the error
55
- Ai1wm_Log::error( 'Exception while listing backup file: ' . $e->getMessage() );
56
- }
57
- }
58
- } catch ( Exception $e ) {
59
- $backups = array();
60
}
61
62
- // Sort backups by most recent first
63
usort( $backups, array( $this, 'compare' ) );
64
65
return $backups;
@@ -105,17 +93,17 @@ class Ai1wm_Backup {
105
}
106
107
/**
108
- * Compare backup files by created at
109
*
110
- * @param Ai1wm_File $a File object
111
- * @param Ai1wm_File $b File object
112
* @return integer
113
*/
114
public function compare( $a, $b ) {
115
- if ( $a->getCreatedAt() === $b->getCreatedAt() ) {
116
return 0;
117
}
118
119
- return ( $a->getCreatedAt() > $b->getCreatedAt() ) ? - 1 : 1;
120
}
121
}
31
* @return array
32
*/
33
public function get_files() {
34
+ $backups = array();
35
36
+ // Get backup files
37
+ $iterator = new Ai1wm_Extension_Filter(
38
+ new DirectoryIterator( AI1WM_BACKUPS_PATH ),
39
+ array( 'wpress', 'bin' )
40
+ );
41
42
+ foreach ( $iterator as $item ) {
43
+ $backups[] = array(
44
+ 'filename' => $item->getFilename(),
45
+ 'mtime' => $item->getMTime(),
46
+ 'size' => $item->getSize(),
47
+ );
48
}
49
50
+ // Sort backups modified date
51
usort( $backups, array( $this, 'compare' ) );
52
53
return $backups;
93
}
94
95
/**
96
+ * Compare backup files by modified time
97
*
98
+ * @param array $a File item A
99
+ * @param array $b File item B
100
* @return integer
101
*/
102
public function compare( $a, $b ) {
103
+ if ( $a['mtime'] === $b['mtime'] ) {
104
return 0;
105
}
106
107
+ return ( $a['mtime'] > $b['mtime'] ) ? - 1 : 1;
108
}
109
}
lib/model/class-ai1wm-export-abstract.php CHANGED
@@ -78,12 +78,20 @@ abstract class Ai1wm_Export_Abstract {
78
'message' => __( 'Retrieving a list of all WordPress files...', AI1WM_PLUGIN_NAME )
79
) );
80
81
- // Enable maintenance mode
82
- if ( $this->should_enable_maintenance() ) {
83
- Ai1wm_Maintenance::enable();
84
- }
85
86
- $filters = array( 'managewp' );
87
88
// Exclude media
89
if ( $this->should_exclude_media() ) {
@@ -106,7 +114,6 @@ abstract class Ai1wm_Export_Abstract {
106
'plugins' . DIRECTORY_SEPARATOR . 'all-in-one-wp-migration-s3-extension',
107
'plugins' . DIRECTORY_SEPARATOR . 'all-in-one-wp-migration-multisite-extension',
108
'plugins' . DIRECTORY_SEPARATOR . 'all-in-one-wp-migration-unlimited-extension',
109
- 'plugins' . DIRECTORY_SEPARATOR . 'all-in-one-wp-migration-pro-extension',
110
'plugins' . DIRECTORY_SEPARATOR . 'all-in-one-wp-migration-ftp-extension',
111
) );
112
}
@@ -399,8 +406,16 @@ abstract class Ai1wm_Export_Abstract {
399
$parsed_url = parse_url( $url, PHP_URL_HOST );
400
401
if ( false !== $parsed_url ) {
402
- $ip = gethostbyname( $parsed_url );
403
404
if ( $ip !== $parsed_url ) {
405
$url = preg_replace( sprintf( '/%s/', preg_quote( $parsed_url, '-' ) ), $ip, $url, 1 );
406
$headers['Host'] = $parsed_url;
78
'message' => __( 'Retrieving a list of all WordPress files...', AI1WM_PLUGIN_NAME )
79
) );
80
81
+ // Default filters
82
+ $filters = array(
83
+ 'ai1wm-backups',
84
+ 'managewp',
85
+ );
86
+
87
+ // Exclude index.php
88
+ $filters = array_merge( $filters, array(
89
+ 'index.php',
90
+ 'themes' . DIRECTORY_SEPARATOR . 'index.php',
91
+ 'plugins' . DIRECTORY_SEPARATOR . 'index.php',
92
+ 'uploads' . DIRECTORY_SEPARATOR . 'index.php',
93
+ ) );
94
95
96
// Exclude media
97
if ( $this->should_exclude_media() ) {
114
'plugins' . DIRECTORY_SEPARATOR . 'all-in-one-wp-migration-s3-extension',
115
'plugins' . DIRECTORY_SEPARATOR . 'all-in-one-wp-migration-multisite-extension',
116
'plugins' . DIRECTORY_SEPARATOR . 'all-in-one-wp-migration-unlimited-extension',
117
'plugins' . DIRECTORY_SEPARATOR . 'all-in-one-wp-migration-ftp-extension',
118
) );
119
}
406
$parsed_url = parse_url( $url, PHP_URL_HOST );
407
408
if ( false !== $parsed_url ) {
409
+ // Get server IP address
410
+ if ( ! empty( $_SERVER['SERVER_ADDR'] ) ) {
411
+ $ip = $_SERVER['SERVER_ADDR'];
412
+ } else if ( ! empty( $_SERVER['LOCAL_ADDR'] ) ) {
413
+ $ip = $_SERVER['LOCAL_ADDR'];
414
+ } else {
415
+ $ip = $_SERVER['SERVER_NAME'];
416
+ }
417
418
+ // Set IP address
419
if ( $ip !== $parsed_url ) {
420
$url = preg_replace( sprintf( '/%s/', preg_quote( $parsed_url, '-' ) ), $ip, $url, 1 );
421
$headers['Host'] = $parsed_url;
lib/model/class-ai1wm-export-file.php CHANGED
@@ -56,7 +56,7 @@ class Ai1wm_Export_File extends Ai1wm_Export_Abstract {
56
size_format( filesize( $this->storage()->backup() ) )
57
)
58
),
59
- $this->storage()->status() // status.log file
60
);
61
}
62
}
56
size_format( filesize( $this->storage()->backup() ) )
57
)
58
),
59
+ $this->storage()->status() // status.html file
60
);
61
}
62
}
lib/model/class-ai1wm-import-abstract.php CHANGED
@@ -327,44 +327,6 @@ abstract class Ai1wm_Import_Abstract {
327
*/
328
protected function validate() {
329
if ( is_file( $this->storage()->package() ) ) {
330
- // Set exclude filters
331
- $exclude = apply_filters( 'ai1wm_exclude_content_from_import', array(
332
- 'plugins' . DIRECTORY_SEPARATOR . 'all-in-one-wp-migration',
333
- 'plugins' . DIRECTORY_SEPARATOR . 'all-in-one-wp-migration-dropbox-extension',
334
- 'plugins' . DIRECTORY_SEPARATOR . 'all-in-one-wp-migration-gdrive-extension',
335
- 'plugins' . DIRECTORY_SEPARATOR . 'all-in-one-wp-migration-s3-extension',
336
- 'plugins' . DIRECTORY_SEPARATOR . 'all-in-one-wp-migration-multisite-extension',
337
- 'plugins' . DIRECTORY_SEPARATOR . 'all-in-one-wp-migration-unlimited-extension',
338
- 'plugins' . DIRECTORY_SEPARATOR . 'all-in-one-wp-migration-pro-extension',
339
- 'plugins' . DIRECTORY_SEPARATOR . 'all-in-one-wp-migration-ftp-extension',
340
- ) );
341
-
342
- // Iterate over WP_CONTENT_DIR directory
343
- $iterator = new RecursiveIteratorIterator(
344
- new Ai1wm_Recursive_Exclude_Filter(
345
- new Ai1wm_Recursive_Directory_Iterator(
346
- WP_CONTENT_DIR
347
- ),
348
- $exclude
349
- ),
350
- RecursiveIteratorIterator::SELF_FIRST
351
- );
352
-
353
- foreach ( $iterator as $item ) {
354
- if ( ! is_readable( $item->getPathname() ) || ! is_writable( $item->getPathname() ) ) {
355
- throw new Ai1wm_Import_Exception(
356
- sprintf(
357
- __(
358
- 'Ensure that file permissions are correctly set-up - 775 or 777 to <strong>%s</strong> ' .
359
- 'directory and all files and folders that it contains.',
360
- AI1WM_PLUGIN_NAME
361
- ),
362
- WP_CONTENT_DIR
363
- )
364
- );
365
- }
366
- }
367
-
368
return true;
369
}
370
@@ -434,8 +396,16 @@ abstract class Ai1wm_Import_Abstract {
434
$parsed_url = parse_url( $url, PHP_URL_HOST );
435
436
if ( false !== $parsed_url ) {
437
- $ip = gethostbyname( $parsed_url );
438
439
if ( $ip !== $parsed_url ) {
440
$url = preg_replace( sprintf( '/%s/', preg_quote( $parsed_url, '-' ) ), $ip, $url, 1 );
441
$headers['Host'] = $parsed_url;
327
*/
328
protected function validate() {
329
if ( is_file( $this->storage()->package() ) ) {
330
return true;
331
}
332
396
$parsed_url = parse_url( $url, PHP_URL_HOST );
397
398
if ( false !== $parsed_url ) {
399
+ // Get server IP address
400
+ if ( ! empty( $_SERVER['SERVER_ADDR'] ) ) {
401
+ $ip = $_SERVER['SERVER_ADDR'];
402
+ } else if ( ! empty( $_SERVER['LOCAL_ADDR'] ) ) {
403
+ $ip = $_SERVER['LOCAL_ADDR'];
404
+ } else {
405
+ $ip = $_SERVER['SERVER_NAME'];
406
+ }
407
408
+ // Set IP address
409
if ( $ip !== $parsed_url ) {
410
$url = preg_replace( sprintf( '/%s/', preg_quote( $parsed_url, '-' ) ), $ip, $url, 1 );
411
$headers['Host'] = $parsed_url;
lib/model/service/class-ai1wm-service-database.php CHANGED
@@ -64,7 +64,7 @@ class Ai1wm_Service_Database implements Ai1wm_Service_Interface
64
/**
65
* Import database
66
*
67
- * @return string
68
*/
69
public function import() {
70
global $wpdb;
@@ -80,24 +80,6 @@ class Ai1wm_Service_Database implements Ai1wm_Service_Interface
80
if ( isset( $config['SiteURL'] ) && ( $config['SiteURL'] !== site_url() ) ) {
81
$old_values[] = $config['SiteURL'];
82
$new_values[] = site_url();
83
-
84
- // Get Domain
85
- $old_domain = parse_url( $config['SiteURL'] );
86
- $new_domain = parse_url( site_url() );
87
-
88
- // Replace Domain
89
- $old_values[] = sprintf( '%s://%s', $old_domain['scheme'], $old_domain['host'] );
90
- $new_values[] = sprintf( '%s://%s', $new_domain['scheme'], $new_domain['host'] );
91
-
92
- // Replace Host
93
- if ( stripos( site_url(), $old_domain['host'] ) === false && stripos( home_url(), $old_domain['host'] ) === false ) {
94
- $old_values[] = $old_domain['host'];
95
- $new_values[] = $new_domain['host'];
96
- }
97
-
98
- // Replace Path
99
- $old_values[] = isset( $old_domain['path'] ) && ( $old_domain['path'] !== '/' ) ? trailingslashit( $old_domain['path'] ) : null;
100
- $new_values[] = isset( $new_domain['path'] ) ? trailingslashit( $new_domain['path'] ) : '/';
101
}
102
103
// Get Home URL
@@ -159,6 +141,41 @@ class Ai1wm_Service_Database implements Ai1wm_Service_Interface
159
// Clear WP options cache
160
wp_cache_flush();
161
162
// Set new user identity
163
if ( isset( $config['Export']['User']['Id'] ) && ( $id = $config['Export']['User']['Id'] ) ) {
164
@@ -201,23 +218,11 @@ class Ai1wm_Service_Database implements Ai1wm_Service_Interface
201
/**
202
* Export database
203
*
204
- * @return string
205
*/
206
public function export() {
207
global $wpdb;
208
209
- // Set include tables
210
- $include_tables = array();
211
- if ( isset( $this->args['options']['include-tables'] ) ) {
212
- $include_tables = $this->args['options']['include-tables'];
213
- }
214
-
215
- // Set exclude tables
216
- $exclude_tables = array();
217
- if ( isset( $this->args['options']['exclude-tables' ] ) ) {
218
- $exclude_tables = $this->args['options']['exclude-tables'];
219
- }
220
-
221
$clauses = array();
222
223
// Spam comments
@@ -234,20 +239,12 @@ class Ai1wm_Service_Database implements Ai1wm_Service_Interface
234
$clauses[ $wpdb->posts ] = " WHERE post_type != 'revision' ";
235
}
236
237
- // No table data, but leave Admin account
238
- $no_table_data = isset( $this->args['options']['no-table-data'] );
239
- if ( $no_table_data ) {
240
- $clauses = array();
241
- $clauses[ $wpdb->users ] = ' WHERE id = 1 ';
242
- $clauses[ $wpdb->usermeta ] = ' WHERE user_id = 1 ';
243
- }
244
-
245
// Find and replace
246
$old_values = array();
247
$new_values = array();
248
if ( isset( $this->args['options']['replace'] ) && ( $replace = $this->args['options']['replace'] ) ) {
249
for ( $i = 0; $i < count( $replace['old-value'] ); $i++ ) {
250
- if ( isset( $replace['old-value'][$i] ) && isset( $replace['new-value'][$i] ) ) {
251
$old_values[] = $replace['old-value'][$i];
252
$new_values[] = $replace['new-value'][$i];
253
}
@@ -256,15 +253,13 @@ class Ai1wm_Service_Database implements Ai1wm_Service_Interface
256
257
// Set dump options
258
$this->connection->setFileName( $this->storage()->database() )
259
- ->setIncludeTables( $include_tables )
260
- ->setExcludeTables( $exclude_tables )
261
- ->setNoTableData( $no_table_data )
262
->setOldTablePrefix( $wpdb->prefix )
263
->setNewTablePrefix( AI1WM_TABLE_PREFIX )
264
->setOldReplaceValues( $old_values )
265
->setNewReplaceValues( $new_values )
266
->setQueryClauses( $clauses )
267
- ->setIgnoreTableReplaces( array( $wpdb->postmeta => array() ) );
268
269
// Export database
270
$this->connection->export();
64
/**
65
* Import database
66
*
67
+ * @return void
68
*/
69
public function import() {
70
global $wpdb;
80
if ( isset( $config['SiteURL'] ) && ( $config['SiteURL'] !== site_url() ) ) {
81
$old_values[] = $config['SiteURL'];
82
$new_values[] = site_url();
83
}
84
85
// Get Home URL
141
// Clear WP options cache
142
wp_cache_flush();
143
144
+ // WP Migration
145
+ if ( is_plugin_active( AI1WM_PLUGIN_BASENAME ) ) {
146
+ activate_plugin( AI1WM_PLUGIN_BASENAME );
147
+ }
148
+
149
+ // Dropbox Extension
150
+ if ( is_plugin_active( AI1WMDE_PLUGIN_BASENAME ) ) {
151
+ activate_plugin( AI1WMDE_PLUGIN_BASENAME );
152
+ }
153
+
154
+ // Google Drive Extension
155
+ if ( is_plugin_active( AI1WMGE_PLUGIN_BASENAME ) ) {
156
+ activate_plugin( AI1WMGE_PLUGIN_BASENAME );
157
+ }
158
+
159
+ // Amazon S3 Extension
160
+ if ( is_plugin_active( AI1WMSE_PLUGIN_BASENAME ) ) {
161
+ activate_plugin( AI1WMSE_PLUGIN_BASENAME );
162
+ }
163
+
164
+ // Multisite Extension
165
+ if ( is_plugin_active( AI1WMME_PLUGIN_BASENAME ) ) {
166
+ activate_plugin( AI1WMME_PLUGIN_BASENAME );
167
+ }
168
+
169
+ // Unlimited Extension
170
+ if ( is_plugin_active( AI1WMUE_PLUGIN_BASENAME ) ) {
171
+ activate_plugin( AI1WMUE_PLUGIN_BASENAME );
172
+ }
173
+
174
+ // FTP Extension
175
+ if ( is_plugin_active( AI1WMFE_PLUGIN_BASENAME ) ) {
176
+ activate_plugin( AI1WMFE_PLUGIN_BASENAME );
177
+ }
178
+
179
// Set new user identity
180
if ( isset( $config['Export']['User']['Id'] ) && ( $id = $config['Export']['User']['Id'] ) ) {
181
218
/**
219
* Export database
220
*
221
+ * @return void
222
*/
223
public function export() {
224
global $wpdb;
225
226
$clauses = array();
227
228
// Spam comments
239
$clauses[ $wpdb->posts ] = " WHERE post_type != 'revision' ";
240
}
241
242
// Find and replace
243
$old_values = array();
244
$new_values = array();
245
if ( isset( $this->args['options']['replace'] ) && ( $replace = $this->args['options']['replace'] ) ) {
246
for ( $i = 0; $i < count( $replace['old-value'] ); $i++ ) {
247
+ if ( ! empty( $replace['old-value'][$i] ) && ! empty( $replace['new-value'][$i] ) ) {
248
$old_values[] = $replace['old-value'][$i];
249
$new_values[] = $replace['new-value'][$i];
250
}
253
254
// Set dump options
255
$this->connection->setFileName( $this->storage()->database() )
256
->setOldTablePrefix( $wpdb->prefix )
257
->setNewTablePrefix( AI1WM_TABLE_PREFIX )
258
->setOldReplaceValues( $old_values )
259
->setNewReplaceValues( $new_values )
260
->setQueryClauses( $clauses )
261
+ ->setTablePrefixColumns( $wpdb->options, array( 'option_name' ) )
262
+ ->setTablePrefixColumns( $wpdb->usermeta, array( 'meta_key' ) );
263
264
// Export database
265
$this->connection->export();
lib/vendor/mysqldump-factory/mysqldump-factory/lib/MysqlDumpInterface.php CHANGED
@@ -114,7 +114,7 @@ interface MysqlDumpInterface
114
* Set old replace values
115
*
116
* @param array $values List of values
117
- * @return MysqlDumpPDO
118
*/
119
public function setOldReplaceValues($values);
120
@@ -129,7 +129,7 @@ interface MysqlDumpInterface
129
* Set new replace values
130
*
131
* @param array $values List of values
132
- * @return MysqlDumpPDO
133
*/
134
public function setNewReplaceValues($values);
135
@@ -156,79 +156,35 @@ interface MysqlDumpInterface
156
public function getQueryClauses();
157
158
/**
159
- * Set ignore table replaces
160
*
161
- * @param array $tables List of SQL tables
162
* @return MysqlDumpInterface
163
*/
164
- public function setIgnoreTableReplaces($tables);
165
166
/**
167
- * Get ignore table replaces
168
*
169
* @return array
170
*/
171
- public function getIgnoreTableReplaces();
172
-
173
- /**
174
- * Set include tables
175
- *
176
- * @param array $tables List of tables
177
- * @return MysqlDumpInterface
178
- */
179
- public function setIncludeTables($tables);
180
181
/**
182
- * Get include tables
183
*
184
- * @return array
185
- */
186
- public function getIncludeTables();
187
-
188
- /**
189
- * Set exclude tables
190
- *
191
- * @param array $tables List of tables
192
- * @return MysqlDumpInterface
193
- */
194
- public function setExcludeTables($tables);
195
-
196
- /**
197
- * Get exclude tables
198
- *
199
- * @return array
200
- */
201
- public function getExcludeTables();
202
-
203
- /**
204
- * Set no table data flag
205
- *
206
- * @param bool $flag Do not export table data
207
- * @return MysqlDumpInterface
208
- */
209
- public function setNoTableData($flag);
210
-
211
- /**
212
- * Get no table data flag
213
- *
214
- * @return bool
215
- */
216
- public function getNoTableData();
217
-
218
- /**
219
- * Set add drop table flag
220
- *
221
- * @param bool $flag Add drop table SQL clause
222
- * @return MysqlDumpInterface
223
*/
224
- public function setAddDropTable($flag);
225
226
/**
227
- * Get add drop table flag
228
*
229
- * @return bool
230
*/
231
- public function getAddDropTable();
232
233
/**
234
* Get MySQL collation name
@@ -261,36 +217,23 @@ interface MysqlDumpInterface
261
public function listTables();
262
263
/**
264
- * Replace table values
265
*
266
* @param string $input Table value
267
* @return string
268
*/
269
- public function replaceTableValues($input);
270
-
271
- /**
272
- * Replace table name prefix
273
- *
274
- * @param string $input Table name
275
- * @return string
276
- */
277
- public function replaceTableNamePrefix($input);
278
-
279
- /**
280
- * Replace create table prefix
281
- *
282
- * @param string $input SQL statement
283
- * @return string
284
- */
285
- public function replaceCreateTablePrefix($input);
286
287
/**
288
- * Replace insert into prefix
289
*
290
- * @param string $input SQL statement
291
* @return string
292
*/
293
- public function replaceInsertIntoPrefix($input);
294
295
/**
296
* Replace table collation
114
* Set old replace values
115
*
116
* @param array $values List of values
117
+ * @return MysqlDumpInterface
118
*/
119
public function setOldReplaceValues($values);
120
129
* Set new replace values
130
*
131
* @param array $values List of values
132
+ * @return MysqlDumpInterface
133
*/
134
public function setNewReplaceValues($values);
135
156
public function getQueryClauses();
157
158
/**
159
+ * Set table prefix columns
160
*
161
+ * @param string $table Table name
162
+ * @param array $columns Table columns
163
* @return MysqlDumpInterface
164
*/
165
+ public function setTablePrefixColumns($table, $columns);
166
167
/**
168
+ * Get table prefix columns
169
*
170
+ * @param string $table Table name
171
* @return array
172
*/
173
+ public function getTablePrefixColumns($table);
174
175
/**
176
+ * Get MySQL version
177
*
178
+ * @return string
179
*/
180
+ public function getVersion();
181
182
/**
183
+ * Get MySQL max allowed packaet
184
*
185
+ * @return integer
186
*/
187
+ public function getMaxAllowedPacket();
188
189
/**
190
* Get MySQL collation name
217
public function listTables();
218
219
/**
220
+ * Replace table prefix
221
*
222
* @param string $input Table value
223
+ * @param boolean $first Replace first occurrence
224
+ * @param boolean $start Replace start occurrence
225
* @return string
226
*/
227
+ public function replaceTablePrefix($input, $first = false, $start = false);
228
229
/**
230
+ * Replace table values
231
*
232
+ * @param string $input Table value
233
+ * @param boolean $parse Parse value
234
* @return string
235
*/
236
+ public function replaceTableValues($input, $parse = false);
237
238
/**
239
* Replace table collation
lib/vendor/mysqldump-factory/mysqldump-factory/lib/MysqlDumpPDO.php CHANGED
@@ -34,7 +34,6 @@
34
*/
35
36
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'MysqlDumpInterface.php';
37
- require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'MysqlQueryAdapter.php';
38
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'MysqlFileAdapter.php';
39
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'MysqlUtility.php';
40
@@ -52,45 +51,35 @@ require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'MysqlUtility.php';
52
*/
53
class MysqlDumpPDO implements MysqlDumpInterface
54
{
55
- protected $hostname = null;
56
57
- protected $port = null;
58
59
- protected $socket = null;
60
61
- protected $username = null;
62
63
- protected $password = null;
64
65
- protected $database = null;
66
67
- protected $fileName = 'database.sql';
68
69
- protected $fileAdapter = null;
70
71
- protected $queryAdapter = null;
72
73
- protected $connection = null;
74
75
- protected $oldTablePrefix = null;
76
77
- protected $newTablePrefix = null;
78
79
- protected $oldReplaceValues = array();
80
81
- protected $newReplaceValues = array();
82
83
- protected $queryClauses = array();
84
-
85
- protected $ignoreTableReplaces = array();
86
-
87
- protected $includeTables = array();
88
-
89
- protected $excludeTables = array();
90
-
91
- protected $noTableData = false;
92
-
93
- protected $addDropTable = false;
94
95
/**
96
* Define MySQL credentials for the current connection
@@ -112,9 +101,6 @@ class MysqlDumpPDO implements MysqlDumpInterface
112
$this->username = $username;
113
$this->password = $password;
114
$this->database = $database;
115
-
116
- // Set Query Adapter
117
- $this->queryAdapter = new MysqlQueryAdapter('mysql');
118
}
119
120
/**
@@ -134,21 +120,12 @@ class MysqlDumpPDO implements MysqlDumpInterface
134
$this->fileAdapter->write($this->getHeader());
135
136
// Listing all tables from database
137
- $tables = array();
138
- foreach ($this->listTables() as $table) {
139
- if (count($this->getIncludeTables()) === 0 || in_array($table, $this->getIncludeTables())) {
140
- $tables[] = $table;
141
- }
142
- }
143
144
// Export Tables
145
foreach ($tables as $table) {
146
- if (in_array($table, $this->getExcludeTables())) {
147
- continue;
148
- }
149
-
150
$isTable = $this->getTableStructure($table);
151
- if (true === $isTable) {
152
$this->listValues($table);
153
}
154
}
@@ -296,118 +273,80 @@ class MysqlDumpPDO implements MysqlDumpInterface
296
}
297
298
/**
299
- * Set ignore table replaces
300
*
301
- * @param array $tables List of SQL tables
302
* @return MysqlDumpPDO
303
*/
304
- public function setIgnoreTableReplaces($tables)
305
{
306
- $this->ignoreTableReplaces = $tables;
307
-
308
- return $this;
309
- }
310
-
311
- /**
312
- * Get ignore table replaces
313
- *
314
- * @return array
315
- */
316
- public function getIgnoreTableReplaces()
317
- {
318
- return $this->ignoreTableReplaces;
319
- }
320
-
321
- /**
322
- * Set include tables
323
- *
324
- * @param array $tables List of tables
325
- * @return MysqlDumpPDO
326
- */
327
- public function setIncludeTables($tables)
328
- {
329
- $this->includeTables = $tables;
330
-
331
- return $this;
332
- }
333
-
334
- /**
335
- * Get include tables
336
- *
337
- * @return array
338
- */
339
- public function getIncludeTables()
340
- {
341
- return $this->includeTables;
342
- }
343
-
344
- /**
345
- * Set exclude tables
346
- *
347
- * @param array $tables List of tables
348
- * @return MysqlDumpPDO
349
- */
350
- public function setExcludeTables($tables)
351
- {
352
- $this->excludeTables = $tables;
353
354
return $this;
355
}
356
357
/**
358
- * Get exclude tables
359
*
360
* @return array
361
*/
362
- public function getExcludeTables()
363
- {
364
- return $this->excludeTables;
365
- }
366
-
367
- /**
368
- * Set no table data flag
369
- *
370
- * @param bool $flag Do not export table data
371
- * @return MysqlDumpPDO
372
- */
373
- public function setNoTableData($flag)
374
{
375
- $this->noTableData = (bool) $flag;
376
-
377
- return $this;
378
- }
379
380
- /**
381
- * Get no table data flag
382
- *
383
- * @return bool
384
- */
385
- public function getNoTableData()
386
- {
387
- return $this->noTableData;
388
}
389
390
/**
391
- * Set add drop table flag
392
*
393
- * @param bool $flag Add drop table SQL clause
394
- * @return MysqlDumpPDO
395
*/
396
- public function setAddDropTable($flag)
397
- {
398
- $this->addDropTable = (bool) $flag;
399
-
400
- return $this;
401
}
402
403
/**
404
- * Get add drop table flag
405
*
406
- * @return bool
407
*/
408
- public function getAddDropTable()
409
- {
410
- return $this->addDropTable;
411
}
412
413
/**
@@ -443,14 +382,14 @@ class MysqlDumpPDO implements MysqlDumpInterface
443
*/
444
public function flush()
445
{
446
- $deleteTables = array();
447
- foreach ($this->listTables() as $table) {
448
- $deleteTables[] = $this->queryAdapter->drop_table($table);
449
}
450
451
// Drop tables
452
- foreach ($deleteTables as $delete) {
453
- $this->getConnection()->query($delete);
454
}
455
}
456
@@ -463,37 +402,53 @@ class MysqlDumpPDO implements MysqlDumpInterface
463
public function import($fileName)
464
{
465
// Set collation name
466
- $collation = $this->getCollation('utf8mb4_unicode_ci');
467
468
$fileHandler = fopen($fileName, 'r');
469
- if ($fileHandler) {
470
- $query = null;
471
472
- // Read database file line by line
473
- while (($line = fgets($fileHandler)) !== false) {
474
- // Replace create table prefix
475
- $line = $this->replaceCreateTablePrefix($line);
476
477
- // Replace insert into prefix
478
- $line = $this->replaceInsertIntoPrefix($line);
479
480
- // Replace table values
481
- $line = $this->replaceTableValues($line);
482
483
- // Replace table collation
484
- if (empty($collation)) {
485
- $line = $this->replaceTableCollation($line);
486
- }
487
488
- $query .= $line;
489
- if (preg_match('/;\s*#x2F;', $line)) {
490
try {
491
// Run SQL query
492
$result = $this->getConnection()->query($query);
493
if ($result === false) {
494
throw new PDOException(var_export($this->getConnection()->errorinfo(), true));
495
}
496
} catch (PDOException $e) {
497
// Log the error
498
Ai1wm_Log::error(
499
sprintf(
@@ -504,13 +459,23 @@ class MysqlDumpPDO implements MysqlDumpInterface
504
);
505
}
506
507
- // Empty query
508
- $query = null;
509
}
510
}
511
512
- return true;
513
}
514
}
515
516
/**
@@ -523,16 +488,16 @@ class MysqlDumpPDO implements MysqlDumpInterface
523
$tables = array();
524
525
try {
526
- $query = $this->queryAdapter->show_tables_information_schema($this->database);
527
- $result = $this->getConnection()->query($query);
528
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
529
- if (isset($row['table_name'])) {
530
- $tables[] = $row['table_name'];
531
}
532
}
533
} catch (Exception $e) {
534
- $query = $this->queryAdapter->show_tables($this->database);
535
- $result = $this->getConnection()->query($query);
536
while ($row = $result->fetch(PDO::FETCH_NUM)) {
537
if (isset($row[0])) {
538
$tables[] = $row[0];
@@ -544,81 +509,113 @@ class MysqlDumpPDO implements MysqlDumpInterface
544
}
545
546
/**
547
- * Replace table values
548
*
549
* @param string $input Table value
550
* @return string
551
*/
552
- public function replaceTableValues($input)
553
{
554
$old = $this->getOldReplaceValues();
555
$new = $this->getNewReplaceValues();
556
557
$oldValues = array();
558
$newValues = array();
559
560
- // Replace strings
561
for ($i = 0; $i < count($old); $i++) {
562
- if (!empty($old[$i]) && ($old[$i] != $new[$i]) && !in_array($old[$i], $oldValues)) {
563
$oldValues[] = $old[$i];
564
$newValues[] = $new[$i];
565
}
566
}
567
568
- // Replace table prefix
569
- $oldValues[] = $this->getOldTablePrefix();
570
- $newValues[] = $this->getNewTablePrefix();
571
-
572
- // Replace table values
573
- $input = str_replace($oldValues, $newValues, $input);
574
575
- // Verify serialization
576
- return MysqlUtility::pregReplace(
577
- $input,
578
- '/s:(\d+):([\\\\]?"[\\\\]?"|[\\\\]?"((.*?)[^\\\\])[\\\\]?");/'
579
- );
580
- }
581
582
- /**
583
- * Replace table name prefix
584
- *
585
- * @param string $input Table name
586
- * @return string
587
- */
588
- public function replaceTableNamePrefix($input)
589
- {
590
- $pattern = '/^(' . preg_quote($this->getOldTablePrefix(), '/') . ')(.+)/i';
591
- $replace = $this->getNewTablePrefix() . '\2';
592
593
- return preg_replace($pattern, $replace, $input);
594
}
595
596
/**
597
- * Replace create table prefix
598
*
599
- * @param string $input SQL statement
600
* @return string
601
*/
602
- public function replaceCreateTablePrefix($input)
603
{
604
- $pattern = '/^CREATE TABLE `(' . preg_quote($this->getOldTablePrefix(), '/') . ')(.+)`/Ui';
605
- $replace = 'CREATE TABLE `' . $this->getNewTablePrefix() . '\2`';
606
607
- return preg_replace($pattern, $replace, $input);
608
}
609
610
/**
611
- * Replace insert into prefix
612
*
613
- * @param string $input SQL statement
614
* @return string
615
*/
616
- public function replaceInsertIntoPrefix($input)
617
{
618
- $pattern = '/^INSERT INTO `(' . preg_quote($this->getOldTablePrefix(), '/') . ')(.+)`/Ui';
619
- $replace = 'INSERT INTO `' . $this->getNewTablePrefix() . '\2`';
620
621
- return preg_replace($pattern, $replace, $input);
622
}
623
624
/**
@@ -629,10 +626,7 @@ class MysqlDumpPDO implements MysqlDumpInterface
629
*/
630
public function replaceTableCollation($input)
631
{
632
- $pattern = array('utf8mb4_unicode_ci', 'utf8mb4');
633
- $replace = array('utf8_general_ci', 'utf8');
634
-
635
- return str_replace($pattern, $replace, $input);
636
}
637
638
/**
@@ -712,12 +706,10 @@ class MysqlDumpPDO implements MysqlDumpInterface
712
$connection->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
713
714
// Set default encoding
715
- $query = $this->queryAdapter->set_names('utf8');
716
- $connection->exec($query);
717
718
// Set foreign key
719
- $query = $this->queryAdapter->set_foreign_key(0);
720
- $connection->exec($query);
721
722
return $connection;
723
}
@@ -750,34 +742,27 @@ class MysqlDumpPDO implements MysqlDumpInterface
750
*/
751
protected function getTableStructure($tableName)
752
{
753
- $query = $this->queryAdapter->show_create_table($tableName);
754
- $result = $this->getConnection()->query($query);
755
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
756
if (isset($row['Create Table'])) {
757
- // Replace table name prefix
758
- $tableName = $this->replaceTableNamePrefix($tableName);
759
-
760
- $this->fileAdapter->write("-- " .
761
- "--------------------------------------------------------" .
762
- "\n\n" .
763
- "--\n" .
764
- "-- Table structure for table `$tableName`\n--\n\n");
765
-
766
- if ($this->getAddDropTable()) {
767
- $this->fileAdapter->write("DROP TABLE IF EXISTS `$tableName`;\n\n");
768
- }
769
770
- // Replace create table prefix
771
- $createTable = $this->replaceCreateTablePrefix($row['Create Table']);
772
773
// Strip table constraints
774
$createTable = $this->stripTableConstraints($createTable);
775
776
- $this->fileAdapter->write($createTable . ";\n\n");
777
778
return true;
779
}
780
}
781
}
782
783
/**
@@ -797,72 +782,40 @@ class MysqlDumpPDO implements MysqlDumpInterface
797
$query .= $queryClause;
798
}
799
800
- // No table data
801
- if ($this->getNoTableData() && !isset($clauses[$tableName])) {
802
- return;
803
- }
804
805
// Get results
806
$result = $this->getConnection()->query($query);
807
808
- // Get ignore table replaces
809
- $ignoreTableReplaces = $this->getIgnoreTableReplaces();
810
811
// Generate insert statements
812
- if (isset($ignoreTableReplaces[$tableName])) {
813
-
814
- // Replace table name prefix
815
- $tableName = $this->replaceTableNamePrefix($tableName);
816
-
817
- $this->fileAdapter->write(
818
- "--\n" .
819
- "-- Dumping data for table `$tableName`\n" .
820
- "--\n\n"
821
- );
822
-
823
- while ($row = $result->fetch(PDO::FETCH_NUM)) {
824
- $items = array();
825
- foreach ($row as $value) {
826
- $items[] = is_null($value) ? 'NULL' : $this->getConnection()->quote($value);
827
}
828
829
- // Set table values
830
- $tableValues = implode(',', $items);
831
-
832
- // Write insert statements
833
- $this->fileAdapter->write("INSERT INTO `$tableName` VALUES ($tableValues);\n");
834
}
835
836
- // Close result cursor
837
- $result->closeCursor();
838
-
839
- } else {
840
-
841
- // Replace table name prefix
842
- $tableName = $this->replaceTableNamePrefix($tableName);
843
-
844
- $this->fileAdapter->write(
845
- "--\n" .
846
- "-- Dumping data for table `$tableName`\n" .
847
- "--\n\n"
848
- );
849
-
850
- while ($row = $result->fetch(PDO::FETCH_NUM)) {
851
- $items = array();
852
- foreach ($row as $value) {
853
- $items[] = is_null($value) ? 'NULL' : $this->getConnection()->quote($this->replaceTableValues($value));
854
- }
855
856
- // Set table values
857
- $tableValues = implode(',', $items);
858
859
- // Write insert statements
860
- $this->fileAdapter->write("INSERT INTO `$tableName` VALUES ($tableValues);\n");
861
- }
862
863
- // Close result cursor
864
- $result->closeCursor();
865
- }
866
}
867
868
/**
34
*/
35
36
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'MysqlDumpInterface.php';
37
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'MysqlFileAdapter.php';
38
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'MysqlUtility.php';
39
51
*/
52
class MysqlDumpPDO implements MysqlDumpInterface
53
{
54
+ protected $hostname = null;
55
56
+ protected $port = null;
57
58
+ protected $socket = null;
59
60
+ protected $username = null;
61
62
+ protected $password = null;
63
64
+ protected $database = null;
65
66
+ protected $fileName = 'database.sql';
67
68
+ protected $fileAdapter = null;
69
70
+ protected $connection = null;
71
72
+ protected $oldTablePrefix = null;
73
74
+ protected $newTablePrefix = null;
75
76
+ protected $oldReplaceValues = array();
77
78
+ protected $newReplaceValues = array();
79
80
+ protected $queryClauses = array();
81
82
+ protected $tablePrefixColumns = array();
83
84
/**
85
* Define MySQL credentials for the current connection
101
$this->username = $username;
102
$this->password = $password;
103
$this->database = $database;
104
}
105
106
/**
120
$this->fileAdapter->write($this->getHeader());
121
122
// Listing all tables from database
123
+ $tables = $this->listTables();
124
125
// Export Tables
126
foreach ($tables as $table) {
127
$isTable = $this->getTableStructure($table);
128
+ if ($isTable) {
129
$this->listValues($table);
130
}
131
}
273
}
274
275
/**
276
+ * Set table prefix columns
277
*
278
+ * @param string $table Table name
279
+ * @param array $columns Table columns
280
* @return MysqlDumpPDO
281
*/
282
+ public function setTablePrefixColumns($table, $columns)
283
{
284
+ foreach ($columns as $column) {
285
+ $this->tablePrefixColumns[$table][$column] = true;
286
+ }
287
288
return $this;
289
}
290
291
/**
292
+ * Get table prefix columns
293
*
294
+ * @param string $table Table name
295
* @return array
296
*/
297
+ public function getTablePrefixColumns($table)
298
{
299
+ if (isset($this->tablePrefixColumns[$table])) {
300
+ return $this->tablePrefixColumns[$table];
301
+ }
302
303
+ return array();
304
}
305
306
/**
307
+ * Get MySQL version
308
*
309
+ * @return string
310
*/
311
+ public function getVersion() {
312
+ try {
313
+ $result = $this->getConnection()->query("SELECT @@version AS VersionName");
314
+ while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
315
+ if (isset($row['VersionName'])) {
316
+ return $row['VersionName'];
317
+ }
318
+ }
319
+ } catch (Exception $e) {
320
+ $result = $this->getConnection()->query("SHOW VARIABLES LIKE 'version'");
321
+ while ($row = $result->fetch(PDO::FETCH_NUM)) {
322
+ if (isset($row[1])) {
323
+ return $row[1];
324
+ }
325
+ }
326
+ }
327
}
328
329
/**
330
+ * Get MySQL max allowed packaet
331
*
332
+ * @return integer
333
*/
334
+ public function getMaxAllowedPacket() {
335
+ try {
336
+ $result = $this->getConnection()->query("SELECT @@max_allowed_packet AS MaxAllowedPacket");
337
+ while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
338
+ if (isset($row['MaxAllowedPacket'])) {
339
+ return $row['MaxAllowedPacket'];
340
+ }
341
+ }
342
+ } catch (Exception $e) {
343
+ $result = $this->getConnection()->query("SHOW VARIABLES LIKE 'max_allowed_packet'");
344
+ while ($row = $result->fetch(PDO::FETCH_NUM)) {
345
+ if (isset($row[1])) {
346
+ return $row[1];
347
+ }
348
+ }
349
+ }
350
}
351
352
/**
382
*/
383
public function flush()
384
{
385
+ $dropTables = array();
386
+ foreach ($this->listTables() as $tableName) {
387
+ $dropTables[] = "DROP TABLE IF EXISTS `$tableName`";
388
}
389
390
// Drop tables
391
+ foreach ($dropTables as $dropQuery) {
392
+ $this->getConnection()->query($dropQuery);
393
}
394
}
395
402
public function import($fileName)
403
{
404
// Set collation name
405
+ $collation = $this->getCollation('utf8mb4_general_ci');
406
+
407
+ // Set max allowed packet
408
+ $maxAllowedPacket = $this->getMaxAllowedPacket();
409
410
+ // Set file handler
411
$fileHandler = fopen($fileName, 'r');
412
+ if ($fileHandler === false) {
413
+ throw new Exception('Unable to open database file');
414
+ }
415
416
+ $passed = 0;
417
+ $failed = 0;
418
+ $query = null;
419
420
+ // Read database file line by line
421
+ while (($line = fgets($fileHandler)) !== false) {
422
+ $query .= $line;
423
424
+ // End of query
425
+ if (preg_match('/;\s*#x2F;', $query)) {
426
427
+ // Check max allowed packet
428
+ if (strlen($query) <= $maxAllowedPacket) {
429
+
430
+ // Replace table prefix
431
+ $query = $this->replaceTablePrefix($query);
432
+
433
+ // Replace table values
434
+ $query = $this->replaceTableValues($query, true);
435
+
436
+ // Replace table collation
437
+ if (empty($collation)) {
438
+ $query = $this->replaceTableCollation($query);
439
+ }
440
441
try {
442
// Run SQL query
443
$result = $this->getConnection()->query($query);
444
if ($result === false) {
445
throw new PDOException(var_export($this->getConnection()->errorinfo(), true));
446
+ } else {
447
+ $passed++;
448
}
449
} catch (PDOException $e) {
450
+ $failed++;
451
+
452
// Log the error
453
Ai1wm_Log::error(
454
sprintf(
459
);
460
}
461
462
+ } else {
463
+ $failed++;
464
}
465
+
466
+ $query = null;
467
}
468
+ }
469
+
470
+ // Close file handler
471
+ fclose($fileHandler);
472
473
+ // Check failed queries
474
+ if ((($failed / $passed) * 100) > 2) {
475
+ return false;
476
}
477
+
478
+ return true;
479
}
480
481
/**
488
$tables = array();
489
490
try {
491
+ $result = $this->getConnection()->query(
492
+ "SELECT TABLE_NAME AS TableName FROM `INFORMATION_SCHEMA`.`TABLES` WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA = '{$this->database}'"
493
+ );
494
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
495
+ if (isset($row['TableName'])) {
496
+ $tables[] = $row['TableName'];
497
}
498
}
499
} catch (Exception $e) {
500
+ $result = $this->getConnection()->query("SHOW TABLES FROM `{$this->database}`");
501
while ($row = $result->fetch(PDO::FETCH_NUM)) {
502
if (isset($row[0])) {
503
$tables[] = $row[0];
509
}
510
511
/**
512
+ * Replace table prefix
513
*
514
* @param string $input Table value
515
+ * @param boolean $first Replace first occurrence
516
+ * @param boolean $start Replace start occurrence
517
* @return string
518
*/
519
+ public function replaceTablePrefix($input, $first = false, $start = false)
520
{
521
+ // Get table prefix
522
+ $search = $this->getOldTablePrefix();
523
+ $replace = $this->getNewTablePrefix();
524
+
525
+ // Replace first occurrence
526
+ if ($first) {
527
+ $pos = strpos($input, $search);
528
+ if ($pos !== false) {
529
+ return substr_replace($input, $replace, $pos, strlen($search));
530
+ }
531
+
532
+ return $input;
533
+ } else if ($start) {
534
+ $pos = strpos($input, $search);
535
+ if ($pos === 0) {
536
+ return substr_replace($input, $replace, $pos, strlen($search));
537
+ }
538
+
539
+ return $input;
540
+ }
541
+
542
+ // Replace all occurrences
543
+ return str_replace($search, $replace, $input);
544
+ }
545
+
546
+ /**
547
+ * Replace table values
548
+ *
549
+ * @param string $input Table value
550
+ * @param boolean $parse Parse value
551
+ * @return string
552
+ */
553
+ public function replaceTableValues($input, $parse = false)
554
+ {
555
+ // Get replace values
556
$old = $this->getOldReplaceValues();
557
$new = $this->getNewReplaceValues();
558
559
$oldValues = array();
560
$newValues = array();
561
562
+ // Prepare replace values
563
for ($i = 0; $i < count($old); $i++) {
564
+ if (strpos($input, $old[$i]) !== false) {
565
$oldValues[] = $old[$i];
566
$newValues[] = $new[$i];
567
}
568
}
569
570
+ // Do replace values
571
+ if ($oldValues) {
572
+ if ($parse) {
573
+ // Parse and replace serialized values
574
+ $input = $this->parseSerializedValues($input);
575
576
+ // Replace values
577
+ return MysqlUtility::replaceValues($oldValues, $newValues, $input);
578
+ }
579
580
+ return MysqlUtility::replaceSerializedValues($oldValues, $newValues, $input);
581
+ }
582
583
+ return $input;
584
}
585
586
/**
587
+ * Parse serialized values
588
*
589
+ * @param string $input Table value
590
* @return string
591
*/
592
+ public function parseSerializedValues($input)
593
{
594
+ // Serialization format
595
+ $array = '(a:\d+:{.*?})';
596
+ $string = '(s:\d+:".*?")';
597
+ $object = '(O:\d+:".+":\d+:{.*})';
598
599
+ // Replace serialized values
600
+ return preg_replace_callback("/'($array|$string|$object)'/", array($this, 'replaceSerializedValues'), $input);
601
}
602
603
/**
604
+ * Replace serialized values (callback)
605
*
606
+ * @param array $matches List of matches
607
* @return string
608
*/
609
+ public function replaceSerializedValues($matches)
610
{
611
+ // Unescape MySQL special characters
612
+ $input = MysqlUtility::unescapeMysql($matches[1]);
613
614
+ // Replace serialized values
615
+ $input = MysqlUtility::replaceSerializedValues($this->getOldReplaceValues(), $this->getNewReplaceValues(), $input);
616
+
617
+ // Prepare query values
618
+ return $this->getConnection()->quote($input);
619
}
620
621
/**
626
*/
627
public function replaceTableCollation($input)
628
{
629
+ return str_replace('utf8mb4_general_ci', 'utf8_general_ci', $input);
630
}
631
632
/**
706
$connection->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
707
708
// Set default encoding
709
+ $connection->exec("SET NAMES 'utf8'");
710
711
// Set foreign key
712
+ $connection->exec("SET FOREIGN_KEY_CHECKS = 0");
713
714
return $connection;
715
}
742
*/
743
protected function getTableStructure($tableName)
744
{
745
+ $result = $this->getConnection()->query("SHOW CREATE TABLE `$tableName`");
746
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
747
if (isset($row['Create Table'])) {
748
749
+ // Replace table prefix
750
+ $createTable = $this->replaceTablePrefix($row['Create Table'], true);
751
752
// Strip table constraints
753
$createTable = $this->stripTableConstraints($createTable);
754
755
+ // Write table structure
756
+ $this->fileAdapter->write($createTable);
757
+
758
+ // Write end of statement
759
+ $this->fileAdapter->write(";\n\n");
760
761
return true;
762
}
763
}
764
+
765
+ return false;
766
}
767
768
/**
782
$query .= $queryClause;
783
}
784
785
+ // Apply additional table prefix columns
786
+ $columns = $this->getTablePrefixColumns($tableName);
787
788
// Get results
789
$result = $this->getConnection()->query($query);
790
791
+ // Replace table name prefix
792
+ $tableName = $this->replaceTablePrefix($tableName, true);
793
794
// Generate insert statements
795
+ while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
796
+ $items = array();
797
+ foreach ($row as $key => $value) {
798
+ // Replace table prefix columns
799
+ if (isset($columns[$key])) {
800
+ $value = $this->replaceTablePrefix($value, false, true);
801
}
802
803
+ // Replace table values
804
+ $items[] = is_null($value) ? 'NULL' : $this->getConnection()->quote($this->replaceTableValues($value));
805
}
806
807
+ // Set table values
808
+ $tableValues = implode(',', $items);
809
810
+ // Write insert statements
811
+ $this->fileAdapter->write("INSERT INTO `$tableName` VALUES ($tableValues);\n");
812
+ }
813
814
+ // Write end of statements
815
+ $this->fileAdapter->write("\n");
816
817
+ // Close result cursor
818
+ $result->closeCursor();
819
}
820
821
/**
lib/vendor/mysqldump-factory/mysqldump-factory/lib/MysqlDumpSQL.php CHANGED
@@ -34,7 +34,6 @@
34
*/
35
36
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'MysqlDumpInterface.php';
37
- require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'MysqlQueryAdapter.php';
38
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'MysqlFileAdapter.php';
39
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'MysqlUtility.php';
40
@@ -52,41 +51,31 @@ require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'MysqlUtility.php';
52
*/
53
class MysqlDumpSQL implements MysqlDumpInterface
54
{
55
- protected $hostname = null;
56
57
- protected $username = null;
58
59
- protected $password = null;
60
61
- protected $database = null;
62
63
- protected $fileName = 'database.sql';
64
65
- protected $fileAdapter = null;
66
67
- protected $queryAdapter = null;
68
69
- protected $connection = null;
70
71
- protected $oldTablePrefix = null;
72
73
- protected $newTablePrefix = null;
74
75
- protected $oldReplaceValues = array();
76
77
- protected $newReplaceValues = array();
78
79
- protected $queryClauses = array();
80
-
81
- protected $ignoreTableReplaces = array();
82
-
83
- protected $includeTables = array();
84
-
85
- protected $excludeTables = array();
86
-
87
- protected $noTableData = false;
88
-
89
- protected $addDropTable = false;
90
91
/**
92
* Define MySQL credentials for the current connection
@@ -104,9 +93,6 @@ class MysqlDumpSQL implements MysqlDumpInterface
104
$this->username = $username;
105
$this->password = $password;
106
$this->database = $database;
107
-
108
- // Set Query Adapter
109
- $this->queryAdapter = new MysqlQueryAdapter('mysql');
110
}
111
112
/**
@@ -126,21 +112,12 @@ class MysqlDumpSQL implements MysqlDumpInterface
126
$this->fileAdapter->write($this->getHeader());
127
128
// Listing all tables from database
129
- $tables = array();
130
- foreach ($this->listTables() as $table) {
131
- if (count($this->getIncludeTables()) === 0 || in_array($table, $this->getIncludeTables())) {
132
- $tables[] = $table;
133
- }
134
- }
135
136
// Export Tables
137
foreach ($tables as $table) {
138
- if (in_array($table, $this->getExcludeTables())) {
139
- continue;
140
- }
141
-
142
$isTable = $this->getTableStructure($table);
143
- if (true === $isTable) {
144
$this->listValues($table);
145
}
146
}
@@ -222,7 +199,7 @@ class MysqlDumpSQL implements MysqlDumpInterface
222
* Set old replace values
223
*
224
* @param array $values List of values
225
- * @return MysqlDumpPDO
226
*/
227
public function setOldReplaceValues($values)
228
{
@@ -245,7 +222,7 @@ class MysqlDumpSQL implements MysqlDumpInterface
245
* Set new replace values
246
*
247
* @param array $values List of values
248
- * @return MysqlDumpPDO
249
*/
250
public function setNewReplaceValues($values)
251
{
@@ -288,118 +265,78 @@ class MysqlDumpSQL implements MysqlDumpInterface
288
}
289
290
/**
291
- * Set ignore table replaces
292
- *
293
- * @param array $tables List of SQL tables
294
- * @return MysqlDumpPDO
295
- */
296
- public function setIgnoreTableReplaces($tables)
297
- {
298
- $this->ignoreTableReplaces = $tables;
299
-
300
- return $this;
301
- }
302
-
303
- /**
304
- * Get ignore table replaces
305
- *
306
- * @return array
307
- */
308
- public function getIgnoreTableReplaces()
309
- {
310
- return $this->ignoreTableReplaces;
311
- }
312
-
313
- /**
314
- * Set include tables
315
- *
316
- * @param array $tables List of tables
317
- * @return MysqlDumpSQL
318
- */
319
- public function setIncludeTables($tables)
320
- {
321
- $this->includeTables = $tables;
322
-
323
- return $this;
324
- }
325
-
326
- /**
327
- * Get include tables
328
- *
329
- * @return array
330
- */
331
- public function getIncludeTables()
332
- {
333
- return $this->includeTables;
334
- }
335
-
336
- /**
337
- * Set exclude tables
338
*
339
- * @param array $tables List of tables
340
* @return MysqlDumpSQL
341
*/
342
- public function setExcludeTables($tables)
343
{
344
- $this->excludeTables = $tables;
345
346
return $this;
347
}
348
349
/**
350
- * Get exclude tables
351
*
352
* @return array
353
*/
354
- public function getExcludeTables()
355
- {
356
- return $this->excludeTables;
357
- }
358
-
359
- /**
360
- * Set no table data flag
361
- *
362
- * @param bool $flag Do not export table data
363
- * @return MysqlDumpSQL
364
- */
365
- public function setNoTableData($flag)
366
{
367
- $this->noTableData = (bool) $flag;
368
-
369
- return $this;
370
- }
371
372
- /**
373
- * Get no table data flag
374
- *
375
- * @return bool
376
- */
377
- public function getNoTableData()
378
- {
379
- return $this->noTableData;
380
}
381
382
/**
383
- * Set add drop table flag
384
*
385
- * @param bool $flag Add drop table SQL clause
386
- * @return MysqlDumpSQL
387
*/
388
- public function setAddDropTable($flag)
389
- {
390
- $this->addDropTable = (bool) $flag;
391
-
392
- return $this;
393
}
394
395
/**
396
- * Get add drop table flag
397
*
398
- * @return bool
399
*/
400
- public function getAddDropTable()
401
- {
402
- return $this->addDropTable;
403
}
404
405
/**
@@ -438,14 +375,14 @@ class MysqlDumpSQL implements MysqlDumpInterface
438
*/
439
public function flush()
440
{
441
- $deleteTables = array();
442
- foreach ($this->listTables() as $table) {
443
- $deleteTables[] = $this->queryAdapter->drop_table($table);
444
}
445
446
// Drop tables
447
- foreach ($deleteTables as $delete) {
448
- mysql_unbuffered_query($delete, $this->getConnection());
449
}
450
}
451
@@ -458,33 +395,47 @@ class MysqlDumpSQL implements MysqlDumpInterface
458
public function import($fileName)
459
{
460
// Set collation name
461
- $collation = $this->getCollation('utf8mb4_unicode_ci');
462
463
$fileHandler = fopen($fileName, 'r');
464
- if ($fileHandler) {
465
- $query = null;
466
467
- // Read database file line by line
468
- while (($line = fgets($fileHandler)) !== false) {
469
- // Replace create table prefix
470
- $line = $this->replaceCreateTablePrefix($line);
471
472
- // Replace insert into prefix
473
- $line = $this->replaceInsertIntoPrefix($line);
474
475
- // Replace table values
476
- $line = $this->replaceTableValues($line);
477
478
- // Replace table collation
479
- if (empty($collation)) {
480
- $line = $this->replaceTableCollation($line);
481
- }
482
483
- $query .= $line;
484
- if (preg_match('/;\s*#x2F;', $line)) {
485
// Run SQL query
486
$result = mysql_unbuffered_query($query, $this->getConnection());
487
if ($result === false) {
488
// Log the error
489
Ai1wm_Log::error(
490
sprintf(
@@ -493,15 +444,27 @@ class MysqlDumpSQL implements MysqlDumpInterface
493
$query
494
)
495
);
496
}
497
498
- // Empty query
499
- $query = null;
500
}
501
}
502
503
- return true;
504
}
505
}
506
507
/**
@@ -513,16 +476,20 @@ class MysqlDumpSQL implements MysqlDumpInterface
513
{
514
$tables = array();
515
516
- $query = $this->queryAdapter->show_tables_information_schema($this->database);
517
- if (($result = mysql_unbuffered_query($query, $this->getConnection()))) {
518
while ($row = mysql_fetch_assoc($result)) {
519
- if (isset($row['table_name'])) {
520
- $tables[] = $row['table_name'];
521
}
522
}
523
} else {
524
- $query = $this->queryAdapter->show_tables($this->database);
525
- $result = mysql_unbuffered_query($query, $this->getConnection());
526
while ($row = mysql_fetch_row($result)) {
527
if (isset($row[0])) {
528
$tables[] = $row[0];
@@ -534,81 +501,113 @@ class MysqlDumpSQL implements MysqlDumpInterface
534
}
535
536
/**
537
- * Replace table values
538
*
539
* @param string $input Table value
540
* @return string
541
*/
542
- public function replaceTableValues($input)
543
{
544
$old = $this->getOldReplaceValues();
545
$new = $this->getNewReplaceValues();
546
547
$oldValues = array();
548
$newValues = array();
549
550
- // Replace strings
551
for ($i = 0; $i < count($old); $i++) {
552
- if (!empty($old[$i]) && ($old[$i] != $new[$i]) && !in_array($old[$i], $oldValues)) {
553
$oldValues[] = $old[$i];
554
$newValues[] = $new[$i];
555
}
556
}
557
558
- // Replace table prefix
559
- $oldValues[] = $this->getOldTablePrefix();
560
- $newValues[] = $this->getNewTablePrefix();
561
-
562
- // Replace table values
563
- $input = str_replace($oldValues, $newValues, $input);
564
565
- // Verify serialization
566
- return MysqlUtility::pregReplace(
567
- $input,
568
- '/s:(\d+):([\\\\]?"[\\\\]?"|[\\\\]?"((.*?)[^\\\\])[\\\\]?");/'
569
- );
570
- }
571
572
- /**
573
- * Replace table name prefix
574
- *
575
- * @param string $input Table name
576
- * @return string
577
- */
578
- public function replaceTableNamePrefix($input)
579
- {
580
- $pattern = '/^(' . preg_quote($this->getOldTablePrefix(), '/') . ')(.+)/i';
581
- $replace = $this->getNewTablePrefix() . '\2';
582
583
- return preg_replace($pattern, $replace, $input);
584
}
585
586
/**
587
- * Replace create table prefix
588
*
589
- * @param string $input SQL statement
590
* @return string
591
*/
592
- public function replaceCreateTablePrefix($input)
593
{
594
- $pattern = '/^CREATE TABLE `(' . preg_quote($this->getOldTablePrefix(), '/') . ')(.+)`/Ui';
595
- $replace = 'CREATE TABLE `' . $this->getNewTablePrefix() . '\2`';
596
597
- return preg_replace($pattern, $replace, $input);
598
}
599
600
/**
601
- * Replace insert into prefix
602
*
603
- * @param string $input SQL statement
604
* @return string
605
*/
606
- public function replaceInsertIntoPrefix($input)
607
{
608
- $pattern = '/^INSERT INTO `(' . preg_quote($this->getOldTablePrefix(), '/') . ')(.+)`/Ui';
609
- $replace = 'INSERT INTO `' . $this->getNewTablePrefix() . '\2`';
610
611
- return preg_replace($pattern, $replace, $input);
612
}
613
614
/**
@@ -619,10 +618,7 @@ class MysqlDumpSQL implements MysqlDumpInterface
619
*/
620
public function replaceTableCollation($input)
621
{
622
- $pattern = array('utf8mb4_unicode_ci', 'utf8mb4');
623
- $replace = array('utf8_general_ci', 'utf8');
624
-
625
- return str_replace($pattern, $replace, $input);
626
}
627
628
/**
@@ -685,12 +681,10 @@ class MysqlDumpSQL implements MysqlDumpInterface
685
if ($connection) {
686
if (mysql_select_db($this->database, $connection)) {
687
// Set default encoding
688
- $query = $this->queryAdapter->set_names('utf8');
689
- mysql_unbuffered_query($query, $connection);
690
691
// Set foreign key
692
- $query = $this->queryAdapter->set_foreign_key(0);
693
- mysql_unbuffered_query($query, $connection);
694
} else {
695
throw new Exception('Could not select MySQL database: ' . mysql_error($connection));
696
}
@@ -727,34 +721,27 @@ class MysqlDumpSQL implements MysqlDumpInterface
727
*/
728
protected function getTableStructure($tableName)
729
{
730
- $query = $this->queryAdapter->show_create_table($tableName);
731
- $result = mysql_unbuffered_query($query, $this->getConnection());
732
while ($row = mysql_fetch_assoc($result)) {
733
if (isset($row['Create Table'])) {
734
- // Replace table name prefix
735
- $tableName = $this->replaceTableNamePrefix($tableName);
736
-
737
- $this->fileAdapter->write("-- " .
738
- "--------------------------------------------------------" .
739
- "\n\n" .
740
- "--\n" .
741
- "-- Table structure for table `$tableName`\n--\n\n");
742
-
743
- if ($this->getAddDropTable()) {
744
- $this->fileAdapter->write("DROP TABLE IF EXISTS `$tableName`;\n\n");
745
- }
746
747
// Replace create table prefix
748
- $createTable = $this->replaceCreateTablePrefix($row['Create Table']);
749
750
// Strip table constraints
751
$createTable = $this->stripTableConstraints($createTable);
752
753
- $this->fileAdapter->write($createTable . ";\n\n");
754
755
return true;
756
}
757
}
758
}
759
760
/**
@@ -774,73 +761,39 @@ class MysqlDumpSQL implements MysqlDumpInterface
774
$query .= $queryClause;
775
}
776
777
- // No table data
778
- if ($this->getNoTableData() && !isset($clauses[$tableName])) {
779
- return;
780
- }
781
782
// Get results
783
$result = mysql_unbuffered_query($query, $this->getConnection());
784
785
- // Get ignore table replaces
786
- $ignoreTableReplaces = $this->getIgnoreTableReplaces();
787
788
// Generate insert statements
789
- if (isset($ignoreTableReplaces[$tableName])) {
790
-
791
- // Replace table name prefix
792
- $tableName = $this->replaceTableNamePrefix($tableName);
793
-
794
- $this->fileAdapter->write(
795
- "--\n" .
796
- "-- Dumping data for table `$tableName`\n" .
797
- "--\n\n"
798
- );
799
-
800
- // Generate insert statements
801
- while ($row = mysql_fetch_row($result)) {
802
- $items = array();
803
- foreach ($row as $value) {
804
- $items[] = is_null($value) ? 'NULL' : "'" . mysql_real_escape_string($value) . "'";
805
}
806
807
- // Set table values
808
- $tableValues = implode(',', $items);
809
-
810
- // Write insert statements
811
- $this->fileAdapter->write("INSERT INTO `$tableName` VALUES ($tableValues);\n");
812
}
813
814
- // Close result cursor
815
- mysql_free_result($result);
816
-
817
- } else {
818
-
819
- // Replace table name prefix
820
- $tableName = $this->replaceTableNamePrefix($tableName);
821
-
822
- $this->fileAdapter->write(
823
- "--\n" .
824
- "-- Dumping data for table `$tableName`\n" .
825
- "--\n\n"
826
- );
827
-
828
- // Generate insert statements
829
- while ($row = mysql_fetch_row($result)) {
830
- $items = array();
831
- foreach ($row as $value) {
832
- $items[] = is_null($value) ? 'NULL' : "'" . mysql_real_escape_string($this->replaceTableValues($value)) . "'";
833
- }
834
835
- // Set table values
836
- $tableValues = implode(',', $items);
837
838
- // Write insert statements
839
- $this->fileAdapter->write("INSERT INTO `$tableName` VALUES ($tableValues);\n");
840
- }
841
842
- // Close result cursor
843
- mysql_free_result($result);
844
- }
845
}
846
}
34
*/
35
36
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'MysqlDumpInterface.php';
37
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'MysqlFileAdapter.php';
38
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'MysqlUtility.php';
39
51
*/
52
class MysqlDumpSQL implements MysqlDumpInterface
53
{
54
+ protected $hostname = null;
55
56
+ protected $username = null;
57
58
+ protected $password = null;
59
60
+ protected $database = null;
61
62
+ protected $fileName = 'database.sql';
63
64
+ protected $fileAdapter = null;
65
66
+ protected $connection = null;
67
68
+ protected $oldTablePrefix = null;
69
70
+ protected $newTablePrefix = null;
71
72
+ protected $oldReplaceValues = array();
73
74
+ protected $newReplaceValues = array();
75
76
+ protected $queryClauses = array();
77
78
+ protected $tablePrefixColumns = array();
79
80
/**
81
* Define MySQL credentials for the current connection
93
$this->username = $username;
94
$this->password = $password;
95
$this->database = $database;
96
}
97
98
/**
112
$this->fileAdapter->write($this->getHeader());
113
114
// Listing all tables from database
115
+ $tables = $this->listTables();
116
117
// Export Tables
118
foreach ($tables as $table) {
119
$isTable = $this->getTableStructure($table);
120
+ if ($isTable) {
121
$this->listValues($table);
122
}
123
}
199
* Set old replace values
200
*
201
* @param array $values List of values
202
+ * @return MysqlDumpSQL
203
*/
204
public function setOldReplaceValues($values)
205
{
222
* Set new replace values
223
*
224
* @param array $values List of values
225
+ * @return MysqlDumpSQL
226
*/
227
public function setNewReplaceValues($values)
228
{
265
}
266
267
/**
268
+ * Set table prefix columns
269
*
270
+ * @param string $table Table name
271
+ * @param array $columns Table columns
272
* @return MysqlDumpSQL
273
*/
274
+ public function setTablePrefixColumns($table, $columns)
275
{
276
+ foreach ($columns as $column) {
277
+ $this->tablePrefixColumns[$table][$column] = true;
278
+ }
279
280
return $this;
281
}
282
283
/**
284
+ * Get table prefix columns
285
*
286
+ * @param string $table Table name
287
* @return array
288
*/
289
+ public function getTablePrefixColumns($table)
290
{
291
+ if (isset($this->tablePrefixColumns[$table])) {
292
+ return $this->tablePrefixColumns[$table];
293
+ }
294
295
+ return array();
296
}
297
298
/**
299
+ * Get MySQL version
300
*
301
+ * @return string
302
*/
303
+ public function getVersion() {
304
+ if (($result = mysql_unbuffered_query("SELECT @@version AS VersionName", $this->getConnection()))) {
305
+ while ($row = mysql_fetch_assoc($result)) {
306
+ if (isset($row['VersionName'])) {
307
+ return $row['VersionName'];
308
+ }
309
+ }
310
+ } else {
311
+ $result = mysql_unbuffered_query("SHOW VARIABLES LIKE 'version'", $this->getConnection());
312
+ while ($row = mysql_fetch_row($result)) {
313
+ if (isset($row[1])) {
314
+ return $row[1];
315
+ }
316
+ }
317
+ }
318
}
319
320
/**
321
+ * Get MySQL max allowed packaet
322
*
323
+ * @return integer
324
*/
325
+ public function getMaxAllowedPacket() {
326
+ if (($result = mysql_unbuffered_query("SELECT @@max_allowed_packet AS MaxAllowedPacket", $this->getConnection()))) {
327
+ while ($row = mysql_fetch_assoc($result)) {
328
+ if (isset($row['MaxAllowedPacket'])) {
329
+ return $row['MaxAllowedPacket'];
330
+ }
331
+ }
332
+ } else {
333
+ $result = mysql_unbuffered_query("SHOW VARIABLES LIKE 'max_allowed_packet'", $this->getConnection());
334
+ while ($row = mysql_fetch_row($result)) {
335
+ if (isset($row[1])) {
336
+ return $row[1];
337
+ }
338
+ }
339
+ }
340
}
341
342
/**
375
*/
376
public function flush()
377
{
378
+ $dropTables = array();
379
+ foreach ($this->listTables() as $tableName) {
380
+ $dropTables[] = "DROP TABLE IF EXISTS `$tableName`";
381
}
382
383
// Drop tables
384
+ foreach ($dropTables as $dropQuery) {
385
+ mysql_unbuffered_query($dropQuery, $this->getConnection());
386
}
387
}
388
395
public function import($fileName)
396
{
397
// Set collation name
398
+ $collation = $this->getCollation('utf8mb4_general_ci');
399
+
400
+ // Set max allowed packet
401
+ $maxAllowedPacket = $this->getMaxAllowedPacket();
402
403
+ // Set file handler
404
$fileHandler = fopen($fileName, 'r');
405
+ if ($fileHandler === false) {
406
+ throw new Exception('Unable to open database file');
407
+ }
408
409
+ $passed = 0;
410
+ $failed = 0;
411
+ $query = null;
412
413
+ // Read database file line by line
414
+ while (($line = fgets($fileHandler)) !== false) {
415
+ $query .= $line;
416
417
+ // End of query
418
+ if (preg_match('/;\s*#x2F;', $query)) {
419
420
+ // Check max allowed packet
421
+ if (strlen($query) <= $maxAllowedPacket) {
422
+
423
+ // Replace table prefix
424
+ $query = $this->replaceTablePrefix($query);
425
+
426
+ // Replace table values
427
+ $query = $this->replaceTableValues($query, true);
428
+
429
+ // Replace table collation
430
+ if (empty($collation)) {
431
+ $query = $this->replaceTableCollation($query);
432
+ }
433
434
// Run SQL query
435
$result = mysql_unbuffered_query($query, $this->getConnection());
436
if ($result === false) {
437
+ $failed++;
438
+
439
// Log the error
440
Ai1wm_Log::error(
441
sprintf(
444
$query
445
)
446
);
447
+ } else {
448
+ $passed++;
449
}
450
451
+ } else {
452
+ $failed++;
453
}
454
+
455
+ $query = null;
456
}
457
+ }
458
459
+ // Close file handler
460
+ fclose($fileHandler);
461
+
462
+ // Check failed queries
463
+ if ((($failed / $passed) * 100) > 2) {
464
+ return false;
465
}
466
+
467
+ return true;
468
}
469
470
/**
476
{
477
$tables = array();
478
479
+ // Get list of tables
480
+ $result = mysql_unbuffered_query(
481
+ "SELECT TABLE_NAME AS TableName FROM `INFORMATION_SCHEMA`.`TABLES` WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_SCHEMA = '{$this->database}'",
482
+ $this->getConnection()
483
+ );
484
+
485
+ if ($result) {
486
while ($row = mysql_fetch_assoc($result)) {
487
+ if (isset($row['TableName'])) {
488
+ $tables[] = $row['TableName'];
489
}
490
}
491
} else {
492
+ $result = mysql_unbuffered_query("SHOW TABLES FROM `{$this->database}`", $this->getConnection());
493
while ($row = mysql_fetch_row($result)) {
494
if (isset($row[0])) {
495
$tables[] = $row[0];
501
}
502
503
/**
504
+ * Replace table prefix
505
*
506
* @param string $input Table value
507
+ * @param boolean $first Replace first occurrence
508
+ * @param boolean $start Replace start occurrence
509
+ * @return string
510
+ */
511
+ public function replaceTablePrefix($input, $first = false, $start = false)
512
+ {
513
+ // Get table prefix
514
+ $search = $this->getOldTablePrefix();
515
+ $replace = $this->getNewTablePrefix();
516
+
517
+ // Replace first occurrence
518
+ if ($first) {
519
+ $pos = strpos($input, $search);
520
+ if ($pos !== false) {
521
+ return substr_replace($input, $replace, $pos, strlen($search));
522
+ }
523
+
524
+ return $input;
525
+ } else if ($start) {
526
+ $pos = strpos($input, $search);
527
+ if ($pos === 0) {
528
+ return substr_replace($input, $replace, $pos, strlen($search));
529
+ }
530
+
531
+ return $input;
532
+ }
533
+
534
+ // Replace all occurrences
535
+ return str_replace($search, $replace, $input);
536
+ }
537
+
538
+ /**
539
+ * Replace table values
540
+ *
541
+ * @param string $input Table value
542
+ * @param boolean $parse Parse value
543
* @return string
544
*/
545
+ public function replaceTableValues($input, $parse = false)
546
{
547
+ // Get replace values
548
$old = $this->getOldReplaceValues();
549
$new = $this->getNewReplaceValues();
550
551
$oldValues = array();
552
$newValues = array();
553
554
+ // Prepare replace values
555
for ($i = 0; $i < count($old); $i++) {
556
+ if (strpos($input, $old[$i]) !== false) {
557
$oldValues[] = $old[$i];
558
$newValues[] = $new[$i];
559
}
560
}
561
562
+ // Do replace values
563
+ if ($oldValues) {
564
+ if ($parse) {
565
+ // Parse and replace serialized values
566
+ $input = $this->parseSerializedValues($input);
567
568
+ // Replace values
569
+ return MysqlUtility::replaceValues($oldValues, $newValues, $input);
570
+ }
571
572
+ return MysqlUtility::replaceSerializedValues($oldValues, $newValues, $input);
573
+ }
574
575
+ return $input;
576
}
577
578
/**
579
+ * Parse serialized values
580
*
581
+ * @param string $input Table value
582
* @return string
583
*/
584
+ public function parseSerializedValues($input)
585
{
586
+ // Serialization format
587
+ $array = '(a:\d+:{.*?})';
588
+ $string = '(s:\d+:".*?")';
589
+ $object = '(O:\d+:".+":\d+:{.*})';
590
591
+ // Replace serialized values
592
+ return preg_replace_callback("/'($array|$string|$object)'/", array($this, 'replaceSerializedValues'), $input);
593
}
594
595
/**
596
+ * Replace serialized values (callback)
597
*
598
+ * @param array $matches List of matches
599
* @return string
600
*/
601
+ public function replaceSerializedValues($matches)
602
{
603
+ // Unescape MySQL special characters
604
+ $input = MysqlUtility::unescapeMysql($matches[1]);
605
606
+ // Replace serialized values
607
+ $input = MysqlUtility::replaceSerializedValues($this->getOldReplaceValues(), $this->getNewReplaceValues(), $input);
608
+
609
+ // Prepare query values
610
+ return "'" . mysql_real_escape_string($input, $this->getConnection()) . "'";
611
}
612
613
/**
618
*/
619
public function replaceTableCollation($input)
620
{
621
+ return str_replace('utf8mb4_general_ci', 'utf8_general_ci', $input);
622
}
623
624
/**
681
if ($connection) {
682
if (mysql_select_db($this->database, $connection)) {
683
// Set default encoding
684
+ mysql_unbuffered_query("SET NAMES 'utf8'", $connection);
685
686
// Set foreign key
687
+ mysql_unbuffered_query("SET FOREIGN_KEY_CHECKS = 0", $connection);
688
} else {
689
throw new Exception('Could not select MySQL database: ' . mysql_error($connection));
690
}
721
*/
722
protected function getTableStructure($tableName)
723
{
724
+ $result = mysql_unbuffered_query("SHOW CREATE TABLE `$tableName`", $this->getConnection());
725
while ($row = mysql_fetch_assoc($result)) {
726
if (isset($row['Create Table'])) {
727
728
// Replace create table prefix
729
+ $createTable = $this->replaceTablePrefix($row['Create Table'], true);
730
731
// Strip table constraints
732
$createTable = $this->stripTableConstraints($createTable);
733
734