Have CommentStore limit the maximum character length of comments
authorBrad Jorsch <bjorsch@wikimedia.org>
Tue, 10 Oct 2017 15:52:13 +0000 (11:52 -0400)
committerBrad Jorsch <bjorsch@wikimedia.org>
Wed, 11 Oct 2017 00:59:52 +0000 (20:59 -0400)
I92954c9 accidentally allowed comments, when CommentStore is enabled, to
be the full 65535 bytes available in the database field. This was never
intended.

There is not yet any consensus in T6714 or T6715 on just how long the
longer comments should be, for now we'll set 1000 because Tim says so.
Note this doesn't change the UI to actually allow more characters and
will only take effect once $wgCommentTableSchemaMigrationStage is raised
above MIGRATION_OLD.

Note this also doesn't make the limit configurable. That too can be done
later if needed, again along with whatever changes are necessary to the
UI to account for a variable limit.

Change-Id: I7e0c55619210ebab467436f0bb915271c0a7ccdc

includes/CommentStore.php
tests/phpunit/includes/CommentStoreTest.php

index b8a31e6..0d679d3 100644 (file)
@@ -29,10 +29,24 @@ use Wikimedia\Rdbms\IDatabase;
  */
 class CommentStore {
 
-       /** Maximum length of a comment. Longer comments will be truncated. */
+       /**
+        * Maximum length of a comment in UTF-8 characters. Longer comments will be truncated.
+        * @note This must be at least 255 and not greater than floor( MAX_COMMENT_LENGTH / 4 ).
+        */
+       const COMMENT_CHARACTER_LIMIT = 1000;
+
+       /**
+        * Maximum length of a comment in bytes. Longer comments will be truncated.
+        * @note This value is determined by the size of the underlying database field,
+        *  currently BLOB in MySQL/MariaDB.
+        */
        const MAX_COMMENT_LENGTH = 65535;
 
-       /** Maximum length of serialized data. Longer data will result in an exception. */
+       /**
+        * Maximum length of serialized data in bytes. Longer data will result in an exception.
+        * @note This value is determined by the size of the underlying database field,
+        *  currently BLOB in MySQL/MariaDB.
+        */
        const MAX_DATA_LENGTH = 65535;
 
        /**
@@ -371,6 +385,15 @@ class CommentStore {
 
                # Truncate comment in a Unicode-sensitive manner
                $comment->text = $this->lang->truncate( $comment->text, self::MAX_COMMENT_LENGTH );
+               if ( mb_strlen( $comment->text, 'UTF-8' ) > self::COMMENT_CHARACTER_LIMIT ) {
+                       $ellipsis = wfMessage( 'ellipsis' )->inLanguage( $this->lang )->escaped();
+                       if ( mb_strlen( $ellipsis ) >= self::COMMENT_CHARACTER_LIMIT ) {
+                               // WTF?
+                               $ellipsis = '...';
+                       }
+                       $maxLength = self::COMMENT_CHARACTER_LIMIT - mb_strlen( $ellipsis, 'UTF-8' );
+                       $comment->text = mb_substr( $comment->text, 0, $maxLength, 'UTF-8' ) . $ellipsis;
+               }
 
                if ( $this->stage > MIGRATION_OLD && !$comment->id ) {
                        $dbData = $comment->data;
index b0f7678..9369f30 100644 (file)
@@ -618,7 +618,7 @@ class CommentStoreTest extends MediaWikiLangTestCase {
        public function testInsertTruncation() {
                $comment = str_repeat( '💣', 16400 );
                $truncated1 = str_repeat( '💣', 63 ) . '...';
-               $truncated2 = str_repeat( '💣', 16383 ) . '...';
+               $truncated2 = str_repeat( '💣', CommentStore::COMMENT_CHARACTER_LIMIT - 3 ) . '...';
 
                $store = $this->makeStore( MIGRATION_WRITE_BOTH, 'ipb_reason' );
                $fields = $store->insert( $this->db, $comment );