Index: trunk/phase3/maintenance/language/messages.inc |
— | — | @@ -408,6 +408,7 @@ |
409 | 409 | 'customjsprotected', |
410 | 410 | 'ns-specialprotected', |
411 | 411 | 'titleprotected', |
| 412 | + 'filereadonlyerror' |
412 | 413 | ), |
413 | 414 | 'virus' => array( |
414 | 415 | 'virus-badscanner', |
Index: trunk/phase3/includes/filerepo/file/LocalFile.php |
— | — | @@ -908,9 +908,13 @@ |
909 | 909 | */ |
910 | 910 | function upload( $srcPath, $comment, $pageText, $flags = 0, $props = false, $timestamp = false, $user = null ) { |
911 | 911 | global $wgContLang; |
| 912 | + |
| 913 | + if ( $this->getRepo()->getReadOnlyReason() !== false ) { |
| 914 | + return $this->readOnlyFatalStatus(); |
| 915 | + } |
| 916 | + |
912 | 917 | // truncate nicely or the DB will do it for us |
913 | | - // non-nicely (dangling multi-byte chars, non-truncated |
914 | | - // version in cache). |
| 918 | + // non-nicely (dangling multi-byte chars, non-truncated version in cache). |
915 | 919 | $comment = $wgContLang->truncate( $comment, 255 ); |
916 | 920 | $this->lock(); // begin |
917 | 921 | $status = $this->publish( $srcPath, $flags ); |
— | — | @@ -1175,6 +1179,10 @@ |
1176 | 1180 | * archive name, or an empty string if it was a new file. |
1177 | 1181 | */ |
1178 | 1182 | function publishTo( $srcPath, $dstRel, $flags = 0 ) { |
| 1183 | + if ( $this->getRepo()->getReadOnlyReason() !== false ) { |
| 1184 | + return $this->readOnlyFatalStatus(); |
| 1185 | + } |
| 1186 | + |
1179 | 1187 | $this->lock(); // begin |
1180 | 1188 | |
1181 | 1189 | $archiveName = wfTimestamp( TS_MW ) . '!'. $this->getName(); |
— | — | @@ -1211,6 +1219,10 @@ |
1212 | 1220 | * @return FileRepoStatus object. |
1213 | 1221 | */ |
1214 | 1222 | function move( $target ) { |
| 1223 | + if ( $this->getRepo()->getReadOnlyReason() !== false ) { |
| 1224 | + return $this->readOnlyFatalStatus(); |
| 1225 | + } |
| 1226 | + |
1215 | 1227 | wfDebugLog( 'imagemove', "Got request to move {$this->name} to " . $target->getText() ); |
1216 | 1228 | $this->lock(); // begin |
1217 | 1229 | |
— | — | @@ -1250,6 +1262,10 @@ |
1251 | 1263 | * @return FileRepoStatus object. |
1252 | 1264 | */ |
1253 | 1265 | function delete( $reason, $suppress = false ) { |
| 1266 | + if ( $this->getRepo()->getReadOnlyReason() !== false ) { |
| 1267 | + return $this->readOnlyFatalStatus(); |
| 1268 | + } |
| 1269 | + |
1254 | 1270 | $this->lock(); // begin |
1255 | 1271 | |
1256 | 1272 | $batch = new LocalFileDeleteBatch( $this, $reason, $suppress ); |
— | — | @@ -1266,7 +1282,7 @@ |
1267 | 1283 | } |
1268 | 1284 | $status = $batch->execute(); |
1269 | 1285 | |
1270 | | - if ( $status->ok ) { |
| 1286 | + if ( $status->isOK() ) { |
1271 | 1287 | // Update site_stats |
1272 | 1288 | $site_stats = $dbw->tableName( 'site_stats' ); |
1273 | 1289 | $dbw->query( "UPDATE $site_stats SET ss_images=ss_images-1", __METHOD__ ); |
— | — | @@ -1293,6 +1309,10 @@ |
1294 | 1310 | * @return FileRepoStatus object. |
1295 | 1311 | */ |
1296 | 1312 | function deleteOld( $archiveName, $reason, $suppress = false ) { |
| 1313 | + if ( $this->getRepo()->getReadOnlyReason() !== false ) { |
| 1314 | + return $this->readOnlyFatalStatus(); |
| 1315 | + } |
| 1316 | + |
1297 | 1317 | $this->lock(); // begin |
1298 | 1318 | |
1299 | 1319 | $batch = new LocalFileDeleteBatch( $this, $reason, $suppress ); |
— | — | @@ -1302,7 +1322,7 @@ |
1303 | 1323 | |
1304 | 1324 | $this->unlock(); // done |
1305 | 1325 | |
1306 | | - if ( $status->ok ) { |
| 1326 | + if ( $status->isOK() ) { |
1307 | 1327 | $this->purgeDescription(); |
1308 | 1328 | $this->purgeHistory(); |
1309 | 1329 | } |
— | — | @@ -1322,6 +1342,12 @@ |
1323 | 1343 | * @return FileRepoStatus |
1324 | 1344 | */ |
1325 | 1345 | function restore( $versions = array(), $unsuppress = false ) { |
| 1346 | + if ( $this->getRepo()->getReadOnlyReason() !== false ) { |
| 1347 | + return $this->readOnlyFatalStatus(); |
| 1348 | + } |
| 1349 | + |
| 1350 | + $this->lock(); // begin |
| 1351 | + |
1326 | 1352 | $batch = new LocalFileRestoreBatch( $this, $unsuppress ); |
1327 | 1353 | |
1328 | 1354 | if ( !$versions ) { |
— | — | @@ -1332,14 +1358,14 @@ |
1333 | 1359 | |
1334 | 1360 | $status = $batch->execute(); |
1335 | 1361 | |
1336 | | - if ( !$status->isGood() ) { |
1337 | | - return $status; |
| 1362 | + if ( $status->isGood() ) { |
| 1363 | + $cleanupStatus = $batch->cleanup(); |
| 1364 | + $cleanupStatus->successCount = 0; |
| 1365 | + $cleanupStatus->failCount = 0; |
| 1366 | + $status->merge( $cleanupStatus ); |
1338 | 1367 | } |
1339 | 1368 | |
1340 | | - $cleanupStatus = $batch->cleanup(); |
1341 | | - $cleanupStatus->successCount = 0; |
1342 | | - $cleanupStatus->failCount = 0; |
1343 | | - $status->merge( $cleanupStatus ); |
| 1369 | + $this->unlock(); // done |
1344 | 1370 | |
1345 | 1371 | return $status; |
1346 | 1372 | } |
— | — | @@ -1443,6 +1469,14 @@ |
1444 | 1470 | $dbw = $this->repo->getMasterDB(); |
1445 | 1471 | $dbw->rollback( __METHOD__ ); |
1446 | 1472 | } |
| 1473 | + |
| 1474 | + /** |
| 1475 | + * @return Status |
| 1476 | + */ |
| 1477 | + protected function readOnlyFatalStatus() { |
| 1478 | + return $this->getRepo()->newFatal( 'filereadonlyerror', $this->getName(), |
| 1479 | + $this->getRepo()->getName(), $this->getRepo()->getReadOnlyReason() ); |
| 1480 | + } |
1447 | 1481 | } // LocalFile class |
1448 | 1482 | |
1449 | 1483 | # ------------------------------------------------------------------------------ |
— | — | @@ -1710,7 +1744,7 @@ |
1711 | 1745 | $this->status->merge( $status ); |
1712 | 1746 | } |
1713 | 1747 | |
1714 | | - if ( !$this->status->ok ) { |
| 1748 | + if ( !$this->status->isOK() ) { |
1715 | 1749 | // Critical file deletion error |
1716 | 1750 | // Roll back inserts, release lock and abort |
1717 | 1751 | // TODO: delete the defunct filearchive rows if we are using a non-transactional DB |
Index: trunk/phase3/includes/filerepo/FileRepo.php |
— | — | @@ -120,6 +120,15 @@ |
121 | 121 | } |
122 | 122 | |
123 | 123 | /** |
| 124 | + * Get an explanatory message if this repo is read-only |
| 125 | + * |
| 126 | + * @return string|bool Returns false if the repo is not read-only |
| 127 | + */ |
| 128 | + public function getReadOnlyReason() { |
| 129 | + return $this->backend->getReadOnlyReason(); |
| 130 | + } |
| 131 | + |
| 132 | + /** |
124 | 133 | * Prepare a single zone or list of zones for usage. |
125 | 134 | * See initDeletedDir() for additional setup needed for the 'deleted' zone. |
126 | 135 | * |
Index: trunk/phase3/languages/messages/MessagesEn.php |
— | — | @@ -997,6 +997,9 @@ |
998 | 998 | 'directorycreateerror' => 'Could not create directory "$1".', |
999 | 999 | 'filenotfound' => 'Could not find file "$1".', |
1000 | 1000 | 'fileexistserror' => 'Unable to write to file "$1": File exists.', |
| 1001 | +'filereadonlyerror' => 'Unable to the modify the file "$1" because the file repository "$2" is in read-only mode. |
| 1002 | + |
| 1003 | +The administrator who locked it offered this explanation: "$3".', |
1001 | 1004 | 'unexpected' => 'Unexpected value: "$1"="$2".', |
1002 | 1005 | 'formerror' => 'Error: Could not submit form.', |
1003 | 1006 | 'badarticleerror' => 'This action cannot be performed on this page.', |