MediaWiki
REL1_24
|
00001 <?php 00022 require_once __DIR__ . '/Maintenance.php'; 00023 00024 class FindMissingFiles extends Maintenance { 00025 function __construct() { 00026 parent::__construct(); 00027 00028 $this->mDescription = 'Find registered files with no corresponding file.'; 00029 $this->addOption( 'start', 'Starting file name', false, true ); 00030 $this->addOption( 'mtimeafter', 'Only include files changed since this time', false, true ); 00031 $this->addOption( 'mtimebefore', 'Only includes files changed before this time', false, true ); 00032 $this->setBatchSize( 300 ); 00033 } 00034 00035 function execute() { 00036 $lastName = $this->getOption( 'start', '' ); 00037 00038 $repo = RepoGroup::singleton()->getLocalRepo(); 00039 $dbr = $repo->getSlaveDB(); 00040 $be = $repo->getBackend(); 00041 00042 $mtime1 = $dbr->timestampOrNull( $this->getOption( 'mtimeafter', null ) ); 00043 $mtime2 = $dbr->timestampOrNull( $this->getOption( 'mtimebefore', null ) ); 00044 00045 $joinTables = array( 'image' ); 00046 $joinConds = array( 'image' => array( 'INNER JOIN', 'img_name = page_title' ) ); 00047 if ( $mtime1 || $mtime2 ) { 00048 $joinTables[] = 'logging'; 00049 $on = array( 'log_page = page_id', 'log_type' => array( 'upload', 'move', 'delete' ) ); 00050 if ( $mtime1 ) { 00051 $on[] = "log_timestamp > {$dbr->addQuotes($mtime1)}"; 00052 } 00053 if ( $mtime2 ) { 00054 $on[] = "log_timestamp < {$dbr->addQuotes($mtime2)}"; 00055 } 00056 $joinConds['logging'] = array( 'INNER JOIN', $on ); 00057 } 00058 00059 do { 00060 $res = $dbr->select( 00061 array_merge( array( 'page' ), $joinTables ), 00062 array( 'img_name' => 'DISTINCT(page_title)' ), 00063 array( 'page_namespace' => NS_FILE, 00064 "page_title >= " . $dbr->addQuotes( $lastName ) ), 00065 __METHOD__, 00066 array( 'ORDER BY' => 'page_title', 'LIMIT' => $this->mBatchSize ), 00067 $joinConds 00068 ); 00069 00070 // Check if any of these files are missing... 00071 $pathsByName = array(); 00072 foreach ( $res as $row ) { 00073 $file = $repo->newFile( $row->img_name ); 00074 $pathsByName[$row->img_name] = $file->getPath(); 00075 $lastName = $row->img_name; 00076 } 00077 $be->preloadFileStat( array( 'srcs' => $pathsByName ) ); 00078 foreach ( $pathsByName as $path ) { 00079 if ( $be->fileExists( array( 'src' => $path ) ) === false ) { 00080 $this->output( "$path\n" ); 00081 } 00082 } 00083 00084 // Find all missing old versions of any of the files in this batch... 00085 if ( count( $pathsByName ) ) { 00086 $ores = $dbr->select( 'oldimage', 00087 array( 'oi_name', 'oi_archive_name' ), 00088 array( 'oi_name' => array_keys( $pathsByName ) ), 00089 __METHOD__ 00090 ); 00091 00092 $checkPaths = array(); 00093 foreach ( $ores as $row ) { 00094 if ( !strlen( $row->oi_archive_name ) ) { 00095 continue; // broken row 00096 } 00097 $file = $repo->newFromArchiveName( $row->oi_name, $row->oi_archive_name ); 00098 $checkPaths[] = $file->getPath(); 00099 } 00100 00101 foreach ( array_chunk( $checkPaths, $this->mBatchSize ) as $paths ) { 00102 $be->preloadFileStat( array( 'srcs' => $paths ) ); 00103 foreach ( $paths as $path ) { 00104 if ( $be->fileExists( array( 'src' => $path ) ) === false ) { 00105 $this->output( "$path\n" ); 00106 } 00107 } 00108 } 00109 } 00110 } while ( $res->numRows() >= $this->mBatchSize ); 00111 } 00112 } 00113 00114 $maintClass = 'FindMissingFiles'; 00115 require_once RUN_MAINTENANCE_IF_MAIN;