Skip to:
Content

BuddyPress.org


Ignore:
Timestamp:
06/25/2015 06:46:16 PM (10 years ago)
Author:
boonebgorges
Message:

The continuing adventures of bp_create_excerpt().

This changeset fixes a bug introduced in [9963] that caused excerpts to be
truncated too much in some cases. It also fixes some potential issues with
multibyte strings when html=true.

Fixes #6517.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/bp-core/bp-core-template.php

    r9962 r9967  
    867867    if ( empty( $r['exact'] ) ) {
    868868        // Find the position of the last space character not part of a tag.
    869         preg_match_all( '/<[a-z\!\/][^>]*>/', $truncate, $truncate_tags, PREG_OFFSET_CAPTURE );
    870         $rtruncate = strrev( $truncate );
    871         $spacepos = false;
    872         for ( $i = strlen( $rtruncate ) - 1; $i >= 0; $i-- ) {
    873             if ( ' ' !== $rtruncate[ $i ] ) {
     869        preg_match_all( '/<[a-z\!\/][^>]*>/', $truncate, $_truncate_tags, PREG_OFFSET_CAPTURE );
     870
     871        // Rekey tags by the string index of their last character.
     872        $truncate_tags = array();
     873        if ( ! empty( $_truncate_tags[0] ) ) {
     874            foreach ( $_truncate_tags[0] as $_tt ) {
     875                $_tt['start'] = $_tt[1];
     876                $_tt['end']   = $_tt[1] + strlen( $_tt[0] );
     877                $truncate_tags[ $_tt['end'] ] = $_tt;
     878            }
     879        }
     880
     881        $truncate_length = mb_strlen( $truncate );
     882        $spacepos = $truncate_length + 1;
     883        for ( $pos = $truncate_length - 1; $pos >= 0; $pos-- ) {
     884            // Word boundaries are spaces and the close of HTML tags, when the tag is preceded by a space.
     885            $is_word_boundary = ' ' === $truncate[ $pos ];
     886            if ( ! $is_word_boundary && isset( $truncate_tags[ $pos - 1 ] ) ) {
     887                $preceding_tag    = $truncate_tags[ $pos - 1 ];
     888                if ( ' ' === $truncate[ $preceding_tag['start'] - 1 ] ) {
     889                    $is_word_boundary = true;
     890                    break;
     891                }
     892            }
     893
     894            if ( ! $is_word_boundary ) {
    874895                continue;
    875896            }
    876897
    877             // Convert rpos to negative offset on forward-facing string.
    878             $pos = -1 - $i;
    879 
    880898            // If there are no tags in the string, the first space found is the right one.
    881             if ( empty( $truncate_tags[0] ) ) {
     899            if ( empty( $truncate_tags ) ) {
    882900                $spacepos = $pos;
    883901                break;
     
    885903
    886904            // Look at each tag to see if the space is inside of it.
    887             foreach ( $truncate_tags[0] as $truncate_tag ) {
    888                 $start = $truncate_tag[1];
    889                 $end   = $start + strlen( $truncate_tag[0] );
    890                 if ( $pos > $start && $pos < $end ) {
    891                     $spacepos = $pos;
    892                     break 2;
     905            $intag = false;
     906            foreach ( $truncate_tags as $tt ) {
     907                if ( $pos > $tt['start'] && $pos < $tt['end'] ) {
     908                    $intag = true;
     909                    break;
    893910                }
    894911            }
    895         }
    896 
    897         if ( false !== $spacepos ) {
    898             if ( $r['html'] ) {
    899                 $bits = mb_substr( $truncate, $spacepos );
    900                 preg_match_all( '/<\/([a-z]+)>/', $bits, $droppedTags, PREG_SET_ORDER );
    901                 if ( !empty( $droppedTags ) ) {
    902                     foreach ( $droppedTags as $closingTag ) {
    903                         if ( !in_array( $closingTag[1], $openTags ) ) {
    904                             array_unshift( $openTags, $closingTag[1] );
    905                         }
     912
     913            if ( ! $intag ) {
     914                $spacepos = $pos;
     915                break;
     916            }
     917        }
     918
     919        if ( $r['html'] ) {
     920            $bits = mb_substr( $truncate, $spacepos );
     921            preg_match_all( '/<\/([a-z]+)>/', $bits, $droppedTags, PREG_SET_ORDER );
     922            if ( !empty( $droppedTags ) ) {
     923                foreach ( $droppedTags as $closingTag ) {
     924                    if ( !in_array( $closingTag[1], $openTags ) ) {
     925                        array_unshift( $openTags, $closingTag[1] );
    906926                    }
    907927                }
    908928            }
    909             $truncate = mb_substr( $truncate, 0, $spacepos );
    910         }
     929        }
     930
     931        $truncate = rtrim( mb_substr( $truncate, 0, $spacepos ) );
    911932    }
    912933    $truncate .= $ending;
Note: See TracChangeset for help on using the changeset viewer.