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 ' . $dbw->buildLike( $dbw->anyString(), ".$ext" ),
00053 $dbw->bitAnd('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->getSharedCacheKey( 'image_redirect', md5( $title->getDBkey() ) );
00087 if ( $memcKey === false ) {
00088 $memcKey = $this->getLocalCacheKey( 'image_redirect', md5( $title->getDBkey() ) );
00089 $expiry = 300;
00090 } else {
00091 $expiry = 86400;
00092 }
00093 $cachedValue = $wgMemc->get( $memcKey );
00094 if ( $cachedValue === ' ' || $cachedValue === '' ) {
00095
00096 return false;
00097 } elseif ( strval( $cachedValue ) !== '' ) {
00098 return Title::newFromText( $cachedValue, NS_FILE );
00099 }
00100
00101 $id = $this->getArticleID( $title );
00102 if( !$id ) {
00103 $wgMemc->set( $memcKey, " ", $expiry );
00104 return false;
00105 }
00106 $dbr = $this->getSlaveDB();
00107 $row = $dbr->selectRow(
00108 'redirect',
00109 array( 'rd_title', 'rd_namespace' ),
00110 array( 'rd_from' => $id ),
00111 __METHOD__
00112 );
00113
00114 if( $row && $row->rd_namespace == NS_FILE ) {
00115 $targetTitle = Title::makeTitle( $row->rd_namespace, $row->rd_title );
00116 $wgMemc->set( $memcKey, $targetTitle->getDBkey(), $expiry );
00117 return $targetTitle;
00118 } else {
00119 $wgMemc->set( $memcKey, '', $expiry );
00120 return false;
00121 }
00122 }
00123
00124
00129 protected function getArticleID( $title ) {
00130 if( !$title instanceof Title ) {
00131 return 0;
00132 }
00133 $dbr = $this->getSlaveDB();
00134 $id = $dbr->selectField(
00135 'page',
00136 'page_id',
00137 array(
00138 'page_namespace' => $title->getNamespace(),
00139 'page_title' => $title->getDBkey(),
00140 ),
00141 __METHOD__
00142 );
00143 return $id;
00144 }
00145
00150 function findBySha1( $hash ) {
00151 $dbr = $this->getSlaveDB();
00152 $res = $dbr->select(
00153 'image',
00154 LocalFile::selectFields(),
00155 array( 'img_sha1' => $hash )
00156 );
00157
00158 $result = array();
00159 while ( $row = $res->fetchObject() )
00160 $result[] = $this->newFileFromRow( $row );
00161 $res->free();
00162 return $result;
00163 }
00164
00168 function getSlaveDB() {
00169 return wfGetDB( DB_SLAVE );
00170 }
00171
00175 function getMasterDB() {
00176 return wfGetDB( DB_MASTER );
00177 }
00178
00184 function getSharedCacheKey( ) {
00185 $args = func_get_args();
00186 return call_user_func_array( 'wfMemcKey', $args );
00187 }
00188
00194 function invalidateImageRedirect( $title ) {
00195 global $wgMemc;
00196 $memcKey = $this->getSharedCacheKey( 'image_redirect', md5( $title->getDBkey() ) );
00197 if ( $memcKey ) {
00198 $wgMemc->delete( $memcKey );
00199 }
00200 }
00201 }
00202