PluginProbe
Import Users from CSV / 1.2
Import Users from CSV v1.2
trunk 0.5.1 1.0.0 1.0.1 1.1 1.2 1.3 1.3.1
import-users-from-csv / class-readcsv.php

class-readcsv.php in Import Users from CSV 1.2, at class-readcsv.php

152 lines 3.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package uc_stock_update
4 * @version 6.x-2.0.2
5 * @licence GNU GPL v2
6 */
7 // $Id: ReadCSV.inc 3 2011-09-19 02:32:14Z david $
8 /**
9 * Use this to read CSV files. PHP's fgetcsv() does not conform to RFC
10 * 4180. In particular, it doesn't handle the correct quote escaping
11 * syntax. See http://tools.ietf.org/html/rfc4180
12 *
13 * David Houlder May 2010
14 * http://davidhoulder.com
15 */
16
17 class ReadCSV {
18 const field_start = 0;
19 const unquoted_field = 1;
20 const quoted_field = 2;
21 const found_quote = 3;
22 const found_cr_q = 4;
23 const found_cr = 5;
24
25 private $file;
26 private $sep;
27 // If $eof is TRUE, the next next_char() will return FALSE.
28 // Note that this is different to feof(), which is TRUE
29 // _after_ EOF is encountered.
30 private $eof;
31 private $nc;
32
33 /**
34 * @param $file_handle
35 * open file to read from
36 * @param $sep
37 * column separator character
38 * @param $skip
39 * initial character sequence to skip if found. e.g. UTF-8 byte-order mark
40 */
41 public function __construct($file_handle, $sep, $skip="") {
42 $this->file = $file_handle;
43 $this->sep = $sep;
44 $this->nc = fgetc($this->file);
45 // skip junk at start
46 for ($i=0; $i < strlen($skip); $i++) {
47 if ($this->nc !== $skip[$i])
48 break;
49 $this->nc = fgetc($this->file);
50 }
51 $this->eof = ($this->nc === FALSE);
52 }
53
54 private function next_char() {
55 $c = $this->nc;
56 $this->nc = fgetc($this->file);
57 $this->eof = ($this->nc === FALSE);
58 return $c;
59 }
60
61
62 /**
63 * Get next record from CSV file.
64 *
65 * @return
66 * array of strings from the next record in the CSV file, or NULL if
67 * there are no more records.
68 */
69 public function get_row() {
70 if ($this->eof)
71 return NULL;
72
73 $row=array();
74 $field="";
75 $state=self::field_start;
76
77 while (1) {
78 $char = $this->next_char();
79
80 if ($state == self::quoted_field) {
81 if ($char === FALSE) {
82 // EOF. (TODO: error case - no closing quote)
83 $row[]=$field;
84 return $row;
85 }
86 // Fall through to accumulate quoted chars in switch() {...}
87 } elseif ($char === FALSE || $char == "\n") {
88 // End of record.
89 // (TODO: error case if $state==self::field_start here - trailing comma)
90 $row[] = $field;
91 return $row;
92 } elseif ($char == "\r") {
93 // Possible start of \r\n line end, but might be just part of foo\rbar
94 $state = ($state == self::found_quote)? self::found_cr_q: self::found_cr;
95 continue;
96 } elseif ($char == $this->sep &&
97 ($state == self::field_start ||
98 $state == self::found_quote ||
99 $state == self::unquoted_field)) {
100 // End of current field, start of next field
101 $row[]=$field;
102 $field="";
103 $state=self::field_start;
104 continue;
105 }
106
107 switch ($state) {
108
109 case self::field_start:
110 if ($char == '"')
111 $state = self::quoted_field;
112 else {
113 $state = self::unquoted_field;
114 $field .= $char;
115 }
116 break;
117
118 case self::quoted_field:
119 if ($char == '"')
120 $state = self::found_quote;
121 else
122 $field .= $char;
123 break;
124
125 case self::unquoted_field:
126 $field .= $char;
127 // (TODO: error case if '"' in middle of unquoted field)
128 break;
129
130 case self::found_quote:
131 // Found '"' escape sequence
132 $field .= $char;
133 $state = self::quoted_field;
134 // (TODO: error case if $char!='"' - non-separator char after single quote)
135 break;
136
137 case self::found_cr:
138 // Lone \rX instead of \r\n. Treat as literal \rX. (TODO: error case?)
139 $field .= "\r".$char;
140 $state = self::unquoted_field;
141 break;
142
143 case self::found_cr_q:
144 // (TODO: error case: "foo"\rX instead of "foo"\r\n or "foo"\n)
145 $field .= "\r".$char;
146 $state = self::quoted_field;
147 break;
148 }
149 }
150 }
151 }
152