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