Merge "Remove parameter 'options' from hook 'SkinEditSectionLinks'"
[lhc/web/wiklou.git] / includes / import / ImportableUploadRevisionImporter.php
1 <?php
2
3 use MediaWiki\MediaWikiServices;
4 use Psr\Log\LoggerInterface;
5
6 /**
7 * @since 1.31
8 */
9 class ImportableUploadRevisionImporter implements UploadRevisionImporter {
10
11 /**
12 * @var LoggerInterface
13 */
14 private $logger;
15
16 /**
17 * @var bool
18 */
19 private $enableUploads;
20
21 /**
22 * @var bool
23 */
24 private $shouldCreateNullRevision = true;
25
26 /**
27 * @param bool $enableUploads
28 * @param LoggerInterface $logger
29 */
30 public function __construct(
31 $enableUploads,
32 LoggerInterface $logger
33 ) {
34 $this->enableUploads = $enableUploads;
35 $this->logger = $logger;
36 }
37
38 /**
39 * Setting this to false will deactivate the creation of a null revision as part of the upload
40 * process logging in LocalFile::recordUpload2, see T193621
41 *
42 * @param bool $shouldCreateNullRevision
43 */
44 public function setNullRevisionCreation( $shouldCreateNullRevision ) {
45 $this->shouldCreateNullRevision = $shouldCreateNullRevision;
46 }
47
48 /**
49 * @return StatusValue
50 */
51 private function newNotOkStatus() {
52 $statusValue = new StatusValue();
53 $statusValue->setOK( false );
54 return $statusValue;
55 }
56
57 public function import( ImportableUploadRevision $importableRevision ) {
58 # Construct a file
59 $archiveName = $importableRevision->getArchiveName();
60 if ( $archiveName ) {
61 $this->logger->debug( __METHOD__ . "Importing archived file as $archiveName\n" );
62 $file = OldLocalFile::newFromArchiveName( $importableRevision->getTitle(),
63 RepoGroup::singleton()->getLocalRepo(), $archiveName );
64 } else {
65 $file = wfLocalFile( $importableRevision->getTitle() );
66 $file->load( File::READ_LATEST );
67 $this->logger->debug( __METHOD__ . 'Importing new file as ' . $file->getName() . "\n" );
68 if ( $file->exists() && $file->getTimestamp() > $importableRevision->getTimestamp() ) {
69 $archiveName = $importableRevision->getTimestamp() . '!' . $file->getName();
70 $file = OldLocalFile::newFromArchiveName( $importableRevision->getTitle(),
71 RepoGroup::singleton()->getLocalRepo(), $archiveName );
72 $this->logger->debug( __METHOD__ . "File already exists; importing as $archiveName\n" );
73 }
74 }
75 if ( !$file ) {
76 $this->logger->debug( __METHOD__ . ': Bad file for ' . $importableRevision->getTitle() . "\n" );
77 return $this->newNotOkStatus();
78 }
79
80 # Get the file source or download if necessary
81 $source = $importableRevision->getFileSrc();
82 $autoDeleteSource = $importableRevision->isTempSrc();
83 if ( !strlen( $source ) ) {
84 $source = $this->downloadSource( $importableRevision );
85 $autoDeleteSource = true;
86 }
87 if ( !strlen( $source ) ) {
88 $this->logger->debug( __METHOD__ . ": Could not fetch remote file.\n" );
89 return $this->newNotOkStatus();
90 }
91
92 $tmpFile = new TempFSFile( $source );
93 if ( $autoDeleteSource ) {
94 $tmpFile->autocollect();
95 }
96
97 $sha1File = ltrim( sha1_file( $source ), '0' );
98 $sha1 = $importableRevision->getSha1();
99 if ( $sha1 && ( $sha1 !== $sha1File ) ) {
100 $this->logger->debug( __METHOD__ . ": Corrupt file $source.\n" );
101 return $this->newNotOkStatus();
102 }
103
104 $user = $importableRevision->getUserObj()
105 ?: User::newFromName( $importableRevision->getUser(), false );
106
107 # Do the actual upload
108 if ( $file instanceof OldLocalFile ) {
109 $status = $file->uploadOld(
110 $source,
111 $importableRevision->getTimestamp(),
112 $importableRevision->getComment(),
113 $user
114 );
115 } else {
116 $flags = 0;
117 $status = $file->upload(
118 $source,
119 $importableRevision->getComment(),
120 $importableRevision->getComment(),
121 $flags,
122 false,
123 $importableRevision->getTimestamp(),
124 $user,
125 [],
126 $this->shouldCreateNullRevision
127 );
128 }
129
130 if ( $status->isGood() ) {
131 $this->logger->debug( __METHOD__ . ": Successful\n" );
132 } else {
133 $this->logger->debug( __METHOD__ . ': failed: ' . $status->getHTML() . "\n" );
134 }
135
136 return $status;
137 }
138
139 /**
140 * @deprecated DO NOT CALL ME.
141 * This method was introduced when factoring UploadImporter out of WikiRevision.
142 * It only has 1 use by the deprecated downloadSource method in WikiRevision.
143 * Do not use this in new code.
144 *
145 * @param ImportableUploadRevision $wikiRevision
146 *
147 * @return bool|string
148 */
149 public function downloadSource( ImportableUploadRevision $wikiRevision ) {
150 if ( !$this->enableUploads ) {
151 return false;
152 }
153
154 $tempo = tempnam( wfTempDir(), 'download' );
155 $f = fopen( $tempo, 'wb' );
156 if ( !$f ) {
157 $this->logger->debug( "IMPORT: couldn't write to temp file $tempo\n" );
158 return false;
159 }
160
161 // @todo FIXME!
162 $src = $wikiRevision->getSrc();
163 $data = MediaWikiServices::getInstance()->getHttpRequestFactory()->
164 get( $src, [], __METHOD__ );
165 if ( !$data ) {
166 $this->logger->debug( "IMPORT: couldn't fetch source $src\n" );
167 fclose( $f );
168 unlink( $tempo );
169 return false;
170 }
171
172 fwrite( $f, $data );
173 fclose( $f );
174
175 return $tempo;
176 }
177
178 }