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