*/
class CommentStore {
+ /** Maximum length of a comment. Longer comments will be truncated. */
+ const MAX_COMMENT_LENGTH = 65535;
+
+ /** Maximum length of serialized data. Longer data will result in an exception. */
+ 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:
/** @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;
}
/**
* @return CommentStoreComment
*/
public function createComment( IDatabase $dbw, $comment, array $data = null ) {
- global $wgContLang;
+ $comment = CommentStoreComment::newUnsavedComment( $comment, $data );
- 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 );
- }
- }
+ # Truncate comment in a Unicode-sensitive manner
+ $comment->text = $this->lang->truncate( $comment->text, self::MAX_COMMENT_LENGTH );
if ( $this->stage > MIGRATION_OLD && !$comment->id ) {
$dbData = $comment->data;
}
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 );
__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,
$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 ) {
}
/**
- * 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.
}
/**
- * 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.