354 | | * @package BuddyPress Core |
355 | | * @param $text str The text to create the excerpt from |
356 | | * @param $excerpt_length Minimum excerpt length, in characters |
357 | | * @param $filter_shortcodes When true, registered shortcodes (in square brackets) will be stripped |
358 | | * @param $append_text Be sure to include a leading space |
359 | | * @return str The excerpt text |
| 356 | * This function is borrowed from CakePHP v2.0, under the MIT license. See |
| 357 | * http://book.cakephp.org/view/1469/Text#truncate-1625 |
| 358 | * |
| 359 | * ### Options: |
| 360 | * |
| 361 | * - `ending` Will be used as Ending and appended to the trimmed string |
| 362 | * - `exact` If false, $text will not be cut mid-word |
| 363 | * - `html` If true, HTML tags would be handled correctly |
| 364 | * - `filter_shortcodes` If true, shortcodes will be stripped before truncating |
| 365 | * |
| 366 | * @package BuddyPress |
| 367 | * |
| 368 | * @param string $text String to truncate. |
| 369 | * @param integer $length Length of returned string, including ellipsis. |
| 370 | * @param array $options An array of html attributes and options. |
| 371 | * @return string Trimmed string. |
361 | | function bp_create_excerpt( $text, $excerpt_length = 225, $filter_shortcodes = true, $append_text = ' […]' ) { // Fakes an excerpt if needed |
| 373 | function bp_create_excerpt( $text, $length = 225, $options = array() ) { |
| 374 | // Backward compatibility. The third argument used to be a boolean $filter_shortcodes |
| 375 | $filter_shortcodes_default = is_bool( $options ) ? $options : true; |
| 376 | |
| 377 | $defaults = array( |
| 378 | 'ending' => ' […]', |
| 379 | 'exact' => false, |
| 380 | 'html' => true, |
| 381 | 'filter_shortcodes' => $filter_shortcodes_default |
| 382 | ); |
| 383 | $r = wp_parse_args( $options, $defaults ); |
| 384 | extract( $r ); |
| 385 | |
| 386 | if ( !function_exists( 'mb_strlen' ) ) { |
| 387 | class_exists( 'Multibyte' ); |
| 388 | } |
| 389 | |
| 390 | // Save the original text, to be passed along to the filter |
373 | | if ( !empty( $matches ) ) { |
374 | | $pos = array_pop( array_pop( $matches ) ); |
375 | | $text = substr( $text, 0, $pos ) . $append_text; |
| 409 | $totalLength = mb_strlen( strip_tags( $ending ) ); |
| 410 | $openTags = array(); |
| 411 | $truncate = ''; |
| 412 | |
| 413 | // Find all the tags and put them in a stack for later use |
| 414 | preg_match_all( '/(<\/?([\w+]+)[^>]*>)?([^<>]*)/', $text, $tags, PREG_SET_ORDER ); |
| 415 | foreach ( $tags as $tag ) { |
| 416 | // Process tags that need to be closed |
| 417 | if ( !preg_match( '/img|br|input|hr|area|base|basefont|col|frame|isindex|link|meta|param/s', $tag[2] ) ) { |
| 418 | if ( preg_match( '/<[\w]+[^>]*>/s', $tag[0] ) ) { |
| 419 | array_unshift( $openTags, $tag[2] ); |
| 420 | } else if ( preg_match('/<\/([\w]+)[^>]*>/s', $tag[0], $closeTag ) ) { |
| 421 | $pos = array_search( $closeTag[1], $openTags ); |
| 422 | if ( $pos !== false ) { |
| 423 | array_splice( $openTags, $pos, 1 ); |
| 424 | } |
| 425 | } |
| 426 | } |
| 427 | $truncate .= $tag[1]; |
| 428 | |
| 429 | $contentLength = mb_strlen( preg_replace( '/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', ' ', $tag[3] ) ); |
| 430 | if ( $contentLength + $totalLength > $length ) { |
| 431 | $left = $length - $totalLength; |
| 432 | $entitiesLength = 0; |
| 433 | if ( preg_match_all( '/&[0-9a-z]{2,8};|&#[0-9]{1,7};|&#x[0-9a-f]{1,6};/i', $tag[3], $entities, PREG_OFFSET_CAPTURE ) ) { |
| 434 | foreach ( $entities[0] as $entity ) { |
| 435 | if ( $entity[1] + 1 - $entitiesLength <= $left ) { |
| 436 | $left--; |
| 437 | $entitiesLength += mb_strlen( $entity[0] ); |
| 438 | } else { |
| 439 | break; |
| 440 | } |
| 441 | } |
| 442 | } |
| 443 | |
| 444 | $truncate .= mb_substr( $tag[3], 0 , $left + $entitiesLength ); |
| 445 | break; |
| 446 | } else { |
| 447 | $truncate .= $tag[3]; |
| 448 | $totalLength += $contentLength; |
| 449 | } |
| 450 | if ( $totalLength >= $length ) { |
| 451 | break; |
| 452 | } |
| 453 | } |
| 454 | } else { |
| 455 | if ( mb_strlen( $text ) <= $length ) { |
| 456 | return $text; |
| 457 | } else { |
| 458 | $truncate = mb_substr( $text, 0, $length - mb_strlen( $ending ) ); |
| 459 | } |
| 460 | } |
| 461 | |
| 462 | // If $exact is false, we can't break on words |
| 463 | if ( !$exact ) { |
| 464 | $spacepos = mb_strrpos( $truncate, ' ' ); |
| 465 | if ( isset( $spacepos ) ) { |
| 466 | if ( $html ) { |
| 467 | $bits = mb_substr( $truncate, $spacepos ); |
| 468 | preg_match_all( '/<\/([a-z]+)>/', $bits, $droppedTags, PREG_SET_ORDER ); |
| 469 | if ( !empty( $droppedTags ) ) { |
| 470 | foreach ( $droppedTags as $closingTag ) { |
| 471 | if ( !in_array( $closingTag[1], $openTags ) ) { |
| 472 | array_unshift( $openTags, $closingTag[1] ); |
| 473 | } |
| 474 | } |
| 475 | } |
| 476 | } |
| 477 | $truncate = mb_substr( $truncate, 0, $spacepos ); |
| 478 | } |
| 479 | } |
| 480 | $truncate .= $ending; |
| 481 | |
| 482 | if ( $html ) { |
| 483 | foreach ( $openTags as $tag ) { |
| 484 | $truncate .= '</' . $tag . '>'; |
| 485 | } |