75be75cc5318f3d08e5c34a2e93fe704bdaa28a9
[core.git] / framework / main / classes / file_directories / text / input / csv / class_CsvInputFile.php
1 <?php
2 // Own namespace
3 namespace CoreFramework\Filesystem\Input\Csv;
4
5 // Import framework stuff
6 use CoreFramework\Filesystem\Text\BaseInputTextFile;
7 use CoreFramework\Stream\Filesystem\CsvInputStreamer;
8
9 /**
10  * A CSV file input class for writing CSV files
11  *
12  * @author              Roland Haeder <webmaster@ship-simu.org>
13  * @version             0.0.0
14  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Core Developer Team
15  * @license             GNU GPL 3.0 or any newer version
16  * @link                http://www.ship-simu.org
17  *
18  * This program is free software: you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License as published by
20  * the Free Software Foundation, either version 3 of the License, or
21  * (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program. If not, see <http://www.gnu.org/licenses/>.
30  */
31 class CsvInputFile extends BaseInputTextFile implements CsvInputStreamer {
32         /**
33          * Protected constructor
34          *
35          * @return      void
36          */
37         protected function __construct () {
38                 // Call parent constructor
39                 parent::__construct(__CLASS__);
40         }
41
42         /**
43          * Creates an instance of this File class and prepares it for usage
44          *
45          * @param       $fileName               Name of the index file
46          * @return      $fileInstance   An instance of this File class
47          */
48         public final static function createCsvInputFile ($fileName) {
49                 // Get a new instance
50                 $fileInstance = new CsvInputFile();
51
52                 // Init this abstract file
53                 $fileInstance->initFile($fileName);
54
55                 // Return the prepared instance
56                 return $fileInstance;
57         }
58
59         /**
60          * Reads a line from CSV file and returns it as an indexed array. Please
61          * note that strings *must* be always in double-quotes, else any found
62          * column separators will be parsed or they may be interpreted incorrectly.
63          *
64          * @param       $columnSeparator        Character to use separting columns
65          * @return      $lineArray                      An indexed array with the read line
66          */
67         public function readCsvFileLine ($columnSeparator) {
68                 // Debug message
69                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] columnSeparator=%s - CALLED!', __METHOD__, __LINE__, $columnSeparator));
70
71                 // Read raw line
72                 $data = $this->getPointerInstance()->readLine();
73
74                 // Debug message
75                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] data()=%d', __METHOD__, __LINE__, strlen($data)));
76
77                 // Parse data
78                 $lineArray = $this->parseDataToIndexedArray($data, $columnSeparator);
79
80                 // Debug message
81                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] lineArray()=%d - EXIT!', __METHOD__, __LINE__, count($lineArray)));
82
83                 // Return it
84                 return $lineArray;
85         }
86
87         /**
88          * Parses given data into an array
89          *
90          * @param       $data                           Raw data e.g. returned from readLine()
91          * @param       $columnSeparator        Character to use separting columns
92          * @return      $lineArray                      An indexed array with the read line
93          */
94         private function parseDataToIndexedArray ($data, $columnSeparator) {
95                 // Debug message
96                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] data()=%d,columnSeparator=%s - CALLED!', __METHOD__, __LINE__, strlen($data), $columnSeparator));
97
98                 // Init return array
99                 $lineArray = array();
100
101                 // Whether the parser reads a quoted string (which may contain the column separator again)
102                 $isInQuotes = false;
103
104                 // Init column data
105                 $column = '';
106
107                 // Now parse the line
108                 for ($idx = 0; $idx < strlen($data); $idx++) {
109                         // "Cache" char
110                         $char = substr($data, $idx, 1);
111
112                         // Debug message
113                         //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] idx=%s,char=%s ...', __METHOD__, __LINE__, $idx, $char));
114
115                         // Is the column separator found and not within quotes?
116                         if (($isInQuotes === false) && ($char == $columnSeparator)) {
117                                 // Debug message
118                                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] Adding column=%s ...', __METHOD__, __LINE__, $column));
119
120                                 // Add this line to the array
121                                 array_push($lineArray, $column);
122
123                                 // Debug message
124                                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] lineArray()=%d - After add!', __METHOD__, __LINE__, count($lineArray)));
125
126                                 // Clear variable ...
127                                 $column = '';
128
129                                 // ... and skip it
130                                 continue;
131                         } elseif ($char == chr(34)) {
132                                 // Debug message
133                                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] column=%s ...', __METHOD__, __LINE__, $column));
134
135                                 // $column must be empty at this point if we are at starting quote
136                                 assert(($isInQuotes === true) || (empty($column)));
137
138                                 // Double-quote found, so flip variable
139                                 $isInQuotes = (!$isInQuotes);
140
141                                 // Debug message
142                                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] isInQuotes=%d ...', __METHOD__, __LINE__, intval($isInQuotes)));
143
144                                 // Skip double-quote (escaping of them is not yet supported)
145                                 continue;
146                         }
147
148                         // Debug message
149                         //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] Adding char=%s ...', __METHOD__, __LINE__, $idx, $char));
150
151                         // Add char to column
152                         $column .= $char;
153                 } // END - for
154
155                 // Is there something outstanding?
156                 if (!empty($column)) {
157                         // Debug message
158                         //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] Adding column=%s ...', __METHOD__, __LINE__, $column));
159
160                         // Then don't forget this. :-)
161                         array_push($lineArray, $column);
162
163                         // Debug message
164                         //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] lineArray()=%d - After add!', __METHOD__, __LINE__, count($lineArray)));
165                 } // END - if
166
167                 // Debug message
168                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('[%s:%d:] lineArray()=%d - EXIT!', __METHOD__, __LINE__, count($lineArray)));
169
170                 // Return it
171                 return $lineArray;
172         }
173
174 }
175