Index: trunk/phase3/maintenance/cleanupUploadStash.php |
— | — | @@ -35,32 +35,33 @@ |
36 | 36 | } |
37 | 37 | |
38 | 38 | public function execute() { |
39 | | - $dbr = wfGetDB( DB_SLAVE ); |
| 39 | + $repo = RepoGroup::singleton()->getLocalRepo(); |
| 40 | + |
| 41 | + $dbr = $repo->getSlaveDb(); |
40 | 42 | |
41 | 43 | $this->output( "Getting list of files to clean up...\n" ); |
42 | 44 | $res = $dbr->select( |
43 | 45 | 'uploadstash', |
44 | 46 | 'us_key', |
45 | | - 'us_timestamp < ' . wfTimestamp( TS_MW, time() - UploadStash::REPO_AGE * 3600 ), |
| 47 | + 'us_timestamp < ' . $dbr->timestamp( time() - UploadStash::REPO_AGE * 3600 ), |
46 | 48 | __METHOD__ |
47 | 49 | ); |
48 | 50 | |
49 | | - if( !is_object( $res ) ) { |
| 51 | + if( !is_object( $res ) || $res->numRows() == 0 ) { |
50 | 52 | // nothing to do. |
51 | 53 | return false; |
52 | 54 | } |
53 | 55 | |
54 | 56 | // finish the read before starting writes. |
55 | 57 | $keys = array(); |
56 | | - while( $row = $dbr->fetchRow( $res ) ) { |
57 | | - array_push( $keys, $row['us_key'] ); |
| 58 | + foreach($res as $row) { |
| 59 | + array_push( $keys, $row->us_key ); |
58 | 60 | } |
59 | 61 | |
60 | 62 | $this->output( 'Removing ' . count($keys) . " file(s)...\n" ); |
61 | 63 | // this could be done some other, more direct/efficient way, but using |
62 | 64 | // UploadStash's own methods means it's less likely to fall accidentally |
63 | 65 | // out-of-date someday |
64 | | - $repo = RepoGroup::singleton()->getLocalRepo(); |
65 | 66 | $stash = new UploadStash( $repo ); |
66 | 67 | |
67 | 68 | foreach( $keys as $key ) { |
Index: trunk/phase3/maintenance/archives/patch-uploadstash.sql |
— | — | @@ -1,5 +1,5 @@ |
2 | 2 | -- |
| 3 | +-- Store information about newly uploaded files before they're |
3 | 4 | -- moved into the actual filestore |
4 | 5 | -- |
5 | 6 | CREATE TABLE /*_*/uploadstash ( |
— | — | @@ -22,7 +22,9 @@ |
23 | 23 | us_source_type varchar(50), |
24 | 24 | |
25 | 25 | -- the date/time on which the file was added |
26 | | - us_timestamp varchar(14) not null, |
| 26 | + us_timestamp varbinary(14) not null, |
| 27 | + |
| 28 | + us_status varchar(50) not null, |
27 | 29 | |
28 | 30 | -- file properties from File::getPropsFromPath. these may prove unnecessary. |
29 | 31 | -- |
— | — | @@ -30,7 +32,8 @@ |
31 | 33 | -- this hash comes from File::sha1Base36(), and is 31 characters |
32 | 34 | us_sha1 varchar(31) NOT NULL, |
33 | 35 | us_mime varchar(255), |
34 | | - us_media_type varchar(255), |
| 36 | + -- Media type as defined by the MEDIATYPE_xxx constants, should duplicate definition in the image table |
| 37 | + us_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL, |
35 | 38 | -- image-specific properties |
36 | 39 | us_image_width int unsigned, |
37 | 40 | us_image_height int unsigned, |
— | — | @@ -43,4 +46,4 @@ |
44 | 47 | -- pick out files by key, enforce key uniqueness |
45 | 48 | CREATE UNIQUE INDEX /*i*/us_key ON /*_*/uploadstash (us_key); |
46 | 49 | -- the abandoned upload cleanup script needs this |
47 | | -CREATE INDEX /*i*/us_timestamp ON /*_*/uploadstash (us_timestamp); |
\ No newline at end of file |
| 50 | +CREATE INDEX /*i*/us_timestamp ON /*_*/uploadstash (us_timestamp); |
Index: trunk/phase3/maintenance/tables.sql |
— | — | @@ -962,7 +962,9 @@ |
963 | 963 | us_source_type varchar(50), |
964 | 964 | |
965 | 965 | -- the date/time on which the file was added |
966 | | - us_timestamp varchar(14) not null, |
| 966 | + us_timestamp varbinary(14) not null, |
| 967 | + |
| 968 | + us_status varchar(50) not null, |
967 | 969 | |
968 | 970 | -- file properties from File::getPropsFromPath. these may prove unnecessary. |
969 | 971 | -- |
— | — | @@ -970,7 +972,8 @@ |
971 | 973 | -- this hash comes from File::sha1Base36(), and is 31 characters |
972 | 974 | us_sha1 varchar(31) NOT NULL, |
973 | 975 | us_mime varchar(255), |
974 | | - us_media_type varchar(255), |
| 976 | + -- Media type as defined by the MEDIATYPE_xxx constants, should duplicate definition in the image table |
| 977 | + us_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL, |
975 | 978 | -- image-specific properties |
976 | 979 | us_image_width int unsigned, |
977 | 980 | us_image_height int unsigned, |
Index: trunk/phase3/includes/upload/UploadFromStash.php |
— | — | @@ -16,15 +16,23 @@ |
17 | 17 | //LocalFile repo |
18 | 18 | private $repo; |
19 | 19 | |
20 | | - public function __construct( $stash = false, $repo = false ) { |
21 | | - if( !$this->repo ) { |
| 20 | + public function __construct( $user = false, $stash = false, $repo = false ) { |
| 21 | + // user object. sometimes this won't exist, as when running from cron. |
| 22 | + $this->user = $user; |
| 23 | + |
| 24 | + if( $repo ) { |
| 25 | + $this->repo = $repo; |
| 26 | + } else { |
22 | 27 | $this->repo = RepoGroup::singleton()->getLocalRepo(); |
23 | 28 | } |
24 | 29 | |
25 | | - if( !$this->stash ) { |
26 | | - $this->stash = new UploadStash( $this->repo ); |
| 30 | + if( $stash ) { |
| 31 | + $this->stash = $stash; |
| 32 | + } else { |
| 33 | + wfDebug( __METHOD__ . " creating new UploadStash instance for " . $user->getId() . "\n" ); |
| 34 | + $this->stash = new UploadStash( $this->repo, $this->user ); |
27 | 35 | } |
28 | | - |
| 36 | + |
29 | 37 | return true; |
30 | 38 | } |
31 | 39 | |
Index: trunk/phase3/includes/upload/UploadStash.php |
— | — | @@ -42,6 +42,9 @@ |
43 | 43 | |
44 | 44 | // fileprops cache |
45 | 45 | protected $fileProps = array(); |
| 46 | + |
| 47 | + // current user |
| 48 | + protected $user, $userId, $isLoggedIn; |
46 | 49 | |
47 | 50 | /** |
48 | 51 | * Represents a temporary filestore, with metadata in the database. |
— | — | @@ -49,16 +52,30 @@ |
50 | 53 | * |
51 | 54 | * @param $repo FileRepo |
52 | 55 | */ |
53 | | - public function __construct( $repo ) { |
| 56 | + public function __construct( $repo, $user = null ) { |
54 | 57 | // this might change based on wiki's configuration. |
55 | 58 | $this->repo = $repo; |
| 59 | + |
| 60 | + // if a user was passed, use it. otherwise, attempt to use the global. |
| 61 | + // this keeps FileRepo from breaking when it creates an UploadStash object |
| 62 | + if( $user ) { |
| 63 | + $this->user = $user; |
| 64 | + } else { |
| 65 | + global $wgUser; |
| 66 | + $this->user = $wgUser; |
| 67 | + } |
| 68 | + |
| 69 | + if( is_object($this->user) ) { |
| 70 | + $this->userId = $this->user->getId(); |
| 71 | + $this->isLoggedIn = $this->user->isLoggedIn(); |
| 72 | + } |
56 | 73 | } |
57 | 74 | |
58 | 75 | /** |
59 | 76 | * Get a file and its metadata from the stash. |
60 | 77 | * |
61 | 78 | * @param $key String: key under which file information is stored |
62 | | - * @param $noauth Boolean (optional) Don't check authentication. Used by maintenance scripts. |
| 79 | + * @param $noAuth Boolean (optional) Don't check authentication. Used by maintenance scripts. |
63 | 80 | * @throws UploadStashFileNotFoundException |
64 | 81 | * @throws UploadStashNotLoggedInException |
65 | 82 | * @throws UploadStashWrongOwnerException |
— | — | @@ -66,19 +83,19 @@ |
67 | 84 | * @return UploadStashFile |
68 | 85 | */ |
69 | 86 | public function getFile( $key, $noAuth = false ) { |
70 | | - global $wgUser; |
71 | 87 | |
72 | 88 | if ( ! preg_match( self::KEY_FORMAT_REGEX, $key ) ) { |
73 | 89 | throw new UploadStashBadPathException( "key '$key' is not in a proper format" ); |
74 | 90 | } |
75 | 91 | |
76 | 92 | if( !$noAuth ) { |
77 | | - $userId = $wgUser->getId(); |
78 | | - if( !$userId ) { |
79 | | - throw new UploadStashNotLoggedInException( 'No user is logged in, files must belong to users' ); |
| 93 | + if( !$this->isLoggedIn ) { |
| 94 | + throw new UploadStashNotLoggedInException( __METHOD__ . ' No user is logged in, files must belong to users' ); |
80 | 95 | } |
81 | 96 | } |
82 | 97 | |
| 98 | + $dbr = $this->repo->getSlaveDb(); |
| 99 | + |
83 | 100 | if ( !isset( $this->fileMetadata[$key] ) ) { |
84 | 101 | // try this first. if it fails to find the row, check for lag, wait, try again. if its still missing, throw an exception. |
85 | 102 | // this more complex solution keeps things moving for page loads with many requests |
— | — | @@ -115,7 +132,7 @@ |
116 | 133 | } |
117 | 134 | |
118 | 135 | if( !$noAuth ) { |
119 | | - if( $this->fileMetadata[$key]['us_user'] != $userId ) { |
| 136 | + if( $this->fileMetadata[$key]['us_user'] != $this->userId ) { |
120 | 137 | throw new UploadStashWrongOwnerException( "This file ($key) doesn't belong to the current user." ); |
121 | 138 | } |
122 | 139 | } |
— | — | @@ -157,7 +174,6 @@ |
158 | 175 | * @return UploadStashFile: file, or null on failure |
159 | 176 | */ |
160 | 177 | public function stashFile( $path, $sourceType = null, $key = null ) { |
161 | | - global $wgUser; |
162 | 178 | if ( ! file_exists( $path ) ) { |
163 | 179 | wfDebug( __METHOD__ . " tried to stash file at '$path', but it doesn't exist\n" ); |
164 | 180 | throw new UploadStashBadPathException( "path doesn't exist" ); |
— | — | @@ -214,13 +230,17 @@ |
215 | 231 | $stashPath = $storeResult->value; |
216 | 232 | |
217 | 233 | // fetch the current user ID |
218 | | - $userId = $wgUser->getId(); |
219 | | - if( !$userId ) { |
220 | | - throw new UploadStashNotLoggedInException( "No user is logged in, files must belong to users" ); |
| 234 | + if( !$this->isLoggedIn ) { |
| 235 | + wfDebugCallstack(); |
| 236 | + throw new UploadStashNotLoggedInException( __METHOD__ . ' No user is logged in, files must belong to users' ); |
221 | 237 | } |
222 | 238 | |
| 239 | + // insert the file metadata into the db. |
| 240 | + wfDebug( __METHOD__ . " inserting $stashPath under $key\n" ); |
| 241 | + $dbw = $this->repo->getMasterDb(); |
| 242 | + |
223 | 243 | $this->fileMetadata[$key] = array( |
224 | | - 'us_user' => $userId, |
| 244 | + 'us_user' => $this->userId, |
225 | 245 | 'us_key' => $key, |
226 | 246 | 'us_orig_path' => $path, |
227 | 247 | 'us_path' => $stashPath, |
— | — | @@ -232,12 +252,11 @@ |
233 | 253 | 'us_image_height' => $fileProps['height'], |
234 | 254 | 'us_image_bits' => $fileProps['bits'], |
235 | 255 | 'us_source_type' => $sourceType, |
236 | | - 'us_timestamp' => wfTimestamp( TS_MW ) |
| 256 | + 'us_timestamp' => $dbw->timestamp(), |
| 257 | + 'us_status' => 'finished' |
237 | 258 | ); |
238 | 259 | |
239 | | - // insert the file metadata into the db. |
240 | | - wfDebug( __METHOD__ . " inserting $stashPath under $key\n" ); |
241 | | - $dbw = wfGetDB( DB_MASTER ); |
| 260 | + |
242 | 261 | $dbw->insert( |
243 | 262 | 'uploadstash', |
244 | 263 | $this->fileMetadata[$key], |
— | — | @@ -261,18 +280,15 @@ |
262 | 281 | * @return boolean: success |
263 | 282 | */ |
264 | 283 | public function clear() { |
265 | | - global $wgUser; |
266 | | - |
267 | | - $userId = $wgUser->getId(); |
268 | | - if( !$userId ) { |
269 | | - throw new UploadStashNotLoggedInException( 'No user is logged in, files must belong to users' ); |
| 284 | + if( !$this->isLoggedIn ) { |
| 285 | + throw new UploadStashNotLoggedInException( __METHOD__ . ' No user is logged in, files must belong to users' ); |
270 | 286 | } |
271 | 287 | |
272 | 288 | wfDebug( __METHOD__ . " clearing all rows for user $userId\n" ); |
273 | | - $dbw = wfGetDB( DB_MASTER ); |
| 289 | + $dbw = $this->repo->getMasterDb(); |
274 | 290 | $dbw->delete( |
275 | 291 | 'uploadstash', |
276 | | - array( 'us_user' => $userId ), |
| 292 | + array( 'us_user' => $this->userId ), |
277 | 293 | __METHOD__ |
278 | 294 | ); |
279 | 295 | |
— | — | @@ -291,14 +307,11 @@ |
292 | 308 | * @return boolean: success |
293 | 309 | */ |
294 | 310 | public function removeFile( $key ){ |
295 | | - global $wgUser; |
296 | | - |
297 | | - $userId = $wgUser->getId(); |
298 | | - if( !$userId ) { |
299 | | - throw new UploadStashNotLoggedInException( 'No user is logged in, files must belong to users' ); |
| 311 | + if( !$this->isLoggedIn ) { |
| 312 | + throw new UploadStashNotLoggedInException( __METHOD__ . ' No user is logged in, files must belong to users' ); |
300 | 313 | } |
301 | 314 | |
302 | | - $dbw = wfGetDB( DB_MASTER ); |
| 315 | + $dbw = $this->repo->getMasterDb(); |
303 | 316 | |
304 | 317 | // this is a cheap query. it runs on the master so that this function still works when there's lag. |
305 | 318 | // it won't be called all that often. |
— | — | @@ -309,7 +322,7 @@ |
310 | 323 | __METHOD__ |
311 | 324 | ); |
312 | 325 | |
313 | | - if( $row->us_user != $userId ) { |
| 326 | + if( $row->us_user != $this->userId ) { |
314 | 327 | throw new UploadStashWrongOwnerException( "Can't delete: the file ($key) doesn't belong to this user." ); |
315 | 328 | } |
316 | 329 | |
— | — | @@ -325,7 +338,7 @@ |
326 | 339 | public function removeFileNoAuth( $key ) { |
327 | 340 | wfDebug( __METHOD__ . " clearing row $key\n" ); |
328 | 341 | |
329 | | - $dbw = wfGetDB( DB_MASTER ); |
| 342 | + $dbw = $this->repo->getMasterDb(); |
330 | 343 | |
331 | 344 | // this gets its own transaction since it's called serially by the cleanupUploadStash maintenance script |
332 | 345 | $dbw->begin(); |
— | — | @@ -353,14 +366,11 @@ |
354 | 367 | * @return Array |
355 | 368 | */ |
356 | 369 | public function listFiles() { |
357 | | - global $wgUser; |
358 | | - |
359 | | - $userId = $wgUser->getId(); |
360 | | - if( !$userId ) { |
361 | | - throw new UploadStashNotLoggedInException( 'No user is logged in, files must belong to users' ); |
| 370 | + if( !$this->isLoggedIn ) { |
| 371 | + throw new UploadStashNotLoggedInException( __METHOD__ . ' No user is logged in, files must belong to users' ); |
362 | 372 | } |
363 | 373 | |
364 | | - $dbw = wfGetDB( DB_SLAVE ); |
| 374 | + $dbr = $this->repo->getSlaveDb(); |
365 | 375 | $res = $dbr->select( |
366 | 376 | 'uploadstash', |
367 | 377 | 'us_key', |
— | — | @@ -368,14 +378,15 @@ |
369 | 379 | __METHOD__ |
370 | 380 | ); |
371 | 381 | |
372 | | - if( !is_object( $res ) ) { |
373 | | - // nothing there. |
| 382 | + if( !is_object( $res ) || $res->numRows() == 0 ) { |
| 383 | + // nothing to do. |
374 | 384 | return false; |
375 | 385 | } |
376 | 386 | |
| 387 | + // finish the read before starting writes. |
377 | 388 | $keys = array(); |
378 | | - while( $row = $dbr->fetchRow( $res ) ) { |
379 | | - array_push( $keys, $row['us_key'] ); |
| 389 | + foreach($res as $row) { |
| 390 | + array_push( $keys, $row->us_key ); |
380 | 391 | } |
381 | 392 | |
382 | 393 | return $keys; |
— | — | @@ -419,7 +430,7 @@ |
420 | 431 | */ |
421 | 432 | protected function fetchFileMetadata( $key ) { |
422 | 433 | // populate $fileMetadata[$key] |
423 | | - $dbr = wfGetDB( DB_SLAVE ); |
| 434 | + $dbr = $this->repo->getSlaveDb(); |
424 | 435 | $row = $dbr->selectRow( |
425 | 436 | 'uploadstash', |
426 | 437 | '*', |
— | — | @@ -444,7 +455,9 @@ |
445 | 456 | 'us_image_width' => $row->us_image_width, |
446 | 457 | 'us_image_height' => $row->us_image_height, |
447 | 458 | 'us_image_bits' => $row->us_image_bits, |
448 | | - 'us_source_type' => $row->us_source_type |
| 459 | + 'us_source_type' => $row->us_source_type, |
| 460 | + 'us_timestamp' => $row->us_timestamp, |
| 461 | + 'us_status' => $row->us_status |
449 | 462 | ); |
450 | 463 | |
451 | 464 | return true; |
Index: trunk/phase3/includes/api/ApiUpload.php |
— | — | @@ -220,7 +220,9 @@ |
221 | 221 | $this->dieUsageMsg( 'invalid-file-key' ); |
222 | 222 | } |
223 | 223 | |
224 | | - $this->mUpload = new UploadFromStash(); |
| 224 | + // context allows access to the current user without creating new $wgUser references |
| 225 | + $context = $this->createContext(); |
| 226 | + $this->mUpload = new UploadFromStash( $context->getUser() ); |
225 | 227 | $this->mUpload->initialize( $this->mParams['filekey'], $this->mParams['filename'] ); |
226 | 228 | |
227 | 229 | } elseif ( isset( $this->mParams['file'] ) ) { |