diff --git a/lib/classes/text.php b/lib/classes/text.php index 587873e31cd..1ae51cebb01 100644 --- a/lib/classes/text.php +++ b/lib/classes/text.php @@ -47,6 +47,8 @@ defined('MOODLE_INTERNAL') || die(); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class core_text { + /** @var string Byte order mark for UTF-8 */ + const UTF8_BOM = "\xef\xbb\xbf"; /** * @var string[] Array of strings representing Unicode non-characters @@ -626,7 +628,7 @@ class core_text { * @return string */ public static function trim_utf8_bom($str) { - $bom = "\xef\xbb\xbf"; + $bom = self::UTF8_BOM; if (strpos($str, $bom) === 0) { return substr($str, strlen($bom)); } diff --git a/lib/csvlib.class.php b/lib/csvlib.class.php index daf8da56f5b..00345879892 100644 --- a/lib/csvlib.class.php +++ b/lib/csvlib.class.php @@ -390,6 +390,10 @@ class csv_export_writer { * @var string $path The directory path for storing the temporary csv file. */ var $path; + /** + * @var boolean $bom If true prefix file with byte order mark (BOM). + */ + private $bom = false; /** * @var resource $fp File pointer for the csv file. */ @@ -401,8 +405,9 @@ class csv_export_writer { * @param string $delimiter The name of the character used to seperate fields. Supported types(comma, tab, semicolon, colon, cfg) * @param string $enclosure The character used for determining the enclosures. * @param string $mimetype Mime type of the file that we are exporting. + * @param boolean $bom If true, prefix file with byte order mark. */ - public function __construct($delimiter = 'comma', $enclosure = '"', $mimetype = 'application/download') { + public function __construct($delimiter = 'comma', $enclosure = '"', $mimetype = 'application/download', $bom = false) { $this->delimiter = $delimiter; // Check that the enclosure is a single character. if (strlen($enclosure) == 1) { @@ -412,6 +417,7 @@ class csv_export_writer { } $this->filename = "Moodle-data-export.csv"; $this->mimetype = $mimetype; + $this->bom = $bom; } /** @@ -437,6 +443,10 @@ class csv_export_writer { if(!isset($this->path)) { $this->set_temp_file_path(); $this->fp = fopen($this->path, 'w+'); + + if ($this->bom) { + fputs($this->fp, core_text::UTF8_BOM); + } } $delimiter = csv_import_reader::get_delimiter($this->delimiter); fputcsv($this->fp, $row, $delimiter, $this->csvenclosure); diff --git a/report/completion/index.php b/report/completion/index.php index 73380d7e011..7ca465d9b03 100644 --- a/report/completion/index.php +++ b/report/completion/index.php @@ -144,7 +144,7 @@ if ($csv) { $shortname = format_string($course->shortname, true, array('context' => $context)); $shortname = preg_replace('/[^a-z0-9-]/', '_',core_text::strtolower(strip_tags($shortname))); - $export = new csv_export_writer(); + $export = new csv_export_writer('comma', '"', 'application/download', $excel); $export->set_filename('completion-'.$shortname); } else {