4 use Wikimedia\ScopedCallback;
5 use Wikimedia\TestingAccessWrapper;
16 'revision_comment_temp',
27 $store =
new CommentStore( MediaWikiServices::getInstance()->getContentLanguage(), $stage );
40 TestingAccessWrapper::newFromObject( $store )->stage = $stage;
53 $this->assertEquals( $expect,
$result );
64 $result = $store->getFields( $key );
65 $this->assertEquals( $expect,
$result );
70 'Simple table, old' => [
72 [
'ipb_reason_text' =>
'ipb_reason',
'ipb_reason_data' =>
'NULL',
'ipb_reason_cid' =>
'NULL' ],
74 'Simple table, write-both' => [
76 [
'ipb_reason_old' =>
'ipb_reason',
'ipb_reason_id' =>
'ipb_reason_id' ],
78 'Simple table, write-new' => [
80 [
'ipb_reason_old' =>
'ipb_reason',
'ipb_reason_id' =>
'ipb_reason_id' ],
82 'Simple table, new' => [
84 [
'ipb_reason_id' =>
'ipb_reason_id' ],
90 'rev_comment_text' =>
'rev_comment',
91 'rev_comment_data' =>
'NULL',
92 'rev_comment_cid' =>
'NULL',
95 'Revision, write-both' => [
97 [
'rev_comment_old' =>
'rev_comment',
'rev_comment_pk' =>
'rev_id' ],
99 'Revision, write-new' => [
101 [
'rev_comment_old' =>
'rev_comment',
'rev_comment_pk' =>
'rev_id' ],
105 [
'rev_comment_pk' =>
'rev_id' ],
111 'img_description_text' =>
'img_description',
112 'img_description_data' =>
'NULL',
113 'img_description_cid' =>
'NULL',
116 'Image, write-both' => [
119 'img_description_old' =>
'img_description',
120 'img_description_id' =>
'img_description_id'
123 'Image, write-new' => [
126 'img_description_old' =>
'img_description',
127 'img_description_id' =>
'img_description_id'
133 'img_description_id' =>
'img_description_id'
148 $this->assertEquals( $expect,
$result );
159 $result = $store->getJoin( $key );
160 $this->assertEquals( $expect,
$result );
165 'Simple table, old' => [
169 'ipb_reason_text' =>
'ipb_reason',
170 'ipb_reason_data' =>
'NULL',
171 'ipb_reason_cid' =>
'NULL',
176 'Simple table, write-both' => [
178 'tables' => [
'comment_ipb_reason' =>
'comment' ],
180 'ipb_reason_text' =>
'COALESCE( comment_ipb_reason.comment_text, ipb_reason )',
181 'ipb_reason_data' =>
'comment_ipb_reason.comment_data',
182 'ipb_reason_cid' =>
'comment_ipb_reason.comment_id',
185 'comment_ipb_reason' => [
'LEFT JOIN',
'comment_ipb_reason.comment_id = ipb_reason_id' ],
189 'Simple table, write-new' => [
191 'tables' => [
'comment_ipb_reason' =>
'comment' ],
193 'ipb_reason_text' =>
'COALESCE( comment_ipb_reason.comment_text, ipb_reason )',
194 'ipb_reason_data' =>
'comment_ipb_reason.comment_data',
195 'ipb_reason_cid' =>
'comment_ipb_reason.comment_id',
198 'comment_ipb_reason' => [
'LEFT JOIN',
'comment_ipb_reason.comment_id = ipb_reason_id' ],
202 'Simple table, new' => [
204 'tables' => [
'comment_ipb_reason' =>
'comment' ],
206 'ipb_reason_text' =>
'comment_ipb_reason.comment_text',
207 'ipb_reason_data' =>
'comment_ipb_reason.comment_data',
208 'ipb_reason_cid' =>
'comment_ipb_reason.comment_id',
211 'comment_ipb_reason' => [
'JOIN',
'comment_ipb_reason.comment_id = ipb_reason_id' ],
220 'rev_comment_text' =>
'rev_comment',
221 'rev_comment_data' =>
'NULL',
222 'rev_comment_cid' =>
'NULL',
227 'Revision, write-both' => [
230 'temp_rev_comment' =>
'revision_comment_temp',
231 'comment_rev_comment' =>
'comment',
234 'rev_comment_text' =>
'COALESCE( comment_rev_comment.comment_text, rev_comment )',
235 'rev_comment_data' =>
'comment_rev_comment.comment_data',
236 'rev_comment_cid' =>
'comment_rev_comment.comment_id',
239 'temp_rev_comment' => [
'LEFT JOIN',
'temp_rev_comment.revcomment_rev = rev_id' ],
240 'comment_rev_comment' => [
'LEFT JOIN',
241 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
245 'Revision, write-new' => [
248 'temp_rev_comment' =>
'revision_comment_temp',
249 'comment_rev_comment' =>
'comment',
252 'rev_comment_text' =>
'COALESCE( comment_rev_comment.comment_text, rev_comment )',
253 'rev_comment_data' =>
'comment_rev_comment.comment_data',
254 'rev_comment_cid' =>
'comment_rev_comment.comment_id',
257 'temp_rev_comment' => [
'LEFT JOIN',
'temp_rev_comment.revcomment_rev = rev_id' ],
258 'comment_rev_comment' => [
'LEFT JOIN',
259 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
266 'temp_rev_comment' =>
'revision_comment_temp',
267 'comment_rev_comment' =>
'comment',
270 'rev_comment_text' =>
'comment_rev_comment.comment_text',
271 'rev_comment_data' =>
'comment_rev_comment.comment_data',
272 'rev_comment_cid' =>
'comment_rev_comment.comment_id',
275 'temp_rev_comment' => [
'JOIN',
'temp_rev_comment.revcomment_rev = rev_id' ],
276 'comment_rev_comment' => [
'JOIN',
277 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
286 'img_description_text' =>
'img_description',
287 'img_description_data' =>
'NULL',
288 'img_description_cid' =>
'NULL',
293 'Image, write-both' => [
296 'comment_img_description' =>
'comment',
299 'img_description_text' =>
'COALESCE( comment_img_description.comment_text, img_description )',
300 'img_description_data' =>
'comment_img_description.comment_data',
301 'img_description_cid' =>
'comment_img_description.comment_id',
304 'comment_img_description' => [
'LEFT JOIN',
305 'comment_img_description.comment_id = img_description_id',
310 'Image, write-new' => [
313 'comment_img_description' =>
'comment',
316 'img_description_text' =>
'COALESCE( comment_img_description.comment_text, img_description )',
317 'img_description_data' =>
'comment_img_description.comment_data',
318 'img_description_cid' =>
'comment_img_description.comment_id',
321 'comment_img_description' => [
'LEFT JOIN',
322 'comment_img_description.comment_id = img_description_id',
330 'comment_img_description' =>
'comment',
333 'img_description_text' =>
'comment_img_description.comment_text',
334 'img_description_data' =>
'comment_img_description.comment_data',
335 'img_description_cid' =>
'comment_img_description.comment_id',
338 'comment_img_description' => [
'JOIN',
339 'comment_img_description.comment_id = img_description_id',
348 $this->assertSame( $expect[
'text'], $actual->text,
"text $from" );
349 $this->assertInstanceOf( get_class( $expect[
'message'] ), $actual->message,
350 "message class $from" );
351 $this->assertSame( $expect[
'message']->getKeysToTry(), $actual->message->getKeysToTry(),
352 "message keys $from" );
353 $this->assertEquals( $expect[
'message']->
text(), $actual->message->text(),
354 "message rendering $from" );
355 $this->assertEquals( $expect[
'data'], $actual->data,
"data $from" );
370 'text' => $expect[
'text'],
371 'message' =>
new RawMessage(
'$1', [ $expect[
'text'] ] ),
383 foreach ( $stages
as $writeStage => $possibleReadStages ) {
384 if ( $key ===
'ipb_reason' ) {
385 $extraFields[
'ipb_address'] = __CLASS__ .
"#$writeStage";
388 $wstore = $this->
makeStore( $writeStage );
389 $usesTemp = $key ===
'rev_comment';
392 list( $fields, $callback ) = $wstore->insertWithTempTable(
393 $this->db, $key, $comment, $data
396 $fields = $wstore->insert( $this->db, $key, $comment, $data );
400 $this->assertSame( $expect[
'text'], $fields[$key],
"old field, stage=$writeStage" );
402 $this->assertArrayNotHasKey( $key, $fields,
"old field, stage=$writeStage" );
405 $this->assertArrayHasKey(
"{$key}_id", $fields,
"new field, stage=$writeStage" );
407 $this->assertArrayNotHasKey(
"{$key}_id", $fields,
"new field, stage=$writeStage" );
410 $this->db->insert( $table, $extraFields + $fields, __METHOD__ );
411 $id = $this->db->insertId();
416 foreach ( $possibleReadStages
as $readStage ) {
417 $rstore = $this->
makeStore( $readStage );
419 $fieldRow = $this->db->selectRow(
421 $rstore->getFields( $key ),
426 $queryInfo = $rstore->getJoin( $key );
427 $joinRow = $this->db->selectRow(
428 [ $table ] + $queryInfo[
'tables'],
429 $queryInfo[
'fields'],
438 $rstore->getCommentLegacy( $this->db, $key, $fieldRow ),
439 "w=$writeStage, r=$readStage, from getFields()"
443 $rstore->getComment( $key, $joinRow ),
444 "w=$writeStage, r=$readStage, from getJoin()"
461 $table, $key, $pk, $extraFields, $comment, $data, $expect
464 'text' => $expect[
'text'],
465 'message' =>
new RawMessage(
'$1', [ $expect[
'text'] ] ),
477 foreach ( $stages
as $writeStage => $possibleReadStages ) {
478 if ( $key ===
'ipb_reason' ) {
479 $extraFields[
'ipb_address'] = __CLASS__ .
"#$writeStage";
483 $usesTemp = $key ===
'rev_comment';
486 list( $fields, $callback ) = $wstore->insertWithTempTable(
487 $this->db, $comment, $data
490 $fields = $wstore->insert( $this->db, $comment, $data );
494 $this->assertSame( $expect[
'text'], $fields[$key],
"old field, stage=$writeStage" );
496 $this->assertArrayNotHasKey( $key, $fields,
"old field, stage=$writeStage" );
499 $this->assertArrayHasKey(
"{$key}_id", $fields,
"new field, stage=$writeStage" );
501 $this->assertArrayNotHasKey(
"{$key}_id", $fields,
"new field, stage=$writeStage" );
504 $this->db->insert( $table, $extraFields + $fields, __METHOD__ );
505 $id = $this->db->insertId();
510 foreach ( $possibleReadStages
as $readStage ) {
513 $fieldRow = $this->db->selectRow(
515 $rstore->getFields(),
520 $queryInfo = $rstore->getJoin();
521 $joinRow = $this->db->selectRow(
522 [ $table ] + $queryInfo[
'tables'],
523 $queryInfo[
'fields'],
532 $rstore->getCommentLegacy( $this->db, $fieldRow ),
533 "w=$writeStage, r=$readStage, from getFields()"
537 $rstore->getComment( $joinRow ),
538 "w=$writeStage, r=$readStage, from getJoin()"
547 $msgComment =
new Message(
'parentheses', [
'message comment' ] );
548 $textCommentMsg =
new RawMessage(
'$1', [
'text comment' ] );
549 $nestedMsgComment =
new Message( [
'parentheses',
'rawmessage' ], [
new Message(
'mainpage' ) ] );
551 'ipb_range_start' =>
'',
552 'ipb_range_end' =>
'',
553 'ipb_timestamp' =>
$db->timestamp(),
554 'ipb_expiry' =>
$db->getInfinity(),
560 'rev_timestamp' =>
$db->timestamp(),
563 null,
'comment store comment',
null, [
'foo' =>
'bar' ]
567 'Simple table, text comment' => [
568 'ipblocks',
'ipb_reason',
'ipb_id', $ipbfields,
'text comment',
null, [
569 'text' =>
'text comment',
570 'message' => $textCommentMsg,
574 'Simple table, text comment with data' => [
575 'ipblocks',
'ipb_reason',
'ipb_id', $ipbfields,
'text comment', [
'message' => 42 ], [
576 'text' =>
'text comment',
577 'message' => $textCommentMsg,
578 'data' => [
'message' => 42 ],
581 'Simple table, message comment' => [
582 'ipblocks',
'ipb_reason',
'ipb_id', $ipbfields, $msgComment,
null, [
583 'text' =>
'(message comment)',
584 'message' => $msgComment,
588 'Simple table, message comment with data' => [
589 'ipblocks',
'ipb_reason',
'ipb_id', $ipbfields, $msgComment, [
'message' => 42 ], [
590 'text' =>
'(message comment)',
591 'message' => $msgComment,
592 'data' => [
'message' => 42 ],
595 'Simple table, nested message comment' => [
596 'ipblocks',
'ipb_reason',
'ipb_id', $ipbfields, $nestedMsgComment,
null, [
597 'text' =>
'(Main Page)',
598 'message' => $nestedMsgComment,
602 'Simple table, CommentStoreComment' => [
603 'ipblocks',
'ipb_reason',
'ipb_id', $ipbfields, clone $comStoreComment, [
'baz' =>
'baz' ], [
604 'text' =>
'comment store comment',
605 'message' => $comStoreComment->message,
606 'data' => [
'foo' =>
'bar' ],
610 'Revision, text comment' => [
611 'revision',
'rev_comment',
'rev_id', $revfields,
'text comment',
null, [
612 'text' =>
'text comment',
613 'message' => $textCommentMsg,
617 'Revision, text comment with data' => [
618 'revision',
'rev_comment',
'rev_id', $revfields,
'text comment', [
'message' => 42 ], [
619 'text' =>
'text comment',
620 'message' => $textCommentMsg,
621 'data' => [
'message' => 42 ],
624 'Revision, message comment' => [
625 'revision',
'rev_comment',
'rev_id', $revfields, $msgComment,
null, [
626 'text' =>
'(message comment)',
627 'message' => $msgComment,
631 'Revision, message comment with data' => [
632 'revision',
'rev_comment',
'rev_id', $revfields, $msgComment, [
'message' => 42 ], [
633 'text' =>
'(message comment)',
634 'message' => $msgComment,
635 'data' => [
'message' => 42 ],
638 'Revision, nested message comment' => [
639 'revision',
'rev_comment',
'rev_id', $revfields, $nestedMsgComment,
null, [
640 'text' =>
'(Main Page)',
641 'message' => $nestedMsgComment,
645 'Revision, CommentStoreComment' => [
646 'revision',
'rev_comment',
'rev_id', $revfields, clone $comStoreComment, [
'baz' =>
'baz' ], [
647 'text' =>
'comment store comment',
648 'message' => $comStoreComment->message,
649 'data' => [
'foo' =>
'bar' ],
656 Wikimedia\suppressWarnings();
657 $reset =
new ScopedCallback(
'Wikimedia\restoreWarnings' );
660 $res = $store->getComment(
'dummy', [
'dummy' =>
'comment' ] );
661 $this->assertSame(
'',
$res->text );
662 $res = $store->getComment(
'dummy', [
'dummy' =>
'comment' ],
true );
663 $this->assertSame(
'comment',
$res->text );
667 $store->getComment(
'dummy', [
'dummy' =>
'comment' ] );
668 $this->fail(
'Expected exception not thrown' );
669 }
catch ( InvalidArgumentException $ex ) {
670 $this->assertSame(
'$row does not contain fields needed for comment dummy', $ex->getMessage() );
672 $res = $store->getComment(
'dummy', [
'dummy' =>
'comment' ],
true );
673 $this->assertSame(
'comment',
$res->text );
675 $store->getComment(
'dummy', [
'dummy_id' => 1 ] );
676 $this->fail(
'Expected exception not thrown' );
677 }
catch ( InvalidArgumentException $ex ) {
679 '$row does not contain fields needed for comment dummy and getComment(), '
680 .
'but does have fields for getCommentLegacy()',
687 $store->getComment(
'rev_comment', [
'rev_comment' =>
'comment' ] );
688 $this->fail(
'Expected exception not thrown' );
689 }
catch ( InvalidArgumentException $ex ) {
691 '$row does not contain fields needed for comment rev_comment', $ex->getMessage()
694 $res = $store->getComment(
'rev_comment', [
'rev_comment' =>
'comment' ],
true );
695 $this->assertSame(
'comment',
$res->text );
697 $store->getComment(
'rev_comment', [
'rev_comment_pk' => 1 ] );
698 $this->fail(
'Expected exception not thrown' );
699 }
catch ( InvalidArgumentException $ex ) {
701 '$row does not contain fields needed for comment rev_comment and getComment(), '
702 .
'but does have fields for getCommentLegacy()',
725 $store->insert( $this->db,
'rev_comment',
'foo' );
736 $store->insertWithTempTable( $this->db,
'ipb_reason',
'foo' );
745 $wrap = TestingAccessWrapper::newFromObject( $store );
746 $wrap->tempTables += [
'ipb_reason' => [
748 'deprecatedIn' =>
'1.30',
751 $this->
hideDeprecated(
'CommentStore::insertWithTempTable for ipb_reason' );
752 list( $fields, $callback ) = $store->insertWithTempTable( $this->db,
'ipb_reason',
'foo' );
753 $this->assertTrue( is_callable( $callback ) );
757 $comment = str_repeat(
'💣', 16400 );
758 $truncated1 = str_repeat(
'💣', 63 ) .
'...';
762 $fields = $store->insert( $this->db,
'ipb_reason', $comment );
763 $this->assertSame( $truncated1, $fields[
'ipb_reason'] );
764 $stored = $this->db->selectField(
765 'comment',
'comment_text', [
'comment_id' => $fields[
'ipb_reason_id'] ], __METHOD__
767 $this->assertSame( $truncated2, $stored );
776 $store->insert( $this->db,
'ipb_reason',
'foo', [
777 'long' => str_repeat(
'💣', 16400 )