diff --git a/lib/csvlib.class.php b/lib/csvlib.class.php index fb380db3411..421058a4128 100644 --- a/lib/csvlib.class.php +++ b/lib/csvlib.class.php @@ -55,14 +55,7 @@ class csv_import_reader { * @var object file handle used during import */ var $_fp; - /** - * @var string delimiter of the records. - */ - var $_delimiter; - /** - * @var string enclosure of each field. - */ - var $_enclosure; + /** * Contructor * @@ -85,7 +78,7 @@ class csv_import_reader { * @param string $column_validation name of function for columns validation, must have one param $columns * @return bool false if error, count of data lines if ok; use get_error() to get error string */ - function load_csv_content(&$content, $encoding, $delimiter_name, $column_validation=null, $enclosure='"') { + function load_csv_content(&$content, $encoding, $delimiter_name, $column_validation=null) { global $USER, $CFG; $this->close(); @@ -96,56 +89,62 @@ class csv_import_reader { $content = textlib::trim_utf8_bom($content); // Fix mac/dos newlines $content = preg_replace('!\r\n?!', "\n", $content); - - $csv_delimiter = csv_import_reader::get_delimiter($delimiter_name); -// $csv_encode = csv_import_reader::get_encoded_delimiter($delimiter_name); - $this->_delimiter = $csv_delimiter; - $this->_enclosure = $enclosure; - - // create a temporary file and store the csv file there in csv file format. - $filename = $CFG->tempdir.'/csvimport/'.$this->_type.'/'.$USER->id.'/'.$this->_iid; - $fp = fopen($filename, 'w+'); - fwrite($fp, $content); - fseek($fp, 0); - // Create an array to store the imported data for error checking. - $columns = array(); - while ($fgetdata = fgetcsv($fp, 0, $csv_delimiter, $enclosure)) { - $columns[] = $fgetdata; - } - - $col_count = 0; - // process header - list of columns - if (!isset($columns[0])) { + // is there anyting in file? + $columns = strtok($content, "\n"); + if ($columns === false) { $this->_error = get_string('csvemptyfile', 'error'); - fclose($fp); - $this->cleanup(); return false; - } else { - $col_count = count($columns[0]); } - // column validation + $csv_delimiter = csv_import_reader::get_delimiter($delimiter_name); + $csv_encode = csv_import_reader::get_encoded_delimiter($delimiter_name); + + // process header - list of columns + $columns = explode($csv_delimiter, $columns); + $col_count = count($columns); + if ($col_count === 0) { + $this->_error = get_string('csvemptyfile', 'error'); + return false; + } + + foreach ($columns as $key=>$value) { + $columns[$key] = str_replace($csv_encode, $csv_delimiter, trim($value)); + } if ($column_validation) { - $result = $column_validation($columns[0]); + $result = $column_validation($columns); if ($result !== true) { $this->_error = $result; - fclose($fp); - $this->cleanup(); return false; } } + $this->_columns = $columns; // cached columns - $this->_columns = $columns[0]; // cached columns - // check to make sure that the data columns match up with the headers. - foreach ($columns as $rowdata) { - if (count($rowdata) !== $col_count) { + // open file for writing + $filename = $CFG->tempdir.'/csvimport/'.$this->_type.'/'.$USER->id.'/'.$this->_iid; + $fp = fopen($filename, "w"); + fwrite($fp, serialize($columns)."\n"); + + // again - do we have any data for processing? + $line = strtok("\n"); + $data_count = 0; + while ($line !== false) { + $line = explode($csv_delimiter, $line); + foreach ($line as $key=>$value) { + $line[$key] = str_replace($csv_encode, $csv_delimiter, trim($value)); + } + if (count($line) !== $col_count) { + // this is critical!! $this->_error = get_string('csvweirdcolumns', 'error'); fclose($fp); $this->cleanup(); return false; } + fwrite($fp, serialize($line)."\n"); + $data_count++; + $line = strtok("\n"); } - $datacount = count($columns); - return $datacount; + + fclose($fp); + return $data_count; } /** @@ -165,12 +164,12 @@ class csv_import_reader { return false; } $fp = fopen($filename, "r"); - $line = fgetcsv($fp, 0, $this->_delimiter, $this->_enclosure); + $line = fgets($fp); fclose($fp); if ($line === false) { return false; } - $this->_columns = $line; + $this->_columns = unserialize($line); return $this->_columns; } @@ -195,7 +194,7 @@ class csv_import_reader { return false; } //skip header - return (fgetcsv($this->_fp, 0, $this->_delimiter, $this->_enclosure) !== false); + return (fgets($this->_fp) !== false); } /** @@ -207,8 +206,8 @@ class csv_import_reader { if (empty($this->_fp) or feof($this->_fp)) { return false; } - if ($ser = fgetcsv($this->_fp, 0, $this->_delimiter, $this->_enclosure)) { - return $ser; + if ($ser = fgets($this->_fp)) { + return unserialize($ser); } else { return false; } diff --git a/lib/tests/csvtest.php b/lib/tests/csvtest.php deleted file mode 100644 index db7d1bdf1bb..00000000000 --- a/lib/tests/csvtest.php +++ /dev/null @@ -1,107 +0,0 @@ -. - -/** - * 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 csv_testcase extends advanced_testcase { - - var $testdata = array(); - var $teststring = ''; - var $teststring2 = ''; - var $teststring3 = ''; - - protected function setUp(){ - - $this->resetAfterTest(true); - - $csvdata = array(); - $csvdata[0][] = 'fullname'; - $csvdata[0][] = 'description of things'; - $csvdata[0][] = 'beer'; - $csvdata[1][] = 'William H T Macey'; - $csvdata[1][] = '
A field that contains "double quotes"
'; - $csvdata[1][] = 'Asahi'; - $csvdata[2][] = 'Phillip Jenkins'; - $csvdata[2][] = 'This field has
-Multiple lines
-and also contains "double quotes"
'; - $csvdata[2][] = 'Yebisu'; - $this->testdata = $csvdata; - - // Please note that each line needs a carriage return. - $this->teststring = 'fullname,"description of things",beer -"William H T Macey","A field that contains ""double quotes""
",Asahi -"Phillip Jenkins","This field has
-Multiple lines
-and also contains ""double quotes""
",Yebisu -'; - - $this->teststring2 = 'fullname,"description of things",beer -"Fred Flint","Find the stone inside the box
",Asahi,"A fourth column" -"Sarah Smith","How are the people next door?
,Yebisu,"Forget the next" -'; - } - - public function test_csv_functions() { - // Testing that the content is imported correctly. - $iid = csv_import_reader::get_new_iid('lib'); - $csvimport = new csv_import_reader($iid, 'lib'); - $contentcount = $csvimport->load_csv_content($this->teststring, 'utf-8', 'comma'); - $csvimport->init(); - $dataset = array(); - $dataset[] = $csvimport->get_columns(); - while ($record = $csvimport->next()) { - $dataset[] = $record; - } - $csvimport->cleanup(); - $csvimport->close(); - $this->assertEquals($dataset, $this->testdata); - - // Testing for the wrong count of columns. - $errortext = get_string('csvweirdcolumns', 'error'); - - $iid = csv_import_reader::get_new_iid('lib'); - $csvimport = new csv_import_reader($iid, 'lib'); - $contentcount = $csvimport->load_csv_content($this->teststring2, 'utf-8', 'comma'); - $importerror = $csvimport->get_error(); - $csvimport->cleanup(); - $csvimport->close(); - $this->assertEquals($importerror, $errortext); - - // Testing for empty content - $errortext = get_string('csvemptyfile', 'error'); - - $iid = csv_import_reader::get_new_iid('lib'); - $csvimport = new csv_import_reader($iid, 'lib'); - $contentcount = $csvimport->load_csv_content($this->teststring3, 'utf-8', 'comma'); - $importerror = $csvimport->get_error(); - $csvimport->cleanup(); - $csvimport->close(); - $this->assertEquals($importerror, $errortext); - } -} \ No newline at end of file