1: <?php
2: 3: 4: 5: 6: 7: 8: 9:
10:
11: namespace Kotchasan;
12:
13: 14: 15: 16: 17: 18: 19:
20: class Csv
21: {
22: 23: 24:
25: private $charset;
26: 27: 28:
29: private $columns;
30: 31: 32:
33: private $datas;
34: 35: 36:
37: private $keys;
38:
39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49:
50: public static function import($csv, $columns, $keys = null, $charset = 'Windows-874')
51: {
52: $obj = new static();
53: $obj->columns = $columns;
54: $obj->datas = array();
55: $obj->charset = strtoupper($charset);
56: $obj->keys = $keys;
57: $obj->read($csv, array($obj, 'importDatas'), array_keys($columns));
58: return $obj->datas;
59: }
60:
61: 62: 63: 64: 65: 66: 67: 68: 69: 70:
71: public static function read($file, $onRow, $headers = array())
72: {
73: $columns = array();
74: $f = @fopen($file, 'r');
75: if ($f) {
76: while (($data = fgetcsv($f)) !== false) {
77: if (empty($columns)) {
78: if (is_array($headers)) {
79: if (count($headers) != count($data)) {
80: throw new \Exception('Invalid CSV Header');
81: } else {
82:
83: $data[0] = self::removeBomUtf8($data[0]);
84:
85: foreach ($headers as $k) {
86: if (!in_array($k, $data)) {
87: throw new \Exception('Invalid CSV Header');
88: }
89: }
90: }
91: }
92: $columns = $data;
93: } else {
94: $items = array();
95: foreach ($data as $k => $v) {
96: if (isset($columns[$k])) {
97: $items[$columns[$k]] = $v;
98: }
99: }
100: call_user_func($onRow, $items);
101: }
102: }
103: fclose($f);
104: }
105: }
106:
107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117:
118: public static function send($file, $header, $datas, $charset = 'Windows-874')
119: {
120:
121: header('Content-Type: text/csv;charset="'.$charset.'"');
122: header('Content-Disposition: attachment;filename="'.$file.'.csv"');
123:
124: $f = fopen('php://output', 'w');
125:
126: $charset = strtoupper($charset);
127:
128: if (!empty($header)) {
129: fputcsv($f, self::convert($header, $charset));
130: }
131:
132: foreach ($datas as $item) {
133: fputcsv($f, self::convert($item, $charset));
134: }
135:
136: fclose($f);
137:
138: return true;
139: }
140:
141: 142: 143: 144: 145: 146: 147:
148: private static function removeBomUtf8($s)
149: {
150: if (substr($s, 0, 3) == chr(hexdec('EF')).chr(hexdec('BB')).chr(hexdec('BF'))) {
151: return substr($s, 3);
152: } else {
153: return $s;
154: }
155: }
156:
157: 158: 159: 160: 161: 162: 163: 164:
165: private static function convert($datas, $charset)
166: {
167: if ($charset != 'UTF-8') {
168: foreach ($datas as $k => $v) {
169: if ($v != '') {
170: $datas[$k] = iconv('UTF-8', $charset.'//IGNORE', $v);
171: }
172: }
173: }
174: return $datas;
175: }
176:
177: 178: 179: 180: 181:
182: private function importDatas($data)
183: {
184: $save = array();
185: foreach ($this->columns as $key => $type) {
186: $save[$key] = null;
187: if (isset($data[$key])) {
188: if (is_array($type)) {
189: $save[$key] = call_user_func($type, $data[$key]);
190: } elseif ($type == 'int') {
191: $save[$key] = (int) $data[$key];
192: } elseif ($type == 'double') {
193: $save[$key] = (float) $data[$key];
194: } elseif ($type == 'float') {
195: $save[$key] = (float) $data[$key];
196: } elseif ($type == 'number') {
197: $save[$key] = preg_replace('/[^0-9]+/', '', $data[$key]);
198: } elseif ($type == 'en') {
199: $save[$key] = preg_replace('/[^a-zA-Z0-9]+/', '', $data[$key]);
200: } elseif ($type == 'date') {
201: if (preg_match('/^([0-9]{4,4})[\-\/]([0-9]{1,2})[\-\/]([0-9]{1,2})$/', $data[$key], $match)) {
202: $save[$key] = "$match[1]-$match[2]-$match[3]";
203: } elseif (preg_match('/^([0-9]{1,2})[\-\/]([0-9]{1,2})[\-\/]([0-9]{4,4})$/', $data[$key], $match)) {
204: $save[$key] = "$match[3]-$match[2]-$match[1]";
205: }
206: } elseif ($type == 'datetime') {
207: if (preg_match('/^([0-9]{4,4})[\-\/]([0-9]{2,2})[\-\/]([0-9]{2,2})\s([0-9]{2,2}):([0-9]{2,2}):([0-9]{2,2})$/', $data[$key])) {
208: $save[$key] = $data[$key];
209: } elseif (preg_match('/^([0-9]{2,2})[\-\/]([0-9]{2,2})[\-\/]([0-9]{4,4})\s(([0-9]{2,2}):([0-9]{2,2}):([0-9]{2,2}))$/', $data[$key], $match)) {
210: $save[$key] = "$match[4]-$match[3]-$match[2] $match[1]";
211: }
212: } elseif ($type == 'time') {
213: if (preg_match('/^([0-9]{2,2}):([0-9]{2,2}):([0-9]{2,2})$/', $data[$key])) {
214: $save[$key] = $data[$key];
215: }
216: } elseif ($this->charset == 'UTF-8') {
217: $save[$key] = \Kotchasan\Text::topic($data[$key]);
218: } else {
219: $save[$key] = iconv($this->charset, 'UTF-8', \Kotchasan\Text::topic($data[$key]));
220: }
221: }
222: }
223: if (empty($this->keys)) {
224: $this->datas[] = $save;
225: } else {
226: $keys = '';
227: foreach ($this->keys as $item) {
228: if ($save[$item] !== null && $save[$item] !== '') {
229: $keys .= $save[$item];
230: } else {
231: $save = null;
232: continue;
233: }
234: }
235: if (!empty($save) && !isset($this->datas[$keys])) {
236: $this->datas[$keys] = $save;
237: }
238: }
239: }
240: }
241: