PageRenderTime 61ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/bbpress/includes/admin/converter.php

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