[ Index ] |
PHP Cross Reference of BBPress |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * bbPress Converter Base Class 5 * 6 * Based on the hard work of Adam Ellis 7 * 8 * @package bbPress 9 * @subpackage Administration 10 */ 11 12 // Exit if accessed directly 13 defined( 'ABSPATH' ) || exit; 14 15 if ( ! class_exists( 'BBP_Converter_Base' ) ) : 16 /** 17 * Base class to be extended by specific individual importers 18 * 19 * @since 2.1.0 bbPress (r3813) 20 */ 21 abstract class BBP_Converter_Base { 22 23 /** 24 * @var array() This is the field mapping array to process. 25 */ 26 protected $field_map = array(); 27 28 /** 29 * @var object This is the connection to the WordPress database. 30 */ 31 protected $wpdb; 32 33 /** 34 * @var object This is the connection to the other platforms database. 35 */ 36 protected $opdb; 37 38 /** 39 * @var int Maximum number of rows to convert at 1 time. Default 100. 40 */ 41 protected $max_rows = 100; 42 43 /** 44 * @var array() Map of topic to forum. It is for optimization. 45 */ 46 protected $map_topicid_to_forumid = array(); 47 48 /** 49 * @var array() Map of from old forum ids to new forum ids. It is for optimization. 50 */ 51 protected $map_forumid = array(); 52 53 /** 54 * @var array() Map of from old topic ids to new topic ids. It is for optimization. 55 */ 56 protected $map_topicid = array(); 57 58 /** 59 * @var array() Map of from old reply_to ids to new reply_to ids. It is for optimization. 60 */ 61 protected $map_reply_to = array(); 62 63 /** 64 * @var array() Map of from old user ids to new user ids. It is for optimization. 65 */ 66 protected $map_userid = array(); 67 68 /** 69 * @var str This is the charset for your wp database. 70 */ 71 public $charset = ''; 72 73 /** 74 * @var boolean Sync table available. 75 */ 76 public $sync_table = false; 77 78 /** 79 * @var str Sync table name. 80 */ 81 public $sync_table_name = ''; 82 83 /** 84 * @var bool Whether users should be converted or not. Default false. 85 */ 86 public $convert_users = false; 87 88 /** 89 * @var bool Whether to clean up any old converter data. Default false. 90 */ 91 public $clean = false; 92 93 /** 94 * @var array Custom BBCode class properties in a key => value format 95 */ 96 public $bbcode_parser_properties = array(); 97 98 /** Methods ***************************************************************/ 99 100 /** 101 * This is the constructor and it connects to the platform databases. 102 */ 103 public function __construct() { 104 $this->init(); 105 $this->setup_globals(); 106 } 107 108 /** 109 * Initialize the converter 110 * 111 * @since 2.1.0 112 */ 113 private function init() { 114 115 /** BBCode Parse Properties *******************************************/ 116 117 // Setup smiley URL & path 118 $this->bbcode_parser_properties = array( 119 'smiley_url' => includes_url( 'images/smilies' ), 120 'smiley_dir' => '/' . WPINC . '/images/smilies' 121 ); 122 123 /** Sanitize Options **************************************************/ 124 125 $this->clean = ! empty( $_POST['_bbp_converter_clean'] ); 126 $this->convert_users = (bool) get_option( '_bbp_converter_convert_users', false ); 127 $this->halt = (bool) get_option( '_bbp_converter_halt', 0 ); 128 $this->max_rows = (int) get_option( '_bbp_converter_rows', 100 ); 129 130 /** Sanitize Connection ***********************************************/ 131 132 $db_user = get_option( '_bbp_converter_db_user', DB_USER ); 133 $db_pass = get_option( '_bbp_converter_db_pass', DB_PASSWORD ); 134 $db_name = get_option( '_bbp_converter_db_name', DB_NAME ); 135 $db_host = get_option( '_bbp_converter_db_server', DB_HOST ); 136 $db_port = get_option( '_bbp_converter_db_port', '' ); 137 $db_prefix = get_option( '_bbp_converter_db_prefix', '' ); 138 139 // Maybe add port to server 140 if ( ! empty( $db_port ) && ! empty( $db_host ) && ! strstr( $db_host, ':' ) ) { 141 $db_host = "{$db_host}:{$db_port}"; 142 } 143 144 /** Get database connections ******************************************/ 145 146 // Setup WordPress Database 147 $this->wpdb = bbp_db(); 148 149 // Setup old forum Database 150 $this->opdb = new BBP_Converter_DB( $db_user, $db_pass, $db_name, $db_host ); 151 152 // Connection failed 153 if ( ! $this->opdb->db_connect( false ) ) { 154 $error = new WP_Error( 'bbp_converter_db_connection_failed', esc_html__( 'Database connection failed.', 'bbpress' ) ); 155 wp_send_json_error( $error ); 156 } 157 158 // Maybe setup the database prefix 159 $this->opdb->prefix = $db_prefix; 160 161 /** 162 * Don't wp_die() uncontrollably 163 */ 164 $this->wpdb->show_errors( false ); 165 $this->opdb->show_errors( false ); 166 167 /** 168 * Syncing 169 */ 170 $this->sync_table_name = $this->wpdb->prefix . 'bbp_converter_translator'; 171 $this->sync_table = $this->sync_table_name === $this->wpdb->get_var( "SHOW TABLES LIKE '{$this->sync_table_name}'" ) 172 ? true 173 : false; 174 175 /** 176 * Character set 177 */ 178 $this->charset = ! empty( $this->wpdb->charset ) 179 ? $this->wpdb->charset 180 : 'UTF8'; 181 182 /** 183 * Default mapping. 184 */ 185 186 /** Forum Section *****************************************************/ 187 188 $this->field_map[] = array( 189 'to_type' => 'forum', 190 'to_fieldname' => 'post_status', 191 'default' => 'publish' 192 ); 193 $this->field_map[] = array( 194 'to_type' => 'forum', 195 'to_fieldname' => 'comment_status', 196 'default' => 'closed' 197 ); 198 $this->field_map[] = array( 199 'to_type' => 'forum', 200 'to_fieldname' => 'ping_status', 201 'default' => 'closed' 202 ); 203 $this->field_map[] = array( 204 'to_type' => 'forum', 205 'to_fieldname' => 'post_type', 206 'default' => 'forum' 207 ); 208 209 /** Topic Section *****************************************************/ 210 211 $this->field_map[] = array( 212 'to_type' => 'topic', 213 'to_fieldname' => 'post_status', 214 'default' => 'publish' 215 ); 216 $this->field_map[] = array( 217 'to_type' => 'topic', 218 'to_fieldname' => 'comment_status', 219 'default' => 'closed' 220 ); 221 $this->field_map[] = array( 222 'to_type' => 'topic', 223 'to_fieldname' => 'ping_status', 224 'default' => 'closed' 225 ); 226 $this->field_map[] = array( 227 'to_type' => 'topic', 228 'to_fieldname' => 'post_type', 229 'default' => 'topic' 230 ); 231 232 /** Post Section ******************************************************/ 233 234 $this->field_map[] = array( 235 'to_type' => 'reply', 236 'to_fieldname' => 'post_status', 237 'default' => 'publish' 238 ); 239 $this->field_map[] = array( 240 'to_type' => 'reply', 241 'to_fieldname' => 'comment_status', 242 'default' => 'closed' 243 ); 244 $this->field_map[] = array( 245 'to_type' => 'reply', 246 'to_fieldname' => 'ping_status', 247 'default' => 'closed' 248 ); 249 $this->field_map[] = array( 250 'to_type' => 'reply', 251 'to_fieldname' => 'post_type', 252 'default' => 'reply' 253 ); 254 255 /** User Section ******************************************************/ 256 257 $this->field_map[] = array( 258 'to_type' => 'user', 259 'to_fieldname' => 'role', 260 'default' => get_option( 'default_role' ) 261 ); 262 } 263 264 /** 265 * Setup global values 266 */ 267 public function setup_globals() {} 268 269 /** 270 * Convert Forums 271 */ 272 public function convert_forums( $start = 1 ) { 273 return $this->convert_table( 'forum', $start ); 274 } 275 276 /** 277 * Convert Topics / Threads 278 */ 279 public function convert_topics( $start = 1 ) { 280 return $this->convert_table( 'topic', $start ); 281 } 282 283 /** 284 * Convert Posts 285 */ 286 public function convert_replies( $start = 1 ) { 287 return $this->convert_table( 'reply', $start ); 288 } 289 290 /** 291 * Convert Users 292 */ 293 public function convert_users( $start = 1 ) { 294 return $this->convert_table( 'user', $start ); 295 } 296 297 /** 298 * Convert Topic Tags 299 */ 300 public function convert_tags( $start = 1 ) { 301 return $this->convert_table( 'tags', $start ); 302 } 303 304 /** 305 * Convert Forum Subscriptions 306 */ 307 public function convert_forum_subscriptions( $start = 1 ) { 308 return $this->convert_table( 'forum_subscriptions', $start ); 309 } 310 311 /** 312 * Convert Topic Subscriptions 313 */ 314 public function convert_topic_subscriptions( $start = 1 ) { 315 return $this->convert_table( 'topic_subscriptions', $start ); 316 } 317 318 /** 319 * Convert Favorites 320 */ 321 public function convert_favorites( $start = 1 ) { 322 return $this->convert_table( 'favorites', $start ); 323 } 324 325 /** 326 * Convert Table 327 * 328 * @param string to type 329 * @param int Start row 330 */ 331 public function convert_table( $to_type, $start ) { 332 333 // Set some defaults 334 $has_insert = false; 335 $from_tablename = ''; 336 $field_list = $from_tables = $tablefield_array = array(); 337 338 // Toggle Table Name based on $to_type (destination) 339 switch ( $to_type ) { 340 case 'user' : 341 $tablename = $this->wpdb->users; 342 break; 343 344 case 'tags' : 345 $tablename = ''; 346 break; 347 348 case 'forum_subscriptions' : 349 $tablename = $this->wpdb->postmeta; 350 break; 351 352 case 'topic_subscriptions' : 353 $tablename = $this->wpdb->postmeta; 354 break; 355 356 case 'favorites' : 357 $tablename = $this->wpdb->postmeta; 358 break; 359 360 default : 361 $tablename = $this->wpdb->posts; 362 } 363 364 // Get the fields from the destination table 365 if ( ! empty( $tablename ) ) { 366 $tablefield_array = $this->get_fields( $tablename ); 367 } 368 369 /** Step 1 ************************************************************/ 370 371 // Loop through the field maps, and look for to_type matches 372 foreach ( $this->field_map as $item ) { 373 374 // Yay a match, and we have a from table, too 375 if ( ( $item['to_type'] === $to_type ) && ! empty( $item['from_tablename'] ) ) { 376 377 // $from_tablename was set from a previous loop iteration 378 if ( ! empty( $from_tablename ) ) { 379 380 // Doing some joining 381 if ( ! in_array( $item['from_tablename'], $from_tables, true ) && in_array( $item['join_tablename'], $from_tables, true ) ) { 382 $from_tablename .= ' ' . $item['join_type'] . ' JOIN ' . $this->opdb->prefix . $item['from_tablename'] . ' AS ' . $item['from_tablename'] . ' ' . $item['join_expression']; 383 } 384 385 // $from_tablename needs to be set 386 } else { 387 $from_tablename = $item['from_tablename'] . ' AS ' . $item['from_tablename']; 388 } 389 390 // Specific FROM expression data used 391 if ( ! empty( $item['from_expression'] ) ) { 392 393 // No 'WHERE' in expression 394 if ( stripos( $from_tablename, 'WHERE' ) === false ) { 395 $from_tablename .= ' ' . $item['from_expression']; 396 397 // 'WHERE' in expression, so replace with 'AND' 398 } else { 399 $from_tablename .= ' ' . str_replace( 'WHERE', 'AND', $item['from_expression'] ); 400 } 401 } 402 403 // Add tablename and fieldname to arrays, formatted for querying 404 $from_tables[] = $item['from_tablename']; 405 $field_list[] = 'convert(' . $item['from_tablename'] . '.' . $item['from_fieldname'] . ' USING "' . $this->charset . '") AS ' . $item['from_fieldname']; 406 } 407 } 408 409 /** Step 2 ************************************************************/ 410 411 // We have a $from_tablename, so we want to get some data to convert 412 if ( ! empty( $from_tablename ) ) { 413 414 // Update rows 415 $this->count_rows_by_table( "{$this->opdb->prefix}{$from_tablename}" ); 416 417 // Get some data from the old forums 418 $field_list = array_unique( $field_list ); 419 $fields = implode( ',', $field_list ); 420 $forum_query = "SELECT {$fields} FROM {$this->opdb->prefix}{$from_tablename} LIMIT {$start}, {$this->max_rows}"; 421 422 // Set this query as the last one ran 423 $this->update_query( $forum_query ); 424 425 // Get results as an array 426 $forum_array = $this->opdb->get_results( $forum_query, ARRAY_A ); 427 428 // Query returned some results 429 if ( ! empty( $forum_array ) ) { 430 431 // Loop through results 432 foreach ( (array) $forum_array as $forum ) { 433 434 // Reset some defaults 435 $insert_post = $insert_postmeta = $insert_data = array(); 436 437 // Loop through field map, again... 438 foreach ( $this->field_map as $row ) { 439 440 // Types match and to_fieldname is present. This means 441 // we have some work to do here. 442 if ( ( $row['to_type'] === $to_type ) && isset( $row['to_fieldname'] ) ) { 443 444 // This row has a destination that matches one of the 445 // columns in this table. 446 if ( in_array( $row['to_fieldname'], $tablefield_array, true ) ) { 447 448 // Allows us to set default fields. 449 if ( isset( $row['default'] ) ) { 450 $insert_post[ $row['to_fieldname'] ] = $row['default']; 451 452 // Translates a field from the old forum. 453 } elseif ( isset( $row['callback_method'] ) ) { 454 if ( ( 'callback_userid' === $row['callback_method'] ) && ( false === $this->convert_users ) ) { 455 $insert_post[ $row['to_fieldname'] ] = $forum[ $row['from_fieldname'] ]; 456 } else { 457 $insert_post[ $row['to_fieldname'] ] = call_user_func_array( array( $this, $row['callback_method'] ), array( $forum[ $row['from_fieldname'] ], $forum ) ); 458 } 459 460 // Maps the field from the old forum. 461 } else { 462 $insert_post[ $row['to_fieldname'] ] = $forum[ $row['from_fieldname'] ]; 463 } 464 465 // Destination field is not empty, so we might need 466 // to do some extra work or set a default. 467 } elseif ( ! empty( $row['to_fieldname'] ) ) { 468 469 // Allows us to set default fields. 470 if ( isset( $row['default'] ) ) { 471 $insert_postmeta[ $row['to_fieldname'] ] = $row['default']; 472 473 // Translates a field from the old forum. 474 } elseif ( isset( $row['callback_method'] ) ) { 475 if ( ( $row['callback_method'] === 'callback_userid' ) && ( false === $this->convert_users ) ) { 476 $insert_postmeta[ $row['to_fieldname'] ] = $forum[ $row['from_fieldname'] ]; 477 } else { 478 $insert_postmeta[ $row['to_fieldname'] ] = call_user_func_array( array( $this, $row['callback_method'] ), array( $forum[ $row['from_fieldname'] ], $forum ) ); 479 } 480 481 // Maps the field from the old forum. 482 } else { 483 $insert_postmeta[ $row['to_fieldname'] ] = $forum[ $row['from_fieldname'] ]; 484 } 485 } 486 } 487 } 488 489 /** Step 3 ************************************************/ 490 491 // Something to insert into the destination field 492 if ( count( $insert_post ) > 0 || ( $to_type == 'tags' && count( $insert_postmeta ) > 0 ) ) { 493 494 switch ( $to_type ) { 495 496 /** New user **************************************/ 497 498 case 'user' : 499 if ( username_exists( $insert_post['user_login'] ) ) { 500 $insert_post['user_login'] = "imported_{$insert_post['user_login']}"; 501 } 502 503 if ( email_exists( $insert_post['user_email'] ) ) { 504 $insert_post['user_email'] = "imported_{$insert_post['user_email']}"; 505 } 506 507 if ( empty( $insert_post['user_pass'] ) ) { 508 $insert_post['user_pass'] = ''; 509 } 510 511 // Internally re-calls _exists() checks above. 512 // Also checks for existing nicename. 513 $post_id = wp_insert_user( $insert_post ); 514 515 if ( is_numeric( $post_id ) ) { 516 foreach ( $insert_postmeta as $key => $value ) { 517 add_user_meta( $post_id, $key, $value, true ); 518 519 if ( '_id' == substr( $key, -3 ) && ( true === $this->sync_table ) ) { 520 $this->wpdb->insert( $this->sync_table_name, array( 521 'value_type' => 'user', 522 'value_id' => $post_id, 523 'meta_key' => $key, 524 'meta_value' => $value 525 ) ); 526 } 527 } 528 } 529 break; 530 531 /** New Topic-Tag *********************************/ 532 533 case 'tags' : 534 $post_id = wp_set_object_terms( $insert_postmeta['objectid'], $insert_postmeta['name'], 'topic-tag', true ); 535 $term = get_term_by( 'name', $insert_postmeta['name'], 'topic-tag'); 536 if ( false !== $term ) { 537 wp_update_term( $term->term_id, 'topic-tag', array( 538 'description' => $insert_postmeta['description'], 539 'slug' => $insert_postmeta['slug'] 540 ) ); 541 } 542 break; 543 544 /** Forum Subscriptions ***************************/ 545 546 case 'forum_subscriptions' : 547 $user_id = $insert_post['user_id']; 548 $items = wp_list_pluck( $insert_postmeta, '_bbp_forum_subscriptions' ); 549 if ( is_numeric( $user_id ) && ! empty( $items ) ) { 550 foreach ( $items as $value ) { 551 552 // Maybe string with commas 553 $value = is_string( $value ) 554 ? explode( ',', $value ) 555 : (array) $value; 556 557 // Add user ID to forums subscribed users 558 foreach ( $value as $fav ) { 559 bbp_add_user_subscription( $user_id, $this->callback_forumid( $fav ) ); 560 } 561 } 562 } 563 break; 564 565 /** Subscriptions *********************************/ 566 567 case 'topic_subscriptions' : 568 $user_id = $insert_post['user_id']; 569 $items = wp_list_pluck( $insert_postmeta, '_bbp_subscriptions' ); 570 if ( is_numeric( $user_id ) && ! empty( $items ) ) { 571 foreach ( $items as $value ) { 572 573 // Maybe string with commas 574 $value = is_string( $value ) 575 ? explode( ',', $value ) 576 : (array) $value; 577 578 // Add user ID to topics subscribed users 579 foreach ( $value as $fav ) { 580 bbp_add_user_subscription( $user_id, $this->callback_topicid( $fav ) ); 581 } 582 } 583 } 584 break; 585 586 /** Favorites *************************************/ 587 588 case 'favorites' : 589 $user_id = $insert_post['user_id']; 590 $items = wp_list_pluck( $insert_postmeta, '_bbp_favorites' ); 591 if ( is_numeric( $user_id ) && ! empty( $items ) ) { 592 foreach ( $items as $value ) { 593 594 // Maybe string with commas 595 $value = is_string( $value ) 596 ? explode( ',', $value ) 597 : (array) $value; 598 599 // Add user ID to topics favorited users 600 foreach ( $value as $fav ) { 601 bbp_add_user_favorite( $user_id, $this->callback_topicid( $fav ) ); 602 } 603 } 604 } 605 break; 606 607 /** Forum, Topic, Reply ***************************/ 608 609 default : 610 $post_id = wp_insert_post( $insert_post, true ); 611 612 if ( is_numeric( $post_id ) ) { 613 foreach ( $insert_postmeta as $key => $value ) { 614 add_post_meta( $post_id, $key, $value, true ); 615 616 /** 617 * If we are using the sync_table add 618 * the meta '_id' keys to the table 619 * 620 * Forums: _bbp_old_forum_id // The old forum ID 621 * _bbp_old_forum_parent_id // The old forum parent ID 622 * 623 * Topics: _bbp_forum_id // The new forum ID 624 * _bbp_old_topic_id // The old topic ID 625 * _bbp_old_closed_status_id // The old topic open/closed status 626 * _bbp_old_sticky_status_id // The old topic sticky status 627 * 628 * Replies: _bbp_forum_id // The new forum ID 629 * _bbp_topic_id // The new topic ID 630 * _bbp_old_reply_id // The old reply ID 631 * _bbp_old_reply_to_id // The old reply to ID 632 */ 633 if ( '_id' === substr( $key, -3 ) && ( true === $this->sync_table ) ) { 634 $this->wpdb->insert( $this->sync_table_name, array( 635 'value_type' => 'post', 636 'value_id' => $post_id, 637 'meta_key' => $key, 638 'meta_value' => $value 639 ) ); 640 } 641 642 /** 643 * Replies need to save their old reply_to ID for 644 * hierarchical replies association. Later we update 645 * the _bbp_reply_to value with the new bbPress 646 * value using convert_reply_to_parents() 647 */ 648 if ( ( 'reply' === $to_type ) && ( '_bbp_old_reply_to_id' === $key ) ) { 649 add_post_meta( $post_id, '_bbp_reply_to', $value ); 650 } 651 } 652 } 653 break; 654 } 655 $has_insert = true; 656 } 657 } 658 } 659 } 660 661 return ! $has_insert; 662 } 663 664 /** 665 * This method converts old forum hierarchy to new bbPress hierarchy. 666 */ 667 public function convert_forum_parents( $start = 1 ) { 668 $has_update = false; 669 $query = ! empty( $this->sync_table ) 670 ? $this->wpdb->prepare( "SELECT value_id, meta_value FROM {$this->sync_table_name} WHERE meta_key = %s AND meta_value > 0 LIMIT {$start}, {$this->max_rows}", '_bbp_old_forum_parent_id' ) 671 : $this->wpdb->prepare( "SELECT post_id AS value_id, meta_value FROM {$this->wpdb->postmeta} WHERE meta_key = %s AND meta_value > 0 LIMIT {$start}, {$this->max_rows}", '_bbp_old_forum_parent_id' ); 672 673 foreach ( $this->count_rows_by_results( $query ) as $row ) { 674 $parent_id = $this->callback_forumid( $row->meta_value ); 675 $this->query( $this->wpdb->prepare( "UPDATE {$this->wpdb->posts} SET post_parent = %d WHERE ID = %d LIMIT 1", $parent_id, $row->value_id ) ); 676 $has_update = true; 677 } 678 679 return ! $has_update; 680 } 681 682 /** 683 * This method converts old topic stickies to new bbPress stickies. 684 * 685 * @since 2.5.0 bbPress (r5170) 686 */ 687 public function convert_topic_stickies( $start = 1 ) { 688 $has_update = false; 689 $query = ! empty( $this->sync_table ) 690 ? $this->wpdb->prepare( "SELECT value_id, meta_value FROM {$this->sync_table_name} WHERE meta_key = %s AND meta_value = %s LIMIT {$start}, {$this->max_rows}", '_bbp_old_sticky_status_id', 'sticky' ) 691 : $this->wpdb->prepare( "SELECT post_id AS value_id, meta_value FROM {$this->wpdb->postmeta} WHERE meta_key = %s AND meta_value = %s LIMIT {$start}, {$this->max_rows}", '_bbp_old_sticky_status_id', 'sticky' ); 692 693 foreach ( $this->count_rows_by_results( $query ) as $row ) { 694 bbp_stick_topic( $row->value_id ); 695 $has_update = true; 696 } 697 698 return ! $has_update; 699 } 700 701 /** 702 * This method converts old topic super stickies to new bbPress super stickies. 703 * 704 * @since 2.5.0 bbPress (r5170) 705 */ 706 public function convert_topic_super_stickies( $start = 1 ) { 707 $has_update = false; 708 $query = ! empty( $this->sync_table ) 709 ? $this->wpdb->prepare( "SELECT value_id, meta_value FROM {$this->sync_table_name} WHERE meta_key = %s AND meta_value = %s LIMIT {$start}, {$this->max_rows}", '_bbp_old_sticky_status_id', 'super-sticky' ) 710 : $this->wpdb->prepare( "SELECT post_id AS value_id, meta_value FROM {$this->wpdb->postmeta} WHERE meta_key = %s AND meta_value = %s LIMIT {$start}, {$this->max_rows}", '_bbp_old_sticky_status_id', 'super-sticky' ); 711 712 foreach ( $this->count_rows_by_results( $query ) as $row ) { 713 $super = true; 714 bbp_stick_topic( $row->value_id, $super ); 715 $has_update = true; 716 } 717 718 return ! $has_update; 719 } 720 721 /** 722 * This method converts old closed topics to bbPress closed topics. 723 * 724 * @since 2.6.0 bbPress (r5425) 725 */ 726 public function convert_topic_closed_topics( $start = 1 ) { 727 $has_update = false; 728 $query = ! empty( $this->sync_table ) 729 ? $this->wpdb->prepare( "SELECT value_id, meta_value FROM {$this->sync_table_name} WHERE meta_key = %s AND meta_value = %s LIMIT {$start}, {$this->max_rows}", '_bbp_old_closed_status_id', 'closed' ) 730 : $this->wpdb->prepare( "SELECT post_id AS value_id, meta_value FROM {$this->wpdb->postmeta} WHERE meta_key = %s AND meta_value = %s LIMIT {$start}, {$this->max_rows}", '_bbp_old_closed_status_id', 'closed' ); 731 732 foreach ( $this->count_rows_by_results( $query ) as $row ) { 733 bbp_close_topic( $row->value_id ); 734 $has_update = true; 735 } 736 737 return ! $has_update; 738 } 739 740 /** 741 * This method converts old reply_to post id to new bbPress reply_to post id. 742 * 743 * @since 2.4.0 bbPress (r5093) 744 */ 745 public function convert_reply_to_parents( $start = 1 ) { 746 $has_update = false; 747 $query = ! empty( $this->sync_table ) 748 ? $this->wpdb->prepare( "SELECT value_id, meta_value FROM {$this->sync_table_name} WHERE meta_key = %s AND meta_value > 0 LIMIT {$start}, {$this->max_rows}", '_bbp_old_reply_to_id' ) 749 : $this->wpdb->prepare( "SELECT post_id AS value_id, meta_value FROM {$this->wpdb->postmeta} WHERE meta_key = %s AND meta_value > 0 LIMIT {$start}, {$this->max_rows}", '_bbp_old_reply_to_id' ); 750 751 foreach ( $this->count_rows_by_results( $query ) as $row ) { 752 $reply_to = $this->callback_reply_to( $row->meta_value ); 753 $this->query( $this->wpdb->prepare( "UPDATE {$this->wpdb->postmeta} SET meta_value = %s WHERE meta_key = %s AND post_id = %d LIMIT 1", $reply_to, '_bbp_reply_to', $row->value_id ) ); 754 $has_update = true; 755 } 756 757 return ! $has_update; 758 } 759 760 /** 761 * This method converts anonymous topics. 762 * 763 * @since 2.6.0 bbPress (r5538) 764 */ 765 public function convert_anonymous_topic_authors( $start = 1 ) { 766 767 $has_update = false; 768 769 if ( ! empty( $this->sync_table ) ) { 770 $query = $this->wpdb->prepare( "SELECT sync_table1.value_id AS topic_id, sync_table1.meta_value AS topic_is_anonymous, sync_table2.meta_value AS topic_author 771 FROM {$this->sync_table_name} AS sync_table1 772 INNER JOIN {$this->sync_table_name} AS sync_table2 773 ON ( sync_table1.value_id = sync_table2.value_id ) 774 WHERE sync_table1.meta_value = %s 775 AND sync_table2.meta_key = %s 776 LIMIT {$start}, {$this->max_rows}", 'true', '_bbp_old_topic_author_name_id' ); 777 } else { 778 $query = $this->wpdb->prepare( "SELECT wp_postmeta1.post_id AS topic_id, wp_postmeta1.meta_value AS topic_is_anonymous, wp_postmeta2.meta_value AS topic_author 779 FROM {$this->wpdb->postmeta} AS wp_postmeta1 780 INNER JOIN {$this->wpdb->postmeta} AS wp_postmeta2 781 ON ( wp_postmeta1.post_id = wp_postmeta2.post_id ) 782 WHERE wp_postmeta1.meta_value = %s 783 AND wp_postmeta2.meta_key = %s 784 LIMIT {$start}, {$this->max_rows}", 'true', '_bbp_old_topic_author_name_id' ); 785 } 786 787 foreach ( $this->count_rows_by_results( $query ) as $row ) { 788 $anonymous_topic_author_id = 0; 789 $this->query( $this->wpdb->prepare( "UPDATE {$this->wpdb->posts} SET post_author = %d WHERE ID = %d LIMIT 1", $anonymous_topic_author_id, $row->topic_id ) ); 790 791 add_post_meta( $row->topic_id, '_bbp_anonymous_name', $row->topic_author ); 792 793 $has_update = true; 794 } 795 796 return ! $has_update; 797 } 798 799 /** 800 * This method converts anonymous replies. 801 * 802 * @since 2.6.0 bbPress (r5538) 803 */ 804 public function convert_anonymous_reply_authors( $start = 1 ) { 805 806 $has_update = false; 807 808 if ( ! empty( $this->sync_table ) ) { 809 $query = $this->wpdb->prepare( "SELECT sync_table1.value_id AS reply_id, sync_table1.meta_value AS reply_is_anonymous, sync_table2.meta_value AS reply_author 810 FROM {$this->sync_table_name} AS sync_table1 811 INNER JOIN {$this->sync_table_name} AS sync_table2 812 ON ( sync_table1.value_id = sync_table2.value_id ) 813 WHERE sync_table1.meta_value = %s 814 AND sync_table2.meta_key = %s 815 LIMIT {$start}, {$this->max_rows}", 'true', '_bbp_old_reply_author_name_id' ); 816 } else { 817 $query = $this->wpdb->prepare( "SELECT wp_postmeta1.post_id AS reply_id, wp_postmeta1.meta_value AS reply_is_anonymous, wp_postmeta2.meta_value AS reply_author 818 FROM {$this->wpdb->postmeta} AS wp_postmeta1 819 INNER JOIN {$this->wpdb->postmeta} AS wp_postmeta2 820 ON ( wp_postmeta1.post_id = wp_postmeta2.post_id ) 821 WHERE wp_postmeta1.meta_value = %s 822 AND wp_postmeta2.meta_key = %s 823 LIMIT {$start}, {$this->max_rows}", 'true', '_bbp_old_reply_author_name_id' ); 824 } 825 826 foreach ( $this->count_rows_by_results( $query ) as $row ) { 827 $anonymous_reply_author_id = 0; 828 $this->query( $this->wpdb->prepare( "UPDATE {$this->wpdb->posts} SET post_author = %d WHERE ID = %d LIMIT 1", $anonymous_reply_author_id, $row->reply_id ) ); 829 830 add_post_meta( $row->reply_id, '_bbp_anonymous_name', $row->reply_author ); 831 832 $has_update = true; 833 } 834 835 return ! $has_update; 836 } 837 838 /** 839 * This method deletes data from the wp database. 840 * 841 * @since 2.6.0 bbPress (r6456) 842 */ 843 public function clean() { 844 845 // Defaults 846 $has_delete = false; 847 848 /** Delete topics/forums/posts ****************************************/ 849 850 $esc_like = $this->wpdb->esc_like( '_bbp_' ) . '%'; 851 $query = ! empty( $this->sync_table ) 852 ? $this->wpdb->prepare( "SELECT value_id FROM {$this->sync_table_name} INNER JOIN {$this->wpdb->posts} ON(value_id = ID) WHERE meta_key LIKE %s AND value_type = %s GROUP BY value_id ORDER BY value_id DESC LIMIT {$this->max_rows}", $esc_like, 'post' ) 853 : $this->wpdb->prepare( "SELECT post_id AS value_id FROM {$this->wpdb->postmeta} WHERE meta_key LIKE %s GROUP BY post_id ORDER BY post_id DESC LIMIT {$this->max_rows}", $esc_like ); 854 855 $posts = $this->get_results( $query, ARRAY_A ); 856 857 if ( isset( $posts[0] ) && ! empty( $posts[0]['value_id'] ) ) { 858 foreach ( (array) $posts as $value ) { 859 $deleted = wp_delete_post( $value['value_id'], true ); 860 861 // Only flag if not empty or error 862 if ( ( false === $has_delete ) && ! empty( $deleted ) && ! is_wp_error( $deleted ) ) { 863 $has_delete = true; 864 } 865 } 866 } 867 868 /** Delete users ******************************************************/ 869 870 $query = ! empty( $this->sync_table ) 871 ? $this->wpdb->prepare( "SELECT value_id FROM {$this->sync_table_name} INNER JOIN {$this->wpdb->users} ON(value_id = ID) WHERE meta_key = %s AND value_type = %s LIMIT {$this->max_rows}", '_bbp_old_user_id', 'user' ) 872 : $this->wpdb->prepare( "SELECT user_id AS value_id FROM {$this->wpdb->usermeta} WHERE meta_key = %s LIMIT {$this->max_rows}", '_bbp_old_user_id' ); 873 874 $users = $this->get_results( $query, ARRAY_A ); 875 876 if ( ! empty( $users ) ) { 877 foreach ( $users as $value ) { 878 $deleted = wp_delete_user( $value['value_id'] ); 879 880 // Only flag if not empty or error 881 if ( ( false === $has_delete ) && ! empty( $deleted ) && ! is_wp_error( $deleted ) ) { 882 $has_delete = true; 883 } 884 } 885 } 886 887 unset( $posts ); 888 unset( $users ); 889 890 return ! $has_delete; 891 } 892 893 /** 894 * This method deletes passwords from the wp database. 895 * 896 * @param int Start row 897 */ 898 public function clean_passwords( $start = 1 ) { 899 $has_delete = false; 900 $query = $this->wpdb->prepare( "SELECT user_id, meta_value FROM {$this->wpdb->usermeta} WHERE meta_key = %s LIMIT {$start}, {$this->max_rows}", '_bbp_password' ); 901 $converted = $this->get_results( $query, ARRAY_A ); 902 903 if ( ! empty( $converted ) ) { 904 foreach ( $converted as $value ) { 905 if ( is_serialized( $value['meta_value'] ) ) { 906 $this->query( $this->wpdb->prepare( "UPDATE {$this->wpdb->users} SET user_pass = '' WHERE ID = %d", $value['user_id'] ) ); 907 } else { 908 $this->query( $this->wpdb->prepare( "UPDATE {$this->wpdb->users} SET user_pass = %s WHERE ID = %d", $value['meta_value'], $value['user_id'] ) ); 909 $this->query( $this->wpdb->prepare( "DELETE FROM {$this->wpdb->usermeta} WHERE meta_key = %s AND user_id = %d", '_bbp_password', $value['user_id'] ) ); 910 } 911 } 912 $has_delete = true; 913 } 914 915 return ! $has_delete; 916 } 917 918 /** 919 * This method implements the authentication for the different forums. 920 * 921 * @param string Un-encoded password. 922 */ 923 abstract protected function authenticate_pass( $password, $hash ); 924 925 /** 926 * Info 927 */ 928 abstract protected function info(); 929 930 /** 931 * This method grabs appropriate fields from the table specified 932 * 933 * @param string The table name to grab fields from 934 */ 935 private function get_fields( $tablename = '' ) { 936 $retval = array(); 937 $field_array = $this->get_results( "DESCRIBE {$tablename}", ARRAY_A ); 938 939 // Bail if no fields 940 if ( empty( $field_array ) ) { 941 return $retval; 942 } 943 944 // Add fields to array 945 foreach ( $field_array as $field ) { 946 if ( ! empty( $field['Field'] ) ) { 947 $retval[] = $field['Field']; 948 } 949 } 950 951 // Add social fields for users table 952 if ( $tablename === $this->wpdb->users ) { 953 $retval[] = 'role'; 954 $retval[] = 'yim'; 955 $retval[] = 'aim'; 956 $retval[] = 'jabber'; 957 } 958 959 return $retval; 960 } 961 962 /** Database Wrappers *****************************************************/ 963 964 /** 965 * Update the last query option and return results 966 * 967 * @param string $query 968 * @param string $output 969 */ 970 private function get_row( $query = '' ) { 971 $this->update_query( $query ); 972 973 return $this->wpdb->get_row( $query ); 974 } 975 976 /** 977 * Update the last query option and return results 978 * 979 * @param string $query 980 * @param string $output 981 */ 982 private function get_results( $query = '', $output = OBJECT ) { 983 $this->update_query( $query ); 984 985 return (array) $this->wpdb->get_results( $query, $output ); 986 } 987 988 /** 989 * Update the last query option and do a general query 990 * 991 * @param string $query 992 */ 993 private function query( $query = '' ) { 994 $this->update_query( $query ); 995 996 return $this->wpdb->query( $query ); 997 } 998 999 /** 1000 * Update the last query ran 1001 * 1002 * @since 2.6.0 bbPress (r6637) 1003 * 1004 * @param string $query The literal MySQL query 1005 * @return bool 1006 */ 1007 private function update_query( $query = '' ) { 1008 return update_option( '_bbp_converter_query', $query ); 1009 } 1010 1011 /** 1012 * Update the number of rows in the current step 1013 * 1014 * @since 2.6.0 bbPress (r6637) 1015 * 1016 * @param string $query The literal MySQL query 1017 * @return bool 1018 */ 1019 private function count_rows_by_results( $query = '' ) { 1020 $results = $this->get_results( $query ); 1021 1022 update_option( '_bbp_converter_rows_in_step', count( $results ) ); 1023 1024 return $results; 1025 } 1026 1027 /** 1028 * Update the number of rows in the current step 1029 * 1030 * @since 2.6.0 bbPress (r6637) 1031 * 1032 * @param string $table_name The literal MySQL query 1033 * @return bool 1034 */ 1035 private function count_rows_by_table( $table_name = '' ) { 1036 $count = (int) $this->opdb->get_var( "SELECT COUNT(*) FROM {$table_name}" ); 1037 1038 return update_option( '_bbp_converter_rows_in_step', $count ); 1039 } 1040 1041 /** Callbacks *************************************************************/ 1042 1043 /** 1044 * Run password through wp_hash_password() 1045 * 1046 * @param string $username 1047 * @param string $password 1048 */ 1049 public function callback_pass( $username = '', $password = '' ) { 1050 1051 // Get user – Bail if not found 1052 $user = $this->get_row( $this->wpdb->prepare( "SELECT * FROM {$this->wpdb->users} WHERE user_login = %s AND user_pass = '' LIMIT 1", $username ) ); 1053 if ( empty( $user ) ) { 1054 return; 1055 } 1056 1057 // Get usermeta – Bail if not found 1058 $usermeta = $this->get_row( $this->wpdb->prepare( "SELECT * FROM {$this->wpdb->usermeta} WHERE meta_key = %s AND user_id = %d LIMIT 1", '_bbp_password', $user->ID ) ); 1059 if ( empty( $usermeta ) ) { 1060 return; 1061 } 1062 1063 // Bail if auth fails 1064 if ( ! $this->authenticate_pass( $password, $usermeta->meta_value ) ) { 1065 return; 1066 } 1067 1068 // Hash the password 1069 $new_pass = wp_hash_password( $password ); 1070 1071 // Update 1072 $this->query( $this->wpdb->prepare( "UPDATE {$this->wpdb->users} SET user_pass = %s WHERE ID = %d", $new_pass, $user->ID ) ); 1073 1074 // Clean up 1075 unset( $new_pass ); 1076 $this->query( $this->wpdb->prepare( "DELETE FROM {$this->wpdb->usermeta} WHERE meta_key = %s AND user_id = %d", '_bbp_password', $user->ID ) ); 1077 $this->query( $this->wpdb->prepare( "DELETE FROM {$this->wpdb->usermeta} WHERE meta_key = %s AND user_id = %d", '_bbp_class', $user->ID ) ); 1078 1079 // Clean the cache for this user since their password was 1080 // upgraded from the old platform to the new. 1081 clean_user_cache( $user->ID ); 1082 } 1083 1084 /** 1085 * A mini cache system to reduce database calls to forum ID's 1086 * 1087 * @param string $field 1088 * @return string 1089 */ 1090 private function callback_forumid( $field ) { 1091 if ( ! isset( $this->map_forumid[ $field ] ) ) { 1092 $row = ! empty( $this->sync_table ) 1093 ? $this->get_row( $this->wpdb->prepare( "SELECT value_id, meta_value FROM {$this->sync_table_name} WHERE meta_key = %s AND meta_value = %s LIMIT 1", '_bbp_old_forum_id', $field ) ) 1094 : $this->get_row( $this->wpdb->prepare( "SELECT post_id AS value_id FROM {$this->wpdb->postmeta} WHERE meta_key = %s AND meta_value = %s LIMIT 1", '_bbp_old_forum_id', $field ) ); 1095 1096 $this->map_forumid[ $field ] = ! is_null( $row ) 1097 ? $row->value_id 1098 : 0; 1099 } 1100 1101 return $this->map_forumid[ $field ]; 1102 } 1103 1104 /** 1105 * A mini cache system to reduce database calls to topic ID's 1106 * 1107 * @param string $field 1108 * @return string 1109 */ 1110 private function callback_topicid( $field ) { 1111 if ( ! isset( $this->map_topicid[ $field ] ) ) { 1112 $row = ! empty( $this->sync_table ) 1113 ? $this->get_row( $this->wpdb->prepare( "SELECT value_id, meta_value FROM {$this->sync_table_name} WHERE meta_key = %s AND meta_value = %s LIMIT 1", '_bbp_old_topic_id', $field ) ) 1114 : $this->get_row( $this->wpdb->prepare( "SELECT post_id AS value_id FROM {$this->wpdb->postmeta} WHERE meta_key = %s AND meta_value = %s LIMIT 1", '_bbp_old_topic_id', $field ) ); 1115 1116 $this->map_topicid[ $field ] = ! is_null( $row ) 1117 ? $row->value_id 1118 : 0; 1119 } 1120 1121 return $this->map_topicid[ $field ]; 1122 } 1123 1124 /** 1125 * A mini cache system to reduce database calls to reply_to post id. 1126 * 1127 * @since 2.4.0 bbPress (r5093) 1128 * 1129 * @param string $field 1130 * @return string 1131 */ 1132 private function callback_reply_to( $field ) { 1133 if ( ! isset( $this->map_reply_to[ $field ] ) ) { 1134 $row = ! empty( $this->sync_table ) 1135 ? $this->get_row( $this->wpdb->prepare( "SELECT value_id, meta_value FROM {$this->sync_table_name} WHERE meta_key = %s AND meta_value = %s LIMIT 1", '_bbp_old_reply_id', $field ) ) 1136 : $this->get_row( $this->wpdb->prepare( "SELECT post_id AS value_id FROM {$this->wpdb->postmeta} WHERE meta_key = %s AND meta_value = %s LIMIT 1", '_bbp_old_reply_id', $field ) ); 1137 1138 $this->map_reply_to[ $field ] = ! is_null( $row ) 1139 ? $row->value_id 1140 : 0; 1141 } 1142 1143 return $this->map_reply_to[ $field ]; 1144 } 1145 1146 /** 1147 * A mini cache system to reduce database calls to user ID's 1148 * 1149 * @param string $field 1150 * @return string 1151 */ 1152 private function callback_userid( $field ) { 1153 if ( ! isset( $this->map_userid[ $field ] ) ) { 1154 $row = ! empty( $this->sync_table ) 1155 ? $this->get_row( $this->wpdb->prepare( "SELECT value_id, meta_value FROM {$this->sync_table_name} WHERE meta_key = %s AND meta_value = %s LIMIT 1", '_bbp_old_user_id', $field ) ) 1156 : $this->get_row( $this->wpdb->prepare( "SELECT user_id AS value_id FROM {$this->wpdb->usermeta} WHERE meta_key = %s AND meta_value = %s LIMIT 1", '_bbp_old_user_id', $field ) ); 1157 1158 if ( ! is_null( $row ) ) { 1159 $this->map_userid[ $field ] = $row->value_id; 1160 } else { 1161 $this->map_userid[ $field ] = ( true === $this->convert_users ) 1162 ? 0 1163 : $field; 1164 } 1165 } 1166 1167 return $this->map_userid[ $field ]; 1168 } 1169 1170 /** 1171 * Check if the topic or reply author is anonymous 1172 * 1173 * @since 2.6.0 bbPress (r5544) 1174 * 1175 * @param string $field 1176 * @return string 1177 */ 1178 private function callback_check_anonymous( $field ) { 1179 $field = ( $this->callback_userid( $field ) == 0 ) 1180 ? 'true' 1181 : 'false'; 1182 1183 return $field; 1184 } 1185 1186 /** 1187 * A mini cache system to reduce database calls map topics ID's to forum ID's 1188 * 1189 * @param string $field 1190 * @return string 1191 */ 1192 private function callback_topicid_to_forumid( $field ) { 1193 $topicid = $this->callback_topicid( $field ); 1194 if ( empty( $topicid ) ) { 1195 $this->map_topicid_to_forumid[ $topicid ] = 0; 1196 } elseif ( ! isset( $this->map_topicid_to_forumid[ $topicid ] ) ) { 1197 $row = $this->get_row( $this->wpdb->prepare( "SELECT post_parent FROM {$this->wpdb->posts} WHERE ID = %d LIMIT 1", $topicid ) ); 1198 1199 $this->map_topicid_to_forumid[ $topicid ] = ! is_null( $row ) 1200 ? $row->post_parent 1201 : 0; 1202 } 1203 1204 return $this->map_topicid_to_forumid[ $topicid ]; 1205 } 1206 1207 protected function callback_slug( $field ) { 1208 return sanitize_title( $field ); 1209 } 1210 1211 protected function callback_negative( $field ) { 1212 return ( $field < 0 ) 1213 ? 0 1214 : $field; 1215 } 1216 1217 protected function callback_html( $field ) { 1218 require_once bbp_admin()->admin_dir . 'parser.php'; 1219 1220 // Setup the BBCode parser 1221 $bbcode = BBCode::getInstance(); 1222 1223 // Pass BBCode properties to the parser 1224 foreach ( $this->bbcode_parser_properties as $prop => $value ) { 1225 $bbcode->{$prop} = $value; 1226 } 1227 1228 return html_entity_decode( $bbcode->Parse( $field ) ); 1229 } 1230 1231 protected function callback_null( $field ) { 1232 return is_null( $field ) 1233 ? '' 1234 : $field; 1235 } 1236 1237 protected function callback_datetime( $field ) { 1238 return is_numeric( $field ) 1239 ? date( 'Y-m-d H:i:s', $field ) 1240 : date( 'Y-m-d H:i:s', strtotime( $field ) ); 1241 } 1242 } 1243 endif;
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sat Dec 21 01:00:52 2024 | Cross-referenced by PHPXref 0.7.1 |