Merge "Make DBAccessBase use DBConnRef, rename $wiki, and hide getLoadBalancer()"
[lhc/web/wiklou.git] / includes / import / WikiRevision.php
1 <?php
2 /**
3 * MediaWiki page data importer.
4 *
5 * Copyright © 2003,2005 Brion Vibber <brion@pobox.com>
6 * https://www.mediawiki.org/
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 * http://www.gnu.org/copyleft/gpl.html
22 *
23 * @file
24 * @ingroup SpecialPage
25 */
26 use MediaWiki\Logger\LoggerFactory;
27 use MediaWiki\MediaWikiServices;
28
29 /**
30 * Represents a revision, log entry or upload during the import process.
31 * This class sticks closely to the structure of the XML dump.
32 *
33 * @since 1.2
34 *
35 * @ingroup SpecialPage
36 */
37 class WikiRevision implements ImportableUploadRevision, ImportableOldRevision {
38
39 /**
40 * @since 1.2
41 * @var Title
42 */
43 public $title = null;
44
45 /**
46 * @since 1.6.4
47 * @var int
48 */
49 public $id = 0;
50
51 /**
52 * @since 1.2
53 * @var string
54 */
55 public $timestamp = "20010115000000";
56
57 /**
58 * @since 1.2
59 * @var string
60 */
61 public $user_text = "";
62
63 /**
64 * @since 1.27
65 * @var User
66 */
67 public $userObj = null;
68
69 /**
70 * @since 1.21
71 * @var string
72 */
73 public $model = null;
74
75 /**
76 * @since 1.21
77 * @var string
78 */
79 public $format = null;
80
81 /**
82 * @since 1.2
83 * @var string
84 */
85 public $text = "";
86
87 /**
88 * @since 1.12.2
89 * @var int
90 */
91 protected $size;
92
93 /**
94 * @since 1.21
95 * @var Content
96 */
97 public $content = null;
98
99 /**
100 * @since 1.24
101 * @var ContentHandler
102 */
103 protected $contentHandler = null;
104
105 /**
106 * @since 1.2.6
107 * @var string
108 */
109 public $comment = "";
110
111 /**
112 * @since 1.5.7
113 * @var bool
114 */
115 public $minor = false;
116
117 /**
118 * @since 1.12.2
119 * @var string
120 */
121 public $type = "";
122
123 /**
124 * @since 1.12.2
125 * @var string
126 */
127 public $action = "";
128
129 /**
130 * @since 1.12.2
131 * @var string
132 */
133 public $params = "";
134
135 /**
136 * @since 1.17
137 * @var string
138 */
139 public $fileSrc = '';
140
141 /**
142 * @since 1.17
143 * @var bool|string
144 */
145 public $sha1base36 = false;
146
147 /**
148 * @since 1.34
149 * @var string[]
150 */
151 protected $tags = [];
152
153 /**
154 * @since 1.17
155 * @var string
156 */
157 public $archiveName = '';
158
159 /**
160 * @since 1.12.2
161 */
162 protected $filename;
163
164 /**
165 * @since 1.12.2
166 * @var string|null
167 */
168 protected $src = null;
169
170 /**
171 * @since 1.18
172 * @var bool
173 * @todo Unused?
174 */
175 public $isTemp = false;
176
177 /**
178 * @since 1.18
179 * @deprecated 1.29 use Wikirevision::isTempSrc()
180 * First written to in 43d5d3b682cc1733ad01a837d11af4a402d57e6a
181 * Actually introduced in 52cd34acf590e5be946b7885ffdc13a157c1c6cf
182 */
183 public $fileIsTemp;
184
185 /** @var bool */
186 private $mNoUpdates = false;
187
188 /** @var Config $config */
189 private $config;
190
191 public function __construct( Config $config ) {
192 $this->config = $config;
193 }
194
195 /**
196 * @since 1.7 taking a Title object (string before)
197 * @param Title $title
198 * @throws MWException
199 */
200 public function setTitle( $title ) {
201 if ( is_object( $title ) ) {
202 $this->title = $title;
203 } elseif ( is_null( $title ) ) {
204 throw new MWException( "WikiRevision given a null title in import. "
205 . "You may need to adjust \$wgLegalTitleChars." );
206 } else {
207 throw new MWException( "WikiRevision given non-object title in import." );
208 }
209 }
210
211 /**
212 * @since 1.6.4
213 * @param int $id
214 */
215 public function setID( $id ) {
216 $this->id = $id;
217 }
218
219 /**
220 * @since 1.2
221 * @param string $ts
222 */
223 public function setTimestamp( $ts ) {
224 # 2003-08-05T18:30:02Z
225 $this->timestamp = wfTimestamp( TS_MW, $ts );
226 }
227
228 /**
229 * @since 1.2
230 * @param string $user
231 */
232 public function setUsername( $user ) {
233 $this->user_text = $user;
234 }
235
236 /**
237 * @since 1.27
238 * @param User $user
239 */
240 public function setUserObj( $user ) {
241 $this->userObj = $user;
242 }
243
244 /**
245 * @since 1.2
246 * @param string $ip
247 */
248 public function setUserIP( $ip ) {
249 $this->user_text = $ip;
250 }
251
252 /**
253 * @since 1.21
254 * @param string $model
255 */
256 public function setModel( $model ) {
257 $this->model = $model;
258 }
259
260 /**
261 * @since 1.21
262 * @param string $format
263 */
264 public function setFormat( $format ) {
265 $this->format = $format;
266 }
267
268 /**
269 * @since 1.2
270 * @param string $text
271 */
272 public function setText( $text ) {
273 $this->text = $text;
274 }
275
276 /**
277 * @since 1.2.6
278 * @param string $text
279 */
280 public function setComment( $text ) {
281 $this->comment = $text;
282 }
283
284 /**
285 * @since 1.5.7
286 * @param bool $minor
287 */
288 public function setMinor( $minor ) {
289 $this->minor = (bool)$minor;
290 }
291
292 /**
293 * @since 1.12.2
294 * @param string|null $src
295 */
296 public function setSrc( $src ) {
297 $this->src = $src;
298 }
299
300 /**
301 * @since 1.17
302 * @param string $src
303 * @param bool $isTemp
304 */
305 public function setFileSrc( $src, $isTemp ) {
306 $this->fileSrc = $src;
307 $this->fileIsTemp = $isTemp;
308 $this->isTemp = $isTemp;
309 }
310
311 /**
312 * @since 1.17
313 * @param string $sha1base36
314 */
315 public function setSha1Base36( $sha1base36 ) {
316 $this->sha1base36 = $sha1base36;
317 }
318
319 /**
320 * @since 1.34
321 * @param string[] $tags
322 */
323 public function setTags( array $tags ) {
324 $this->tags = $tags;
325 }
326
327 /**
328 * @since 1.12.2
329 * @param string $filename
330 */
331 public function setFilename( $filename ) {
332 $this->filename = $filename;
333 }
334
335 /**
336 * @since 1.17
337 * @param string $archiveName
338 */
339 public function setArchiveName( $archiveName ) {
340 $this->archiveName = $archiveName;
341 }
342
343 /**
344 * @since 1.12.2
345 * @param int $size
346 */
347 public function setSize( $size ) {
348 $this->size = intval( $size );
349 }
350
351 /**
352 * @since 1.12.2
353 * @param string $type
354 */
355 public function setType( $type ) {
356 $this->type = $type;
357 }
358
359 /**
360 * @since 1.12.2
361 * @param string $action
362 */
363 public function setAction( $action ) {
364 $this->action = $action;
365 }
366
367 /**
368 * @since 1.12.2
369 * @param string $params
370 */
371 public function setParams( $params ) {
372 $this->params = $params;
373 }
374
375 /**
376 * @since 1.18
377 * @param bool $noupdates
378 */
379 public function setNoUpdates( $noupdates ) {
380 $this->mNoUpdates = $noupdates;
381 }
382
383 /**
384 * @since 1.2
385 * @return Title
386 */
387 public function getTitle() {
388 return $this->title;
389 }
390
391 /**
392 * @since 1.6.4
393 * @return int
394 */
395 public function getID() {
396 return $this->id;
397 }
398
399 /**
400 * @since 1.2
401 * @return string
402 */
403 public function getTimestamp() {
404 return $this->timestamp;
405 }
406
407 /**
408 * @since 1.2
409 * @return string
410 */
411 public function getUser() {
412 return $this->user_text;
413 }
414
415 /**
416 * @since 1.27
417 * @return User
418 */
419 public function getUserObj() {
420 return $this->userObj;
421 }
422
423 /**
424 * @since 1.2
425 * @return string
426 */
427 public function getText() {
428 return $this->text;
429 }
430
431 /**
432 * @since 1.24
433 * @return ContentHandler
434 */
435 public function getContentHandler() {
436 if ( is_null( $this->contentHandler ) ) {
437 $this->contentHandler = ContentHandler::getForModelID( $this->getModel() );
438 }
439
440 return $this->contentHandler;
441 }
442
443 /**
444 * @since 1.21
445 * @return Content
446 */
447 public function getContent() {
448 if ( is_null( $this->content ) ) {
449 $handler = $this->getContentHandler();
450 $this->content = $handler->unserializeContent( $this->text, $this->getFormat() );
451 }
452
453 return $this->content;
454 }
455
456 /**
457 * @since 1.21
458 * @return string
459 */
460 public function getModel() {
461 if ( is_null( $this->model ) ) {
462 $this->model = $this->getTitle()->getContentModel();
463 }
464
465 return $this->model;
466 }
467
468 /**
469 * @since 1.21
470 * @return string
471 */
472 public function getFormat() {
473 if ( is_null( $this->format ) ) {
474 $this->format = $this->getContentHandler()->getDefaultFormat();
475 }
476
477 return $this->format;
478 }
479
480 /**
481 * @since 1.2.6
482 * @return string
483 */
484 public function getComment() {
485 return $this->comment;
486 }
487
488 /**
489 * @since 1.5.7
490 * @return bool
491 */
492 public function getMinor() {
493 return $this->minor;
494 }
495
496 /**
497 * @since 1.12.2
498 * @return string|null
499 */
500 public function getSrc() {
501 return $this->src;
502 }
503
504 /**
505 * @since 1.17
506 * @return bool|string
507 */
508 public function getSha1() {
509 if ( $this->sha1base36 ) {
510 return Wikimedia\base_convert( $this->sha1base36, 36, 16 );
511 }
512 return false;
513 }
514
515 /**
516 * @since 1.31
517 * @return bool|string
518 */
519 public function getSha1Base36() {
520 if ( $this->sha1base36 ) {
521 return $this->sha1base36;
522 }
523 return false;
524 }
525
526 /**
527 * @since 1.34
528 * @return string[]
529 */
530 public function getTags() {
531 return $this->tags;
532 }
533
534 /**
535 * @since 1.17
536 * @return string
537 */
538 public function getFileSrc() {
539 return $this->fileSrc;
540 }
541
542 /**
543 * @since 1.17
544 * @return bool
545 */
546 public function isTempSrc() {
547 return $this->isTemp;
548 }
549
550 /**
551 * @since 1.12.2
552 * @return mixed
553 */
554 public function getFilename() {
555 return $this->filename;
556 }
557
558 /**
559 * @since 1.17
560 * @return string
561 */
562 public function getArchiveName() {
563 return $this->archiveName;
564 }
565
566 /**
567 * @since 1.12.2
568 * @return mixed
569 */
570 public function getSize() {
571 return $this->size;
572 }
573
574 /**
575 * @since 1.12.2
576 * @return string
577 */
578 public function getType() {
579 return $this->type;
580 }
581
582 /**
583 * @since 1.12.2
584 * @return string
585 */
586 public function getAction() {
587 return $this->action;
588 }
589
590 /**
591 * @since 1.12.2
592 * @return string
593 */
594 public function getParams() {
595 return $this->params;
596 }
597
598 /**
599 * @since 1.4.1
600 * @deprecated in 1.31. Use OldRevisionImporter::import
601 * @return bool
602 */
603 public function importOldRevision() {
604 if ( $this->mNoUpdates ) {
605 $importer = MediaWikiServices::getInstance()->getWikiRevisionOldRevisionImporterNoUpdates();
606 } else {
607 $importer = MediaWikiServices::getInstance()->getWikiRevisionOldRevisionImporter();
608 }
609 return $importer->import( $this );
610 }
611
612 /**
613 * @since 1.12.2
614 * @return bool
615 */
616 public function importLogItem() {
617 $dbw = wfGetDB( DB_MASTER );
618
619 $user = $this->getUserObj() ?: User::newFromName( $this->getUser(), false );
620
621 # @todo FIXME: This will not record autoblocks
622 if ( !$this->getTitle() ) {
623 wfDebug( __METHOD__ . ": skipping invalid {$this->type}/{$this->action} log time, timestamp " .
624 $this->timestamp . "\n" );
625 return false;
626 }
627 # Check if it exists already
628 // @todo FIXME: Use original log ID (better for backups)
629 $prior = $dbw->selectField( 'logging', '1',
630 [ 'log_type' => $this->getType(),
631 'log_action' => $this->getAction(),
632 'log_timestamp' => $dbw->timestamp( $this->timestamp ),
633 'log_namespace' => $this->getTitle()->getNamespace(),
634 'log_title' => $this->getTitle()->getDBkey(),
635 'log_params' => $this->params ],
636 __METHOD__
637 );
638 // @todo FIXME: This could fail slightly for multiple matches :P
639 if ( $prior ) {
640 wfDebug( __METHOD__
641 . ": skipping existing item for Log:{$this->type}/{$this->action}, timestamp "
642 . $this->timestamp . "\n" );
643 return false;
644 }
645 $data = [
646 'log_type' => $this->type,
647 'log_action' => $this->action,
648 'log_timestamp' => $dbw->timestamp( $this->timestamp ),
649 'log_namespace' => $this->getTitle()->getNamespace(),
650 'log_title' => $this->getTitle()->getDBkey(),
651 'log_params' => $this->params
652 ] + CommentStore::getStore()->insert( $dbw, 'log_comment', $this->getComment() )
653 + ActorMigration::newMigration()->getInsertValues( $dbw, 'log_user', $user );
654 $dbw->insert( 'logging', $data, __METHOD__ );
655
656 return true;
657 }
658
659 /**
660 * @since 1.12.2
661 * @deprecated in 1.31. Use UploadRevisionImporter::import
662 * @return bool
663 */
664 public function importUpload() {
665 $importer = MediaWikiServices::getInstance()->getWikiRevisionUploadImporter();
666 $statusValue = $importer->import( $this );
667 return $statusValue->isGood();
668 }
669
670 /**
671 * @since 1.12.2
672 * @deprecated in 1.31. No replacement
673 * @return bool|string
674 */
675 public function downloadSource() {
676 $importer = new ImportableUploadRevisionImporter(
677 $this->config->get( 'EnableUploads' ),
678 LoggerFactory::getInstance( 'UploadRevisionImporter' )
679 );
680 return $importer->downloadSource( $this );
681 }
682
683 }