Merge "jquery.suggestions: Use Object.create( null )"
[lhc/web/wiklou.git] / tests / phpunit / includes / Revision / RevisionQueryInfoTest.php
1 <?php
2
3 namespace MediaWiki\Tests\Revision;
4
5 use MediaWiki\MediaWikiServices;
6 use MediaWiki\Revision\SlotRecord;
7 use MediaWikiTestCase;
8 use Revision;
9
10 /**
11 * Tests RevisionStore against the post-migration MCR DB schema.
12 *
13 * @group RevisionStore
14 * @group Storage
15 * @group Database
16 */
17 class RevisionQueryInfoTest extends MediaWikiTestCase {
18
19 protected function getRevisionQueryFields( $returnTextIdField = true ) {
20 $fields = [
21 'rev_id',
22 'rev_page',
23 'rev_timestamp',
24 'rev_minor_edit',
25 'rev_deleted',
26 'rev_len',
27 'rev_parent_id',
28 'rev_sha1',
29 ];
30 if ( $returnTextIdField ) {
31 $fields[] = 'rev_text_id';
32 }
33 return $fields;
34 }
35
36 protected function getArchiveQueryFields( $returnTextFields = true ) {
37 $fields = [
38 'ar_id',
39 'ar_page_id',
40 'ar_namespace',
41 'ar_title',
42 'ar_rev_id',
43 'ar_timestamp',
44 'ar_minor_edit',
45 'ar_deleted',
46 'ar_len',
47 'ar_parent_id',
48 'ar_sha1',
49 ];
50 if ( $returnTextFields ) {
51 $fields[] = 'ar_text_id';
52 }
53 return $fields;
54 }
55
56 protected function getNewCommentQueryFields( $prefix ) {
57 return [
58 "{$prefix}_comment_text" => "comment_{$prefix}_comment.comment_text",
59 "{$prefix}_comment_data" => "comment_{$prefix}_comment.comment_data",
60 "{$prefix}_comment_cid" => "comment_{$prefix}_comment.comment_id",
61 ];
62 }
63
64 protected function getOldActorQueryFields( $prefix ) {
65 return [
66 "{$prefix}_user" => "{$prefix}_user",
67 "{$prefix}_user_text" => "{$prefix}_user_text",
68 "{$prefix}_actor" => 'NULL',
69 ];
70 }
71
72 protected function getNewActorQueryFields( $prefix, $tmp = false ) {
73 return [
74 "{$prefix}_user" => "actor_{$prefix}_user.actor_user",
75 "{$prefix}_user_text" => "actor_{$prefix}_user.actor_name",
76 "{$prefix}_actor" => $tmp ?: "{$prefix}_actor",
77 ];
78 }
79
80 protected function getNewActorJoins( $prefix ) {
81 return [
82 "temp_{$prefix}_user" => [
83 "JOIN",
84 "temp_{$prefix}_user.revactor_{$prefix} = {$prefix}_id",
85 ],
86 "actor_{$prefix}_user" => [
87 "JOIN",
88 "actor_{$prefix}_user.actor_id = temp_{$prefix}_user.revactor_actor",
89 ],
90 ];
91 }
92
93 protected function getTextQueryFields() {
94 return [
95 'old_text',
96 'old_flags',
97 ];
98 }
99
100 protected function getPageQueryFields() {
101 return [
102 'page_namespace',
103 'page_title',
104 'page_id',
105 'page_latest',
106 'page_is_redirect',
107 'page_len',
108 ];
109 }
110
111 protected function getUserQueryFields() {
112 return [
113 'user_name',
114 ];
115 }
116
117 protected function getContentHandlerQueryFields( $prefix ) {
118 return [
119 "{$prefix}_content_format",
120 "{$prefix}_content_model",
121 ];
122 }
123
124 public function provideArchiveQueryInfo() {
125 yield 'MCR, comment, actor' => [
126 [
127 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
128 'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
129 ],
130 [
131 'tables' => [
132 'archive',
133 'actor_ar_user' => 'actor',
134 'comment_ar_comment' => 'comment',
135 ],
136 'fields' => array_merge(
137 $this->getArchiveQueryFields( false ),
138 $this->getNewActorQueryFields( 'ar' ),
139 $this->getNewCommentQueryFields( 'ar' )
140 ),
141 'joins' => [
142 'comment_ar_comment'
143 => [ 'JOIN', 'comment_ar_comment.comment_id = ar_comment_id' ],
144 'actor_ar_user' => [ 'JOIN', 'actor_ar_user.actor_id = ar_actor' ],
145 ],
146 ]
147 ];
148 yield 'read-new MCR, comment, actor' => [
149 [
150 'wgContentHandlerUseDB' => true,
151 'wgMultiContentRevisionSchemaMigrationStage'
152 => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
153 'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
154 ],
155 [
156 'tables' => [
157 'archive',
158 'actor_ar_user' => 'actor',
159 'comment_ar_comment' => 'comment',
160 ],
161 'fields' => array_merge(
162 $this->getArchiveQueryFields( false ),
163 $this->getNewActorQueryFields( 'ar' ),
164 $this->getNewCommentQueryFields( 'ar' )
165 ),
166 'joins' => [
167 'comment_ar_comment'
168 => [ 'JOIN', 'comment_ar_comment.comment_id = ar_comment_id' ],
169 'actor_ar_user' => [ 'JOIN', 'actor_ar_user.actor_id = ar_actor' ],
170 ],
171 ]
172 ];
173 yield 'MCR write-both/read-old' => [
174 [
175 'wgContentHandlerUseDB' => true,
176 'wgMultiContentRevisionSchemaMigrationStage'
177 => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
178 'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
179 ],
180 [
181 'tables' => [
182 'archive',
183 'comment_ar_comment' => 'comment',
184 ],
185 'fields' => array_merge(
186 $this->getArchiveQueryFields( true ),
187 $this->getContentHandlerQueryFields( 'ar' ),
188 $this->getOldActorQueryFields( 'ar' ),
189 $this->getNewCommentQueryFields( 'ar' )
190 ),
191 'joins' => [
192 'comment_ar_comment'
193 => [ 'JOIN', 'comment_ar_comment.comment_id = ar_comment_id' ],
194 ],
195 ]
196 ];
197 yield 'pre-MCR, no model' => [
198 [
199 'wgContentHandlerUseDB' => false,
200 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
201 'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
202 ],
203 [
204 'tables' => [
205 'archive',
206 'comment_ar_comment' => 'comment',
207 ],
208 'fields' => array_merge(
209 $this->getArchiveQueryFields( true ),
210 $this->getOldActorQueryFields( 'ar' ),
211 $this->getNewCommentQueryFields( 'ar' )
212 ),
213 'joins' => [
214 'comment_ar_comment'
215 => [ 'JOIN', 'comment_ar_comment.comment_id = ar_comment_id' ],
216 ],
217 ]
218 ];
219 }
220
221 public function provideQueryInfo() {
222 // TODO: more option variations
223 yield 'MCR, page, user, comment, actor' => [
224 [
225 'wgContentHandlerUseDB' => true,
226 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
227 'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
228 ],
229 [ 'page', 'user' ],
230 [
231 'tables' => [
232 'revision',
233 'page',
234 'user',
235 'temp_rev_user' => 'revision_actor_temp',
236 'temp_rev_comment' => 'revision_comment_temp',
237 'actor_rev_user' => 'actor',
238 'comment_rev_comment' => 'comment',
239 ],
240 'fields' => array_merge(
241 $this->getRevisionQueryFields( false ),
242 $this->getPageQueryFields(),
243 $this->getUserQueryFields(),
244 $this->getNewActorQueryFields( 'rev', 'temp_rev_user.revactor_actor' ),
245 $this->getNewCommentQueryFields( 'rev' )
246 ),
247 'joins' => [
248 'page' => [ 'JOIN', [ 'page_id = rev_page' ] ],
249 'user' => [
250 'LEFT JOIN',
251 [ 'actor_rev_user.actor_user != 0', 'user_id = actor_rev_user.actor_user' ],
252 ],
253 'comment_rev_comment' => [
254 'JOIN',
255 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id',
256 ],
257 'actor_rev_user' => [
258 'JOIN',
259 'actor_rev_user.actor_id = temp_rev_user.revactor_actor',
260 ],
261 'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
262 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
263 ],
264 ]
265 ];
266 yield 'MCR read-new, page, user, comment, actor' => [
267 [
268 'wgContentHandlerUseDB' => true,
269 'wgMultiContentRevisionSchemaMigrationStage'
270 => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
271 'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
272 ],
273 [ 'page', 'user' ],
274 [
275 'tables' => [
276 'revision',
277 'page',
278 'user',
279 'temp_rev_user' => 'revision_actor_temp',
280 'temp_rev_comment' => 'revision_comment_temp',
281 'actor_rev_user' => 'actor',
282 'comment_rev_comment' => 'comment',
283 ],
284 'fields' => array_merge(
285 $this->getRevisionQueryFields( false ),
286 $this->getPageQueryFields(),
287 $this->getUserQueryFields(),
288 $this->getNewActorQueryFields( 'rev', 'temp_rev_user.revactor_actor' ),
289 $this->getNewCommentQueryFields( 'rev' )
290 ),
291 'joins' => array_merge(
292 [
293 'page' => [ 'JOIN', [ 'page_id = rev_page' ] ],
294 'user' => [
295 'LEFT JOIN',
296 [
297 'actor_rev_user.actor_user != 0',
298 'user_id = actor_rev_user.actor_user',
299 ]
300 ],
301 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
302 'comment_rev_comment'
303 => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
304 ],
305 $this->getNewActorJoins( 'rev' )
306 ),
307 ]
308 ];
309 yield 'MCR read-new' => [
310 [
311 'wgContentHandlerUseDB' => true,
312 'wgMultiContentRevisionSchemaMigrationStage'
313 => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
314 'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
315 ],
316 [ 'page', 'user' ],
317 [
318 'tables' => [
319 'revision',
320 'page',
321 'user',
322 'temp_rev_user' => 'revision_actor_temp',
323 'temp_rev_comment' => 'revision_comment_temp',
324 'actor_rev_user' => 'actor',
325 'comment_rev_comment' => 'comment',
326 ],
327 'fields' => array_merge(
328 $this->getRevisionQueryFields( false ),
329 $this->getPageQueryFields(),
330 $this->getUserQueryFields(),
331 $this->getNewActorQueryFields( 'rev', 'temp_rev_user.revactor_actor' ),
332 $this->getNewCommentQueryFields( 'rev' )
333 ),
334 'joins' => array_merge(
335 [
336 'page' => [ 'JOIN', [ 'page_id = rev_page' ] ],
337 'user' => [
338 'LEFT JOIN',
339 [
340 'actor_rev_user.actor_user != 0',
341 'user_id = actor_rev_user.actor_user'
342 ]
343 ],
344 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
345 'comment_rev_comment'
346 => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
347 ],
348 $this->getNewActorJoins( 'rev' )
349 ),
350 ]
351 ];
352 yield 'MCR write-both/read-old' => [
353 [
354 'wgContentHandlerUseDB' => true,
355 'wgMultiContentRevisionSchemaMigrationStage'
356 => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
357 'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
358 ],
359 [],
360 [
361 'tables' => [
362 'revision',
363 'temp_rev_comment' => 'revision_comment_temp',
364 'comment_rev_comment' => 'comment',
365 ],
366 'fields' => array_merge(
367 $this->getRevisionQueryFields( true ),
368 $this->getContentHandlerQueryFields( 'rev' ),
369 $this->getOldActorQueryFields( 'rev', 'temp_rev_user.revactor_actor' ),
370 $this->getNewCommentQueryFields( 'rev' )
371 ),
372 'joins' => [
373 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
374 'comment_rev_comment'
375 => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
376 ],
377 ]
378 ];
379 yield 'MCR write-both/read-old, page, user' => [
380 [
381 'wgContentHandlerUseDB' => true,
382 'wgMultiContentRevisionSchemaMigrationStage'
383 => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
384 'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
385 ],
386 [ 'page', 'user' ],
387 [
388 'tables' => [
389 'revision',
390 'page',
391 'user',
392 'temp_rev_comment' => 'revision_comment_temp',
393 'comment_rev_comment' => 'comment',
394 ],
395 'fields' => array_merge(
396 $this->getRevisionQueryFields( true ),
397 $this->getContentHandlerQueryFields( 'rev' ),
398 $this->getUserQueryFields(),
399 $this->getPageQueryFields(),
400 $this->getOldActorQueryFields( 'rev', 'temp_rev_user.revactor_actor' ),
401 $this->getNewCommentQueryFields( 'rev' )
402 ),
403 'joins' => array_merge(
404 [
405 'page' => [ 'JOIN', [ 'page_id = rev_page' ] ],
406 'user' => [
407 'LEFT JOIN',
408 [
409 'rev_user != 0',
410 'user_id = rev_user'
411 ]
412 ],
413 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
414 'comment_rev_comment'
415 => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
416 ]
417 ),
418 ]
419 ];
420 yield 'pre-MCR' => [
421 [
422 'wgContentHandlerUseDB' => true,
423 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
424 'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
425 ],
426 [],
427 [
428 'tables' => [
429 'revision',
430 'temp_rev_comment' => 'revision_comment_temp',
431 'comment_rev_comment' => 'comment',
432 ],
433 'fields' => array_merge(
434 $this->getRevisionQueryFields( true ),
435 $this->getContentHandlerQueryFields( 'rev' ),
436 $this->getOldActorQueryFields( 'rev' ),
437 $this->getNewCommentQueryFields( 'rev' )
438 ),
439 'joins' => [
440 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
441 'comment_rev_comment'
442 => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
443 ],
444 ]
445 ];
446 yield 'pre-MCR, page, user' => [
447 [
448 'wgContentHandlerUseDB' => true,
449 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
450 'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
451 ],
452 [ 'page', 'user' ],
453 [
454 'tables' => [
455 'revision', 'page', 'user',
456 'temp_rev_comment' => 'revision_comment_temp',
457 'comment_rev_comment' => 'comment',
458 ],
459 'fields' => array_merge(
460 $this->getRevisionQueryFields( true ),
461 $this->getContentHandlerQueryFields( 'rev' ),
462 $this->getPageQueryFields(),
463 $this->getUserQueryFields(),
464 $this->getOldActorQueryFields( 'rev' ),
465 $this->getNewCommentQueryFields( 'rev' )
466 ),
467 'joins' => [
468 'page' => [ 'JOIN', [ 'page_id = rev_page' ] ],
469 'user' => [ 'LEFT JOIN', [ 'rev_user != 0', 'user_id = rev_user' ] ],
470 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
471 'comment_rev_comment'
472 => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
473 ],
474 ]
475 ];
476 yield 'pre-MCR, no model' => [
477 [
478 'wgContentHandlerUseDB' => false,
479 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
480 'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
481 ],
482 [],
483 [
484 'tables' => [
485 'revision',
486 'temp_rev_comment' => 'revision_comment_temp',
487 'comment_rev_comment' => 'comment',
488 ],
489 'fields' => array_merge(
490 $this->getRevisionQueryFields( true ),
491 $this->getOldActorQueryFields( 'rev' ),
492 $this->getNewCommentQueryFields( 'rev' )
493 ),
494 'joins' => [
495 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
496 'comment_rev_comment'
497 => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
498 ],
499 ],
500 ];
501 yield 'pre-MCR, no model, page' => [
502 [
503 'wgContentHandlerUseDB' => false,
504 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
505 'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
506 ],
507 [ 'page' ],
508 [
509 'tables' => [
510 'revision', 'page',
511 'temp_rev_comment' => 'revision_comment_temp',
512 'comment_rev_comment' => 'comment',
513 ],
514 'fields' => array_merge(
515 $this->getRevisionQueryFields( true ),
516 $this->getPageQueryFields(),
517 $this->getOldActorQueryFields( 'rev' ),
518 $this->getNewCommentQueryFields( 'rev' )
519 ),
520 'joins' => [
521 'page' => [ 'JOIN', [ 'page_id = rev_page' ], ],
522 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
523 'comment_rev_comment'
524 => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
525 ],
526 ],
527 ];
528 yield 'pre-MCR, no model, user' => [
529 [
530 'wgContentHandlerUseDB' => false,
531 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
532 'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
533 ],
534 [ 'user' ],
535 [
536 'tables' => [
537 'revision', 'user',
538 'temp_rev_comment' => 'revision_comment_temp',
539 'comment_rev_comment' => 'comment',
540 ],
541 'fields' => array_merge(
542 $this->getRevisionQueryFields( true ),
543 $this->getUserQueryFields(),
544 $this->getOldActorQueryFields( 'rev' ),
545 $this->getNewCommentQueryFields( 'rev' )
546 ),
547 'joins' => [
548 'user' => [ 'LEFT JOIN', [ 'rev_user != 0', 'user_id = rev_user' ] ],
549 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
550 'comment_rev_comment'
551 => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
552 ],
553 ],
554 ];
555 yield 'pre-MCR, no model, text' => [
556 [
557 'wgContentHandlerUseDB' => false,
558 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
559 'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
560 ],
561 [ 'text' ],
562 [
563 'tables' => [
564 'revision', 'text',
565 'temp_rev_comment' => 'revision_comment_temp',
566 'comment_rev_comment' => 'comment',
567 ],
568 'fields' => array_merge(
569 $this->getRevisionQueryFields( true ),
570 $this->getTextQueryFields(),
571 $this->getOldActorQueryFields( 'rev' ),
572 $this->getNewCommentQueryFields( 'rev' )
573 ),
574 'joins' => [
575 'text' => [ 'JOIN', [ 'rev_text_id=old_id' ] ],
576 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
577 'comment_rev_comment'
578 => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
579 ],
580 ],
581 ];
582 yield 'pre-MCR, no model, text, page, user' => [
583 [
584 'wgContentHandlerUseDB' => false,
585 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
586 'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
587 ],
588 [ 'text', 'page', 'user' ],
589 [
590 'tables' => [
591 'revision', 'page', 'user', 'text',
592 'temp_rev_comment' => 'revision_comment_temp',
593 'comment_rev_comment' => 'comment',
594 ],
595 'fields' => array_merge(
596 $this->getRevisionQueryFields( true ),
597 $this->getPageQueryFields(),
598 $this->getUserQueryFields(),
599 $this->getTextQueryFields(),
600 $this->getOldActorQueryFields( 'rev' ),
601 $this->getNewCommentQueryFields( 'rev' )
602 ),
603 'joins' => [
604 'page' => [
605 'JOIN',
606 [ 'page_id = rev_page' ],
607 ],
608 'user' => [
609 'LEFT JOIN',
610 [
611 'rev_user != 0',
612 'user_id = rev_user',
613 ],
614 ],
615 'text' => [
616 'JOIN',
617 [ 'rev_text_id=old_id' ],
618 ],
619 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
620 'comment_rev_comment'
621 => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
622 ],
623 ],
624 ];
625 }
626
627 public function provideSlotsQueryInfo() {
628 yield 'MCR, no options' => [
629 [
630 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
631 ],
632 [],
633 [
634 'tables' => [
635 'slots'
636 ],
637 'fields' => [
638 'slot_revision_id',
639 'slot_content_id',
640 'slot_origin',
641 'slot_role_id',
642 ],
643 'joins' => [],
644 ]
645 ];
646 yield 'MCR, role option' => [
647 [
648 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
649 ],
650 [ 'role' ],
651 [
652 'tables' => [
653 'slots',
654 'slot_roles',
655 ],
656 'fields' => [
657 'slot_revision_id',
658 'slot_content_id',
659 'slot_origin',
660 'slot_role_id',
661 'role_name',
662 ],
663 'joins' => [
664 'slot_roles' => [ 'LEFT JOIN', [ 'slot_role_id = role_id' ] ],
665 ],
666 ]
667 ];
668 yield 'MCR read-new, content option' => [
669 [
670 'wgMultiContentRevisionSchemaMigrationStage'
671 => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
672 ],
673 [ 'content' ],
674 [
675 'tables' => [
676 'slots',
677 'content',
678 ],
679 'fields' => [
680 'slot_revision_id',
681 'slot_content_id',
682 'slot_origin',
683 'slot_role_id',
684 'content_size',
685 'content_sha1',
686 'content_address',
687 'content_model',
688 ],
689 'joins' => [
690 'content' => [ 'JOIN', [ 'slot_content_id = content_id' ] ],
691 ],
692 ]
693 ];
694 yield 'MCR read-new, content and model options' => [
695 [
696 'wgMultiContentRevisionSchemaMigrationStage'
697 => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
698 ],
699 [ 'content', 'model' ],
700 [
701 'tables' => [
702 'slots',
703 'content',
704 'content_models',
705 ],
706 'fields' => [
707 'slot_revision_id',
708 'slot_content_id',
709 'slot_origin',
710 'slot_role_id',
711 'content_size',
712 'content_sha1',
713 'content_address',
714 'content_model',
715 'model_name',
716 ],
717 'joins' => [
718 'content' => [ 'JOIN', [ 'slot_content_id = content_id' ] ],
719 'content_models' => [ 'LEFT JOIN', [ 'content_model = model_id' ] ],
720 ],
721 ]
722 ];
723
724 $db = wfGetDB( DB_REPLICA );
725
726 yield 'MCR write-both/read-old' => [
727 [
728 'wgMultiContentRevisionSchemaMigrationStage'
729 => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
730 ],
731 [],
732 [
733 'tables' => [
734 'slots' => 'revision',
735 ],
736 'fields' => array_merge(
737 [
738 'slot_revision_id' => 'slots.rev_id',
739 'slot_content_id' => 'NULL',
740 'slot_origin' => 'slots.rev_id',
741 'role_name' => $db->addQuotes( SlotRecord::MAIN ),
742 ]
743 ),
744 'joins' => [],
745 ]
746 ];
747 yield 'MCR write-both/read-old, content' => [
748 [
749 'wgMultiContentRevisionSchemaMigrationStage'
750 => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
751 ],
752 [ 'content' ],
753 [
754 'tables' => [
755 'slots' => 'revision',
756 ],
757 'fields' => array_merge(
758 [
759 'slot_revision_id' => 'slots.rev_id',
760 'slot_content_id' => 'NULL',
761 'slot_origin' => 'slots.rev_id',
762 'role_name' => $db->addQuotes( SlotRecord::MAIN ),
763 'content_size' => 'slots.rev_len',
764 'content_sha1' => 'slots.rev_sha1',
765 'content_address' => $db->buildConcat( [
766 $db->addQuotes( 'tt:' ), 'slots.rev_text_id' ] ),
767 'model_name' => 'slots.rev_content_model',
768 ]
769 ),
770 'joins' => [],
771 ]
772 ];
773 yield 'MCR write-both/read-old, content, model, role' => [
774 [
775 'wgMultiContentRevisionSchemaMigrationStage'
776 => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
777 ],
778 [ 'content', 'model', 'role' ],
779 [
780 'tables' => [
781 'slots' => 'revision',
782 ],
783 'fields' => array_merge(
784 [
785 'slot_revision_id' => 'slots.rev_id',
786 'slot_content_id' => 'NULL',
787 'slot_origin' => 'slots.rev_id',
788 'role_name' => $db->addQuotes( SlotRecord::MAIN ),
789 'content_size' => 'slots.rev_len',
790 'content_sha1' => 'slots.rev_sha1',
791 'content_address' => $db->buildConcat( [
792 $db->addQuotes( 'tt:' ), 'slots.rev_text_id' ] ),
793 'model_name' => 'slots.rev_content_model',
794 ]
795 ),
796 'joins' => [],
797 ]
798 ];
799 yield 'pre-MCR' => [
800 [
801 'wgMultiContentRevisionSchemaMigrationStage'
802 => SCHEMA_COMPAT_OLD,
803 ],
804 [],
805 [
806 'tables' => [
807 'slots' => 'revision',
808 ],
809 'fields' => array_merge(
810 [
811 'slot_revision_id' => 'slots.rev_id',
812 'slot_content_id' => 'NULL',
813 'slot_origin' => 'slots.rev_id',
814 'role_name' => $db->addQuotes( SlotRecord::MAIN ),
815 ]
816 ),
817 'joins' => [],
818 ]
819 ];
820 yield 'pre-MCR, content' => [
821 [
822 'wgMultiContentRevisionSchemaMigrationStage'
823 => SCHEMA_COMPAT_OLD,
824 ],
825 [ 'content' ],
826 [
827 'tables' => [
828 'slots' => 'revision',
829 ],
830 'fields' => array_merge(
831 [
832 'slot_revision_id' => 'slots.rev_id',
833 'slot_content_id' => 'NULL',
834 'slot_origin' => 'slots.rev_id',
835 'role_name' => $db->addQuotes( SlotRecord::MAIN ),
836 'content_size' => 'slots.rev_len',
837 'content_sha1' => 'slots.rev_sha1',
838 'content_address' =>
839 $db->buildConcat( [ $db->addQuotes( 'tt:' ), 'slots.rev_text_id' ] ),
840 'model_name' => 'slots.rev_content_model',
841 ]
842 ),
843 'joins' => [],
844 ]
845 ];
846 }
847
848 public function provideSelectFields() {
849 yield 'with model, comment, and actor' => [
850 [
851 'wgContentHandlerUseDB' => true,
852 'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
853 ],
854 'fields' => array_merge(
855 [
856 'rev_id',
857 'rev_page',
858 'rev_text_id',
859 'rev_timestamp',
860 'rev_user_text',
861 'rev_user',
862 'rev_actor' => 'NULL',
863 'rev_minor_edit',
864 'rev_deleted',
865 'rev_len',
866 'rev_parent_id',
867 'rev_sha1',
868 ],
869 $this->getContentHandlerQueryFields( 'rev' ),
870 [
871 'rev_comment_pk' => 'rev_id',
872 ]
873 ),
874 ];
875 yield 'no mode, no comment, no actor' => [
876 [
877 'wgContentHandlerUseDB' => false,
878 'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
879 ],
880 'fields' => array_merge(
881 [
882 'rev_id',
883 'rev_page',
884 'rev_text_id',
885 'rev_timestamp',
886 'rev_user_text',
887 'rev_user',
888 'rev_actor' => 'NULL',
889 'rev_minor_edit',
890 'rev_deleted',
891 'rev_len',
892 'rev_parent_id',
893 'rev_sha1',
894 'rev_comment_pk' => 'rev_id',
895 ]
896 ),
897 ];
898 }
899
900 public function provideSelectArchiveFields() {
901 yield 'with model, comment, and actor' => [
902 [
903 'wgContentHandlerUseDB' => true,
904 'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
905 ],
906 'fields' => array_merge(
907 [
908 'ar_id',
909 'ar_page_id',
910 'ar_rev_id',
911 'ar_text_id',
912 'ar_timestamp',
913 'ar_user_text',
914 'ar_user',
915 'ar_actor' => 'NULL',
916 'ar_minor_edit',
917 'ar_deleted',
918 'ar_len',
919 'ar_parent_id',
920 'ar_sha1',
921 ],
922 $this->getContentHandlerQueryFields( 'ar' ),
923 [
924 'ar_comment_id' => 'ar_comment_id',
925 ]
926 ),
927 ];
928 yield 'no mode, no comment, no actor' => [
929 [
930 'wgContentHandlerUseDB' => false,
931 'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
932 ],
933 'fields' => array_merge(
934 [
935 'ar_id',
936 'ar_page_id',
937 'ar_rev_id',
938 'ar_text_id',
939 'ar_timestamp',
940 'ar_user_text',
941 'ar_user',
942 'ar_actor' => 'NULL',
943 'ar_minor_edit',
944 'ar_deleted',
945 'ar_len',
946 'ar_parent_id',
947 'ar_sha1',
948 'ar_comment_id' => 'ar_comment_id',
949 ]
950 ),
951 ];
952 }
953
954 /**
955 * @dataProvider provideSelectFields
956 * @covers Revision::selectFields
957 */
958 public function testRevisionSelectFields( $migrationStageSettings, $expected ) {
959 $this->setMwGlobals( $migrationStageSettings );
960 $this->overrideMwServices();
961
962 $this->hideDeprecated( 'Revision::selectFields' );
963 $this->assertArrayEqualsIgnoringIntKeyOrder( $expected, Revision::selectFields() );
964 }
965
966 /**
967 * @dataProvider provideSelectArchiveFields
968 * @covers Revision::selectArchiveFields
969 */
970 public function testRevisionSelectArchiveFields( $migrationStageSettings, $expected ) {
971 $this->setMwGlobals( $migrationStageSettings );
972 $this->overrideMwServices();
973
974 $this->hideDeprecated( 'Revision::selectArchiveFields' );
975 $this->assertArrayEqualsIgnoringIntKeyOrder( $expected, Revision::selectArchiveFields() );
976 }
977
978 /**
979 * @covers Revision::userJoinCond
980 */
981 public function testRevisionUserJoinCond() {
982 $this->hideDeprecated( 'Revision::userJoinCond' );
983 $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', SCHEMA_COMPAT_OLD );
984 $this->overrideMwServices();
985 $this->assertEquals(
986 [ 'LEFT JOIN', [ 'rev_user != 0', 'user_id = rev_user' ] ],
987 Revision::userJoinCond()
988 );
989 }
990
991 /**
992 * @covers Revision::pageJoinCond
993 */
994 public function testRevisionPageJoinCond() {
995 $this->hideDeprecated( 'Revision::pageJoinCond' );
996 $this->assertEquals(
997 [ 'JOIN', [ 'page_id = rev_page' ] ],
998 Revision::pageJoinCond()
999 );
1000 }
1001
1002 /**
1003 * @covers Revision::selectTextFields
1004 */
1005 public function testRevisionSelectTextFields() {
1006 $this->hideDeprecated( 'Revision::selectTextFields' );
1007 $this->assertEquals(
1008 $this->getTextQueryFields(),
1009 Revision::selectTextFields()
1010 );
1011 }
1012
1013 /**
1014 * @covers Revision::selectPageFields
1015 */
1016 public function testRevisionSelectPageFields() {
1017 $this->hideDeprecated( 'Revision::selectPageFields' );
1018 $this->assertEquals(
1019 $this->getPageQueryFields(),
1020 Revision::selectPageFields()
1021 );
1022 }
1023
1024 /**
1025 * @covers Revision::selectUserFields
1026 */
1027 public function testRevisionSelectUserFields() {
1028 $this->hideDeprecated( 'Revision::selectUserFields' );
1029 $this->assertEquals(
1030 $this->getUserQueryFields(),
1031 Revision::selectUserFields()
1032 );
1033 }
1034
1035 /**
1036 * @covers Revision::getArchiveQueryInfo
1037 * @dataProvider provideArchiveQueryInfo
1038 */
1039 public function testRevisionGetArchiveQueryInfo( $migrationStageSettings, $expected ) {
1040 $this->setMwGlobals( $migrationStageSettings );
1041 $this->overrideMwServices();
1042
1043 $queryInfo = Revision::getArchiveQueryInfo();
1044 $this->assertQueryInfoEquals( $expected, $queryInfo );
1045 }
1046
1047 /**
1048 * @covers Revision::getQueryInfo
1049 * @dataProvider provideQueryInfo
1050 */
1051 public function testRevisionGetQueryInfo( $migrationStageSettings, $options, $expected ) {
1052 $this->setMwGlobals( $migrationStageSettings );
1053 $this->overrideMwServices();
1054
1055 $queryInfo = Revision::getQueryInfo( $options );
1056 $this->assertQueryInfoEquals( $expected, $queryInfo );
1057 }
1058
1059 /**
1060 * @dataProvider provideQueryInfo
1061 * @covers \MediaWiki\Revision\RevisionStore::getQueryInfo
1062 */
1063 public function testRevisionStoreGetQueryInfo( $migrationStageSettings, $options, $expected ) {
1064 $this->setMwGlobals( $migrationStageSettings );
1065 $this->overrideMwServices();
1066
1067 $store = MediaWikiServices::getInstance()->getRevisionStore();
1068
1069 $queryInfo = $store->getQueryInfo( $options );
1070 $this->assertQueryInfoEquals( $expected, $queryInfo );
1071 }
1072
1073 /**
1074 * @dataProvider provideSlotsQueryInfo
1075 * @covers \MediaWiki\Revision\RevisionStore::getSlotsQueryInfo
1076 */
1077 public function testRevisionStoreGetSlotsQueryInfo(
1078 $migrationStageSettings,
1079 $options,
1080 $expected
1081 ) {
1082 $this->setMwGlobals( $migrationStageSettings );
1083 $this->overrideMwServices();
1084
1085 $store = MediaWikiServices::getInstance()->getRevisionStore();
1086
1087 $queryInfo = $store->getSlotsQueryInfo( $options );
1088 $this->assertQueryInfoEquals( $expected, $queryInfo );
1089 }
1090
1091 /**
1092 * @dataProvider provideArchiveQueryInfo
1093 * @covers \MediaWiki\Revision\RevisionStore::getArchiveQueryInfo
1094 */
1095 public function testRevisionStoreGetArchiveQueryInfo( $migrationStageSettings, $expected ) {
1096 $this->setMwGlobals( $migrationStageSettings );
1097 $this->overrideMwServices();
1098
1099 $store = MediaWikiServices::getInstance()->getRevisionStore();
1100
1101 $queryInfo = $store->getArchiveQueryInfo();
1102 $this->assertQueryInfoEquals( $expected, $queryInfo );
1103 }
1104
1105 private function assertQueryInfoEquals( $expected, $queryInfo ) {
1106 $this->assertArrayEqualsIgnoringIntKeyOrder(
1107 $expected['tables'],
1108 $queryInfo['tables'],
1109 'tables'
1110 );
1111 $this->assertArrayEqualsIgnoringIntKeyOrder(
1112 $expected['fields'],
1113 $queryInfo['fields'],
1114 'fields'
1115 );
1116 $this->assertArrayEqualsIgnoringIntKeyOrder(
1117 $expected['joins'],
1118 $queryInfo['joins'],
1119 'joins'
1120 );
1121 }
1122
1123 /**
1124 * Assert that the two arrays passed are equal, ignoring the order of the values that integer
1125 * keys.
1126 *
1127 * Note: Failures of this assertion can be slightly confusing as the arrays are actually
1128 * split into a string key array and an int key array before assertions occur.
1129 *
1130 * @param array $expected
1131 * @param array $actual
1132 */
1133 private function assertArrayEqualsIgnoringIntKeyOrder(
1134 array $expected,
1135 array $actual,
1136 $message = null
1137 ) {
1138 $this->objectAssociativeSort( $expected );
1139 $this->objectAssociativeSort( $actual );
1140
1141 // Separate the int key values from the string key values so that assertion failures are
1142 // easier to understand.
1143 $expectedIntKeyValues = [];
1144 $actualIntKeyValues = [];
1145
1146 // Remove all int keys and re add them at the end after sorting by value
1147 // This will result in all int keys being in the same order with same ints at the end of
1148 // the array
1149 foreach ( $expected as $key => $value ) {
1150 if ( is_int( $key ) ) {
1151 unset( $expected[$key] );
1152 $expectedIntKeyValues[] = $value;
1153 }
1154 }
1155 foreach ( $actual as $key => $value ) {
1156 if ( is_int( $key ) ) {
1157 unset( $actual[$key] );
1158 $actualIntKeyValues[] = $value;
1159 }
1160 }
1161
1162 $this->objectAssociativeSort( $expected );
1163 $this->objectAssociativeSort( $actual );
1164
1165 $this->objectAssociativeSort( $expectedIntKeyValues );
1166 $this->objectAssociativeSort( $actualIntKeyValues );
1167
1168 $this->assertEquals( $expected, $actual, $message );
1169 $this->assertEquals( $expectedIntKeyValues, $actualIntKeyValues, $message );
1170 }
1171
1172 }