MediaWiki  REL1_24
importImages.php
Go to the documentation of this file.
00001 <?php
00035 $optionsWithArgs = array(
00036     'extensions', 'comment', 'comment-file', 'comment-ext', 'summary', 'user',
00037     'license', 'sleep', 'limit', 'from', 'source-wiki-url', 'timestamp',
00038 );
00039 require_once __DIR__ . '/commandLine.inc';
00040 require_once __DIR__ . '/importImages.inc';
00041 $processed = $added = $ignored = $skipped = $overwritten = $failed = 0;
00042 
00043 echo "Import Images\n\n";
00044 
00045 # Need a path
00046 if ( count( $args ) == 0 ) {
00047     showUsage();
00048 }
00049 
00050 $dir = $args[0];
00051 
00052 # Check Protection
00053 if ( isset( $options['protect'] ) && isset( $options['unprotect'] ) ) {
00054     die( "Cannot specify both protect and unprotect.  Only 1 is allowed.\n" );
00055 }
00056 
00057 if ( isset( $options['protect'] ) && $options['protect'] == 1 ) {
00058     die( "You must specify a protection option.\n" );
00059 }
00060 
00061 # Prepare the list of allowed extensions
00062 global $wgFileExtensions;
00063 $extensions = isset( $options['extensions'] )
00064     ? explode( ',', strtolower( $options['extensions'] ) )
00065     : $wgFileExtensions;
00066 
00067 # Search the path provided for candidates for import
00068 $files = findFiles( $dir, $extensions, isset( $options['search-recursively'] ) );
00069 
00070 # Initialise the user for this operation
00071 $user = isset( $options['user'] )
00072     ? User::newFromName( $options['user'] )
00073     : User::newFromName( 'Maintenance script' );
00074 if ( !$user instanceof User ) {
00075     $user = User::newFromName( 'Maintenance script' );
00076 }
00077 $wgUser = $user;
00078 
00079 # Get block check. If a value is given, this specified how often the check is performed
00080 if ( isset( $options['check-userblock'] ) ) {
00081     if ( !$options['check-userblock'] ) {
00082         $checkUserBlock = 1;
00083     } else {
00084         $checkUserBlock = (int)$options['check-userblock'];
00085     }
00086 } else {
00087     $checkUserBlock = false;
00088 }
00089 
00090 # Get --from
00091 wfSuppressWarnings();
00092 $from = $options['from'];
00093 wfRestoreWarnings();
00094 
00095 # Get sleep time.
00096 wfSuppressWarnings();
00097 $sleep = $options['sleep'];
00098 wfRestoreWarnings();
00099 
00100 if ( $sleep ) {
00101     $sleep = (int)$sleep;
00102 }
00103 
00104 # Get limit number
00105 wfSuppressWarnings();
00106 $limit = $options['limit'];
00107 wfRestoreWarnings();
00108 
00109 if ( $limit ) {
00110     $limit = (int)$limit;
00111 }
00112 
00113 $timestamp = isset( $options['timestamp'] ) ? $options['timestamp'] : false;
00114 
00115 # Get the upload comment. Provide a default one in case there's no comment given.
00116 $comment = 'Importing file';
00117 
00118 if ( isset( $options['comment-file'] ) ) {
00119     $comment = file_get_contents( $options['comment-file'] );
00120     if ( $comment === false || $comment === null ) {
00121         die( "failed to read comment file: {$options['comment-file']}\n" );
00122     }
00123 } elseif ( isset( $options['comment'] ) ) {
00124     $comment = $options['comment'];
00125 }
00126 
00127 $commentExt = isset( $options['comment-ext'] ) ? $options['comment-ext'] : false;
00128 
00129 $summary = isset( $options['summary'] ) ? $options['summary'] : '';
00130 
00131 # Get the license specifier
00132 $license = isset( $options['license'] ) ? $options['license'] : '';
00133 
00134 # Batch "upload" operation
00135 $count = count( $files );
00136 if ( $count > 0 ) {
00137 
00138     foreach ( $files as $file ) {
00139         $base = wfBaseName( $file );
00140 
00141         # Validate a title
00142         $title = Title::makeTitleSafe( NS_FILE, $base );
00143         if ( !is_object( $title ) ) {
00144             echo "{$base} could not be imported; a valid title cannot be produced\n";
00145             continue;
00146         }
00147 
00148         if ( $from ) {
00149             if ( $from == $title->getDBkey() ) {
00150                 $from = null;
00151             } else {
00152                 $ignored++;
00153                 continue;
00154             }
00155         }
00156 
00157         if ( $checkUserBlock && ( ( $processed % $checkUserBlock ) == 0 ) ) {
00158             $user->clearInstanceCache( 'name' ); // reload from DB!
00159             if ( $user->isBlocked() ) {
00160                 echo $user->getName() . " was blocked! Aborting.\n";
00161                 break;
00162             }
00163         }
00164 
00165         # Check existence
00166         $image = wfLocalFile( $title );
00167         if ( $image->exists() ) {
00168             if ( isset( $options['overwrite'] ) ) {
00169                 echo "{$base} exists, overwriting...";
00170                 $svar = 'overwritten';
00171             } else {
00172                 echo "{$base} exists, skipping\n";
00173                 $skipped++;
00174                 continue;
00175             }
00176         } else {
00177             if ( isset( $options['skip-dupes'] ) ) {
00178                 $repo = $image->getRepo();
00179                 # XXX: we end up calculating this again when actually uploading. that sucks.
00180                 $sha1 = FSFile::getSha1Base36FromPath( $file );
00181 
00182                 $dupes = $repo->findBySha1( $sha1 );
00183 
00184                 if ( $dupes ) {
00185                     echo "{$base} already exists as " . $dupes[0]->getName() . ", skipping\n";
00186                     $skipped++;
00187                     continue;
00188                 }
00189             }
00190 
00191             echo "Importing {$base}...";
00192             $svar = 'added';
00193         }
00194 
00195         if ( isset( $options['source-wiki-url'] ) ) {
00196             /* find comment text directly from source wiki, through MW's API */
00197             $real_comment = getFileCommentFromSourceWiki( $options['source-wiki-url'], $base );
00198             if ( $real_comment === false ) {
00199                 $commentText = $comment;
00200             } else {
00201                 $commentText = $real_comment;
00202             }
00203 
00204             /* find user directly from source wiki, through MW's API */
00205             $real_user = getFileUserFromSourceWiki( $options['source-wiki-url'], $base );
00206             if ( $real_user === false ) {
00207                 $wgUser = $user;
00208             } else {
00209                 $wgUser = User::newFromName( $real_user );
00210                 if ( $wgUser === false ) {
00211                     # user does not exist in target wiki
00212                     echo "failed: user '$real_user' does not exist in target wiki.";
00213                     continue;
00214                 }
00215             }
00216         } else {
00217             # Find comment text
00218             $commentText = false;
00219 
00220             if ( $commentExt ) {
00221                 $f = findAuxFile( $file, $commentExt );
00222                 if ( !$f ) {
00223                     echo " No comment file with extension {$commentExt} found "
00224                         . "for {$file}, using default comment. ";
00225                 } else {
00226                     $commentText = file_get_contents( $f );
00227                     if ( !$commentText ) {
00228                         echo " Failed to load comment file {$f}, using default comment. ";
00229                     }
00230                 }
00231             }
00232 
00233             if ( !$commentText ) {
00234                 $commentText = $comment;
00235             }
00236         }
00237 
00238         # Import the file
00239         if ( isset( $options['dry'] ) ) {
00240             echo " publishing {$file} by '" . $wgUser->getName() . "', comment '$commentText'... ";
00241         } else {
00242             $props = FSFile::getPropsFromPath( $file );
00243             $flags = 0;
00244             $publishOptions = array();
00245             $handler = MediaHandler::getHandler( $props['mime'] );
00246             if ( $handler ) {
00247                 $publishOptions['headers'] = $handler->getStreamHeaders( $props['metadata'] );
00248             } else {
00249                 $publishOptions['headers'] = array();
00250             }
00251             $archive = $image->publish( $file, $flags, $publishOptions );
00252             if ( !$archive->isGood() ) {
00253                 echo "failed. (" .
00254                     $archive->getWikiText() .
00255                     ")\n";
00256                 $failed++;
00257                 continue;
00258             }
00259         }
00260 
00261         $commentText = SpecialUpload::getInitialPageText( $commentText, $license );
00262         if ( !isset( $options['summary'] ) ) {
00263             $summary = $commentText;
00264         }
00265 
00266         if ( isset( $options['dry'] ) ) {
00267             echo "done.\n";
00268         } elseif ( $image->recordUpload2(
00269             $archive->value,
00270             $summary,
00271             $commentText,
00272             $props,
00273             $timestamp
00274         ) ) {
00275             # We're done!
00276             echo "done.\n";
00277 
00278             $doProtect = false;
00279 
00280             global $wgRestrictionLevels;
00281 
00282             $protectLevel = isset( $options['protect'] ) ? $options['protect'] : null;
00283 
00284             if ( $protectLevel && in_array( $protectLevel, $wgRestrictionLevels ) ) {
00285                 $doProtect = true;
00286             }
00287             if ( isset( $options['unprotect'] ) ) {
00288                 $protectLevel = '';
00289                 $doProtect = true;
00290             }
00291 
00292             if ( $doProtect ) {
00293                 # Protect the file
00294                 echo "\nWaiting for slaves...\n";
00295                 // Wait for slaves.
00296                 sleep( 2.0 ); # Why this sleep?
00297                 wfWaitForSlaves();
00298 
00299                 echo "\nSetting image restrictions ... ";
00300 
00301                 $cascade = false;
00302                 $restrictions = array();
00303                 foreach ( $title->getRestrictionTypes() as $type ) {
00304                     $restrictions[$type] = $protectLevel;
00305                 }
00306 
00307                 $page = WikiPage::factory( $title );
00308                 $status = $page->doUpdateRestrictions( $restrictions, array(), $cascade, '', $user );
00309                 echo ( $status->isOK() ? 'done' : 'failed' ) . "\n";
00310             }
00311         } else {
00312             echo "failed. (at recordUpload stage)\n";
00313             $svar = 'failed';
00314         }
00315 
00316         $$svar++;
00317         $processed++;
00318 
00319         if ( $limit && $processed >= $limit ) {
00320             break;
00321         }
00322 
00323         if ( $sleep ) {
00324             sleep( $sleep );
00325         }
00326     }
00327 
00328     # Print out some statistics
00329     echo "\n";
00330     foreach (
00331         array(
00332             'count' => 'Found',
00333             'limit' => 'Limit',
00334             'ignored' => 'Ignored',
00335             'added' => 'Added',
00336             'skipped' => 'Skipped',
00337             'overwritten' => 'Overwritten',
00338             'failed' => 'Failed'
00339         ) as $var => $desc
00340     ) {
00341         if ( $$var > 0 ) {
00342             echo "{$desc}: {$$var}\n";
00343         }
00344     }
00345 } else {
00346     echo "No suitable files could be found for import.\n";
00347 }
00348 
00349 exit( 0 );
00350 
00351 function showUsage( $reason = false ) {
00352     if ( $reason ) {
00353         echo $reason . "\n";
00354     }
00355 
00356     echo <<<TEXT
00357 Imports images and other media files into the wiki
00358 USAGE: php importImages.php [options] <dir>
00359 
00360 <dir> : Path to the directory containing images to be imported
00361 
00362 Options:
00363 --extensions=<exts>     Comma-separated list of allowable extensions, defaults
00364                         to \$wgFileExtensions.
00365 --overwrite             Overwrite existing images with the same name (default
00366                         is to skip them).
00367 --limit=<num>           Limit the number of images to process. Ignored or
00368                         skipped images are not counted.
00369 --from=<name>           Ignore all files until the one with the given name.
00370                         Useful for resuming aborted imports. <name> should be
00371                         the file's canonical database form.
00372 --skip-dupes            Skip images that were already uploaded under a different
00373                         name (check SHA1).
00374 --search-recursively    Search recursively for files in subdirectories.
00375 --sleep=<sec>           Sleep between files. Useful mostly for debugging.
00376 --user=<username>       Set username of uploader, default 'Maintenance script'.
00377 --check-userblock       Check if the user got blocked during import.
00378 --comment=<text>        Set file description, default 'Importing file'.
00379 --comment-file=<file>   Set description to the content of <file>.
00380 --comment-ext=<ext>     Causes the description for each file to be loaded from a
00381                         file with the same name, but the extension <ext>. If a
00382                         global description is also given, it is appended.
00383 --license=<code>        Use an optional license template.
00384 --dry                   Dry run, don't import anything.
00385 --protect=<protect>     Specify the protect value (autoconfirmed,sysop).
00386 --summary=<summary>     Upload summary, description will be used if not
00387                         provided.
00388 --timestamp=<timestamp> Override upload time/date, all MediaWiki timestamp
00389                         formats are accepted.
00390 --unprotect             Unprotects all uploaded images.
00391 --source-wiki-url       If specified, take User and Comment data for each
00392                         imported file from this URL. For example,
00393                         --source-wiki-url="http://en.wikipedia.org/."
00394 
00395 TEXT;
00396     exit( 1 );
00397 }