[ Index ] |
|
Code source de Horde 3.1.3 |
1 <?php 2 /** 3 * Horde_Data implementation for comma-separated data (CSV). 4 * 5 * $Horde: framework/Data/Data/csv.php,v 1.30.10.8 2006/01/28 16:21:58 chuck Exp $ 6 * 7 * Copyright 1999-2006 Jan Schneider <jan@horde.org> 8 * 9 * See the enclosed file COPYING for license information (LGPL). If you did 10 * not receive this file, see http://www.fsf.org/copyleft/lgpl.html. 11 * 12 * @author Jan Schneider <jan@horde.org> 13 * @author Chuck Hagenbuch <chuck@horde.org> 14 * @since Horde 1.3 15 * @package Horde_Data 16 */ 17 class Horde_Data_csv extends Horde_Data { 18 19 var $_extension = 'csv'; 20 var $_contentType = 'text/comma-separated-values'; 21 22 /** 23 * Tries to discover the CSV file's parameters. 24 * 25 * @param string $filename The name of the file to investigate. 26 * 27 * @return array An associative array with the following possible keys: 28 * <pre> 29 * 'sep': The field separator 30 * 'quote': The quoting character 31 * 'fields': The number of fields (columns) 32 * </pre> 33 */ 34 function discoverFormat($filename) 35 { 36 @include_once('File/CSV.php'); 37 if (class_exists('File_CSV')) { 38 return File_CSV::discoverFormat($filename); 39 } else { 40 return array('sep' => ','); 41 } 42 } 43 44 /** 45 * Imports and parses a CSV file. 46 * 47 * @param string $filename The name of the file to parse. 48 * @param boolean $header Does the first line contain the field/column 49 * names? 50 * @param string $sep The field/column separator. 51 * @param string $quote The quoting character. 52 * @param integer $fields The number or fields/columns. 53 * @param string $charset The file's charset. @since Horde 3.1. 54 * @param string $crlf The file's linefeed characters. @since Horde 3.1. 55 * 56 * @return array A two-dimensional array of all imported data rows. If 57 * $header was true the rows are associative arrays with the 58 * field/column names as the keys. 59 */ 60 function importFile($filename, $header = false, $sep = '', $quote = '', 61 $fields = null, $import_mapping = array(), 62 $charset = null, $crlf = null) 63 { 64 @include_once('File/CSV.php'); 65 66 $data = array(); 67 68 /* File_CSV is present. */ 69 if (class_exists('File_CSV')) { 70 $this->_warnings = array(); 71 72 /* File_CSV is a bit picky at what parameter it expects. */ 73 $conf = array(); 74 if (!empty($quote)) { 75 $conf['quote'] = $quote; 76 } 77 if (empty($sep)) { 78 $conf['sep'] = ','; 79 } else { 80 $conf['sep'] = $sep; 81 } 82 if ($fields) { 83 $conf['fields'] = $fields; 84 } else { 85 return $data; 86 } 87 if (!empty($crlf)) { 88 $conf['crlf'] = $crlf; 89 } 90 91 /* Strip and keep the first line if it contains the field 92 * names. */ 93 if ($header) { 94 $head = File_CSV::read($filename, $conf); 95 if (is_a($head, 'PEAR_Error')) { 96 return $head; 97 } 98 if (!empty($charset)) { 99 $head = String::convertCharset($head, $charset, NLS::getCharset()); 100 } 101 } 102 103 while ($line = File_CSV::read($filename, $conf)) { 104 if (is_a($line, 'PEAR_Error')) { 105 return $line; 106 } 107 if (!empty($charset)) { 108 $line = String::convertCharset($line, $charset, NLS::getCharset()); 109 } 110 if (!isset($head)) { 111 $data[] = $line; 112 } else { 113 $newline = array(); 114 for ($i = 0; $i < count($head); $i++) { 115 if (isset($import_mapping[$head[$i]])) { 116 $head[$i] = $import_mapping[$head[$i]]; 117 } 118 $cell = $line[$i]; 119 $cell = preg_replace("/\"\"/", "\"", $cell); 120 $newline[$head[$i]] = empty($cell) ? '' : $cell; 121 } 122 $data[] = $newline; 123 } 124 } 125 126 $fp = File_CSV::getPointer($filename, $conf); 127 if ($fp && !is_a($fp, 'PEAR_Error')) { 128 rewind($fp); 129 } 130 131 $this->_warnings = File_CSV::warning(); 132 133 /* Fall back to fgetcsv(). */ 134 } else { 135 $fp = fopen($filename, 'r'); 136 if (!$fp) { 137 return false; 138 } 139 140 /* Strip and keep the first line if it contains the field 141 names. */ 142 if ($header) { 143 $head = fgetcsv($fp, 1024, $sep); 144 } 145 if (!empty($charset)) { 146 $head = String::convertCharset($head, $charset, NLS::getCharset()); 147 } 148 while ($line = fgetcsv($fp, 1024, $sep)) { 149 if (!empty($charset)) { 150 $line = String::convertCharset($line, $charset, NLS::getCharset()); 151 } 152 if (!isset($head)) { 153 $data[] = $line; 154 } else { 155 $newline = array(); 156 for ($i = 0; $i < count($head); $i++) { 157 if (isset($import_mapping[$head[$i]])) { 158 $head[$i] = $import_mapping[$head[$i]]; 159 } 160 $cell = $line[$i]; 161 $cell = preg_replace("/\"/", "\"\"", $cell); 162 $newline[$head[$i]] = empty($cell) ? '' : $cell; 163 } 164 $data[] = $newline; 165 } 166 } 167 168 fclose($fp); 169 } 170 return $data; 171 } 172 173 /** 174 * Builds a CSV file from a given data structure and returns it as a 175 * string. 176 * 177 * @param array $data A two-dimensional array containing the data set. 178 * @param boolean $header If true, the rows of $data are associative 179 * arrays with field names as their keys. 180 * 181 * @return string The CSV data. 182 */ 183 function exportData($data, $header = false, $export_mapping = array()) 184 { 185 if (!is_array($data) || count($data) == 0) { 186 return ''; 187 } 188 189 $export = ''; 190 $eol = "\n"; 191 $head = array_keys(current($data)); 192 if ($header) { 193 foreach ($head as $key) { 194 if (!empty($key)) { 195 if (isset($export_mapping[$key])) { 196 $key = $export_mapping[$key]; 197 } 198 $export .= '"' . $key . '"'; 199 } 200 $export .= ','; 201 } 202 $export = substr($export, 0, -1) . $eol; 203 } 204 205 foreach ($data as $row) { 206 foreach ($head as $key) { 207 $cell = $row[$key]; 208 if (!empty($cell) || $cell === 0) { 209 $export .= '"' . $cell . '"'; 210 } 211 $export .= ','; 212 } 213 $export = substr($export, 0, -1) . $eol; 214 } 215 216 return $export; 217 } 218 219 /** 220 * Builds a CSV file from a given data structure and triggers its 221 * download. It DOES NOT exit the current script but only outputs the 222 * correct headers and data. 223 * 224 * @param string $filename The name of the file to be downloaded. 225 * @param array $data A two-dimensional array containing the data 226 * set. 227 * @param boolean $header If true, the rows of $data are associative 228 * arrays with field names as their keys. 229 */ 230 function exportFile($filename, $data, $header = false, 231 $export_mapping = array()) 232 { 233 $export = $this->exportData($data, $header, $export_mapping); 234 $GLOBALS['browser']->downloadHeaders($filename, 'application/csv', false, strlen($export)); 235 echo $export; 236 } 237 238 /** 239 * Takes all necessary actions for the given import step, parameters and 240 * form values and returns the next necessary step. 241 * 242 * @param integer $action The current step. One of the IMPORT_* constants. 243 * @param array $param An associative array containing needed 244 * parameters for the current step. 245 * 246 * @return mixed Either the next step as an integer constant or imported 247 * data set after the final step. 248 */ 249 function nextStep($action, $param = array()) 250 { 251 switch ($action) { 252 case IMPORT_FILE: 253 $next_step = parent::nextStep($action, $param); 254 if (is_a($next_step, 'PEAR_Error')) { 255 return $next_step; 256 } 257 258 /* Move uploaded file so that we can read it again in the next 259 step after the user gave some format details. */ 260 $file_name = Horde::getTempFile('import', false); 261 if (!move_uploaded_file($_FILES['import_file']['tmp_name'], $file_name)) { 262 return PEAR::raiseError(_("The uploaded file could not be saved.")); 263 } 264 $_SESSION['import_data']['file_name'] = $file_name; 265 266 /* Try to discover the file format ourselves. */ 267 $conf = $this->discoverFormat($file_name); 268 if (!$conf) { 269 $conf = array('sep' => ','); 270 } 271 $_SESSION['import_data'] = array_merge($_SESSION['import_data'], $conf); 272 273 /* Check if charset was specified. */ 274 $_SESSION['import_data']['charset'] = Util::getFormData('charset'); 275 276 /* Read the file's first two lines to show them to the user. */ 277 $_SESSION['import_data']['first_lines'] = ''; 278 $fp = @fopen($file_name, 'r'); 279 if ($fp) { 280 $line_no = 1; 281 while ($line_no < 3 && $line = fgets($fp)) { 282 if (!empty($_SESSION['import_data']['charset'])) { 283 $line = String::convertCharset($line, $_SESSION['import_data']['charset'], NLS::getCharset()); 284 } 285 $newline = String::length($line) > 100 ? "\n" : ''; 286 $_SESSION['import_data']['first_lines'] .= substr($line, 0, 100) . $newline; 287 $line_no++; 288 } 289 } 290 return IMPORT_CSV; 291 292 case IMPORT_CSV: 293 $_SESSION['import_data']['header'] = Util::getFormData('header'); 294 $import_mapping = array(); 295 if (isset($param['import_mapping'])) { 296 $import_mapping = $param['import_mapping']; 297 } 298 $import_data = $this->importFile($_SESSION['import_data']['file_name'], 299 $_SESSION['import_data']['header'], 300 Util::getFormData('sep'), 301 Util::getFormData('quote'), 302 Util::getFormData('fields'), 303 $import_mapping, 304 $_SESSION['import_data']['charset'], 305 $_SESSION['import_data']['crlf']); 306 $_SESSION['import_data']['data'] = $import_data; 307 unset($_SESSION['import_data']['map']); 308 return IMPORT_MAPPED; 309 310 default: 311 return parent::nextStep($action, $param); 312 } 313 } 314 315 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 18:01:28 2007 | par Balluche grâce à PHPXref 0.7 |