53 private $joinCache = [];
85 if ( !array_key_exists( $key, $this->joinCache ) ) {
90 $alias =
"comment_$key";
91 $tables[$alias] =
'comment';
92 $joins[$alias] = [
'JOIN',
"{$alias}.comment_id = {$key}_id" ];
94 $fields[
"{$key}_text"] =
"{$alias}.comment_text";
95 $fields[
"{$key}_data"] =
"{$alias}.comment_data";
96 $fields[
"{$key}_cid"] =
"{$alias}.comment_id";
98 $this->joinCache[$key] = [
105 return $this->joinCache[$key];
122 if ( array_key_exists(
"{$key}_text", $row ) && array_key_exists(
"{$key}_data", $row ) ) {
123 $cid = $row[
"{$key}_cid"] ??
null;
124 $text = $row[
"{$key}_text"];
125 $data = $row[
"{$key}_data"];
128 if ( array_key_exists(
"{$key}_id", $row ) ) {
130 throw new InvalidArgumentException(
131 "\$row does not contain fields needed for comment $key and getComment(), but "
132 .
"does have fields for getCommentLegacy()"
135 $id = $row[
"{$key}_id"];
137 ->select( [
'comment_id',
'comment_text',
'comment_data' ] )
139 ->where( [
'comment_id' => $id ] )
140 ->caller( __METHOD__ )->fetchRow();
142 if ( $row2 ===
null &&
$fallback && isset( $row[$key] ) ) {
143 wfLogWarning(
"Using deprecated fallback handling for comment $key" );
144 $row2 = (object)[
'comment_text' => $row[$key],
'comment_data' =>
null ];
146 if ( $row2 ===
null ) {
147 throw new InvalidArgumentException(
"\$row does not contain fields needed for comment $key" );
151 $cid = $row2->comment_id;
152 $text = $row2->comment_text;
153 $data = $row2->comment_data;
166 if ( $data !==
null ) {
167 $data = FormatJson::decode( $data,
true );
168 if ( !is_array( $data ) ) {
170 wfLogWarning(
"Invalid JSON object in comment: $data" );
174 if ( isset( $data[
'_message'] ) ) {
175 $msg = self::decodeMessage( $data[
'_message'] )
178 if ( !empty( $data[
'_null'] ) ) {
181 foreach ( $data as $k => $v ) {
182 if ( str_starts_with( $k,
'_' ) ) {
190 return new CommentStoreComment( $cid, $text, $msg, $data );
210 if ( $row ===
null ) {
212 throw new InvalidArgumentException(
'$row must not be null' );
215 return $this->getCommentInternal(
null, $key, $row,
$fallback );
238 if ( $row ===
null ) {
240 throw new InvalidArgumentException(
'$row must not be null' );
243 return $this->getCommentInternal( $db, $key, $row,
$fallback );
269 # Truncate comment in a Unicode-sensitive manner
270 $comment->text = $this->lang->truncateForVisual( $comment->text, self::COMMENT_CHARACTER_LIMIT );
272 if ( !$comment->id ) {
273 $dbData = $comment->data;
274 if ( !$comment->message instanceof
RawMessage ) {
275 $dbData ??= [
'_null' => true ];
276 $dbData[
'_message'] = self::encodeMessage( $comment->message );
278 if ( $dbData !==
null ) {
279 $dbData = FormatJson::encode( (
object)$dbData,
false, FormatJson::ALL_OK );
280 $len = strlen( $dbData );
281 if ( $len > self::MAX_DATA_LENGTH ) {
283 throw new OverflowException(
"Comment data is too long ($len bytes, maximum is $max)" );
287 $hash = self::hash( $comment->text, $dbData );
289 ->select(
'comment_id' )
292 'comment_hash' => $hash,
293 'comment_text' => $comment->text,
294 'comment_data' => $dbData,
296 ->caller( __METHOD__ )->fetchField();
299 ->insertInto(
'comment' )
300 ->row( [
'comment_hash' => $hash,
'comment_text' => $comment->text,
'comment_data' => $dbData ] )
301 ->caller( __METHOD__ )->execute();
304 $comment->id = (int)$commentId;
327 if ( $comment ===
null ) {
329 throw new InvalidArgumentException(
'$comment can not be null' );
334 return [
"{$key}_id" => $comment->id ];
342 private static function encodeMessage(
Message $msg ) {
345 foreach ( $params as &$param ) {
346 if ( $param instanceof
Message ) {
348 'message' => self::encodeMessage( $param )
352 array_unshift( $params, $key );
361 private static function decodeMessage( $data ) {
362 $key = array_shift( $data );
363 foreach ( $data as &$param ) {
364 if ( is_object( $param ) ) {
365 $param = (array)$param;
367 if ( is_array( $param ) && count( $param ) === 1 && isset( $param[
'message'] ) ) {
368 $param = self::decodeMessage( $param[
'message'] );
371 return new Message( $key, $data );
380 private static function hash( $text, $data ) {
381 $hash = crc32( $text ) ^ crc32( (
string)$data );
385 if ( $hash >= 0x80000000 ) {