Overview

Packages

  • Data

Classes

  • Horde_Data
  • Horde_Data_Base
  • Horde_Data_Csv
  • Horde_Data_Exception
  • Horde_Data_Icalendar
  • Horde_Data_Imc
  • Horde_Data_Outlookcsv
  • Horde_Data_Translation
  • Horde_Data_Tsv
  • Horde_Data_Vcard
  • Horde_Data_Vnote
  • Horde_Data_Vtodo
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Horde_Data implementation for tab-separated data (TSV).
  4:  *
  5:  * Copyright 1999-2012 Horde LLC (http://www.horde.org/)
  6:  *
  7:  * See the enclosed file COPYING for license information (LGPL). If you
  8:  * did not receive this file, see http://www.horde.org/licenses/lgpl21.
  9:  *
 10:  * @author   Jan Schneider <jan@horde.org>
 11:  * @author   Chuck Hagenbuch <chuck@horde.org>
 12:  * @category Horde
 13:  * @package  Data
 14:  */
 15: class Horde_Data_Tsv extends Horde_Data_Base
 16: {
 17:     /**
 18:      * File extension.
 19:      *
 20:      * @var string
 21:      */
 22:     protected $_extension = 'tsv';
 23: 
 24:     /**
 25:      * MIME content type.
 26:      *
 27:      * @var string
 28:      */
 29:     protected $_contentType = 'text/tab-separated-values';
 30: 
 31:     /**
 32:      * Convert data file contents to list of data records.
 33:      *
 34:      * @param string $contents   Data file contents.
 35:      * @param boolean $header    True if a header row is present.
 36:      * @param string $delimiter  Field delimiter.
 37:      *
 38:      * @return array  List of data records.
 39:      */
 40:     public function importData($contents, $header = false, $delimiter = "\t")
 41:     {
 42:         if ($GLOBALS['injector']->getInstance('Horde_Session')->get('horde', 'import_data/format') == 'pine') {
 43:             $contents = preg_replace('/\n +/', '', $contents);
 44:         }
 45: 
 46:         $contents = explode("\n", $contents);
 47:         $data = array();
 48:         if ($header) {
 49:             $head = explode($delimiter, array_shift($contents));
 50:         }
 51: 
 52:         foreach ($contents as $line) {
 53:             if (trim($line) == '') {
 54:                 continue;
 55:             }
 56:             $line = explode($delimiter, $line);
 57:             if (!isset($head)) {
 58:                 $data[] = $line;
 59:             } else {
 60:                 $newline = array();
 61:                 for ($i = 0; $i < count($head); $i++) {
 62:                     $newline[$head[$i]] = empty($line[$i]) ? '' : $line[$i];
 63:                 }
 64:                 $data[] = $newline;
 65:             }
 66:         }
 67: 
 68:         return $data;
 69:     }
 70: 
 71:     /**
 72:      * Builds a TSV file from a given data structure and returns it as a
 73:      * string.
 74:      *
 75:      * @param array $data      A two-dimensional array containing the data set.
 76:      * @param boolean $header  If true, the rows of $data are associative
 77:      *                         arrays with field names as their keys.
 78:      *
 79:      * @return string  The TSV data.
 80:      */
 81:     public function exportData($data, $header = false)
 82:     {
 83:         if (!is_array($data) || count($data) == 0) {
 84:             return '';
 85:         }
 86:         $export = '';
 87:         $head = array_keys(current($data));
 88:         if ($header) {
 89:             $export = implode("\t", $head) . "\n";
 90:         }
 91:         foreach ($data as $row) {
 92:             foreach ($head as $key) {
 93:                 $cell = $row[$key];
 94:                 if (!empty($cell) || $cell === 0) {
 95:                     $export .= $cell;
 96:                 }
 97:                 $export .= "\t";
 98:             }
 99:             $export = substr($export, 0, -1) . "\n";
100:         }
101: 
102:         return $export;
103:     }
104: 
105:     /**
106:      * Builds a TSV file from a given data structure and triggers its download.
107:      * It DOES NOT exit the current script but only outputs the correct headers
108:      * and data.
109:      *
110:      * @param string $filename  The name of the file to be downloaded.
111:      * @param array $data       A two-dimensional array containing the data
112:      *                          set.
113:      * @param boolean $header   If true, the rows of $data are associative
114:      *                          arrays with field names as their keys.
115:      */
116:     public function exportFile($filename, $data, $header = false)
117:     {
118:         if (!isset($this->_browser)) {
119:             throw new LogicException('Missing browser parameter.');
120:         }
121: 
122:         $export = $this->exportData($data, $header);
123:         $this->_browser->downloadHeaders($filename, 'text/tab-separated-values', false, strlen($export));
124:         echo $export;
125:     }
126: 
127:     /**
128:      * Takes all necessary actions for the given import step, parameters and
129:      * form values and returns the next necessary step.
130:      *
131:      * @param integer $action  The current step. One of the IMPORT_* constants.
132:      * @param array $param     An associative array containing needed
133:      *                         parameters for the current step.
134:      *
135:      * @return mixed  Either the next step as an integer constant or imported
136:      *                data set after the final step.
137:      * @throws Horde_Data_Exception
138:      */
139:     public function nextStep($action, $param = array())
140:     {
141:         $session = $GLOBALS['injector']->getInstance('Horde_Session');
142: 
143:         switch ($action) {
144:         case Horde_Data::IMPORT_FILE:
145:             parent::nextStep($action, $param);
146: 
147:             $format = $session->get('horde', 'import_data/format');
148:             if (in_array($format, array('mulberry', 'pine'))) {
149:                 $filedata = $this->importFile($_FILES['import_file']['tmp_name']);
150: 
151:                 switch ($format) {
152:                 case 'mulberry':
153:                     $appKeys  = array('alias', 'name', 'email', 'company', 'workAddress', 'workPhone', 'homePhone', 'fax', 'notes');
154:                     $dataKeys = array(0, 1, 2, 3, 4, 5, 6, 7, 9);
155:                     break;
156: 
157:                 case 'pine':
158:                     $appKeys = array('alias', 'name', 'email', 'notes');
159:                     $dataKeys = array(0, 1, 2, 4);
160:                     break;
161:                 }
162: 
163:                 foreach ($appKeys as $key => $app) {
164:                     $map[$dataKeys[$key]] = $app;
165:                 }
166: 
167:                 $data = array();
168:                 foreach ($filedata as $row) {
169:                     $hash = array();
170: 
171:                     switch ($format) {
172:                     case 'mulberry':
173:                         if (preg_match("/^Grp:/", $row[0]) || empty($row[1])) {
174:                             continue;
175:                         }
176:                         $row[1] = preg_replace('/^([^,"]+),\s*(.*)$/', '$2 $1', $row[1]);
177:                         foreach ($dataKeys as $key) {
178:                             if (array_key_exists($key, $row)) {
179:                                 $hash[$key] = stripslashes(preg_replace('/\\\\r/', "\n", $row[$key]));
180:                             }
181:                         }
182:                         break;
183: 
184:                     case 'pine':
185:                         if (count($row) < 3 || preg_match("/^#DELETED/", $row[0]) || preg_match("/[()]/", $row[2])) {
186:                             continue;
187:                         }
188:                         $row[1] = preg_replace('/^([^,"]+),\s*(.*)$/', '$2 $1', $row[1]);
189:                         /* Address can be a full RFC822 address */
190:                         try {
191:                             $addr_arr = Horde_Mime_Address::parseAddressList($row[2]);
192:                         } catch (Horde_Mime_Exception $e) {
193:                             continue;
194:                         }
195:                         if (empty($addr_arr[0]->mailbox)) {
196:                             continue;
197:                         }
198:                         $row[2] = $addr_arr[0]->mailbox . '@' . $addr_arr[0]->host;
199:                         if (empty($row[1]) && !empty($addr_arr[0]->personal)) {
200:                             $row[1] = $addr_arr[0]->personal;
201:                         }
202:                         foreach ($dataKeys as $key) {
203:                             if (array_key_exists($key, $row)) {
204:                                 $hash[$key] = $row[$key];
205:                             }
206:                         }
207:                         break;
208:                     }
209: 
210:                     $data[] = $hash;
211:                 }
212: 
213:                 $session->set('horde', 'import_data/data', $data);
214:                 $session->set('horde', 'import_data/map', $map);
215: 
216:                 return $this->nextStep(Horde_Data::IMPORT_DATA, $param);
217:             }
218: 
219:             /* Move uploaded file so that we can read it again in the next step
220:                after the user gave some format details. */
221:             try {
222:                 $this->_browser->wasFileUploaded('import_file', Horde_Data_Translation::t("TSV file"));
223:             } catch (Horde_Browser_Exception $e) {
224:                 throw new Horde_Data_Exception($e);
225:             }
226:             $file_name = Horde_Util::getTempFile('import', false);
227:             if (!move_uploaded_file($_FILES['import_file']['tmp_name'], $file_name)) {
228:                 throw new Horde_Data_Exception(Horde_Data_Translation::t("The uploaded file could not be saved."));
229:             }
230:             $session->set('horde', 'import_data/file_name', $file_name);
231: 
232:             /* Read the file's first two lines to show them to the user. */
233:             $first_lines = '';
234:             if ($fp = @fopen($file_name, 'r')) {
235:                 $line_no = 1;
236:                 while (($line_no < 3) && ($line = fgets($fp))) {
237:                     $newline = Horde_String::length($line) > 100 ? "\n" : '';
238:                     $first_lines .= substr($line, 0, 100) . $newline;
239:                     ++$line_no;
240:                 }
241:             }
242:             $session->set('horde', 'import_data/first_lines', $first_lines);
243:             return Horde_Data::IMPORT_TSV;
244: 
245:         case Horde_Data::IMPORT_TSV:
246:             $session->set('horde', 'import_data/header', $this->_vars->header);
247:             $session->set('horde', 'import_data/data', $this->importFile($session->get('horde', 'import_data/file_name'), $session->get('horde', 'import_data/header')));
248:             $session->remove('horde', 'import_data/map');
249:             return Horde_Data::IMPORT_MAPPED;
250:         }
251: 
252:         return parent::nextStep($action, $param);
253:     }
254: 
255: }
256: 
API documentation generated by ApiGen