[0005684] Attach documents: error message when attaching document on some php8 versio...
[fa-stable.git] / includes / ui / simple_crud_class.inc
1 <?php
2 /**********************************************************************
3     Copyright (C) FrontAccounting, LLC.
4         Released under the terms of the GNU General Public License, GPL, 
5         as published by the Free Software Foundation, either version 3 
6         of the License, or (at your option) any later version.
7     This program is distributed in the hope that it will be useful,
8     but WITHOUT ANY WARRANTY; without even the implied warranty of
9     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
10     See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
11 ***********************************************************************/
12 //
13 //      Template for simple table editors
14 //
15 class simple_crud {
16         var $name;
17         var $Mode;
18         var $selected_id;
19         var $_none = ''; // selector value when no item is selected
20         var $pre_handlers; // control buttons and related methods called before view display
21         var $views;
22         var $data = array();
23         var $fields;
24         var $tool_buttons;
25         var $options;
26         var $dec;
27         //
28         //
29         function __construct($name, $fields = null)
30         {
31                 $this->name = $name;
32                 $this->pre_handlers = array(
33                         'Edit' => '_edit',
34                         'Delete' => '_delete',
35                         'NEW' => '_edit',
36                         'ADD' => '_add',
37                         'UPDATE' => '_update',
38                         'RESET' => '_cancel',
39                         'CLONE' => '_cloning'
40                         );
41                 $this->views = array(
42                         '' => 'list_view',                      // default view
43                         'Edit' => 'editor_view',
44                         'Delete' => 'list_view',
45                         'NEW' => 'editor_view',
46                         'ADD' => 'editor_view',
47                         'UPDATE' => 'editor_view',
48                         'RESET' => 'list_view',
49                         'CLONE' => 'editor_view'
50                         );
51                 $this->tool_buttons['Edit'] =
52                         array(_('Edit'), _('Edit document line'), ICON_EDIT, '');
53                 $this->tool_buttons['Delete'] =
54                         array(_('Delete'), _('Remove line from document'), ICON_DELETE, '');
55                 $this->tool_buttons['UPDATE'] =
56                         array(_('Update'), _('Confirm changes'), ICON_UPDATE, '');
57                 $this->tool_buttons['RESET'] =
58                         array(_('Cancel'), _('Cancel changes'), ICON_CANCEL, '');
59
60                 $this->fields = $fields;
61                 $this->selected_id = $this->_none;
62         }
63         /*
64                 Input/output formatters - convert values between php/user domains.
65         */
66         function _format_input($value, $fmt)
67         {
68                 switch($fmt) {
69                         case 'stock':
70                                 $this->dec = get_qty_dec($value);
71                                 return $value;
72                         case 'price':
73                         case 'qty':
74                         case 'number':
75                                     return user_numeric($value);
76                         case 'percent':
77                                         return user_numeric($value)/100;
78                         case 'text':
79                         case 'date':
80                         default:
81                                 return $value;
82                 }
83         }
84         
85         function _format_output($value, $fmt)
86         {
87                 switch($fmt) {
88                         case 'price':
89                                 return price_format($value);
90                         case 'qty':
91                                 return number_format2($value, $this->dec);
92                         case 'number':
93                                 return number_format2($value);
94                         case 'percent':
95                                 return percent_format($value*100);
96                         case 'stock':
97                                 $this->dec = get_qty_dec($value); // retrieve dec for use in later qty fields
98                         case 'text':
99                         case 'date':
100                         default:
101                                 return $value;
102                 }
103         }
104
105         function _check_mode()
106         {
107                 global $Ajax;
108
109                 // list controls lookup
110                 foreach (array_keys($this->pre_handlers) as $m) {
111                         if (isset($_POST[$this->name.$m])) {
112                                 unset($_POST['_focus']); // focus on first form entry
113                                 $Ajax->activate($this->name.'_div');
114                                 $val = is_array($_POST[$this->name.$m]) ? key($_POST[$this->name.$m]) : null;
115                                 $this->selected_id = $val!==null ? @quoted_printable_decode($val) : $this->_none;
116                                 return $m;
117                         }
118                 }
119                 $mod = get_post($this->name.'Mode', '');
120                 if ($mod) {
121                         $val = @key($mod);
122                         $this->selected_id = $val!==null ? @quoted_printable_decode($val) : $this->_none;
123                         return $mod[$val];
124                 }
125                 return '';
126         }
127
128         //
129         //      Set record for edition
130         //
131         function _edit($mode)
132         {
133                 if ($this->Mode != $mode) {
134                         if ($this->selected_id != $this->_none) {
135                                 $this->data = $this->db_read();
136                         }
137                         $this->set_posts($this->data);
138                 }
139                 $this->Mode = $mode;
140         }
141         //
142         //      Update record after edition
143         //
144         function _update($mode)
145         {
146                 $this->get_posts();
147                 if ($this->update_check()) {
148                         if ($this->db_update()) {
149                                 $this->selected_id = $this->_none;
150                                 $this->Mode = '';
151                                 return;
152                         }
153                 }
154                 $this->Mode = $mode;
155         }
156         //
157         //      Add new record
158         //
159         function _add($mode)
160         {
161                 $this->get_posts();
162                 if ($this->insert_check()) {
163                         $this->db_insert();
164                         $this->_cancel();
165                         return;
166                 }
167                 $this->Mode = $mode;
168         }
169         //
170         //      Delete selected  record
171         //
172         function _delete()
173         {
174                 if ($this->delete_check())
175                         $this->db_delete();
176                 $this->_cancel();
177         }
178         //
179         //      Return to listing view
180         //
181         function _cancel()
182         {
183                 $this->selected_id = $this->_none;
184                 $this->db_cancel();
185                 $this->Mode = '';
186         }
187         //
188         // Clone record for new edition
189         //
190         function _cloning()
191         {
192                 $this->Mode = '';
193                 $this->_edit('Edit');
194                 $this->selected_id = $this->_none;
195         }
196         /*
197                 Generate form controls
198         */
199         function _bottom_controls()
200         {
201                 $clone = $this->selected_id != $this->_none;
202
203                 $title=false;
204                 $async='both';
205                 $base=$this->name;
206
207                 $cancel = $async;
208
209                 if ($async === 'both') {
210                         $async = 'default'; $cancel = 'cancel';
211                 } 
212                 elseif ($async === 'default')
213                         $cancel = true;
214                 elseif ($async === 'cancel')
215                         $async = true;
216                 echo "<center>";
217
218                 if ($this->Mode == '' || $this->Mode == 'RESET')
219                         submit("{$base}NEW", _("Add new"), true, $title, $async);
220                 else {
221                         if ($this->Mode == 'NEW' || $this->selected_id==$this->_none)
222                                 
223                                 submit("{$base}ADD", _("Add"), true, $title, $async);
224                         else {
225                                 submit("{$base}UPDATE[{$this->selected_id}]", _("Update"), true, _('Submit changes'), $async);
226                                 if ($clone) 
227                                         submit("{$base}CLONE[{$this->selected_id}]", _("Clone"), true, _('Edit new record with current data'), $async);
228                         }
229                         submit("{$base}RESET", _("Cancel"), true, _('Cancel edition'), $cancel);
230                 }
231                 echo "</center>";
232         }
233         //===========================================================================
234         // Public functions
235         //
236         
237         function tool_button($name, $selected_id=null, $params='')
238         {
239                 $b = $this->tool_buttons[$name];
240
241                 return "<td align='center' $params>"
242                         .button( "{$this->name}$name"
243                                 .($selected_id === null || $selected_id === $this->_none ? '': "[$selected_id]"),
244                                 $b[0], $b[1], $b[2], $b[3])."</td>";
245         }
246         
247         function set_posts()
248         {
249                 foreach($this->fields as $name => $fmt) {
250                         if (is_int($name)) {
251                                 $name = $fmt;
252                                 $fmt = array();
253                         }
254                         if is_string($fmt) {
255                             $fmt = array('fmt' => $fmt)
256                         }
257                         $post = isset($fmt['post']) ? $fmt['post'] : $name;
258                         $fld = isset($fmt['fld']) ? $fmt['fld'] : $name;
259
260                         $value = $this->selected_id == $this->_none ? (isset($fmt['dflt']) ? $fmt['dflt'] : null) :
261                                 (is_array($this->data) ? $this->data[$fld]: $this->data->$fld);
262
263                         $_POST[$post] = $this->_format_output($value, isset($fmt['fmt']) ? $fmt['fmt'] : null);
264                 }
265         }
266         //--------------------------
267         //
268         //      Get editor POST variables. 
269         //
270         function get_posts() {
271                 foreach ($this->fields as $name => $fmt) {
272                         if (is_int($name)) {
273                                 $name = $fmt;
274                                 $fmt = array();
275                         }
276                         if is_string($fmt) {
277                             $fmt = array('fmt' => $fmt)
278                         }
279                         $post = isset($fmt['post']) ? $fmt['post'] : $name;
280                         $fld = isset($fmt['fld']) ? $fmt['fld'] : $name;
281
282                         $value = $this->_format_input(@$_POST[$post], @$fmt['fmt']);
283                         if (is_array($this->data))
284                                 $this->data[$fld] = $value;
285                         else
286                                 $this->data->$fld = $value;
287                 }
288         }
289         //      Main function - display current CRUD editor content
290         //
291         function show()
292         {
293                 if (!isset($_POST[$this->name.'Mode']))
294                         $this->set_posts();
295
296                 $Mode = $this->_check_mode(true);
297                 div_start($this->name.'_div');
298
299                 if (array_key_exists($Mode, $this->pre_handlers)) {
300                         $fun = $this->pre_handlers[$Mode];
301                         $this->$fun($Mode);
302                 }
303
304                 if (isset($this->views[$this->Mode]))
305                         $this->{$this->views[$this->Mode]}();
306                 else
307                         $this->{$this->views['']}(); // default view
308
309                 $this->_bottom_controls();
310                 // this is needed only when we use temporary crud object together with ajax screen updates
311                 hidden($this->name.'Mode'.'['.$this->selected_id.']', $this->Mode);
312                 div_end();
313         }
314         
315         //===========================================================================
316         //      Database functions placeholders
317         
318         //
319         //      Read record from db for edition
320         //
321         function db_read() {
322                 display_notification(__FUNCTION__. ' is not defined...');
323                 return array();
324         }
325         //
326         //      Update record in db after edition
327         //
328         function db_update()
329         {
330                 $this->db_insert();
331         }
332         //
333         //      Delete record
334         //
335         function db_delete() {
336                 display_notification(__FUNCTION__. ' is not defined...');
337         }
338         //
339         //      Insert record
340         //
341         function db_insert()
342         {
343                 display_notification(__FUNCTION__. ' is not defined...');
344         }
345         //
346         //      Cancel edition
347         //      Optional things like focus set.
348         //
349         function db_cancel()
350         {
351         }
352
353
354         function delete_check() {
355                 display_notification(__FUNCTION__. ' is not defined...');
356                 return true; 
357         }
358
359         function insert_check() {
360                 return true;
361         }
362
363         function update_check() 
364         {
365                 return $this->insert_check(); 
366         }
367
368         //
369         //      Show database content in pager/table
370         //
371         function list_view() {
372                 display_notification(__FUNCTION__. ' is not defined...');
373         }
374
375         //
376         //      Show record editor screen content
377         //
378         function editor_view() {
379                 display_notification(__FUNCTION__. ' is not defined...');
380         }
381 };
382