Index: trunk/phase3/RELEASE-NOTES-1.19 |
— | — | @@ -48,6 +48,8 @@ |
49 | 49 | * Do not convert text in the user interface language to another script. |
50 | 50 | * (bug 26283) Previewing user JS/CSS pages doesn't load other user JS/CSS pages |
51 | 51 | * (bug 11374) Improved diff readability for colorblind people. |
| 52 | +* (bug 26486) ResourceLoader modules with paths to nonexistent files cause PHP |
| 53 | + warnings/notices to be thrown |
52 | 54 | |
53 | 55 | === API changes in 1.19 === |
54 | 56 | * (bug 19838) siprop=interwikimap can now use the interwiki cache. |
Index: trunk/phase3/includes/resourceloader/ResourceLoaderFileModule.php |
— | — | @@ -367,7 +367,7 @@ |
368 | 368 | } |
369 | 369 | |
370 | 370 | wfProfileIn( __METHOD__.'-filemtime' ); |
371 | | - $filesMtime = max( array_map( 'filemtime', $files ) ); |
| 371 | + $filesMtime = max( array_map( array( __CLASS__, 'safeFilemtime' ), $files ) ); |
372 | 372 | wfProfileOut( __METHOD__.'-filemtime' ); |
373 | 373 | $this->modifiedTime[$context->getHash()] = max( |
374 | 374 | $filesMtime, |
— | — | @@ -493,10 +493,10 @@ |
494 | 494 | $js = ''; |
495 | 495 | foreach ( array_unique( $scripts ) as $fileName ) { |
496 | 496 | $localPath = $this->getLocalPath( $fileName ); |
497 | | - $contents = file_get_contents( $localPath ); |
498 | | - if ( $contents === false ) { |
| 497 | + if ( !file_exists( $localPath ) ) { |
499 | 498 | throw new MWException( __METHOD__.": script file not found: \"$localPath\"" ); |
500 | 499 | } |
| 500 | + $contents = file_get_contents( $localPath ); |
501 | 501 | if ( $wgResourceLoaderValidateStaticJS ) { |
502 | 502 | // Static files don't really need to be checked as often; unlike |
503 | 503 | // on-wiki module they shouldn't change unexpectedly without |
— | — | @@ -542,17 +542,18 @@ |
543 | 543 | * |
544 | 544 | * This method can be used as a callback for array_map() |
545 | 545 | * |
546 | | - * @param $path String: File path of script file to read |
| 546 | + * @param $path String: File path of style file to read |
547 | 547 | * @param $flip bool |
548 | 548 | * |
549 | 549 | * @return String: CSS data in script file |
| 550 | + * @throws MWException if the file doesn't exist |
550 | 551 | */ |
551 | 552 | protected function readStyleFile( $path, $flip ) { |
552 | 553 | $localPath = $this->getLocalPath( $path ); |
553 | | - $style = file_get_contents( $localPath ); |
554 | | - if ( $style === false ) { |
| 554 | + if ( !file_exists( $localPath ) ) { |
555 | 555 | throw new MWException( __METHOD__.": style file not found: \"$localPath\"" ); |
556 | 556 | } |
| 557 | + $style = file_get_contents( $localPath ); |
557 | 558 | if ( $flip ) { |
558 | 559 | $style = CSSJanus::transform( $style, true, false ); |
559 | 560 | } |
— | — | @@ -571,6 +572,23 @@ |
572 | 573 | $style, $dir, $remoteDir, true |
573 | 574 | ); |
574 | 575 | } |
| 576 | + |
| 577 | + /** |
| 578 | + * Safe version of filemtime(), which doesn't throw a PHP warning if the file doesn't exist |
| 579 | + * but returns 1 instead. |
| 580 | + * @param $filename string File name |
| 581 | + * @return int UNIX timestamp, or 1 if the file doesn't exist |
| 582 | + */ |
| 583 | + protected static function safeFilemtime( $filename ) { |
| 584 | + if ( file_exists( $filename ) ) { |
| 585 | + return filemtime( $filename ); |
| 586 | + } else { |
| 587 | + // We only ever map this function on an array if we're gonna call max() after, |
| 588 | + // so return our standard minimum timestamps here. This is 1, not 0, because |
| 589 | + // wfTimestamp(0) == NOW |
| 590 | + return 1; |
| 591 | + } |
| 592 | + } |
575 | 593 | |
576 | 594 | /** |
577 | 595 | * Get whether CSS for this module should be flipped |