[ Index ] |
PHP Cross Reference of BuddyPress |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Core bbPress functions. 4 * 5 * @package bbPress 6 */ 7 8 9 10 /** 11 * Initialization functions mostly called in bb-settings.php 12 */ 13 14 /** 15 * Marks things as deprecated and informs when they have been used. 16 * 17 * @since 0.9 18 * 19 * @param string $type The type of thing that was attempted: function, class::function, constant, variable or page. 20 * @param string $name The thing that was called. 21 * @param string $replacement Optional. The thing that should have been called. 22 * @uses $bb_log BP_Log logging object. 23 */ 24 function bb_log_deprecated( $type, $name, $replacement = 'none' ) { 25 global $bb_log; 26 $bb_log->notice( sprintf( __( 'Using deprecated bbPress %1$s - %2$s - replace with - %3$s' ), $type, $name, $replacement ) ); 27 28 if ( $bb_log->level & BP_LOG_DEBUG && $bb_log->level & BP_LOG_NOTICE ) { // Only compute the location if we're going to log it. 29 $backtrace = debug_backtrace(); 30 31 $file = $backtrace[2]['file']; 32 33 if ( substr( $file, 0, strlen( BB_PATH ) - 1 ) == rtrim( BB_PATH, '\\/') ) 34 $file = substr( $file, strlen( BB_PATH ) ); 35 36 $file = str_replace( '\\', '/', $file ); 37 38 // 0 = this function, 1 = the deprecated function 39 $bb_log->notice( ' ' . sprintf( __( 'on line %1$d of file %2$s' ), $backtrace[2]['line'], $file ) ); 40 } 41 } 42 43 /** 44 * Sanitizes user input en-masse. 45 * 46 * @param mixed $array The array of values or a single value to sanitize, usually a global variable like $_GET or $_POST. 47 * @param boolean $trim Optional. Whether to trim the value or not. Default is true. 48 * @return mixed The sanitized data. 49 */ 50 function bb_global_sanitize( $array, $trim = true ) 51 { 52 foreach ( $array as $k => $v ) { 53 if ( is_array( $v ) ) { 54 $array[$k] = bb_global_sanitize( $v ); 55 } else { 56 if ( !get_magic_quotes_gpc() ) { 57 $array[$k] = addslashes( $v ); 58 } 59 if ( $trim ) { 60 $array[$k] = trim( $array[$k] ); 61 } 62 } 63 } 64 65 return $array; 66 } 67 68 /** 69 * Reports whether bbPress is installed by getting forums. 70 * 71 * @return boolean True if there are forums, otherwise false. 72 */ 73 function bb_is_installed() 74 { 75 // Maybe grab all the forums and cache them 76 global $bbdb; 77 $bbdb->suppress_errors(); 78 $forums = (array) @bb_get_forums(); 79 $bbdb->suppress_errors(false); 80 81 if ( !$forums ) { 82 return false; 83 } 84 85 return true; 86 } 87 88 /** 89 * Sets the required variables to connect to custom user tables. 90 * 91 * @return boolean Always returns true. 92 */ 93 function bb_set_custom_user_tables() 94 { 95 global $bb; 96 97 // Check for older style custom user table 98 if ( !isset( $bb->custom_tables['users'] ) ) { // Don't stomp new setting style 99 if ( $bb->custom_user_table = bb_get_option( 'custom_user_table' ) ) { 100 if ( !isset( $bb->custom_tables ) ) { 101 $bb->custom_tables = array(); 102 } 103 $bb->custom_tables['users'] = $bb->custom_user_table; 104 } 105 } 106 107 // Check for older style custom user meta table 108 if ( !isset( $bb->custom_tables['usermeta'] ) ) { // Don't stomp new setting style 109 if ( $bb->custom_user_meta_table = bb_get_option( 'custom_user_meta_table' ) ) { 110 if ( !isset( $bb->custom_tables ) ) { 111 $bb->custom_tables = array(); 112 } 113 $bb->custom_tables['usermeta'] = $bb->custom_user_meta_table; 114 } 115 } 116 117 // Check for older style wp_table_prefix 118 if ( $bb->wp_table_prefix = bb_get_option( 'wp_table_prefix' ) ) { // User has set old constant 119 if ( !isset( $bb->custom_tables ) ) { 120 $bb->custom_tables = array( 121 'users' => $bb->wp_table_prefix . 'users', 122 'usermeta' => $bb->wp_table_prefix . 'usermeta' 123 ); 124 } else { 125 if ( !isset( $bb->custom_tables['users'] ) ) { // Don't stomp new setting style 126 $bb->custom_tables['users'] = $bb->wp_table_prefix . 'users'; 127 } 128 if ( !isset( $bb->custom_tables['usermeta'] ) ) { 129 $bb->custom_tables['usermeta'] = $bb->wp_table_prefix . 'usermeta'; 130 } 131 } 132 } 133 134 if ( bb_get_option( 'wordpress_mu_primary_blog_id' ) ) { 135 $bb->wordpress_mu_primary_blog_id = bb_get_option( 'wordpress_mu_primary_blog_id' ); 136 } 137 138 // Check for older style user database 139 if ( !isset( $bb->custom_databases ) ) { 140 $bb->custom_databases = array(); 141 } 142 if ( !isset( $bb->custom_databases['user'] ) ) { 143 if ( $bb->user_bbdb_name = bb_get_option( 'user_bbdb_name' ) ) { 144 $bb->custom_databases['user']['name'] = $bb->user_bbdb_name; 145 } 146 if ( $bb->user_bbdb_user = bb_get_option( 'user_bbdb_user' ) ) { 147 $bb->custom_databases['user']['user'] = $bb->user_bbdb_user; 148 } 149 if ( $bb->user_bbdb_password = bb_get_option( 'user_bbdb_password' ) ) { 150 $bb->custom_databases['user']['password'] = $bb->user_bbdb_password; 151 } 152 if ( $bb->user_bbdb_host = bb_get_option( 'user_bbdb_host' ) ) { 153 $bb->custom_databases['user']['host'] = $bb->user_bbdb_host; 154 } 155 if ( $bb->user_bbdb_charset = bb_get_option( 'user_bbdb_charset' ) ) { 156 $bb->custom_databases['user']['charset'] = $bb->user_bbdb_charset; 157 } 158 if ( $bb->user_bbdb_collate = bb_get_option( 'user_bbdb_collate' ) ) { 159 $bb->custom_databases['user']['collate'] = $bb->user_bbdb_collate; 160 } 161 if ( isset( $bb->custom_databases['user'] ) ) { 162 if ( isset( $bb->custom_tables['users'] ) ) { 163 $bb->custom_tables['users'] = array( 'user', $bb->custom_tables['users'] ); 164 } 165 if ( isset( $bb->custom_tables['usermeta'] ) ) { 166 $bb->custom_tables['usermeta'] = array( 'user', $bb->custom_tables['usermeta'] ); 167 } 168 } 169 } 170 171 return true; 172 } 173 174 175 /* Pagination */ 176 177 /** 178 * Retrieve paginated links for pages. 179 * 180 * Technically, the function can be used to create paginated link list for any 181 * area. The 'base' argument is used to reference the url, which will be used to 182 * create the paginated links. The 'format' argument is then used for replacing 183 * the page number. It is however, most likely and by default, to be used on the 184 * archive post pages. 185 * 186 * The 'type' argument controls format of the returned value. The default is 187 * 'plain', which is just a string with the links separated by a newline 188 * character. The other possible values are either 'array' or 'list'. The 189 * 'array' value will return an array of the paginated link list to offer full 190 * control of display. The 'list' value will place all of the paginated links in 191 * an unordered HTML list. 192 * 193 * The 'total' argument is the total amount of pages and is an integer. The 194 * 'current' argument is the current page number and is also an integer. 195 * 196 * An example of the 'base' argument is "http://example.com/all_posts.php%_%" 197 * and the '%_%' is required. The '%_%' will be replaced by the contents of in 198 * the 'format' argument. An example for the 'format' argument is "?page=%#%" 199 * and the '%#%' is also required. The '%#%' will be replaced with the page 200 * number. 201 * 202 * You can include the previous and next links in the list by setting the 203 * 'prev_next' argument to true, which it is by default. You can set the 204 * previous text, by using the 'prev_text' argument. You can set the next text 205 * by setting the 'next_text' argument. 206 * 207 * If the 'show_all' argument is set to true, then it will show all of the pages 208 * instead of a short list of the pages near the current page. By default, the 209 * 'show_all' is set to false and controlled by the 'end_size' and 'mid_size' 210 * arguments. The 'end_size' argument is how many numbers on either the start 211 * and the end list edges, by default is 1. The 'mid_size' argument is how many 212 * numbers to either side of current page, but not including current page. 213 * 214 * It is possible to add query vars to the link by using the 'add_args' argument 215 * and see {@link add_query_arg()} for more information. 216 * 217 * @since 1.0 218 * 219 * @param string|array $args Optional. Override defaults. 220 * @return array|string String of page links or array of page links. 221 */ 222 function bb_paginate_links( $args = '' ) { 223 $defaults = array( 224 'base' => '%_%', // http://example.com/all_posts.php%_% : %_% is replaced by format (below) 225 'format' => '?page=%#%', // ?page=%#% : %#% is replaced by the page number 226 'total' => 1, 227 'current' => 0, 228 'show_all' => false, 229 'prev_next' => true, 230 'prev_text' => __( '« Previous' ), 231 'next_text' => __( 'Next »' ), 232 'end_size' => 1, // How many numbers on either end including the end 233 'mid_size' => 2, // How many numbers to either side of current not including current 234 'type' => 'plain', 235 'add_args' => false, // array of query args to add 236 'add_fragment' => '', 237 'n_title' => __( 'Page %d' ), // Not from WP version 238 'prev_title' => __( 'Previous page' ), // Not from WP version 239 'next_title' => __( 'Next page' ) // Not from WP version 240 ); 241 242 $args = wp_parse_args( $args, $defaults ); 243 extract( $args, EXTR_SKIP ); 244 245 // Who knows what else people pass in $args 246 $total = (int) $total; 247 if ( $total < 2 ) 248 return; 249 $current = (int) $current; 250 $end_size = 0 < (int) $end_size ? (int) $end_size : 1; // Out of bounds? Make it the default. 251 $mid_size = 0 <= (int) $mid_size ? (int) $mid_size : 2; 252 $add_args = is_array($add_args) ? $add_args : false; 253 $r = ''; 254 $page_links = array(); 255 $n = 0; 256 $dots = false; 257 258 $empty_format = ''; 259 if ( strpos( $format, '?' ) === 0 ) { 260 $empty_format = '?'; 261 } 262 263 if ( $prev_next && $current && 1 < $current ) { 264 $link = str_replace( '%_%', 2 == $current ? $empty_format : $format, $base ); 265 $link = str_replace( '%#%', $current - 1, $link ); 266 $link = str_replace( '?&', '?', $link ); 267 if ( $add_args ) 268 $link = add_query_arg( $add_args, $link ); 269 $link .= $add_fragment; 270 $page_links[] = '<a class="prev page-numbers" href="' . esc_url( $link ) . '" title="' . esc_attr( $prev_title ) . '">' . $prev_text . '</a>'; 271 } 272 273 for ( $n = 1; $n <= $total; $n++ ) { 274 if ( $n == $current ) { 275 $n_display = bb_number_format_i18n( $n ); 276 $n_display_title = esc_attr( sprintf( $n_title, $n ) ); 277 $page_links[] = '<span class="page-numbers current" title="' . $n_display_title . '">' . $n_display . '</span>'; 278 $dots = true; 279 } else { 280 if ( $show_all || ( $n <= $end_size || ( $current && $n >= $current - $mid_size && $n <= $current + $mid_size ) || $n > $total - $end_size ) ) { 281 $n_display = bb_number_format_i18n( $n ); 282 $n_display_title = esc_attr( sprintf( $n_title, $n ) ); 283 $link = str_replace( '%_%', 1 == $n ? $empty_format : $format, $base ); 284 $link = str_replace( '%#%', $n, $link ); 285 $link = str_replace( '?&', '?', $link ); 286 if ( $add_args ) 287 $link = add_query_arg( $add_args, $link ); 288 $link .= $add_fragment; 289 $page_links[] = '<a class="page-numbers" href="' . esc_url( $link ) . '" title="' . $n_display_title . '">' . $n_display . '</a>'; 290 $dots = true; 291 } elseif ( $dots && !$show_all ) { 292 $page_links[] = '<span class="page-numbers dots">…</span>'; 293 $dots = false; 294 } 295 } 296 } 297 if ( $prev_next && $current && ( $current < $total || -1 == $total ) ) { 298 $link = str_replace( '%_%', $format, $base ); 299 $link = str_replace( '%#%', $current + 1, $link ); 300 if ( $add_args ) 301 $link = add_query_arg( $add_args, $link ); 302 $link .= $add_fragment; 303 $page_links[] = '<a class="next page-numbers" href="' . esc_url( $link ) . '" title="' . esc_attr( $next_title ) . '">' . $next_text . '</a>'; 304 } 305 switch ( $type ) { 306 case 'array': 307 return $page_links; 308 break; 309 case 'list': 310 $r .= '<ul class="page-numbers">' . "\n\t" . '<li>'; 311 $r .= join( '</li>' . "\n\t" . '<li>', $page_links ); 312 $r .= '</li>' . "\n" . '</ul>' . "\n"; 313 break; 314 default: 315 $r = join( "\n", $page_links ); 316 break; 317 } 318 return $r; 319 } 320 321 function bb_get_uri_page() { 322 if ( isset($_GET['page']) && is_numeric($_GET['page']) && 1 < (int) $_GET['page'] ) 323 return (int) $_GET['page']; 324 325 if ( isset($_SERVER['PATH_INFO']) ) 326 $path = $_SERVER['PATH_INFO']; 327 else 328 if ( !$path = strtok($_SERVER['REQUEST_URI'], '?') ) 329 return 1; 330 331 if ( preg_match( '/^\/([0-9]+)\/?$/', $path, $matches ) ) { 332 $page = (int) $matches[1]; 333 if ( 1 < $page ) { 334 return $page; 335 } 336 } 337 338 if ( $page = strstr($path, '/page/') ) { 339 $page = (int) substr($page, 6); 340 if ( 1 < $page ) 341 return $page; 342 } 343 return 1; 344 } 345 346 //expects $item = 1 to be the first, not 0 347 function bb_get_page_number( $item, $per_page = 0 ) { 348 if ( !$per_page ) 349 $per_page = bb_get_option('page_topics'); 350 return intval( ceil( $item / $per_page ) ); // page 1 is the first page 351 } 352 353 354 355 /* Time */ 356 357 function bb_timer_stop($display = 0, $precision = 3) { //if called like bb_timer_stop(1), will echo $timetotal 358 global $bb_timestart, $timeend; 359 $mtime = explode(' ', microtime()); 360 $timeend = $mtime[1] + $mtime[0]; 361 $timetotal = $timeend - $bb_timestart; 362 if ($display) 363 echo bb_number_format_i18n($timetotal, $precision); 364 return bb_number_format_i18n($timetotal, $precision); 365 } 366 367 // GMT -> so many minutes ago 368 function bb_since( $original, $args = '' ) 369 { 370 $defaults = array( 371 'levels' => 1, 372 'separator' => ', ' 373 ); 374 375 // $args used to be $do_more 376 // $do_more = 0 is equivalent to $args['levels'] = 1 377 // $do_more = 1 is equivalent to $args['levels'] = 2 378 if ( !is_array( $args ) ) { 379 $args = array( 380 'levels' => abs( (integer) $args ) + 1 381 ); 382 } 383 384 $args = wp_parse_args( $args, $defaults ); 385 extract( $args, EXTR_SKIP ); 386 387 $today = (integer) time(); 388 389 if ( !is_numeric( $original ) ) { 390 if ( $today < $_original = bb_gmtstrtotime( str_replace( ',', ' ', $original ) ) ) { // Looks like bb_since was called twice 391 return $original; 392 } else { 393 $original = $_original; 394 } 395 } 396 397 $seconds = $today - ( (integer) $original ); 398 if ( 0 === $seconds ) { 399 return sprintf( _n( '%d second', '%d seconds', 0 ), 0 ); 400 } 401 402 $levels = abs( (integer) $levels ); 403 if ( 0 === $levels ) { 404 return ''; 405 } 406 407 // array of time period chunks 408 $chunks = array( 409 ( 60 * 60 * 24 * 365 ), // years 410 ( 60 * 60 * 24 * 30 ), // months 411 ( 60 * 60 * 24 * 7 ), // weeks 412 ( 60 * 60 * 24 ), // days 413 ( 60 * 60 ), // hours 414 ( 60 ), // minutes 415 ( 1 ) // seconds 416 ); 417 418 $caught = 0; 419 $parts = array(); 420 for ( $i = 0; $i < count( $chunks ); $i++ ) { 421 if ( ( $count = floor( $seconds / $chunks[$i] ) ) || $caught ) { 422 if ( $count ) { 423 $trans = array( 424 _n( '%d year', '%d years', $count ), 425 _n( '%d month', '%d months', $count ), 426 _n( '%d week', '%d weeks', $count ), 427 _n( '%d day', '%d days', $count ), 428 _n( '%d hour', '%d hours', $count ), 429 _n( '%d minute', '%d minutes', $count ), 430 _n( '%d second', '%d seconds', $count ) 431 ); 432 $parts[] = sprintf( $trans[$i], $count ); 433 } 434 $caught++; 435 $seconds = $seconds - ( $count * $chunks[$i] ); 436 } 437 if ( $caught === $levels ) { 438 break; 439 } 440 } 441 442 if ( empty( $parts ) ) { 443 return sprintf( _n( '%d second', '%d seconds', 0 ), 0 ); 444 } 445 446 return join( $separator, $parts ); 447 } 448 449 function bb_current_time( $type = 'timestamp' ) { 450 return current_time( $type, true ); 451 } 452 453 // GMT -> Local 454 // in future versions this could eaily become a user option. 455 function bb_offset_time( $time, $args = null ) { 456 if ( isset($args['format']) && 'since' == $args['format'] ) 457 return $time; 458 if ( !is_numeric($time) ) { 459 if ( -1 !== $_time = bb_gmtstrtotime( $time ) ) 460 return gmdate('Y-m-d H:i:s', $_time + bb_get_option( 'gmt_offset' ) * 3600); 461 else 462 return $time; // Perhaps should return -1 here 463 } else { 464 return $time + bb_get_option( 'gmt_offset' ) * 3600; 465 } 466 } 467 468 469 470 /* Permalinking / URLs / Paths */ 471 472 /** 473 * BB_URI_CONTEXT_* - Bitwise definitions for bb_uri() and bb_get_uri() contexts 474 * 475 * @since 1.0 476 */ 477 define( 'BB_URI_CONTEXT_NONE', 0 ); 478 define( 'BB_URI_CONTEXT_HEADER', 1 ); 479 define( 'BB_URI_CONTEXT_TEXT', 2 ); 480 define( 'BB_URI_CONTEXT_A_HREF', 4 ); 481 define( 'BB_URI_CONTEXT_FORM_ACTION', 8 ); 482 define( 'BB_URI_CONTEXT_IMG_SRC', 16 ); 483 define( 'BB_URI_CONTEXT_LINK_STYLESHEET_HREF', 32 ); 484 define( 'BB_URI_CONTEXT_LINK_ALTERNATE_HREF', 64 ); 485 define( 'BB_URI_CONTEXT_LINK_OTHER', 128 ); 486 define( 'BB_URI_CONTEXT_SCRIPT_SRC', 256 ); 487 define( 'BB_URI_CONTEXT_IFRAME_SRC', 512 ); 488 define( 'BB_URI_CONTEXT_BB_FEED', 1024 ); 489 define( 'BB_URI_CONTEXT_BB_USER_FORMS', 2048 ); 490 define( 'BB_URI_CONTEXT_BB_ADMIN', 4096 ); 491 define( 'BB_URI_CONTEXT_BB_XMLRPC', 8192 ); 492 define( 'BB_URI_CONTEXT_WP_HTTP_REQUEST', 16384 ); 493 //define( 'BB_URI_CONTEXT_*', 32768 ); // Reserved for future definitions 494 //define( 'BB_URI_CONTEXT_*', 65536 ); // Reserved for future definitions 495 //define( 'BB_URI_CONTEXT_*', 131072 ); // Reserved for future definitions 496 //define( 'BB_URI_CONTEXT_*', 262144 ); // Reserved for future definitions 497 define( 'BB_URI_CONTEXT_AKISMET', 524288 ); 498 499 /** 500 * Echo a URI based on the URI setting 501 * 502 * @since 1.0 503 * 504 * @param $resource string The directory, may include a querystring 505 * @param $query mixed The query arguments as a querystring or an associative array 506 * @param $context integer The context of the URI, use BB_URI_CONTEXT_* 507 * @return void 508 */ 509 function bb_uri( $resource = null, $query = null, $context = BB_URI_CONTEXT_A_HREF ) 510 { 511 echo apply_filters( 'bb_uri', bb_get_uri( $resource, $query, $context ), $resource, $query, $context ); 512 } 513 514 /** 515 * Return a URI based on the URI setting 516 * 517 * @since 1.0 518 * 519 * @param $resource string The directory, may include a querystring 520 * @param $query mixed The query arguments as a querystring or an associative array 521 * @param $context integer The context of the URI, use BB_URI_CONTEXT_* 522 * @return string The complete URI 523 */ 524 function bb_get_uri( $resource = null, $query = null, $context = BB_URI_CONTEXT_A_HREF ) 525 { 526 // If there is a querystring in the resource then extract it 527 if ( $resource && strpos( $resource, '?' ) !== false ) { 528 list( $_resource, $_query ) = explode( '?', trim( $resource ), 2 ); 529 $resource = $_resource; 530 $_query = wp_parse_args( $_query ); 531 } else { 532 // Make sure $_query is an array for array_merge() 533 $_query = array(); 534 } 535 536 // $query can be an array as well as a string 537 if ( $query ) { 538 if ( is_string( $query ) ) { 539 $query = ltrim( trim( $query ), '?' ); 540 } 541 $query = wp_parse_args( $query ); 542 } 543 544 // Make sure $query is an array for array_merge() 545 if ( !$query ) { 546 $query = array(); 547 } 548 549 // Merge the queries into a single array 550 $query = array_merge( $_query, $query ); 551 552 // Make sure context is an integer 553 if ( !$context || !is_integer( $context ) ) { 554 $context = BB_URI_CONTEXT_A_HREF; 555 } 556 557 // Get the base URI 558 static $_uri; 559 if( !isset( $_uri ) ) { 560 $_uri = bb_get_option( 'uri' ); 561 } 562 $uri = $_uri; 563 564 // Use https? 565 if ( 566 ( ( $context & BB_URI_CONTEXT_BB_USER_FORMS ) && force_ssl_login() ) // Force https when required on user forms 567 || 568 ( ( $context & BB_URI_CONTEXT_BB_ADMIN ) && force_ssl_admin() ) // Force https when required in admin 569 ) { 570 static $_uri_ssl; 571 if( !isset( $_uri_ssl ) ) { 572 $_uri_ssl = bb_get_option( 'uri_ssl' ); 573 } 574 $uri = $_uri_ssl; 575 } 576 577 // Add the directory 578 $uri .= ltrim( $resource, '/' ); 579 580 // Add the query string to the URI 581 $uri = add_query_arg( $query, $uri ); 582 583 return apply_filters( 'bb_get_uri', $uri, $resource, $context ); 584 } 585 586 /** 587 * Forces redirection to an SSL page when required 588 * 589 * @since 1.0 590 * 591 * @return void 592 */ 593 function bb_ssl_redirect() 594 { 595 $page = bb_get_location(); 596 597 do_action( 'bb_ssl_redirect' ); 598 599 if ( BB_IS_ADMIN ) { 600 if ( !force_ssl_admin() ) { 601 return; 602 } 603 } else { 604 switch ( $page ) { 605 case 'login-page': 606 case 'register-page': 607 if ( !force_ssl_login() ) { 608 return; 609 } 610 break; 611 case 'profile-page': 612 global $self; 613 if ( $self == 'profile-edit.php' ) { 614 if ( !force_ssl_login() ) { 615 return; 616 } 617 } else { 618 return; 619 } 620 break; 621 default: 622 return; 623 break; 624 } 625 } 626 627 if ( is_ssl() ) { 628 return; 629 } 630 631 $uri_ssl = parse_url( bb_get_option( 'uri_ssl' ) ); 632 $uri = $uri_ssl['scheme'] . '://' . $uri_ssl['host'] . $_SERVER['REQUEST_URI']; 633 bb_safe_redirect( $uri ); 634 exit; 635 } 636 637 function bb_get_path( $level = 1, $base = false, $request = false ) { 638 if ( !$request ) 639 $request = $_SERVER['REQUEST_URI']; 640 if ( is_string($request) ) 641 $request = parse_url($request); 642 if ( !is_array($request) || !isset($request['path']) ) 643 return ''; 644 645 $path = rtrim($request['path'], " \t\n\r\0\x0B/"); 646 if ( !$base ) 647 $base = rtrim(bb_get_option('path'), " \t\n\r\0\x0B/"); 648 $path = preg_replace('|' . preg_quote($base, '|') . '/?|','',$path,1); 649 if ( !$path ) 650 return ''; 651 if ( strpos($path, '/') === false ) 652 return ''; 653 654 $url = explode('/',$path); 655 if ( !isset($url[$level]) ) 656 return ''; 657 658 return urldecode($url[$level]); 659 } 660 661 function bb_find_filename( $text ) { 662 if ( preg_match('|.*?/([a-z\-]+\.php)/?.*|', $text, $matches) ) 663 return $matches[1]; 664 else { 665 $path = bb_get_option( 'path' ); 666 $text = preg_replace("#^$path#", '', $text); 667 $text = preg_replace('#/.+$#', '', $text); 668 return $text . '.php'; 669 } 670 return false; 671 } 672 673 function bb_send_headers() { 674 if ( bb_is_user_logged_in() ) 675 nocache_headers(); 676 @header('Content-Type: ' . bb_get_option( 'html_type' ) . '; charset=' . bb_get_option( 'charset' )); 677 do_action( 'bb_send_headers' ); 678 } 679 680 function bb_pingback_header() { 681 if (bb_get_option('enable_pingback')) 682 @header('X-Pingback: '. bb_get_uri('xmlrpc.php', null, BB_URI_CONTEXT_HEADER + BB_URI_CONTEXT_BB_XMLRPC)); 683 } 684 685 // Inspired by and adapted from Yung-Lung Scott YANG's http://scott.yang.id.au/2005/05/permalink-redirect/ (GPL) 686 function bb_repermalink() { 687 global $page; 688 $location = bb_get_location(); 689 $uri = $_SERVER['REQUEST_URI']; 690 if ( isset($_GET['id']) ) 691 $id = $_GET['id']; 692 else 693 $id = bb_get_path(); 694 $_original_id = $id; 695 696 do_action( 'pre_permalink', $id ); 697 698 $id = apply_filters( 'bb_repermalink', $id ); 699 700 switch ($location) { 701 case 'front-page': 702 $path = null; 703 $querystring = null; 704 if ($page > 1) { 705 if (bb_get_option( 'mod_rewrite' )) { 706 $path = 'page/' . $page; 707 } else { 708 $querystring = array('page' => $page); 709 } 710 } 711 $permalink = bb_get_uri($path, $querystring, BB_URI_CONTEXT_HEADER); 712 $issue_404 = true; 713 break; 714 case 'forum-page': 715 if (empty($id)) { 716 $permalink = bb_get_uri(null, null, BB_URI_CONTEXT_HEADER); 717 break; 718 } 719 global $forum_id, $forum; 720 $forum = bb_get_forum( $id ); 721 $forum_id = $forum->forum_id; 722 $permalink = get_forum_link( $forum->forum_id, $page ); 723 break; 724 case 'topic-edit-page': 725 case 'topic-page': 726 if (empty($id)) { 727 $permalink = bb_get_uri(null, null, BB_URI_CONTEXT_HEADER); 728 break; 729 } 730 global $topic_id, $topic; 731 $topic = get_topic( $id ); 732 $topic_id = $topic->topic_id; 733 $permalink = get_topic_link( $topic->topic_id, $page ); 734 break; 735 case 'profile-page': // This handles the admin side of the profile as well. 736 global $user_id, $user, $profile_hooks, $self; 737 if ( isset($_GET['id']) ) 738 $id = $_GET['id']; 739 elseif ( isset($_GET['username']) ) 740 $id = $_GET['username']; 741 else 742 $id = bb_get_path(); 743 $_original_id = $id; 744 745 if ( !$id ) { 746 $user = bb_get_current_user(); // Attempt to go to the current users profile 747 } else { 748 if ( bb_get_option( 'mod_rewrite' ) === 'slugs') { 749 if ( !$user = bb_get_user_by_nicename( $id ) ) { 750 $user = bb_get_user( $id ); 751 } 752 } else { 753 if ( !$user = bb_get_user( $id ) ) { 754 $user = bb_get_user_by_nicename( $id ); 755 } 756 } 757 } 758 759 if ( !$user || ( 1 == $user->user_status && !bb_current_user_can( 'moderate' ) ) ) 760 bb_die(__('User not found.'), '', 404); 761 762 $user_id = $user->ID; 763 bb_global_profile_menu_structure(); 764 $valid = false; 765 if ( $tab = isset($_GET['tab']) ? $_GET['tab'] : bb_get_path(2) ) { 766 foreach ( $profile_hooks as $valid_tab => $valid_file ) { 767 if ( $tab == $valid_tab ) { 768 $valid = true; 769 $self = $valid_file; 770 } 771 } 772 } 773 if ( $valid ) { 774 $permalink = get_profile_tab_link( $user->ID, $tab, $page ); 775 } else { 776 $permalink = get_user_profile_link( $user->ID, $page ); 777 unset($self, $tab); 778 } 779 break; 780 case 'favorites-page': 781 $permalink = get_favorites_link(); 782 break; 783 case 'tag-page': // It's not an integer and tags.php pulls double duty. 784 $id = ( isset($_GET['tag']) ) ? $_GET['tag'] : false; 785 if ( ! $id || ! bb_get_tag( (string) $id ) ) 786 $permalink = bb_get_tag_page_link(); 787 else { 788 global $tag, $tag_name; 789 $tag_name = $id; 790 $tag = bb_get_tag( (string) $id ); 791 $permalink = bb_get_tag_link( 0, $page ); // 0 => grabs $tag from global. 792 } 793 break; 794 case 'view-page': // Not an integer 795 if ( isset($_GET['view']) ) 796 $id = $_GET['view']; 797 else 798 $id = bb_get_path(); 799 $_original_id = $id; 800 global $view; 801 $view = $id; 802 $permalink = get_view_link( $view, $page ); 803 break; 804 default: 805 return; 806 break; 807 } 808 809 wp_parse_str($_SERVER['QUERY_STRING'], $args); 810 $args = urlencode_deep($args); 811 if ( $args ) { 812 $permalink = add_query_arg($args, $permalink); 813 if ( bb_get_option('mod_rewrite') ) { 814 $pretty_args = array('id', 'page', 'tag', 'tab', 'username'); // these are already specified in the path 815 if ( $location == 'view-page' ) 816 $pretty_args[] = 'view'; 817 foreach ( $pretty_args as $pretty_arg ) 818 $permalink = remove_query_arg( $pretty_arg, $permalink ); 819 } 820 } 821 822 $permalink = apply_filters( 'bb_repermalink_result', $permalink, $location ); 823 824 $domain = bb_get_option('domain'); 825 $domain = preg_replace('/^https?/', '', $domain); 826 $check = preg_replace( '|^.*' . trim($domain, ' /' ) . '|', '', $permalink, 1 ); 827 $uri = rtrim( $uri, " \t\n\r\0\x0B?" ); 828 $uri = str_replace( '/index.php', '/', $uri ); 829 830 global $bb_log; 831 $bb_log->debug($uri, 'bb_repermalink() ' . __('REQUEST_URI')); 832 $bb_log->debug($check, 'bb_repermalink() ' . __('should be')); 833 $bb_log->debug($permalink, 'bb_repermalink() ' . __('full permalink')); 834 $bb_log->debug(isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : null, 'bb_repermalink() ' . __('PATH_INFO')); 835 836 if ( $check != $uri && $check != str_replace(urlencode($_original_id), $_original_id, $uri) ) { 837 if ( $issue_404 && rtrim( $check, " \t\n\r\0\x0B/" ) !== rtrim( $uri, " \t\n\r\0\x0B/" ) ) { 838 status_header( 404 ); 839 bb_load_template( '404.php' ); 840 } else { 841 wp_redirect( $permalink ); 842 } 843 exit; 844 } 845 846 do_action( 'post_permalink', $permalink ); 847 } 848 849 /* Profile/Admin */ 850 851 function bb_global_profile_menu_structure() { 852 global $user_id, $profile_menu, $profile_hooks; 853 // Menu item name 854 // The capability required for own user to view the tab ('' to allow non logged in access) 855 // The capability required for other users to view the tab ('' to allow non logged in access) 856 // The URL of the item's file 857 // Item name for URL (nontranslated) 858 $profile_menu[0] = array(__('Edit'), 'edit_profile', 'edit_users', 'profile-edit.php', 'edit'); 859 $profile_menu[5] = array(__('Favorites'), '', '', 'favorites.php', 'favorites'); 860 861 // Create list of page plugin hook names the current user can access 862 $profile_hooks = array(); 863 foreach ($profile_menu as $profile_tab) 864 if ( bb_can_access_tab( $profile_tab, bb_get_current_user_info( 'id' ), $user_id ) ) 865 $profile_hooks[bb_sanitize_with_dashes($profile_tab[4])] = $profile_tab[3]; 866 867 do_action('bb_profile_menu'); 868 ksort($profile_menu); 869 } 870 871 function bb_add_profile_tab($tab_title, $users_cap, $others_cap, $file, $arg = false) { 872 global $profile_menu, $profile_hooks, $user_id; 873 874 $arg = $arg ? $arg : $tab_title; 875 876 $profile_tab = array($tab_title, $users_cap, $others_cap, $file, $arg); 877 $profile_menu[] = $profile_tab; 878 if ( bb_can_access_tab( $profile_tab, bb_get_current_user_info( 'id' ), $user_id ) ) 879 $profile_hooks[bb_sanitize_with_dashes($arg)] = $file; 880 } 881 882 function bb_can_access_tab( $profile_tab, $viewer_id, $owner_id ) { 883 global $bb_current_user; 884 $viewer_id = (int) $viewer_id; 885 $owner_id = (int) $owner_id; 886 if ( $viewer_id == bb_get_current_user_info( 'id' ) ) 887 $viewer =& $bb_current_user; 888 else 889 $viewer = new BP_User( $viewer_id ); 890 if ( !$viewer ) 891 return '' === $profile_tab[2]; 892 893 if ( $owner_id == $viewer_id ) { 894 if ( '' === $profile_tab[1] ) 895 return true; 896 else 897 return $viewer->has_cap($profile_tab[1]); 898 } else { 899 if ( '' === $profile_tab[2] ) 900 return true; 901 else 902 return $viewer->has_cap($profile_tab[2]); 903 } 904 } 905 906 //meta_key => (required?, Label, hCard property). Don't use user_{anything} as the name of your meta_key. 907 function bb_get_profile_info_keys( $context = null ) { 908 return apply_filters( 'get_profile_info_keys', array( 909 'first_name' => array(0, __('First name')), 910 'last_name' => array(0, __('Last name')), 911 'display_name' => array(1, __('Display name as')), 912 'user_email' => array(1, __('Email'), 'email'), 913 'user_url' => array(0, __('Website'), 'url'), 914 'from' => array(0, __('Location')), 915 'occ' => array(0, __('Occupation'), 'role'), 916 'interest' => array(0, __('Interests')), 917 ), $context ); 918 } 919 920 function bb_get_profile_admin_keys( $context = null ) { 921 global $bbdb; 922 return apply_filters( 'get_profile_admin_keys', array( 923 $bbdb->prefix . 'title' => array(0, __('Custom Title')) 924 ), $context ); 925 } 926 927 function bb_get_assignable_caps() { 928 $caps = array(); 929 if ( $throttle_time = bb_get_option( 'throttle_time' ) ) 930 $caps['throttle'] = sprintf( __('Ignore the %d second post throttling limit'), $throttle_time ); 931 return apply_filters( 'get_assignable_caps', $caps ); 932 } 933 934 /* Views */ 935 936 function bb_get_views() { 937 global $bb_views; 938 939 $views = array(); 940 foreach ( (array) $bb_views as $view => $array ) 941 $views[$view] = $array['title']; 942 943 return $views; 944 } 945 946 function bb_register_view( $view, $title, $query_args = '', $feed = TRUE ) { 947 global $bb_views; 948 949 $view = bb_slug_sanitize( $view ); 950 $title = esc_html( $title ); 951 952 if ( !$view || !$title ) 953 return false; 954 955 $query_args = wp_parse_args( $query_args ); 956 957 if ( !$sticky_set = isset($query_args['sticky']) ) 958 $query_args['sticky'] = 'no'; 959 960 $bb_views[$view]['title'] = $title; 961 $bb_views[$view]['query'] = $query_args; 962 $bb_views[$view]['sticky'] = !$sticky_set; // No sticky set => split into stickies and not 963 $bb_views[$view]['feed'] = $feed; 964 return $bb_views[$view]; 965 } 966 967 function bb_deregister_view( $view ) { 968 global $bb_views; 969 970 $view = bb_slug_sanitize( $view ); 971 if ( !isset($bb_views[$view]) ) 972 return false; 973 974 unset($GLOBALS['bb_views'][$view]); 975 return true; 976 } 977 978 function bb_view_query( $view, $new_args = '' ) { 979 global $bb_views; 980 981 $view = bb_slug_sanitize( $view ); 982 if ( !isset($bb_views[$view]) ) 983 return false; 984 985 if ( $new_args ) { 986 $new_args = wp_parse_args( $new_args ); 987 $query_args = array_merge( $bb_views[$view]['query'], $new_args ); 988 } else { 989 $query_args = $bb_views[$view]['query']; 990 } 991 992 return new BB_Query( 'topic', $query_args, "bb_view_$view" ); 993 } 994 995 function bb_get_view_query_args( $view ) { 996 global $bb_views; 997 998 $view = bb_slug_sanitize( $view ); 999 if ( !isset($bb_views[$view]) ) 1000 return false; 1001 1002 return $bb_views[$view]['query']; 1003 } 1004 1005 function bb_register_default_views() { 1006 // no posts (besides the first one), older than 2 hours 1007 bb_register_view( 'no-replies', __('Topics with no replies'), array( 'post_count' => 1, 'started' => '<' . gmdate( 'YmdH', time() - 7200 ) ) ); 1008 bb_register_view( 'untagged' , __('Topics with no tags') , array( 'tag_count' => 0 ) ); 1009 } 1010 1011 /* Feeds */ 1012 1013 /** 1014 * Send status headers for clients supporting Conditional Get 1015 * 1016 * The function sends the Last-Modified and ETag headers for all clients. It 1017 * then checks both the If-None-Match and If-Modified-Since headers to see if 1018 * the client has used them. If so, and the ETag does matches the client ETag 1019 * or the last modified date sent by the client is newer or the same as the 1020 * generated last modified, the function sends a 304 Not Modified and exits. 1021 * 1022 * @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3 1023 * @param string $bb_last_modified Last modified time. Must be a HTTP-date 1024 */ 1025 function bb_send_304( $bb_last_modified ) { 1026 $bb_etag = '"' . md5($bb_last_modified) . '"'; 1027 @header("Last-Modified: $bb_last_modified"); 1028 @header("ETag: $bb_etag"); 1029 1030 // Support for Conditional GET 1031 if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) $client_etag = stripslashes($_SERVER['HTTP_IF_NONE_MATCH']); 1032 else $client_etag = false; 1033 1034 $client_last_modified = trim( $_SERVER['HTTP_IF_MODIFIED_SINCE']); 1035 // If string is empty, return 0. If not, attempt to parse into a timestamp 1036 $client_modified_timestamp = $client_last_modified ? bb_gmtstrtotime($client_last_modified) : 0; 1037 1038 // Make a timestamp for our most recent modification... 1039 $bb_modified_timestamp = bb_gmtstrtotime($bb_last_modified); 1040 1041 if ( ($client_last_modified && $client_etag) ? 1042 (($client_modified_timestamp >= $bb_modified_timestamp) && ($client_etag == $bb_etag)) : 1043 (($client_modified_timestamp >= $bb_modified_timestamp) || ($client_etag == $bb_etag)) ) { 1044 status_header( 304 ); 1045 exit; 1046 } 1047 } 1048 1049 /* Nonce */ 1050 1051 /** 1052 * Retrieve URL with nonce added to URL query. 1053 * 1054 * @package bbPress 1055 * @subpackage Security 1056 * @since 1.0 1057 * 1058 * @param string $actionurl URL to add nonce action 1059 * @param string $action Optional. Nonce action name 1060 * @return string URL with nonce action added. 1061 */ 1062 function bb_nonce_url( $actionurl, $action = -1 ) { 1063 $actionurl = str_replace( '&', '&', $actionurl ); 1064 $nonce = bb_create_nonce( $action ); 1065 return esc_html( add_query_arg( '_wpnonce', $nonce, $actionurl ) ); 1066 } 1067 1068 /** 1069 * Retrieve or display nonce hidden field for forms. 1070 * 1071 * The nonce field is used to validate that the contents of the form came from 1072 * the location on the current site and not somewhere else. The nonce does not 1073 * offer absolute protection, but should protect against most cases. It is very 1074 * important to use nonce field in forms. 1075 * 1076 * If you set $echo to true and set $referer to true, then you will need to 1077 * retrieve the {@link wp_referer_field() wp referer field}. If you have the 1078 * $referer set to true and are echoing the nonce field, it will also echo the 1079 * referer field. 1080 * 1081 * The $action and $name are optional, but if you want to have better security, 1082 * it is strongly suggested to set those two parameters. It is easier to just 1083 * call the function without any parameters, because validation of the nonce 1084 * doesn't require any parameters, but since crackers know what the default is 1085 * it won't be difficult for them to find a way around your nonce and cause 1086 * damage. 1087 * 1088 * The input name will be whatever $name value you gave. The input value will be 1089 * the nonce creation value. 1090 * 1091 * @package bbPress 1092 * @subpackage Security 1093 * @since 1.0 1094 * 1095 * @param string $action Optional. Action name. 1096 * @param string $name Optional. Nonce name. 1097 * @param bool $referer Optional, default true. Whether to set the referer field for validation. 1098 * @param bool $echo Optional, default true. Whether to display or return hidden form field. 1099 * @return string Nonce field. 1100 */ 1101 function bb_nonce_field( $action = -1, $name = "_wpnonce", $referer = true , $echo = true ) { 1102 $name = esc_attr( $name ); 1103 $nonce = bb_create_nonce( $action ); 1104 $nonce_field = '<input type="hidden" id="' . $name . '" name="' . $name . '" value="' . $nonce . '" />'; 1105 if ( $echo ) 1106 echo $nonce_field; 1107 1108 if ( $referer ) 1109 wp_referer_field( $echo, 'previous' ); 1110 1111 return $nonce_field; 1112 } 1113 1114 function bb_nonce_ays( $action ) 1115 { 1116 $title = __( 'bbPress Failure Notice' ); 1117 $html .= "\t<div id='message' class='updated fade'>\n\t<p>" . esc_html( bb_explain_nonce( $action ) ) . "</p>\n\t<p>"; 1118 if ( wp_get_referer() ) 1119 $html .= "<a href='" . remove_query_arg( 'updated', esc_url( wp_get_referer() ) ) . "'>" . __( 'Please try again.' ) . "</a>"; 1120 $html .= "</p>\n\t</div>\n"; 1121 $html .= "</body>\n</html>"; 1122 bb_die( $html, $title ); 1123 } 1124 1125 function bb_install_header( $title = '', $header = false, $logo = false ) 1126 { 1127 if ( empty($title) ) 1128 if ( function_exists('__') ) 1129 $title = __('bbPress'); 1130 else 1131 $title = 'bbPress'; 1132 1133 $uri = false; 1134 if ( function_exists('bb_get_uri') && !BB_INSTALLING ) { 1135 $uri = bb_get_uri(); 1136 $uri_stylesheet = bb_get_uri('bb-admin/install.css', null, BB_URI_CONTEXT_LINK_STYLESHEET_HREF + BB_URI_CONTEXT_BB_INSTALLER); 1137 $uri_stylesheet_rtl = bb_get_uri('bb-admin/install-rtl.css', null, BB_URI_CONTEXT_LINK_STYLESHEET_HREF + BB_URI_CONTEXT_BB_INSTALLER); 1138 $uri_logo = bb_get_uri('bb-admin/images/bbpress-logo.png', null, BB_URI_CONTEXT_IMG_SRC + BB_URI_CONTEXT_BB_INSTALLER); 1139 } 1140 1141 if (!$uri) { 1142 $uri = preg_replace('|(/bb-admin)?/[^/]+?$|', '/', $_SERVER['PHP_SELF']); 1143 $uri_stylesheet = $uri . 'bb-admin/install.css'; 1144 $uri_stylesheet_rtl = $uri . 'bb-admin/install-rtl.css'; 1145 $uri_logo = $uri . 'bb-admin/images/bbpress-logo.png'; 1146 } 1147 1148 header('Content-Type: text/html; charset=utf-8'); 1149 ?> 1150 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 1151 <html xmlns="http://www.w3.org/1999/xhtml"<?php if ( function_exists( 'bb_language_attributes' ) ) bb_language_attributes(); ?>> 1152 <head> 1153 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 1154 <title><?php echo $title; ?></title> 1155 <meta name="robots" content="noindex, nofollow" /> 1156 <link rel="stylesheet" href="<?php echo $uri_stylesheet; ?>" type="text/css" /> 1157 <?php 1158 if ( function_exists( 'bb_get_option' ) && 'rtl' == bb_get_option( 'text_direction' ) ) { 1159 ?> 1160 <link rel="stylesheet" href="<?php echo $uri_stylesheet_rtl; ?>" type="text/css" /> 1161 <?php 1162 } 1163 ?> 1164 </head> 1165 <body> 1166 <div id="container"> 1167 <?php 1168 if ( $logo ) { 1169 ?> 1170 <div class="logo"> 1171 <img src="<?php echo $uri_logo; ?>" alt="bbPress" /> 1172 </div> 1173 <?php 1174 } 1175 1176 if ( !empty($header) ) { 1177 ?> 1178 <h1> 1179 <?php echo $header; ?> 1180 </h1> 1181 <?php 1182 } 1183 } 1184 1185 function bb_install_footer() { 1186 ?> 1187 </div> 1188 </body> 1189 </html> 1190 <?php 1191 } 1192 1193 function bb_die( $message, $title = '', $header = 0 ) { 1194 global $bb_locale; 1195 1196 if ( $header && !headers_sent() ) 1197 status_header( $header ); 1198 1199 if ( function_exists( 'is_wp_error' ) && is_wp_error( $message ) ) { 1200 if ( empty( $title ) ) { 1201 $error_data = $message->get_error_data(); 1202 if ( is_array( $error_data ) && isset( $error_data['title'] ) ) 1203 $title = $error_data['title']; 1204 } 1205 $errors = $message->get_error_messages(); 1206 switch ( count( $errors ) ) : 1207 case 0 : 1208 $message = ''; 1209 break; 1210 case 1 : 1211 $message = "<p>{$errors[0]}</p>"; 1212 break; 1213 default : 1214 $message = "<ul>\n\t\t<li>" . join( "</li>\n\t\t<li>", $errors ) . "</li>\n\t</ul>"; 1215 break; 1216 endswitch; 1217 } elseif ( is_string( $message ) ) { 1218 $message = bb_autop( $message ); 1219 } 1220 1221 if ( empty($title) ) 1222 $title = __('bbPress › Error'); 1223 1224 bb_install_header( $title ); 1225 ?> 1226 <?php echo $message; ?> 1227 <?php 1228 if ($uri = bb_get_uri()) { 1229 ?> 1230 <p class="last"><?php printf( __('Back to <a href="%s">%s</a>.'), $uri, bb_get_option( 'name' ) ); ?></p> 1231 <?php 1232 } 1233 bb_install_footer(); 1234 die(); 1235 } 1236 1237 function bb_explain_nonce($action) { 1238 if ( $action !== -1 && preg_match('/([a-z]+)-([a-z]+)(_(.+))?/', $action, $matches) ) { 1239 $verb = $matches[1]; 1240 $noun = $matches[2]; 1241 1242 $trans = array(); 1243 $trans['create']['post'] = array(__('Your attempt to submit this post has failed.'), false); 1244 $trans['edit']['post'] = array(__('Your attempt to edit this post has failed.'), false); 1245 $trans['delete']['post'] = array(__('Your attempt to delete this post has failed.'), false); 1246 1247 $trans['create']['topic'] = array(__('Your attempt to create this topic has failed.'), false); 1248 $trans['resolve']['topic'] = array(__('Your attempt to change the resolution status of this topic has failed.'), false); 1249 $trans['delete']['topic'] = array(__('Your attempt to delete this topic has failed.'), false); 1250 $trans['close']['topic'] = array(__('Your attempt to change the status of this topic has failed.'), false); 1251 $trans['stick']['topic'] = array(__('Your attempt to change the sticky status of this topic has failed.'), false); 1252 $trans['move']['topic'] = array(__('Your attempt to move this topic has failed.'), false); 1253 1254 $trans['add']['tag'] = array(__('Your attempt to add this tag to this topic has failed.'), false); 1255 $trans['rename']['tag'] = array(__('Your attempt to rename this tag has failed.'), false); 1256 $trans['merge']['tag'] = array(__('Your attempt to submit these tags has failed.'), false); 1257 $trans['destroy']['tag'] = array(__('Your attempt to destroy this tag has failed.'), false); 1258 $trans['remove']['tag'] = array(__('Your attempt to remove this tag from this topic has failed.'), false); 1259 1260 $trans['toggle']['favorite'] = array(__('Your attempt to toggle your favorite status for this topic has failed.'), false); 1261 1262 $trans['edit']['profile'] = array(__("Your attempt to edit this user's profile has failed."), false); 1263 1264 $trans['add']['forum'] = array(__("Your attempt to add this forum has failed."), false); 1265 $trans['update']['forums'] = array(__("Your attempt to update your forums has failed."), false); 1266 $trans['delete']['forums'] = array(__("Your attempt to delete that forum has failed."), false); 1267 1268 $trans['do']['counts'] = array(__("Your attempt to recount these items has failed."), false); 1269 1270 $trans['switch']['theme'] = array(__("Your attempt to switch themes has failed."), false); 1271 1272 if ( isset($trans[$verb][$noun]) ) { 1273 if ( !empty($trans[$verb][$noun][1]) ) { 1274 $lookup = $trans[$verb][$noun][1]; 1275 $object = $matches[4]; 1276 if ( 'use_id' != $lookup ) 1277 $object = call_user_func($lookup, $object); 1278 return sprintf($trans[$verb][$noun][0], esc_html( $object )); 1279 } else { 1280 return $trans[$verb][$noun][0]; 1281 } 1282 } 1283 } 1284 1285 return apply_filters( 'bb_explain_nonce_' . $verb . '-' . $noun, __('Your attempt to do this has failed.'), $matches[4] ); 1286 } 1287 1288 /* DB Helpers */ 1289 1290 function bb_count_last_query( $query = '' ) { 1291 global $bbdb, $bb_last_countable_query; 1292 1293 if ( $query ) 1294 $q = $query; 1295 elseif ( $bb_last_countable_query ) 1296 $q = $bb_last_countable_query; 1297 else 1298 $q = $bbdb->last_query; 1299 1300 if ( false === strpos($q, 'SELECT') ) 1301 return false; 1302 1303 if ( false !== strpos($q, 'SQL_CALC_FOUND_ROWS') ) 1304 return (int) $bbdb->get_var( "SELECT FOUND_ROWS()" ); 1305 1306 $q_original = $q; 1307 1308 $q = preg_replace( 1309 array('/SELECT.*?\s+FROM/', '/LIMIT [0-9]+(\s*,\s*[0-9]+)?/', '/ORDER BY\s+.*$/', '/DESC/', '/ASC/'), 1310 array('SELECT COUNT(*) FROM', ''), 1311 $q 1312 ); 1313 1314 if ( preg_match( '/GROUP BY\s+(\S+)/', $q, $matches ) ) 1315 $q = str_replace( array( 'COUNT(*)', $matches[0] ), array( "COUNT(DISTINCT $matches[1])", '' ), $q ); 1316 1317 if ( !$query ) 1318 $bb_last_countable_query = ''; 1319 1320 $q = apply_filters( 'bb_count_last_query', $q, $q_original ); 1321 1322 return (int) $bbdb->get_var($q); 1323 } 1324 1325 function bb_no_where( $where ) { 1326 return; 1327 } 1328 1329 /* Plugins/Themes utility */ 1330 1331 function bb_basename( $file, $directories ) 1332 { 1333 if ( strpos( $file, '#' ) !== false ) { 1334 return $file; // It's already a basename 1335 } 1336 1337 foreach ( $directories as $type => $directory ) { 1338 if ( strpos( $file, $directory ) !== false ) { 1339 break; // Keep the $file and $directory set and use them below, nifty huh? 1340 } 1341 } 1342 1343 list( $file, $directory ) = str_replace( '\\','/', array( $file, $directory ) ); 1344 list( $file, $directory ) = preg_replace( '|/+|','/', array( $file,$directory ) ); 1345 $file = preg_replace( '|^.*' . preg_quote( $directory, '|' ) . '|', $type . '#', $file ); 1346 1347 return $file; 1348 } 1349 1350 /* Plugins */ 1351 1352 function bb_plugin_basename( $file ) 1353 { 1354 global $bb; 1355 $directories = array(); 1356 foreach ( $bb->plugin_locations as $_name => $_data ) { 1357 $directories[$_name] = $_data['dir']; 1358 } 1359 return bb_basename( $file, $directories ); 1360 } 1361 1362 function bb_register_plugin_activation_hook( $file, $function ) 1363 { 1364 $file = bb_plugin_basename( $file ); 1365 add_action( 'bb_activate_plugin_' . $file, $function ); 1366 } 1367 1368 function bb_register_plugin_deactivation_hook( $file, $function ) 1369 { 1370 $file = bb_plugin_basename( $file ); 1371 add_action( 'bb_deactivate_plugin_' . $file, $function ); 1372 } 1373 1374 function bb_get_plugin_uri( $plugin = false ) 1375 { 1376 global $bb; 1377 if ( preg_match( '/^([a-z0-9_-]+)#((?:[a-z0-9\/\\_-]+.)+)(php)$/i', $plugin, $_matches ) ) { 1378 $plugin_uri = $bb->plugin_locations[$_matches[1]]['url'] . $_matches[2] . $_matches[3]; 1379 $plugin_uri = dirname( $plugin_uri ) . '/'; 1380 } else { 1381 $plugin_uri = $bb->plugin_locations['core']['url']; 1382 } 1383 return apply_filters( 'bb_get_plugin_uri', $plugin_uri, $plugin ); 1384 } 1385 1386 function bb_get_plugin_directory( $plugin = false, $path = false ) 1387 { 1388 global $bb; 1389 if ( preg_match( '/^([a-z0-9_-]+)#((?:[a-z0-9\/\\_-]+.)+)(php)$/i', $plugin, $_matches ) ) { 1390 $plugin_directory = $bb->plugin_locations[$_matches[1]]['dir'] . $_matches[2] . $_matches[3]; 1391 if ( !$path ) { 1392 $plugin_directory = dirname( $plugin_directory ) . '/'; 1393 } 1394 } else { 1395 $plugin_directory = $bb->plugin_locations['core']['dir']; 1396 } 1397 return apply_filters( 'bb_get_plugin_directory', $plugin_directory, $plugin, $path ); 1398 } 1399 1400 function bb_get_plugin_path( $plugin = false ) 1401 { 1402 $plugin_path = bb_get_plugin_directory( $plugin, true ); 1403 return apply_filters( 'bb_get_plugin_path', $plugin_path, $plugin ); 1404 } 1405 1406 /* Themes / Templates */ 1407 1408 function bb_get_active_theme_directory() 1409 { 1410 return apply_filters( 'bb_get_active_theme_directory', bb_get_theme_directory() ); 1411 } 1412 1413 function bb_get_theme_directory( $theme = false ) 1414 { 1415 global $bb; 1416 if ( !$theme ) { 1417 $theme = bb_get_option( 'bb_active_theme' ); 1418 } 1419 if ( preg_match( '/^([a-z0-9_-]+)#([\.a-z0-9_-]+)$/i', $theme, $_matches ) ) { 1420 $theme_directory = $bb->theme_locations[$_matches[1]]['dir'] . $_matches[2] . '/'; 1421 } else { 1422 $theme_directory = BB_DEFAULT_THEME_DIR; 1423 } 1424 return $theme_directory; 1425 } 1426 1427 function bb_get_themes() 1428 { 1429 $r = array(); 1430 global $bb; 1431 foreach ( $bb->theme_locations as $_name => $_data ) { 1432 if ( $themes_dir = @dir( $_data['dir'] ) ) { 1433 while( ( $theme_dir = $themes_dir->read() ) !== false ) { 1434 if ( is_file( $_data['dir'] . $theme_dir . '/style.css' ) && is_readable( $_data['dir'] . $theme_dir . '/style.css' ) && '.' != $theme_dir{0} ) { 1435 $r[$_name . '#' . $theme_dir] = $_name . '#' . $theme_dir; 1436 } 1437 } 1438 } 1439 } 1440 ksort( $r ); 1441 return $r; 1442 } 1443 1444 function bb_theme_basename( $file ) 1445 { 1446 global $bb; 1447 $directories = array(); 1448 foreach ( $bb->theme_locations as $_name => $_data ) { 1449 $directories[$_name] = $_data['dir']; 1450 } 1451 $file = bb_basename( $file, $directories ); 1452 $file = preg_replace( '|/+.*|', '', $file ); 1453 return $file; 1454 } 1455 1456 function bb_register_theme_activation_hook( $file, $function ) 1457 { 1458 $file = bb_theme_basename( $file ); 1459 add_action( 'bb_activate_theme_' . $file, $function ); 1460 } 1461 1462 function bb_register_theme_deactivation_hook( $file, $function ) 1463 { 1464 $file = bb_theme_basename( $file ); 1465 add_action( 'bb_deactivate_theme_' . $file, $function ); 1466 } 1467 1468 /* Search Functions */ 1469 // NOT bbdb::prepared 1470 function bb_user_search( $args = '' ) { 1471 global $bbdb, $bb_last_countable_query; 1472 1473 if ( $args && is_string( $args ) && false === strpos( $args, '=' ) ) { 1474 $args = array( 'query' => $args ); 1475 } 1476 1477 $defaults = array( 1478 'query' => '', 1479 'append_meta' => true, 1480 'user_login' => true, 1481 'display_name' => true, 1482 'user_nicename' => false, 1483 'user_url' => true, 1484 'user_email' => false, 1485 'user_meta' => false, 1486 'users_per_page' => false, 1487 'page' => false, 1488 'roles' => false 1489 ); 1490 1491 $args = wp_parse_args( $args, $defaults ); 1492 extract( $args, EXTR_SKIP ); 1493 1494 $query = trim( $query ); 1495 if ( $query && strlen( preg_replace( '/[^a-z0-9]/i', '', $query ) ) < 3 ) { 1496 return new WP_Error( 'invalid-query', __('Your search term was too short') ); 1497 } 1498 $query = $bbdb->escape( $query ); 1499 1500 if ( !$page ) { 1501 $page = $GLOBALS['page']; 1502 } 1503 $page = (int) $page; 1504 1505 $limit = 0 < (int) $users_per_page ? (int) $users_per_page : bb_get_option( 'page_topics' ); 1506 if ( 1 < $page ) { 1507 $limit = ($limit * ($page - 1)) . ", $limit"; 1508 } 1509 1510 $likeit = preg_replace( '/\s+/', '%', like_escape( $query ) ); 1511 1512 $fields = array(); 1513 foreach ( array( 'user_login', 'display_name', 'user_nicename', 'user_url', 'user_email' ) as $field ) { 1514 if ( $$field ) { 1515 $fields[] = $field; 1516 } 1517 } 1518 1519 if ( $roles ) { 1520 $roles = (array) $roles; 1521 } 1522 1523 if ( $roles && !empty( $roles ) && false === $role_user_ids = apply_filters( 'bb_user_search_role_user_ids', false, $roles, $args ) ) { 1524 $role_meta_key = $bbdb->escape( $bbdb->prefix . 'capabilities' ); 1525 $role_sql_terms = array(); 1526 foreach ( $roles as $role ) { 1527 $role_sql_terms[] = "`meta_value` LIKE '%" . $bbdb->escape( like_escape( $role ) ) . "%'"; 1528 } 1529 $role_sql_terms = join( ' OR ', $role_sql_terms ); 1530 $role_sql = "SELECT `user_id` FROM `$bbdb->usermeta` WHERE `meta_key` = '$role_meta_key' AND ($role_sql_terms);"; 1531 $role_user_ids = $bbdb->get_col( $role_sql, 0 ); 1532 if ( is_wp_error( $role_user_ids ) ) { 1533 return false; 1534 } 1535 } 1536 1537 if ( is_array( $role_user_ids ) && empty( $role_user_ids ) ) { 1538 return false; 1539 } 1540 1541 if ( $query && $user_meta && false === $meta_user_ids = apply_filters( 'bb_user_search_meta_user_ids', false, $args ) ) { 1542 $meta_sql = "SELECT `user_id` FROM `$bbdb->usermeta` WHERE `meta_value` LIKE ('%$likeit%')"; 1543 if ( empty( $fields ) ) { 1544 $meta_sql .= " LIMIT $limit"; 1545 } 1546 $meta_user_ids = $bbdb->get_col( $meta_sql, 0 ); 1547 if ( is_wp_error( $meta_user_ids ) ) { 1548 $meta_user_ids = false; 1549 } 1550 } 1551 1552 $user_ids = array(); 1553 if ( $role_user_ids && $meta_user_ids ) { 1554 $user_ids = array_intersect( (array) $role_user_ids, (array) $meta_user_ids ); 1555 } elseif ( $role_user_ids ) { 1556 $user_ids = (array) $role_user_ids; 1557 } elseif ( $meta_user_ids ) { 1558 $user_ids = (array) $meta_user_ids; 1559 } 1560 1561 $sql = "SELECT * FROM $bbdb->users"; 1562 1563 $sql_terms = array(); 1564 if ( $query && count( $fields ) ) { 1565 foreach ( $fields as $field ) { 1566 $sql_terms[] = "$field LIKE ('%$likeit%')"; 1567 } 1568 } 1569 1570 $user_ids_sql = ''; 1571 if ( $user_ids ) { 1572 $user_ids_sql = "AND ID IN (". join(',', $user_ids) . ")"; 1573 } 1574 1575 if ( $query && empty( $sql_terms ) ) { 1576 return new WP_Error( 'invalid-query', __( 'Your query parameters are invalid' ) ); 1577 } 1578 1579 if ( count( $sql_terms ) || count( $user_ids ) ) { 1580 $sql .= ' WHERE '; 1581 } 1582 1583 if ( count( $sql_terms ) ) { 1584 $sql .= '(' . implode( ' OR ', $sql_terms ) . ')'; 1585 } 1586 1587 if ( count( $sql_terms ) && count( $user_ids ) ) { 1588 $sql .= ' AND '; 1589 } 1590 1591 if ( count( $user_ids ) ) { 1592 $sql .= '`ID` IN (' . join( ',', $user_ids ) . ')'; 1593 } 1594 1595 $sql .= " ORDER BY user_login LIMIT $limit"; 1596 1597 $bb_last_countable_query = $sql; 1598 1599 do_action( 'bb_user_search', $sql, $args ); 1600 1601 if ( ( $users = $bbdb->get_results( $sql ) ) && $append_meta ) { 1602 return bb_append_meta( $users, 'user' ); 1603 } 1604 1605 return $users ? $users : false; 1606 } 1607 1608 function bb_tag_search( $args = '' ) { 1609 global $page, $wp_taxonomy_object; 1610 1611 if ( $args && is_string($args) && false === strpos($args, '=') ) 1612 $args = array( 'search' => $args ); 1613 1614 $defaults = array( 'search' => '', 'number' => false ); 1615 1616 $args = wp_parse_args( $args ); 1617 if ( isset( $args['query'] ) ) 1618 $args['search'] = $args['query']; 1619 if ( isset( $args['tags_per_page'] ) ) 1620 $args['number'] = $args['tags_per_page']; 1621 unset($args['query'], $args['tags_per_page']); 1622 $args = wp_parse_args( $args, $defaults ); 1623 1624 extract( $args, EXTR_SKIP ); 1625 1626 $number = (int) $number; 1627 $search = trim( $search ); 1628 if ( strlen( $search ) < 3 ) 1629 return new WP_Error( 'invalid-query', __('Your search term was too short') ); 1630 1631 $number = 0 < $number ? $number : bb_get_option( 'page_topics' ); 1632 if ( 1 < $page ) 1633 $offset = ( intval($page) - 1 ) * $number; 1634 1635 $args = array_merge( $args, compact( 'number', 'offset', 'search' ) ); 1636 1637 $terms = $wp_taxonomy_object->get_terms( 'bb_topic_tag', $args ); 1638 if ( is_wp_error( $terms ) ) 1639 return false; 1640 1641 for ( $i = 0; isset($terms[$i]); $i++ ) 1642 _bb_make_tag_compat( $terms[$i] ); 1643 1644 return $terms; 1645 } 1646 1647 1648 1649 /* Slugs */ 1650 1651 function bb_slug_increment( $slug, $existing_slug, $slug_length = 255 ) { 1652 if ( preg_match('/^.*-([0-9]+)$/', $existing_slug, $m) ) 1653 $number = (int) $m[1] + 1; 1654 else 1655 $number = 1; 1656 1657 $r = bb_encoded_utf8_cut( $slug, $slug_length - 1 - strlen($number) ); 1658 return apply_filters( 'bb_slug_increment', "$r-$number", $slug, $existing_slug, $slug_length ); 1659 } 1660 1661 function bb_get_id_from_slug( $table, $slug, $slug_length = 255 ) { 1662 global $bbdb; 1663 $tablename = $table . 's'; 1664 1665 list($_slug, $sql) = bb_get_sql_from_slug( $table, $slug, $slug_length ); 1666 1667 if ( !$_slug || !$sql ) 1668 return 0; 1669 1670 return (int) $bbdb->get_var( "SELECT $table}_id FROM {$bbdb->$tablename} WHERE $sql" ); 1671 } 1672 1673 function bb_get_sql_from_slug( $table, $slug, $slug_length = 255 ) { 1674 global $bbdb; 1675 1676 // Look for new style equiv of old style slug 1677 $_slug = bb_slug_sanitize( (string) $slug ); 1678 if ( strlen( $_slug ) < 1 ) 1679 return ''; 1680 1681 if ( strlen($_slug) > $slug_length && preg_match('/^.*-([0-9]+)$/', $_slug, $m) ) { 1682 $_slug = bb_encoded_utf8_cut( $_slug, $slug_length - 1 - strlen($number) ); 1683 $number = (int) $m[1]; 1684 $_slug = "$_slug-$number"; 1685 } 1686 1687 return array( $_slug, $bbdb->prepare( "$table}_slug = %s", $_slug ) ); 1688 } 1689 1690 1691 1692 /* Utility */ 1693 1694 function bb_flatten_array( $array, $cut_branch = 0, $keep_child_array_keys = true ) { 1695 if ( !is_array($array) ) 1696 return $array; 1697 1698 if ( empty($array) ) 1699 return null; 1700 1701 $temp = array(); 1702 foreach ( $array as $k => $v ) { 1703 if ( $cut_branch && $k == $cut_branch ) 1704 continue; 1705 if ( is_array($v) ) { 1706 if ( $keep_child_array_keys ) { 1707 $temp[$k] = true; 1708 } 1709 $temp += bb_flatten_array($v, $cut_branch, $keep_child_array_keys); 1710 } else { 1711 $temp[$k] = $v; 1712 } 1713 } 1714 return $temp; 1715 } 1716 1717 function bb_get_common_parts($string1 = false, $string2 = false, $delimiter = '', $reverse = false) { 1718 if (!$string1 || !$string2) { 1719 return false; 1720 } 1721 1722 if ($string1 === $string2) { 1723 return $string1; 1724 } 1725 1726 $string1_parts = explode( $delimiter, (string) $string1 ); 1727 $string2_parts = explode( $delimiter, (string) $string2 ); 1728 1729 if ($reverse) { 1730 $string1_parts = array_reverse( $string1_parts ); 1731 $string2_parts = array_reverse( $string2_parts ); 1732 ksort( $string1_parts ); 1733 ksort( $string2_parts ); 1734 } 1735 1736 $common_parts = array(); 1737 foreach ( $string1_parts as $index => $part ) { 1738 if ( isset( $string2_parts[$index] ) && $string2_parts[$index] == $part ) { 1739 $common_parts[] = $part; 1740 } else { 1741 break; 1742 } 1743 } 1744 1745 if (!count($common_parts)) { 1746 return false; 1747 } 1748 1749 if ($reverse) { 1750 $common_parts = array_reverse( $common_parts ); 1751 } 1752 1753 return join( $delimiter, $common_parts ); 1754 } 1755 1756 function bb_get_common_domains($domain1 = false, $domain2 = false) { 1757 if (!$domain1 || !$domain2) { 1758 return false; 1759 } 1760 1761 $domain1 = strtolower( preg_replace( '@^https?://([^/]+).*$@i', '$1', $domain1 ) ); 1762 $domain2 = strtolower( preg_replace( '@^https?://([^/]+).*$@i', '$1', $domain2 ) ); 1763 1764 return bb_get_common_parts( $domain1, $domain2, '.', true ); 1765 } 1766 1767 function bb_get_common_paths($path1 = false, $path2 = false) { 1768 if (!$path1 || !$path2) { 1769 return false; 1770 } 1771 1772 $path1 = preg_replace('@^https?://[^/]+(.*)$@i', '$1', $path1); 1773 $path2 = preg_replace('@^https?://[^/]+(.*)$@i', '$1', $path2); 1774 1775 if ($path1 === $path2) { 1776 return $path1; 1777 } 1778 1779 $path1 = trim( $path1, '/' ); 1780 $path2 = trim( $path2, '/' ); 1781 1782 $common_path = bb_get_common_parts( $path1, $path2, '/' ); 1783 1784 if ($common_path) { 1785 return '/' . $common_path . '/'; 1786 } else { 1787 return '/'; 1788 } 1789 } 1790 1791 function bb_match_domains($domain1 = false, $domain2 = false) { 1792 if (!$domain1 || !$domain2) { 1793 return false; 1794 } 1795 1796 $domain1 = strtolower( preg_replace( '@^https?://([^/]+).*$@i', '$1', $domain1 ) ); 1797 $domain2 = strtolower( preg_replace( '@^https?://([^/]+).*$@i', '$1', $domain2 ) ); 1798 1799 if ( (string) $domain1 === (string) $domain2 ) { 1800 return true; 1801 } 1802 1803 return false; 1804 } 1805 1806 function bb_glob($pattern) { 1807 // On fail return an empty array so that loops don't explode 1808 1809 if (!$pattern) 1810 return array(); 1811 1812 // May break if pattern contains forward slashes 1813 $directory = dirname( $pattern ); 1814 1815 if (!$directory) 1816 return array(); 1817 1818 if (!file_exists($directory)) 1819 return array(); 1820 1821 if (!is_dir($directory)) 1822 return array(); 1823 1824 if (!function_exists('glob')) 1825 return array(); 1826 1827 if (!is_callable('glob')) 1828 return array(); 1829 1830 $glob = glob($pattern); 1831 1832 if (!is_array($glob)) 1833 $glob = array(); 1834 1835 return $glob; 1836 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Dec 7 01:01:35 2017 | Cross-referenced by PHPXref 0.7.1 |