mirror of
https://github.com/moodle/moodle.git
synced 2025-06-03 14:46:35 +02:00
MDL-34074 - lib - Creation of a csv upload class which is FRC 4180 compliant and the alteration of various files around Moodle to use this class.
This commit is contained in:
parent
55a568fa7d
commit
9a5abd1b70
@ -148,23 +148,13 @@ function user_download_csv($fields) {
|
||||
global $CFG, $SESSION, $DB;
|
||||
|
||||
require_once($CFG->dirroot.'/user/profile/lib.php');
|
||||
require_once($CFG->libdir . '/csvlib.class.php');
|
||||
|
||||
$filename = clean_filename(get_string('users').'.csv');
|
||||
$filename = clean_filename(get_string('users'));
|
||||
|
||||
header("Content-Type: application/download\n");
|
||||
header("Content-Disposition: attachment; filename=\"$filename\"");
|
||||
header("Expires: 0");
|
||||
header("Cache-Control: must-revalidate,post-check=0,pre-check=0");
|
||||
header("Pragma: public");
|
||||
|
||||
$delimiter = get_string('listsep', 'langconfig');
|
||||
$encdelim = '&#'.ord($delimiter);
|
||||
|
||||
$row = array();
|
||||
foreach ($fields as $fieldname) {
|
||||
$row[] = str_replace($delimiter, $encdelim, $fieldname);
|
||||
}
|
||||
echo implode($delimiter, $row)."\n";
|
||||
$csvexport = new csv_export_writer();
|
||||
$csvexport->set_filename($filename);
|
||||
$csvexport->add_data($fields);
|
||||
|
||||
foreach ($SESSION->bulk_users as $userid) {
|
||||
$row = array();
|
||||
@ -172,10 +162,19 @@ function user_download_csv($fields) {
|
||||
continue;
|
||||
}
|
||||
profile_load_data($user);
|
||||
$userprofiledata = array();
|
||||
foreach ($fields as $field=>$unused) {
|
||||
$row[] = str_replace($delimiter, $encdelim, $user->$field);
|
||||
// Custom user profile textarea fields come in an array
|
||||
// The first element is the text and the second is the format.
|
||||
// We only take the text.
|
||||
if (is_array($user->$field)) {
|
||||
$userprofiledata[] = reset($user->$field);
|
||||
} else {
|
||||
$userprofiledata[] = $user->$field;
|
||||
}
|
||||
}
|
||||
echo implode($delimiter, $row)."\n";
|
||||
$csvexport->add_data($userprofiledata);
|
||||
}
|
||||
$csvexport->download_file();
|
||||
die;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
require_once($CFG->dirroot.'/grade/export/lib.php');
|
||||
require_once($CFG->libdir . '/csvlib.class.php');
|
||||
|
||||
class grade_export_txt extends grade_export {
|
||||
|
||||
@ -54,46 +55,25 @@ class grade_export_txt extends grade_export {
|
||||
$strgrades = get_string('grades');
|
||||
$profilefields = grade_helper::get_user_profile_fields($this->course->id, $this->usercustomfields);
|
||||
|
||||
switch ($this->separator) {
|
||||
case 'comma':
|
||||
$separator = ",";
|
||||
break;
|
||||
case 'tab':
|
||||
default:
|
||||
$separator = "\t";
|
||||
}
|
||||
|
||||
// Print header to force download
|
||||
if (strpos($CFG->wwwroot, 'https://') === 0) { //https sites - watch out for IE! KB812935 and KB316431
|
||||
@header('Cache-Control: max-age=10');
|
||||
@header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT');
|
||||
@header('Pragma: ');
|
||||
} else { //normal http - prevent caching at all cost
|
||||
@header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=0');
|
||||
@header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT');
|
||||
@header('Pragma: no-cache');
|
||||
}
|
||||
header("Content-Type: application/download\n");
|
||||
$shortname = format_string($this->course->shortname, true, array('context' => context_course::instance($this->course->id)));
|
||||
$downloadfilename = clean_filename("$shortname $strgrades");
|
||||
header("Content-Disposition: attachment; filename=\"$downloadfilename.txt\"");
|
||||
$csvexport = new csv_export_writer($this->separator);
|
||||
$csvexport->set_filename($downloadfilename);
|
||||
|
||||
// Print names of all the fields
|
||||
$fieldfullnames = array();
|
||||
$exporttitle = array();
|
||||
foreach ($profilefields as $field) {
|
||||
$fieldfullnames[] = $field->fullname;
|
||||
$exporttitle[] = $field->fullname;
|
||||
}
|
||||
echo implode($separator, $fieldfullnames);
|
||||
|
||||
// Add a feedback column.
|
||||
foreach ($this->columns as $grade_item) {
|
||||
echo $separator.$this->format_column_name($grade_item);
|
||||
|
||||
// Add a feedback column.
|
||||
$exporttitle[] = $this->format_column_name($grade_item);
|
||||
if ($this->export_feedback) {
|
||||
echo $separator.$this->format_column_name($grade_item, true);
|
||||
$exporttitle[] = $this->format_column_name($grade_item, true);
|
||||
}
|
||||
}
|
||||
echo "\n";
|
||||
$csvexport->add_data($exporttitle);
|
||||
|
||||
// Print all the lines of data.
|
||||
$geub = new grade_export_update_buffer();
|
||||
@ -103,31 +83,29 @@ class grade_export_txt extends grade_export {
|
||||
$gui->init();
|
||||
while ($userdata = $gui->next_user()) {
|
||||
|
||||
$exportdata = array();
|
||||
$user = $userdata->user;
|
||||
|
||||
$items = array();
|
||||
foreach ($profilefields as $field) {
|
||||
$fieldvalue = grade_helper::get_user_field_value($user, $field);
|
||||
$items[] = $fieldvalue;
|
||||
$exportdata[] = $fieldvalue;
|
||||
}
|
||||
echo implode($separator, $items);
|
||||
|
||||
foreach ($userdata->grades as $itemid => $grade) {
|
||||
if ($export_tracking) {
|
||||
$status = $geub->track($grade);
|
||||
}
|
||||
|
||||
echo $separator.$this->format_grade($grade);
|
||||
$exportdata[] = $this->format_grade($grade);
|
||||
|
||||
if ($this->export_feedback) {
|
||||
echo $separator.$this->format_feedback($userdata->feedbacks[$itemid]);
|
||||
$exportdata[] = $this->format_feedback($userdata->feedbacks[$itemid]);
|
||||
}
|
||||
}
|
||||
echo "\n";
|
||||
$csvexport->add_data($exportdata);
|
||||
}
|
||||
$gui->close();
|
||||
$geub->close();
|
||||
|
||||
$csvexport->download_file();
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
@ -279,6 +279,7 @@ class csv_import_reader {
|
||||
case 'tab': return "\t";
|
||||
case 'cfg': if (isset($CFG->CSV_DELIMITER)) { return $CFG->CSV_DELIMITER; } // no break; fall back to comma
|
||||
case 'comma': return ',';
|
||||
default : return ','; // If anything else comes in, default to comma.
|
||||
}
|
||||
}
|
||||
|
||||
@ -319,3 +320,193 @@ class csv_import_reader {
|
||||
return $iiid;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Utitily class for exporting of CSV files.
|
||||
* @copyright 2012 Adrian Greeve
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @package core
|
||||
* @category csv
|
||||
*/
|
||||
class csv_export_writer {
|
||||
/**
|
||||
* @var string $delimiter The name of the delimiter. Supported types(comma, tab, semicolon, colon, cfg)
|
||||
*/
|
||||
var $delimiter;
|
||||
/**
|
||||
* @var string $csvenclosure How fields with spaces and commas are enclosed.
|
||||
*/
|
||||
var $csvenclosure;
|
||||
/**
|
||||
* @var string $mimetype Mimetype of the file we are exporting.
|
||||
*/
|
||||
var $mimetype;
|
||||
/**
|
||||
* @var string $filename The filename for the csv file to be downloaded.
|
||||
*/
|
||||
var $filename;
|
||||
/**
|
||||
* @var string $path The directory path for storing the temporary csv file.
|
||||
*/
|
||||
var $path;
|
||||
/**
|
||||
* @var resource $fp File pointer for the csv file.
|
||||
*/
|
||||
protected $fp;
|
||||
|
||||
/**
|
||||
* Constructor for the csv export reader
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
public function __construct($delimiter = 'comma', $enclosure = '"', $mimetype = 'application/download') {
|
||||
$this->delimiter = $delimiter;
|
||||
// Check that the enclosure is a single character.
|
||||
if (strlen($enclosure) == 1) {
|
||||
$this->csvenclosure = $enclosure;
|
||||
} else {
|
||||
$this->csvenclosure = '"';
|
||||
}
|
||||
$this->filename = "Moodle-data-export.csv";
|
||||
$this->mimetype = $mimetype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the file path to the temporary file.
|
||||
*/
|
||||
protected function set_temp_file_path() {
|
||||
global $USER, $CFG;
|
||||
make_temp_directory('csvimport/' . $USER->id);
|
||||
$path = $CFG->tempdir . '/csvimport/' . $USER->id. '/' . $this->filename;
|
||||
// Check to see if the file exists, if so delete it.
|
||||
if (file_exists($path)) {
|
||||
unlink($path);
|
||||
}
|
||||
$this->path = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add data to the temporary file in csv format
|
||||
*
|
||||
* @param array $row An array of values.
|
||||
*/
|
||||
public function add_data($row) {
|
||||
if(!isset($this->path)) {
|
||||
$this->set_temp_file_path();
|
||||
$this->fp = fopen($this->path, 'w+');
|
||||
}
|
||||
$delimiter = csv_import_reader::get_delimiter($this->delimiter);
|
||||
fputcsv($this->fp, $row, $delimiter, $this->csvenclosure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Echos or returns a csv data line by line for displaying.
|
||||
*
|
||||
* @param bool $return Set to true to return a string with the csv data.
|
||||
* @return string csv data.
|
||||
*/
|
||||
public function print_csv_data($return = false) {
|
||||
fseek($this->fp, 0);
|
||||
$returnstring = '';
|
||||
while (($content = fgets($this->fp)) !== false) {
|
||||
if (!$return){
|
||||
echo $content;
|
||||
} else {
|
||||
$returnstring .= $content;
|
||||
}
|
||||
}
|
||||
if ($return) {
|
||||
return $returnstring;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the filename for the uploaded csv file
|
||||
*
|
||||
* @param string $dataname The name of the module.
|
||||
* @param string $extenstion File extension for the file.
|
||||
*/
|
||||
public function set_filename($dataname, $extension = '.csv') {
|
||||
$filename = clean_filename($dataname);
|
||||
$filename .= clean_filename('-' . gmdate("Ymd_Hi"));
|
||||
$filename .= clean_filename("-{$this->delimiter}_separated");
|
||||
$filename .= $extension;
|
||||
$this->filename = $filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output file headers to initialise the download of the file.
|
||||
*/
|
||||
protected function send_header() {
|
||||
global $CFG;
|
||||
if (strpos($CFG->wwwroot, 'https://') === 0) { //https sites - watch out for IE! KB812935 and KB316431
|
||||
header('Cache-Control: max-age=10');
|
||||
header('Pragma: ');
|
||||
} else { //normal http - prevent caching at all cost
|
||||
header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=0');
|
||||
header('Pragma: no-cache');
|
||||
}
|
||||
header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT');
|
||||
header("Content-Type: $this->mimetype\n");
|
||||
header("Content-Disposition: attachment; filename=\"$this->filename\"");
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the csv file.
|
||||
*/
|
||||
public function download_file() {
|
||||
$this->send_header();
|
||||
$this->print_csv_data();
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a file for downloading an array into a deliminated format.
|
||||
* This function is useful if you are happy with the defaults and all of your
|
||||
* information is in one array.
|
||||
*
|
||||
* @param string $filename The filename of the file being created.
|
||||
* @param array $records An array of information to be converted.
|
||||
* @param string $delimiter The name of the delimiter. Supported types(comma, tab, semicolon, colon, cfg)
|
||||
* @param string $enclosure How speical fields are enclosed.
|
||||
*/
|
||||
public static function download_array($filename, array &$records, $delimiter = 'comma', $enclosure='"') {
|
||||
$csvdata = new csv_export_writer($delimiter, $enclosure);
|
||||
$csvdata->set_filename($filename);
|
||||
foreach ($records as $row) {
|
||||
$csvdata->add_data($row);
|
||||
}
|
||||
$csvdata->download_file();
|
||||
}
|
||||
|
||||
/**
|
||||
* This will convert an array of values into a deliminated string.
|
||||
* Like the above function, this is for convenience.
|
||||
*
|
||||
* @param array $records An array of information to be converted.
|
||||
* @param string $delimiter The name of the delimiter. Supported types(comma, tab, semicolon, colon, cfg)
|
||||
* @param string $enclosure How speical fields are enclosed.
|
||||
* @param bool $return If true will return a string with the csv data.
|
||||
* @return string csv data.
|
||||
*/
|
||||
public static function print_array(array &$records, $delimiter = 'comma', $enclosure = '"', $return = false) {
|
||||
$csvdata = new csv_export_writer($delimiter, $enclosure);
|
||||
foreach ($records as $row) {
|
||||
$csvdata->add_data($row);
|
||||
}
|
||||
$data = $csvdata->print_csv_data($return);
|
||||
if ($return) {
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that everything is closed when we are finished.
|
||||
*/
|
||||
public function __destruct() {
|
||||
fclose($this->fp);
|
||||
unlink($this->path);
|
||||
}
|
||||
}
|
||||
|
@ -1557,18 +1557,19 @@ class table_ods_export_format extends table_spreadsheet_export_format_parent {
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class table_text_export_format_parent extends table_default_export_format_parent {
|
||||
protected $seperator = "\t";
|
||||
protected $seperator = "tab";
|
||||
protected $mimetype = 'text/tab-separated-values';
|
||||
protected $ext = '.txt';
|
||||
protected $myexporter;
|
||||
|
||||
public function __construct() {
|
||||
$this->myexporter = new csv_export_writer($this->seperator, '"', $this->mimetype);
|
||||
}
|
||||
|
||||
public function start_document($filename) {
|
||||
$this->filename = $filename . $this->ext;
|
||||
header('Content-Type: ' . $this->mimetype . '; charset=UTF-8');
|
||||
header('Content-Disposition: attachment; filename="' . $this->filename . '"');
|
||||
header('Expires: 0');
|
||||
header('Cache-Control: must-revalidate,post-check=0,pre-check=0');
|
||||
header('Pragma: public');
|
||||
$this->filename = $filename;
|
||||
$this->documentstarted = true;
|
||||
$this->myexporter->set_filename($filename, $this->ext);
|
||||
}
|
||||
|
||||
public function start_table($sheettitle) {
|
||||
@ -1576,19 +1577,20 @@ class table_text_export_format_parent extends table_default_export_format_parent
|
||||
}
|
||||
|
||||
public function output_headers($headers) {
|
||||
echo $this->format_row($headers);
|
||||
$this->myexporter->add_data($headers);
|
||||
}
|
||||
|
||||
public function add_data($row) {
|
||||
echo $this->format_row($row);
|
||||
$this->myexporter->add_data($row);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function finish_table() {
|
||||
echo "\n\n";
|
||||
//nothing to do here
|
||||
}
|
||||
|
||||
public function finish_document() {
|
||||
$this->myexporter->download_file();
|
||||
exit;
|
||||
}
|
||||
|
||||
@ -1612,24 +1614,23 @@ class table_text_export_format_parent extends table_default_export_format_parent
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class table_tsv_export_format extends table_text_export_format_parent {
|
||||
protected $seperator = "\t";
|
||||
protected $seperator = "tab";
|
||||
protected $mimetype = 'text/tab-separated-values';
|
||||
protected $ext = '.txt';
|
||||
}
|
||||
|
||||
|
||||
require_once($CFG->libdir . '/csvlib.class.php');
|
||||
/**
|
||||
* @package moodlecore
|
||||
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class table_csv_export_format extends table_text_export_format_parent {
|
||||
protected $seperator = ",";
|
||||
protected $seperator = "comma";
|
||||
protected $mimetype = 'text/csv';
|
||||
protected $ext = '.csv';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @package moodlecore
|
||||
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
|
||||
|
75
lib/tests/csvclass_test.php
Normal file
75
lib/tests/csvclass_test.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Tests csv import and export functions
|
||||
*
|
||||
* @package core
|
||||
* @category phpunit
|
||||
* @copyright 2012 Adrian Greeve
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once($CFG->dirroot . '/lib/csvlib.class.php');
|
||||
|
||||
class csvclass_testcase extends advanced_testcase {
|
||||
|
||||
var $testdata = array();
|
||||
var $teststring = '';
|
||||
|
||||
protected function setUp(){
|
||||
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
$csvdata = array();
|
||||
$csvdata[0][] = 'fullname';
|
||||
$csvdata[0][] = 'description of things';
|
||||
$csvdata[0][] = 'beer';
|
||||
$csvdata[1][] = 'William B Stacey';
|
||||
$csvdata[1][] = '<p>A field that contains "double quotes"</p>';
|
||||
$csvdata[1][] = 'Asahi';
|
||||
$csvdata[2][] = 'Phillip Jenkins';
|
||||
$csvdata[2][] = '<p>This field has </p>
|
||||
<p>Multiple lines</p>
|
||||
<p>and also contains "double quotes"</p>';
|
||||
$csvdata[2][] = 'Yebisu';
|
||||
$this->testdata = $csvdata;
|
||||
|
||||
// Please note that each line needs a carriage return.
|
||||
$this->teststring = 'fullname,"description of things",beer
|
||||
"William B Stacey","<p>A field that contains ""double quotes""</p>",Asahi
|
||||
"Phillip Jenkins","<p>This field has </p>
|
||||
<p>Multiple lines</p>
|
||||
<p>and also contains ""double quotes""</p>",Yebisu
|
||||
';
|
||||
}
|
||||
|
||||
public function test_csv_functions() {
|
||||
$csvexport = new csv_export_writer();
|
||||
$csvexport->set_filename('unittest');
|
||||
foreach ($this->testdata as $data) {
|
||||
$csvexport->add_data($data);
|
||||
}
|
||||
$csvoutput = $csvexport->print_csv_data(true);
|
||||
$this->assertEquals($csvoutput, $this->teststring);
|
||||
|
||||
$test_data = csv_export_writer::print_array($this->testdata, 'comma', '"', true);
|
||||
$this->assertEquals($test_data, $this->teststring);
|
||||
}
|
||||
}
|
@ -2646,37 +2646,19 @@ function data_supports($feature) {
|
||||
* @param bool $return
|
||||
* @return string|void
|
||||
*/
|
||||
function data_export_csv($export, $delimiter_name, $dataname, $count, $return=false) {
|
||||
function data_export_csv($export, $delimiter_name, $database, $count, $return=false) {
|
||||
global $CFG;
|
||||
require_once($CFG->libdir . '/csvlib.class.php');
|
||||
$delimiter = csv_import_reader::get_delimiter($delimiter_name);
|
||||
$filename = clean_filename("{$dataname}-{$count}_record");
|
||||
|
||||
$filename = $database . '-' . $count . '-record';
|
||||
if ($count > 1) {
|
||||
$filename .= 's';
|
||||
}
|
||||
$filename .= clean_filename('-' . gmdate("Ymd_Hi"));
|
||||
$filename .= clean_filename("-{$delimiter_name}_separated");
|
||||
$filename .= '.csv';
|
||||
if (empty($return)) {
|
||||
header("Content-Type: application/download\n");
|
||||
header("Content-Disposition: attachment; filename=\"$filename\"");
|
||||
header('Expires: 0');
|
||||
header('Cache-Control: must-revalidate,post-check=0,pre-check=0');
|
||||
header('Pragma: public');
|
||||
if ($return) {
|
||||
return csv_export_writer::print_array($export, $delimiter_name, '"', true);
|
||||
} else {
|
||||
csv_export_writer::download_array($filename, $export, $delimiter_name);
|
||||
}
|
||||
$encdelim = '&#' . ord($delimiter) . ';';
|
||||
$returnstr = '';
|
||||
foreach($export as $row) {
|
||||
foreach($row as $key => $column) {
|
||||
$row[$key] = str_replace($delimiter, $encdelim, $column);
|
||||
}
|
||||
$returnstr .= implode($delimiter, $row) . "\n";
|
||||
}
|
||||
if (empty($return)) {
|
||||
echo $returnstr;
|
||||
return;
|
||||
}
|
||||
return $returnstr;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user