root/trunk/patForms/Storage/CSV.php

Revision 297, 5.4 kB (checked in by schst, 3 years ago)

Test and fix the CSV storage container (closes ticket #177)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 <?php
2 /**
3  * patForms storage CSV
4  *
5  * $Id$
6  *
7  * @package        patForms
8  * @subpackage    Storage
9  * @author        Stephan Schmidt <schst@php-tools.net>
10  */
11  
12 /**
13  * patForms storage CSV
14  *
15  * Stores form data in a CSV file.
16  *
17  * @access        protected
18  * @package        patForms
19  * @subpackage    Storage
20  * @author        Stephan Schmidt <schst@php-tools.net>
21  * @license        LGPL, see license.txt for details
22  * @link        http://www.php-tools.net
23  */
24 class patForms_Storage_CSV extends patForms_Storage
25 {
26    /**
27     * storage file
28     *
29     * @access    private
30     * @var        string
31     */
32     var $_file;
33
34    /**
35     * csv delimeter
36     *
37     * @access    private
38     * @var        string
39     */
40     var $_delimeter    = ';';
41
42    /**
43     * linefeed
44     *
45     * @access    private
46     * @var        string
47     */
48     var $_linefeed = "\n";
49
50    /**
51     * field order
52     *
53     * @access    private
54     * @var        string
55     */
56     var $_fieldOrder = array();
57
58    /**
59     * set the storage file
60     *
61     * @access    public
62     * @param    string        filename
63     */
64     function setFile($file)
65     {
66         $this->_file = $file;
67         if (file_exists($file) && !is_writable($file)) {
68             return patErrorManager::raiseError(PATFORMS_STORAGE_ERROR_STORAGE_INVALID, 'Could not open ' . $file . ' for writing.');
69         }
70     }
71
72    /**
73     * set the delimeter
74     *
75     * @access    public
76     * @param    string        delimeter
77     */
78     function setDelimeter($delimeter)
79     {
80         $this->_delimeter = $delimeter;
81     }
82
83    /**
84     * set the field order
85     *
86     * @access    public
87     * @param    array        field order
88     */
89     function setFieldOrder($fields)
90     {
91         $this->_fieldOrder = $fields;
92     }
93
94    /**
95     * get an entry
96     *
97     * This tries to find an entry in the storage container
98     * that matches the current data that has been set in the
99     * form and populates the form with the data of this
100     * entry
101     *
102     * @access    public
103     * @param    object patForms        patForms object that should be stored
104     * @return    boolean                true on success
105     */
106     function loadEntry(&$form)
107     {
108         $values  = $form->getValues();
109         $primary = $this->getPrimary( $values );
110
111         /**
112          * primary key not given
113          */
114         if (empty($primary)) {
115             return array();
116         }
117
118         /**
119          * entry does not exists
120          */
121         if (!$data = $this->_entryExists($primary)) {
122             return array();
123         }
124
125         $values = array();
126         foreach ($this->_fieldOrder as $pos => $field) {
127             if (isset($data[$pos])) {
128                 $values[$field] = $data[$pos];
129             }
130         }
131         $form->setValues($values);
132         return true;
133     }
134
135    /**
136     * adds an entry to the storage
137     *
138     * The entry will be appended at the end of the file.
139     *
140     * @abstract
141     * @param    object patForms        patForms object that should be stored
142     * @return    boolean                true on success
143     */
144     function _addEntry( &$form )
145     {
146         $values = $form->getValues();
147         
148         $line    = array();
149         foreach ($this->_fieldOrder as $field) {
150             if (!isset( $values[$field])) {
151                 $value = '';
152             } else {
153                 $value = $values[$field];
154             }           
155             array_push($line, '"'.addslashes( $value ).'"');
156         }
157         $line = implode( $this->_delimeter, $line ) . $this->_linefeed;
158         $fp   = @fopen($this->_file, 'a');
159         if (!$fp) {
160             return patErrorManager::raiseError(PATFORMS_STORAGE_ERROR_STORAGE_INVALID, 'Could not open the supplied csv file.');
161         }
162         
163         flock($fp, LOCK_EX);
164         fwrite($fp, $line);
165         flock($fp, LOCK_UN);
166         fclose($fp);
167         return true;
168     }
169
170    /**
171     * updates an entry in the storage
172     *
173     * Implement this in the concrete storage container.
174     *
175     * @abstract
176     * @param    object patForms        patForms object that should be stored
177     * @return    boolean                true on success
178     */
179     function _updateEntry(&$form, $primary)
180     {
181         $keys = array();
182         foreach ($primary as $key => $value) {
183             $pos = array_search($key, $this->_fieldOrder);
184             $keys[$pos] = $value;
185         }
186     
187         $fp = @fopen($this->_file, 'r');
188         if (!$fp) {
189             return patErrorManager::raiseError( PATFORMS_STORAGE_ERROR_STORAGE_INVALID, 'Could not open the supplied csv file.' );
190         }
191         
192         $new = array();
193         flock($fp, LOCK_SH);
194         while (!feof($fp)) {
195             $tmp = fgetcsv($fp, 10000, $this->_delimeter);
196
197             foreach ($keys as $key => $value) {
198                 if ($tmp[$key] != $value) {
199                     array_push($new, $tmp);
200                     continue;
201                 }
202                 
203                 $line = array();
204                 $values = $form->getValues();
205                 foreach ($this->_fieldOrder as $field) {
206                     if (!isset( $values[$field])) {
207                         $value = '';
208                     } else {
209                         $value = $values[$field];
210                     }
211                     array_push($line, $value);
212                 }
213                 array_push($new, $line);
214             }
215         }
216         flock($fp, LOCK_UN);
217         fclose($fp);
218
219         /**
220          * rewrite the file
221          */
222         $fp = @fopen($this->_file, 'w');
223         if(!$fp) {
224             return patErrorManager::raiseError( PATFORMS_STORAGE_ERROR_STORAGE_INVALID, 'Could not open the supplied csv file.' );
225         }
226         
227         flock($fp, LOCK_EX);
228
229         foreach ($new as $line) {
230             if (empty($line)) {
231                 continue;
232             }
233             for ($i = 0; $i < count( $line ); $i++) {
234                 $line[$i] = '"'.addslashes($line[$i]).'"';
235             }
236             $line = implode($this->_delimeter, $line) . $this->_linefeed;
237             fwrite($fp, $line);
238         }
239
240         flock($fp, LOCK_UN);
241         fclose($fp);
242         return true;
243     }
244
245    /**
246     * check, whether an entry exists
247     *
248     * @access    private
249     * @param    array
250     */
251     function _entryExists( $primary )
252     {
253         $keys = array();
254         foreach ($primary as $key => $value) {
255             $pos = array_search($key, $this->_fieldOrder);
256             $keys[$pos] = $value;
257         }
258     
259         $fp = @fopen($this->_file, 'r');
260         if (!$fp) {
261             return false;
262         }
263         flock($fp, LOCK_SH);
264         while(!feof($fp)) {
265             $tmp = fgetcsv( $fp, 10000, $this->_delimeter );
266             foreach ($keys as $key => $value) {
267                 if ($tmp[$key] != $value) {
268                     continue;
269                 }
270
271                 flock($fp, LOCK_UN);
272                 fclose($fp);
273                 return $tmp;
274             }
275         }
276         flock($fp, LOCK_UN);
277         fclose($fp);
278         return false;
279     }
280 }
281 ?>
Note: See TracBrowser for help on using the browser.