Skip to content

Commit

Permalink
MDL-72035 csvlib: Write BOM for Excel
Browse files Browse the repository at this point in the history
Add option to class csv_export_writer to prefix CSV file with UTF-8 byte
order mark (BOM).  This helps Microsoft Excel detect the file's character
encoding.
  • Loading branch information
leonstr committed Jun 30, 2021
1 parent 017dce9 commit 0eb14ac
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 3 deletions.
4 changes: 3 additions & 1 deletion lib/classes/text.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
* @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
Expand Down Expand Up @@ -626,7 +628,7 @@ public static function utf8_to_entities($str, $dec=false, $nonnum=false) {
* @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));
}
Expand Down
12 changes: 11 additions & 1 deletion lib/csvlib.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand All @@ -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) {
Expand All @@ -412,6 +417,7 @@ public function __construct($delimiter = 'comma', $enclosure = '"', $mimetype =
}
$this->filename = "Moodle-data-export.csv";
$this->mimetype = $mimetype;
$this->bom = $bom;
}

/**
Expand All @@ -437,6 +443,10 @@ public function add_data($row) {
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);
Expand Down
2 changes: 1 addition & 1 deletion report/completion/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@
$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 {
Expand Down

0 comments on commit 0eb14ac

Please sign in to comment.