125 $permissionManager = $services->getPermissionManager();
137 $this->
output(
"Importing Files\n\n" );
139 $dir = $this->
getArg( 0 );
143 $this->
fatalError(
"Cannot specify both protect and unprotect. Only 1 is allowed.\n" );
147 $this->
fatalError(
"You must specify a protection option.\n" );
150 # Prepare the list of allowed extensions
151 $extensions = $this->
hasOption(
'extensions' )
152 ? explode(
',', strtolower( $this->
getOption(
'extensions' ) ) )
153 : $this->
getConfig()->get( MainConfigNames::FileExtensions );
155 # Search the path provided for candidates for import
156 $files = $this->findFiles( $dir, $extensions, $this->
hasOption(
'search-recursively' ) );
157 if ( !$files->valid() ) {
158 $this->
output(
"No suitable files could be found for import.\n" );
162 # Initialise the user for this operation
164 ? User::newFromName( $this->
getOption(
'user' ) )
165 : User::newSystemUser( User::MAINTENANCE_SCRIPT_USER, [
'steal' =>
true ] );
166 if ( !$user instanceof
User ) {
167 $user = User::newSystemUser( User::MAINTENANCE_SCRIPT_USER, [
'steal' =>
true ] );
169 '@phan-var User $user';
170 StubGlobalUser::setUser( $user );
172 # Get block check. If a value is given, this specified how often the check is performed
173 $checkUserBlock = (int)$this->
getOption(
'check-userblock' );
176 $sleep = (int)$this->
getOption(
'sleep' );
177 $limit = (int)$this->
getOption(
'limit' );
178 $timestamp = $this->
getOption(
'timestamp',
false );
180 # Get the upload comment. Provide a default one in case there's no comment given.
181 $commentFile = $this->
getOption(
'comment-file' );
182 if ( $commentFile !==
null ) {
183 $comment = file_get_contents( $commentFile );
184 if ( $comment ===
false || $comment ===
null ) {
185 $this->
fatalError(
"failed to read comment file: {$commentFile}\n" );
188 $comment = $this->
getOption(
'comment',
'Importing file' );
190 $commentExt = $this->
getOption(
'comment-ext' );
191 $summary = $this->
getOption(
'summary',
'' );
192 $license = $this->
getOption(
'license',
'' );
193 $sourceWikiUrl = $this->
getOption(
'source-wiki-url' );
196 ChangeTags::TAG_SERVER_SIDE_UPLOAD,
199 ? [ ChangeTags::TAG_SERVER_SIDE_UPLOAD ]
202 # Batch "upload" operation
203 $restrictionStore = $services->getRestrictionStore();
204 foreach ( $files as $file ) {
206 if ( $sleep && ( $processed > 0 ) ) {
210 $base = UtfNormal\Validator::cleanUp(
wfBaseName( $file ) );
213 $title = Title::makeTitleSafe(
NS_FILE, $base );
216 "{$base} could not be imported; a valid title cannot be produced\n"
222 if ( $from !== $title->getDBkey() ) {
223 $statistics[
'ignored']++;
230 if ( $checkUserBlock && ( ( $processed % $checkUserBlock ) == 0 ) ) {
231 $user->clearInstanceCache(
'name' );
232 if ( $permissionManager->isBlockedFrom( $user, $title ) ) {
234 "{$user->getName()} is blocked from {$title->getPrefixedText()}! skipping.\n"
236 $statistics[
'skipped']++;
242 $image = $services->getRepoGroup()->getLocalRepo()
244 if ( $image->exists() ) {
246 $this->
output(
"{$base} exists, overwriting..." );
247 $svar =
'overwritten';
249 $this->
output(
"{$base} exists, skipping\n" );
250 $statistics[
'skipped']++;
254 if ( $this->
hasOption(
'skip-dupes' ) ) {
255 $repo = $image->getRepo();
256 # XXX: we end up calculating this again when actually uploading. that sucks.
257 $sha1 = FSFile::getSha1Base36FromPath( $file );
258 $dupes = $repo->findBySha1( $sha1 );
261 "{$base} already exists as {$dupes[0]->getName()}, skipping\n"
263 $statistics[
'skipped']++;
268 $this->
output(
"Importing {$base}..." );
272 if ( $sourceWikiUrl ) {
274 $real_comment = $this->getFileCommentFromSourceWiki( $sourceWikiUrl, $base );
275 $commentText = $real_comment !==
false ? $real_comment : $comment;
278 $real_user = $this->getFileUserFromSourceWiki( $sourceWikiUrl, $base );
279 if ( $real_user !==
false ) {
280 $realUser = User::newFromName( $real_user );
281 if ( $realUser ===
false ) {
282 # user does not exist in target wiki
284 "failed: user '$real_user' does not exist in target wiki."
288 StubGlobalUser::setUser( $realUser );
293 $commentText =
false;
296 $f = $this->findAuxFile( $file, $commentExt );
298 $this->
output(
" No comment file with extension {$commentExt} found "
299 .
"for {$file}, using default comment." );
301 $commentText = file_get_contents( $f );
302 if ( !$commentText ) {
304 " Failed to load comment file {$f}, using default comment."
310 if ( !$commentText ) {
311 $commentText = $comment;
318 " publishing {$file} by '{$user->getName()}', comment '$commentText'..."
321 $mwProps =
new MWFileProps( $services->getMimeAnalyzer() );
322 $props = $mwProps->getPropsFromPath( $file,
true );
324 $publishOptions = [];
325 $handler = MediaHandler::getHandler( $props[
'mime'] );
327 $publishOptions[
'headers'] = $handler->getContentHeaders( $props[
'metadata'] );
329 $publishOptions[
'headers'] = [];
331 $archive = $image->publish( $file, $flags, $publishOptions );
332 if ( !$archive->isGood() ) {
333 $this->
output(
"failed. (" .
334 $archive->getMessage(
false,
false,
'en' )->text() .
336 $statistics[
'failed']++;
341 $commentText = SpecialUpload::getInitialPageText( $commentText, $license );
343 $summary = $commentText;
347 $this->
output(
"done.\n" );
349 $uploadStatus = $image->recordUpload3(
361 if ( $uploadStatus->isOK() ) {
362 $this->
output(
"done.\n" );
366 $protectLevel = $this->
getOption(
'protect' );
367 $restrictionLevels = $this->
getConfig()->get( MainConfigNames::RestrictionLevels );
369 if ( $protectLevel && in_array( $protectLevel, $restrictionLevels ) ) {
379 $this->
output(
"\nWaiting for replica DBs...\n" );
381 sleep( 2 ); # Why
this sleep?
384 $this->
output(
"\nSetting image restrictions ..." );
388 foreach ( $restrictionStore->listApplicableRestrictionTypes( $title ) as $type ) {
389 $restrictions[$type] = $protectLevel;
392 $page = $services->getWikiPageFactory()->newFromTitle( $title );
393 $status = $page->doUpdateRestrictions( $restrictions, [], $cascade,
'', $user );
394 $this->
output( ( $status->isOK() ?
'done' :
'failed' ) .
"\n" );
396 } elseif ( $uploadStatus->hasMessage(
'fileexists-no-change' ) ) {
397 $this->
output(
"skipped. (fileexists-no-change)\n" );
400 $errors = $uploadStatus->getMessages(
'error' );
401 $firstErrorKey = ( $errors !== [] ) ? $errors[0]->getKey() :
'unknown error at recordUpload';
402 $this->
output(
"failed. ($firstErrorKey)\n" );
407 $statistics[$svar]++;
410 if ( $limit && $processed >= $limit ) {
415 # Print out some statistics
417 foreach ( array_merge(
423 ) as $desc => $number ) {
425 $this->
output( ucfirst( $desc ) .
": $number\n" );
431 return $statistics[
'failed'] === 0;