dolibarr 20.0.2
actions_extrafields.inc.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2011-2020 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 * $elementype must be defined.
19 */
20
26$maxsizestring = 255;
27$maxsizeint = 10;
28$mesg = array();
29
30$extrasize = GETPOST('size', 'intcomma');
31$type = GETPOST('type', 'alphanohtml');
32$param = GETPOST('param', 'alphanohtml');
33$css = GETPOST('css', 'alphanohtml');
34$cssview = GETPOST('cssview', 'alphanohtml');
35$csslist = GETPOST('csslist', 'alphanohtml');
36$confirm = GETPOST('confirm', 'alpha');
37
38if ($type == 'double' && strpos($extrasize, ',') === false) {
39 $extrasize = '24,8';
40}
41if ($type == 'date') {
42 $extrasize = '';
43}
44if ($type == 'datetime') {
45 $extrasize = '';
46}
47if ($type == 'select') {
48 $extrasize = '';
49}
50
51$listofreservedwords = array(
52 'ADD', 'ALL', 'ALTER', 'ANALYZE', 'AND', 'AS', 'ASENSITIVE', 'BEFORE', 'BETWEEN', 'BINARY', 'BLOB', 'BOTH', 'CALL', 'CASCADE', 'CASE', 'CHANGE', 'CHAR', 'CHARACTER', 'CHECK', 'COLLATE', 'COLUMN', 'CONDITION', 'CONSTRAINT', 'CONTINUE', 'CONVERT', 'CREATE', 'CROSS', 'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'CURRENT_USER',
53 'CURSOR', 'DATABASE', 'DATABASES', 'DAY_HOUR', 'DAY_MICROSECOND', 'DAY_MINUTE', 'DAY_SECOND', 'DECIMAL', 'DECLARE', 'DEFAULT', 'DELAYED', 'DELETE', 'DESC', 'DESCRIBE', 'DETERMINISTIC', 'DISTINCT', 'DISTINCTROW', 'DOUBLE', 'DROP', 'DUAL',
54 'EACH', 'ELSE', 'ELSEIF', 'ENCLOSED', 'ESCAPED', 'EXISTS', 'EXPLAIN', 'FALSE', 'FETCH', 'FLOAT', 'FLOAT4', 'FLOAT8', 'FORCE', 'FOREIGN', 'FULLTEXT', 'GRANT', 'GROUP', 'HAVING', 'HIGH_PRIORITY', 'HOUR_MICROSECOND', 'HOUR_MINUTE', 'HOUR_SECOND',
55 'IGNORE', 'IGNORE_SERVER_IDS', 'INDEX', 'INFILE', 'INNER', 'INOUT', 'INSENSITIVE', 'INSERT', 'INT', 'INTEGER', 'INTERVAL', 'INTO', 'ITERATE',
56 'KEYS', 'KEYWORD', 'LEADING', 'LEAVE', 'LEFT', 'LIKE', 'LIMIT', 'LINES', 'LOCALTIME', 'LOCALTIMESTAMP', 'LONGBLOB', 'LONGTEXT', 'MASTER_SSL_VERIFY_SERVER_CERT', 'MATCH', 'MEDIUMBLOB', 'MEDIUMINT', 'MEDIUMTEXT', 'MIDDLEINT', 'MINUTE_MICROSECOND', 'MINUTE_SECOND', 'MODIFIES', 'NATURAL', 'NOT', 'NO_WRITE_TO_BINLOG', 'NUMERIC',
57 'OFFSET', 'ON', 'OPTION', 'OPTIONALLY', 'OUTER', 'OUTFILE',
58 'PARTITION', 'POSITION', 'PRECISION', 'PRIMARY', 'PROCEDURE', 'PURGE', 'RANGE', 'READS', 'READ_WRITE', 'REAL', 'REFERENCES', 'REGEXP', 'RELEASE', 'RENAME', 'REPEAT', 'REQUIRE', 'RESTRICT', 'RETURN', 'REVOKE', 'RIGHT', 'RLIKE',
59 'SCHEMAS', 'SECOND_MICROSECOND', 'SENSITIVE', 'SEPARATOR', 'SIGNAL', 'SMALLINT', 'SPATIAL', 'SPECIFIC', 'SQLEXCEPTION', 'SQLSTATE', 'SQLWARNING', 'SQL_BIG_RESULT', 'SQL_CALC_FOUND_ROWS', 'SQL_SMALL_RESULT', 'SSL', 'STARTING', 'STRAIGHT_JOIN',
60 'TABLE', 'TERMINATED', 'TINYBLOB', 'TINYINT', 'TINYTEXT', 'TRAILING', 'TRIGGER', 'UNDO', 'UNIQUE', 'UNSIGNED', 'UPDATE', 'USAGE', 'USING', 'UTC_DATE', 'UTC_TIME', 'UTC_TIMESTAMP', 'VALUES', 'VARBINARY', 'VARCHAR', 'VARYING',
61 'WHEN', 'WHERE', 'WHILE', 'WRITE', 'XOR', 'YEAR_MONTH', 'ZEROFILL'
62);
63
64// Add attribute
65if ($action == 'add') {
66 if (GETPOST("button") != $langs->trans("Cancel")) {
67 // Check values
68 if (!$type) {
69 $error++;
70 $langs->load("errors");
71 $mesg[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type"));
72 $action = 'create';
73 }
74 if ($type == 'varchar' && $extrasize <= 0) {
75 $error++;
76 $langs->load("errors");
77 $mesg[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Size"));
78 $action = 'edit';
79 }
80 if ($type == 'varchar' && $extrasize > $maxsizestring) {
81 $error++;
82 $langs->load("errors");
83 $mesg[] = $langs->trans("ErrorSizeTooLongForVarcharType", $maxsizestring);
84 $action = 'create';
85 }
86 if ($type == 'int' && $extrasize > $maxsizeint) {
87 $error++;
88 $langs->load("errors");
89 $mesg[] = $langs->trans("ErrorSizeTooLongForIntType", $maxsizeint);
90 $action = 'create';
91 }
92 if ($type == 'select' && !$param) {
93 $error++;
94 $langs->load("errors");
95 $mesg[] = $langs->trans("ErrorNoValueForSelectType");
96 $action = 'create';
97 }
98 if ($type == 'sellist' && !$param) {
99 $error++;
100 $langs->load("errors");
101 $mesg[] = $langs->trans("ErrorNoValueForSelectListType");
102 $action = 'create';
103 }
104 if ($type == 'checkbox' && !$param) {
105 $error++;
106 $langs->load("errors");
107 $mesg[] = $langs->trans("ErrorNoValueForCheckBoxType");
108 $action = 'create';
109 }
110 if ($type == 'link' && !$param) {
111 $error++;
112 $langs->load("errors");
113 $mesg[] = $langs->trans("ErrorNoValueForLinkType");
114 $action = 'create';
115 }
116 if ($type == 'radio' && !$param) {
117 $error++;
118 $langs->load("errors");
119 $mesg[] = $langs->trans("ErrorNoValueForRadioType");
120 $action = 'create';
121 }
122 if ((($type == 'radio') || ($type == 'checkbox')) && $param) {
123 // Construct array for parameter (value of select list)
124 $parameters = $param;
125 $parameters_array = explode("\r\n", $parameters);
126 foreach ($parameters_array as $param_ligne) {
127 if (!empty($param_ligne)) {
128 if (preg_match_all('/,/', $param_ligne, $matches)) {
129 if (count($matches[0]) > 1) {
130 $error++;
131 $langs->load("errors");
132 $mesg[] = $langs->trans("ErrorBadFormatValueList", $param_ligne);
133 $action = 'create';
134 }
135 } else {
136 $error++;
137 $langs->load("errors");
138 $mesg[] = $langs->trans("ErrorBadFormatValueList", $param_ligne);
139 $action = 'create';
140 }
141 }
142 }
143 }
144
145 if (!$error) {
146 if (strlen(GETPOST('attrname', 'aZ09')) < 3) {
147 $error++;
148 $langs->load("errors");
149 $mesg[] = $langs->trans("ErrorValueLength", $langs->transnoentitiesnoconv("AttributeCode"), 3);
150 $action = 'create';
151 }
152 }
153
154 // Check reserved keyword with more than 3 characters
155 if (!$error) {
156 if (in_array(strtoupper(GETPOST('attrname', 'aZ09')), $listofreservedwords)) {
157 $error++;
158 $langs->load("errors");
159 $mesg[] = $langs->trans("ErrorReservedKeyword", GETPOST('attrname', 'aZ09'));
160 $action = 'create';
161 }
162 }
163
164 if (!$error) {
165 // attrname must be alphabetical and lower case only
166 if (GETPOSTISSET("attrname") && preg_match("/^[a-z0-9_]+$/", GETPOST('attrname', 'aZ09')) && !is_numeric(GETPOST('attrname', 'aZ09'))) {
167 // Construct array for parameter (value of select list)
168 $default_value = GETPOST('default_value', 'alpha');
169 $parameters = $param;
170 $parameters_array = explode("\r\n", $parameters);
171 $params = array();
172 //In sellist we have only one line and it can have come to do SQL expression
173 if ($type == 'sellist' || $type == 'chkbxlst') {
174 foreach ($parameters_array as $param_ligne) {
175 $params['options'] = array($parameters => null);
176 }
177 } else {
178 // Else it's separated key/value and coma list
179 foreach ($parameters_array as $param_ligne) {
180 if (strpos($param_ligne, ',') !== false) {
181 list($key, $value) = explode(',', $param_ligne);
182 if (!array_key_exists('options', $params)) {
183 $params['options'] = array();
184 }
185 } else {
186 $key = $param_ligne;
187 $value = null;
188 }
189 $params['options'][$key] = $value;
190 }
191 }
192
193 // Visibility: -1=not visible by default in list, 1=visible, 0=hidden
194 $visibility = GETPOST('list', 'alpha');
195 if (in_array($type, ['separate', 'point', 'linestrg', 'polygon'])) {
196 $visibility = 3;
197 }
198
199 $result = $extrafields->addExtraField(
200 GETPOST('attrname', 'aZ09'),
201 GETPOST('label', 'alpha'),
202 $type,
203 GETPOSTINT('pos'),
204 $extrasize,
205 $elementtype,
206 (GETPOST('unique', 'alpha') ? 1 : 0),
207 (GETPOST('required', 'alpha') ? 1 : 0),
208 $default_value,
209 $params,
210 (GETPOST('alwayseditable', 'alpha') ? 1 : 0),
211 (GETPOST('perms', 'alpha') ? GETPOST('perms', 'alpha') : ''),
212 $visibility,
213 GETPOST('help', 'alpha'),
214 GETPOST('computed_value', 'alpha'),
215 (GETPOST('entitycurrentorall', 'alpha') ? 0 : ''),
216 GETPOST('langfile', 'alpha'),
217 1,
218 (GETPOST('totalizable', 'alpha') ? 1 : 0),
219 GETPOST('printable', 'alpha'),
220 array('css' => $css, 'cssview' => $cssview, 'csslist' => $csslist)
221 );
222 if ($result > 0) {
223 setEventMessages($langs->trans('SetupSaved'), null, 'mesgs');
224 header("Location: ".$_SERVER["PHP_SELF"]);
225 exit;
226 } else {
227 $error++;
228 $mesg = $extrafields->error;
229 setEventMessages($mesg, null, 'errors');
230 }
231 } else {
232 $error++;
233 $langs->load("errors");
234 $mesg = $langs->trans("ErrorFieldCanNotContainSpecialNorUpperCharacters", $langs->transnoentities("AttributeCode"));
235 setEventMessages($mesg, null, 'errors');
236 $action = 'create';
237 }
238 } else {
239 setEventMessages($mesg, null, 'errors');
240 }
241 }
242}
243
244// Rename field
245if ($action == 'update') {
246 if (GETPOST("button") != $langs->trans("Cancel")) {
247 // Check values
248 if (!$type) {
249 $error++;
250 $langs->load("errors");
251 $mesg[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type"));
252 $action = 'edit';
253 }
254 if ($type == 'varchar' && $extrasize <= 0) {
255 $error++;
256 $langs->load("errors");
257 $mesg[] = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Size"));
258 $action = 'edit';
259 }
260 if ($type == 'varchar' && $extrasize > $maxsizestring) {
261 $error++;
262 $langs->load("errors");
263 $mesg[] = $langs->trans("ErrorSizeTooLongForVarcharType", $maxsizestring);
264 $action = 'edit';
265 }
266 if ($type == 'int' && $extrasize > $maxsizeint) {
267 $error++;
268 $langs->load("errors");
269 $mesg[] = $langs->trans("ErrorSizeTooLongForIntType", $maxsizeint);
270 $action = 'edit';
271 }
272 if ($type == 'select' && !$param) {
273 $error++;
274 $langs->load("errors");
275 $mesg[] = $langs->trans("ErrorNoValueForSelectType");
276 $action = 'edit';
277 }
278 if ($type == 'sellist' && !$param) {
279 $error++;
280 $langs->load("errors");
281 $mesg[] = $langs->trans("ErrorNoValueForSelectListType");
282 $action = 'edit';
283 }
284 if ($type == 'checkbox' && !$param) {
285 $error++;
286 $langs->load("errors");
287 $mesg[] = $langs->trans("ErrorNoValueForCheckBoxType");
288 $action = 'edit';
289 }
290 if ($type == 'radio' && !$param) {
291 $error++;
292 $langs->load("errors");
293 $mesg[] = $langs->trans("ErrorNoValueForRadioType");
294 $action = 'edit';
295 }
296 if ((($type == 'radio') || ($type == 'checkbox')) && $param) {
297 // Construct array for parameter (value of select list)
298 $parameters = $param;
299 $parameters_array = explode("\r\n", $parameters);
300 foreach ($parameters_array as $param_ligne) {
301 if (!empty($param_ligne)) {
302 if (preg_match_all('/,/', $param_ligne, $matches)) {
303 if (count($matches[0]) > 1) {
304 $error++;
305 $langs->load("errors");
306 $mesg[] = $langs->trans("ErrorBadFormatValueList", $param_ligne);
307 $action = 'edit';
308 }
309 } else {
310 $error++;
311 $langs->load("errors");
312 $mesg[] = $langs->trans("ErrorBadFormatValueList", $param_ligne);
313 $action = 'edit';
314 }
315 }
316 }
317 }
318
319 if (!$error) {
320 if (strlen(GETPOST('attrname', 'aZ09')) < 3 && !getDolGlobalString('MAIN_DISABLE_EXTRAFIELDS_CHECK_FOR_UPDATE')) {
321 $error++;
322 $langs->load("errors");
323 $mesg[] = $langs->trans("ErrorValueLength", $langs->transnoentitiesnoconv("AttributeCode"), 3);
324 $action = 'edit';
325 }
326 }
327
328 // Check reserved keyword with more than 3 characters
329 if (!$error) {
330 if (in_array(strtoupper(GETPOST('attrname', 'aZ09')), $listofreservedwords) && !getDolGlobalString('MAIN_DISABLE_EXTRAFIELDS_CHECK_FOR_UPDATE')) {
331 $error++;
332 $langs->load("errors");
333 $mesg[] = $langs->trans("ErrorReservedKeyword", GETPOST('attrname', 'aZ09'));
334 $action = 'edit';
335 }
336 }
337
338 if (!$error) {
339 if (GETPOSTISSET("attrname") && preg_match("/^\w[a-zA-Z0-9-_]*$/", GETPOST('attrname', 'aZ09')) && !is_numeric(GETPOST('attrname', 'aZ09'))) {
340 $pos = GETPOSTINT('pos');
341 // Construct array for parameter (value of select list)
342 $parameters = $param;
343 $parameters_array = explode("\r\n", $parameters);
344 $params = array();
345 //In sellist we have only one line and it can have come to do SQL expression
346 if ($type == 'sellist' || $type == 'chkbxlst') {
347 foreach ($parameters_array as $param_ligne) {
348 $params['options'] = array($parameters => null);
349 }
350 } else {
351 //Else it's separated key/value and coma list
352 foreach ($parameters_array as $param_ligne) {
353 $tmp = explode(',', $param_ligne);
354 $key = $tmp[0];
355 if (!empty($tmp[1])) {
356 $value = $tmp[1];
357 }
358 if (!array_key_exists('options', $params)) {
359 $params['options'] = array();
360 }
361 $params['options'][$key] = $value;
362 }
363 }
364
365 // $params['options'][$key] can be 'Facture:/compta/facture/class/facture.class.php' => '/custom'
366
367 // Visibility: -1=not visible by default in list, 1=visible, 0=hidden
368 $visibility = GETPOST('list', 'alpha');
369 if (in_array($type, ['separate', 'point', 'linestrg', 'polygon'])) {
370 $visibility = 3;
371 }
372
373 // Example: is_object($object) ? ($object->id < 10 ? round($object->id / 2, 2) : (2 * $user->id) * (int) substr($mysoc->zip, 1, 2)) : 'objnotdefined'
374 $computedvalue = GETPOST('computed_value', 'nohtml');
375
376 $result = $extrafields->update(
377 GETPOST('attrname', 'aZ09'),
378 GETPOST('label', 'alpha'),
379 $type,
380 $extrasize,
381 $elementtype,
382 (GETPOST('unique', 'alpha') ? 1 : 0),
383 (GETPOST('required', 'alpha') ? 1 : 0),
384 $pos,
385 $params,
386 (GETPOST('alwayseditable', 'alpha') ? 1 : 0),
387 (GETPOST('perms', 'alpha') ? GETPOST('perms', 'alpha') : ''),
388 $visibility,
389 GETPOST('help', 'alpha'),
390 GETPOST('default_value', 'alpha'),
391 $computedvalue,
392 (GETPOST('entitycurrentorall', 'alpha') ? 0 : ''),
393 GETPOST('langfile'),
394 GETPOST('enabled', 'nohtml'),
395 (GETPOST('totalizable', 'alpha') ? 1 : 0),
396 GETPOST('printable', 'alpha'),
397 array('css' => $css, 'cssview' => $cssview, 'csslist' => $csslist)
398 );
399 if ($result > 0) {
400 setEventMessages($langs->trans('SetupSaved'), null, 'mesgs');
401 header("Location: ".$_SERVER["PHP_SELF"]);
402 exit;
403 } else {
404 $error++;
405 $mesg = $extrafields->error;
406 setEventMessages($mesg, null, 'errors');
407 }
408 } else {
409 $error++;
410 $langs->load("errors");
411 $mesg = $langs->trans("ErrorFieldCanNotContainSpecialCharacters", $langs->transnoentities("AttributeCode"));
412 setEventMessages($mesg, null, 'errors');
413 }
414 } else {
415 setEventMessages($mesg, null, 'errors');
416 }
417 }
418}
419
420// Delete attribute
421if ($action == 'confirm_delete' && $confirm == "yes") {
422 if (GETPOSTISSET("attrname") && preg_match("/^\w[a-zA-Z0-9-_]*$/", GETPOST("attrname", 'aZ09'))) {
423 $attributekey = GETPOST('attrname', 'aZ09');
424
425 $result = $extrafields->delete($attributekey, $elementtype);
426 if ($result >= 0) {
427 setEventMessages($langs->trans("ExtrafieldsDeleted", $attributekey), null, 'mesgs');
428
429 header("Location: ".$_SERVER["PHP_SELF"]);
430 exit;
431 } else {
432 $mesg = $extrafields->error;
433 }
434 } else {
435 $error++;
436 $langs->load("errors");
437 $mesg = $langs->trans("ErrorFieldCanNotContainSpecialCharacters", $langs->transnoentities("AttributeCode"));
438 }
439}
440
441// Recrypt data password
442if ($action == 'encrypt') {
443 // Load $extrafields->attributes
444 $extrafields->fetch_name_optionals_label($elementtype);
445 $attributekey = GETPOST('attrname', 'aZ09');
446
447 if (!empty($extrafields->attributes[$elementtype]['type'][$attributekey]) && $extrafields->attributes[$elementtype]['type'][$attributekey] == 'password') {
448 if (!empty($extrafields->attributes[$elementtype]['param'][$attributekey]['options'])) {
449 if (array_key_exists('dolcrypt', $extrafields->attributes[$elementtype]['param'][$attributekey]['options'])) {
450 // We can encrypt data with dolCrypt()
451 $arrayofelement = getElementProperties($elementtype);
452 if (!empty($arrayofelement['table_element'])) {
453 if ($extrafields->attributes[$elementtype]['entityid'][$attributekey] == $conf->entity || empty($extrafields->attributes[$elementtype]['entityid'][$attributekey])) {
454 dol_syslog("Loop on each extafields of table ".$arrayofelement['table_element']);
455
456 $sql = "SELECT te.rowid, te.".$attributekey;
457 $sql .= " FROM ".MAIN_DB_PREFIX.$arrayofelement['table_element']." as t, ".MAIN_DB_PREFIX.$arrayofelement['table_element'].'_extrafields as te';
458 $sql .= " WHERE te.fk_object = t.rowid";
459 $sql .= " AND te.".$attributekey." NOT LIKE 'dolcrypt:%'";
460 $sql .= " AND te.".$attributekey." IS NOT NULL";
461 $sql .= " AND te.".$attributekey." <> ''";
462 if ($extrafields->attributes[$elementtype]['entityid'][$attributekey] == $conf->entity) {
463 $sql .= " AND t.entity = ".getEntity($arrayofelement['table_element'], 0);
464 }
465
466 //print $sql;
467 $nbupdatedone = 0;
468 $resql = $db->query($sql);
469 if ($resql) {
470 $num_rows = $db->num_rows($resql);
471 $i = 0;
472 while ($i < $num_rows) {
473 $objtmp = $db->fetch_object($resql);
474 $id = $objtmp->rowid;
475 $pass = $objtmp->$attributekey;
476 if ($pass) {
477 $newpassword = dolEncrypt($pass);
478
479 $sqlupdate = "UPDATE ".MAIN_DB_PREFIX.$arrayofelement['table_element'].'_extrafields';
480 $sqlupdate .= " SET ".$attributekey." = '".$db->escape($newpassword)."'";
481 $sqlupdate .= " WHERE rowid = ".((int) $id);
482
483 $resupdate = $db->query($sqlupdate);
484 if ($resupdate) {
485 $nbupdatedone++;
486 } else {
487 setEventMessages($db->lasterror(), '', 'errors');
488 $error++;
489 break;
490 }
491 }
492
493 $i++;
494 }
495 }
496
497 if ($nbupdatedone > 0) {
498 setEventMessages($langs->trans("PasswordFieldEncrypted", $nbupdatedone), null, 'mesgs');
499 } else {
500 setEventMessages($langs->trans("PasswordFieldEncrypted", $nbupdatedone), null, 'warnings');
501 }
502 }
503 }
504 }
505 }
506 }
507}
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
getElementProperties($elementType)
Get an array with properties of an element.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dolEncrypt($chain, $key='', $ciphering='AES-256-CTR', $forceseed='')
Encode a string with a symmetric encryption.