· 9 years ago · Jan 11, 2017, 05:36 PM
1<?php
2/**
3 * bbPress Installation class
4 *
5 * @since 0.9
6 */
7class BB_Install
8{
9 /**
10 * The file where the class was instantiated
11 *
12 * @var string
13 */
14 var $caller;
15
16 /**
17 * Whether or not we need to load some of the includes normally loaded by bb-settings.php
18 *
19 * @var boolean
20 */
21 var $load_includes = false;
22
23 /**
24 * An array of available languages to use in the installer
25 *
26 * @var array
27 */
28 var $languages = array( 'en_US' => 'en_US' );
29
30 /**
31 * The currently selected language for the installer
32 *
33 * @var string
34 */
35 var $language = 'en_US';
36
37 /**
38 * The current step in the install process
39 *
40 * @var integer
41 */
42 var $step;
43
44 /**
45 * Info about config files and their locations
46 *
47 * @var array
48 */
49 var $configs = array(
50 'writable' => false,
51 'bb-config.php' => false,
52 'config.php' => false
53 );
54
55 /**
56 * An array of the current status of each step
57 *
58 * @var array
59 */
60 var $step_status = array(
61 0 => 'incomplete',
62 1 => 'incomplete',
63 2 => 'incomplete',
64 3 => 'incomplete',
65 4 => 'incomplete'
66 );
67
68 /**
69 * An array of most strings in use, including errors
70 *
71 * @var array
72 */
73 var $strings = array();
74
75 /**
76 * The data being manipulated as we go through the forms
77 *
78 * @var array
79 */
80 var $data = array();
81
82 /**
83 * A boolean that can get flagged to stop posting of a form getting processed
84 *
85 * @var boolean
86 */
87 var $stop_process = false;
88
89 /**
90 * Keeps track of where the tabindex is up to
91 *
92 * @var integer
93 */
94 var $tabindex = 0;
95
96 /**
97 * Constructor
98 *
99 * Loads everything we might need to do the business
100 *
101 * @param string $caller The full path of the file that instantiated the class
102 * @return boolean Always returns true
103 */
104 function BB_Install( $caller )
105 {
106 $this->caller = $caller;
107
108 $this->set_initial_step();
109 $this->define_paths();
110
111 // We need to load these when bb-settings.php isn't loaded
112 if ( $this->load_includes ) {
113 require_once( BACKPRESS_PATH . 'functions.core.php' );
114 require_once( BACKPRESS_PATH . 'functions.compat.php' );
115 require_once( BACKPRESS_PATH . 'functions.formatting.php' );
116 require_once( BACKPRESS_PATH . 'functions.plugin-api.php' );
117 require_once( BACKPRESS_PATH . 'class.wp-error.php' );
118 require_once( BB_PATH . BB_INC . 'functions.bb-core.php' );
119 require_once( BB_PATH . BB_INC . 'functions.bb-meta.php' );
120 require_once( BB_PATH . BB_INC . 'class.bp-options.php' );
121 require_once( BACKPRESS_PATH . 'functions.bp-options.php' );
122 require_once( BACKPRESS_PATH . 'functions.kses.php' );
123 require_once( BB_PATH . BB_INC . 'functions.bb-l10n.php' );
124 require_once( BB_PATH . BB_INC . 'functions.bb-template.php' );
125 }
126
127 $this->get_languages();
128 $this->set_language();
129
130 if ( $this->language ) {
131 global $locale;
132 global $l10n;
133 $locale = $this->language;
134 unset( $l10n['default'] );
135
136 if ( !class_exists( 'MO' ) ) {
137 require_once( BACKPRESS_PATH . 'pomo/mo.php' );
138 }
139 }
140
141 // Load the default text localization domain. Doing this twice doesn't hurt too much.
142 bb_load_default_textdomain();
143
144 // Pull in locale data after loading text domain.
145 if ( $this->load_includes ) {
146 require_once( BB_PATH . BB_INC . 'class.bb-locale.php' );
147 }
148 global $bb_locale;
149 $bb_locale = new BB_Locale();
150
151 $this->prepare_strings();
152 $this->check_prerequisites();
153 $this->check_configs();
154
155 if ( $this->step > -1 ) {
156 $this->set_step();
157 $this->prepare_data();
158 $this->process_form();
159 }
160
161 return true;
162 }
163
164 /**
165 * Set initial step
166 *
167 * Sets the step from the post data and keeps it within range
168 *
169 * @return integer The calculated step
170 */
171 function set_initial_step()
172 {
173 // Set the step based on the $_POST value or 0
174 $this->step = $_POST['step'] ? (integer) $_POST['step'] : 0;
175
176 // Make sure the requested step is from 0-4
177 if ( 0 > $this->step || 4 < $this->step ) {
178 $this->step = 0;
179 }
180 return $this->step;
181 }
182
183 /**
184 * Prepare text strings
185 *
186 * Sets up many of the strings to be used by the class that may
187 * be later subject to change due to processing of the forms
188 */
189 function prepare_strings()
190 {
191 $this->strings = array(
192 -1 => array(
193 'title' => __( 'bbPress › Error' ),
194 'h1' => __( 'Oh dear!' ),
195 'messages' => array()
196 ),
197 0 => array(
198 'title' => sprintf( __( '%1$s › %2$s' ), __( 'bbPress installer' ), __( 'Welcome' ) ),
199 'h2' => __( 'Welcome to the bbPress installer' ),
200 'status' => '',
201 'messages' => array(),
202 'intro' => array(
203 __( 'We\'re now going to go through a few steps to get you up and running.' ),
204 __( 'Ready? Then let\'s get started!' )
205 )
206 ),
207 1 => array(
208 'title' => sprintf( __( '%1$s › %2$s' ), __( 'bbPress installer' ), __( 'Step 1' ) ),
209 'h2' => sprintf( __( '%1$s - %2$s' ), __( 'Step 1' ), __( 'Database configuration' ) ),
210 'status' => '',
211 'intro' => array(
212 __( 'In this step you need to enter your database connection details. The installer will attempt to create a file called <code>bb-config.php</code> in the root directory of your bbPress installation.' ),
213 __( 'If you\'re not sure what to put here, contact your web hosting provider.' )
214 ),
215 'messages' => array()
216 ),
217 2 => array(
218 'title' => sprintf( __( '%1$s › %2$s' ), __( 'bbPress installer' ), __( 'Step 2' ) ),
219 'h2' => sprintf( __( '%1$s - %2$s' ), __( 'Step 2' ), __( 'WordPress integration (optional)' ) ),
220 'status' => __( '« skipped' ),
221 'intro' => array(
222 __( 'bbPress can integrate login and user data seamlessly with WordPress. You can safely skip this step if you do not wish to integrate with an existing WordPress install.' )
223 ),
224 'messages' => array(),
225 'form_errors' => array()
226 ),
227 3 => array(
228 'title' => sprintf( __( '%1$s › %2$s' ), __( 'bbPress installer' ), __( 'Step 3' ) ),
229 'h2' => sprintf( __( '%1$s - %2$s' ), __( 'Step 3' ), __( 'Site settings' ) ),
230 'status' => '',
231 'intro' => array(
232 __( 'Finalize your installation by adding a name, your first user and your first forum.' )
233 ),
234 'messages' => array(),
235 'form_errors' => array(),
236 'scripts' => array()
237 ),
238 4 => array(
239 'title' => sprintf( __( '%1$s › %2$s' ), __( 'bbPress installer' ), __( 'Finished' ) ),
240 'h2' => __( 'Installation complete!' ),
241 'messages' => array()
242 )
243 );
244 }
245
246 /**
247 * Check installation pre-requisites
248 *
249 * Checks for appropriate PHP extensions.
250 *
251 * @return boolean False if any pre-requisites are not met, otherwise true
252 */
253 function check_prerequisites()
254 {
255 // BPDB wants the MySQL extension - this is also checked when BPDB is initialised so may be a bit redundant here
256 if ( !extension_loaded( 'mysql' ) ) {
257 $this->strings[-1]['messages']['error'][] = __( 'Your PHP installation appears to be missing the MySQL extension which is required for bbPress' );
258 $this->step = -1;
259 }
260
261 if ( defined( 'BB_IS_WP_LOADED' ) && BB_IS_WP_LOADED ) {
262 $this->strings[-1]['messages']['error'][] = __( 'Please complete your installation before attempting to include WordPress within bbPress' );
263 $this->step = -1;
264 }
265
266 if ( $this->step === -1 ) {
267 return false;
268 }
269
270 return true;
271 }
272
273 /**
274 * Define path constants
275 *
276 * Sets some bbPress constants if they are not otherwise available based
277 * on the classes initiating file path.
278 *
279 * @return boolean False if no path was supplied, otherwise always true
280 */
281 function define_paths()
282 {
283 if ( !$this->caller ) {
284 return false;
285 }
286
287 if ( !defined( 'BACKPRESS_PATH' ) ) {
288 // Define BACKPRESS_PATH
289 // Tell us to load includes because bb-settings.php was not loaded
290 // bb-settings.php is generally not loaded on steps -1, 0 and 1 but
291 // there are exceptions, so this is safer than just reading the step
292 $this->load_includes = true;
293 define( 'BACKPRESS_PATH', BB_PATH . BB_INC . 'backpress/' );
294 }
295
296 // Define the language file directory
297 if ( !defined( 'BB_LANG_DIR' ) ) {
298 define( 'BB_LANG_DIR', BB_PATH . 'my-languages/' );
299 }
300
301 return true;
302 }
303
304 /**
305 * Gets an array of available languages form the language directory
306 *
307 * @return array
308 */
309 function get_languages()
310 {
311 foreach ( bb_glob( BB_LANG_DIR . '*.mo' ) as $language ) {
312 if ( substr( $language, 0, 18 ) === 'continents-cities-' ) {
313 continue;
314 }
315 $language = str_replace( '.mo', '', basename( $language ) );
316 $this->languages[$language] = $language;
317 }
318
319 return $this->languages;
320 }
321
322 /**
323 * Returns a language selector for switching installation languages
324 *
325 * @return string|false Either the html for the selector or false if there are no languages
326 */
327 function get_language_selector()
328 {
329 // Don't provide a selection if there is only english
330 if ( 2 > count( $this->languages ) ) {
331 return false;
332 }
333
334 $r = '<script type="text/javascript" charset="utf-8">' . "\n";
335 $r .= "\t" . 'function changeLanguage(selectObj) {' . "\n";
336 $r .= "\t\t" . 'var selectedLanguage = selectObj.options[selectObj.selectedIndex].value;' . "\n";
337 $r .= "\t\t" . 'location.href = "install.php?language=" + selectedLanguage;' . "\n";
338 $r .= "\t" . '}' . "\n";
339 $r .= '</script>' . "\n";
340 //$r .= '<form id="lang" action="install.php">' . "\n";
341 $r .= "\t" . '<fieldset>' . "\n";
342 $r .= "\t\t" . '<label class="has-note has-label for-select">' . "\n";
343 $r .= "\t\t\t" . '<span>' . __( 'Installation language' ) . '</span>' . "\n";
344 $this->tabindex++;
345 $r .= "\t\t\t" . '<select class="has-note" onchange="changeLanguage(this);" name="language" tabindex="' . $this->tabindex . '">' . "\n";
346 foreach ( $this->languages as $language ) {
347 $selected = '';
348 if ( $language == $this->language ) {
349 $selected = ' selected="selected"';
350 }
351 $r .= "\t\t\t\t" . '<option value="' . $language . '"' . $selected . '>' . $language . '</option>' . "\n";
352 }
353 $r .= "\t\t\t" . '</select>' . "\n";
354 $r .= "\t\t\t" . '<a class="note-toggle" href="javascript:void(0);" onclick="toggleNote(\'note-language\');">?</a>' . "\n";
355 $r .= "\t\t\t" . '<p id="note-language" class="note" style="display:none">' . __( 'Sets the language to be used during the installation process only.' ) . '</p>' . "\n";
356 $r .= "\t\t\t" . '<div class="clear"></div>' . "\n";
357 $r .= "\t\t" . '</label>' . "\n";
358 $r .= "\t" . '</fieldset>' . "\n";
359 //$r .= '</form>' . "\n";
360
361 echo $r;
362 }
363
364 /**
365 * Sets the current installation language
366 *
367 * @return string The currently set language
368 */
369 function set_language()
370 {
371 if ( isset( $_COOKIE['bb_install_language'] ) && 1 < count( $this->languages ) ) {
372 if ( in_array( $_COOKIE['bb_install_language'], $this->languages ) ) {
373 $this->language = $_COOKIE['bb_install_language'];
374 }
375 }
376
377 $language_requested = false;
378 if ( isset( $_POST['language'] ) && $_POST['language'] ) {
379 $language_requested = (string) $_POST['language'];
380 } elseif ( isset( $_GET['language'] ) && $_GET['language'] ) {
381 $language_requested = (string) $_GET['language'];
382 }
383
384 if ( $language_requested && 1 < count( $this->languages ) ) {
385 if ( in_array( $language_requested, $this->languages ) ) {
386 $this->language = $language_requested;
387 setcookie( 'bb_install_language', $this->language );
388 }
389 }
390
391 if ( !$this->language || 'en_US' === $this->language ) {
392 $this->language = 'en_US';
393 setcookie( 'bb_install_language', ' ', time() - 31536000 );
394 }
395
396 return $this->language;
397 }
398
399 /**
400 * Tests whether database tables exist
401 *
402 * Checks for the existence of the forum table in the database that is
403 * currently configured.
404 *
405 * @return boolean False if the table isn't found, otherwise true
406 */
407 function database_tables_are_installed()
408 {
409 global $bbdb;
410 $bbdb->suppress_errors();
411 $installed = (boolean) $bbdb->get_results( 'DESCRIBE `' . $bbdb->forums . '`;', ARRAY_A );
412 $bbdb->suppress_errors( false );
413 return $installed;
414 }
415
416 /**
417 * Tests whether an option is set in the database
418 *
419 * @return boolean False if the option isn't set, otherwise true
420 */
421 function bb_options_are_set()
422 {
423 if ( $this->load_includes ) {
424 return false;
425 }
426 if ( !bb_get_option( 'uri' ) ) {
427 return false;
428 }
429 return true;
430 }
431
432 /**
433 * Tests whether bbPress is installed
434 *
435 * @return boolean False if bbPress isn't installed, otherwise true
436 */
437 function is_installed()
438 {
439 if ( !$this->database_tables_are_installed() ) {
440 return false;
441 }
442 if ( !$this->bb_options_are_set() ) {
443 return false;
444 }
445 return true;
446 }
447
448 /**
449 * Checks for configs and sets variables describing current install state
450 *
451 * @return integer The current step we should be on based on the existence of the config file
452 */
453 function check_configs()
454 {
455 // Check for a config file
456 if ( file_exists( BB_PATH . 'bb-config.php' ) ) {
457 $this->configs['bb-config.php'] = BB_PATH . 'bb-config.php';
458 } elseif ( file_exists( dirname( BB_PATH ) . '/bb-config.php' ) ) {
459 $this->configs['bb-config.php'] = dirname( BB_PATH ) . '/bb-config.php';
460 }
461
462 // Check for an old config file
463 if ( file_exists( BB_PATH . 'config.php' ) ) {
464 $this->configs['config.php'] = BB_PATH . 'config.php';
465 } elseif ( file_exists( dirname( BB_PATH ) . '/config.php' ) ) {
466 $this->configs['config.php'] = dirname( BB_PATH ) . '/config.php';
467 }
468
469 if ( $this->configs['config.php'] && !$this->configs['bb-config.php'] ) {
470 // There is an old school config file
471 // Step -1 is where we send fatal errors from any screen
472 $this->strings[-1]['messages']['error'][] = __( 'An old <code>config.php</code> file has been detected in your installation. You should remove it and run the <a href="install.php">installer</a> again. You can use the same database connection details if you do.' );
473 $this->step = -1;
474 return $this->step;
475 }
476
477 // Check if bbPress is already installed
478 // Is there a current config file
479 if ( $this->configs['bb-config.php'] ) {
480
481 // Is it valid
482 if ( $this->validate_current_config() ) {
483 // Step 1 is complete
484 $this->step_status[1] = 'complete';
485 $this->strings[1]['status'] = __( '« completed' );
486
487 // On step 1 we want to report that the file is good and allow the user to continue
488 if ( $this->step === 1 ) {
489 // Stop form processing if it is posted
490 $this->stop_process = true;
491
492 // Display a nice message saying the config file exists
493 $this->strings[1]['messages']['message'][] = __( 'A valid configuration file was found at <code>bb-config.php</code><br />You may continue to the next step.' );
494 return $this->step;
495 }
496 } else {
497 // Invalid config files on any step cause us to exit to step 0
498 $this->strings[-1]['messages']['error'][] = __( 'An invalid configuration file was found at <code>bb-config.php</code><br />The installation cannot continue.' );
499 $this->strings[-1]['messages'][0][] = __( 'Usually this is caused by one of the database connection settings being incorrect. Make sure that the specified user has appropriate permission to access the database.' );
500 $this->step = -1;
501 }
502
503 // If we have made it this far, then we can check if the database tables exist and have content
504 if ( $this->is_installed() ) {
505 // The database is installed
506 // The following standard functions should be available
507 if ( bb_get_option( 'bb_db_version' ) > bb_get_option_from_db( 'bb_db_version' ) ) {
508 // The database needs upgrading
509 $this->strings[-1]['messages'][0][] = __( 'bbPress is already installed, but appears to require an upgrade.' );
510 } else {
511 $this->strings[-1]['messages'][0][] = __( 'bbPress is already installed.' );
512 }
513 $this->strings[-1]['messages'][0][] = sprintf(
514 __( 'Perhaps you meant to run the <a href="%s">upgrade script</a> instead?' ),
515 bb_get_uri( 'bb-admin/upgrade.php', null, BB_URI_CONTEXT_A_HREF + BB_URI_CONTEXT_BB_ADMIN )
516 );
517 $this->step = -1;
518 }
519
520 } else {
521
522 if ( 2 > $this->step && !file_exists( BB_PATH . 'bb-config-sample.php' ) ) {
523 // There is no sample config file
524 $this->strings[0]['messages']['error'][] = __( 'I could not find the file <code>bb-config-sample.php</code><br />Please upload it to the root directory of your bbPress installation.' );
525 $this->step = 0;
526 }
527
528 if ( 1 !== $this->step ) {
529 // There is no config file, go back to the beginning
530 $this->strings[0]['messages']['message'][] = __( 'There doesn\'t seem to be a <code>bb-config.php</code> file. This usually means that you want to install bbPress.' );
531 $this->step = 0;
532 }
533
534 }
535
536 // Check if the config file path is writable
537 if ( file_exists( $this->configs['bb-config.php'] ) ) {
538 if ( is_writable( $this->configs['bb-config.php'] ) ) {
539 $this->configs['writable'] = true;
540 }
541 } elseif ( is_writable( BB_PATH ) ) {
542 $this->configs['writable'] = true;
543 }
544
545 return $this->step;
546 }
547
548 /**
549 * Determines if the current config is valid
550 *
551 * @return boolean False if the config is bad, otherwise true
552 */
553 function validate_current_config()
554 {
555 // If we are validating then the config file has already been included
556 // So we can just check for valid constants
557
558 // The required constants for a valid config file
559 $required_constants = array(
560 'BBDB_NAME',
561 'BBDB_USER',
562 'BBDB_PASSWORD',
563 'BBDB_HOST'
564 );
565
566 // Check the required constants are defined
567 foreach ( $required_constants as $required_constant ) {
568 if ( !defined( $required_constant ) ) {
569 return false;
570 }
571 }
572
573 global $bb_table_prefix;
574
575 if ( !isset( $bb_table_prefix ) ) {
576 return false;
577 }
578
579 // Everthing is OK so far, validate the connection as well
580 return $this->validate_current_database();
581 }
582
583 /**
584 * Validates the current database settings
585 *
586 * @return boolean False if the current database isn't valid, otherwise true
587 */
588 function validate_current_database()
589 {
590 global $bbdb;
591 $db = $bbdb->db_connect( "SELECT * FROM $bbdb->forums LIMIT 1" );
592
593 if ( !is_resource( $db ) ) {
594 return false;
595 }
596
597 return true;
598 }
599
600 /**
601 * Sets up default values for input data as well as labels and notes
602 *
603 * @return void
604 */
605 function prepare_data()
606 {
607 /**
608 * Should be exactly the same as the default value of the KEYS in bb-config-sample.php
609 * @since 1.0
610 */
611 $_bb_default_secret_key = 'put your unique phrase here';
612
613 $this->data = array(
614 0 => array(
615 'form' => array(
616 'forward_0_0' => array(
617 'value' => __( 'Go to step 1' )
618 )
619 )
620 ),
621 1 => array(
622 'form' => array(
623 'bbdb_name' => array(
624 'value' => '',
625 'label' => __( 'Database name' ),
626 'note' => __( 'The name of the database in which you want to run bbPress.' )
627 ),
628 'bbdb_user' => array(
629 'value' => '',
630 'label' => __( 'Database user' ),
631 'note' => __( 'The database user that has access to that database.' ),
632 'autocomplete' => 'off'
633 ),
634 'bbdb_password' => array(
635 'type' => 'password',
636 'value' => '',
637 'label' => __( 'Database password' ),
638 'note' => __( 'That database user\'s password.' ),
639 'autocomplete' => 'off'
640 ),
641 'bb_lang' => array(
642 'value' => '',
643 'label' => __( 'Language' ),
644 'note' => sprintf( __( 'The language which bbPress will be presented in once installed. Your current installer language choice (%s) will be the same for the rest of the install process.' ), $this->language )
645 ),
646 'toggle_1' => array(
647 'value' => 0,
648 'label' => __( 'Show advanced settings' ),
649 'note' => __( 'These settings usually do not have to be changed.' ),
650 'checked' => '',
651 'display' => 'none'
652 ),
653 'bbdb_host' => array(
654 'value' => 'localhost',
655 'label' => __( 'Database host' ),
656 'note' => __( 'The domain name or IP address of the server where the database is located. If the database is on the same server as the web site, then this probably should remain <strong>localhost</strong>.' ),
657 'prerequisite' => 'toggle_1'
658 ),
659 'bbdb_charset' => array(
660 'value' => 'utf8',
661 'label' => __( 'Database character set' ),
662 'note' => __( 'The best choice is <strong>utf8</strong>, but you will need to match the character set which you created the database with.' ),
663 'prerequisite' => 'toggle_1'
664 ),
665 'bbdb_collate' => array(
666 'value' => '',
667 'label' => __( 'Database character collation' ),
668 'note' => __( 'The character collation value set when the database was created.' ),
669 'prerequisite' => 'toggle_1'
670 ),
671 /*
672 'bb_auth_key' => array(
673 'value' => $_bb_default_secret_key,
674 'label' => __( 'bbPress "auth" cookie key' ),
675 'note' => __( 'This should be a unique and secret phrase, it will be used to make your bbPress "auth" cookie unique and harder for an attacker to decipher.' ),
676 'prerequisite' => 'toggle_1'
677 ),
678 'bb_secure_auth_key' => array(
679 'value' => $_bb_default_secret_key,
680 'label' => __( 'bbPress "secure auth" cookie key' ),
681 'note' => __( 'This should be a unique and secret phrase, it will be used to make your bbPress "secure auth" cookie unique and harder for an attacker to decipher.' ),
682 'prerequisite' => 'toggle_1'
683 ),
684 'bb_logged_in_key' => array(
685 'value' => $_bb_default_secret_key,
686 'label' => __( 'bbPress "logged in" cookie key' ),
687 'note' => __( 'This should be a unique and secret phrase, it will be used to make your bbPress "logged in" cookie unique and harder for an attacker to decipher.' ),
688 'prerequisite' => 'toggle_1'
689 ),
690 'bb_nonce_key' => array(
691 'value' => $_bb_default_secret_key,
692 'label' => __( 'bbPress "nonce" key' ),
693 'note' => __( 'This should be a unique and secret phrase, it will be used to make form submission harder for an attacker to spoof.' ),
694 'prerequisite' => 'toggle_1'
695 ),
696 */
697 'bb_table_prefix' => array(
698 'value' => 'bb_',
699 'label' => __( 'Table name prefix' ),
700 'note' => __( 'If you are running multiple bbPress sites in a single database, you will probably want to change this.' ),
701 'prerequisite' => 'toggle_1'
702 ),
703 'config' => array(
704 'value' => '',
705 'label' => __( 'Contents for <code>bb-config.php</code>' ),
706 'note' => __( 'Once you have created the configuration file, you can check for it below.' )
707 ),
708 'forward_1_0' => array(
709 'value' => __( 'Save database configuration file' )
710 ),
711 'back_1_1' => array(
712 'value' => __( '« Go back' )
713 ),
714 'forward_1_1' => array(
715 'value' => __( 'Check for configuration file' )
716 ),
717 'forward_1_2' => array(
718 'value' => __( 'Go to step 2' )
719 )
720 )
721 ),
722
723 2 => array(
724 'form' => array(
725 'toggle_2_0' => array(
726 'value' => 0,
727 'label' => __( 'Add integration settings' ),
728 'note' => __( 'If you want to integrate bbPress with an existing WordPress site.' ),
729 'checked' => '',
730 'display' => 'none',
731 'toggle_value' => array(
732 'target' => 'forward_2_0',
733 'off_value' => __( 'Skip WordPress integration' ),
734 'on_value' => __( 'Save WordPress integration settings' )
735 )
736 ),
737 'toggle_2_1' => array(
738 'value' => 0,
739 'label' => __( 'Add cookie integration settings' ),
740 'note' => __( 'If you want to allow shared logins with an existing WordPress site.' ),
741 'checked' => '',
742 'display' => 'none',
743 'prerequisite' => 'toggle_2_0'
744 ),
745 'wp_siteurl' => array(
746 'value' => '',
747 'label' => __( 'WordPress address (URL)' ),
748 'note' => __( 'This value should exactly match the <strong>WordPress address (URL)</strong> setting in your WordPress general settings.' ),
749 'prerequisite' => 'toggle_2_1'
750 ),
751 'wp_home' => array(
752 'value' => '',
753 'label' => __( 'Blog address (URL)' ),
754 'note' => __( 'This value should exactly match the <strong>Blog address (URL)</strong> setting in your WordPress general settings.' ),
755 'prerequisite' => 'toggle_2_1'
756 ),
757 'wp_auth_key' => array(
758 'value' => '',
759 'label' => __( 'WordPress "auth" cookie key' ),
760 'note' => __( 'This value must match the value of the constant named "AUTH_KEY" in your WordPress <code>wp-config.php</code> file. This will replace the bbPress "auth" cookie key set in the first step.' ),
761 'prerequisite' => 'toggle_2_1',
762 'autocomplete' => 'off'
763 ),
764 'wp_auth_salt' => array(
765 'value' => '',
766 'label' => __( 'WordPress "auth" cookie salt' ),
767 'note' => __( 'This must match the value of the WordPress setting named "auth_salt" in your WordPress site. Look for the option labeled "auth_salt" in <a href="#" id="getAuthSaltOption" onclick="window.open(this.href); return false;">this WordPress admin page</a>. If you leave this blank the installer will try to fetch the value based on your WordPress database integration settings.' ),
768 'prerequisite' => 'toggle_2_1',
769 'autocomplete' => 'off'
770 ),
771 'wp_secure_auth_key' => array(
772 'value' => '',
773 'label' => __( 'WordPress "secure auth" cookie key' ),
774 'note' => __( 'This value must match the value of the constant named "SECURE_AUTH_KEY" in your WordPress <code>wp-config.php</code> file. This will replace the bbPress "secure auth" cookie key set in the first step.' ),
775 'prerequisite' => 'toggle_2_1',
776 'autocomplete' => 'off'
777 ),
778 'wp_secure_auth_salt' => array(
779 'value' => '',
780 'label' => __( 'WordPress "secure auth" cookie salt' ),
781 'note' => __( 'This must match the value of the WordPress setting named "secure_auth_salt" in your WordPress site. Look for the option labeled "secure_auth_salt" in <a href="#" id="getSecureAuthSaltOption" onclick="window.open(this.href); return false;">this WordPress admin page</a>. If you leave this blank the installer will try to fetch the value based on your WordPress database integration settings. Sometimes this value is not set in WordPress, in that case you can leave this setting blank as well.' ),
782 'prerequisite' => 'toggle_2_1',
783 'autocomplete' => 'off'
784 ),
785 'wp_logged_in_key' => array(
786 'value' => '',
787 'label' => __( 'WordPress "logged in" cookie key' ),
788 'note' => __( 'This value must match the value of the constant named "LOGGED_IN_KEY" in your WordPress <code>wp-config.php</code> file. This will replace the bbPress "logged in" cookie key set in the first step.' ),
789 'prerequisite' => 'toggle_2_1',
790 'autocomplete' => 'off'
791 ),
792 'wp_logged_in_salt' => array(
793 'value' => '',
794 'label' => __( 'WordPress "logged in" cookie salt' ),
795 'note' => __( 'This must match the value of the WordPress setting named "logged_in_salt" in your WordPress site. Look for the option labeled "logged_in_salt" in <a href="#" id="getLoggedInSaltOption" onclick="window.open(this.href); return false;">this WordPress admin page</a>. If you leave this blank the installer will try to fetch the value based on your WordPress database integration settings.' ),
796 'prerequisite' => 'toggle_2_1',
797 'autocomplete' => 'off'
798 ),
799 'toggle_2_2' => array(
800 'value' => 0,
801 'label' => __( 'Add user database integration settings' ),
802 'note' => __( 'If you want to share user data with an existing WordPress site.' ),
803 'checked' => '',
804 'display' => 'none',
805 'prerequisite' => 'toggle_2_0'
806 ),
807 'wp_table_prefix' => array(
808 'value' => 'wp_',
809 'default_value' => '', // Used when setting is ignored
810 'label' => __( 'User database table prefix' ),
811 'note' => __( 'If your bbPress and WordPress sites share the same database, then this is the same value as <code>$table_prefix</code> in your WordPress <code>wp-config.php</code> file. It is usually <strong>wp_</strong>.' ),
812 'prerequisite' => 'toggle_2_2'
813 ),
814 'wordpress_mu_primary_blog_id' => array(
815 'value' => '',
816 'default_value' => '',
817 'label' => __( 'WordPress MU primary blog ID' ),
818 'note' => __( 'If you are integrating with a WordPress MU site you need to specify the primary blog ID for that site. It is usually <strong>1</strong>. You should probably leave this blank if you are integrating with a standard WordPress site' ),
819 'prerequisite' => 'toggle_2_2'
820 ),
821 'toggle_2_3' => array(
822 'value' => 0,
823 'label' => __( 'Show advanced database settings' ),
824 'note' => __( 'If your bbPress and WordPress site do not share the same database, then you will need to add advanced settings.' ),
825 'checked' => '',
826 'display' => 'none',
827 'prerequisite' => 'toggle_2_2'
828 ),
829 'user_bbdb_name' => array(
830 'value' => '',
831 'label' => __( 'User database name' ),
832 'note' => __( 'The name of the database in which your user tables reside.' ),
833 'prerequisite' => 'toggle_2_3'
834 ),
835 'user_bbdb_user' => array(
836 'value' => '',
837 'label' => __( 'User database user' ),
838 'note' => __( 'The database user that has access to that database.' ),
839 'prerequisite' => 'toggle_2_3',
840 'autocomplete' => 'off'
841 ),
842 'user_bbdb_password' => array(
843 'type' => 'password',
844 'value' => '',
845 'label' => __( 'User database password' ),
846 'note' => __( 'That database user\'s password.' ),
847 'prerequisite' => 'toggle_2_3',
848 'autocomplete' => 'off'
849 ),
850 'user_bbdb_host' => array(
851 'value' => '',
852 'label' => __( 'User database host' ),
853 'note' => __( 'The domain name or IP address of the server where the database is located. If the database is on the same server as the web site, then this probably should be <strong>localhost</strong>.' ),
854 'prerequisite' => 'toggle_2_3'
855 ),
856 'user_bbdb_charset' => array(
857 'value' => '',
858 'label' => __( 'User database character set' ),
859 'note' => __( 'The best choice is <strong>utf8</strong>, but you will need to match the character set which you created the database with.' ),
860 'prerequisite' => 'toggle_2_3'
861 ),
862 'user_bbdb_collate' => array(
863 'value' => '',
864 'label' => __( 'User database character collation' ),
865 'note' => __( 'The character collation value set when the user database was created.' ),
866 'prerequisite' => 'toggle_2_3'
867 ),
868 'custom_user_table' => array(
869 'value' => '',
870 'label' => __( 'User database "user" table' ),
871 'note' => __( 'The complete table name, including any prefix.' ),
872 'prerequisite' => 'toggle_2_3'
873 ),
874 'custom_user_meta_table' => array(
875 'value' => '',
876 'label' => __( 'User database "user meta" table' ),
877 'note' => __( 'The complete table name, including any prefix.' ),
878 'prerequisite' => 'toggle_2_3'
879 ),
880 'forward_2_0' => array(
881 'value' => __( 'Skip WordPress integration' )
882 ),
883 'back_2_1' => array(
884 'value' => __( '« Go back' )
885 ),
886 'forward_2_1' => array(
887 'value' => __( 'Go to step 3' )
888 )
889 )
890 ),
891
892 3 => array(
893 'form' => array(
894 'name' => array(
895 'value' => '',
896 'label' => __( 'Site name' ),
897 'note' => __( 'This is what you are going to call your bbPress site.' )
898 ),
899 'uri' => array(
900 'value' => $this->guess_uri(),
901 'label' => __( 'Site address (URL)' ),
902 'note' => __( 'We have attempted to guess this; it\'s usually correct, but change it here if you wish.' )
903 ),
904 'keymaster_user_login' => array(
905 'value' => '',
906 'maxlength' => 60,
907 'label' => __( '"Key Master" Username' ),
908 'note' => __( 'This is the user login for the initial bbPress administrator (known as a "Key Master").' ),
909 'autocomplete' => 'off'
910 ),
911 'keymaster_user_email' => array(
912 'value' => '',
913 'maxlength' => 100,
914 'label' => __( '"Key Master" Email address' ),
915 'note' => __( 'The login details will be emailed to this address.' ),
916 'autocomplete' => 'off'
917 ),
918 'keymaster_user_type' => array(
919 'value' => 'new'
920 ),
921 'forum_name' => array(
922 'value' => '',
923 'maxlength' => 150,
924 'label' => __( 'First forum name' ),
925 'note' => __( 'This can be changed after installation, so don\'t worry about it too much.' )
926 ),
927 'forward_3_0' => array(
928 'value' => __( 'Save site settings' )
929 ),
930 'back_3_1' => array(
931 'value' => __( '« Go back' )
932 ),
933 'forward_3_1' => array(
934 'value' => __( 'Complete the installation' )
935 )
936 )
937 ),
938
939 4 => array(
940 'form' => array(
941 'toggle_4' => array(
942 'value' => 0,
943 'label' => __( 'Show installation messages' )
944 ),
945 'error_log' => array(
946 'value' => '',
947 'label' => __( 'Installation errors' )
948 ),
949 'installation_log' => array(
950 'value' => '',
951 'label' => __( 'Installation log' )
952 )
953 )
954 )
955 );
956 }
957
958 /**
959 * Guesses the final installed URI based on the location of the install script
960 *
961 * @return string The guessed URI
962 */
963 function guess_uri()
964 {
965 global $bb;
966
967 if ( $bb->uri ) {
968 $uri = $bb->uri;
969 } else {
970 $schema = 'http://';
971 if ( isset( $_SERVER['HTTPS'] ) && strtolower( $_SERVER['HTTPS'] ) == 'on' ) {
972 $schema = 'https://';
973 }
974 $uri = preg_replace( '|/bb-admin/.*|i', '/', $schema . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
975 }
976
977 return rtrim( $uri, " \t\n\r\0\x0B/" ) . '/';
978 }
979
980 /**
981 * Writes the given alterations to file
982 *
983 * @param $file_source string The full path to the file to be read from
984 * @param $file_target string The full path to the file to be written to
985 * @param $alterations array An array of arrays containing alterations to be made
986 * @return void
987 */
988 function write_lines_to_file( $file_source, $file_target, $alterations )
989 {
990 if ( !$file_source || !file_exists( $file_source ) || !is_file( $file_source ) ) {
991 return -1;
992 }
993
994 if ( !$file_target ) {
995 $file_target = $file_source;
996 }
997
998 if ( !$alterations || !is_array( $alterations ) ) {
999 return -2;
1000 }
1001
1002 /*
1003 Alterations array takes the form
1004 array(
1005 '1st 20 chars of line' => array( 'Search string', 'Replacement string' ),
1006 '1st 20 chars of line' => array( 'Search string', 'Replacement string' )
1007 );
1008 */
1009
1010 // Get the existing lines in the file
1011 $lines = file( $file_source );
1012
1013 // Initialise an array to store the modified lines
1014 $modified_lines = array();
1015
1016 // Loop through the lines and modify them
1017 foreach ( $lines as $line ) {
1018 if ( isset( $alterations[substr( $line, 0, 20 )] ) ) {
1019 $alteration = $alterations[substr( $line, 0, 20 )];
1020 $modified_lines[] = str_replace( $alteration[0], $alteration[1], $line );
1021 } else {
1022 $modified_lines[] = $line;
1023 }
1024 }
1025
1026 $writable = true;
1027 if ( file_exists( $file_target ) ) {
1028 if ( !is_writable( $file_target ) ) {
1029 $writable = false;
1030 }
1031 } else {
1032 $dir_target = dirname( $file_target );
1033 if ( file_exists( $dir_target ) ) {
1034 if ( !is_writable( $dir_target ) || !is_dir( $dir_target ) ) {
1035 $writable = false;
1036 }
1037 } else {
1038 $writable = false;
1039 }
1040 }
1041
1042 if ( !$writable ) {
1043 return trim( join( null, $modified_lines ) );
1044 }
1045
1046 // Open the file for writing - rewrites the whole file
1047 $file_handle = fopen( $file_target, 'w' );
1048
1049 // Write lines one by one to avoid OS specific newline hassles
1050 foreach ( $modified_lines as $modified_line ) {
1051 if ( false !== strpos( $modified_line, '?>' ) ) {
1052 $modified_line = '?>';
1053 }
1054 fwrite( $file_handle, $modified_line );
1055 if ( $modified_line == '?>' ) {
1056 break;
1057 }
1058 }
1059
1060 // Close the config file
1061 fclose( $file_handle );
1062
1063 @chmod( $file_target, 0666 );
1064
1065 return 1;
1066 }
1067
1068 /**
1069 * Reports whether the request method is post or not
1070 *
1071 * @return boolean True if the page was posted, otherwise false
1072 */
1073 function is_posted()
1074 {
1075 if ( 'post' === strtolower( $_SERVER['REQUEST_METHOD'] ) ) {
1076 return true;
1077 }
1078 return false;
1079 }
1080
1081 /**
1082 * Determines which step the installer is on based on user input
1083 *
1084 * @return boolean Always returns true
1085 **/
1086 function set_step()
1087 {
1088 if ( $this->is_posted() ) {
1089 switch ( $this->step ) {
1090 case 1:
1091 $this->set_language();
1092 if ( $_POST['forward_0_0'] ) {
1093 $this->stop_process = 1;
1094 }
1095 break;
1096
1097 case 2:
1098 if ( $_POST['forward_1_2'] ) {
1099 $this->stop_process = 1;
1100 }
1101 break;
1102
1103 case 3:
1104 // If this is actually a request to go back to step 2
1105 if ( $_POST['back_2_1'] ) {
1106 $this->step = 2;
1107 break;
1108 }
1109
1110 // If we have come forward from step 2 then don't process form 3
1111 if ( $_POST['forward_2_1'] ) {
1112 $this->stop_process = true;
1113 }
1114
1115 // Determine what the status of the previous step was based on input
1116 if ( $_POST['toggle_2_0'] ) {
1117 $this->strings[2]['status'] = __( '« completed' );
1118 $this->step_status[2] = 'complete';
1119 }
1120 break;
1121
1122 case 4:
1123 // Determine what the status of the previous step was based on input
1124 if ( $_POST['toggle_2_0'] ) {
1125 $this->strings[2]['status'] = __( '« completed' );
1126 $this->step_status[2] = 'complete';
1127 }
1128
1129 // If this is actually a request to go back to step 3
1130 if ( $_POST['back_3_1'] ) {
1131 $this->step = 3;
1132 break;
1133 }
1134
1135 // We have to have come forward from step 3
1136 if ( $_POST['forward_3_1'] ) {
1137 $this->strings[3]['status'] = __( '« completed' );
1138 $this->step_status[3] = 'complete';
1139 } else {
1140 $this->step = 2;
1141 }
1142 break;
1143 }
1144 }
1145 return true;
1146 }
1147
1148 /**
1149 * Sanitizes all data stored in the data array
1150 *
1151 * @return boolean Always returns true
1152 **/
1153 function sanitize_form_data()
1154 {
1155 foreach ( $this->data as $step => $data ) {
1156 if ( isset( $data['form'] ) && is_array( $data['form'] ) ) {
1157 foreach ( $data['form'] as $key => $value ) {
1158 $this->data[$step]['form'][$key]['value'] = esc_attr( $value['value'] );
1159 }
1160 }
1161 }
1162 return true;
1163 }
1164
1165 /**
1166 * Directs processing of the form data based on the current step
1167 *
1168 * @return boolean Always returns true
1169 **/
1170 function process_form()
1171 {
1172 if ( $this->is_posted() && !$this->stop_process ) {
1173 switch ( $this->step ) {
1174 case 1:
1175 $this->process_form_config_file();
1176 break;
1177
1178 case 2:
1179 $this->process_form_wordpress_integration();
1180 break;
1181
1182 case 3:
1183 $this->process_form_site_options();
1184 break;
1185
1186 case 4:
1187 $this->process_form_finalise_installation();
1188 break;
1189 }
1190 }
1191 return true;
1192 }
1193
1194 /**
1195 * Takes inputted form data and injects it into the data array
1196 *
1197 * @param integer $step Which steps data to process
1198 * @return boolean Always returns true
1199 **/
1200 function inject_form_values_into_data( $step )
1201 {
1202 $data =& $this->data[$step]['form'];
1203
1204 foreach ( $data as $key => $value ) {
1205 if ( 'forward_' !== substr( $key, 0, 8 ) && 'back_' !== substr( $key, 0, 5 ) ) {
1206 if ( isset( $data[$key]['prerequisite'] ) && !$_POST[$data[$key]['prerequisite']] ) {
1207 if ( isset( $data[$key]['default_value'] ) ) {
1208 $data[$key]['value'] = $data[$key]['default_value'];
1209 }
1210 // do nothing - keep the default value
1211 } else {
1212 $data[$key]['value'] = stripslashes_deep( trim( $_POST[$key] ) );
1213 }
1214 }
1215 }
1216
1217 return true;
1218 }
1219
1220 /**
1221 * Validates the supplied config file data and writes it to the config file.
1222 *
1223 * @return void
1224 **/
1225 function process_form_config_file()
1226 {
1227 $this->inject_form_values_into_data( 1 );
1228
1229 $data =& $this->data[1]['form'];
1230
1231 if ( 'en_US' == $data['bb_lang']['value'] ) {
1232 $data['bb_lang']['value'] = '';
1233 }
1234
1235 if ( $data['toggle_1']['value'] ) {
1236 $data['toggle_1']['checked'] = 'checked="checked"';
1237 $data['toggle_1']['display'] = 'block';
1238
1239 // Deal with slashes in the keys
1240 //$data['bb_auth_key']['value'] = addslashes( stripslashes( $data['bb_auth_key']['value'] ) );
1241 //$data['bb_secure_auth_key']['value'] = addslashes( stripslashes( $data['bb_secure_auth_key']['value'] ) );
1242 //$data['bb_logged_in_key']['value'] = addslashes( stripslashes( $data['bb_logged_in_key']['value'] ) );
1243 //$data['bb_nonce_key']['value'] = addslashes( stripslashes( $data['bb_nonce_key']['value'] ) );
1244 }
1245
1246 $requested_prefix = $data['bb_table_prefix']['value'];
1247 $data['bb_table_prefix']['value'] = preg_replace( '/[^0-9a-zA-Z_]/', '', $data['bb_table_prefix']['value'] );
1248 if ( $requested_prefix !== $data['bb_table_prefix']['value'] ) {
1249 $data['toggle_1']['checked'] = 'checked="checked"';
1250 $data['toggle_1']['display'] = 'block';
1251 $this->step_status[1] = 'incomplete';
1252 $this->strings[1]['messages']['error'][] = __( 'The table prefix can only contain letters, numbers and underscores.<br />Please review the suggestion below.' );
1253 $this->strings[1]['form_errors']['bb_table_prefix'][] = __( '• Based on your input the following prefix is suggested.' );
1254 return 'incomplete';
1255 }
1256 if ( empty( $data['bb_table_prefix']['value'] ) ) {
1257 $data['bb_table_prefix']['value'] = 'bb_';
1258 $data['toggle_1']['checked'] = 'checked="checked"';
1259 $data['toggle_1']['display'] = 'block';
1260 $this->step_status[1] = 'incomplete';
1261 $this->strings[1]['messages']['error'][] = __( 'The table prefix can not be blank.<br />Please review the suggestion below.' );
1262 $this->strings[1]['form_errors']['bb_table_prefix'][] = __( '• The default prefix has been inserted.' );
1263 return 'incomplete';
1264 }
1265
1266 // Stop here if we are going backwards
1267 if ( $_POST['back_1_1'] ) {
1268 $this->step_status[1] = 'incomplete';
1269 return 'incomplete';
1270 }
1271
1272 // Test the db connection.
1273 define( 'BBDB_NAME', $data['bbdb_name']['value'] );
1274 define( 'BBDB_USER', $data['bbdb_user']['value'] );
1275 define( 'BBDB_PASSWORD', $data['bbdb_password']['value'] );
1276 define( 'BBDB_HOST', $data['bbdb_host']['value'] );
1277 define( 'BBDB_CHARSET', $data['bbdb_charset']['value'] );
1278 define( 'BBDB_COLLATE', $data['bbdb_collate']['value'] );
1279
1280 // We'll fail here if the values are no good.
1281 require_once( BACKPRESS_PATH . 'class.bpdb-multi.php' );
1282
1283 $bbdb =& new BPDB_Multi( array(
1284 'name' => BBDB_NAME,
1285 'user' => BBDB_USER,
1286 'password' => BBDB_PASSWORD,
1287 'host' => BBDB_HOST,
1288 'charset' => defined( 'BBDB_CHARSET' ) ? BBDB_CHARSET : false,
1289 'collate' => defined( 'BBDB_COLLATE' ) ? BBDB_COLLATE : false,
1290 'errors' => 'suppress'
1291 ) );
1292
1293 if ( !$bbdb->db_connect( 'SHOW TABLES;' ) ) {
1294 $bbdb->suppress_errors( false );
1295 $this->step_status[1] = 'incomplete';
1296 $this->strings[1]['messages']['error'][] = __( 'There was a problem connecting to the database you specified.<br />Please check the settings, then try again.' );
1297 return 'error';
1298 }
1299 $bbdb->suppress_errors( false );
1300
1301 $config_result = $this->write_lines_to_file(
1302 BB_PATH . 'bb-config-sample.php',
1303 BB_PATH . 'bb-config.php',
1304 array(
1305 "define( 'BBDB_NAME'," => array( "'bbpress'", "'" . $data['bbdb_name']['value'] . "'" ),
1306 "define( 'BBDB_USER'," => array( "'username'", "'" . $data['bbdb_user']['value'] . "'" ),
1307 "define( 'BBDB_PASSWO" => array( "'password'", "'" . $data['bbdb_password']['value'] . "'" ),
1308 "define( 'BBDB_HOST'," => array( "'localhost'", "'" . $data['bbdb_host']['value'] . "'" ),
1309 "define( 'BBDB_CHARSE" => array( "'utf8'", "'" . $data['bbdb_charset']['value'] . "'" ),
1310 "define( 'BBDB_COLLAT" => array( "''", "'" . $data['bbdb_collate']['value'] . "'" ),
1311 //"define( 'BB_AUTH_KEY" => array( "'put your unique phrase here'", "'" . $data['bb_auth_key']['value'] . "'" ),
1312 //"define( 'BB_SECURE_A" => array( "'put your unique phrase here'", "'" . $data['bb_secure_auth_key']['value'] . "'" ),
1313 //"define( 'BB_LOGGED_I" => array( "'put your unique phrase here'", "'" . $data['bb_logged_in_key']['value'] . "'" ),
1314 //"define( 'BB_NONCE_KE" => array( "'put your unique phrase here'", "'" . $data['bb_nonce_key']['value'] . "'" ),
1315 "\$bb_table_prefix = '" => array( "'bb_'", "'" . $data['bb_table_prefix']['value'] . "'" ),
1316 "define( 'BB_LANG', '" => array( "''", "'" . $data['bb_lang']['value'] . "'" )
1317 )
1318 );
1319
1320 switch ( $config_result ) {
1321 case -1:
1322 $this->step_status[1] = 'error';
1323 $this->strings[1]['messages']['error'][] = __( 'I could not find the file <code>bb-config-sample.php</code><br />Please upload it to the root directory of your bbPress installation.' );
1324 return 'error';
1325 break;
1326 case 1:
1327 $this->configs['bb-config.php'] = BB_PATH . 'bb-config.php';
1328 $this->step_status[1] = 'complete';
1329 $this->strings[1]['messages']['message'][] = __( 'Your settings have been saved to the file <code>bb-config.php</code><br />You can now continue to the next step.' );
1330 break;
1331 default:
1332 // Just write the contents to screen
1333 $this->data[1]['form']['config']['value'] = $config_result;
1334
1335 $this->step_status[1] = 'manual';
1336 $this->strings[1]['messages']['error'][] = __( 'Your settings could not be saved to a configuration file. You will need to save the text shown below into a file named <code>bb-config.php</code> in the root directory of your bbPress installation before you can continue.' );
1337 break;
1338 }
1339 }
1340
1341 /**
1342 * Validates the WordPress integration settings
1343 *
1344 * @return void
1345 **/
1346 function process_form_wordpress_integration()
1347 {
1348 // Check the referer
1349 bb_check_admin_referer( 'bbpress-installer' );
1350
1351 $this->inject_form_values_into_data( 2 );
1352
1353 $data =& $this->data[2]['form'];
1354
1355 // If there are no settings then goto step 3
1356 if ( !$data['toggle_2_0']['value'] && !$_POST['back_2_1'] ) {
1357 $this->step_status[2] = 'complete';
1358 $this->strings[2]['messages']['message'][] = __( 'You have chosen to skip the WordPress integration step. You can always integrate WordPress later from within the admin area of bbPress.' );
1359 return 'complete';
1360 }
1361
1362 // If integration is selected
1363 if ( $data['toggle_2_0']['value'] ) {
1364 $data['toggle_2_0']['checked'] = 'checked="checked"';
1365 $data['toggle_2_0']['display'] = 'block';
1366 $data['forward_2_0']['value'] = $data['toggle_2_0']['toggle_value']['on_value'];
1367
1368 if ( $data['toggle_2_1']['value'] ) {
1369 $data['toggle_2_1']['checked'] = 'checked="checked"';
1370 $data['toggle_2_1']['display'] = 'block';
1371
1372 // Check the wp_siteurl URL for errors
1373 $data['wp_siteurl']['value'] = $data['wp_siteurl']['value'] ? rtrim( $data['wp_siteurl']['value'], " \t\n\r\0\x0B/" ) . '/' : '';
1374 $this->strings[2]['form_errors']['wp_siteurl'][] = empty( $data['wp_siteurl']['value'] ) ? 'empty' : false;
1375 if ( $parsed = parse_url( $data['wp_siteurl']['value'] ) ) {
1376 $this->strings[2]['form_errors']['wp_siteurl'][] = preg_match( '/https?/i', $parsed['scheme'] ) ? false : 'urlscheme';
1377 $this->strings[2]['form_errors']['wp_siteurl'][] = empty( $parsed['host'] ) ? 'urlhost' : false;
1378 } else {
1379 $this->strings[2]['form_errors']['wp_siteurl'][] = 'urlparse';
1380 }
1381
1382 // Check the wp_home URL for errors
1383 $data['wp_home']['value'] = $data['wp_home']['value'] ? rtrim( $data['wp_home']['value'], " \t\n\r\0\x0B/" ) . '/' : '';
1384 $this->strings[2]['form_errors']['wp_home'][] = empty( $data['wp_home']['value'] ) ? 'empty' : false;
1385 if ( $parsed = parse_url( $data['wp_home']['value'] ) ) {
1386 $this->strings[2]['form_errors']['wp_home'][] = preg_match( '/https?/i', $parsed['scheme'] ) ? false : 'urlscheme';
1387 $this->strings[2]['form_errors']['wp_home'][] = empty( $parsed['host'] ) ? 'urlhost' : false;
1388 } else {
1389 $this->strings[2]['form_errors']['wp_home'][] = 'urlparse';
1390 }
1391
1392 // Deal with slashes in the keys
1393 $data['wp_auth_key']['value'] = addslashes( stripslashes( $data['wp_auth_key']['value'] ) );
1394 $data['wp_auth_salt']['value'] = addslashes( stripslashes( $data['wp_auth_salt']['value'] ) );
1395 $data['wp_secure_auth_key']['value'] = addslashes( stripslashes( $data['wp_secure_auth_key']['value'] ) );
1396 $data['wp_secure_auth_salt']['value'] = addslashes( stripslashes( $data['wp_secure_auth_salt']['value'] ) );
1397 $data['wp_logged_in_key']['value'] = addslashes( stripslashes( $data['wp_logged_in_key']['value'] ) );
1398 $data['wp_logged_in_salt']['value'] = addslashes( stripslashes( $data['wp_logged_in_salt']['value'] ) );
1399
1400 // Check the keys for errors
1401 $this->strings[2]['form_errors']['wp_auth_key'][] = empty( $data['wp_auth_key']['value'] ) ? 'empty' : false;
1402 $this->strings[2]['form_errors']['wp_secure_auth_key'][] = empty( $data['wp_secure_auth_key']['value'] ) ? 'empty' : false;
1403 $this->strings[2]['form_errors']['wp_logged_in_key'][] = empty( $data['wp_logged_in_key']['value'] ) ? 'empty' : false;
1404
1405 // Salts can be taken from the database if specified
1406 if ( !$data['toggle_2_2']['value'] ) {
1407 $this->strings[2]['form_errors']['wp_auth_salt'][] = empty( $data['wp_auth_salt']['value'] ) ? 'empty' : false;
1408 // NB; secure_auth_salt is not always set in WordPress
1409 $this->strings[2]['form_errors']['wp_logged_in_salt'][] = empty( $data['wp_logged_in_salt']['value'] ) ? 'empty' : false;
1410 }
1411 }
1412
1413 // If database integration is selected
1414 if ( $data['toggle_2_2']['value'] ) {
1415 $data['toggle_2_2']['checked'] = 'checked="checked"';
1416 $data['toggle_2_2']['display'] = 'block';
1417
1418 // Make the wp_table_prefix valid
1419 $data['wp_table_prefix']['value'] = preg_replace( '/[^0-9a-zA-Z_]/', '', $data['wp_table_prefix']['value'] );
1420 $data['wp_table_prefix']['value'] = empty( $data['wp_table_prefix']['value'] ) ? 'wp_' : $data['wp_table_prefix']['value'];
1421
1422 // Make the wordpress_mu_primary_blog_id valid
1423 $data['wordpress_mu_primary_blog_id']['value'] = preg_replace( '/[^0-9]/', '', $data['wordpress_mu_primary_blog_id']['value'] );
1424
1425 // If advanced database integration is selected
1426 if ( $data['toggle_2_3']['value'] ) {
1427 $data['toggle_2_3']['checked'] = 'checked="checked"';
1428 $data['toggle_2_3']['display'] = 'block';
1429 }
1430 }
1431
1432 if ( !$data['toggle_2_1']['value'] && !$data['toggle_2_2']['value'] ) {
1433 $this->step_status[2] = 'incomplete';
1434 $this->strings[2]['messages']['error'][] = __( 'You must enter your settings for integration setup to complete. Choose which integration settings you wish to enter from the options below.' );
1435 $this->strings[2]['form_errors']['toggle_2_1'][] = true;
1436 $this->strings[2]['form_errors']['toggle_2_2'][] = true;
1437 return 'incomplete';
1438 }
1439
1440 // Remove empty values from the error array
1441 foreach ( $this->strings[2]['form_errors'] as $input => $types) {
1442 $types = array_filter( $types);
1443 if ( !count( $types ) ) {
1444 unset( $this->strings[2]['form_errors'][$input] );
1445 }
1446 }
1447
1448 // Check for errors and build error messages
1449 if ( count( $this->strings[2]['form_errors'] ) ) {
1450
1451 $this->step_status[2] = 'incomplete';
1452 $this->strings[2]['messages']['error'][] = __( 'Your integration settings have not been processed due to errors with the items marked below.' );
1453
1454 foreach ( $this->strings[2]['form_errors'] as $input => $types ) {
1455 $errors = array();
1456
1457 foreach ( $types as $type ) {
1458 switch ( $type ) {
1459 case 'empty':
1460 // Only return this error when empty
1461 $errors = array( __( '• This value is required to continue.' ) );
1462 break(2);
1463 case 'urlparse':
1464 $errors[] = __( '• This does not appear to be a valid URL.' );
1465 break;
1466 case 'urlscheme':
1467 $errors[] = __( '• The URL must begin with "http" or "https".' );
1468 break;
1469 case 'urlhost':
1470 $errors[] = __( '• The URL does not contain a host name.' );
1471 break;
1472 }
1473 }
1474
1475 $this->strings[2]['form_errors'][$input] = $errors;
1476 }
1477
1478 return 'incomplete';
1479 }
1480
1481 // If database integration is selected
1482 if ( $data['toggle_2_2']['value'] ) {
1483
1484 // Test the db connection.
1485
1486 // Setup variables and constants if available
1487 global $bb;
1488 $bb->wp_table_prefix = $data['wp_table_prefix']['value'];
1489 if ( $data['toggle_2_3']['value'] ) {
1490 // These may be empty at this particular stage
1491 if ( !empty( $data['user_bbdb_name']['value'] ) ) {
1492 $bb->user_bbdb_name = $data['user_bbdb_name']['value'];
1493 }
1494 if ( !empty( $data['user_bbdb_user']['value'] ) ) {
1495 $bb->user_bbdb_user = $data['user_bbdb_user']['value'];
1496 }
1497 if ( !empty( $data['user_bbdb_password']['value'] ) ) {
1498 $bb->user_bbdb_password = $data['user_bbdb_password']['value'];
1499 }
1500 if ( !empty( $data['user_bbdb_host']['value'] ) ) {
1501 $bb->user_bbdb_host = $data['user_bbdb_host']['value'];
1502 }
1503 if ( !empty( $data['user_bbdb_charset']['value'] ) ) {
1504 $bb->user_bbdb_charset = preg_replace( '/[^a-z0-9_-]/i', '', $data['user_bbdb_charset']['value'] );
1505 }
1506 if ( !empty( $data['user_bbdb_collate']['value'] ) ) {
1507 $bb->user_bbdb_collate = preg_replace( '/[^a-z0-9_-]/i', '', $data['user_bbdb_collate']['value'] );
1508 }
1509 if ( !empty( $data['custom_user_table']['value'] ) ) {
1510 $bb->custom_user_table = preg_replace( '/[^a-z0-9_-]/i', '', $data['custom_user_table']['value'] );
1511 }
1512 if ( !empty( $data['custom_user_meta_table']['value'] ) ) {
1513 $bb->custom_user_meta_table = preg_replace( '/[^a-z0-9_-]/i', '', $data['custom_user_meta_table']['value'] );
1514 }
1515 }
1516
1517 // Bring in the database object
1518 global $bbdb;
1519 global $bb_table_prefix;
1520
1521 // Resolve the custom user tables for bpdb
1522 bb_set_custom_user_tables();
1523
1524 if ( isset( $bb->custom_databases) && isset( $bb->custom_databases['user'] ) ) {
1525 $bbdb->add_db_server( 'user', $bb->custom_databases['user'] );
1526 }
1527
1528 // Add custom tables if required
1529 if ( isset( $bb->custom_tables['users'] ) || isset( $bb->custom_tables['usermeta'] ) ) {
1530 $bbdb->tables = array_merge( $bbdb->tables, $bb->custom_tables );
1531 if ( is_wp_error( $bbdb->set_prefix( $bb_table_prefix ) ) ) {
1532 die( __( 'Your user table prefix may only contain letters, numbers and underscores.' ) );
1533 }
1534 }
1535
1536 // Hide errors for the test
1537 $bbdb->hide_errors();
1538
1539 $result = $bbdb->query( 'DESCRIBE ' . $bbdb->users . ';' );
1540 $result_error = $bbdb->get_error();
1541
1542 // Select from the user table (may fail if there are no records in the table)
1543 if ( !$result && $result_error ) {
1544 // We couldn't connect to the database at all
1545
1546 // Turn errors back on
1547 $bbdb->show_errors();
1548
1549 // Set the status
1550 $this->step_status[2] = 'incomplete';
1551 if ( !empty( $data['user_bbdb_name']['value'] ) ) {
1552 $this->strings[2]['form_errors']['user_bbdb_name'][] = true;
1553 }
1554 if ( !empty( $data['user_bbdb_user']['value'] ) ) {
1555 $this->strings[2]['form_errors']['user_bbdb_user'][] = true;
1556 }
1557 if ( !empty( $data['user_bbdb_password']['value'] ) ) {
1558 $this->strings[2]['form_errors']['user_bbdb_password'][] = true;
1559 }
1560 if ( !empty( $data['user_bbdb_host']['value'] ) ) {
1561 $this->strings[2]['form_errors']['user_bbdb_host'][] = true;
1562 }
1563 if ( !empty( $data['custom_user_table']['value'] ) ) {
1564 $this->strings[2]['form_errors']['custom_user_table'][] = true;
1565 }
1566 if ( !empty( $data['custom_user_meta_table']['value'] ) ) {
1567 $this->strings[2]['form_errors']['custom_user_meta_table'][] = true;
1568 }
1569 $this->strings[2]['messages']['error'][] = __( 'There was a problem connecting to the WordPress user database you specified. Please check the settings, then try again.' );
1570 return 'incomplete';
1571 }
1572
1573 if ( $result_error ) {
1574 // The result is an error, presumably telling us the table doesn't exist
1575
1576 // Turn errors back on
1577 $bbdb->show_errors();
1578
1579 // Set the status
1580 $this->step_status[2] = 'incomplete';
1581
1582 if ( $data['toggle_2_3']['value'] ) {
1583 $this->strings[2]['messages']['error'][] = __( 'Existing WordPress user tables could not be found in the WordPress database you specified.' );
1584 } else {
1585 $this->strings[2]['messages']['error'][] = __( 'Existing WordPress user tables could not be found in the bbPress database you specified in step 1.<br /><br />This is probably because the database does not already contain working WordPress tables. You may need to specify advanced database settings or leave integration until after installation.' );
1586 }
1587 $this->strings[2]['form_errors']['wp_table_prefix'][] = __( '• This may not be a valid user table prefix.' );
1588 return 'incomplete';
1589 }
1590
1591 // Turn errors back on
1592 $bbdb->show_errors();
1593 }
1594 }
1595
1596 // Stop here if we are going backwards
1597 if ( $_POST['back_2_1'] ) {
1598 $this->step_status[2] = 'incomplete';
1599 return 'incomplete';
1600 }
1601
1602 // If we make it this may we are complete, so set the status to complete
1603 $this->step_status[2] = 'complete';
1604 $this->strings[2]['messages']['message'][] = __( 'Your WordPress integration cookie and database settings have been successfully validated. They will be saved after the next step.<br /><br />Once you have finished installing, you should visit the WordPress integration section of the bbPress admin area for further options and integration instructions, including user mapping and the correct cookie settings to add to your WordPress configuration file.' );
1605 return 'complete';
1606 }
1607
1608 /**
1609 * Validates the site options.
1610 *
1611 * @return void
1612 **/
1613 function process_form_site_options()
1614 {
1615 // Check the referer
1616 bb_check_admin_referer( 'bbpress-installer' );
1617
1618 $this->inject_form_values_into_data( 2 );
1619 $this->inject_form_values_into_data( 3 );
1620
1621 $data =& $this->data[3]['form'];
1622
1623 $this->strings[3]['form_errors']['name'][] = empty( $data['name']['value'] ) ? 'empty' : false;
1624
1625 $data['uri']['value'] = $data['uri']['value'] ? rtrim( $data['uri']['value'], " \t\n\r\0\x0B/" ) . '/' : '';
1626 $this->strings[3]['form_errors']['uri'][] = empty( $data['uri']['value'] ) ? 'empty' : false;
1627 if ( $parsed = parse_url( $data['uri']['value'] ) ) {
1628 $this->strings[3]['form_errors']['uri'][] = preg_match( '/https?/i', $parsed['scheme'] ) ? false : 'urlscheme';
1629 $this->strings[3]['form_errors']['uri'][] = empty( $parsed['host'] ) ? 'urlhost' : false;
1630 } else {
1631 $this->strings[3]['form_errors']['uri'][] = 'urlparse';
1632 }
1633
1634 $this->strings[3]['form_errors']['keymaster_user_login'][] = empty( $data['keymaster_user_login']['value'] ) ? 'empty' : false;
1635 if ( $data['keymaster_user_login']['value'] != sanitize_user( $data['keymaster_user_login']['value'], true ) ) {
1636 $this->strings[3]['form_errors']['keymaster_user_login'][] = 'userlogin';
1637 }
1638 $data['keymaster_user_login']['value'] = sanitize_user( $data['keymaster_user_login']['value'], true );
1639
1640 // Check for a valid email
1641 $this->strings[3]['form_errors']['keymaster_user_email'][] = empty( $data['keymaster_user_email']['value'] ) ? 'empty' : false;
1642 $this->strings[3]['form_errors']['keymaster_user_email'][] = !is_email( $data['keymaster_user_email']['value'] ) ? 'email' : false;
1643
1644 // Check for a forum name
1645 if ( !$this->database_tables_are_installed() ) {
1646 $this->strings[3]['form_errors']['forum_name'][] = empty( $data['forum_name']['value'] ) ? 'empty' : false;
1647 }
1648
1649 // Remove empty values from the error array
1650 foreach ( $this->strings[3]['form_errors'] as $input => $types ) {
1651 $types = array_filter( $types );
1652 if ( !count( $types ) ) {
1653 unset( $this->strings[3]['form_errors'][$input] );
1654 }
1655 }
1656
1657 // Check for errors and build error messages
1658 if ( count( $this->strings[3]['form_errors'] ) ) {
1659
1660 $this->step_status[3] = 'incomplete';
1661 $this->strings[3]['messages']['error'][] = __( 'Your site settings have not been processed due to errors with the items marked below.' );
1662
1663 foreach ( $this->strings[3]['form_errors'] as $input => $types ) {
1664 $errors = array();
1665
1666 foreach ( $types as $type ) {
1667 switch ( $type ) {
1668 case 'empty':
1669 // Only return this error when empty
1670 $errors = array( __( '• This value is required to continue.' ) );
1671 break(2);
1672 case 'urlparse':
1673 $errors[] = __( '• This does not appear to be a valid URL.' );
1674 break;
1675 case 'urlscheme':
1676 $errors[] = __( '• The URL must begin with "http" or "https".' );
1677 break;
1678 case 'urlhost':
1679 $errors[] = __( '• The URL does not contain a host name.' );
1680 break;
1681 case 'userlogin':
1682 $errors[] = __( '• Contains disallowed characters which have been removed.' );
1683 break;
1684 case 'email':
1685 $errors[] = __( '• The user email address appears to be invalid.' );
1686 break;
1687 }
1688 }
1689
1690 $this->strings[3]['form_errors'][$input] = $errors;
1691 }
1692
1693 return 'incomplete';
1694 }
1695
1696 // Stop here if we are going backwards
1697 if ( $_POST['back_3_1'] ) {
1698 $this->step_status[3] = 'incomplete';
1699 return 'incomplete';
1700 }
1701
1702 // If we make it this far we are good to go
1703 $this->step_status[3] = 'complete';
1704 $this->strings[3]['messages']['message'][] = __( 'Your site settings have been saved and we are now ready to complete the installation. So what are you waiting for?' );
1705 return 'complete';
1706 }
1707
1708 /**
1709 * Finalises the installation by creating the database and writing all the supplied data to the database.
1710 *
1711 * @return void
1712 **/
1713 function process_form_finalise_installation()
1714 {
1715 require_once( BB_PATH . 'bb-admin/includes/functions.bb-upgrade.php' );
1716 require_once( BB_PATH . 'bb-admin/includes/functions.bb-admin.php' );
1717
1718 $this->inject_form_values_into_data( 2 );
1719 $this->inject_form_values_into_data( 3 );
1720
1721 $data2 =& $this->data[2]['form'];
1722 $data3 =& $this->data[3]['form'];
1723 $data4 =& $this->data[4]['form'];
1724
1725 $error_log = array();
1726 $installation_log = array();
1727
1728 // Check the referer
1729 bb_check_admin_referer( 'bbpress-installer' );
1730 $installation_log[] = __( 'Referrer is OK, beginning installation…' );
1731
1732 global $bbdb;
1733
1734 // Setup user table variables and constants if available
1735 if ( $data2['toggle_2_2']['value'] ) {
1736
1737 $installation_log[] = '>>> ' . __( 'Setting up custom user table constants' );
1738
1739 global $bb;
1740 global $bb_table_prefix;
1741
1742 if ( !empty( $data2['wp_table_prefix']['value'] ) ) {
1743 $bb->wp_table_prefix = $data2['wp_table_prefix']['value'];
1744 }
1745 if ( !empty( $data2['user_bbdb_name']['value'] ) ) {
1746 $bb->user_bbdb_name = $data2['user_bbdb_name']['value'];
1747 }
1748 if ( !empty( $data2['user_bbdb_user']['value'] ) ) {
1749 $bb->user_bbdb_user = $data2['user_bbdb_user']['value'];
1750 }
1751 if ( !empty( $data2['user_bbdb_password']['value'] ) ) {
1752 $bb->user_bbdb_password = $data2['user_bbdb_password']['value'];
1753 }
1754 if ( !empty( $data2['user_bbdb_host']['value'] ) ) {
1755 $bb->user_bbdb_host = $data2['user_bbdb_host']['value'];
1756 }
1757 if ( !empty( $data2['user_bbdb_charset']['value'] ) ) {
1758 $bb->user_bbdb_charset = preg_replace( '/[^a-z0-9_-]/i', '', $data2['user_bbdb_charset']['value'] );
1759 }
1760 if ( !empty( $data2['user_bbdb_collate']['value'] ) ) {
1761 $bb->user_bbdb_collate = preg_replace( '/[^a-z0-9_-]/i', '', $data2['user_bbdb_collate']['value'] );
1762 }
1763
1764 bb_set_custom_user_tables();
1765
1766 // Add custom user database if required
1767 if ( isset( $bb->custom_databases['user'] ) ) {
1768 $bbdb->add_db_server( 'user', $bb->custom_databases['user'] );
1769 }
1770
1771 // Add custom tables if required
1772 if ( isset( $bb->custom_tables ) ) {
1773 $bbdb->tables = array_merge( $bbdb->tables, $bb->custom_tables );
1774 if ( is_wp_error( $bbdb->set_prefix( $bb_table_prefix ) ) )
1775 die( __( 'Your user table prefix may only contain letters, numbers and underscores.' ) );
1776 }
1777 }
1778
1779 // Create the database
1780 $installation_log[] = "\n" . __( 'Step 1 - Creating database tables' );
1781
1782 if ( !$this->database_tables_are_installed() ) {
1783 // Hide db errors
1784 $bbdb->hide_errors();
1785 // Install the database
1786 $alterations = bb_install();
1787 // Show db errors
1788 $bbdb->show_errors();
1789
1790 if ( isset( $alterations['errors'] ) && is_array( $alterations['errors'] ) ) {
1791 $error_log = array_merge( $error_log, $alterations['errors'] );
1792 }
1793 if ( isset( $alterations['messages'] ) && is_array( $alterations['messages'] ) ) {
1794 $installation_log = array_merge( $installation_log, $alterations['messages'] );
1795 }
1796
1797 if ( !$this->database_tables_are_installed() ) {
1798 $installation_log[] = '>>> ' . __( 'Database installation failed!!!' );
1799 $installation_log[] = '>>>>>> ' . __( 'Halting installation!' );
1800 $error_log[] = __( 'Database installation failed!!!' );
1801
1802 $this->step_status[4] = 'incomplete';
1803 $this->strings[4]['h2'] = __( 'Installation failed!' );
1804 $this->strings[4]['messages']['error'][] = __( 'The database failed to install. You may need to replace bbPress with a fresh copy and start again.' );
1805
1806 $data4['installation_log']['value'] = join( "\n", $installation_log );
1807 $data4['error_log']['value'] = join( "\n", $error_log );
1808
1809 return 'incomplete';
1810 }
1811 } else {
1812 $installation_log[] = '>>> ' . __( 'Database is already installed!!!' );
1813 }
1814
1815 // Integration settings passed from step 2
1816 // These are already validated provided that the referer checks out
1817 $installation_log[] = "\n" . __( 'Step 2 - WordPress integration (optional)' );
1818 if ( $data2['toggle_2_0']['value'] ) {
1819 if ( $data2['toggle_2_1']['value'] ) {
1820 bb_update_option( 'wp_siteurl', $data2['wp_siteurl']['value'] );
1821 $installation_log[] = '>>> ' . __( 'WordPress address (URL):' ) . ' ' . $data2['wp_siteurl']['value'];
1822
1823 bb_update_option( 'wp_home', $data2['wp_home']['value'] );
1824 $installation_log[] = '>>> ' . __( 'Blog address (URL):' ) . ' ' . $data2['wp_home']['value'];
1825
1826 $config_result = $this->write_lines_to_file(
1827 BB_PATH . 'bb-config.php',
1828 false,
1829 array(
1830 "define( 'BB_AUTH_KEY" => array( "'" . BB_AUTH_KEY . "'", "'" . $data2['wp_auth_key']['value'] . "'" ),
1831 "define( 'BB_SECURE_A" => array( "'" . BB_SECURE_AUTH_KEY . "'", "'" . $data2['wp_secure_auth_key']['value'] . "'" ),
1832 "define( 'BB_LOGGED_I" => array( "'" . BB_LOGGED_IN_KEY . "'", "'" . $data2['wp_logged_in_key']['value'] . "'" ),
1833 )
1834 );
1835
1836 switch ( $config_result ) {
1837 case 1:
1838 $installation_log[] = '>>> ' . __( 'WordPress cookie keys set.' );
1839 break;
1840 default:
1841 $error_log[] = '>>> ' . __( 'WordPress cookie keys not set.' );
1842 $error_log[] = '>>>>>> ' . __( 'Your "bb-config.php" file was not writable.' );
1843 $error_log[] = '>>>>>> ' . __( 'You will need to manually re-define "BB_AUTH_KEY", "BB_SECURE_AUTH_KEY" and "BB_LOGGED_IN_KEY" in your "bb-config.php" file.' );
1844 $installation_log[] = '>>> ' . __( 'WordPress cookie keys not set.' );
1845 break;
1846 }
1847
1848 if ( !empty( $data2['wp_auth_salt']['value'] ) ) {
1849 bb_update_option( 'bb_auth_salt', $data2['wp_auth_salt']['value'] );
1850 $installation_log[] = '>>> ' . __( 'WordPress "auth" cookie salt set from input.' );
1851 }
1852
1853 if ( !empty( $data2['wp_secure_auth_salt']['value'] ) ) {
1854 bb_update_option( 'bb_secure_auth_salt', $data2['wp_secure_auth_salt']['value'] );
1855 $installation_log[] = '>>> ' . __( 'WordPress "secure auth" cookie salt set from input.' );
1856 }
1857
1858 if ( !empty( $data2['wp_logged_in_salt']['value'] ) ) {
1859 bb_update_option( 'bb_logged_in_salt', $data2['wp_logged_in_salt']['value'] );
1860 $installation_log[] = '>>> ' . __( 'WordPress "logged in" cookie salt set from input.' );
1861 }
1862 }
1863
1864 if ( $data2['toggle_2_2']['value'] ) {
1865 if (
1866 !bb_get_option( 'bb_auth_salt' ) ||
1867 !bb_get_option( 'bb_secure_auth_salt' ) ||
1868 !bb_get_option( 'bb_logged_in_salt' )
1869 ) {
1870 $installation_log[] = '>>> ' . __( 'Fetching missing WordPress cookie salts.' );
1871
1872 $_prefix = $bb->wp_table_prefix;
1873 if ( !empty( $data2['wordpress_mu_primary_blog_id']['value'] ) ) {
1874 $_prefix .= $data2['wordpress_mu_primary_blog_id']['value'] . '_';
1875 }
1876
1877 if ( isset( $bb->custom_databases['user'] ) ) {
1878 $bbdb->tables['options'] = array( 'user', $_prefix . 'options' );
1879 } else {
1880 $bbdb->tables['options'] = $_prefix . 'options';
1881 }
1882
1883 unset( $_prefix );
1884
1885 $bbdb->set_prefix( $bb_table_prefix );
1886
1887 if ( !bb_get_option( 'bb_auth_salt' ) ) {
1888 $wp_auth_salt = $bbdb->get_var( "SELECT `option_value` FROM $bbdb->options WHERE `option_name` = 'auth_salt' LIMIT 1" );
1889 if ( $wp_auth_salt ) {
1890 bb_update_option( 'bb_auth_salt', $wp_auth_salt );
1891 $installation_log[] = '>>>>>> ' . __( 'WordPress "auth" cookie salt set.' );
1892 } else {
1893 $error_log[] = '>>> ' . __( 'WordPress "auth" cookie salt not set.' );
1894 $error_log[] = '>>>>>> ' . __( 'Could not fetch "auth" cookie salt from the WordPress options table.' );
1895 $error_log[] = '>>>>>> ' . __( 'You will need to manually define the "auth" cookie salt in your database.' );
1896 $installation_log[] = '>>>>>> ' . __( 'WordPress "auth" cookie salt not set.' );
1897 }
1898 }
1899
1900 if ( !bb_get_option( 'bb_secure_auth_salt' ) ) {
1901 $wp_secure_auth_salt = $bbdb->get_var( "SELECT `option_value` FROM $bbdb->options WHERE `option_name` = 'secure_auth_salt' LIMIT 1" );
1902 if ( $wp_secure_auth_salt ) {
1903 bb_update_option( 'bb_secure_auth_salt', $wp_secure_auth_salt );
1904 $installation_log[] = '>>>>>> ' . __( 'WordPress "secure auth" cookie salt set.' );
1905 } else {
1906 // This cookie salt is sometimes empty so don't error
1907 $installation_log[] = '>>>>>> ' . __( 'WordPress "secure auth" cookie salt not set.' );
1908 }
1909 }
1910
1911 if ( !bb_get_option( 'bb_logged_in_salt' ) ) {
1912 $wp_logged_in_salt = $bbdb->get_var( "SELECT `option_value` FROM $bbdb->options WHERE `option_name` = 'logged_in_salt' LIMIT 1" );
1913 if ( $wp_logged_in_salt ) {
1914 bb_update_option( 'bb_logged_in_salt', $wp_logged_in_salt );
1915 $installation_log[] = '>>>>>> ' . __( 'WordPress "logged in" cookie salt set.' );
1916 } else {
1917 $error_log[] = '>>> ' . __( 'WordPress "logged in" cookie salt not set.' );
1918 $error_log[] = '>>>>>> ' . __( 'Could not fetch "logged in" cookie salt from the WordPress options table.' );
1919 $error_log[] = '>>>>>> ' . __( 'You will need to manually define the "logged in" cookie salt in your database.' );
1920 $installation_log[] = '>>>>>> ' . __( 'WordPress "logged in" cookie salt not set.' );
1921 }
1922 }
1923 }
1924
1925 if ( !empty( $data2['wp_table_prefix']['value'] ) ) {
1926 bb_update_option( 'wp_table_prefix', $data2['wp_table_prefix']['value'] );
1927 $installation_log[] = '>>> ' . __( 'User database table prefix:' ) . ' ' . $data2['wp_table_prefix']['value'];
1928 }
1929
1930 if ( !empty( $data2['wordpress_mu_primary_blog_id']['value'] ) ) {
1931 bb_update_option( 'wordpress_mu_primary_blog_id', $data2['wordpress_mu_primary_blog_id']['value'] );
1932 $installation_log[] = '>>> ' . __( 'WordPress MU primary blog ID:' ) . ' ' . $data2['wordpress_mu_primary_blog_id']['value'];
1933 }
1934
1935 if ( $data2['toggle_2_3']['value'] ) {
1936 if ( !empty( $data2['user_bbdb_name']['value'] ) ) {
1937 bb_update_option( 'user_bbdb_name', $data2['user_bbdb_name']['value'] );
1938 $installation_log[] = '>>> ' . __( 'User database name:' ) . ' ' . $data2['user_bbdb_name']['value'];
1939 }
1940 if ( !empty( $data2['user_bbdb_user']['value'] ) ) {
1941 bb_update_option( 'user_bbdb_user', $data2['user_bbdb_user']['value'] );
1942 $installation_log[] = '>>> ' . __( 'User database user:' ) . ' ' . $data2['user_bbdb_user']['value'];
1943 }
1944 if ( !empty( $data2['user_bbdb_password']['value'] ) ) {
1945 bb_update_option( 'user_bbdb_password', $data2['user_bbdb_password']['value'] );
1946 $installation_log[] = '>>> ' . __( 'User database password:' ) . ' ' . $data2['user_bbdb_password']['value'];
1947 }
1948 if ( !empty( $data2['user_bbdb_host']['value'] ) ) {
1949 bb_update_option( 'user_bbdb_host', $data2['user_bbdb_host']['value'] );
1950 $installation_log[] = '>>> ' . __( 'User database host:' ) . ' ' . $data2['user_bbdb_host']['value'];
1951 }
1952 if ( !empty( $data2['user_bbdb_charset']['value'] ) ) {
1953 bb_update_option( 'user_bbdb_charset', $data2['user_bbdb_charset']['value'] );
1954 $installation_log[] = '>>> ' . __( 'User database character set:' ) . ' ' . $data2['user_bbdb_charset']['value'];
1955 }
1956 if ( !empty( $data2['user_bbdb_collate']['value'] ) ) {
1957 bb_update_option( 'user_bbdb_collate', $data2['user_bbdb_collate']['value'] );
1958 $installation_log[] = '>>> ' . __( 'User database collation:' ) . ' ' . $data2['user_bbdb_collate']['value'];
1959 }
1960 if ( !empty( $data2['custom_user_table']['value'] ) ) {
1961 bb_update_option( 'custom_user_table', $data2['custom_user_table']['value'] );
1962 $installation_log[] = '>>> ' . __( 'User database "user" table:' ) . ' ' . $data2['custom_user_table']['value'];
1963 }
1964 if ( !empty( $data2['custom_user_meta_table']['value'] ) ) {
1965 bb_update_option( 'custom_user_meta_table', $data2['custom_user_meta_table']['value'] );
1966 $installation_log[] = '>>> ' . __( 'User database "user meta" table:' ) . ' ' . $data2['custom_user_meta_table']['value'];
1967 }
1968 }
1969 }
1970 } else {
1971 $installation_log[] = '>>> ' . __( 'Integration not enabled' );
1972 }
1973
1974 // Site settings passed from step 3
1975 // These are already validated provided that the referer checks out
1976 $installation_log[] = "\n" . __( 'Step 3 - Site settings' );
1977 bb_update_option( 'name', $data3['name']['value'] );
1978 $installation_log[] = '>>> ' . __( 'Site name:' ) . ' ' . $data3['name']['value'];
1979 bb_update_option( 'uri', $data3['uri']['value'] );
1980 $installation_log[] = '>>> ' . __( 'Site address (URL):' ) . ' ' . $data3['uri']['value'];
1981 bb_update_option( 'from_email', $data3['keymaster_user_email']['value'] );
1982 $installation_log[] = '>>> ' . __( 'From email address:' ) . ' ' . $data3['keymaster_user_email']['value'];
1983
1984 // Create the key master
1985 $keymaster_created = false;
1986
1987 switch ( $data3['keymaster_user_type']['value'] ) {
1988 case 'new':
1989
1990 // Check to see if the user login already exists
1991 if ( $keymaster_user = bb_get_user( $data3['keymaster_user_login']['value'], array( 'by' => 'login' ) ) ) {
1992 // The keymaster is an existing bbPress user
1993 $installation_log[] = '>>> ' . __( 'Key master could not be created!' );
1994 $installation_log[] = '>>>>>> ' . __( 'That login is already taken!' );
1995 $error_log[] = __( 'Key master could not be created!' );
1996
1997 if ( $keymaster_user->bb_capabilities['keymaster'] ) {
1998 // The existing user is a key master - continue
1999 $bb_current_user = bb_set_current_user( $keymaster_user->ID );
2000 $installation_log[] = '>>>>>> ' . __( 'Existing key master entered!' );
2001 $data4['keymaster_user_password']['value'] = __( 'Your bbPress password' );
2002 $data3['keymaster_user_email']['value'] = $keymaster_user->user_email;
2003 bb_update_option( 'from_email', $keymaster_user->user_email);
2004 $installation_log[] = '>>>>>> ' . __( 'Re-setting admin email address.' );
2005 $keymaster_created = true;
2006 } else {
2007 // The existing user is a non-key master user - halt installation
2008 $installation_log[] = '>>>>>> ' . __( 'Existing user without key master role entered!' );
2009 $installation_log[] = '>>>>>>>>> ' . __( 'Halting installation!' );
2010 $this->step_status[4] = 'incomplete';
2011 $this->strings[4]['h2'] = __( 'Installation failed!' );
2012 $this->strings[4]['messages']['error'][] = __( 'The key master could not be created. An existing user was found with that user login.' );
2013
2014 $data4['installation_log']['value'] = join( "\n", $installation_log );
2015 $data4['error_log']['value'] = join( "\n", $error_log );
2016
2017 return 'incomplete';
2018 }
2019
2020 break;
2021 }
2022
2023 // Helper function to let us know the password that was created
2024 global $keymaster_password;
2025 function bb_get_keymaster_password( $user_id, $pass ) {
2026 global $keymaster_password;
2027 $keymaster_password = $pass;
2028 }
2029 add_action( 'bb_new_user', 'bb_get_keymaster_password', 10, 2 );
2030
2031 // Create the new user (automattically given key master role when BB_INSTALLING is true)
2032 if ( $keymaster_user_id = bb_new_user( $data3['keymaster_user_login']['value'], $data3['keymaster_user_email']['value'], '' ) ) {
2033 $bb_current_user = bb_set_current_user( $keymaster_user_id );
2034 $data4['keymaster_user_password']['value'] = $keymaster_password;
2035 $installation_log[] = '>>> ' . __( 'Key master created' );
2036 $installation_log[] = '>>>>>> ' . __( 'Username:' ) . ' ' . $data3['keymaster_user_login']['value'];
2037 $installation_log[] = '>>>>>> ' . __( 'Email address:' ) . ' ' . $data3['keymaster_user_email']['value'];
2038 $installation_log[] = '>>>>>> ' . __( 'Password:' ) . ' ' . $data4['keymaster_user_password']['value'];
2039 $keymaster_created = true;
2040 } else {
2041 $installation_log[] = '>>> ' . __( 'Key master could not be created!' );
2042 $installation_log[] = '>>>>>> ' . __( 'Halting installation!' );
2043 $error_log[] = __( 'Key master could not be created!' );
2044 $this->step_status[4] = 'incomplete';
2045 $this->strings[4]['h2'] = __( 'Installation failed!' );
2046 $this->strings[4]['messages']['error'][] = __( 'The key master could not be created. You may need to replace bbPress with a fresh copy and start again.' );
2047
2048 $data4['installation_log']['value'] = join( "\n", $installation_log );
2049 $data4['error_log']['value'] = join( "\n", $error_log );
2050
2051 return 'incomplete';
2052 }
2053 break;
2054
2055 case 'old':
2056 if ( $keymaster_user = bb_get_user( $data3['keymaster_user_login']['value'], array( 'by' => 'login' ) ) ) {
2057 // The keymaster is an existing bbPress or WordPress user
2058 $bb_current_user = bb_set_current_user( $keymaster_user->ID );
2059 $bb_current_user->set_role( 'keymaster' );
2060 $data4['keymaster_user_password']['value'] = __( 'Your existing password' );
2061 $installation_log[] = '>>> ' . __( 'Key master role assigned to existing user' );
2062 $installation_log[] = '>>>>>> ' . __( 'Username:' ) . ' ' . $data3['keymaster_user_login']['value'];
2063 $installation_log[] = '>>>>>> ' . __( 'Email address:' ) . ' ' . $data3['keymaster_user_email']['value'];
2064 $installation_log[] = '>>>>>> ' . __( 'Password:' ) . ' ' . $data4['keymaster_user_password']['value'];
2065 $keymaster_created = true;
2066 } else {
2067 $installation_log[] = '>>> ' . __( 'Key master role could not be assigned to existing user!' );
2068 $installation_log[] = '>>>>>> ' . __( 'Halting installation!' );
2069 $error_log[] = __( 'Key master could not be created!' );
2070 $this->step_status[4] = 'incomplete';
2071 $this->strings[4]['h2'] = __( 'Installation failed!' );
2072 $this->strings[4]['messages']['error'][] = __( 'The key master could not be assigned. You may need to replace bbPress with a fresh copy and start again.' );
2073
2074 $data4['installation_log']['value'] = join( "\n", $installation_log );
2075 $data4['error_log']['value'] = join( "\n", $error_log );
2076
2077 return 'incomplete';
2078 }
2079 break;
2080 }
2081
2082 // Don't create an initial forum if any forums already exist
2083 if (!$bbdb->get_results( 'SELECT `forum_id` FROM `' . $bbdb->forums . '` LIMIT 1;' ) ) {
2084 if ( $this->language != BB_LANG) {
2085 global $locale, $l10n;
2086 $locale = BB_LANG;
2087 unset( $l10n['default'] );
2088 bb_load_default_textdomain();
2089 }
2090
2091 $description = __( 'Just another bbPress community' );
2092 bb_update_option( 'description', $description);
2093
2094 if ( $this->language != BB_LANG) {
2095 $locale = $this->language;
2096 unset( $l10n['default'] );
2097 bb_load_default_textdomain();
2098 }
2099
2100 $installation_log[] = '>>> ' . __( 'Description:' ) . ' ' . $description;
2101
2102 if ( $forum_id = bb_new_forum( array( 'forum_name' => $data3['forum_name']['value'] ) ) ) {
2103 $installation_log[] = '>>> ' . __( 'Forum name:' ) . ' ' . $data3['forum_name']['value'];
2104
2105 if ( $this->language != BB_LANG) {
2106 $locale = BB_LANG;
2107 unset( $l10n['default'] );
2108 bb_load_default_textdomain();
2109 }
2110
2111 $topic_title = __( 'Your first topic' );
2112 $topic_id = bb_insert_topic(
2113 array(
2114 'topic_title' => $topic_title,
2115 'forum_id' => $forum_id,
2116 'tags' => 'bbPress'
2117 )
2118 );
2119 $post_text = __( 'First Post! w00t.' );
2120 bb_insert_post(
2121 array(
2122 'topic_id' => $topic_id,
2123 'post_text' => $post_text
2124 )
2125 );
2126
2127 if ( $this->language != BB_LANG ) {
2128 $locale = $this->language;
2129 unset( $l10n['default'] );
2130 bb_load_default_textdomain();
2131 }
2132
2133 $installation_log[] = '>>>>>> ' . __( 'Topic:' ) . ' ' . $topic_title;
2134 $installation_log[] = '>>>>>>>>> ' . __( 'Post:' ) . ' ' . $post_text;
2135 } else {
2136 $installation_log[] = '>>> ' . __( 'Forum could not be created!' );
2137 $error_log[] = __( 'Forum could not be created!' );
2138 }
2139 } else {
2140 $installation_log[] = '>>> ' . __( 'There are existing forums in this database.' );
2141 $installation_log[] = '>>>>>> ' . __( 'No new forum created.' );
2142 $error_log[] = __( 'Forums already exist!' );
2143 }
2144
2145 if ( defined( 'BB_PLUGIN_DIR' ) && BB_PLUGIN_DIR && !file_exists( BB_PLUGIN_DIR ) ) {
2146 // Just suppress errors as this is not critical
2147 if ( @mkdir( BB_PLUGIN_DIR, 0755 ) ) {
2148 $installation_log[] = '>>> ' . sprintf( __( 'Making plugin directory at %s.' ), BB_PLUGIN_DIR );
2149 }
2150 }
2151
2152 if ( defined( 'BB_THEME_DIR' ) && BB_THEME_DIR && !file_exists( BB_THEME_DIR ) ) {
2153 // Just suppress errors as this is not critical
2154 if ( @mkdir( BB_THEME_DIR, 0755 ) ) {
2155 $installation_log[] = '>>> ' . sprintf( __( 'Making theme directory at %s.' ), BB_THEME_DIR );
2156 }
2157 }
2158
2159 if ( $keymaster_created ) {
2160 $keymaster_email_message = sprintf(
2161 __( "Your new bbPress site has been successfully set up at:\n\n%1\$s\n\nYou can log in to the key master account with the following information:\n\nUsername: %2\$s\nPassword: %3\$s\n\nWe hope you enjoy your new forums. Thanks!\n\n--The bbPress Team\nhttp://bbpress.org/" ),
2162 bb_get_uri( null, null, BB_URI_CONTEXT_TEXT ),
2163 $data3['keymaster_user_login']['value'],
2164 $data4['keymaster_user_password']['value']
2165 );
2166
2167 if ( bb_mail( $data3['keymaster_user_email']['value'], __( 'New bbPress installation' ), $keymaster_email_message ) ) {
2168 $installation_log[] = '>>> ' . __( 'Key master email sent' );
2169 } else {
2170 $installation_log[] = '>>> ' . __( 'Key master email not sent!' );
2171 $error_log[] = __( 'Key master email not sent!' );
2172 }
2173 }
2174
2175 if ( count( $error_log ) ) {
2176 $this->strings[4]['h2'] = __( 'Installation completed with some errors!' );
2177 $this->strings[4]['messages']['error'][] = __( 'Your installation completed with some minor errors. See the error log below for more specific information.' );
2178 $installation_log[] = "\n" . __( 'There were some errors encountered during installation!' );
2179 } else {
2180 $this->strings[4]['messages']['message'][] = __( 'Your installation completed successfully.' );
2181 $installation_log[] = "\n" . __( 'Installation complete!' );
2182 }
2183
2184 $this->step_status[4] = 'complete';
2185
2186 $data4['installation_log']['value'] = join( "\n", $installation_log );
2187 $data4['error_log']['value'] = join( "\n", $error_log );
2188
2189 return 'complete';
2190 }
2191
2192 /**
2193 * Prints a text input form element.
2194 *
2195 * @param $key string The key of the data to populate the element with.
2196 * @param $direction string Optional. The text direction, only 'ltr' or 'rtl' are acceptable.
2197 * @return void
2198 **/
2199 function input_text( $key, $direction = false )
2200 {
2201 $data = $this->data[$this->step]['form'][$key];
2202
2203 $class = '';
2204 $classes = array();
2205 if ( isset( $data['note'] ) ) {
2206 $classes[] = 'has-note';
2207 }
2208 if ( isset( $data['label'] ) ) {
2209 $classes[] = 'has-label';
2210 }
2211
2212 if ( isset( $this->data[$this->step]['form'][$key]['type'] ) ) {
2213 $type = $this->data[$this->step]['form'][$key]['type'];
2214 } else {
2215 $type = 'text';
2216 }
2217 $classes[] = 'for-input-' . $type;
2218
2219 if ( isset( $this->strings[$this->step]['form_errors'][$key] ) ) {
2220 $classes[] = 'error';
2221 }
2222 if ( count( $classes ) ) {
2223 $class = ' class="' . join( ' ', $classes ) . '"';
2224 }
2225
2226 $r = "\t" . '<label id="label-' . esc_attr( $key ) . '" for="' . esc_attr( $key ) . '"' . $class . '>' . "\n";
2227
2228 if ( isset( $data['label'] ) ) {
2229 $r .= "\t\t" . '<span>' . $data['label'] . '</span>' . "\n";
2230 }
2231
2232 if ( isset( $this->strings[$this->step]['form_errors'][$key] ) ) {
2233 foreach ( $this->strings[$this->step]['form_errors'][$key] as $error ) {
2234 if ( !is_bool( $error ) ) {
2235 $r .= "\t\t" . '<span class="error">' . $error . '</span>' . "\n";
2236 }
2237 }
2238 }
2239
2240 if ( isset( $data['maxlength'] ) && is_integer( $data['maxlength'] ) ) {
2241 $maxlength = ' maxlength="' . esc_attr( $data['maxlength'] ) . '"';
2242 }
2243
2244 if ( $direction && in_array( strtolower( $direction ), array( 'ltr', 'rtl' ) ) ) {
2245 $direction = ' dir="' . esc_attr( strtolower( $direction ) ) . '"';
2246 }
2247
2248 if ( isset( $data['autocomplete'] ) ) {
2249 $autocomplete = ' autocomplete="' . esc_attr( $data['autocomplete'] ) . '"';
2250 } else {
2251 $autocomplete = '';
2252 }
2253
2254 $this->tabindex++;
2255 $r .= "\t\t" . '<input' . $direction . ' type="' . esc_attr( $type ) . '" id="' . esc_attr( $key ) . '" name="' . esc_attr( $key ) . '" class="text' . $has_note_class . '" value="' . esc_attr( $data['value'] ) . '"' . $maxlength . $autocomplete . ' tabindex="' . $this->tabindex . '" />' . "\n";
2256
2257 if ( isset( $data['note'] ) ) {
2258 $r .= "\t\t" . '<a class="note-toggle" href="javascript:void(0);" onclick="toggleNote(\'note-' . esc_attr( $key ) . '\');">?</a>' . "\n";
2259 $r .= "\t\t" . '<p id="note-' . esc_attr( $key ) . '" class="note" style="display:none">' . $data['note'] . '</p>' . "\n";
2260 }
2261
2262 $r .= "\t\t" . '<div class="clear"></div>' . "\n";
2263 $r .= "\t" . '</label>' . "\n";
2264
2265 echo $r;
2266 }
2267
2268 /**
2269 * Prints a hidden input form element.
2270 *
2271 * @param $key string The key of the data to populate the element with.
2272 * @return void
2273 **/
2274 function input_hidden( $key )
2275 {
2276 $r = "\t" . '<input type="hidden" id="' . esc_attr( $key ) . '" name="' . esc_attr( $key ) . '" value="' . esc_attr( $this->data[$this->step]['form'][$key]['value'] ) . '" />' . "\n";
2277
2278 echo $r;
2279 }
2280
2281 /**
2282 * Prints a textarea form element.
2283 *
2284 * @param $key string The key of the data to populate the element with.
2285 * @param $direction string Optional. The text direction, only 'ltr' or 'rtl' are acceptable.
2286 * @return void
2287 **/
2288 function textarea( $key, $direction = false)
2289 {
2290 $data = $this->data[$this->step]['form'][$key];
2291
2292 $class = '';
2293 $classes = array( 'for-textarea' );
2294 if ( isset( $data['note'] ) ) {
2295 $classes[] = 'has-note';
2296 }
2297 if ( isset( $data['label'] ) ) {
2298 $classes[] = 'has-label';
2299 }
2300 if ( count( $classes ) ) {
2301 $class = ' class="' . join( ' ', $classes ) . '"';
2302 }
2303
2304 $r = "\t" . '<label id="label-' . esc_attr( $key ) . '"' . $class . ' for="' . esc_attr( $key ) . '">' . "\n";
2305
2306 if ( isset( $data['label'] ) ) {
2307 $r .= "\t\t" . '<span>' . $data['label'] . '</span>' . "\n";
2308 }
2309
2310 if ( isset( $data['note'] ) ) {
2311 $r .= "\t\t" . '<a class="note-toggle" href="javascript:void(0);" onclick="toggleNote(\'note-' . esc_attr( $key ) . '\');">?</a>' . "\n";
2312 $r .= "\t\t" . '<p id="note-' . esc_attr( $key ) . '" class="note" style="display:none">' . $data['note'] . '</p>' . "\n";
2313 }
2314
2315 if ( $direction && in_array( strtolower( $direction ), array( 'ltr', 'rtl' ) ) ) {
2316 $direction = ' dir="' . esc_attr( strtolower( $direction ) ) . '"';
2317 }
2318
2319 $this->tabindex++;
2320 $r .= "\t\t" . '<textarea id="' . esc_attr( $key ) . '" rows="5" cols="30"' . $direction . ' tabindex="' . $this->tabindex . '">' . esc_html( $data['value'] ) . '</textarea>' . "\n";
2321
2322 $r .= "\t" . '</label>' . "\n";
2323
2324 echo $r;
2325 }
2326
2327 /**
2328 * Prints a select form element populated with options.
2329 *
2330 * @param $key string The key of the data to populate the element with.
2331 * @return void
2332 **/
2333 function select( $key )
2334 {
2335 $data = $this->data[$this->step]['form'][$key];
2336
2337 $class = '';
2338 $classes = array( 'for-select' );
2339 if ( isset( $data['note'] ) ) {
2340 $classes[] = 'has-note';
2341 }
2342 if ( isset( $data['label'] ) ) {
2343 $classes[] = 'has-label';
2344 }
2345 if ( count( $classes ) ) {
2346 $class = ' class="' . join( ' ', $classes ) . '"';
2347 }
2348
2349 $r = "\t" . '<label id="label-' . esc_attr( $key ) . '"' . $class . ' for="' . esc_attr( $key ) . '">' . "\n";
2350
2351 if ( isset( $data['label'] ) ) {
2352 $r .= "\t\t" . '<span>' . $data['label'] . '</span>' . "\n";
2353 }
2354
2355 if ( isset( $data['options'] ) ) {
2356 $r .= "\t\t" . '<select id="' . esc_attr( $key ) . '" name="' . esc_attr( $key ) . '"';
2357 if ( isset( $data['onchange'] ) ) {
2358 $r .= ' onchange="' . esc_attr( $data['onchange'] ) . '"';
2359 }
2360 $this->tabindex++;
2361 $r .= ' tabindex="' . $this->tabindex . '">' . "\n";
2362
2363 foreach ( $data['options'] as $value => $display ) {
2364 if ( $data['value'] == $value ) {
2365 $selected = ' selected="selected"';
2366 } else {
2367 $selected = '';
2368 }
2369
2370 $r .= "\t\t\t" . '<option value="' . esc_attr( $value ) . '"' . $selected . '>' . esc_html( $display ) . '</option>' . "\n";
2371 }
2372
2373 $r .= "\t\t" . '</select>';
2374 }
2375
2376 if ( isset( $data['note'] ) ) {
2377 $r .= "\t\t" . '<a class="note-toggle" href="javascript:void(0);" onclick="toggleNote(\'note-' . esc_attr( $key ) . '\');">?</a>' . "\n";
2378 $r .= "\t\t" . '<p id="note-' . esc_attr( $key ) . '" class="note" style="display:none">' . $data['note'] . '</p>' . "\n";
2379 }
2380
2381 $r .= "\t\t" . '<div class="clear"></div>' . "\n";
2382 $r .= "\t" . '</label>' . "\n";
2383
2384 echo $r;
2385 }
2386
2387 /**
2388 * Prints an appropriate language selection form element if there are any available.
2389 *
2390 * @return void
2391 **/
2392 function select_language()
2393 {
2394 if ( count( $this->languages ) > 1 ) {
2395 $this->data[1]['form']['bb_lang']['value'] = $this->language;
2396 $this->data[1]['form']['bb_lang']['options'] = $this->languages;
2397 $this->select( 'bb_lang' );
2398 } else {
2399 $this->data[1]['form']['bb_lang']['value'] = 'en_US';
2400 $this->input_hidden( 'bb_lang' );
2401 }
2402 }
2403
2404 /**
2405 * Prints an input checkbox which controls display of an optional section of settings.
2406 *
2407 * @param string $key The identifier of the area to be toggled.
2408 * @return void
2409 **/
2410 function input_toggle( $key )
2411 {
2412 $data = $this->data[$this->step]['form'][$key];
2413
2414 $class = '';
2415 $classes = array( 'for-toggle' );
2416 if ( isset( $data['note'] ) ) {
2417 $classes[] = 'has-note';
2418 }
2419 if ( isset( $data['label'] ) ) {
2420 $classes[] = 'has-label';
2421 }
2422
2423 $onclick = 'toggleBlock(this, \'' . esc_js( $key . '_target' ) . '\' );';
2424 if ( isset( $data['toggle_value'] ) ) {
2425 $onclick .= ' toggleValue(this, \'' . esc_js( $data['toggle_value']['target'] ) . '\', \'' . esc_js( $data['toggle_value']['off_value'] ) . '\', \'' . esc_js( $data['toggle_value']['on_value'] ) . '\' );';
2426 }
2427
2428 $checked = $data['checked'] ? ' ' . trim( $data['checked'] ) : '';
2429
2430 if ( isset( $this->strings[$this->step]['form_errors'][$key] ) ) {
2431 $classes[] = 'error';
2432 }
2433 if ( count( $classes ) ) {
2434 $class = ' class="' . join( ' ', $classes ) . '"';
2435 }
2436
2437 $r = "\t" . '<label id="label-' . esc_attr( $key ) . '"' . $class . ' for="' . esc_attr( $key ) . '">' . "\n";
2438
2439 $r .= "\t\t" . '<span>' . "\n";
2440 $this->tabindex++;
2441 $r .= "\t\t\t" . '<input type="checkbox" id="' . esc_attr( $key ) . '" name="' . esc_attr( $key ) . '" class="checkbox" onclick="' . esc_attr( $onclick ) . '"' . $checked . ' value="1" tabindex="' . $this->tabindex . '" />' . "\n";
2442 if ( isset( $data['label'] ) ) {
2443 $r .= "\t\t\t" . $data['label'] . "\n";
2444 }
2445 $r .= "\t\t" . '</span>' . "\n";
2446
2447 if ( isset( $data['note'] ) ) {
2448 $r .= "\t\t" . '<a class="note-toggle" href="javascript:void(0);" onclick="toggleNote(\'note-' . esc_attr( $key ) . '\');">?</a>' . "\n";
2449 $r .= "\t\t" . '<p id="note-' . esc_attr( $key ) . '" class="note" style="display:none">' . $data['note'] . '</p>' . "\n";
2450 }
2451
2452 $r .= "\t\t" . '<div class="clear"></div>' . "\n";
2453 $r .= "\t" . '</label>' . "\n";
2454
2455 echo $r;
2456 }
2457
2458 /**
2459 * Prints the input buttons which post each step and optionally go back a step.
2460 *
2461 * @param string $forward The HTML element ID of the forward button.
2462 * @param string $back Optional. The HTML element ID of the back button.
2463 * @return void
2464 **/
2465 function input_buttons( $forward, $back = false, $step = false )
2466 {
2467 $data_back = $back ? $this->data[$this->step]['form'][$back] : false;
2468 $data_forward = $this->data[$this->step]['form'][$forward];
2469
2470 $r = '<fieldset class="buttons">' . "\n";
2471
2472 if ( !$step ) {
2473 $step = $this->step;
2474 }
2475 $r .= "\t" . '<input type="hidden" id="step" name="step" value="' . (int) $step . '" />' . "\n";
2476
2477 if ( $back) {
2478 $r .= "\t" . '<label id="label-' . esc_attr( $back ) . '" for="' . esc_attr( $back ) . '" class="back">' . "\n";
2479 $this->tabindex++;
2480 $r .= "\t\t" . '<input type="submit" id="' . esc_attr( $back ) . '" name="' . esc_attr( $back ) . '" class="button" value="' . esc_attr( $data_back['value'] ) . '" tabindex="' . $this->tabindex . '" />' . "\n";
2481 $r .= "\t" . '</label>' . "\n";
2482 }
2483
2484 $r .= "\t" . '<label id="label-' . esc_attr( $forward ) . '" for="' . esc_attr( $forward ) . '" class="forward">' . "\n";
2485 $this->tabindex++;
2486 $r .= "\t\t" . '<input type="submit" id="' . esc_attr( $forward ) . '" name="' . esc_attr( $forward ) . '" class="button" value="' . esc_attr( $data_forward['value'] ) . '" tabindex="' . $this->tabindex . '" />' . "\n";
2487 $r .= "\t" . '</label>' . "\n";
2488
2489 $r .= '</fieldset>' . "\n";
2490
2491 echo $r;
2492 }
2493
2494 /**
2495 * Prints hidden input elements containing the data inputted in a given step.
2496 *
2497 * @param integer $step Optional. The number of the step whose hidden inputs should be printed.
2498 * @return void
2499 **/
2500 function hidden_step_inputs( $step = false )
2501 {
2502 if ( !$step ) {
2503 $step = $this->step;
2504 } elseif ( $step !== $this->step ) {
2505 $this->inject_form_values_into_data( $step );
2506 }
2507
2508 $data = $this->data[$step]['form'];
2509
2510 $r = '<fieldset>' . "\n";
2511
2512 foreach ( $data as $key => $value ) {
2513 if ( 'forward_' !== substr( $key, 0, 8 ) && 'back_' !== substr( $key, 0, 5 ) ) {
2514 $r .= "\t" . '<input type="hidden" name="' . esc_attr( $key ) . '" value="' . esc_attr( $value['value'] ) . '" />' . "\n";
2515 }
2516 }
2517
2518 $r .= '</fieldset>' . "\n";
2519
2520 echo $r;
2521 }
2522
2523 /**
2524 * Rewrites the admin user input into a select element containing existing WordPress administrators.
2525 *
2526 * @return boolean True if the select element was created, otherwise false.
2527 **/
2528 function populate_keymaster_user_login_from_user_tables()
2529 {
2530 $data =& $this->data[3]['form']['keymaster_user_login'];
2531
2532 // Get the existing WordPress admin users
2533
2534 // Setup variables and constants if available
2535 global $bb;
2536 if ( !empty( $this->data[2]['form']['wp_table_prefix']['value'] ) ) {
2537 $bb->wp_table_prefix = $this->data[2]['form']['wp_table_prefix']['value'];
2538 }
2539 if ( !empty( $this->data[2]['form']['user_bbdb_name']['value'] ) ) {
2540 $bb->user_bbdb_name = $this->data[2]['form']['user_bbdb_name']['value'];
2541 }
2542 if ( !empty( $this->data[2]['form']['user_bbdb_user']['value'] ) ) {
2543 $bb->user_bbdb_user = $this->data[2]['form']['user_bbdb_user']['value'];
2544 }
2545 if ( !empty( $this->data[2]['form']['user_bbdb_password']['value'] ) ) {
2546 $bb->user_bbdb_password = $this->data[2]['form']['user_bbdb_password']['value'];
2547 }
2548 if ( !empty( $this->data[2]['form']['user_bbdb_host']['value'] ) ) {
2549 $bb->user_bbdb_host = $this->data[2]['form']['user_bbdb_host']['value'];
2550 }
2551 if ( !empty( $this->data[2]['form']['user_bbdb_charset']['value'] ) ) {
2552 $bb->user_bbdb_charset = preg_replace( '/[^a-z0-9_-]/i', '', $this->data[2]['form']['user_bbdb_charset']['value'] );
2553 }
2554 if ( !empty( $this->data[2]['form']['user_bbdb_collate']['value'] ) ) {
2555 $bb->user_bbdb_charset = preg_replace( '/[^a-z0-9_-]/i', '', $this->data[2]['form']['user_bbdb_collate']['value'] );
2556 }
2557 if ( !empty( $this->data[2]['form']['custom_user_table']['value'] ) ) {
2558 $bb->custom_user_table = preg_replace( '/[^a-z0-9_-]/i', '', $this->data[2]['form']['custom_user_table']['value'] );
2559 }
2560 if ( !empty( $this->data[2]['form']['custom_user_meta_table']['value'] ) ) {
2561 $bb->custom_user_meta_table = preg_replace( '/[^a-z0-9_-]/i', '', $this->data[2]['form']['custom_user_meta_table']['value'] );
2562 }
2563
2564 global $bbdb;
2565 global $bb_table_prefix;
2566
2567 // Resolve the custom user tables for bpdb
2568 bb_set_custom_user_tables();
2569
2570 if ( isset( $bb->custom_databases ) && isset( $bb->custom_databases['user'] ) ) {
2571 $bbdb->add_db_server( 'user', $bb->custom_databases['user'] );
2572 }
2573
2574 // Add custom tables if required
2575 if ( isset( $bb->custom_tables['users'] ) || isset( $bb->custom_tables['usermeta'] ) ) {
2576 $bbdb->tables = array_merge( $bbdb->tables, $bb->custom_tables );
2577 if ( is_wp_error( $bbdb->set_prefix( $bb_table_prefix ) ) ) {
2578 die( __( 'Your user table prefix may only contain letters, numbers and underscores.' ) );
2579 }
2580 }
2581
2582 $bb_keymaster_meta_key = $bbdb->escape( $bb_table_prefix . 'capabilities' );
2583 $wp_administrator_meta_key = $bbdb->escape( $bb->wp_table_prefix . 'capabilities' );
2584 if ( !empty( $this->data[2]['form']['wordpress_mu_primary_blog_id']['value'] ) ) {
2585 $wp_administrator_meta_key = $bb->wp_table_prefix . $this->data[2]['form']['wordpress_mu_primary_blog_id']['value'] . '_capabilities';
2586 }
2587
2588 $keymaster_query = <<<EOQ
2589 SELECT
2590 user_login, user_email, display_name
2591 FROM
2592 $bbdb->users
2593 LEFT JOIN
2594 $bbdb->usermeta ON
2595 $bbdb->users.ID = $bbdb->usermeta.user_id
2596 WHERE
2597 (
2598 (
2599 meta_key = '$wp_administrator_meta_key' AND
2600 meta_value LIKE '%administrator%'
2601 ) OR
2602 (
2603 meta_key = '$bb_keymaster_meta_key' AND
2604 meta_value LIKE '%keymaster%'
2605 )
2606 ) AND
2607 user_email IS NOT NULL AND
2608 user_email != ''
2609 ORDER BY
2610 user_login;
2611EOQ;
2612 $bbdb->suppress_errors();
2613
2614 if ( $keymasters = $bbdb->get_results( $keymaster_query, ARRAY_A ) ) {
2615
2616 $bbdb->suppress_errors( false );
2617
2618 if ( count( $keymasters ) ) {
2619 $email_maps = '';
2620 $data['options'] = array();
2621 $data['onchange'] = 'changeKeymasterEmail( this, \'keymaster_user_email\' );';
2622 $data['note'] = __( 'Please select an existing bbPress Keymaster or WordPress administrator.' );
2623
2624 $data['options'][''] = '';
2625 foreach ( $keymasters as $keymaster ) {
2626 $email_maps .= 'emailMap[\'' . $keymaster['user_login'] . '\'] = \'' . $keymaster['user_email'] . '\';' . "\n\t\t\t\t\t\t\t\t";
2627 if ( $keymaster['display_name'] ) {
2628 $data['options'][$keymaster['user_login']] = $keymaster['user_login'] . ' (' . $keymaster['display_name'] . ')';
2629 } else {
2630 $data['options'][$keymaster['user_login']] = $keymaster['user_login'];
2631 }
2632 }
2633
2634 $this->strings[3]['scripts']['changeKeymasterEmail'] = <<<EOS
2635 <script type="text/javascript" charset="utf-8">
2636 function changeKeymasterEmail( selectObj, target ) {
2637 var emailMap = new Array;
2638 emailMap[''] = '';
2639 $email_maps
2640 var targetObj = document.getElementById( target );
2641 var selectedAdmin = selectObj.options[selectObj.selectedIndex].value;
2642 targetObj.value = emailMap[selectedAdmin];
2643 }
2644 </script>
2645EOS;
2646
2647 $this->data[3]['form']['keymaster_user_type']['value'] = 'old';
2648
2649 return true;
2650 }
2651 }
2652
2653 $bbdb->suppress_errors( false );
2654
2655 return false;
2656 }
2657
2658 /**
2659 * Sends HTTP headers and prints the page header.
2660 *
2661 * @return void
2662 **/
2663 function header()
2664 {
2665 nocache_headers();
2666
2667 bb_install_header( $this->strings[$this->step]['title'], $this->strings[$this->step]['h1'], true );
2668 }
2669
2670 /**
2671 * Prints the page footer.
2672 *
2673 * @return void
2674 **/
2675 function footer()
2676 {
2677 bb_install_footer();
2678 }
2679
2680 /**
2681 * Prints the returned messages for the current step.
2682 *
2683 * @return void
2684 **/
2685 function messages()
2686 {
2687 if ( isset( $this->strings[$this->step]['messages'] ) ) {
2688 $messages = $this->strings[$this->step]['messages'];
2689
2690 // This count works as long as $messages is only two-dimensional
2691 $count = ( count( $messages, COUNT_RECURSIVE ) - count( $messages ) );
2692 $i = 0;
2693 $r = '';
2694 foreach ( $messages as $type => $paragraphs ) {
2695 $class = $type ? $type : '';
2696
2697 foreach ( $paragraphs as $paragraph ) {
2698 $i++;
2699 $class = ( $i === $count ) ? ( $class . ' last' ) : $class;
2700 $r .= '<p class="' . esc_attr( $class ) . '">' . $paragraph . '</p>' . "\n";
2701 }
2702 }
2703 echo $r;
2704 }
2705 }
2706
2707 /**
2708 * Prints the introduction paragraphs for the current step.
2709 *
2710 * @return void
2711 **/
2712 function intro()
2713 {
2714 if ( 'incomplete' == $this->step_status[$this->step] && isset( $this->strings[$this->step]['intro'] ) ) {
2715 $messages = $this->strings[$this->step]['intro'];
2716 $count = count( $messages );
2717 $i = 0;
2718 $r = '';
2719 foreach ( $messages as $paragraph ) {
2720 $i++;
2721 $class = ( $i === $count ) ? 'intro last' : 'intro';
2722 $r .= '<p class="' . $class . '">' . $paragraph . '</p>' . "\n";
2723 }
2724 echo $r;
2725 }
2726 }
2727
2728 /**
2729 * Prints the standard header for each step.
2730 *
2731 * @param integer $step The number of the step whose header should be printed.
2732 * @return void
2733 **/
2734 function step_header( $step )
2735 {
2736 $class = ( $step == $this->step ) ? 'open' : 'closed';
2737
2738 $r = '<div id="' . esc_attr( 'step' . $step ) . '" class="' . $class . '">' . "\n";
2739 $r .= '<h2 class="' . $class . '">' . $this->strings[$step]['h2'] . '</h2>' . "\n";
2740 $r .= '<div>' . "\n";
2741
2742 if ( $step < $this->step && $this->strings[$step]['status'] ) {
2743 $r .= '<p class="status">' . $this->strings[$step]['status'] . '</p>' . "\n";
2744 }
2745
2746 echo $r;
2747
2748 if ( $step == $this->step ) {
2749 $this->intro();
2750 }
2751
2752 $this->tabindex = 0;
2753 }
2754
2755 /**
2756 * Prints the standard step footer.
2757 *
2758 * @return void
2759 **/
2760 function step_footer()
2761 {
2762 $r = '</div></div>' . "\n";
2763
2764 echo $r;
2765 }
2766} // END class BB_Install