X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FCommentStore.php;h=0d679d37db02b8c480d8cbf806e86afe33c5eae0;hb=f9814f7709e75d8a50a6b363d454da26a047339d;hp=0c86c1e871a9b40e4871105faedf4124ad38395d;hpb=9bd7c7f66058fe26e130759090e7a73beee4d3d0;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/CommentStore.php b/includes/CommentStore.php index 0c86c1e871..0d679d37db 100644 --- a/includes/CommentStore.php +++ b/includes/CommentStore.php @@ -29,6 +29,26 @@ use Wikimedia\Rdbms\IDatabase; */ class CommentStore { + /** + * 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 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; + /** * Define fields that use temporary tables for transitional purposes * @var array Keys are '$key', values are arrays with four fields: @@ -68,15 +88,21 @@ class CommentStore { /** @var array|null Cache for `self::getJoin()` */ protected $joinCache = null; + /** @var Language Language to use for comment truncation */ + protected $lang; + /** * @param string $key A key such as "rev_comment" identifying the comment * field being fetched. + * @param Language $lang Language to use for comment truncation. Defaults + * to $wgContLang. */ - public function __construct( $key ) { - global $wgCommentTableSchemaMigrationStage; + public function __construct( $key, Language $lang = null ) { + global $wgCommentTableSchemaMigrationStage, $wgContLang; $this->key = $key; $this->stage = $wgCommentTableSchemaMigrationStage; + $this->lang = $lang ?: $wgContLang; } /** @@ -355,25 +381,18 @@ class CommentStore { * @return CommentStoreComment */ public function createComment( IDatabase $dbw, $comment, array $data = null ) { - global $wgContLang; - - if ( !$comment instanceof CommentStoreComment ) { - if ( $data !== null ) { - foreach ( $data as $k => $v ) { - if ( substr( $k, 0, 1 ) === '_' ) { - throw new InvalidArgumentException( 'Keys in $data beginning with "_" are reserved' ); - } - } - } - if ( $comment instanceof Message ) { - $message = clone $comment; - $text = $message->inLanguage( $wgContLang ) // Avoid $wgForceUIMsgAsContentMsg - ->setInterfaceMessageFlag( true ) - ->text(); - $comment = new CommentStoreComment( null, $text, $message, $data ); - } else { - $comment = new CommentStoreComment( null, $comment, null, $data ); + $comment = CommentStoreComment::newUnsavedComment( $comment, $data ); + + # 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 ) { @@ -386,6 +405,11 @@ class CommentStore { } if ( $dbData !== null ) { $dbData = FormatJson::encode( (object)$dbData, false, FormatJson::ALL_OK ); + $len = strlen( $dbData ); + if ( $len > self::MAX_DATA_LENGTH ) { + $max = self::MAX_DATA_LENGTH; + throw new OverflowException( "Comment data is too long ($len bytes, maximum is $max)" ); + } } $hash = self::hash( $comment->text, $dbData ); @@ -400,11 +424,9 @@ class CommentStore { __METHOD__ ); if ( !$comment->id ) { - $comment->id = $dbw->nextSequenceValue( 'comment_comment_id_seq' ); $dbw->insert( 'comment', [ - 'comment_id' => $comment->id, 'comment_hash' => $hash, 'comment_text' => $comment->text, 'comment_data' => $dbData, @@ -432,7 +454,7 @@ class CommentStore { $comment = $this->createComment( $dbw, $comment, $data ); if ( $this->stage <= MIGRATION_WRITE_BOTH ) { - $fields[$this->key] = $comment->text; + $fields[$this->key] = $this->lang->truncate( $comment->text, 255 ); } if ( $this->stage >= MIGRATION_WRITE_BOTH ) { @@ -459,7 +481,7 @@ class CommentStore { } /** - * Prepare for the insertion of a row with a comment + * Insert a comment in preparation for a row that references it * * @note It's recommended to include both the call to this method and the * row insert in the same transaction. @@ -478,7 +500,7 @@ class CommentStore { } /** - * Prepare for the insertion of a row with a comment and temporary table + * Insert a comment in a temporary table in preparation for a row that references it * * This is currently needed for "rev_comment" and "img_description". In the * future that requirement will be removed.