PluginProbe
bbPress / 2.2.2
bbPress v2.2.2
trunk 2.0 2.0-beta-1 2.0-beta-2b 2.0-beta-3 2.0-beta-3b 2.0-rc-2 2.0-rc-3 2.0-rc-4 2.0-rc-5 2.0.1 2.0.2 2.0.3 2.1 2.1-beta-1 2.1-rc1 2.1-rc2 2.1-rc3 2.1-rc4 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.2.2 All 71 releases
bbpress / includes / admin / converter.php

converter.php in bbPress 2.2.2, at includes/admin/converter.php

1,296 lines 40.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * bbPress Converter
5 *
6 * Based on the hard work of Adam Ellis at http://bbconverter.com
7 *
8 * @package bbPress
9 * @subpackage Administration
10 */
11
12 // Exit if accessed directly
13 if ( !defined( 'ABSPATH' ) ) exit;
14
15 /**
16 * Main BBP_Converter Class
17 */
18 class BBP_Converter {
19
20 /**
21 * The main bbPress Converter loader
22 *
23 * @since bbPress (r3813)
24 * @uses BBP_Converter::includes() Include the required files
25 * @uses BBP_Converter::setup_actions() Setup the actions
26 */
27 public function __construct() {
28
29 // Bail if request is not correct
30 switch ( strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
31
32 // Converter is converting
33 case 'POST' :
34 if ( ( empty( $_POST['action'] ) || ( 'bbconverter_process' != $_POST['action'] ) ) )
35 return;
36
37 break;
38
39 // Some other admin page
40 case 'GET' :
41 if ( ( empty( $_GET['page'] ) || ( 'bbp-converter' != $_GET['page'] ) ) )
42 return;
43
44 break;
45 }
46
47 // Proceed with the actions
48 $this->setup_actions();
49 }
50
51 /**
52 * Setup the default actions
53 *
54 * @since bbPress (r3813)
55 * @uses add_action() To add various actions
56 */
57 private function setup_actions() {
58
59 // Attach to the admin head with our ajax requests cycle and css
60 add_action( 'bbp_admin_head', array( $this, 'admin_head' ) );
61
62 // Attach the bbConverter admin settings action to the WordPress admin init action.
63 add_action( 'bbp_register_admin_settings', array( $this, 'register_admin_settings' ) );
64
65 // Attach to the admin ajax request to process cycles
66 add_action( 'wp_ajax_bbconverter_process', array( $this, 'process_callback' ) );
67 }
68
69 /**
70 * Register the settings
71 *
72 * @since bbPress (r3813)
73 * @uses add_settings_section() To add our own settings section
74 * @uses add_settings_field() To add various settings fields
75 * @uses register_setting() To register various settings
76 */
77 public function register_admin_settings() {
78
79 // Add the main section
80 add_settings_section( 'bbpress_converter_main', __( 'Database Settings', 'bbpress' ), 'bbp_converter_setting_callback_main_section', 'bbpress_converter' );
81
82 // System Select
83 add_settings_field( '_bbp_converter_platform', __( 'Select Platform', 'bbpress' ), 'bbp_converter_setting_callback_platform', 'bbpress_converter', 'bbpress_converter_main' );
84 register_setting ( 'bbpress_converter_main', '_bbp_converter_platform', 'sanitize_title' );
85
86 // Database Server
87 add_settings_field( '_bbp_converter_db_server', __( 'Database Server', 'bbpress' ), 'bbp_converter_setting_callback_dbserver', 'bbpress_converter', 'bbpress_converter_main' );
88 register_setting ( 'bbpress_converter_main', '_bbp_converter_db_server', 'sanitize_title' );
89
90 // Database Server Port
91 add_settings_field( '_bbp_converter_db_port', __( 'Database Port', 'bbpress' ), 'bbp_converter_setting_callback_dbport', 'bbpress_converter', 'bbpress_converter_main' );
92 register_setting ( 'bbpress_converter_main', '_bbp_converter_db_port', 'sanitize_title' );
93
94 // Database Name
95 add_settings_field( '_bbp_converter_db_name', __( 'Database Name', 'bbpress' ), 'bbp_converter_setting_callback_dbname', 'bbpress_converter', 'bbpress_converter_main' );
96 register_setting ( 'bbpress_converter_main', '_bbp_converter_db_name', 'sanitize_title' );
97
98 // Database User
99 add_settings_field( '_bbp_converter_db_user', __( 'Database User', 'bbpress' ), 'bbp_converter_setting_callback_dbuser', 'bbpress_converter', 'bbpress_converter_main' );
100 register_setting ( 'bbpress_converter_main', '_bbp_converter_db_user', 'sanitize_title' );
101
102 // Database Pass
103 add_settings_field( '_bbp_converter_db_pass', __( 'Database Password', 'bbpress' ), 'bbp_converter_setting_callback_dbpass', 'bbpress_converter', 'bbpress_converter_main' );
104 register_setting ( 'bbpress_converter_main', '_bbp_converter_db_pass', 'sanitize_title' );
105
106 // Database Prefix
107 add_settings_field( '_bbp_converter_db_prefix', __( 'Table Prefix', 'bbpress' ), 'bbp_converter_setting_callback_dbprefix', 'bbpress_converter', 'bbpress_converter_main' );
108 register_setting ( 'bbpress_converter_main', '_bbp_converter_db_prefix', 'sanitize_title' );
109
110 // Add the options section
111 add_settings_section( 'bbpress_converter_opt', __( 'Options', 'bbpress' ), 'bbp_converter_setting_callback_options_section', 'bbpress_converter' );
112
113 // Rows Limit
114 add_settings_field( '_bbp_converter_rows', __( 'Rows Limit', 'bbpress' ), 'bbp_converter_setting_callback_rows', 'bbpress_converter', 'bbpress_converter_opt' );
115 register_setting ( 'bbpress_converter_opt', '_bbp_converter_rows', 'intval' );
116
117 // Delay Time
118 add_settings_field( '_bbp_converter_delay_time', __( 'Delay Time', 'bbpress' ), 'bbp_converter_setting_callback_delay_time', 'bbpress_converter', 'bbpress_converter_opt' );
119 register_setting ( 'bbpress_converter_opt', '_bbp_converter_delay_time', 'intval' );
120
121 // Convert Users ?
122 add_settings_field( '_bbp_converter_convert_users', __( 'Convert Users', 'bbpress' ), 'bbp_converter_setting_callback_convert_users', 'bbpress_converter', 'bbpress_converter_opt' );
123 register_setting ( 'bbpress_converter_opt', '_bbp_converter_convert_users', 'intval' );
124
125 // Restart
126 add_settings_field( '_bbp_converter_restart', __( 'Start Over', 'bbpress' ), 'bbp_converter_setting_callback_restart', 'bbpress_converter', 'bbpress_converter_opt' );
127 register_setting ( 'bbpress_converter_opt', '_bbp_converter_restart', 'intval' );
128
129 // Clean
130 add_settings_field( '_bbp_converter_clean', __( 'Purge Previous Import', 'bbpress' ), 'bbp_converter_setting_callback_clean', 'bbpress_converter', 'bbpress_converter_opt' );
131 register_setting ( 'bbpress_converter_opt', '_bbp_converter_clean', 'intval' );
132 }
133
134 /**
135 * Admin scripts
136 *
137 * @since bbPress (r3813)
138 */
139 public function admin_head() { ?>
140
141 <style type="text/css" media="screen">
142 /*<![CDATA[*/
143
144 div.bbp-converter-updated,
145 div.bbp-converter-warning {
146 border-radius: 3px 3px 3px 3px;
147 border-style: solid;
148 border-width: 1px;
149 padding: 5px 5px 5px 5px;
150 }
151
152 div.bbp-converter-updated {
153 height: 300px;
154 overflow: auto;
155 display: none;
156 background-color: #FFFFE0;
157 border-color: #E6DB55;
158 font-family: monospace;
159 font-weight: bold;
160 }
161
162 div.bbp-converter-updated p {
163 margin: 0.5em 0;
164 padding: 2px;
165 float: left;
166 clear: left;
167 }
168
169 div.bbp-converter-updated p.loading {
170 padding: 2px 20px 2px 2px;
171 background-image: url('<?php echo admin_url(); ?>images/wpspin_light.gif');
172 background-repeat: no-repeat;
173 background-position: center right;
174 }
175
176 #bbp-converter-stop {
177 display:none;
178 }
179
180 #bbp-converter-progress {
181 display:none;
182 }
183
184 /*]]>*/
185 </style>
186
187 <script language="javascript">
188
189 var bbconverter_is_running = false;
190 var bbconverter_run_timer;
191 var bbconverter_delay_time = 0;
192
193 function bbconverter_grab_data() {
194 var values = {};
195 jQuery.each(jQuery('#bbp-converter-settings').serializeArray(), function(i, field) {
196 values[field.name] = field.value;
197 });
198
199 if( values['_bbp_converter_restart'] ) {
200 jQuery('#_bbp_converter_restart').removeAttr("checked");
201 }
202
203 if( values['_bbp_converter_delay_time'] ) {
204 bbconverter_delay_time = values['_bbp_converter_delay_time'] * 1000;
205 }
206
207 values['action'] = 'bbconverter_process';
208 values['_ajax_nonce'] = '<?php echo wp_create_nonce( 'bbp_converter_process' ); ?>';
209
210 return values;
211 }
212
213 function bbconverter_start() {
214 if( false == bbconverter_is_running ) {
215 bbconverter_is_running = true;
216 jQuery('#bbp-converter-start').hide();
217 jQuery('#bbp-converter-stop').show();
218 jQuery('#bbp-converter-progress').show();
219 bbconverter_log( '<p class="loading"><?php _e( 'Starting Conversion', 'bbpress' ); ?></p>' );
220 bbconverter_run();
221 }
222 }
223
224 function bbconverter_run() {
225 jQuery.post(ajaxurl, bbconverter_grab_data(), function(response) {
226 var response_length = response.length - 1;
227 response = response.substring(0,response_length);
228 bbconverter_success(response);
229 });
230 }
231
232 function bbconverter_stop() {
233 jQuery('#bbp-converter-start').show();
234 jQuery('#bbp-converter-stop').hide();
235 jQuery('#bbp-converter-progress').hide();
236 jQuery('#bbp-converter-message p').removeClass( 'loading' );
237 bbconverter_is_running = false;
238 clearTimeout( bbconverter_run_timer );
239 }
240
241 function bbconverter_success(response) {
242 bbconverter_log(response);
243
244 if ( response == '<p class="loading"><?php _e( 'Conversion Complete', 'bbpress' ); ?></p>' || response.indexOf('error') > -1 ) {
245 bbconverter_log('<p>Repair any missing information: <a href="<?php echo admin_url(); ?>tools.php?page=bbp-repair">Continue</a></p>');
246 bbconverter_stop();
247 } else if( bbconverter_is_running ) { // keep going
248 jQuery('#bbp-converter-progress').show();
249 clearTimeout( bbconverter_run_timer );
250 bbconverter_run_timer = setTimeout( 'bbconverter_run()', bbconverter_delay_time );
251 } else {
252 bbconverter_stop();
253 }
254 }
255
256 function bbconverter_log(text) {
257 if ( jQuery('#bbp-converter-message').css('display') == 'none' ) {
258 jQuery('#bbp-converter-message').show();
259 }
260 if ( text ) {
261 jQuery('#bbp-converter-message p').removeClass( 'loading' );
262 jQuery('#bbp-converter-message').prepend( text );
263 }
264 }
265
266 </script>
267
268 <?php
269 }
270
271 /**
272 * Wrap the converter output in paragraph tags, so styling can be applied
273 *
274 * @since bbPress (r4052)
275 *
276 * @param string $output
277 */
278 private static function converter_output( $output = '' ) {
279
280 // Get the last query
281 $before = '<p class="loading">';
282 $after = '</p>';
283 $query = get_option( '_bbp_converter_query' );
284
285 if ( ! empty( $query ) )
286 $before = '<p class="loading" title="' . esc_attr( $query ) . '">';
287
288 echo $before . $output . $after;
289 }
290
291 /**
292 * Callback processor
293 *
294 * @since bbPress (r3813)
295 */
296 public function process_callback() {
297
298 // Verify intent
299 check_ajax_referer( 'bbp_converter_process' );
300
301 if ( ! ini_get( 'safe_mode' ) ) {
302 set_time_limit( 0 );
303 ini_set( 'memory_limit', '256M' );
304 ini_set( 'implicit_flush', '1' );
305 ignore_user_abort( true );
306 }
307
308 // Save step and count so that it can be restarted.
309 if ( ! get_option( '_bbp_converter_step' ) || ( !empty( $_POST['_bbp_converter_restart'] ) ) ) {
310 update_option( '_bbp_converter_step', 1 );
311 update_option( '_bbp_converter_start', 0 );
312 }
313
314 $step = (int) get_option( '_bbp_converter_step', 1 );
315 $min = (int) get_option( '_bbp_converter_start', 0 );
316 $count = (int) ! empty( $_POST['_bbp_converter_rows'] ) ? $_POST['_bbp_converter_rows'] : 100;
317 $max = ( $min + $count ) - 1;
318 $start = $min;
319
320 // Bail if platform did not get saved
321 $platform = !empty( $_POST['_bbp_converter_platform' ] ) ? $_POST['_bbp_converter_platform' ] : get_option( '_bbp_converter_platform' );
322 if ( empty( $platform ) )
323 return;
324
325 // Include the appropriate converter.
326 $converter = bbp_new_converter( $platform );
327
328 switch ( $step ) {
329
330 // STEP 1. Clean all tables.
331 case 1 :
332 if ( !empty( $_POST['_bbp_converter_clean'] ) ) {
333 if ( $converter->clean( $start ) ) {
334 update_option( '_bbp_converter_step', $step + 1 );
335 update_option( '_bbp_converter_start', 0 );
336 $this->sync_table( true );
337 if ( empty( $start ) ) {
338 $this->converter_output( __( 'No data to clean', 'bbpress' ) );
339 }
340 } else {
341 update_option( '_bbp_converter_start', $max + 1 );
342 $this->converter_output( sprintf( __( 'Deleting previously converted data (%1$s - %2$s)', 'bbpress' ), $min, $max ) );
343 }
344 } else {
345 update_option( '_bbp_converter_step', $step + 1 );
346 update_option( '_bbp_converter_start', 0 );
347 }
348
349 break;
350
351 // STEP 2. Convert users.
352 case 2 :
353 if ( !empty( $_POST['_bbp_converter_convert_users'] ) ) {
354 if ( $converter->convert_users( $start ) ) {
355 update_option( '_bbp_converter_step', $step + 1 );
356 update_option( '_bbp_converter_start', 0 );
357 if ( empty( $start ) ) {
358 $this->converter_output( __( 'No users to convert', 'bbpress' ) );
359 }
360 } else {
361 update_option( '_bbp_converter_start', $max + 1 );
362 $this->converter_output( sprintf( __( 'Converting users (%1$s - %2$s)', 'bbpress' ), $min, $max ) );
363 }
364 } else {
365 update_option( '_bbp_converter_step', $step + 1 );
366 update_option( '_bbp_converter_start', 0 );
367 }
368
369 break;
370
371 // STEP 3. Clean passwords.
372 case 3 :
373 if ( !empty( $_POST['_bbp_converter_convert_users'] ) ) {
374 if ( $converter->clean_passwords( $start ) ) {
375 update_option( '_bbp_converter_step', $step + 1 );
376 update_option( '_bbp_converter_start', 0 );
377 if ( empty( $start ) ) {
378 $this->converter_output( __( 'No passwords to clear', 'bbpress' ) );
379 }
380 } else {
381 update_option( '_bbp_converter_start', $max + 1 );
382 $this->converter_output( sprintf( __( 'Delete users wordpress default passwords (%1$s - %2$s)', 'bbpress' ), $min, $max ) );
383 }
384 } else {
385 update_option( '_bbp_converter_step', $step + 1 );
386 update_option( '_bbp_converter_start', 0 );
387 }
388
389 break;
390
391 // STEP 4. Convert forums.
392 case 4 :
393 if ( $converter->convert_forums( $start ) ) {
394 update_option( '_bbp_converter_step', $step + 1 );
395 update_option( '_bbp_converter_start', 0 );
396 if ( empty( $start ) ) {
397 $this->converter_output( __( 'No forums to convert', 'bbpress' ) );
398 }
399 } else {
400 update_option( '_bbp_converter_start', $max + 1 );
401 $this->converter_output( sprintf( __( 'Converting forums (%1$s - %2$s)', 'bbpress' ), $min, $max ) );
402 }
403
404 break;
405
406 // STEP 5. Convert forum parents.
407 case 5 :
408 if ( $converter->convert_forum_parents( $start ) ) {
409 update_option( '_bbp_converter_step', $step + 1 );
410 update_option( '_bbp_converter_start', 0 );
411 if ( empty( $start ) ) {
412 $this->converter_output( __( 'No forum parents to convert', 'bbpress' ) );
413 }
414 } else {
415 update_option( '_bbp_converter_start', $max + 1 );
416 $this->converter_output( sprintf( __( 'Calculating forum hierarchy (%1$s - %2$s)', 'bbpress' ), $min, $max ) );
417 }
418
419 break;
420
421 // STEP 6. Convert topics.
422 case 6 :
423 if ( $converter->convert_topics( $start ) ) {
424 update_option( '_bbp_converter_step', $step + 1 );
425 update_option( '_bbp_converter_start', 0 );
426 if ( empty( $start ) ) {
427 $this->converter_output( __( 'No topics to convert', 'bbpress' ) );
428 }
429 } else {
430 update_option( '_bbp_converter_start', $max + 1 );
431 $this->converter_output( sprintf( __( 'Converting topics (%1$s - %2$s)', 'bbpress' ), $min, $max ) );
432 }
433
434 break;
435
436 // STEP 7. Convert tags.
437 case 7 :
438 if ( $converter->convert_tags( $start ) ) {
439 update_option( '_bbp_converter_step', $step + 1 );
440 update_option( '_bbp_converter_start', 0 );
441 if ( empty( $start ) ) {
442 $this->converter_output( __( 'No tags to convert', 'bbpress' ) );
443 }
444 } else {
445 update_option( '_bbp_converter_start', $max + 1 );
446 $this->converter_output( sprintf( __( 'Converting topic tags (%1$s - %2$s)', 'bbpress' ), $min, $max ) );
447 }
448
449 break;
450
451 // STEP 8. Convert replies.
452 case 8 :
453 if ( $converter->convert_replies( $start ) ) {
454 update_option( '_bbp_converter_step', $step + 1 );
455 update_option( '_bbp_converter_start', 0 );
456 if ( empty( $start ) ) {
457 $this->converter_output( __( 'No replies to convert', 'bbpress' ) );
458 }
459 } else {
460 update_option( '_bbp_converter_start', $max + 1 );
461 $this->converter_output( sprintf( __( 'Converting replies (%1$s - %2$s)', 'bbpress' ), $min, $max ) );
462 }
463
464 break;
465
466 default :
467 delete_option( '_bbp_converter_step' );
468 delete_option( '_bbp_converter_start' );
469 delete_option( '_bbp_converter_query' );
470
471 $this->converter_output( __( 'Conversion Complete', 'bbpress' ) );
472
473 break;
474 }
475 }
476
477 /**
478 * Create Tables for fast syncing
479 *
480 * @since bbPress (r3813)
481 */
482 public function sync_table( $drop = false ) {
483 global $wpdb;
484
485 $table_name = $wpdb->prefix . 'bbp_converter_translator';
486 if ( ! empty( $drop ) && $wpdb->get_var( "SHOW TABLES LIKE '{$table_name}'" ) == $table_name )
487 $wpdb->query( "DROP TABLE {$table_name}" );
488
489 require_once( ABSPATH . '/wp-admin/includes/upgrade.php' );
490
491 if ( !empty( $wpdb->charset ) ) {
492 $charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
493 }
494
495 if ( !empty( $wpdb->collate ) ) {
496 $charset_collate .= " COLLATE $wpdb->collate";
497 }
498
499 /** Translator ****************************************************/
500
501 $sql = "CREATE TABLE {$table_name} (
502 meta_id mediumint(8) unsigned not null auto_increment,
503 value_type varchar(25) null,
504 value_id bigint(20) unsigned not null default '0',
505 meta_key varchar(25) null,
506 meta_value varchar(25) null,
507 PRIMARY KEY (meta_id),
508 KEY value_id (value_id),
509 KEY meta_join (meta_key, meta_value) ) {$charset_collate};";
510
511 dbDelta( $sql );
512 }
513 }
514
515 /**
516 * Base class to be extended by specific individual importers
517 *
518 * @since bbPress (r3813)
519 */
520 abstract class BBP_Converter_Base {
521
522 /**
523 * @var array() This is the field mapping array to process.
524 */
525 protected $field_map = array();
526
527 /**
528 * @var object This is the connection to the wordpress datbase.
529 */
530 protected $wpdb;
531
532 /**
533 * @var object This is the connection to the other platforms database.
534 */
535 protected $opdb;
536
537 /**
538 * @var int This is the max rows to process at a time.
539 */
540 public $max_rows;
541
542 /**
543 * @var array() Map of topic to forum. It is for optimization.
544 */
545 private $map_topicid_to_forumid = array();
546
547 /**
548 * @var array() Map of from old forum ids to new forum ids. It is for optimization.
549 */
550 private $map_forumid = array();
551
552 /**
553 * @var array() Map of from old topic ids to new topic ids. It is for optimization.
554 */
555 private $map_topicid = array();
556
557 /**
558 * @var array() Map of from old user ids to new user ids. It is for optimization.
559 */
560 private $map_userid = array();
561
562 /**
563 * @var str This is the charset for your wp database.
564 */
565 public $charset;
566
567 /**
568 * @var boolean Sync table available.
569 */
570 public $sync_table = false;
571
572 /**
573 * @var str Sync table name.
574 */
575 public $sync_table_name;
576
577 /** Methods ***************************************************************/
578
579 /**
580 * This is the constructor and it connects to the platform databases.
581 */
582 public function __construct() {
583 $this->setup_globals();
584 }
585
586 private function setup_globals() {
587 global $wpdb;
588
589 /** Get database connections ******************************************/
590
591 $this->wpdb = $wpdb;
592 $this->max_rows = (int) $_POST['_bbp_converter_rows'];
593 $this->opdb = new wpdb( $_POST['_bbp_converter_db_user'], $_POST['_bbp_converter_db_pass'], $_POST['_bbp_converter_db_name'], $_POST['_bbp_converter_db_server'] );
594 $this->opdb->prefix = $_POST['_bbp_converter_db_prefix'];
595
596 /**
597 * Error Reporting
598 */
599 $this->wpdb->show_errors();
600 $this->opdb->show_errors();
601
602 /**
603 * Syncing
604 */
605 $this->sync_table_name = $this->wpdb->prefix . 'bbp_converter_translator';
606 if ( $this->wpdb->get_var( "SHOW TABLES LIKE '" . $this->sync_table_name . "'" ) == $this->sync_table_name ) {
607 $this->sync_table = true;
608 } else {
609 $this->sync_table = false;
610 }
611
612 /**
613 * Charset
614 */
615 if ( empty( $this->wpdb->charset ) ) {
616 $this->charset = 'UTF8';
617 } else {
618 $this->charset = $this->wpdb->charset;
619 }
620
621 /**
622 * Default mapping.
623 */
624
625 /** Forum Section *****************************************************/
626
627 $this->field_map[] = array(
628 'to_type' => 'forum',
629 'to_fieldname' => 'post_status',
630 'default' => 'publish'
631 );
632 $this->field_map[] = array(
633 'to_type' => 'forum',
634 'to_fieldname' => 'comment_status',
635 'default' => 'closed'
636 );
637 $this->field_map[] = array(
638 'to_type' => 'forum',
639 'to_fieldname' => 'ping_status',
640 'default' => 'closed'
641 );
642 $this->field_map[] = array(
643 'to_type' => 'forum',
644 'to_fieldname' => 'post_type',
645 'default' => 'forum'
646 );
647
648 /** Topic Section *****************************************************/
649
650 $this->field_map[] = array(
651 'to_type' => 'topic',
652 'to_fieldname' => 'post_status',
653 'default' => 'publish'
654 );
655 $this->field_map[] = array(
656 'to_type' => 'topic',
657 'to_fieldname' => 'comment_status',
658 'default' => 'closed'
659 );
660 $this->field_map[] = array(
661 'to_type' => 'topic',
662 'to_fieldname' => 'ping_status',
663 'default' => 'closed'
664 );
665 $this->field_map[] = array(
666 'to_type' => 'topic',
667 'to_fieldname' => 'post_type',
668 'default' => 'topic'
669 );
670
671 /** Post Section ******************************************************/
672
673 $this->field_map[] = array(
674 'to_type' => 'reply',
675 'to_fieldname' => 'post_status',
676 'default' => 'publish'
677 );
678 $this->field_map[] = array(
679 'to_type' => 'reply',
680 'to_fieldname' => 'comment_status',
681 'default' => 'closed'
682 );
683 $this->field_map[] = array(
684 'to_type' => 'reply',
685 'to_fieldname' => 'ping_status',
686 'default' => 'closed'
687 );
688 $this->field_map[] = array(
689 'to_type' => 'reply',
690 'to_fieldname' => 'post_type',
691 'default' => 'reply'
692 );
693
694 /** User Section ******************************************************/
695
696 $this->field_map[] = array(
697 'to_type' => 'user',
698 'to_fieldname' => 'role',
699 'default' => get_option( 'default_role' )
700 );
701 }
702
703 /**
704 * Convert Forums
705 */
706 public function convert_forums( $start = 1 ) {
707 return $this->convert_table( 'forum', $start );
708 }
709
710 /**
711 * Convert Topics / Threads
712 */
713 public function convert_topics( $start = 1 ) {
714 return $this->convert_table( 'topic', $start );
715 }
716
717 /**
718 * Convert Posts
719 */
720 public function convert_replies( $start = 1 ) {
721 return $this->convert_table( 'reply', $start );
722 }
723
724 /**
725 * Convert Users
726 */
727 public function convert_users( $start = 1 ) {
728 return $this->convert_table( 'user', $start );
729 }
730
731 /**
732 * Convert Tags
733 */
734 public function convert_tags( $start = 1 ) {
735 return $this->convert_table( 'tags', $start );
736 }
737
738 /**
739 * Convert Table
740 *
741 * @param string to type
742 * @param int Start row
743 */
744 public function convert_table( $to_type, $start ) {
745
746 // Are we usig a sync table, or postmeta?
747 if ( $this->wpdb->get_var( "SHOW TABLES LIKE '" . $this->sync_table_name . "'" ) == $this->sync_table_name ) {
748 $this->sync_table = true;
749 } else {
750 $this->sync_table = false;
751 }
752
753 // Set some defaults
754 $has_insert = false;
755 $from_tablename = '';
756 $field_list = $from_tables = $tablefield_array = array();
757
758 // Toggle Table Name based on $to_type (destination)
759 switch ( $to_type ) {
760 case 'user' :
761 $tablename = $this->wpdb->users;
762 break;
763
764 case 'tags' :
765 $tablename = '';
766 break;
767
768 default :
769 $tablename = $this->wpdb->posts;
770 }
771
772 // Get the fields from the destination table
773 if ( !empty( $tablename ) ) {
774 $tablefield_array = $this->get_fields( $tablename );
775 }
776
777 /** Step 1 ************************************************************/
778
779 // Loop through the field maps, and look for to_type matches
780 foreach ( $this->field_map as $item ) {
781
782 // Yay a match, and we have a from table, too
783 if ( ( $item['to_type'] == $to_type ) && !empty( $item['from_tablename'] ) ) {
784
785 // $from_tablename was set from a previous loop iteration
786 if ( ! empty( $from_tablename ) ) {
787
788 // Doing some joining
789 if ( !in_array( $item['from_tablename'], $from_tables ) && in_array( $item['join_tablename'], $from_tables ) ) {
790 $from_tablename .= ' ' . $item['join_type'] . ' JOIN ' . $this->opdb->prefix . $item['from_tablename'] . ' AS ' . $item['from_tablename'] . ' ' . $item['join_expression'];
791 }
792
793 // $from_tablename needs to be set
794 } else {
795 $from_tablename = $item['from_tablename'] . ' AS ' . $item['from_tablename'];
796 }
797
798 // Specific FROM expression data used
799 if ( !empty( $item['from_expression'] ) ) {
800
801 // No 'WHERE' in expression
802 if ( stripos( $from_tablename, "WHERE" ) === false ) {
803 $from_tablename .= ' ' . $item['from_expression'];
804
805 // 'WHERE' in expression, so replace with 'AND'
806 } else {
807 $from_tablename .= ' ' . str_replace( "WHERE", "AND", $item['from_expression'] );
808 }
809 }
810
811 // Add tablename and fieldname to arrays, formatted for querying
812 $from_tables[] = $item['from_tablename'];
813 $field_list[] = 'convert(' . $item['from_tablename'] . '.' . $item['from_fieldname'] . ' USING "' . $this->charset . '") AS ' . $item['from_fieldname'];
814 }
815 }
816
817 /** Step 2 ************************************************************/
818
819 // We have a $from_tablename, so we want to get some data to convert
820 if ( !empty( $from_tablename ) ) {
821
822 // Get some data from the old forums
823 $field_list = array_unique( $field_list );
824 $forum_query = 'SELECT ' . implode( ',', $field_list ) . ' FROM ' . $this->opdb->prefix . $from_tablename . ' LIMIT ' . $start . ', ' . $this->max_rows;
825 $forum_array = $this->opdb->get_results( $forum_query, ARRAY_A );
826
827 // Set this query as the last one ran
828 update_option( '_bbp_converter_query', $forum_query );
829
830 // Query returned some results
831 if ( !empty( $forum_array ) ) {
832
833 // Loop through results
834 foreach ( (array) $forum_array as $forum ) {
835
836 // Reset some defaults
837 $insert_post = $insert_postmeta = $insert_data = array();
838
839 // Loop through field map, again...
840 foreach ( $this->field_map as $row ) {
841
842 // Types matchand to_fieldname is present. This means
843 // we have some work to do here.
844 if ( ( $row['to_type'] == $to_type ) && ! is_null( $row['to_fieldname'] ) ) {
845
846 // This row has a destination that matches one of the
847 // columns in this table.
848 if ( in_array( $row['to_fieldname'], $tablefield_array ) ) {
849
850 // Allows us to set default fields.
851 if ( isset( $row['default'] ) ) {
852 $insert_post[$row['to_fieldname']] = $row['default'];
853
854 // Translates a field from the old forum.
855 } elseif ( isset( $row['callback_method'] ) ) {
856 if ( ( 'callback_userid' == $row['callback_method'] ) && empty( $_POST['_bbp_converter_convert_users'] ) ) {
857 $insert_post[$row['to_fieldname']] = $forum[$row['from_fieldname']];
858 } else {
859 $insert_post[$row['to_fieldname']] = call_user_func_array( array( $this, $row['callback_method'] ), array( $forum[$row['from_fieldname']], $forum ) );
860 }
861
862 // Maps the field from the old forum.
863 } else {
864 $insert_post[$row['to_fieldname']] = $forum[$row['from_fieldname']];
865 }
866
867 // Destination field is not empty, so we might need
868 // to do some extra work or set a default.
869 } elseif ( !empty( $row['to_fieldname'] ) ) {
870
871 // Allows us to set default fields.
872 if ( isset( $row['default'] ) ) {
873 $insert_postmeta[$row['to_fieldname']] = $row['default'];
874
875 // Translates a field from the old forum.
876 } elseif ( isset( $row['callback_method'] ) ) {
877 if ( ( $row['callback_method'] == 'callback_userid' ) && ( 0 == $_POST['_bbp_converter_convert_users'] ) ) {
878 $insert_postmeta[$row['to_fieldname']] = $forum[$row['from_fieldname']];
879 } else {
880 $insert_postmeta[$row['to_fieldname']] = call_user_func_array( array( $this, $row['callback_method'] ), array( $forum[$row['from_fieldname']], $forum ) );
881 }
882
883 // Maps the field from the old forum.
884 } else {
885 $insert_postmeta[$row['to_fieldname']] = $forum[$row['from_fieldname']];
886 }
887 }
888 }
889 }
890
891 /** Step 3 ************************************************/
892
893 // Something to insert into the destination field
894 if ( count( $insert_post ) > 0 || ( $to_type == 'tags' && count( $insert_postmeta ) > 0 ) ) {
895
896 switch ( $to_type ) {
897
898 /** New user **************************************/
899
900 case 'user':
901 if ( username_exists( $insert_post['user_login'] ) ) {
902 $insert_post['user_login'] = 'imported_' . $insert_post['user_login'];
903 }
904
905 if ( email_exists( $insert_post['user_email'] ) ) {
906 $insert_post['user_email'] = 'imported_' . $insert_post['user_email'];
907 }
908
909 $post_id = wp_insert_user( $insert_post );
910
911 if ( is_numeric( $post_id ) ) {
912
913 foreach ( $insert_postmeta as $key => $value ) {
914
915 add_user_meta( $post_id, $key, $value, true );
916
917 if ( '_id' == substr( $key, -3 ) && ( true === $this->sync_table ) ) {
918 $this->wpdb->insert( $this->sync_table_name, array( 'value_type' => 'user', 'value_id' => $post_id, 'meta_key' => $key, 'meta_value' => $value ) );
919 }
920 }
921 }
922 break;
923
924 /** New Topic-Tag *********************************/
925
926 case 'tags':
927 $post_id = wp_set_object_terms( $insert_postmeta['objectid'], $insert_postmeta['name'], 'topic-tag', true );
928 break;
929
930 /** Forum, Topic, Reply ***************************/
931
932 default:
933 $post_id = wp_insert_post( $insert_post );
934
935 if ( is_numeric( $post_id ) ) {
936
937 foreach ( $insert_postmeta as $key => $value ) {
938
939 add_post_meta( $post_id, $key, $value, true );
940
941 // Forums need to save their old ID for group forum association
942 if ( ( 'forum' == $to_type ) && ( '_bbp_forum_id' == $key ) )
943 add_post_meta( $post_id, '_bbp_old_forum_id', $value );
944
945 // Topics need an extra bit of metadata
946 // to be keyed to the new post_id
947 if ( ( 'topic' == $to_type ) && ( '_bbp_topic_id' == $key ) ) {
948
949 // Update the live topic ID
950 update_post_meta( $post_id, $key, $post_id );
951
952 // Save the old topic ID
953 add_post_meta( $post_id, '_bbp_old_topic_id', $value );
954 if ( '_id' == substr( $key, -3 ) && ( true === $this->sync_table ) ) {
955 $this->wpdb->insert( $this->sync_table_name, array( 'value_type' => 'post', 'value_id' => $post_id, 'meta_key' => '_bbp_topic_id', 'meta_value' => $post_id ) );
956 $this->wpdb->insert( $this->sync_table_name, array( 'value_type' => 'post', 'value_id' => $post_id, 'meta_key' => '_bbp_old_topic_id', 'meta_value' => $value ) );
957 }
958
959 } elseif ( '_id' == substr( $key, -3 ) && ( true === $this->sync_table ) ) {
960 $this->wpdb->insert( $this->sync_table_name, array( 'value_type' => 'post', 'value_id' => $post_id, 'meta_key' => $key, 'meta_value' => $value ) );
961 }
962 }
963 }
964 break;
965 }
966 $has_insert = true;
967 }
968 }
969 }
970 }
971
972 return ! $has_insert;
973 }
974
975 public function convert_forum_parents( $start ) {
976
977 $has_update = false;
978
979 if ( !empty( $this->sync_table ) )
980 $query = 'SELECT value_id, meta_value FROM ' . $this->sync_table_name . ' WHERE meta_key = "_bbp_forum_parent_id" AND meta_value > 0 LIMIT ' . $start . ', ' . $this->max_rows;
981 else
982 $query = 'SELECT post_id AS value_id, meta_value FROM ' . $this->wpdb->postmeta . ' WHERE meta_key = "_bbp_forum_parent_id" AND meta_value > 0 LIMIT ' . $start . ', ' . $this->max_rows;
983
984 update_option( '_bbp_converter_query', $query );
985
986 $forum_array = $this->wpdb->get_results( $query );
987
988 foreach ( (array) $forum_array as $row ) {
989 $parent_id = $this->callback_forumid( $row->meta_value );
990 $this->wpdb->query( 'UPDATE ' . $this->wpdb->posts . ' SET post_parent = "' . $parent_id . '" WHERE ID = "' . $row->value_id . '" LIMIT 1' );
991 $has_update = true;
992 }
993
994 return ! $has_update;
995 }
996
997 /**
998 * This method deletes data from the wp database.
999 */
1000 public function clean( $start ) {
1001
1002 $start = 0;
1003 $has_delete = false;
1004
1005 /** Delete bbconverter topics/forums/posts ****************************/
1006
1007 if ( true === $this->sync_table )
1008 $query = 'SELECT value_id FROM ' . $this->sync_table_name . ' INNER JOIN ' . $this->wpdb->posts . ' ON(value_id = ID) WHERE meta_key LIKE "_bbp_%" AND value_type = "post" GROUP BY value_id ORDER BY value_id DESC LIMIT ' . $this->max_rows;
1009 else
1010 $query = 'SELECT post_id AS value_id FROM ' . $this->wpdb->postmeta . ' WHERE meta_key LIKE "_bbp_%" GROUP BY post_id ORDER BY post_id DESC LIMIT ' . $this->max_rows;
1011
1012 update_option( '_bbp_converter_query', $query );
1013
1014 $posts = $this->wpdb->get_results( $query, ARRAY_A );
1015
1016 if ( isset( $posts[0] ) && ! empty( $posts[0]['value_id'] ) ) {
1017 foreach ( (array) $posts as $value ) {
1018 wp_delete_post( $value['value_id'], true );
1019 }
1020 $has_delete = true;
1021 }
1022
1023 /** Delete bbconverter users ******************************************/
1024
1025 if ( true === $this->sync_table )
1026 $query = 'SELECT value_id FROM ' . $this->sync_table_name . ' INNER JOIN ' . $this->wpdb->users . ' ON(value_id = ID) WHERE meta_key = "_bbp_user_id" AND value_type = "user" LIMIT ' . $this->max_rows;
1027 else
1028 $query = 'SELECT user_id AS value_id FROM ' . $this->wpdb->usermeta . ' WHERE meta_key = "_bbp_user_id" LIMIT ' . $this->max_rows;
1029
1030 update_option( '_bbp_converter_query', $query );
1031
1032 $users = $this->wpdb->get_results( $query, ARRAY_A );
1033
1034 if ( !empty( $users ) ) {
1035 foreach ( $users as $value ) {
1036 wp_delete_user( $value['value_id'] );
1037 }
1038 $has_delete = true;
1039 }
1040
1041 unset( $posts );
1042 unset( $users );
1043
1044 return ! $has_delete;
1045 }
1046
1047 /**
1048 * This method deletes passwords from the wp database.
1049 *
1050 * @param int Start row
1051 */
1052 public function clean_passwords( $start ) {
1053
1054 $has_delete = false;
1055
1056 /** Delete bbconverter passwords **************************************/
1057
1058 $query = 'SELECT user_id, meta_value FROM ' . $this->wpdb->usermeta . ' WHERE meta_key = "_bbp_password" LIMIT ' . $start . ', ' . $this->max_rows;
1059 update_option( '_bbp_converter_query', $query );
1060
1061 $bbconverter = $this->wpdb->get_results( $query, ARRAY_A );
1062
1063 if ( !empty( $bbconverter ) ) {
1064
1065 foreach ( $bbconverter as $value ) {
1066 if ( is_serialized( $value['meta_value'] ) ) {
1067 $this->wpdb->query( 'UPDATE ' . $this->wpdb->users . ' ' . 'SET user_pass = "" ' . 'WHERE ID = "' . $value['user_id'] . '"' );
1068 } else {
1069 $this->wpdb->query( 'UPDATE ' . $this->wpdb->users . ' ' . 'SET user_pass = "' . $value['meta_value'] . '" ' . 'WHERE ID = "' . $value['user_id'] . '"' );
1070 $this->wpdb->query( 'DELETE FROM ' . $this->wpdb->usermeta . ' WHERE meta_key = "_bbp_password" AND user_id = "' . $value['user_id'] . '"' );
1071 }
1072 }
1073 $has_delete = true;
1074 }
1075
1076 return ! $has_delete;
1077 }
1078
1079 /**
1080 * This method implements the authentication for the different forums.
1081 *
1082 * @param string Unencoded password.
1083 */
1084 abstract protected function authenticate_pass( $password, $hash );
1085
1086 /**
1087 * Info
1088 */
1089 abstract protected function info();
1090
1091 /**
1092 * This method grabs appropriate fields from the table specified
1093 *
1094 * @param string The table name to grab fields from
1095 */
1096 private function get_fields( $tablename ) {
1097 $rval = array();
1098 $field_array = $this->wpdb->get_results( 'DESCRIBE ' . $tablename, ARRAY_A );
1099
1100 foreach ( $field_array as $field ) {
1101 $rval[] = $field['Field'];
1102 }
1103
1104 if ( $tablename == $this->wpdb->users ) {
1105 $rval[] = 'role';
1106 $rval[] = 'yim';
1107 $rval[] = 'aim';
1108 $rval[] = 'jabber';
1109 }
1110 return $rval;
1111 }
1112
1113 /** Callbacks *************************************************************/
1114
1115 /**
1116 * Run password through wp_hash_password()
1117 *
1118 * @param string $username
1119 * @param string $password
1120 */
1121 public function callback_pass( $username, $password ) {
1122 $user = $this->wpdb->get_row( 'SELECT * FROM ' . $this->wpdb->users . ' WHERE user_login = "' . $username . '" AND user_pass = "" LIMIT 1' );
1123 if ( !empty( $user ) ) {
1124 $usermeta = $this->wpdb->get_row( 'SELECT * FROM ' . $this->wpdb->usermeta . ' WHERE meta_key = "_bbp_password" AND user_id = "' . $user->ID . '" LIMIT 1' );
1125
1126 if ( !empty( $usermeta ) ) {
1127 if ( $this->authenticate_pass( $password, $usermeta->meta_value ) ) {
1128 $this->wpdb->query( 'UPDATE ' . $this->wpdb->users . ' ' . 'SET user_pass = "' . wp_hash_password( $password ) . '" ' . 'WHERE ID = "' . $user->ID . '"' );
1129 $this->wpdb->query( 'DELETE FROM ' . $this->wpdb->usermeta . ' WHERE meta_key = "_bbp_password" AND user_id = "' . $user->ID . '"' );
1130 }
1131 }
1132 }
1133 }
1134
1135 /**
1136 * A mini cache system to reduce database calls to forum ID's
1137 *
1138 * @param string $field
1139 * @return string
1140 */
1141 private function callback_forumid( $field ) {
1142 if ( !isset( $this->map_forumid[$field] ) ) {
1143 if ( !empty( $this->sync_table ) ) {
1144 $row = $this->wpdb->get_row( 'SELECT value_id, meta_value FROM ' . $this->sync_table_name . ' WHERE meta_key = "_bbp_forum_id" AND meta_value = "' . $field . '" LIMIT 1' );
1145 } else {
1146 $row = $this->wpdb->get_row( 'SELECT post_id AS value_id FROM ' . $this->wpdb->postmeta . ' WHERE meta_key = "_bbp_forum_id" AND meta_value = "' . $field . '" LIMIT 1' );
1147 }
1148
1149 if ( !is_null( $row ) ) {
1150 $this->map_forumid[$field] = $row->value_id;
1151 } else {
1152 $this->map_forumid[$field] = 0;
1153 }
1154 }
1155 return $this->map_forumid[$field];
1156 }
1157
1158 /**
1159 * A mini cache system to reduce database calls to topic ID's
1160 *
1161 * @param string $field
1162 * @return string
1163 */
1164 private function callback_topicid( $field ) {
1165 if ( !isset( $this->map_topicid[$field] ) ) {
1166 if ( !empty( $this->sync_table ) ) {
1167 $row = $this->wpdb->get_row( 'SELECT value_id, meta_value FROM ' . $this->sync_table_name . ' WHERE meta_key = "_bbp_old_topic_id" AND meta_value = "' . $field . '" LIMIT 1' );
1168 } else {
1169 $row = $this->wpdb->get_row( 'SELECT post_id AS value_id FROM ' . $this->wpdb->postmeta . ' WHERE meta_key = "_bbp_old_topic_id" AND meta_value = "' . $field . '" LIMIT 1' );
1170 }
1171
1172 if ( !is_null( $row ) ) {
1173 $this->map_topicid[$field] = $row->value_id;
1174 } else {
1175 $this->map_topicid[$field] = 0;
1176 }
1177 }
1178 return $this->map_topicid[$field];
1179 }
1180
1181 /**
1182 * A mini cache system to reduce database calls to user ID's
1183 *
1184 * @param string $field
1185 * @return string
1186 */
1187 private function callback_userid( $field ) {
1188 if ( !isset( $this->map_userid[$field] ) ) {
1189 if ( !empty( $this->sync_table ) ) {
1190 $row = $this->wpdb->get_row( 'SELECT value_id, meta_value FROM ' . $this->sync_table_name . ' WHERE meta_key = "_bbp_user_id" AND meta_value = "' . $field . '" LIMIT 1' );
1191 } else {
1192 $row = $this->wpdb->get_row( 'SELECT user_id AS value_id FROM ' . $this->wpdb->usermeta . ' WHERE meta_key = "_bbp_user_id" AND meta_value = "' . $field . '" LIMIT 1' );
1193 }
1194
1195 if ( !is_null( $row ) ) {
1196 $this->map_userid[$field] = $row->value_id;
1197 } else {
1198 if ( !empty( $_POST['_bbp_converter_convert_users'] ) && ( $_POST['_bbp_converter_convert_users'] == 1 ) ) {
1199 $this->map_userid[$field] = 0;
1200 } else {
1201 $this->map_userid[$field] = $field;
1202 }
1203 }
1204 }
1205 return $this->map_userid[$field];
1206 }
1207
1208 /**
1209 * A mini cache system to reduce database calls map topics ID's to forum ID's
1210 *
1211 * @param string $field
1212 * @return string
1213 */
1214 private function callback_topicid_to_forumid( $field ) {
1215 $topicid = $this->callback_topicid( $field );
1216 if ( empty( $topicid ) ) {
1217 $this->map_topicid_to_forumid[$topicid] = 0;
1218 } elseif ( ! isset( $this->map_topicid_to_forumid[$topicid] ) ) {
1219 $row = $this->wpdb->get_row( 'SELECT post_parent FROM ' . $this->wpdb->posts . ' WHERE ID = "' . $topicid . '" LIMIT 1' );
1220
1221 if ( !is_null( $row ) ) {
1222 $this->map_topicid_to_forumid[$topicid] = $row->post_parent;
1223 } else {
1224 $this->map_topicid_to_forumid[$topicid] = 0;
1225 }
1226 }
1227
1228 return $this->map_topicid_to_forumid[$topicid];
1229 }
1230
1231 protected function callback_slug( $field ) {
1232 return sanitize_title( $field );
1233 }
1234
1235 protected function callback_negative( $field ) {
1236 if ( $field < 0 ) {
1237 return 0;
1238 } else {
1239 return $field;
1240 }
1241 }
1242
1243 protected function callback_html( $field ) {
1244 require_once( bbpress()->admin->admin_dir . 'parser.php' );
1245 $bbcode = BBCode::getInstance();
1246 return html_entity_decode( $bbcode->Parse( $field ) );
1247 }
1248
1249 protected function callback_null( $field ) {
1250 if ( is_null( $field ) ) {
1251 return '';
1252 } else {
1253 return $field;
1254 }
1255 }
1256
1257 protected function callback_datetime( $field ) {
1258 if ( is_numeric( $field ) ) {
1259 return date( 'Y-m-d H:i:s', $field );
1260 } else {
1261 return date( 'Y-m-d H:i:s', strtotime( $field ) );
1262 }
1263 }
1264 }
1265
1266 /**
1267 * This is a function that is purposely written to look like a "new" statement.
1268 * It is basically a dynamic loader that will load in the platform conversion
1269 * of your choice.
1270 *
1271 * @param string $platform Name of valid platform class.
1272 */
1273 function bbp_new_converter( $platform ) {
1274 $found = false;
1275
1276 if ( $curdir = opendir( bbpress()->admin->admin_dir . 'converters/' ) ) {
1277 while ( $file = readdir( $curdir ) ) {
1278 if ( stristr( $file, '.php' ) && stristr( $file, 'index' ) === FALSE ) {
1279 $file = preg_replace( '/.php/', '', $file );
1280 if ( $platform == $file ) {
1281 $found = true;
1282 continue;
1283 }
1284 }
1285 }
1286 closedir( $curdir );
1287 }
1288
1289 if ( true === $found ) {
1290 require_once( bbpress()->admin->admin_dir . 'converters/' . $platform . '.php' );
1291 return new $platform;
1292 } else {
1293 return null;
1294 }
1295 }
1296