Skip to:
Content

BuddyPress.org

Changeset 9968


Ignore:
Timestamp:
06/25/2015 06:50:14 PM (9 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.

Merges [9967] to the 2.3 branch for 2.3.3.

Fixes #6517.

Location:
branches/2.3
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/2.3

    • Property svn:mergeinfo changed
      /trunkmerged: 9967
  • branches/2.3/src/bp-core/bp-core-template.php

    r9963 r9968  
    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;
  • branches/2.3/tests/phpunit/testcases/core/template/bpCreateExcerpt.php

    r9963 r9968  
    5252
    5353    /**
     54     * @ticket BP6517
     55     */
     56    public function test_exact_false_should_properly_account_for_accented_characters() {
     57        $text = 'Toutes les connaissances que les hommes avaient mis sur Internet lui étaient accessible. Les grandes bibliothèques du monde entier n’avaient plus de secret pour lui. Il pouvait apprendre très vite, beaucoup plus vite que n’importe quel humain.
     58Il avait appris toutes les connaissances du monde entier, visiter tout les pays. C’est lui qui avait fait en sorte qu’Internet se déploie ainsi.';
     59        $expected = 'Toutes les connaissances que les hommes avaient mis sur Internet lui étaient accessible. Les';
     60        $this->assertSame( $expected, bp_create_excerpt( $text, 98, array(
     61            'ending' => '',
     62            'exact' => false,
     63        ) ) );
     64    }
     65
     66    /**
    5467     * @ticket BP6254
    5568     */
Note: See TracChangeset for help on using the changeset viewer.