Index: branches/FileBackend/phase3/tests/phpunit/includes/filerepo/FileBackendTest.php |
— | — | @@ -352,6 +352,7 @@ |
353 | 353 | "$base/cont1/subdir2/subdir/test4.txt", |
354 | 354 | "$base/cont1/subdir2/subdir/test5.txt", |
355 | 355 | "$base/cont1/subdir2/subdir/sub/test0.txt", |
| 356 | + "$base/cont1/subdir2/subdir/sub/120-px-file.txt", |
356 | 357 | ); |
357 | 358 | $this->pathsToPrune = array_merge( $this->pathsToPrune, $files ); |
358 | 359 | |
— | — | @@ -378,6 +379,7 @@ |
379 | 380 | "subdir2/subdir/test4.txt", |
380 | 381 | "subdir2/subdir/test5.txt", |
381 | 382 | "subdir2/subdir/sub/test0.txt", |
| 383 | + "subdir2/subdir/sub/120-px-file.txt", |
382 | 384 | ); |
383 | 385 | $expected = sort( $expected ); |
384 | 386 | |
— | — | @@ -398,6 +400,13 @@ |
399 | 401 | } |
400 | 402 | |
401 | 403 | $this->assertEquals( $expected, sort( $list ), "Correct file listing." ); |
| 404 | + |
| 405 | + foreach ( $files as $file ) { |
| 406 | + $this->backend->delete( array( 'src' => "$base/$files" ) ); |
| 407 | + } |
| 408 | + |
| 409 | + $iter = $this->backend->getFileList( array( 'dir' => "$base/cont1/not/exists" ) ); |
| 410 | + foreach ( $iter as $iter ) {} // no errors |
402 | 411 | } |
403 | 412 | |
404 | 413 | function tearDown() { |
Index: branches/FileBackend/phase3/includes/filerepo/backend/FileOp.php |
— | — | @@ -59,7 +59,7 @@ |
60 | 60 | * @param $performOps Array List of FileOp operations |
61 | 61 | * @return Status |
62 | 62 | */ |
63 | | - public static function attemptBatch( array $performOps ) { |
| 63 | + final public static function attemptBatch( array $performOps ) { |
64 | 64 | $status = Status::newGood(); |
65 | 65 | |
66 | 66 | $predicates = FileOp::newPredicates(); // account for previous op in prechecks |
Index: branches/FileBackend/phase3/includes/filerepo/backend/FSFileBackend.php |
— | — | @@ -438,14 +438,21 @@ |
439 | 439 | function getFileList( array $params ) { |
440 | 440 | list( $c, $dir ) = $this->resolveStoragePath( $params['dir'] ); |
441 | 441 | if ( $dir === null ) { // invalid storage path |
442 | | - return array(); // empty result |
| 442 | + return null; |
443 | 443 | } |
444 | | - try { |
445 | | - $iter = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir ) ); |
446 | | - } catch ( UnexpectedValueException $e ) { |
447 | | - $iter = array(); // dir does not exist? |
| 444 | + wfSuppressWarnings(); |
| 445 | + $exists = is_dir( $dir ); |
| 446 | + wfRestoreWarnings(); |
| 447 | + if ( !$exists ) { |
| 448 | + return array(); // nothing under this dir |
448 | 449 | } |
449 | | - return $iter; |
| 450 | + wfSuppressWarnings(); |
| 451 | + $readable = is_readable( $dir ); |
| 452 | + wfRestoreWarnings(); |
| 453 | + if ( !$readable ) { |
| 454 | + return null; // bad permissions? |
| 455 | + } |
| 456 | + return new FSFileIterator( $dir ); |
450 | 457 | } |
451 | 458 | |
452 | 459 | function getLocalReference( array $params ) { |
— | — | @@ -499,3 +506,53 @@ |
500 | 507 | return $ok; |
501 | 508 | } |
502 | 509 | } |
| 510 | + |
| 511 | +/** |
| 512 | + * Wrapper around RecursiveDirectoryIterator that catches |
| 513 | + * exception or does any custom behavoir that we may want. |
| 514 | + */ |
| 515 | +class FSFileIterator implements Iterator { |
| 516 | + /** @var RecursiveIteratorIterator */ |
| 517 | + protected $iter; |
| 518 | + |
| 519 | + /** |
| 520 | + * Get an FSFileIterator from a file system directory |
| 521 | + * |
| 522 | + * @param $dir string |
| 523 | + */ |
| 524 | + public function __construct( $dir ) { |
| 525 | + try { |
| 526 | + $this->iter = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir ) ); |
| 527 | + } catch ( UnexpectedValueException $e ) { |
| 528 | + $this->iter = null; // bad permissions? deleted? |
| 529 | + } |
| 530 | + } |
| 531 | + |
| 532 | + public function current() { |
| 533 | + return $this->iter->current(); |
| 534 | + } |
| 535 | + |
| 536 | + public function key() { |
| 537 | + return $this->iter->key(); |
| 538 | + } |
| 539 | + |
| 540 | + public function next() { |
| 541 | + try { |
| 542 | + $this->iter->next(); |
| 543 | + } catch ( UnexpectedValueException $e ) { |
| 544 | + $this->iter = null; |
| 545 | + } |
| 546 | + } |
| 547 | + |
| 548 | + public function rewind() { |
| 549 | + try { |
| 550 | + $this->iter->rewind(); |
| 551 | + } catch ( UnexpectedValueException $e ) { |
| 552 | + $this->iter = null; |
| 553 | + } |
| 554 | + } |
| 555 | + |
| 556 | + public function valid() { |
| 557 | + return $this->iter && $this->iter->valid(); |
| 558 | + } |
| 559 | +} |
Index: branches/FileBackend/phase3/includes/filerepo/backend/FileBackend.php |
— | — | @@ -263,7 +263,7 @@ |
264 | 264 | * $params include: |
265 | 265 | * dir : storage path directory |
266 | 266 | * |
267 | | - * @return Iterator|Array |
| 267 | + * @return Traversable|Array|null Returns null on failure |
268 | 268 | */ |
269 | 269 | abstract public function getFileList( array $params ); |
270 | 270 | |