if ( !file_exists( $localPath ) ) {
throw new MWException( __METHOD__ . ": skip function file not found: \"$localPath\"" );
}
- $contents = file_get_contents( $localPath );
+ $contents = $this->stripBom( file_get_contents( $localPath ) );
if ( $this->getConfig()->get( 'ResourceLoaderValidateStaticJS' ) ) {
$contents = $this->validateScriptFile( $localPath, $contents );
}
if ( !file_exists( $localPath ) ) {
throw new MWException( __METHOD__ . ": script file not found: \"$localPath\"" );
}
- $contents = file_get_contents( $localPath );
+ $contents = $this->stripBom( file_get_contents( $localPath ) );
if ( $this->getConfig()->get( 'ResourceLoaderValidateStaticJS' ) ) {
// Static files don't really need to be checked as often; unlike
// on-wiki module they shouldn't change unexpectedly without
$style = $this->compileLessFile( $localPath, $context );
$this->hasGeneratedStyles = true;
} else {
- $style = file_get_contents( $localPath );
+ $style = $this->stripBom( file_get_contents( $localPath ) );
}
if ( $flip ) {
$localPath = $this->getLocalPath( $templatePath );
if ( file_exists( $localPath ) ) {
$content = file_get_contents( $localPath );
- $templates[$alias] = $content;
+ $templates[$alias] = $this->stripBom( $content );
} else {
$msg = __METHOD__ . ": template file not found: \"$localPath\"";
wfDebugLog( 'resourceloader', $msg );
}
return $templates;
}
+
+ /**
+ * Takes an input string and removes the UTF-8 BOM character if present
+ *
+ * We need to remove these after reading a file, because we concatenate our files and
+ * the BOM character is not valid in the middle of a string.
+ * We already assume UTF-8 everywhere, so this should be safe.
+ *
+ * @return string input minus the intial BOM char
+ */
+ protected function stripBom( $input ) {
+ if ( substr_compare( "\xef\xbb\xbf", $input, 0, 3 ) === 0 ) {
+ return substr( $input, 3 );
+ }
+ return $input;
+ }
}
$this->assertEquals( $rl->getTemplates(), $expected );
}
+
+ public function testBomConcatenation() {
+ $basePath = __DIR__ . '/../../data/css';
+ $testModule = new ResourceLoaderFileModule( [
+ 'localBasePath' => $basePath,
+ 'styles' => [ 'bom.css' ],
+ ] );
+ $this->assertEquals(
+ substr( file_get_contents( "$basePath/bom.css" ), 0, 10 ),
+ "\xef\xbb\xbf.efbbbf",
+ 'File has leading BOM'
+ );
+
+ $contextLtr = $this->getResourceLoaderContext( 'en', 'ltr' );
+ $this->assertEquals(
+ $testModule->getStyles( $contextLtr ),
+ [ 'all' => ".efbbbf_bom_char_at_start_of_file {}\n" ],
+ 'Leading BOM removed when concatenating files'
+ );
+ }
}