dolibarr 23.0.3
ajaxextrafield.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2007-2024 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
25if (!defined('NOTOKENRENEWAL')) {
26 // Disables token renewal
27 define('NOTOKENRENEWAL', 1);
28}
29if (!defined('NOREQUIREMENU')) {
30 define('NOREQUIREMENU', '1');
31}
32if (!defined('NOREQUIREHTML')) {
33 define('NOREQUIREHTML', '1');
34}
35if (!defined('NOREQUIREAJAX')) {
36 define('NOREQUIREAJAX', '1');
37}
38if (!defined('NOHEADERNOFOOTER')) {
39 define('NOHEADERNOFOOTER', '1');
40}
41
42include '../../main.inc.php';
43include_once DOL_DOCUMENT_ROOT . '/core/class/html.form.class.php';
51// object id
52$objectid = GETPOST('objectid', 'aZ09');
53// 'module' or 'myobject@mymodule', 'mymodule_myobject'
54$objecttype = GETPOST('objecttype', 'aZ09arobase');
55$objectkey = GETPOST('objectkey', 'restricthtml');
56$search = GETPOST('search', 'restricthtml');
57$page = GETPOSTINT('page');
58$mode = GETPOST('mode', 'aZ09');
59$value = GETPOST('value', 'alphanohtml');
60$limit = 10;
61$offset = (($page - 1) * $limit);
62$element_ref = '';
63if (is_numeric($objectid)) {
64 $objectid = (int) $objectid;
65} else {
66 $element_ref = $objectid;
67 $objectid = 0;
68}
69// Load object according to $element
70$object = fetchObjectByElement($objectid, $objecttype, $element_ref);
71if (empty($object->element)) {
72 httponly_accessforbidden('Failed to get object with fetchObjectByElement(id=' . $objectid . ', objecttype=' . $objecttype . ')');
73}
74
75$module = $object->module;
76$element = $object->element;
77
78$usesublevelpermission = ($module != $element ? $element : '');
79if ($usesublevelpermission && !$user->hasRight($module, $element)) { // There is no permission on object defined, we will check permission on module directly
80 $usesublevelpermission = '';
81}
82
83// print $object->id.' - '.$object->module.' - '.$object->element.' - '.$object->table_element.' - '.$usesublevelpermission."\n";
84
85// Security check
86restrictedArea($user, $object->module, $object, $object->table_element, $usesublevelpermission);
87
88
89/*
90 * View
91 */
92
94
95$data = [
96 'results' => [],
97 'pagination' => [
98 'more' => true,
99 ]
100];
101if ($page == 1) {
102 $data['results'][] = [
103 'id' => -1,
104 'text' => '&nbsp;',
105 ];
106}
107$i = 0;
108if ($object instanceof CommonObject) {
109 $extrafields = new ExtraFields($db);
110 $extrafields->fetch_name_optionals_label($element);
111 $options = $extrafields->attributes[$element]['param'][$objectkey]['options'];
112 if (is_array($options)) {
113 // WARNING!! @FIXME This code is duplicated into core/class/extrafields.class.php
114
115 $tmpparamoptions = array_keys($options);
116 $paramoptions = preg_split('/[\r\n]+/', $tmpparamoptions[0]);
117
118 $InfoFieldList = explode(":", $paramoptions[0], 5);
119 // 0 : tableName
120 // 1 : label field name
121 // 2 : key fields name (if different of rowid)
122 // optional parameters...
123 // 3 : key field parent (for dependent lists). How this is used ?
124 // 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value. Or use USF on the second line.
125 // 5 : string category type. This replace the filter.
126 // 6 : ids categories list separated by comma for category root. This replace the filter.
127 // 7 : sort field (not used here but used into format for commobject)
128
129 // If there is a filter, we extract it by taking all content inside parenthesis.
130 if (! empty($InfoFieldList[4])) {
131 $pos = 0; // $pos will be position of ending filter
132 $parenthesisopen = 0;
133 while (substr($InfoFieldList[4], $pos, 1) !== '' && ($parenthesisopen || $pos == 0 || substr($InfoFieldList[4], $pos, 1) != ':')) {
134 if (substr($InfoFieldList[4], $pos, 1) == '(') {
135 $parenthesisopen++;
136 }
137 if (substr($InfoFieldList[4], $pos, 1) == ')') {
138 $parenthesisopen--;
139 }
140 $pos++;
141 }
142 $tmpbefore = substr($InfoFieldList[4], 0, $pos);
143 $tmpafter = substr($InfoFieldList[4], $pos + 1);
144 //var_dump($InfoFieldList[4].' -> '.$pos); var_dump($tmpafter);
145 $InfoFieldList[4] = $tmpbefore;
146 if ($tmpafter !== '') {
147 $InfoFieldList = array_merge($InfoFieldList, explode(':', $tmpafter));
148 }
149
150 // Fix better compatibility with some old extrafield syntax filter "(field=123)"
151 $reg = array();
152 if (preg_match('/^\‍(?([a-z0-9]+)([=<>]+)(\d+)\‍)?$/i', $InfoFieldList[4], $reg)) {
153 $InfoFieldList[4] = '(' . $reg[1] . ':' . $reg[2] . ':' . $reg[3] . ')';
154 }
155
156 //var_dump($InfoFieldList);
157 }
158
159 $parentName = '';
160 $parentField = '';
161 $keyList = (empty($InfoFieldList[2]) ? 'rowid' : $InfoFieldList[2] . ' as rowid');
162
163 if (count($InfoFieldList) > 3 && !empty($InfoFieldList[3])) {
164 list($parentName, $parentField) = explode('|', $InfoFieldList[3]);
165 $keyList .= ', ' . $parentField;
166 }
167 if (count($InfoFieldList) > 4 && !empty($InfoFieldList[4])) {
168 if (strpos($InfoFieldList[4], 'extra.') !== false) {
169 $keyList = 'main.' . $InfoFieldList[2] . ' as rowid';
170 } else {
171 $keyList = $InfoFieldList[2] . ' as rowid';
172 }
173 }
174
175 $filter_categorie = false;
176 if (count($InfoFieldList) > 5) {
177 if ($InfoFieldList[0] == 'categorie') {
178 $filter_categorie = true;
179 }
180 }
181
182 if (!$filter_categorie) {
183 $fields_label = isset($InfoFieldList[1]) ? explode('|', $InfoFieldList[1]) : array();
184 if (!empty($fields_label)) {
185 $keyList .= ', ';
186 $keyList .= implode(', ', $fields_label);
187 }
188
189 $sqlwhere = '';
190 $sql = "SELECT " . $keyList;
191 $sql .= ' FROM ' . $db->prefix() . $InfoFieldList[0];
192
193 // Add filter from 4th field
194 if (!empty($InfoFieldList[4])) {
195 // can use current entity filter
196 if (strpos($InfoFieldList[4], '$ENTITY$') !== false) {
197 $InfoFieldList[4] = str_replace('$ENTITY$', (string) $conf->entity, $InfoFieldList[4]);
198 }
199 // can use SELECT request
200 if (!getDolGlobalString("MAIN_DISALLOW_UNSECURED_SELECT_INTO_EXTRAFIELDS_FILTER")) {
201 if (strpos($InfoFieldList[4], '$SEL$') !== false) {
202 $InfoFieldList[4] = str_replace('$SEL$', 'SELECT', $InfoFieldList[4]);
203 }
204 }
205 // can use MODE parameter (list or view)
206 if (strpos($InfoFieldList[4], '$MODE$') !== false) {
207 $InfoFieldList[4] = str_replace('$MODE$', preg_replace('/[^a-z0-9_]/i', '', (string) $mode), $InfoFieldList[4]);
208 }
209
210 // current object id can be use into filter
211 if (strpos($InfoFieldList[4], '$ID$') !== false && !empty($objectid)) {
212 $InfoFieldList[4] = str_replace('$ID$', (string) $objectid, $InfoFieldList[4]);
213 } else {
214 $InfoFieldList[4] = str_replace('$ID$', '0', $InfoFieldList[4]);
215 }
216
217 // can filter on any field of object
218 //if (is_object($object)) {
219 $tags = [];
220 preg_match_all('/\$(.*?)\$/', $InfoFieldList[4], $tags);
221 foreach ($tags[0] as $keytag => $valuetag) {
222 $property = preg_replace('/[^a-z0-9_]/', '', strtolower($tags[1][$keytag]));
223 if (strpos($InfoFieldList[4], $valuetag) !== false && property_exists($object, $property) && !empty($object->$property)) {
224 $InfoFieldList[4] = str_replace($valuetag, (string) $object->$property, $InfoFieldList[4]);
225 } else {
226 $InfoFieldList[4] = str_replace($valuetag, '0', $InfoFieldList[4]);
227 }
228 }
229 //}
230
231 // We have to filter on a field of the extrafield table
232 $errstr = '';
233 if (strpos($InfoFieldList[4], 'extra.') !== false) {
234 $sql .= ' as main, ' . $db->sanitize($db->prefix() . $InfoFieldList[0]) . '_extrafields as extra'; // Add the join
235 $sqlwhere .= " WHERE extra.fk_object = main." . $db->sanitize($InfoFieldList[2]);
236 $sqlwhere .= " AND " . forgeSQLFromUniversalSearchCriteria($InfoFieldList[4], $errstr, 1); // Add the filter
237 } else {
238 $sqlwhere .= " WHERE " . forgeSQLFromUniversalSearchCriteria($InfoFieldList[4], $errstr, 1);
239 }
240 } else {
241 $sqlwhere .= ' WHERE 1=1';
242 }
243
244 // Some tables may have field, some other not. For the moment we disable it.
245 if (in_array($InfoFieldList[0], array('tablewithentity'))) {
246 $sqlwhere .= ' AND entity = ' . ((int) $conf->entity);
247 }
248 if ($search) {
249 if ($fields_label) {
250 $sqlwhere .= " " . natural_search($fields_label, $search, 0);
251 }
252 }
253
254 $sql .= $sqlwhere;
255
256 $orderfields = explode('|', $InfoFieldList[1]);
257 $keyList = $InfoFieldList[1];
258 if (count($orderfields)) {
259 $keyList = implode(', ', $orderfields);
260 }
261 $sql .= $db->order($keyList);
262 $sql .= $db->plimit($limit, $offset);
263
264 $data['sql'] = $sql;
265
266 $resql = $db->query($sql);
267 if ($resql) {
268 // $out .= '<option value="0">&nbsp;</option>';
269 $num = $db->num_rows($resql);
270 $i = 0;
271 while ($i < $num) {
272 $labeltoshow = '';
273 $obj = $db->fetch_object($resql);
274
275 // Several field into label (eq table:code|label:rowid)
276 $notrans = false;
277 $fields_label = explode('|', $InfoFieldList[1]);
278 if (count($fields_label) > 1) {
279 $notrans = true;
280 foreach ($fields_label as $field_toshow) {
281 $labeltoshow .= $obj->$field_toshow . ' ';
282 }
283 } else {
284 $labeltoshow = $obj->{$InfoFieldList[1]};
285 }
286
287 if ($value == $obj->rowid) {
288 if (!$notrans) {
289 foreach ($fields_label as $field_toshow) {
290 $translabel = $langs->trans($obj->$field_toshow);
291 $labeltoshow = $translabel . ' ';
292 }
293 }
294 // $out .= '<option value="'.$obj->rowid.'" selected>'.$labeltoshow.'</option>';
295 $data['results'][] = [
296 'id' => $obj->rowid,
297 'text' => $labeltoshow,
298 ];
299 } else {
300 if (!$notrans) {
301 $translabel = $langs->trans($obj->{$InfoFieldList[1]});
302 $labeltoshow = $translabel;
303 }
304 if (empty($labeltoshow)) {
305 $labeltoshow = '(not defined)';
306 }
307
308 /*
309 if (!empty($InfoFieldList[3]) && $parentField) {
310 $parent = $parentName . ':' . $obj->{$parentField};
311 }
312
313 $out .= '<option value="'.$obj->rowid.'"';
314 $out .= ($value == $obj->rowid ? ' selected' : '');
315 $out .= (!empty($parent) ? ' data-parent="'.$parent.'"' : '');
316 $out .= '>'.$labeltoshow.'</option>';
317 */
318 $data['results'][] = [
319 'id' => $obj->rowid,
320 'text' => $labeltoshow,
321 ];
322 }
323
324 $i++;
325 }
326 $db->free($resql);
327 } else {
328 dol_syslog('Error in request ' . $db->lasterror() . '. Check setup of extra parameters.', LOG_ERR);
329 }
330 } else {
331 require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
332 require_once DOL_DOCUMENT_ROOT . '/core/class/html.form.class.php';
333 }
334 }
335}
336
337if ($page > 1 && $i < 9) {
338 $data['pagination'] = [
339 'more' => false,
340 ];
341}
342print json_encode($data);
343
344$db->close();
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
Parent class of all other business classes (invoices, contracts, proposals, orders,...
Class to manage standard extra fields.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0)
forgeSQLFromUniversalSearchCriteria
natural_search($fields, $value, $mode=0, $nofirstand=0, $sqltoadd='')
Generate natural SQL search string for a criteria (this criteria can be tested on one or several fiel...
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
if(!defined( 'NOREQUIREMENU')) if(!empty(GETPOST('seteventmessages', 'alpha'))) if(!function_exists("llxHeader")) top_httphead($contenttype='text/html', $forcenocache=0)
Show HTTP header.
httponly_accessforbidden($message='1', $http_response_code=403, $stringalreadysanitized=0)
Show a message to say access is forbidden and stop program.
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.