00001 <?php 00007 class LocalRepo extends FSRepo { 00008 var $fileFactory = array( 'LocalFile', 'newFromTitle' ); 00009 var $oldFileFactory = array( 'OldLocalFile', 'newFromTitle' ); 00010 var $fileFromRowFactory = array( 'LocalFile', 'newFromRow' ); 00011 var $oldFileFromRowFactory = array( 'OldLocalFile', 'newFromRow' ); 00012 00013 function newFileFromRow( $row ) { 00014 if ( isset( $row->img_name ) ) { 00015 return call_user_func( $this->fileFromRowFactory, $row, $this ); 00016 } elseif ( isset( $row->oi_name ) ) { 00017 return call_user_func( $this->oldFileFromRowFactory, $row, $this ); 00018 } else { 00019 throw new MWException( __METHOD__.': invalid row' ); 00020 } 00021 } 00022 00023 function newFromArchiveName( $title, $archiveName ) { 00024 return OldLocalFile::newFromArchiveName( $title, $this, $archiveName ); 00025 } 00026 00034 function cleanupDeletedBatch( $storageKeys ) { 00035 $root = $this->getZonePath( 'deleted' ); 00036 $dbw = $this->getMasterDB(); 00037 $status = $this->newGood(); 00038 $storageKeys = array_unique($storageKeys); 00039 foreach ( $storageKeys as $key ) { 00040 $hashPath = $this->getDeletedHashPath( $key ); 00041 $path = "$root/$hashPath$key"; 00042 $dbw->begin(); 00043 $inuse = $dbw->selectField( 'filearchive', '1', 00044 array( 'fa_storage_group' => 'deleted', 'fa_storage_key' => $key ), 00045 __METHOD__, array( 'FOR UPDATE' ) ); 00046 if( !$inuse ) { 00047 $sha1 = substr( $key, 0, strcspn( $key, '.' ) ); 00048 $ext = substr( $key, strcspn($key,'.') + 1 ); 00049 $ext = File::normalizeExtension($ext); 00050 $inuse = $dbw->selectField( 'oldimage', '1', 00051 array( 'oi_sha1' => $sha1, 00052 "oi_archive_name LIKE '%.{$ext}'", 00053 'oi_deleted & '.File::DELETED_FILE => File::DELETED_FILE ), 00054 __METHOD__, array( 'FOR UPDATE' ) ); 00055 } 00056 if ( !$inuse ) { 00057 wfDebug( __METHOD__ . ": deleting $key\n" ); 00058 if ( !@unlink( $path ) ) { 00059 $status->error( 'undelete-cleanup-error', $path ); 00060 $status->failCount++; 00061 } 00062 } else { 00063 wfDebug( __METHOD__ . ": $key still in use\n" ); 00064 $status->successCount++; 00065 } 00066 $dbw->commit(); 00067 } 00068 return $status; 00069 } 00070 00076 function checkRedirect( $title ) { 00077 global $wgMemc; 00078 00079 if( is_string( $title ) ) { 00080 $title = Title::newFromTitle( $title ); 00081 } 00082 if( $title instanceof Title && $title->getNamespace() == NS_MEDIA ) { 00083 $title = Title::makeTitle( NS_FILE, $title->getText() ); 00084 } 00085 00086 $memcKey = $this->getMemcKey( "image_redirect:" . md5( $title->getPrefixedDBkey() ) ); 00087 $cachedValue = $wgMemc->get( $memcKey ); 00088 if( $cachedValue ) { 00089 return Title::newFromDbKey( $cachedValue ); 00090 } elseif( $cachedValue == ' ' ) { # FIXME: ugly hack, but BagOStuff caching seems to be weird and return false if !cachedValue, not only if it doesn't exist 00091 return false; 00092 } 00093 00094 $id = $this->getArticleID( $title ); 00095 if( !$id ) { 00096 $wgMemc->set( $memcKey, " ", 9000 ); 00097 return false; 00098 } 00099 $dbr = $this->getSlaveDB(); 00100 $row = $dbr->selectRow( 00101 'redirect', 00102 array( 'rd_title', 'rd_namespace' ), 00103 array( 'rd_from' => $id ), 00104 __METHOD__ 00105 ); 00106 00107 if( $row ) $targetTitle = Title::makeTitle( $row->rd_namespace, $row->rd_title ); 00108 $wgMemc->set( $memcKey, ($row ? $targetTitle->getPrefixedDBkey() : " "), 9000 ); 00109 if( !$row ) { 00110 return false; 00111 } 00112 return $targetTitle; 00113 } 00114 00115 00120 protected function getArticleID( $title ) { 00121 if( !$title instanceof Title ) { 00122 return 0; 00123 } 00124 $dbr = $this->getSlaveDB(); 00125 $id = $dbr->selectField( 00126 'page', // Table 00127 'page_id', //Field 00128 array( //Conditions 00129 'page_namespace' => $title->getNamespace(), 00130 'page_title' => $title->getDBKey(), 00131 ), 00132 __METHOD__ //Function name 00133 ); 00134 return $id; 00135 } 00136 00137 00138 00139 function findBySha1( $hash ) { 00140 $dbr = $this->getSlaveDB(); 00141 $res = $dbr->select( 00142 'image', 00143 LocalFile::selectFields(), 00144 array( 'img_sha1' => $hash ) 00145 ); 00146 00147 $result = array(); 00148 while ( $row = $res->fetchObject() ) 00149 $result[] = $this->newFileFromRow( $row ); 00150 $res->free(); 00151 return $result; 00152 } 00153 00154 /* 00155 * Find many files using one query 00156 */ 00157 function findFiles( $titles ) { 00158 // FIXME: Only accepts a $titles array where the keys are the sanitized 00159 // file names. 00160 00161 if ( count( $titles ) == 0 ) return array(); 00162 00163 $dbr = $this->getSlaveDB(); 00164 $res = $dbr->select( 00165 'image', 00166 LocalFile::selectFields(), 00167 array( 'img_name' => array_keys( $titles ) ) 00168 ); 00169 00170 $result = array(); 00171 while ( $row = $res->fetchObject() ) { 00172 $result[$row->img_name] = $this->newFileFromRow( $row ); 00173 } 00174 $res->free(); 00175 return $result; 00176 } 00177 }