dolibarr  16.0.5
actions_addupdatedelete.inc.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2017-2019 Laurent Destailleur <eldy@users.sourceforge.net>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <https://www.gnu.org/licenses/>.
16  * or see https://www.gnu.org/
17  */
18 
25 // $action or $cancel must be defined
26 // $object must be defined
27 // $permissiontoadd must be defined
28 // $permissiontodelete must be defined
29 // $backurlforlist must be defined
30 // $backtopage may be defined
31 // $noback may be defined
32 // $triggermodname may be defined
33 
34 $hidedetails = isset($hidedetails) ? $hidedetails : '';
35 $hidedesc = isset($hidedesc) ? $hidedesc : '';
36 $hideref = isset($hideref) ? $hideref : '';
37 
38 
39 if (!empty($permissionedit) && empty($permissiontoadd)) {
40  $permissiontoadd = $permissionedit; // For backward compatibility
41 }
42 
43 if ($cancel) {
44  /*var_dump($cancel);var_dump($backtopage);var_dump($backtopageforcancel);exit;*/
45  if (!empty($backtopageforcancel)) {
46  header("Location: ".$backtopageforcancel);
47  exit;
48  } elseif (!empty($backtopage)) {
49  header("Location: ".$backtopage);
50  exit;
51  }
52  $action = '';
53 }
54 
55 
56 // Action to add record
57 if ($action == 'add' && !empty($permissiontoadd)) {
58  foreach ($object->fields as $key => $val) {
59  if ($object->fields[$key]['type'] == 'duration') {
60  if (GETPOST($key.'hour') == '' && GETPOST($key.'min') == '') {
61  continue; // The field was not submited to be saved
62  }
63  } else {
64  if (!GETPOSTISSET($key)) {
65  continue; // The field was not submited to be saved
66  }
67  }
68  // Ignore special fields
69  if (in_array($key, array('rowid', 'entity', 'import_key'))) {
70  continue;
71  }
72  if (in_array($key, array('date_creation', 'tms', 'fk_user_creat', 'fk_user_modif'))) {
73  if (!in_array(abs($val['visible']), array(1, 3))) {
74  continue; // Only 1 and 3 that are case to create
75  }
76  }
77 
78  // Set value to insert
79  if (in_array($object->fields[$key]['type'], array('text', 'html'))) {
80  $value = GETPOST($key, 'restricthtml');
81  } elseif ($object->fields[$key]['type'] == 'date') {
82  $value = dol_mktime(12, 0, 0, GETPOST($key.'month', 'int'), GETPOST($key.'day', 'int'), GETPOST($key.'year', 'int')); // for date without hour, we use gmt
83  } elseif ($object->fields[$key]['type'] == 'datetime') {
84  $value = dol_mktime(GETPOST($key.'hour', 'int'), GETPOST($key.'min', 'int'), GETPOST($key.'sec', 'int'), GETPOST($key.'month', 'int'), GETPOST($key.'day', 'int'), GETPOST($key.'year', 'int'), 'tzuserrel');
85  } elseif ($object->fields[$key]['type'] == 'duration') {
86  $value = 60 * 60 * GETPOST($key.'hour', 'int') + 60 * GETPOST($key.'min', 'int');
87  } elseif (preg_match('/^(integer|price|real|double)/', $object->fields[$key]['type'])) {
88  $value = price2num(GETPOST($key, 'alphanohtml')); // To fix decimal separator according to lang setup
89  } elseif ($object->fields[$key]['type'] == 'boolean') {
90  $value = ((GETPOST($key) == '1' || GETPOST($key) == 'on') ? 1 : 0);
91  } elseif ($object->fields[$key]['type'] == 'reference') {
92  $tmparraykey = array_keys($object->param_list);
93  $value = $tmparraykey[GETPOST($key)].','.GETPOST($key.'2');
94  } else {
95  if ($key == 'lang') {
96  $value = GETPOST($key, 'aZ09') ?GETPOST($key, 'aZ09') : "";
97  } else {
98  $value = GETPOST($key, 'alphanohtml');
99  }
100  }
101  if (preg_match('/^integer:/i', $object->fields[$key]['type']) && $value == '-1') {
102  $value = ''; // This is an implicit foreign key field
103  }
104  if (!empty($object->fields[$key]['foreignkey']) && $value == '-1') {
105  $value = ''; // This is an explicit foreign key field
106  }
107 
108  //var_dump($key.' '.$value.' '.$object->fields[$key]['type']);
109  $object->$key = $value;
110  if (!empty($val['notnull']) && $val['notnull'] > 0 && $object->$key == '' && isset($val['default']) && $val['default'] == '(PROV)') {
111  $object->$key = '(PROV)';
112  }
113  if (!empty($val['notnull']) && $val['notnull'] > 0 && $object->$key == '' && !isset($val['default'])) {
114  $error++;
115  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv($val['label'])), null, 'errors');
116  }
117 
118  // Validation of fields values
119  if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2 || !empty($conf->global->MAIN_ACTIVATE_VALIDATION_RESULT)) {
120  if (!$error && !empty($val['validate']) && is_callable(array($object, 'validateField'))) {
121  if (!$object->validateField($object->fields, $key, $value)) {
122  $error++;
123  }
124  }
125  }
126  }
127 
128  // Fill array 'array_options' with data from add form
129  if (!$error) {
130  $ret = $extrafields->setOptionalsFromPost(null, $object, '', 1);
131  if ($ret < 0) {
132  $error++;
133  }
134  }
135 
136  if (!$error) {
137  $result = $object->create($user);
138  if ($result > 0) {
139  // Creation OK
140  if (isModEnabled('categorie') && method_exists($object, 'setCategories')) {
141  $categories = GETPOST('categories', 'array:int');
142  $object->setCategories($categories);
143  }
144  $urltogo = $backtopage ? str_replace('__ID__', $result, $backtopage) : $backurlforlist;
145  $urltogo = preg_replace('/--IDFORBACKTOPAGE--/', $object->id, $urltogo); // New method to autoselect project after a New on another form object creation
146 
147  if (empty($noback)) {
148  header("Location: " . $urltogo);
149  exit;
150  }
151  } else {
152  $error++;
153  // Creation KO
154  if (!empty($object->errors)) {
155  setEventMessages(null, $object->errors, 'errors');
156  } else {
157  setEventMessages($object->error, null, 'errors');
158  }
159  $action = 'create';
160  }
161  } else {
162  $action = 'create';
163  }
164 }
165 
166 // Action to update record
167 if ($action == 'update' && !empty($permissiontoadd)) {
168  foreach ($object->fields as $key => $val) {
169  // Check if field was submited to be edited
170  if ($object->fields[$key]['type'] == 'duration') {
171  if (!GETPOSTISSET($key.'hour') || !GETPOSTISSET($key.'min')) {
172  continue; // The field was not submited to be saved
173  }
174  } elseif ($object->fields[$key]['type'] == 'boolean') {
175  if (!GETPOSTISSET($key)) {
176  $object->$key = 0; // use 0 instead null if the field is defined as not null
177  continue;
178  }
179  } else {
180  if (!GETPOSTISSET($key)) {
181  continue; // The field was not submited to be saved
182  }
183  }
184  // Ignore special fields
185  if (in_array($key, array('rowid', 'entity', 'import_key'))) {
186  continue;
187  }
188  if (in_array($key, array('date_creation', 'tms', 'fk_user_creat', 'fk_user_modif'))) {
189  if (!in_array(abs($val['visible']), array(1, 3, 4))) {
190  continue; // Only 1 and 3 and 4, that are cases to update
191  }
192  }
193 
194  // Set value to update
195  if (preg_match('/^(text|html)/', $object->fields[$key]['type'])) {
196  $tmparray = explode(':', $object->fields[$key]['type']);
197  if (!empty($tmparray[1])) {
198  $value = GETPOST($key, $tmparray[1]);
199  } else {
200  $value = GETPOST($key, 'restricthtml');
201  }
202  } elseif ($object->fields[$key]['type'] == 'date') {
203  $value = dol_mktime(12, 0, 0, GETPOST($key.'month', 'int'), GETPOST($key.'day', 'int'), GETPOST($key.'year', 'int')); // for date without hour, we use gmt
204  } elseif ($object->fields[$key]['type'] == 'datetime') {
205  $value = dol_mktime(GETPOST($key.'hour', 'int'), GETPOST($key.'min', 'int'), GETPOST($key.'sec', 'int'), GETPOST($key.'month', 'int'), GETPOST($key.'day', 'int'), GETPOST($key.'year', 'int'), 'tzuserrel');
206  } elseif ($object->fields[$key]['type'] == 'duration') {
207  if (GETPOST($key.'hour', 'int') != '' || GETPOST($key.'min', 'int') != '') {
208  $value = 60 * 60 * GETPOST($key.'hour', 'int') + 60 * GETPOST($key.'min', 'int');
209  } else {
210  $value = '';
211  }
212  } elseif (preg_match('/^(integer|price|real|double)/', $object->fields[$key]['type'])) {
213  $value = price2num(GETPOST($key, 'alphanohtml')); // To fix decimal separator according to lang setup
214  } elseif ($object->fields[$key]['type'] == 'boolean') {
215  $value = ((GETPOST($key, 'aZ09') == 'on' || GETPOST($key, 'aZ09') == '1') ? 1 : 0);
216  } elseif ($object->fields[$key]['type'] == 'reference') {
217  $value = array_keys($object->param_list)[GETPOST($key)].','.GETPOST($key.'2');
218  } else {
219  if ($key == 'lang') {
220  $value = GETPOST($key, 'aZ09');
221  } else {
222  $value = GETPOST($key, 'alphanohtml');
223  }
224  }
225  if (preg_match('/^integer:/i', $object->fields[$key]['type']) && $value == '-1') {
226  $value = ''; // This is an implicit foreign key field
227  }
228  if (!empty($object->fields[$key]['foreignkey']) && $value == '-1') {
229  $value = ''; // This is an explicit foreign key field
230  }
231 
232  $object->$key = $value;
233  if ($val['notnull'] > 0 && $object->$key == '' && is_null($val['default'])) {
234  $error++;
235  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv($val['label'])), null, 'errors');
236  }
237 
238  // Validation of fields values
239  if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2 || !empty($conf->global->MAIN_ACTIVATE_VALIDATION_RESULT)) {
240  if (!$error && !empty($val['validate']) && is_callable(array($object, 'validateField'))) {
241  if (!$object->validateField($object->fields, $key, $value)) {
242  $error++;
243  }
244  }
245  }
246 
247  if (isModEnabled('categorie')) {
248  $categories = GETPOST('categories', 'array');
249  if (method_exists($object, 'setCategories')) {
250  $object->setCategories($categories);
251  }
252  }
253  }
254 
255  // Fill array 'array_options' with data from add form
256  if (!$error) {
257  $ret = $extrafields->setOptionalsFromPost(null, $object, '@GETPOSTISSET');
258  if ($ret < 0) {
259  $error++;
260  }
261  }
262 
263  if (!$error) {
264  $result = $object->update($user);
265  if ($result > 0) {
266  $action = 'view';
267  $urltogo = $backtopage ? str_replace('__ID__', $result, $backtopage) : $backurlforlist;
268  $urltogo = preg_replace('/--IDFORBACKTOPAGE--/', $object->id, $urltogo); // New method to autoselect project after a New on another form object creation
269  if ($urltogo && !$noback) {
270  header("Location: " . $urltogo);
271  exit;
272  }
273  } else {
274  $error++;
275  // Creation KO
276  setEventMessages($object->error, $object->errors, 'errors');
277  $action = 'edit';
278  }
279  } else {
280  $action = 'edit';
281  }
282 }
283 
284 // Action to update one extrafield
285 if ($action == "update_extras" && !empty($permissiontoadd)) {
286  $object->fetch(GETPOST('id', 'int'));
287 
288  $attributekey = GETPOST('attribute', 'alpha');
289  $attributekeylong = 'options_'.$attributekey;
290 
291  if (GETPOSTISSET($attributekeylong.'day') && GETPOSTISSET($attributekeylong.'month') && GETPOSTISSET($attributekeylong.'year')) {
292  // This is properties of a date
293  $object->array_options['options_'.$attributekey] = dol_mktime(GETPOST($attributekeylong.'hour', 'int'), GETPOST($attributekeylong.'min', 'int'), GETPOST($attributekeylong.'sec', 'int'), GETPOST($attributekeylong.'month', 'int'), GETPOST($attributekeylong.'day', 'int'), GETPOST($attributekeylong.'year', 'int'));
294  //var_dump(dol_print_date($object->array_options['options_'.$attributekey]));exit;
295  } else {
296  $object->array_options['options_'.$attributekey] = GETPOST($attributekeylong, 'alpha');
297  }
298 
299  $result = $object->insertExtraFields(empty($triggermodname) ? '' : $triggermodname, $user);
300  if ($result > 0) {
301  setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
302  $action = 'view';
303  } else {
304  $error++;
305  setEventMessages($object->error, $object->errors, 'errors');
306  $action = 'edit_extras';
307  }
308 }
309 
310 // Action to delete
311 if ($action == 'confirm_delete' && !empty($permissiontodelete)) {
312  if (!($object->id > 0)) {
313  dol_print_error('', 'Error, object must be fetched before being deleted');
314  exit;
315  }
316 
317  $result = $object->delete($user);
318 
319  if ($result > 0) {
320  // Delete OK
321  setEventMessages("RecordDeleted", null, 'mesgs');
322 
323  if (empty($noback)) {
324  header("Location: " . $backurlforlist);
325  exit;
326  }
327  } else {
328  $error++;
329  if (!empty($object->errors)) {
330  setEventMessages(null, $object->errors, 'errors');
331  } else {
332  setEventMessages($object->error, null, 'errors');
333  }
334  }
335 
336  $action = '';
337 }
338 
339 // Remove a line
340 if ($action == 'confirm_deleteline' && $confirm == 'yes' && !empty($permissiontoadd)) {
341  if (method_exists($object, 'deleteline')) {
342  $result = $object->deleteline($user, $lineid); // For backward compatibility
343  } else {
344  $result = $object->deleteLine($user, $lineid);
345  }
346  if ($result > 0) {
347  // Define output language
348  $outputlangs = $langs;
349  $newlang = '';
350  if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
351  $newlang = GETPOST('lang_id', 'aZ09');
352  }
353  if ($conf->global->MAIN_MULTILANGS && empty($newlang) && is_object($object->thirdparty)) {
354  $newlang = $object->thirdparty->default_lang;
355  }
356  if (!empty($newlang)) {
357  $outputlangs = new Translate("", $conf);
358  $outputlangs->setDefaultLang($newlang);
359  }
360  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
361  if (method_exists($object, 'generateDocument')) {
362  $ret = $object->fetch($object->id); // Reload to get new records
363  $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
364  }
365  }
366 
367  setEventMessages($langs->trans('RecordDeleted'), null, 'mesgs');
368 
369  if (empty($noback)) {
370  header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
371  exit;
372  }
373  } else {
374  $error++;
375  setEventMessages($object->error, $object->errors, 'errors');
376  }
377  $action = '';
378 }
379 
380 // Action validate object
381 if ($action == 'confirm_validate' && $confirm == 'yes' && $permissiontoadd) {
382  $result = $object->validate($user);
383  if ($result >= 0) {
384  // Define output language
385  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
386  if (method_exists($object, 'generateDocument')) {
387  $outputlangs = $langs;
388  $newlang = '';
389  if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
390  $newlang = GETPOST('lang_id', 'aZ09');
391  }
392  if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) {
393  $newlang = $object->thirdparty->default_lang;
394  }
395  if (!empty($newlang)) {
396  $outputlangs = new Translate("", $conf);
397  $outputlangs->setDefaultLang($newlang);
398  }
399 
400  $ret = $object->fetch($id); // Reload to get new records
401 
402  $model = $object->model_pdf;
403 
404  $retgen = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
405  if ($retgen < 0) {
406  setEventMessages($object->error, $object->errors, 'warnings');
407  }
408  }
409  }
410  } else {
411  $error++;
412  setEventMessages($object->error, $object->errors, 'errors');
413  }
414  $action = '';
415 }
416 
417 // Action close object
418 if ($action == 'confirm_close' && $confirm == 'yes' && $permissiontoadd) {
419  $result = $object->cancel($user);
420  if ($result >= 0) {
421  // Define output language
422  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
423  if (method_exists($object, 'generateDocument')) {
424  $outputlangs = $langs;
425  $newlang = '';
426  if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
427  $newlang = GETPOST('lang_id', 'aZ09');
428  }
429  if ($conf->global->MAIN_MULTILANGS && empty($newlang)) {
430  $newlang = $object->thirdparty->default_lang;
431  }
432  if (!empty($newlang)) {
433  $outputlangs = new Translate("", $conf);
434  $outputlangs->setDefaultLang($newlang);
435  }
436  $model = $object->model_pdf;
437  $ret = $object->fetch($id); // Reload to get new records
438 
439  $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
440  }
441  }
442  } else {
443  $error++;
444  setEventMessages($object->error, $object->errors, 'errors');
445  }
446  $action = '';
447 }
448 
449 // Action setdraft object
450 if ($action == 'confirm_setdraft' && $confirm == 'yes' && $permissiontoadd) {
451  $result = $object->setDraft($user);
452  if ($result >= 0) {
453  // Nothing else done
454  } else {
455  $error++;
456  setEventMessages($object->error, $object->errors, 'errors');
457  }
458  $action = '';
459 }
460 
461 // Action reopen object
462 if ($action == 'confirm_reopen' && $confirm == 'yes' && $permissiontoadd) {
463  $result = $object->reopen($user);
464  if ($result >= 0) {
465  // Define output language
466  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
467  if (method_exists($object, 'generateDocument')) {
468  $outputlangs = $langs;
469  $newlang = '';
470  if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
471  $newlang = GETPOST('lang_id', 'aZ09');
472  }
473  if ($conf->global->MAIN_MULTILANGS && empty($newlang)) {
474  $newlang = $object->thirdparty->default_lang;
475  }
476  if (!empty($newlang)) {
477  $outputlangs = new Translate("", $conf);
478  $outputlangs->setDefaultLang($newlang);
479  }
480  $model = $object->model_pdf;
481  $ret = $object->fetch($id); // Reload to get new records
482 
483  $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
484  }
485  }
486  } else {
487  $error++;
488  setEventMessages($object->error, $object->errors, 'errors');
489  }
490  $action = '';
491 }
492 
493 // Action clone object
494 if ($action == 'confirm_clone' && $confirm == 'yes' && !empty($permissiontoadd)) {
495  if (1 == 0 && !GETPOST('clone_content') && !GETPOST('clone_receivers')) {
496  setEventMessages($langs->trans("NoCloneOptionsSpecified"), null, 'errors');
497  } else {
498  $objectutil = dol_clone($object, 1); // To avoid to denaturate loaded object when setting some properties for clone or if createFromClone modifies the object. We use native clone to keep this->db valid.
499  //$objectutil->date = dol_mktime(12, 0, 0, GETPOST('newdatemonth', 'int'), GETPOST('newdateday', 'int'), GETPOST('newdateyear', 'int'));
500  // ...
501  $result = $objectutil->createFromClone($user, (($object->id > 0) ? $object->id : $id));
502  if (is_object($result) || $result > 0) {
503  $newid = 0;
504  if (is_object($result)) {
505  $newid = $result->id;
506  } else {
507  $newid = $result;
508  }
509 
510  if (empty($noback)) {
511  header("Location: " . $_SERVER['PHP_SELF'] . '?id=' . $newid); // Open record of new object
512  exit;
513  }
514  } else {
515  $error++;
516  setEventMessages($objectutil->error, $objectutil->errors, 'errors');
517  $action = '';
518  }
519  }
520 }
GETPOST
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
Definition: functions.lib.php:484
dol_print_error
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
Definition: functions.lib.php:4844
Translate
Class to manage translations.
Definition: translate.class.php:30
dol_clone
dol_clone($object, $native=0)
Create a clone of instance of object (new instance with same value for each properties) With native =...
Definition: functions.lib.php:1158
price2num
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
Definition: functions.lib.php:5661
isModEnabled
isModEnabled($module)
Is Dolibarr module enabled.
Definition: functions.lib.php:105
GETPOSTISSET
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
Definition: functions.lib.php:386
setEventMessages
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='')
Set event messages in dol_events session object.
Definition: functions.lib.php:8137
dol_mktime
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
Definition: functions.lib.php:2757
getDolGlobalInt
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
Definition: functions.lib.php:93