[ Index ] |
PHP Cross Reference of BBPress |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * bbPress Formatting 5 * 6 * @package bbPress 7 * @subpackage Formatting 8 */ 9 10 // Exit if accessed directly 11 defined( 'ABSPATH' ) || exit; 12 13 /** Kses **********************************************************************/ 14 15 /** 16 * Custom allowed tags for forum topics and replies 17 * 18 * Allows all users to post links, quotes, code, formatting, lists, and images 19 * 20 * @since 2.3.0 bbPress (r4603) 21 * 22 * @return array Associative array of allowed tags and attributes 23 */ 24 function bbp_kses_allowed_tags() { 25 26 // Filter & return 27 return (array) apply_filters( 'bbp_kses_allowed_tags', array( 28 29 // Links 30 'a' => array( 31 'href' => true, 32 'title' => true, 33 'rel' => true, 34 'target' => true 35 ), 36 37 // Quotes 38 'blockquote' => array( 39 'cite' => true 40 ), 41 42 // Code 43 'code' => array(), 44 'pre' => array( 45 'class' => true 46 ), 47 48 // Formatting 49 'em' => array(), 50 'strong' => array(), 51 'del' => array( 52 'datetime' => true, 53 'cite' => true 54 ), 55 'ins' => array( 56 'datetime' => true, 57 'cite' => true 58 ), 59 60 // Lists 61 'ul' => array(), 62 'ol' => array( 63 'start' => true, 64 ), 65 'li' => array(), 66 67 // Images 68 'img' => array( 69 'src' => true, 70 'border' => true, 71 'alt' => true, 72 'height' => true, 73 'width' => true, 74 ) 75 ) ); 76 } 77 78 /** 79 * Custom kses filter for forum topics and replies, for filtering incoming data 80 * 81 * @since 2.3.0 bbPress (r4603) 82 * 83 * @param string $data Content to filter, expected to be escaped with slashes 84 * @return string Filtered content 85 */ 86 function bbp_filter_kses( $data = '' ) { 87 return wp_slash( wp_kses( wp_unslash( $data ), bbp_kses_allowed_tags() ) ); 88 } 89 90 /** 91 * Custom kses filter for forum topics and replies, for raw data 92 * 93 * @since 2.3.0 bbPress (r4603) 94 * 95 * @param string $data Content to filter, expected to not be escaped 96 * @return string Filtered content 97 */ 98 function bbp_kses_data( $data = '' ) { 99 return wp_kses( $data, bbp_kses_allowed_tags() ); 100 } 101 102 /** Formatting ****************************************************************/ 103 104 /** 105 * Filter the topic or reply content and output code and pre tags 106 * 107 * @since 2.3.0 bbPress (r4641) 108 * 109 * @param string $content Topic and reply content 110 * @return string Partially encoded content 111 */ 112 function bbp_code_trick( $content = '' ) { 113 $content = str_replace( array( "\r\n", "\r" ), "\n", $content ); 114 $content = preg_replace_callback('|(`)(.*?)`|', 'bbp_encode_callback', $content ); 115 $content = preg_replace_callback( "!(^|\n)`(.*?)`!s", 'bbp_encode_callback', $content ); 116 117 return $content; 118 } 119 120 /** 121 * When editing a topic or reply, reverse the code trick so the textarea 122 * contains the correct editable content. 123 * 124 * @since 2.3.0 bbPress (r4641) 125 * 126 * @param string $content Topic and reply content 127 * @return string Partially encoded content 128 */ 129 function bbp_code_trick_reverse( $content = '' ) { 130 131 // Setup variables 132 $openers = array( '<p>', '<br />' ); 133 $content = preg_replace_callback( '!(<pre><code>|<code>)(.*?)(</code></pre>|</code>)!s', 'bbp_decode_callback', $content ); 134 135 // Do the do 136 $content = str_replace( $openers, '', $content ); 137 $content = str_replace( '</p>', "\n", $content ); 138 $content = str_replace( '<coded_br />', '<br />', $content ); 139 $content = str_replace( '<coded_p>', '<p>', $content ); 140 $content = str_replace( '</coded_p>', '</p>', $content ); 141 142 return $content; 143 } 144 145 /** 146 * Filter the content and encode any bad HTML tags 147 * 148 * @since 2.3.0 bbPress (r4641) 149 * 150 * @param string $content Topic and reply content 151 * @return string Partially encoded content 152 */ 153 function bbp_encode_bad( $content = '' ) { 154 155 // Setup variables 156 $content = _wp_specialchars( $content, ENT_NOQUOTES ); 157 $content = preg_split( '@(`[^`]*`)@m', $content, -1, PREG_SPLIT_NO_EMPTY + PREG_SPLIT_DELIM_CAPTURE ); 158 $allowed = bbp_kses_allowed_tags(); 159 $empty = array( 160 'br' => true, 161 'hr' => true, 162 'img' => true, 163 'input' => true, 164 'param' => true, 165 'area' => true, 166 'col' => true, 167 'embed' => true 168 ); 169 170 // Loop through allowed tags and compare for empty and normal tags 171 foreach ( $allowed as $tag => $args ) { 172 $preg = $args ? "{$tag}(?:\s.*?)?" : $tag; 173 174 // Which walker to use based on the tag and arguments 175 if ( isset( $empty[ $tag ] ) ) { 176 array_walk( $content, 'bbp_encode_empty_callback', $preg ); 177 } else { 178 array_walk( $content, 'bbp_encode_normal_callback', $preg ); 179 } 180 } 181 182 // Return the joined content array 183 return implode( '', $content ); 184 } 185 186 /** Code Callbacks ************************************************************/ 187 188 /** 189 * Callback to encode the tags in topic or reply content 190 * 191 * @since 2.3.0 bbPress (r4641) 192 * 193 * @param array $matches 194 * @return string 195 */ 196 function bbp_encode_callback( $matches = array() ) { 197 198 // Trim inline code, not pre blocks (to prevent removing indentation) 199 if ( '`' === $matches[1] ) { 200 $content = trim( $matches[2] ); 201 } else { 202 $content = $matches[2]; 203 } 204 205 // Do some replacing 206 $content = htmlspecialchars( $content, ENT_QUOTES ); 207 $content = str_replace( array( "\r\n", "\r" ), "\n", $content ); 208 $content = preg_replace( "|\n\n\n+|", "\n\n", $content ); 209 $content = str_replace( '&amp;', '&', $content ); 210 $content = str_replace( '&lt;', '<', $content ); 211 $content = str_replace( '&gt;', '>', $content ); 212 213 // Wrap in code tags 214 $content = '<code>' . $content . '</code>'; 215 216 // Wrap blocks in pre tags 217 if ('`' !== $matches[1] ) { 218 $content = "\n<pre>" . $content . "</pre>\n"; 219 } 220 221 return $content; 222 } 223 224 /** 225 * Callback to decode the tags in topic or reply content 226 * 227 * @since 2.3.0 bbPress (r4641) 228 * 229 * @param array $matches 230 * @todo Experiment with _wp_specialchars() 231 * @return string 232 */ 233 function bbp_decode_callback( $matches = array() ) { 234 235 // Setup variables 236 $trans_table = array_flip( get_html_translation_table( HTML_ENTITIES ) ); 237 $amps = array( '&', '&', '&' ); 238 $single = array( ''', ''' ); 239 $content = $matches[2]; 240 $content = strtr( $content, $trans_table ); 241 242 // Do the do 243 $content = str_replace( '<br />', '<coded_br />', $content ); 244 $content = str_replace( '<p>', '<coded_p>', $content ); 245 $content = str_replace( '</p>', '</coded_p>', $content ); 246 $content = str_replace( $amps, '&', $content ); 247 $content = str_replace( $single, "'", $content ); 248 249 // Return content wrapped in code tags 250 return '`' . $content . '`'; 251 } 252 253 /** 254 * Callback to replace empty HTML tags in a content string 255 * 256 * @since 2.3.0 bbPress (r4641) 257 * 258 * @internal Used by bbp_encode_bad() 259 * @param string $content 260 * @param string $key Not used 261 * @param string $preg 262 */ 263 function bbp_encode_empty_callback( &$content = '', $key = '', $preg = '' ) { 264 if ( strpos( $content, '`' ) !== 0 ) { 265 $content = preg_replace( "|<({$preg})\s*?/*?>|i", '<$1 />', $content ); 266 } 267 } 268 269 /** 270 * Callback to replace normal HTML tags in a content string 271 * 272 * @since 2.3.0 bbPress (r4641) 273 * 274 * @internal Used by bbp_encode_bad() 275 * 276 * @param string $content 277 * @param string $key 278 * @param string $preg 279 */ 280 function bbp_encode_normal_callback( &$content = '', $key = '', $preg = '') { 281 if ( strpos( $content, '`' ) !== 0 ) { 282 $content = preg_replace( "|<(/?{$preg})>|i", '<$1>', $content ); 283 } 284 } 285 286 /** No Follow *****************************************************************/ 287 288 /** 289 * Catches links so rel=nofollow can be added (on output, not save) 290 * 291 * @since 2.3.0 bbPress (r4865) 292 * 293 * @param string $text Post text 294 * @return string $text Text with rel=nofollow added to any links 295 */ 296 function bbp_rel_nofollow( $text = '' ) { 297 return preg_replace_callback( '|<a (.+?)>|i', 'bbp_rel_nofollow_callback', $text ); 298 } 299 300 /** 301 * Adds rel=nofollow to a link 302 * 303 * @since 2.3.0 bbPress (r4865) 304 * 305 * @param array $matches 306 * @return string $text Link with rel=nofollow added 307 */ 308 function bbp_rel_nofollow_callback( $matches = array() ) { 309 $text = $matches[1]; 310 $atts = shortcode_parse_atts( $matches[1] ); 311 $rel = 'nofollow'; 312 $home_url = home_url(); 313 314 // Bail on links that match the current domain 315 if ( preg_match( '%href=["\'](' . preg_quote( set_url_scheme( $home_url, 'http' ) ) . ')%i', $text ) || 316 preg_match( '%href=["\'](' . preg_quote( set_url_scheme( $home_url, 'https' ) ) . ')%i', $text ) 317 ) { 318 return "<a {$text}>"; 319 } 320 321 // Avoid collisions with existing "rel" attribute 322 if ( ! empty( $atts['rel'] ) ) { 323 $parts = array_map( 'trim', explode( ' ', $atts['rel'] ) ); 324 if ( false === array_search( 'nofollow', $parts ) ) { 325 $parts[] = 'nofollow'; 326 } 327 328 $rel = implode( ' ', $parts ); 329 unset( $atts['rel'] ); 330 331 $html = ''; 332 foreach ( $atts as $name => $value ) { 333 $html .= "{$name}=\"{$value}\" "; 334 } 335 336 $text = trim( $html ); 337 } 338 339 return "<a {$text} rel=\"{$rel}\">"; 340 } 341 342 /** Make Clickable ************************************************************/ 343 344 /** 345 * Convert plaintext URI to HTML links. 346 * 347 * Converts URI, www and ftp, and email addresses. Finishes by fixing links 348 * within links. 349 * 350 * This custom version of WordPress's make_clickable() skips links inside of 351 * pre and code tags. 352 * 353 * @since 2.4.0 bbPress (r4941) 354 * 355 * @param string $text Content to convert URIs. 356 * @return string Content with converted URIs. 357 */ 358 function bbp_make_clickable( $text = '' ) { 359 $r = ''; 360 $textarr = preg_split( '/(<[^<>]+>)/', $text, -1, PREG_SPLIT_DELIM_CAPTURE ); // split out HTML tags 361 $nested_code_pre = 0; // Keep track of how many levels link is nested inside <pre> or <code> 362 363 foreach ( $textarr as $piece ) { 364 365 if ( preg_match( '|^<code[\s>]|i', $piece ) || preg_match( '|^<pre[\s>]|i', $piece ) || preg_match( '|^<script[\s>]|i', $piece ) || preg_match( '|^<style[\s>]|i', $piece ) ) { 366 $nested_code_pre++; 367 } elseif ( $nested_code_pre && ( '</code>' === strtolower( $piece ) || '</pre>' === strtolower( $piece ) || '</script>' === strtolower( $piece ) || '</style>' === strtolower( $piece ) ) ) { 368 $nested_code_pre--; 369 } 370 371 if ( $nested_code_pre || empty( $piece ) || ( $piece[0] === '<' && ! preg_match( '|^<\s*[\w]{1,20}+://|', $piece ) ) ) { 372 $r .= $piece; 373 continue; 374 } 375 376 // Long strings might contain expensive edge cases ... 377 if ( 10000 < strlen( $piece ) ) { 378 // ... break it up 379 foreach ( _split_str_by_whitespace( $piece, 2100 ) as $chunk ) { // 2100: Extra room for scheme and leading and trailing paretheses 380 if ( 2101 < strlen( $chunk ) ) { 381 $r .= $chunk; // Too big, no whitespace: bail. 382 } else { 383 $r .= bbp_make_clickable( $chunk ); 384 } 385 } 386 } else { 387 $ret = " {$piece} "; // Pad with whitespace to simplify the regexes 388 $ret = apply_filters( 'bbp_make_clickable', $ret, $text ); 389 $ret = substr( $ret, 1, -1 ); // Remove our whitespace padding. 390 $r .= $ret; 391 } 392 } 393 394 // Cleanup of accidental links within links 395 return preg_replace( '#(<a([ \r\n\t]+[^>]+?>|>))<a [^>]+?>([^>]+?)</a>([^<]*)</a>#i', '$1$3$4</a>', $r ); 396 } 397 398 /** 399 * Make URLs clickable in content areas 400 * 401 * @since 2.6.0 bbPress (r6014) 402 * 403 * @param string $text 404 * @return string 405 */ 406 function bbp_make_urls_clickable( $text = '' ) { 407 $url_clickable = '~ 408 ([\\s(<.,;:!?]) # 1: Leading whitespace, or punctuation 409 ( # 2: URL 410 [\\w]{1,20}+:// # Scheme and hier-part prefix 411 (?=\S{1,2000}\s) # Limit to URLs less than about 2000 characters long 412 [\\w\\x80-\\xff#%\\~/@\\[\\]*(+=&$-]*+ # Non-punctuation URL character 413 (?: # Unroll the Loop: Only allow puctuation URL character if followed by a non-punctuation URL character 414 [\'.,;:!?)] # Punctuation URL character 415 [\\w\\x80-\\xff#%\\~/@\\[\\]*(+=&$-]++ # Non-punctuation URL character 416 )* 417 ) 418 (\)?) # 3: Trailing closing parenthesis (for parethesis balancing post processing) 419 ~xS'; 420 421 // The regex is a non-anchored pattern and does not have a single fixed starting character. 422 // Tell PCRE to spend more time optimizing since, when used on a page load, it will probably be used several times. 423 return preg_replace_callback( $url_clickable, '_make_url_clickable_cb', $text ); 424 } 425 426 /** 427 * Make FTP clickable in content areas 428 * 429 * @since 2.6.0 bbPress (r6014) 430 * 431 * @see make_clickable() 432 * 433 * @param string $text 434 * @return string 435 */ 436 function bbp_make_ftps_clickable( $text = '' ) { 437 return preg_replace_callback( '#([\s>])((www|ftp)\.[\w\\x80-\\xff\#$%&~/.\-;:=,?@\[\]+]+)#is', '_make_web_ftp_clickable_cb', $text ); 438 } 439 440 /** 441 * Make emails clickable in content areas 442 * 443 * @since 2.6.0 bbPress (r6014) 444 * 445 * @see make_clickable() 446 * 447 * @param string $text 448 * @return string 449 */ 450 function bbp_make_emails_clickable( $text = '' ) { 451 return preg_replace_callback( '#([\s>])([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})#i', '_make_email_clickable_cb', $text ); 452 } 453 454 /** 455 * Make mentions clickable in content areas 456 * 457 * @since 2.6.0 bbPress (r6014) 458 * 459 * @see make_clickable() 460 * 461 * @param string $text 462 * @return string 463 */ 464 function bbp_make_mentions_clickable( $text = '' ) { 465 return preg_replace_callback( '#([\s>])@([0-9a-zA-Z-_]+)#i', 'bbp_make_mentions_clickable_callback', $text ); 466 } 467 468 /** 469 * Callback to convert mention matches to HTML A tag. 470 * 471 * @since 2.6.0 bbPress (r6014) 472 * 473 * @param array $matches Regular expression matches in the current text blob. 474 * 475 * @return string Original text if no user exists, or link to user profile. 476 */ 477 function bbp_make_mentions_clickable_callback( $matches = array() ) { 478 479 // Bail if the match is empty malformed 480 if ( empty( $matches[2] ) || ! is_string( $matches[2] ) ) { 481 return $matches[0]; 482 } 483 484 // Get user; bail if not found 485 $user = get_user_by( 'slug', $matches[2] ); 486 if ( empty( $user ) || bbp_is_user_inactive( $user->ID ) ) { 487 return $matches[0]; 488 } 489 490 // Default anchor classes 491 $classes = array( 492 'bbp-user-mention', 493 'bbp-user-id-' . absint( $user->ID ) 494 ); 495 496 // Filter classes 497 $classes = (array) apply_filters( 'bbp_make_mentions_clickable_classes', $classes, $user ); 498 499 // Escape & implode if not empty, otherwise an empty string 500 $class_str = ! empty( $classes ) 501 ? implode( ' ', array_map( 'sanitize_html_class', $classes ) ) 502 : ''; 503 504 // Setup as a variable to avoid a potentially empty class attribute 505 $class = ! empty( $class_str ) 506 ? ' class="' . esc_attr( $class_str ) . '"' 507 : ''; 508 509 // Create the link to the user's profile 510 $html = '<a href="%1$s"' . $class . '>%2$s</a>'; 511 $url = bbp_get_user_profile_url( $user->ID ); 512 $anchor = sprintf( $html, esc_url( $url ), esc_html( $matches[0] ) ); 513 514 // Prevent this link from being followed by bots 515 $link = bbp_rel_nofollow( $anchor ); 516 517 // Concatenate the matches into the return value 518 $retval = $matches[1] . $link; 519 520 // Return the link 521 return $retval; 522 } 523 524 /** Numbers *******************************************************************/ 525 526 /** 527 * Never let a numeric value be less than zero. 528 * 529 * @since 2.6.0 bbPress (r6300) 530 * 531 * @param int $number 532 */ 533 function bbp_number_not_negative( $number = 0 ) { 534 535 // Protect against formatted strings 536 if ( is_string( $number ) ) { 537 $number = strip_tags( $number ); // No HTML 538 $number = preg_replace( '/[^0-9-]/', '', $number ); // No number-format 539 540 // Protect against objects, arrays, scalars, etc... 541 } elseif ( ! is_numeric( $number ) ) { 542 $number = 0; 543 } 544 545 // Make the number an integer 546 $int = intval( $number ); 547 548 // Pick the maximum value, never less than zero 549 $not_less_than_zero = max( 0, $int ); 550 551 // Filter & return 552 return (int) apply_filters( 'bbp_number_not_negative', $not_less_than_zero, $int, $number ); 553 } 554 555 /** 556 * A bbPress specific method of formatting numeric values 557 * 558 * @since 2.0.0 bbPress (r2486) 559 * 560 * @param string $number Number to format 561 * @param string $decimals Optional. Display decimals 562 * 563 * @return string Formatted string 564 */ 565 function bbp_number_format( $number = 0, $decimals = false, $dec_point = '.', $thousands_sep = ',' ) { 566 567 // If empty, set $number to (int) 0 568 if ( ! is_numeric( $number ) ) { 569 $number = 0; 570 } 571 572 // Filter & return 573 return apply_filters( 'bbp_number_format', number_format( $number, $decimals, $dec_point, $thousands_sep ), $number, $decimals, $dec_point, $thousands_sep ); 574 } 575 576 /** 577 * A bbPress specific method of formatting numeric values 578 * 579 * @since 2.1.0 bbPress (r3857) 580 * 581 * @param string $number Number to format 582 * @param string $decimals Optional. Display decimals 583 * 584 * @return string Formatted string 585 */ 586 function bbp_number_format_i18n( $number = 0, $decimals = false ) { 587 588 // If empty, set $number to (int) 0 589 if ( ! is_numeric( $number ) ) { 590 $number = 0; 591 } 592 593 // Filter & return 594 return apply_filters( 'bbp_number_format_i18n', number_format_i18n( $number, $decimals ), $number, $decimals ); 595 } 596 597 /** Dates *********************************************************************/ 598 599 /** 600 * Convert time supplied from database query into specified date format. 601 * 602 * @since 2.0.0 bbPress (r2544) 603 * 604 * @param string $time Time to convert 605 * @param string $d Optional. Default is 'U'. Either 'G', 'U', or php date 606 * format 607 * @param bool $translate Optional. Default is false. Whether to translate the 608 * 609 * @return string Returns timestamp 610 */ 611 function bbp_convert_date( $time, $d = 'U', $translate = false ) { 612 $new_time = mysql2date( $d, $time, $translate ); 613 614 // Filter & return 615 return apply_filters( 'bbp_convert_date', $new_time, $d, $translate, $time ); 616 } 617 618 /** 619 * Output formatted time to display human readable time difference. 620 * 621 * @since 2.0.0 bbPress (r2544) 622 * 623 * @param string $older_date Unix timestamp from which the difference begins. 624 * @param string $newer_date Optional. Unix timestamp from which the 625 * difference ends. False for current time. 626 * @param int $gmt Optional. Whether to use GMT timezone. Default is false. 627 */ 628 function bbp_time_since( $older_date, $newer_date = false, $gmt = false ) { 629 echo bbp_get_time_since( $older_date, $newer_date, $gmt ); 630 } 631 /** 632 * Return formatted time to display human readable time difference. 633 * 634 * @since 2.0.0 bbPress (r2544) 635 * 636 * @param string $older_date Unix timestamp from which the difference begins. 637 * @param string $newer_date Optional. Unix timestamp from which the 638 * difference ends. False for current time. 639 * @param int $gmt Optional. Whether to use GMT timezone. Default is false. 640 * 641 * @return string Formatted time 642 */ 643 function bbp_get_time_since( $older_date, $newer_date = false, $gmt = false ) { 644 645 // Setup the strings 646 $unknown_text = apply_filters( 'bbp_core_time_since_unknown_text', esc_html__( 'sometime', 'bbpress' ) ); 647 $right_now_text = apply_filters( 'bbp_core_time_since_right_now_text', esc_html__( 'right now', 'bbpress' ) ); 648 $ago_text = apply_filters( 'bbp_core_time_since_ago_text', esc_html__( '%s ago', 'bbpress' ) ); 649 650 // array of time period chunks 651 $chunks = array( 652 array( YEAR_IN_SECONDS, _n_noop( '%s year', '%s years', 'bbpress' ) ), 653 array( MONTH_IN_SECONDS, _n_noop( '%s month', '%s months', 'bbpress' ) ), 654 array( WEEK_IN_SECONDS, _n_noop( '%s week', '%s weeks', 'bbpress' ) ), 655 array( DAY_IN_SECONDS, _n_noop( '%s day', '%s days', 'bbpress' ) ), 656 array( HOUR_IN_SECONDS, _n_noop( '%s hour', '%s hours', 'bbpress' ) ), 657 array( MINUTE_IN_SECONDS, _n_noop( '%s minute', '%s minutes', 'bbpress' ) ), 658 array( 1, _n_noop( '%s second', '%s seconds', 'bbpress' ) ), 659 ); 660 661 // Attempt to parse non-numeric older date 662 if ( ! empty( $older_date ) && ! is_numeric( $older_date ) ) { 663 $time_chunks = explode( ':', str_replace( ' ', ':', $older_date ) ); 664 $date_chunks = explode( '-', str_replace( ' ', '-', $older_date ) ); 665 $older_date = gmmktime( (int) $time_chunks[1], (int) $time_chunks[2], (int) $time_chunks[3], (int) $date_chunks[1], (int) $date_chunks[2], (int) $date_chunks[0] ); 666 } 667 668 // Attempt to parse non-numeric newer date 669 if ( ! empty( $newer_date ) && ! is_numeric( $newer_date ) ) { 670 $time_chunks = explode( ':', str_replace( ' ', ':', $newer_date ) ); 671 $date_chunks = explode( '-', str_replace( ' ', '-', $newer_date ) ); 672 $newer_date = gmmktime( (int) $time_chunks[1], (int) $time_chunks[2], (int) $time_chunks[3], (int) $date_chunks[1], (int) $date_chunks[2], (int) $date_chunks[0] ); 673 } 674 675 // Set newer date to current time 676 if ( empty( $newer_date ) ) { 677 $newer_date = strtotime( current_time( 'mysql', $gmt ) ); 678 } 679 680 // Cast both dates to ints to avoid notices & errors with invalid values 681 $newer_date = intval( $newer_date ); 682 $older_date = intval( $older_date ); 683 684 // Difference in seconds 685 $since = intval( $newer_date - $older_date ); 686 687 // Something went wrong with date calculation and we ended up with a negative date. 688 if ( 0 > $since ) { 689 $output = $unknown_text; 690 691 // We only want to output two chunks of time here, eg: 692 // x years, xx months 693 // x days, xx hours 694 // so there's only two bits of calculation below: 695 } else { 696 697 // Default count values 698 $count = 0; 699 $count2 = 0; 700 701 // Step one: the first chunk 702 for ( $i = 0, $j = count( $chunks ); $i < $j; ++$i ) { 703 $seconds = $chunks[ $i ][0]; 704 705 // Finding the biggest chunk (if the chunk fits, break) 706 $count = floor( $since / $seconds ); 707 if ( 0 != $count ) { 708 break; 709 } 710 } 711 712 // If $i iterates all the way to $j, then the event happened 0 seconds ago 713 if ( ! isset( $chunks[ $i ] ) ) { 714 $output = $right_now_text; 715 716 } else { 717 718 // Set output var 719 $output = sprintf( translate_nooped_plural( $chunks[ $i ][1], $count, 'bbpress' ), bbp_number_format_i18n( $count ) ); 720 721 // Step two: the second chunk 722 if ( $i + 2 < $j ) { 723 $seconds2 = $chunks[ $i + 1 ][0]; 724 $count2 = floor( ( $since - ( $seconds * $count ) ) / $seconds2 ); 725 726 // Add to output var 727 if ( 0 != $count2 ) { 728 $output .= _x( ',', 'Separator in time since', 'bbpress' ) . ' '; 729 $output .= sprintf( translate_nooped_plural( $chunks[ $i + 1 ][1], $count2, 'bbpress' ), bbp_number_format_i18n( $count2 ) ); 730 } 731 } 732 733 // Empty counts, so fallback to right now 734 if ( empty( $count ) && empty( $count2 ) ) { 735 $output = $right_now_text; 736 } 737 } 738 } 739 740 // Append 'ago' to the end of time-since if not 'right now' 741 if ( $output != $right_now_text ) { 742 $output = sprintf( $ago_text, $output ); 743 } 744 745 // Filter & return 746 return apply_filters( 'bbp_get_time_since', $output, $older_date, $newer_date ); 747 } 748 749 /** Revisions *****************************************************************/ 750 751 /** 752 * Formats the reason for editing the topic/reply. 753 * 754 * Does these things: 755 * - Trimming 756 * - Removing periods from the end of the string 757 * - Trimming again 758 * 759 * @since 2.0.0 bbPress (r2782) 760 * 761 * @param string $reason Optional. User submitted reason for editing. 762 * @return string Status of topic 763 */ 764 function bbp_format_revision_reason( $reason = '' ) { 765 $reason = (string) $reason; 766 767 // Bail if reason is empty 768 if ( empty( $reason ) ) { 769 return $reason; 770 } 771 772 // Trimming 773 $reason = trim( $reason ); 774 775 // We add our own full stop. 776 while ( substr( $reason, -1 ) === '.' ) { 777 $reason = substr( $reason, 0, -1 ); 778 } 779 780 // Trim again 781 $reason = trim( $reason ); 782 783 return $reason; 784 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sat Dec 21 01:00:52 2024 | Cross-referenced by PHPXref 0.7.1 |