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