Merge "Add .pipeline/ with dev image variant"
[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 /**
189 * @deprecated since 1.31, along with self::downloadSource()
190 * @var Config $config
191 */
192 private $config;
193
194 /**
195 * @param Config $config Deprecated since 1.31, along with self::downloadSource(). Just pass an
196 * empty HashConfig.
197 */
198 public function __construct( Config $config ) {
199 $this->config = $config;
200 }
201
202 /**
203 * @since 1.7 taking a Title object (string before)
204 * @param Title $title
205 * @throws MWException
206 */
207 public function setTitle( $title ) {
208 if ( is_object( $title ) ) {
209 $this->title = $title;
210 } elseif ( is_null( $title ) ) {
211 throw new MWException( "WikiRevision given a null title in import. "
212 . "You may need to adjust \$wgLegalTitleChars." );
213 } else {
214 throw new MWException( "WikiRevision given non-object title in import." );
215 }
216 }
217
218 /**
219 * @since 1.6.4
220 * @param int $id
221 */
222 public function setID( $id ) {
223 $this->id = $id;
224 }
225
226 /**
227 * @since 1.2
228 * @param string $ts
229 */
230 public function setTimestamp( $ts ) {
231 # 2003-08-05T18:30:02Z
232 $this->timestamp = wfTimestamp( TS_MW, $ts );
233 }
234
235 /**
236 * @since 1.2
237 * @param string $user
238 */
239 public function setUsername( $user ) {
240 $this->user_text = $user;
241 }
242
243 /**
244 * @since 1.27
245 * @param User $user
246 */
247 public function setUserObj( $user ) {
248 $this->userObj = $user;
249 }
250
251 /**
252 * @since 1.2
253 * @param string $ip
254 */
255 public function setUserIP( $ip ) {
256 $this->user_text = $ip;
257 }
258
259 /**
260 * @since 1.21
261 * @param string $model
262 */
263 public function setModel( $model ) {
264 $this->model = $model;
265 }
266
267 /**
268 * @since 1.21
269 * @param string $format
270 */
271 public function setFormat( $format ) {
272 $this->format = $format;
273 }
274
275 /**
276 * @since 1.2
277 * @param string $text
278 */
279 public function setText( $text ) {
280 $this->text = $text;
281 }
282
283 /**
284 * @since 1.2.6
285 * @param string $text
286 */
287 public function setComment( $text ) {
288 $this->comment = $text;
289 }
290
291 /**
292 * @since 1.5.7
293 * @param bool $minor
294 */
295 public function setMinor( $minor ) {
296 $this->minor = (bool)$minor;
297 }
298
299 /**
300 * @since 1.12.2
301 * @param string|null $src
302 */
303 public function setSrc( $src ) {
304 $this->src = $src;
305 }
306
307 /**
308 * @since 1.17
309 * @param string $src
310 * @param bool $isTemp
311 */
312 public function setFileSrc( $src, $isTemp ) {
313 $this->fileSrc = $src;
314 $this->fileIsTemp = $isTemp;
315 $this->isTemp = $isTemp;
316 }
317
318 /**
319 * @since 1.17
320 * @param string $sha1base36
321 */
322 public function setSha1Base36( $sha1base36 ) {
323 $this->sha1base36 = $sha1base36;
324 }
325
326 /**
327 * @since 1.34
328 * @param string[] $tags
329 */
330 public function setTags( array $tags ) {
331 $this->tags = $tags;
332 }
333
334 /**
335 * @since 1.12.2
336 * @param string $filename
337 */
338 public function setFilename( $filename ) {
339 $this->filename = $filename;
340 }
341
342 /**
343 * @since 1.17
344 * @param string $archiveName
345 */
346 public function setArchiveName( $archiveName ) {
347 $this->archiveName = $archiveName;
348 }
349
350 /**
351 * @since 1.12.2
352 * @param int $size
353 */
354 public function setSize( $size ) {
355 $this->size = intval( $size );
356 }
357
358 /**
359 * @since 1.12.2
360 * @param string $type
361 */
362 public function setType( $type ) {
363 $this->type = $type;
364 }
365
366 /**
367 * @since 1.12.2
368 * @param string $action
369 */
370 public function setAction( $action ) {
371 $this->action = $action;
372 }
373
374 /**
375 * @since 1.12.2
376 * @param string $params
377 */
378 public function setParams( $params ) {
379 $this->params = $params;
380 }
381
382 /**
383 * @since 1.18
384 * @param bool $noupdates
385 */
386 public function setNoUpdates( $noupdates ) {
387 $this->mNoUpdates = $noupdates;
388 }
389
390 /**
391 * @since 1.2
392 * @return Title
393 */
394 public function getTitle() {
395 return $this->title;
396 }
397
398 /**
399 * @since 1.6.4
400 * @return int
401 */
402 public function getID() {
403 return $this->id;
404 }
405
406 /**
407 * @since 1.2
408 * @return string
409 */
410 public function getTimestamp() {
411 return $this->timestamp;
412 }
413
414 /**
415 * @since 1.2
416 * @return string
417 */
418 public function getUser() {
419 return $this->user_text;
420 }
421
422 /**
423 * @since 1.27
424 * @return User
425 */
426 public function getUserObj() {
427 return $this->userObj;
428 }
429
430 /**
431 * @since 1.2
432 * @return string
433 */
434 public function getText() {
435 return $this->text;
436 }
437
438 /**
439 * @since 1.24
440 * @return ContentHandler
441 */
442 public function getContentHandler() {
443 if ( is_null( $this->contentHandler ) ) {
444 $this->contentHandler = ContentHandler::getForModelID( $this->getModel() );
445 }
446
447 return $this->contentHandler;
448 }
449
450 /**
451 * @since 1.21
452 * @return Content
453 */
454 public function getContent() {
455 if ( is_null( $this->content ) ) {
456 $handler = $this->getContentHandler();
457 $this->content = $handler->unserializeContent( $this->text, $this->getFormat() );
458 }
459
460 return $this->content;
461 }
462
463 /**
464 * @since 1.21
465 * @return string
466 */
467 public function getModel() {
468 if ( is_null( $this->model ) ) {
469 $this->model = $this->getTitle()->getContentModel();
470 }
471
472 return $this->model;
473 }
474
475 /**
476 * @since 1.21
477 * @return string
478 */
479 public function getFormat() {
480 if ( is_null( $this->format ) ) {
481 $this->format = $this->getContentHandler()->getDefaultFormat();
482 }
483
484 return $this->format;
485 }
486
487 /**
488 * @since 1.2.6
489 * @return string
490 */
491 public function getComment() {
492 return $this->comment;
493 }
494
495 /**
496 * @since 1.5.7
497 * @return bool
498 */
499 public function getMinor() {
500 return $this->minor;
501 }
502
503 /**
504 * @since 1.12.2
505 * @return string|null
506 */
507 public function getSrc() {
508 return $this->src;
509 }
510
511 /**
512 * @since 1.17
513 * @return bool|string
514 */
515 public function getSha1() {
516 if ( $this->sha1base36 ) {
517 return Wikimedia\base_convert( $this->sha1base36, 36, 16 );
518 }
519 return false;
520 }
521
522 /**
523 * @since 1.31
524 * @return bool|string
525 */
526 public function getSha1Base36() {
527 if ( $this->sha1base36 ) {
528 return $this->sha1base36;
529 }
530 return false;
531 }
532
533 /**
534 * @since 1.34
535 * @return string[]
536 */
537 public function getTags() {
538 return $this->tags;
539 }
540
541 /**
542 * @since 1.17
543 * @return string
544 */
545 public function getFileSrc() {
546 return $this->fileSrc;
547 }
548
549 /**
550 * @since 1.17
551 * @return bool
552 */
553 public function isTempSrc() {
554 return $this->isTemp;
555 }
556
557 /**
558 * @since 1.12.2
559 * @return mixed
560 */
561 public function getFilename() {
562 return $this->filename;
563 }
564
565 /**
566 * @since 1.17
567 * @return string
568 */
569 public function getArchiveName() {
570 return $this->archiveName;
571 }
572
573 /**
574 * @since 1.12.2
575 * @return mixed
576 */
577 public function getSize() {
578 return $this->size;
579 }
580
581 /**
582 * @since 1.12.2
583 * @return string
584 */
585 public function getType() {
586 return $this->type;
587 }
588
589 /**
590 * @since 1.12.2
591 * @return string
592 */
593 public function getAction() {
594 return $this->action;
595 }
596
597 /**
598 * @since 1.12.2
599 * @return string
600 */
601 public function getParams() {
602 return $this->params;
603 }
604
605 /**
606 * @since 1.4.1
607 * @deprecated in 1.31. Use OldRevisionImporter::import
608 * @return bool
609 */
610 public function importOldRevision() {
611 if ( $this->mNoUpdates ) {
612 $importer = MediaWikiServices::getInstance()->getWikiRevisionOldRevisionImporterNoUpdates();
613 } else {
614 $importer = MediaWikiServices::getInstance()->getWikiRevisionOldRevisionImporter();
615 }
616 return $importer->import( $this );
617 }
618
619 /**
620 * @since 1.12.2
621 * @return bool
622 */
623 public function importLogItem() {
624 $dbw = wfGetDB( DB_MASTER );
625
626 $user = $this->getUserObj() ?: User::newFromName( $this->getUser(), false );
627
628 # @todo FIXME: This will not record autoblocks
629 if ( !$this->getTitle() ) {
630 wfDebug( __METHOD__ . ": skipping invalid {$this->type}/{$this->action} log time, timestamp " .
631 $this->timestamp . "\n" );
632 return false;
633 }
634 # Check if it exists already
635 // @todo FIXME: Use original log ID (better for backups)
636 $prior = $dbw->selectField( 'logging', '1',
637 [ 'log_type' => $this->getType(),
638 'log_action' => $this->getAction(),
639 'log_timestamp' => $dbw->timestamp( $this->timestamp ),
640 'log_namespace' => $this->getTitle()->getNamespace(),
641 'log_title' => $this->getTitle()->getDBkey(),
642 'log_params' => $this->params ],
643 __METHOD__
644 );
645 // @todo FIXME: This could fail slightly for multiple matches :P
646 if ( $prior ) {
647 wfDebug( __METHOD__
648 . ": skipping existing item for Log:{$this->type}/{$this->action}, timestamp "
649 . $this->timestamp . "\n" );
650 return false;
651 }
652 $data = [
653 'log_type' => $this->type,
654 'log_action' => $this->action,
655 'log_timestamp' => $dbw->timestamp( $this->timestamp ),
656 'log_namespace' => $this->getTitle()->getNamespace(),
657 'log_title' => $this->getTitle()->getDBkey(),
658 'log_params' => $this->params
659 ] + CommentStore::getStore()->insert( $dbw, 'log_comment', $this->getComment() )
660 + ActorMigration::newMigration()->getInsertValues( $dbw, 'log_user', $user );
661 $dbw->insert( 'logging', $data, __METHOD__ );
662
663 return true;
664 }
665
666 /**
667 * @since 1.12.2
668 * @deprecated in 1.31. Use UploadRevisionImporter::import
669 * @return bool
670 */
671 public function importUpload() {
672 $importer = MediaWikiServices::getInstance()->getWikiRevisionUploadImporter();
673 $statusValue = $importer->import( $this );
674 return $statusValue->isGood();
675 }
676
677 /**
678 * @since 1.12.2
679 * @deprecated in 1.31. No replacement
680 * @return bool|string
681 */
682 public function downloadSource() {
683 $importer = new ImportableUploadRevisionImporter(
684 $this->config->get( 'EnableUploads' ),
685 LoggerFactory::getInstance( 'UploadRevisionImporter' )
686 );
687 return $importer->downloadSource( $this );
688 }
689
690 }