MediaWiki REL1_31
CommentStoreTest.php
Go to the documentation of this file.
1<?php
2
3use Wikimedia\ScopedCallback;
4use Wikimedia\TestingAccessWrapper;
5
12
13 protected $tablesUsed = [
14 'revision',
15 'revision_comment_temp',
16 'ipblocks',
17 'comment',
18 ];
19
25 protected function makeStore( $stage ) {
26 global $wgContLang;
27 $store = new CommentStore( $wgContLang, $stage );
28 return $store;
29 }
30
37 protected function makeStoreWithKey( $stage, $key ) {
38 $store = CommentStore::newKey( $key );
39 TestingAccessWrapper::newFromObject( $store )->stage = $stage;
40 return $store;
41 }
42
49 public function testGetFields_withKeyConstruction( $stage, $key, $expect ) {
50 $store = $this->makeStoreWithKey( $stage, $key );
51 $result = $store->getFields();
52 $this->assertEquals( $expect, $result );
53 }
54
61 public function testGetFields( $stage, $key, $expect ) {
62 $store = $this->makeStore( $stage );
63 $result = $store->getFields( $key );
64 $this->assertEquals( $expect, $result );
65 }
66
67 public static function provideGetFields() {
68 return [
69 'Simple table, old' => [
70 MIGRATION_OLD, 'ipb_reason',
71 [ 'ipb_reason_text' => 'ipb_reason', 'ipb_reason_data' => 'NULL', 'ipb_reason_cid' => 'NULL' ],
72 ],
73 'Simple table, write-both' => [
74 MIGRATION_WRITE_BOTH, 'ipb_reason',
75 [ 'ipb_reason_old' => 'ipb_reason', 'ipb_reason_id' => 'ipb_reason_id' ],
76 ],
77 'Simple table, write-new' => [
78 MIGRATION_WRITE_NEW, 'ipb_reason',
79 [ 'ipb_reason_old' => 'ipb_reason', 'ipb_reason_id' => 'ipb_reason_id' ],
80 ],
81 'Simple table, new' => [
82 MIGRATION_NEW, 'ipb_reason',
83 [ 'ipb_reason_id' => 'ipb_reason_id' ],
84 ],
85
86 'Revision, old' => [
87 MIGRATION_OLD, 'rev_comment',
88 [
89 'rev_comment_text' => 'rev_comment',
90 'rev_comment_data' => 'NULL',
91 'rev_comment_cid' => 'NULL',
92 ],
93 ],
94 'Revision, write-both' => [
95 MIGRATION_WRITE_BOTH, 'rev_comment',
96 [ 'rev_comment_old' => 'rev_comment', 'rev_comment_pk' => 'rev_id' ],
97 ],
98 'Revision, write-new' => [
99 MIGRATION_WRITE_NEW, 'rev_comment',
100 [ 'rev_comment_old' => 'rev_comment', 'rev_comment_pk' => 'rev_id' ],
101 ],
102 'Revision, new' => [
103 MIGRATION_NEW, 'rev_comment',
104 [ 'rev_comment_pk' => 'rev_id' ],
105 ],
106
107 'Image, old' => [
108 MIGRATION_OLD, 'img_description',
109 [
110 'img_description_text' => 'img_description',
111 'img_description_data' => 'NULL',
112 'img_description_cid' => 'NULL',
113 ],
114 ],
115 'Image, write-both' => [
116 MIGRATION_WRITE_BOTH, 'img_description',
117 [ 'img_description_old' => 'img_description', 'img_description_pk' => 'img_name' ],
118 ],
119 'Image, write-new' => [
120 MIGRATION_WRITE_NEW, 'img_description',
121 [ 'img_description_old' => 'img_description', 'img_description_pk' => 'img_name' ],
122 ],
123 'Image, new' => [
124 MIGRATION_NEW, 'img_description',
125 [ 'img_description_pk' => 'img_name' ],
126 ],
127 ];
128 }
129
136 public function testGetJoin_withKeyConstruction( $stage, $key, $expect ) {
137 $store = $this->makeStoreWithKey( $stage, $key );
138 $result = $store->getJoin();
139 $this->assertEquals( $expect, $result );
140 }
141
148 public function testGetJoin( $stage, $key, $expect ) {
149 $store = $this->makeStore( $stage );
150 $result = $store->getJoin( $key );
151 $this->assertEquals( $expect, $result );
152 }
153
154 public static function provideGetJoin() {
155 return [
156 'Simple table, old' => [
157 MIGRATION_OLD, 'ipb_reason', [
158 'tables' => [],
159 'fields' => [
160 'ipb_reason_text' => 'ipb_reason',
161 'ipb_reason_data' => 'NULL',
162 'ipb_reason_cid' => 'NULL',
163 ],
164 'joins' => [],
165 ],
166 ],
167 'Simple table, write-both' => [
168 MIGRATION_WRITE_BOTH, 'ipb_reason', [
169 'tables' => [ 'comment_ipb_reason' => 'comment' ],
170 'fields' => [
171 'ipb_reason_text' => 'COALESCE( comment_ipb_reason.comment_text, ipb_reason )',
172 'ipb_reason_data' => 'comment_ipb_reason.comment_data',
173 'ipb_reason_cid' => 'comment_ipb_reason.comment_id',
174 ],
175 'joins' => [
176 'comment_ipb_reason' => [ 'LEFT JOIN', 'comment_ipb_reason.comment_id = ipb_reason_id' ],
177 ],
178 ],
179 ],
180 'Simple table, write-new' => [
181 MIGRATION_WRITE_NEW, 'ipb_reason', [
182 'tables' => [ 'comment_ipb_reason' => 'comment' ],
183 'fields' => [
184 'ipb_reason_text' => 'COALESCE( comment_ipb_reason.comment_text, ipb_reason )',
185 'ipb_reason_data' => 'comment_ipb_reason.comment_data',
186 'ipb_reason_cid' => 'comment_ipb_reason.comment_id',
187 ],
188 'joins' => [
189 'comment_ipb_reason' => [ 'LEFT JOIN', 'comment_ipb_reason.comment_id = ipb_reason_id' ],
190 ],
191 ],
192 ],
193 'Simple table, new' => [
194 MIGRATION_NEW, 'ipb_reason', [
195 'tables' => [ 'comment_ipb_reason' => 'comment' ],
196 'fields' => [
197 'ipb_reason_text' => 'comment_ipb_reason.comment_text',
198 'ipb_reason_data' => 'comment_ipb_reason.comment_data',
199 'ipb_reason_cid' => 'comment_ipb_reason.comment_id',
200 ],
201 'joins' => [
202 'comment_ipb_reason' => [ 'JOIN', 'comment_ipb_reason.comment_id = ipb_reason_id' ],
203 ],
204 ],
205 ],
206
207 'Revision, old' => [
208 MIGRATION_OLD, 'rev_comment', [
209 'tables' => [],
210 'fields' => [
211 'rev_comment_text' => 'rev_comment',
212 'rev_comment_data' => 'NULL',
213 'rev_comment_cid' => 'NULL',
214 ],
215 'joins' => [],
216 ],
217 ],
218 'Revision, write-both' => [
219 MIGRATION_WRITE_BOTH, 'rev_comment', [
220 'tables' => [
221 'temp_rev_comment' => 'revision_comment_temp',
222 'comment_rev_comment' => 'comment',
223 ],
224 'fields' => [
225 'rev_comment_text' => 'COALESCE( comment_rev_comment.comment_text, rev_comment )',
226 'rev_comment_data' => 'comment_rev_comment.comment_data',
227 'rev_comment_cid' => 'comment_rev_comment.comment_id',
228 ],
229 'joins' => [
230 'temp_rev_comment' => [ 'LEFT JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
231 'comment_rev_comment' => [ 'LEFT JOIN',
232 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
233 ],
234 ],
235 ],
236 'Revision, write-new' => [
237 MIGRATION_WRITE_NEW, 'rev_comment', [
238 'tables' => [
239 'temp_rev_comment' => 'revision_comment_temp',
240 'comment_rev_comment' => 'comment',
241 ],
242 'fields' => [
243 'rev_comment_text' => 'COALESCE( comment_rev_comment.comment_text, rev_comment )',
244 'rev_comment_data' => 'comment_rev_comment.comment_data',
245 'rev_comment_cid' => 'comment_rev_comment.comment_id',
246 ],
247 'joins' => [
248 'temp_rev_comment' => [ 'LEFT JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
249 'comment_rev_comment' => [ 'LEFT JOIN',
250 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
251 ],
252 ],
253 ],
254 'Revision, new' => [
255 MIGRATION_NEW, 'rev_comment', [
256 'tables' => [
257 'temp_rev_comment' => 'revision_comment_temp',
258 'comment_rev_comment' => 'comment',
259 ],
260 'fields' => [
261 'rev_comment_text' => 'comment_rev_comment.comment_text',
262 'rev_comment_data' => 'comment_rev_comment.comment_data',
263 'rev_comment_cid' => 'comment_rev_comment.comment_id',
264 ],
265 'joins' => [
266 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
267 'comment_rev_comment' => [ 'JOIN',
268 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
269 ],
270 ],
271 ],
272
273 'Image, old' => [
274 MIGRATION_OLD, 'img_description', [
275 'tables' => [],
276 'fields' => [
277 'img_description_text' => 'img_description',
278 'img_description_data' => 'NULL',
279 'img_description_cid' => 'NULL',
280 ],
281 'joins' => [],
282 ],
283 ],
284 'Image, write-both' => [
285 MIGRATION_WRITE_BOTH, 'img_description', [
286 'tables' => [
287 'temp_img_description' => 'image_comment_temp',
288 'comment_img_description' => 'comment',
289 ],
290 'fields' => [
291 'img_description_text' => 'COALESCE( comment_img_description.comment_text, img_description )',
292 'img_description_data' => 'comment_img_description.comment_data',
293 'img_description_cid' => 'comment_img_description.comment_id',
294 ],
295 'joins' => [
296 'temp_img_description' => [ 'LEFT JOIN', 'temp_img_description.imgcomment_name = img_name' ],
297 'comment_img_description' => [ 'LEFT JOIN',
298 'comment_img_description.comment_id = temp_img_description.imgcomment_description_id' ],
299 ],
300 ],
301 ],
302 'Image, write-new' => [
303 MIGRATION_WRITE_NEW, 'img_description', [
304 'tables' => [
305 'temp_img_description' => 'image_comment_temp',
306 'comment_img_description' => 'comment',
307 ],
308 'fields' => [
309 'img_description_text' => 'COALESCE( comment_img_description.comment_text, img_description )',
310 'img_description_data' => 'comment_img_description.comment_data',
311 'img_description_cid' => 'comment_img_description.comment_id',
312 ],
313 'joins' => [
314 'temp_img_description' => [ 'LEFT JOIN', 'temp_img_description.imgcomment_name = img_name' ],
315 'comment_img_description' => [ 'LEFT JOIN',
316 'comment_img_description.comment_id = temp_img_description.imgcomment_description_id' ],
317 ],
318 ],
319 ],
320 'Image, new' => [
321 MIGRATION_NEW, 'img_description', [
322 'tables' => [
323 'temp_img_description' => 'image_comment_temp',
324 'comment_img_description' => 'comment',
325 ],
326 'fields' => [
327 'img_description_text' => 'comment_img_description.comment_text',
328 'img_description_data' => 'comment_img_description.comment_data',
329 'img_description_cid' => 'comment_img_description.comment_id',
330 ],
331 'joins' => [
332 'temp_img_description' => [ 'JOIN', 'temp_img_description.imgcomment_name = img_name' ],
333 'comment_img_description' => [ 'JOIN',
334 'comment_img_description.comment_id = temp_img_description.imgcomment_description_id' ],
335 ],
336 ],
337 ],
338 ];
339 }
340
341 private function assertComment( $expect, $actual, $from ) {
342 $this->assertSame( $expect['text'], $actual->text, "text $from" );
343 $this->assertInstanceOf( get_class( $expect['message'] ), $actual->message,
344 "message class $from" );
345 $this->assertSame( $expect['message']->getKeysToTry(), $actual->message->getKeysToTry(),
346 "message keys $from" );
347 $this->assertEquals( $expect['message']->text(), $actual->message->text(),
348 "message rendering $from" );
349 $this->assertEquals( $expect['data'], $actual->data, "data $from" );
350 }
351
362 public function testInsertRoundTrip( $table, $key, $pk, $extraFields, $comment, $data, $expect ) {
363 $expectOld = [
364 'text' => $expect['text'],
365 'message' => new RawMessage( '$1', [ $expect['text'] ] ),
366 'data' => null,
367 ];
368
369 $stages = [
374 ];
375
376 foreach ( $stages as $writeStage => $readRange ) {
377 if ( $key === 'ipb_reason' ) {
378 $extraFields['ipb_address'] = __CLASS__ . "#$writeStage";
379 }
380
381 $wstore = $this->makeStore( $writeStage );
382 $usesTemp = $key === 'rev_comment';
383
384 if ( $usesTemp ) {
385 list( $fields, $callback ) = $wstore->insertWithTempTable(
386 $this->db, $key, $comment, $data
387 );
388 } else {
389 $fields = $wstore->insert( $this->db, $key, $comment, $data );
390 }
391
392 if ( $writeStage <= MIGRATION_WRITE_BOTH ) {
393 $this->assertSame( $expect['text'], $fields[$key], "old field, stage=$writeStage" );
394 } else {
395 $this->assertArrayNotHasKey( $key, $fields, "old field, stage=$writeStage" );
396 }
397 if ( $writeStage >= MIGRATION_WRITE_BOTH && !$usesTemp ) {
398 $this->assertArrayHasKey( "{$key}_id", $fields, "new field, stage=$writeStage" );
399 } else {
400 $this->assertArrayNotHasKey( "{$key}_id", $fields, "new field, stage=$writeStage" );
401 }
402
403 $this->db->insert( $table, $extraFields + $fields, __METHOD__ );
404 $id = $this->db->insertId();
405 if ( $usesTemp ) {
406 $callback( $id );
407 }
408
409 for ( $readStage = $readRange[0]; $readStage <= $readRange[1]; $readStage++ ) {
410 $rstore = $this->makeStore( $readStage );
411
412 $fieldRow = $this->db->selectRow(
413 $table,
414 $rstore->getFields( $key ),
415 [ $pk => $id ],
416 __METHOD__
417 );
418
419 $queryInfo = $rstore->getJoin( $key );
420 $joinRow = $this->db->selectRow(
421 [ $table ] + $queryInfo['tables'],
422 $queryInfo['fields'],
423 [ $pk => $id ],
424 __METHOD__,
425 [],
426 $queryInfo['joins']
427 );
428
429 $this->assertComment(
430 $writeStage === MIGRATION_OLD || $readStage === MIGRATION_OLD ? $expectOld : $expect,
431 $rstore->getCommentLegacy( $this->db, $key, $fieldRow ),
432 "w=$writeStage, r=$readStage, from getFields()"
433 );
434 $this->assertComment(
435 $writeStage === MIGRATION_OLD || $readStage === MIGRATION_OLD ? $expectOld : $expect,
436 $rstore->getComment( $key, $joinRow ),
437 "w=$writeStage, r=$readStage, from getJoin()"
438 );
439 }
440 }
441 }
442
454 $table, $key, $pk, $extraFields, $comment, $data, $expect
455 ) {
456 $expectOld = [
457 'text' => $expect['text'],
458 'message' => new RawMessage( '$1', [ $expect['text'] ] ),
459 'data' => null,
460 ];
461
462 $stages = [
467 ];
468
469 foreach ( $stages as $writeStage => $readRange ) {
470 if ( $key === 'ipb_reason' ) {
471 $extraFields['ipb_address'] = __CLASS__ . "#$writeStage";
472 }
473
474 $wstore = $this->makeStoreWithKey( $writeStage, $key );
475 $usesTemp = $key === 'rev_comment';
476
477 if ( $usesTemp ) {
478 list( $fields, $callback ) = $wstore->insertWithTempTable(
479 $this->db, $comment, $data
480 );
481 } else {
482 $fields = $wstore->insert( $this->db, $comment, $data );
483 }
484
485 if ( $writeStage <= MIGRATION_WRITE_BOTH ) {
486 $this->assertSame( $expect['text'], $fields[$key], "old field, stage=$writeStage" );
487 } else {
488 $this->assertArrayNotHasKey( $key, $fields, "old field, stage=$writeStage" );
489 }
490 if ( $writeStage >= MIGRATION_WRITE_BOTH && !$usesTemp ) {
491 $this->assertArrayHasKey( "{$key}_id", $fields, "new field, stage=$writeStage" );
492 } else {
493 $this->assertArrayNotHasKey( "{$key}_id", $fields, "new field, stage=$writeStage" );
494 }
495
496 $this->db->insert( $table, $extraFields + $fields, __METHOD__ );
497 $id = $this->db->insertId();
498 if ( $usesTemp ) {
499 $callback( $id );
500 }
501
502 for ( $readStage = $readRange[0]; $readStage <= $readRange[1]; $readStage++ ) {
503 $rstore = $this->makeStoreWithKey( $readStage, $key );
504
505 $fieldRow = $this->db->selectRow(
506 $table,
507 $rstore->getFields(),
508 [ $pk => $id ],
509 __METHOD__
510 );
511
512 $queryInfo = $rstore->getJoin();
513 $joinRow = $this->db->selectRow(
514 [ $table ] + $queryInfo['tables'],
515 $queryInfo['fields'],
516 [ $pk => $id ],
517 __METHOD__,
518 [],
519 $queryInfo['joins']
520 );
521
522 $this->assertComment(
523 $writeStage === MIGRATION_OLD || $readStage === MIGRATION_OLD ? $expectOld : $expect,
524 $rstore->getCommentLegacy( $this->db, $fieldRow ),
525 "w=$writeStage, r=$readStage, from getFields()"
526 );
527 $this->assertComment(
528 $writeStage === MIGRATION_OLD || $readStage === MIGRATION_OLD ? $expectOld : $expect,
529 $rstore->getComment( $joinRow ),
530 "w=$writeStage, r=$readStage, from getJoin()"
531 );
532 }
533 }
534 }
535
536 public static function provideInsertRoundTrip() {
537 $db = wfGetDB( DB_REPLICA ); // for timestamps
538
539 $msgComment = new Message( 'parentheses', [ 'message comment' ] );
540 $textCommentMsg = new RawMessage( '$1', [ 'text comment' ] );
541 $nestedMsgComment = new Message( [ 'parentheses', 'rawmessage' ], [ new Message( 'mainpage' ) ] );
542 $ipbfields = [
543 'ipb_range_start' => '',
544 'ipb_range_end' => '',
545 'ipb_timestamp' => $db->timestamp(),
546 'ipb_expiry' => $db->getInfinity(),
547 ];
548 $revfields = [
549 'rev_page' => 42,
550 'rev_text_id' => 42,
551 'rev_len' => 0,
552 'rev_timestamp' => $db->timestamp(),
553 ];
554 $comStoreComment = new CommentStoreComment(
555 null, 'comment store comment', null, [ 'foo' => 'bar' ]
556 );
557
558 return [
559 'Simple table, text comment' => [
560 'ipblocks', 'ipb_reason', 'ipb_id', $ipbfields, 'text comment', null, [
561 'text' => 'text comment',
562 'message' => $textCommentMsg,
563 'data' => null,
564 ]
565 ],
566 'Simple table, text comment with data' => [
567 'ipblocks', 'ipb_reason', 'ipb_id', $ipbfields, 'text comment', [ 'message' => 42 ], [
568 'text' => 'text comment',
569 'message' => $textCommentMsg,
570 'data' => [ 'message' => 42 ],
571 ]
572 ],
573 'Simple table, message comment' => [
574 'ipblocks', 'ipb_reason', 'ipb_id', $ipbfields, $msgComment, null, [
575 'text' => '(message comment)',
576 'message' => $msgComment,
577 'data' => null,
578 ]
579 ],
580 'Simple table, message comment with data' => [
581 'ipblocks', 'ipb_reason', 'ipb_id', $ipbfields, $msgComment, [ 'message' => 42 ], [
582 'text' => '(message comment)',
583 'message' => $msgComment,
584 'data' => [ 'message' => 42 ],
585 ]
586 ],
587 'Simple table, nested message comment' => [
588 'ipblocks', 'ipb_reason', 'ipb_id', $ipbfields, $nestedMsgComment, null, [
589 'text' => '(Main Page)',
590 'message' => $nestedMsgComment,
591 'data' => null,
592 ]
593 ],
594 'Simple table, CommentStoreComment' => [
595 'ipblocks', 'ipb_reason', 'ipb_id', $ipbfields, clone $comStoreComment, [ 'baz' => 'baz' ], [
596 'text' => 'comment store comment',
597 'message' => $comStoreComment->message,
598 'data' => [ 'foo' => 'bar' ],
599 ]
600 ],
601
602 'Revision, text comment' => [
603 'revision', 'rev_comment', 'rev_id', $revfields, 'text comment', null, [
604 'text' => 'text comment',
605 'message' => $textCommentMsg,
606 'data' => null,
607 ]
608 ],
609 'Revision, text comment with data' => [
610 'revision', 'rev_comment', 'rev_id', $revfields, 'text comment', [ 'message' => 42 ], [
611 'text' => 'text comment',
612 'message' => $textCommentMsg,
613 'data' => [ 'message' => 42 ],
614 ]
615 ],
616 'Revision, message comment' => [
617 'revision', 'rev_comment', 'rev_id', $revfields, $msgComment, null, [
618 'text' => '(message comment)',
619 'message' => $msgComment,
620 'data' => null,
621 ]
622 ],
623 'Revision, message comment with data' => [
624 'revision', 'rev_comment', 'rev_id', $revfields, $msgComment, [ 'message' => 42 ], [
625 'text' => '(message comment)',
626 'message' => $msgComment,
627 'data' => [ 'message' => 42 ],
628 ]
629 ],
630 'Revision, nested message comment' => [
631 'revision', 'rev_comment', 'rev_id', $revfields, $nestedMsgComment, null, [
632 'text' => '(Main Page)',
633 'message' => $nestedMsgComment,
634 'data' => null,
635 ]
636 ],
637 'Revision, CommentStoreComment' => [
638 'revision', 'rev_comment', 'rev_id', $revfields, clone $comStoreComment, [ 'baz' => 'baz' ], [
639 'text' => 'comment store comment',
640 'message' => $comStoreComment->message,
641 'data' => [ 'foo' => 'bar' ],
642 ]
643 ],
644 ];
645 }
646
647 public function testGetCommentErrors() {
648 Wikimedia\suppressWarnings();
649 $reset = new ScopedCallback( 'Wikimedia\restoreWarnings' );
650
651 $store = $this->makeStore( MIGRATION_OLD );
652 $res = $store->getComment( 'dummy', [ 'dummy' => 'comment' ] );
653 $this->assertSame( '', $res->text );
654 $res = $store->getComment( 'dummy', [ 'dummy' => 'comment' ], true );
655 $this->assertSame( 'comment', $res->text );
656
657 $store = $this->makeStore( MIGRATION_NEW );
658 try {
659 $store->getComment( 'dummy', [ 'dummy' => 'comment' ] );
660 $this->fail( 'Expected exception not thrown' );
661 } catch ( InvalidArgumentException $ex ) {
662 $this->assertSame( '$row does not contain fields needed for comment dummy', $ex->getMessage() );
663 }
664 $res = $store->getComment( 'dummy', [ 'dummy' => 'comment' ], true );
665 $this->assertSame( 'comment', $res->text );
666 try {
667 $store->getComment( 'dummy', [ 'dummy_id' => 1 ] );
668 $this->fail( 'Expected exception not thrown' );
669 } catch ( InvalidArgumentException $ex ) {
670 $this->assertSame(
671 '$row does not contain fields needed for comment dummy and getComment(), '
672 . 'but does have fields for getCommentLegacy()',
673 $ex->getMessage()
674 );
675 }
676
677 $store = $this->makeStore( MIGRATION_NEW );
678 try {
679 $store->getComment( 'rev_comment', [ 'rev_comment' => 'comment' ] );
680 $this->fail( 'Expected exception not thrown' );
681 } catch ( InvalidArgumentException $ex ) {
682 $this->assertSame(
683 '$row does not contain fields needed for comment rev_comment', $ex->getMessage()
684 );
685 }
686 $res = $store->getComment( 'rev_comment', [ 'rev_comment' => 'comment' ], true );
687 $this->assertSame( 'comment', $res->text );
688 try {
689 $store->getComment( 'rev_comment', [ 'rev_comment_pk' => 1 ] );
690 $this->fail( 'Expected exception not thrown' );
691 } catch ( InvalidArgumentException $ex ) {
692 $this->assertSame(
693 '$row does not contain fields needed for comment rev_comment and getComment(), '
694 . 'but does have fields for getCommentLegacy()',
695 $ex->getMessage()
696 );
697 }
698 }
699
700 public static function provideStages() {
701 return [
702 'MIGRATION_OLD' => [ MIGRATION_OLD ],
703 'MIGRATION_WRITE_BOTH' => [ MIGRATION_WRITE_BOTH ],
704 'MIGRATION_WRITE_NEW' => [ MIGRATION_WRITE_NEW ],
705 'MIGRATION_NEW' => [ MIGRATION_NEW ],
706 ];
707 }
708
715 public function testInsertWrong( $stage ) {
716 $store = $this->makeStore( $stage );
717 $store->insert( $this->db, 'rev_comment', 'foo' );
718 }
719
726 public function testInsertWithTempTableWrong( $stage ) {
727 $store = $this->makeStore( $stage );
728 $store->insertWithTempTable( $this->db, 'ipb_reason', 'foo' );
729 }
730
735 public function testInsertWithTempTableDeprecated( $stage ) {
736 $wrap = TestingAccessWrapper::newFromClass( CommentStore::class );
737 $wrap->formerTempTables += [ 'ipb_reason' => '1.30' ];
738
739 $this->hideDeprecated( 'CommentStore::insertWithTempTable for ipb_reason' );
740 $store = $this->makeStore( $stage );
741 list( $fields, $callback ) = $store->insertWithTempTable( $this->db, 'ipb_reason', 'foo' );
742 $this->assertTrue( is_callable( $callback ) );
743 }
744
745 public function testInsertTruncation() {
746 $comment = str_repeat( '💣', 16400 );
747 $truncated1 = str_repeat( '💣', 63 ) . '...';
748 $truncated2 = str_repeat( '💣', CommentStore::COMMENT_CHARACTER_LIMIT - 3 ) . '...';
749
750 $store = $this->makeStore( MIGRATION_WRITE_BOTH );
751 $fields = $store->insert( $this->db, 'ipb_reason', $comment );
752 $this->assertSame( $truncated1, $fields['ipb_reason'] );
753 $stored = $this->db->selectField(
754 'comment', 'comment_text', [ 'comment_id' => $fields['ipb_reason_id'] ], __METHOD__
755 );
756 $this->assertSame( $truncated2, $stored );
757 }
758
763 public function testInsertTooMuchData() {
764 $store = $this->makeStore( MIGRATION_WRITE_BOTH );
765 $store->insert( $this->db, 'ipb_reason', 'foo', [
766 'long' => str_repeat( '💣', 16400 )
767 ] );
768 }
769
770 public function testGetStore() {
771 $this->assertInstanceOf( CommentStore::class, CommentStore::getStore() );
772 }
773
774 public function testNewKey() {
775 $this->assertInstanceOf( CommentStore::class, CommentStore::newKey( 'dummy' ) );
776 }
777
778}
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
CommentStoreComment represents a comment stored by CommentStore.
Database CommentStore CommentStoreComment.
testInsertRoundTrip( $table, $key, $pk, $extraFields, $comment, $data, $expect)
provideInsertRoundTrip
testInsertWithTempTableWrong( $stage)
provideStages
testGetFields_withKeyConstruction( $stage, $key, $expect)
provideGetFields
testInsertTooMuchData()
OverflowException Comment data is too long (65611 bytes, maximum is 65535)
testGetFields( $stage, $key, $expect)
provideGetFields
testInsertWrong( $stage)
provideStages
testGetJoin( $stage, $key, $expect)
provideGetJoin
testInsertRoundTrip_withKeyConstruction( $table, $key, $pk, $extraFields, $comment, $data, $expect)
provideInsertRoundTrip
testGetJoin_withKeyConstruction( $stage, $key, $expect)
provideGetJoin
assertComment( $expect, $actual, $from)
makeStoreWithKey( $stage, $key)
Create a store for a particular stage and key (for testing deprecated behaviour)
makeStore( $stage)
Create a store for a particular stage.
static provideInsertRoundTrip()
testInsertWithTempTableDeprecated( $stage)
provideStages
CommentStore handles storage of comments (edit summaries, log reasons, etc) in the database.
Base class that store and restore the Language objects.
Database $db
Primary database.
hideDeprecated( $function)
Don't throw a warning if $function is deprecated and called later.
The Message class provides methods which fulfil two basic services:
Definition Message.php:159
Variant of the Message class.
timestamp( $ts=0)
Convert a timestamp in one of the formats accepted by wfTimestamp() to the format used for inserting ...
getInfinity()
Find out when 'infinity' is.
$res
Definition database.txt:21
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
Definition deferred.txt:11
this class mediates it Skin Encapsulates a look and feel for the wiki All of the functions that render HTML and make choices about how to render it are here and are called from various other places when and is meant to be subclassed with other skins that may override some of its functions The User object contains a reference to a and so rather than having a global skin object we just rely on the global User and get the skin with $wgUser and also has some character encoding functions and other locale stuff The current user interface language is instantiated as and the local content language as $wgContLang
Definition design.txt:57
design txt This is a brief overview of the new design More thorough and up to date information is available on the documentation wiki at etc Handles the details of getting and saving to the user table of the and dealing with sessions and cookies OutputPage Encapsulates the entire HTML page that will be sent in response to any server request It is used by calling its functions to add text
Definition design.txt:18
const MIGRATION_WRITE_NEW
Definition Defines.php:304
const MIGRATION_NEW
Definition Defines.php:305
const MIGRATION_WRITE_BOTH
Definition Defines.php:303
const MIGRATION_OLD
Definition Defines.php:302
const DB_REPLICA
Definition defines.php:25