1 | <?php |
||
2 | /* Copyright (C) 2018 Alxarafe <[email protected]> |
||
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 <http://www.gnu.org/licenses/>. |
||
16 | */ |
||
17 | namespace Alixar\Base; |
||
18 | |||
19 | use Alixar\Base\ExtraFields; |
||
20 | |||
21 | abstract class CommonObject |
||
22 | { |
||
23 | /** |
||
24 | * @var int The object identifier |
||
25 | */ |
||
26 | public $id; |
||
27 | |||
28 | /** |
||
29 | * @var string Error string |
||
30 | * @see errors |
||
31 | */ |
||
32 | public $error; |
||
33 | |||
34 | /** |
||
35 | * @var string[] Array of error strings |
||
36 | */ |
||
37 | public $errors=array(); |
||
38 | |||
39 | /** |
||
40 | * @var string ID to identify managed object |
||
41 | */ |
||
42 | public $element; |
||
43 | |||
44 | /** |
||
45 | * @var string Name of table without prefix where object is stored |
||
46 | */ |
||
47 | public $table_element; |
||
48 | |||
49 | /** |
||
50 | * @var int Name of subtable line |
||
51 | */ |
||
52 | public $table_element_line=''; |
||
53 | |||
54 | /** |
||
55 | * @var string Key value used to track if data is coming from import wizard |
||
56 | */ |
||
57 | public $import_key; |
||
58 | |||
59 | /** |
||
60 | * @var mixed Contains data to manage extrafields |
||
61 | */ |
||
62 | public $array_options=array(); |
||
63 | |||
64 | /** |
||
65 | * @var int[][] Array of linked objects ids. Loaded by ->fetchObjectLinked |
||
66 | */ |
||
67 | public $linkedObjectsIds; |
||
68 | |||
69 | /** |
||
70 | * @var mixed Array of linked objects. Loaded by ->fetchObjectLinked |
||
71 | */ |
||
72 | public $linkedObjects; |
||
73 | |||
74 | /** |
||
75 | * @var Object To store a cloned copy of object before to edit it and keep track of old properties |
||
76 | */ |
||
77 | public $oldcopy; |
||
78 | |||
79 | /** |
||
80 | * @var string Column name of the ref field. |
||
81 | */ |
||
82 | protected $table_ref_field = ''; |
||
83 | |||
84 | |||
85 | |||
86 | // Following vars are used by some objects only. We keep this property here in CommonObject to be able to provide common method using them. |
||
87 | |||
88 | /** |
||
89 | * @var array<string,mixed> Can be used to pass information when only object is provided to method |
||
90 | */ |
||
91 | public $context=array(); |
||
92 | |||
93 | /** |
||
94 | * @var string Contains canvas name if record is an alternative canvas record |
||
95 | */ |
||
96 | public $canvas; |
||
97 | |||
98 | /** |
||
99 | * @var Project The related project |
||
100 | * @see fetch_projet() |
||
101 | */ |
||
102 | public $project; |
||
103 | |||
104 | /** |
||
105 | * @var int The related project ID |
||
106 | * @see setProject(), project |
||
107 | */ |
||
108 | public $fk_project; |
||
109 | |||
110 | /** |
||
111 | * @deprecated |
||
112 | * @see project |
||
113 | */ |
||
114 | public $projet; |
||
115 | |||
116 | /** |
||
117 | * @var Contact a related contact |
||
118 | * @see fetch_contact() |
||
119 | */ |
||
120 | public $contact; |
||
121 | |||
122 | /** |
||
123 | * @var int The related contact ID |
||
124 | * @see fetch_contact() |
||
125 | */ |
||
126 | public $contact_id; |
||
127 | |||
128 | /** |
||
129 | * @var Societe A related thirdparty |
||
130 | * @see fetch_thirdparty() |
||
131 | */ |
||
132 | public $thirdparty; |
||
133 | |||
134 | /** |
||
135 | * @var User A related user |
||
136 | * @see fetch_user() |
||
137 | */ |
||
138 | public $user; |
||
139 | |||
140 | /** |
||
141 | * @var string The type of originating object ('commande', 'facture', ...) |
||
142 | * @see fetch_origin() |
||
143 | */ |
||
144 | public $origin; |
||
145 | |||
146 | /** |
||
147 | * @var int The id of originating object |
||
148 | * @see fetch_origin() |
||
149 | */ |
||
150 | public $origin_id; |
||
151 | |||
152 | /** |
||
153 | * @var string The object's reference |
||
154 | */ |
||
155 | public $ref; |
||
156 | |||
157 | /** |
||
158 | * @var string The object's previous reference |
||
159 | */ |
||
160 | public $ref_previous; |
||
161 | |||
162 | /** |
||
163 | * @var string The object's next reference |
||
164 | */ |
||
165 | public $ref_next; |
||
166 | |||
167 | /** |
||
168 | * @var string An external reference for the object |
||
169 | */ |
||
170 | public $ref_ext; |
||
171 | |||
172 | /** |
||
173 | * @var int The object's status |
||
174 | * @see setStatut() |
||
175 | */ |
||
176 | public $statut; |
||
177 | |||
178 | /** |
||
179 | * @var string |
||
180 | * @see getFullAddress() |
||
181 | */ |
||
182 | public $country; |
||
183 | |||
184 | /** |
||
185 | * @var int |
||
186 | * @see getFullAddress(), country |
||
187 | */ |
||
188 | public $country_id; |
||
189 | |||
190 | /** |
||
191 | * @var string |
||
192 | * @see getFullAddress(), isInEEC(), country |
||
193 | */ |
||
194 | public $country_code; |
||
195 | |||
196 | /** |
||
197 | * @var string |
||
198 | * @see getFullAddress() |
||
199 | */ |
||
200 | public $state; |
||
201 | |||
202 | /** |
||
203 | * @var int |
||
204 | * @see getFullAddress(), state |
||
205 | */ |
||
206 | public $state_id; |
||
207 | |||
208 | /** |
||
209 | * @var string |
||
210 | * @see getFullAddress(), state |
||
211 | */ |
||
212 | public $state_code; |
||
213 | |||
214 | /** |
||
215 | * @var string |
||
216 | * @see getFullAddress(), region |
||
217 | */ |
||
218 | public $region; |
||
219 | |||
220 | /** |
||
221 | * @var string |
||
222 | * @see getFullAddress(), region |
||
223 | */ |
||
224 | public $region_code; |
||
225 | |||
226 | /** |
||
227 | * @var int |
||
228 | * @see fetch_barcode() |
||
229 | */ |
||
230 | public $barcode_type; |
||
231 | |||
232 | /** |
||
233 | * @var string |
||
234 | * @see fetch_barcode(), barcode_type |
||
235 | */ |
||
236 | public $barcode_type_code; |
||
237 | |||
238 | /** |
||
239 | * @var string |
||
240 | * @see fetch_barcode(), barcode_type |
||
241 | */ |
||
242 | public $barcode_type_label; |
||
243 | |||
244 | /** |
||
245 | * @var string |
||
246 | * @see fetch_barcode(), barcode_type |
||
247 | */ |
||
248 | public $barcode_type_coder; |
||
249 | |||
250 | /** |
||
251 | * @var int Payment method ID (cheque, cash, ...) |
||
252 | * @see setPaymentMethods() |
||
253 | */ |
||
254 | public $mode_reglement_id; |
||
255 | |||
256 | /** |
||
257 | * @var int Payment terms ID |
||
258 | * @see setPaymentTerms() |
||
259 | */ |
||
260 | public $cond_reglement_id; |
||
261 | |||
262 | /** |
||
263 | * @var int Payment terms ID |
||
264 | * @deprecated Kept for compatibility |
||
265 | * @see cond_reglement_id; |
||
266 | */ |
||
267 | public $cond_reglement; |
||
268 | |||
269 | /** |
||
270 | * @var int Delivery address ID |
||
271 | * @deprecated |
||
272 | * @see setDeliveryAddress() |
||
273 | */ |
||
274 | public $fk_delivery_address; |
||
275 | |||
276 | /** |
||
277 | * @var int Shipping method ID |
||
278 | * @see setShippingMethod() |
||
279 | */ |
||
280 | public $shipping_method_id; |
||
281 | |||
282 | /** |
||
283 | * @var string |
||
284 | * @see SetDocModel() |
||
285 | */ |
||
286 | public $modelpdf; |
||
287 | |||
288 | /** |
||
289 | * @var int Bank account ID |
||
290 | * @see SetBankAccount() |
||
291 | */ |
||
292 | public $fk_account; |
||
293 | |||
294 | /** |
||
295 | * @var string Public note |
||
296 | * @see update_note() |
||
297 | */ |
||
298 | public $note_public; |
||
299 | |||
300 | /** |
||
301 | * @var string Private note |
||
302 | * @see update_note() |
||
303 | */ |
||
304 | public $note_private; |
||
305 | |||
306 | /** |
||
307 | * @deprecated |
||
308 | * @see note_public |
||
309 | */ |
||
310 | public $note; |
||
311 | |||
312 | /** |
||
313 | * @var float Total amount before taxes |
||
314 | * @see update_price() |
||
315 | */ |
||
316 | public $total_ht; |
||
317 | |||
318 | /** |
||
319 | * @var float Total VAT amount |
||
320 | * @see update_price() |
||
321 | */ |
||
322 | public $total_tva; |
||
323 | |||
324 | /** |
||
325 | * @var float Total local tax 1 amount |
||
326 | * @see update_price() |
||
327 | */ |
||
328 | public $total_localtax1; |
||
329 | |||
330 | /** |
||
331 | * @var float Total local tax 2 amount |
||
332 | * @see update_price() |
||
333 | */ |
||
334 | public $total_localtax2; |
||
335 | |||
336 | /** |
||
337 | * @var float Total amount with taxes |
||
338 | * @see update_price() |
||
339 | */ |
||
340 | public $total_ttc; |
||
341 | |||
342 | /** |
||
343 | * @var CommonObjectLine[] |
||
344 | */ |
||
345 | public $lines; |
||
346 | |||
347 | /** |
||
348 | * @var mixed Contains comments |
||
349 | * @see fetchComments() |
||
350 | */ |
||
351 | public $comments=array(); |
||
352 | |||
353 | /** |
||
354 | * @var int |
||
355 | * @see setIncoterms() |
||
356 | */ |
||
357 | public $fk_incoterms; |
||
358 | |||
359 | /** |
||
360 | * @var string |
||
361 | * @see SetIncoterms() |
||
362 | */ |
||
363 | public $libelle_incoterms; |
||
364 | |||
365 | /** |
||
366 | * @var string |
||
367 | * @see display_incoterms() |
||
368 | */ |
||
369 | public $location_incoterms; |
||
370 | |||
371 | public $name; |
||
372 | public $lastname; |
||
373 | public $firstname; |
||
374 | public $civility_id; |
||
375 | |||
376 | // Dates |
||
377 | public $date_creation; // Date creation |
||
378 | public $date_validation; // Date validation |
||
379 | public $date_modification; // Date last change (tms field) |
||
380 | |||
381 | |||
382 | |||
383 | // No constructor as it is an abstract class |
||
384 | |||
385 | /** |
||
386 | * Check an object id/ref exists |
||
387 | * If you don't need/want to instantiate object and just need to know if object exists, use this method instead of fetch |
||
388 | * |
||
389 | * @param string $element String of element ('product', 'facture', ...) |
||
390 | * @param int $id Id of object |
||
391 | * @param string $ref Ref of object to check |
||
392 | * @param string $ref_ext Ref ext of object to check |
||
393 | * @return int <0 if KO, 0 if OK but not found, >0 if OK and exists |
||
394 | */ |
||
395 | static function isExistingObject($element, $id, $ref='', $ref_ext='') |
||
396 | { |
||
397 | global $db,$conf; |
||
398 | |||
399 | $sql = "SELECT rowid, ref, ref_ext"; |
||
400 | $sql.= " FROM ".MAIN_DB_PREFIX.$element; |
||
401 | $sql.= " WHERE entity IN (".getEntity($element).")" ; |
||
402 | |||
403 | if ($id > 0) $sql.= " AND rowid = ".$db->escape($id); |
||
404 | else if ($ref) $sql.= " AND ref = '".$db->escape($ref)."'"; |
||
405 | else if ($ref_ext) $sql.= " AND ref_ext = '".$db->escape($ref_ext)."'"; |
||
406 | else { |
||
407 | $error='ErrorWrongParameters'; |
||
408 | dol_print_error(get_class()."::isExistingObject ".$error, LOG_ERR); |
||
409 | return -1; |
||
410 | } |
||
411 | if ($ref || $ref_ext) $sql.= " AND entity = ".$conf->entity; |
||
412 | |||
413 | dol_syslog(get_class()."::isExistingObject", LOG_DEBUG); |
||
414 | $resql = $db->query($sql); |
||
415 | if ($resql) |
||
416 | { |
||
417 | $num=$db->num_rows($resql); |
||
418 | if ($num > 0) return 1; |
||
419 | else return 0; |
||
420 | } |
||
421 | return -1; |
||
422 | } |
||
423 | |||
424 | /** |
||
425 | * Method to output saved errors |
||
426 | * |
||
427 | * @return string String with errors |
||
428 | */ |
||
429 | function errorsToString() |
||
430 | { |
||
431 | return $this->error.(is_array($this->errors)?(($this->error!=''?', ':'').join(', ',$this->errors)):''); |
||
432 | } |
||
433 | |||
434 | /** |
||
435 | * Return full name (civility+' '+name+' '+lastname) |
||
436 | * |
||
437 | * @param Translate $langs Language object for translation of civility (used only if option is 1) |
||
438 | * @param int $option 0=No option, 1=Add civility |
||
439 | * @param int $nameorder -1=Auto, 0=Lastname+Firstname, 1=Firstname+Lastname, 2=Firstname |
||
440 | * @param int $maxlen Maximum length |
||
441 | * @return string String with full name |
||
442 | */ |
||
443 | function getFullName($langs,$option=0,$nameorder=-1,$maxlen=0) |
||
444 | { |
||
445 | //print "lastname=".$this->lastname." name=".$this->name." nom=".$this->nom."<br>\n"; |
||
446 | $lastname=$this->lastname; |
||
447 | $firstname=$this->firstname; |
||
448 | if (empty($lastname)) $lastname=(isset($this->lastname)?$this->lastname:(isset($this->name)?$this->name:(isset($this->nom)?$this->nom:(isset($this->societe)?$this->societe:(isset($this->company)?$this->company:''))))); |
||
449 | |||
450 | $ret=''; |
||
451 | if ($option && $this->civility_id) |
||
452 | { |
||
453 | if ($langs->transnoentitiesnoconv("Civility".$this->civility_id)!="Civility".$this->civility_id) $ret.=$langs->transnoentitiesnoconv("Civility".$this->civility_id).' '; |
||
454 | else $ret.=$this->civility_id.' '; |
||
455 | } |
||
456 | |||
457 | $ret.=dolGetFirstLastname($firstname, $lastname, $nameorder); |
||
458 | |||
459 | return dol_trunc($ret,$maxlen); |
||
460 | } |
||
461 | |||
462 | /** |
||
463 | * Return full address of contact |
||
464 | * |
||
465 | * @param int $withcountry 1=Add country into address string |
||
466 | * @param string $sep Separator to use to build string |
||
467 | * @param int $withregion 1=Add region into address string |
||
468 | * @return string Full address string |
||
469 | */ |
||
470 | function getFullAddress($withcountry=0, $sep="\n", $withregion=0) |
||
471 | { |
||
472 | if ($withcountry && $this->country_id && (empty($this->country_code) || empty($this->country))) |
||
473 | { |
||
474 | require_once DOL_DOCUMENT_ROOT .'/core/lib/company.lib.php'; |
||
475 | $tmparray=getCountry($this->country_id,'all'); |
||
476 | $this->country_code=$tmparray['code']; |
||
477 | $this->country =$tmparray['label']; |
||
478 | } |
||
479 | |||
480 | if ($withregion && $this->state_id && (empty($this->state_code) || empty($this->state) || empty($this->region) || empty($this->region_cpde))) |
||
481 | { |
||
482 | require_once DOL_DOCUMENT_ROOT .'/core/lib/company.lib.php'; |
||
483 | $tmparray=getState($this->state_id,'all',0,1); |
||
484 | $this->state_code =$tmparray['code']; |
||
485 | $this->state =$tmparray['label']; |
||
486 | $this->region_code =$tmparray['region_code']; |
||
487 | $this->region =$tmparray['region']; |
||
488 | } |
||
489 | |||
490 | return dol_format_address($this, $withcountry, $sep); |
||
491 | } |
||
492 | |||
493 | |||
494 | /** |
||
495 | * Return full address for banner |
||
496 | * |
||
497 | * @param string $htmlkey HTML id to make banner content unique |
||
498 | * @param Object $object Object (thirdparty, thirdparty of contact for contact, null for a member) |
||
499 | * @return string Full address string |
||
500 | */ |
||
501 | function getBannerAddress($htmlkey, $object) |
||
502 | { |
||
503 | global $conf, $langs; |
||
504 | |||
505 | $countriesusingstate=array('AU','US','IN','GB','ES','UK','TR'); // See also option MAIN_FORCE_STATE_INTO_ADDRESS |
||
506 | |||
507 | $contactid=0; |
||
508 | $thirdpartyid=0; |
||
509 | if ($this->element == 'societe') |
||
510 | { |
||
511 | $thirdpartyid=$this->id; |
||
512 | } |
||
513 | if ($this->element == 'contact') |
||
514 | { |
||
515 | $contactid=$this->id; |
||
516 | $thirdpartyid=$object->fk_soc; |
||
517 | } |
||
518 | if ($this->element == 'user') |
||
519 | { |
||
520 | $contactid=$this->contact_id; |
||
521 | $thirdpartyid=$object->fk_soc; |
||
522 | } |
||
523 | |||
524 | $out='<!-- BEGIN part to show address block -->'; |
||
525 | |||
526 | $outdone=0; |
||
527 | $coords = $this->getFullAddress(1,', ',$conf->global->MAIN_SHOW_REGION_IN_STATE_SELECT); |
||
528 | if ($coords) |
||
529 | { |
||
530 | if (! empty($conf->use_javascript_ajax)) |
||
531 | { |
||
532 | $namecoords = $this->getFullName($langs,1).'<br>'.$coords; |
||
533 | // hideonsmatphone because copyToClipboard call jquery dialog that does not work with jmobile |
||
534 | $out.='<a href="#" class="hideonsmartphone" onclick="return copyToClipboard(\''.dol_escape_js($namecoords).'\',\''.dol_escape_js($langs->trans("HelpCopyToClipboard")).'\');">'; |
||
535 | $out.=img_picto($langs->trans("Address"), 'object_address.png'); |
||
536 | $out.='</a> '; |
||
537 | } |
||
538 | $out.=dol_print_address($coords, 'address_'.$htmlkey.'_'.$this->id, $this->element, $this->id, 1, ', '); $outdone++; |
||
539 | $outdone++; |
||
540 | } |
||
541 | |||
542 | if (! in_array($this->country_code,$countriesusingstate) && empty($conf->global->MAIN_FORCE_STATE_INTO_ADDRESS) // If MAIN_FORCE_STATE_INTO_ADDRESS is on, state is already returned previously with getFullAddress |
||
543 | && empty($conf->global->SOCIETE_DISABLE_STATE) && $this->state) |
||
544 | { |
||
545 | if (!empty($conf->global->MAIN_SHOW_REGION_IN_STATE_SELECT) && $conf->global->MAIN_SHOW_REGION_IN_STATE_SELECT == 1 && $this->region) { |
||
546 | $out.=($outdone?' - ':'').$this->region.' - '.$this->state; |
||
547 | } |
||
548 | else { |
||
549 | $out.=($outdone?' - ':'').$this->state; |
||
550 | } |
||
551 | $outdone++; |
||
552 | } |
||
553 | |||
554 | if (! empty($this->phone) || ! empty($this->phone_pro) || ! empty($this->phone_mobile) || ! empty($this->phone_perso) || ! empty($this->fax) || ! empty($this->office_phone) || ! empty($this->user_mobile) || ! empty($this->office_fax)) $out.=($outdone?'<br>':''); |
||
555 | if (! empty($this->phone) && empty($this->phone_pro)) { // For objects that store pro phone into ->phone |
||
556 | $out.=dol_print_phone($this->phone,$this->country_code,$contactid,$thirdpartyid,'AC_TEL',' ','phone',$langs->trans("PhonePro")); $outdone++; |
||
557 | } |
||
558 | if (! empty($this->phone_pro)) { |
||
559 | $out.=dol_print_phone($this->phone_pro,$this->country_code,$contactid,$thirdpartyid,'AC_TEL',' ','phone',$langs->trans("PhonePro")); $outdone++; |
||
560 | } |
||
561 | if (! empty($this->phone_mobile)) { |
||
562 | $out.=dol_print_phone($this->phone_mobile,$this->country_code,$contactid,$thirdpartyid,'AC_TEL',' ','mobile',$langs->trans("PhoneMobile")); $outdone++; |
||
563 | } |
||
564 | if (! empty($this->phone_perso)) { |
||
565 | $out.=dol_print_phone($this->phone_perso,$this->country_code,$contactid,$thirdpartyid,'AC_TEL',' ','phone',$langs->trans("PhonePerso")); $outdone++; |
||
566 | } |
||
567 | if (! empty($this->office_phone)) { |
||
568 | $out.=dol_print_phone($this->office_phone,$this->country_code,$contactid,$thirdpartyid,'AC_TEL',' ','phone',$langs->trans("PhonePro")); $outdone++; |
||
569 | } |
||
570 | if (! empty($this->user_mobile)) { |
||
571 | $out.=dol_print_phone($this->user_mobile,$this->country_code,$contactid,$thirdpartyid,'AC_TEL',' ','mobile',$langs->trans("PhoneMobile")); $outdone++; |
||
572 | } |
||
573 | if (! empty($this->fax)) { |
||
574 | $out.=dol_print_phone($this->fax,$this->country_code,$contactid,$thirdpartyid,'AC_FAX',' ','fax',$langs->trans("Fax")); $outdone++; |
||
575 | } |
||
576 | if (! empty($this->office_fax)) { |
||
577 | $out.=dol_print_phone($this->office_fax,$this->country_code,$contactid,$thirdpartyid,'AC_FAX',' ','fax',$langs->trans("Fax")); $outdone++; |
||
578 | } |
||
579 | |||
580 | $out.='<div style="clear: both;"></div>'; |
||
581 | $outdone=0; |
||
582 | if (! empty($this->email)) |
||
583 | { |
||
584 | $out.=dol_print_email($this->email,$this->id,$object->id,'AC_EMAIL',0,0,1); |
||
585 | $outdone++; |
||
586 | } |
||
587 | if (! empty($this->url)) |
||
588 | { |
||
589 | $out.=dol_print_url($this->url,'_goout',0,1); |
||
590 | $outdone++; |
||
591 | } |
||
592 | $out.='<div style="clear: both;">'; |
||
593 | if (! empty($conf->socialnetworks->enabled)) |
||
594 | { |
||
595 | if ($this->skype) $out.=dol_print_socialnetworks($this->skype,$this->id,$object->id,'skype'); |
||
596 | $outdone++; |
||
597 | if ($this->jabberid) $out.=dol_print_socialnetworks($this->jabberid,$this->id,$object->id,'jabber'); |
||
598 | $outdone++; |
||
599 | if ($this->twitter) $out.=dol_print_socialnetworks($this->twitter,$this->id,$object->id,'twitter'); |
||
600 | $outdone++; |
||
601 | if ($this->facebook) $out.=dol_print_socialnetworks($this->facebook,$this->id,$object->id,'facebook'); |
||
602 | $outdone++; |
||
603 | } |
||
604 | $out.='</div>'; |
||
605 | |||
606 | $out.='<!-- END Part to show address block -->'; |
||
607 | |||
608 | return $out; |
||
609 | } |
||
610 | |||
611 | /** |
||
612 | * Return the link of last main doc file for direct public download. |
||
613 | * |
||
614 | * @param string $modulepart Module related to document |
||
615 | * @param int $initsharekey Init the share key if it was not yet defined |
||
616 | * @param int $relativelink 0=Return full external link, 1=Return link relative to root of file |
||
617 | * @return string Link or empty string if there is no download link |
||
618 | */ |
||
619 | function getLastMainDocLink($modulepart, $initsharekey=0, $relativelink=0) |
||
620 | { |
||
621 | global $user, $dolibarr_main_url_root; |
||
622 | |||
623 | if (empty($this->last_main_doc)) |
||
624 | { |
||
625 | return ''; // No way to known which document name to use |
||
626 | } |
||
627 | |||
628 | include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php'; |
||
629 | $ecmfile=new EcmFiles($this->db); |
||
630 | $result = $ecmfile->fetch(0, '', $this->last_main_doc); |
||
631 | if ($result < 0) |
||
632 | { |
||
633 | $this->error = $ecmfile->error; |
||
634 | $this->errors = $ecmfile->errors; |
||
635 | return -1; |
||
636 | } |
||
637 | |||
638 | if (empty($ecmfile->id)) |
||
639 | { |
||
640 | // Add entry into index |
||
641 | if ($initsharekey) |
||
642 | { |
||
643 | require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; |
||
644 | // TODO We can't, we dont' have full path of file, only last_main_doc adn ->element, so we must rebuild full path first |
||
645 | /* |
||
646 | $ecmfile->filepath = $rel_dir; |
||
647 | $ecmfile->filename = $filename; |
||
648 | $ecmfile->label = md5_file(dol_osencode($destfull)); // hash of file content |
||
649 | $ecmfile->fullpath_orig = ''; |
||
650 | $ecmfile->gen_or_uploaded = 'generated'; |
||
651 | $ecmfile->description = ''; // indexed content |
||
652 | $ecmfile->keyword = ''; // keyword content |
||
653 | $ecmfile->share = getRandomPassword(true); |
||
654 | $result = $ecmfile->create($user); |
||
655 | if ($result < 0) |
||
656 | { |
||
657 | $this->error = $ecmfile->error; |
||
658 | $this->errors = $ecmfile->errors; |
||
659 | } |
||
660 | */ |
||
661 | } |
||
662 | else return ''; |
||
663 | } |
||
664 | elseif (empty($ecmfile->share)) |
||
665 | { |
||
666 | // Add entry into index |
||
667 | if ($initsharekey) |
||
668 | { |
||
669 | require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; |
||
670 | $ecmfile->share = getRandomPassword(true); |
||
671 | $ecmfile->update($user); |
||
672 | } |
||
673 | else return ''; |
||
674 | } |
||
675 | |||
676 | // Define $urlwithroot |
||
677 | $urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root)); |
||
678 | $urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file |
||
679 | //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current |
||
680 | |||
681 | $forcedownload=0; |
||
682 | |||
683 | $paramlink=''; |
||
684 | //if (! empty($modulepart)) $paramlink.=($paramlink?'&':'').'modulepart='.$modulepart; // For sharing with hash (so public files), modulepart is not required. |
||
685 | //if (! empty($ecmfile->entity)) $paramlink.='&entity='.$ecmfile->entity; // For sharing with hash (so public files), entity is not required. |
||
686 | //$paramlink.=($paramlink?'&':'').'file='.urlencode($filepath); // No need of name of file for public link, we will use the hash |
||
687 | if (! empty($ecmfile->share)) $paramlink.=($paramlink?'&':'').'hashp='.$ecmfile->share; // Hash for public share |
||
688 | if ($forcedownload) $paramlink.=($paramlink?'&':'').'attachment=1'; |
||
689 | |||
690 | if ($relativelink) |
||
691 | { |
||
692 | $linktoreturn='document.php'.($paramlink?'?'.$paramlink:''); |
||
693 | } |
||
694 | else |
||
695 | { |
||
696 | $linktoreturn=$urlwithroot.'/document.php'.($paramlink?'?'.$paramlink:''); |
||
697 | } |
||
698 | |||
699 | // Here $ecmfile->share is defined |
||
700 | return $linktoreturn; |
||
701 | } |
||
702 | |||
703 | |||
704 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
705 | /** |
||
706 | * Add a link between element $this->element and a contact |
||
707 | * |
||
708 | * @param int $fk_socpeople Id of thirdparty contact (if source = 'external') or id of user (if souce = 'internal') to link |
||
709 | * @param int $type_contact Type of contact (code or id). Must be id or code found into table llx_c_type_contact. For example: SALESREPFOLL |
||
710 | * @param string $source external=Contact extern (llx_socpeople), internal=Contact intern (llx_user) |
||
711 | * @param int $notrigger Disable all triggers |
||
712 | * @return int <0 if KO, >0 if OK |
||
713 | */ |
||
714 | function add_contact($fk_socpeople, $type_contact, $source='external',$notrigger=0) |
||
715 | { |
||
716 | // phpcs:enable |
||
717 | global $user,$langs; |
||
718 | |||
719 | |||
720 | dol_syslog(get_class($this)."::add_contact $fk_socpeople, $type_contact, $source, $notrigger"); |
||
721 | |||
722 | // Check parameters |
||
723 | if ($fk_socpeople <= 0) |
||
724 | { |
||
725 | $langs->load("errors"); |
||
726 | $this->error=$langs->trans("ErrorWrongValueForParameterX","1"); |
||
727 | dol_syslog(get_class($this)."::add_contact ".$this->error,LOG_ERR); |
||
728 | return -1; |
||
729 | } |
||
730 | if (! $type_contact) |
||
731 | { |
||
732 | $langs->load("errors"); |
||
733 | $this->error=$langs->trans("ErrorWrongValueForParameterX","2"); |
||
734 | dol_syslog(get_class($this)."::add_contact ".$this->error,LOG_ERR); |
||
735 | return -2; |
||
736 | } |
||
737 | |||
738 | $id_type_contact=0; |
||
739 | if (is_numeric($type_contact)) |
||
740 | { |
||
741 | $id_type_contact=$type_contact; |
||
742 | } |
||
743 | else |
||
744 | { |
||
745 | // We look for id type_contact |
||
746 | $sql = "SELECT tc.rowid"; |
||
747 | $sql.= " FROM ".MAIN_DB_PREFIX."c_type_contact as tc"; |
||
748 | $sql.= " WHERE tc.element='".$this->db->escape($this->element)."'"; |
||
749 | $sql.= " AND tc.source='".$this->db->escape($source)."'"; |
||
750 | $sql.= " AND tc.code='".$this->db->escape($type_contact)."' AND tc.active=1"; |
||
751 | //print $sql; |
||
752 | $resql=$this->db->query($sql); |
||
753 | if ($resql) |
||
754 | { |
||
755 | $obj = $this->db->fetch_object($resql); |
||
756 | if ($obj) $id_type_contact=$obj->rowid; |
||
757 | } |
||
758 | } |
||
759 | |||
760 | if ($id_type_contact == 0) |
||
761 | { |
||
762 | $this->error='CODE_NOT_VALID_FOR_THIS_ELEMENT'; |
||
763 | dol_syslog("CODE_NOT_VALID_FOR_THIS_ELEMENT: Code type of contact '".$type_contact."' does not exists or is not active for element ".$this->element.", we can ignore it"); |
||
764 | return -3; |
||
765 | } |
||
766 | |||
767 | $datecreate = dol_now(); |
||
768 | |||
769 | // Socpeople must have already been added by some trigger, then we have to check it to avoid DB_ERROR_RECORD_ALREADY_EXISTS error |
||
770 | $TListeContacts=$this->liste_contact(-1, $source); |
||
771 | $already_added=false; |
||
772 | if(!empty($TListeContacts)) { |
||
773 | foreach($TListeContacts as $array_contact) { |
||
774 | if($array_contact['status'] == 4 && $array_contact['id'] == $fk_socpeople && $array_contact['fk_c_type_contact'] == $id_type_contact) { |
||
775 | $already_added=true; |
||
776 | break; |
||
777 | } |
||
778 | } |
||
779 | } |
||
780 | |||
781 | if(!$already_added) { |
||
782 | |||
783 | $this->db->begin(); |
||
784 | |||
785 | // Insert into database |
||
786 | $sql = "INSERT INTO ".MAIN_DB_PREFIX."element_contact"; |
||
787 | $sql.= " (element_id, fk_socpeople, datecreate, statut, fk_c_type_contact) "; |
||
788 | $sql.= " VALUES (".$this->id.", ".$fk_socpeople." , " ; |
||
789 | $sql.= "'".$this->db->idate($datecreate)."'"; |
||
790 | $sql.= ", 4, ". $id_type_contact; |
||
791 | $sql.= ")"; |
||
792 | |||
793 | $resql=$this->db->query($sql); |
||
794 | if ($resql) |
||
795 | { |
||
796 | if (! $notrigger) |
||
797 | { |
||
798 | $result=$this->call_trigger(strtoupper($this->element).'_ADD_CONTACT', $user); |
||
799 | if ($result < 0) |
||
800 | { |
||
801 | $this->db->rollback(); |
||
802 | return -1; |
||
803 | } |
||
804 | } |
||
805 | |||
806 | $this->db->commit(); |
||
807 | return 1; |
||
808 | } |
||
809 | else |
||
810 | { |
||
811 | if ($this->db->errno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') |
||
812 | { |
||
813 | $this->error=$this->db->errno(); |
||
814 | $this->db->rollback(); |
||
815 | echo 'err rollback'; |
||
816 | return -2; |
||
817 | } |
||
818 | else |
||
819 | { |
||
820 | $this->error=$this->db->error(); |
||
821 | $this->db->rollback(); |
||
822 | return -1; |
||
823 | } |
||
824 | } |
||
825 | } else return 0; |
||
826 | } |
||
827 | |||
828 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
829 | /** |
||
830 | * Copy contact from one element to current |
||
831 | * |
||
832 | * @param CommonObject $objFrom Source element |
||
833 | * @param string $source Nature of contact ('internal' or 'external') |
||
834 | * @return int >0 if OK, <0 if KO |
||
835 | */ |
||
836 | function copy_linked_contact($objFrom, $source='internal') |
||
837 | { |
||
838 | // phpcs:enable |
||
839 | $contacts = $objFrom->liste_contact(-1, $source); |
||
840 | foreach($contacts as $contact) |
||
841 | { |
||
842 | if ($this->add_contact($contact['id'], $contact['fk_c_type_contact'], $contact['source']) < 0) |
||
843 | { |
||
844 | $this->error=$this->db->lasterror(); |
||
845 | return -1; |
||
846 | } |
||
847 | } |
||
848 | return 1; |
||
849 | } |
||
850 | |||
851 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
852 | /** |
||
853 | * Update a link to contact line |
||
854 | * |
||
855 | * @param int $rowid Id of line contact-element |
||
856 | * @param int $statut New status of link |
||
857 | * @param int $type_contact_id Id of contact type (not modified if 0) |
||
858 | * @param int $fk_socpeople Id of soc_people to update (not modified if 0) |
||
859 | * @return int <0 if KO, >= 0 if OK |
||
860 | */ |
||
861 | function update_contact($rowid, $statut, $type_contact_id=0, $fk_socpeople=0) |
||
862 | { |
||
863 | // phpcs:enable |
||
864 | // Insert into database |
||
865 | $sql = "UPDATE ".MAIN_DB_PREFIX."element_contact set"; |
||
866 | $sql.= " statut = ".$statut; |
||
867 | if ($type_contact_id) $sql.= ", fk_c_type_contact = '".$type_contact_id ."'"; |
||
868 | if ($fk_socpeople) $sql.= ", fk_socpeople = '".$fk_socpeople ."'"; |
||
869 | $sql.= " where rowid = ".$rowid; |
||
870 | $resql=$this->db->query($sql); |
||
871 | if ($resql) |
||
872 | { |
||
873 | return 0; |
||
874 | } |
||
875 | else |
||
876 | { |
||
877 | $this->error=$this->db->lasterror(); |
||
878 | return -1; |
||
879 | } |
||
880 | } |
||
881 | |||
882 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
883 | /** |
||
884 | * Delete a link to contact line |
||
885 | * |
||
886 | * @param int $rowid Id of contact link line to delete |
||
887 | * @param int $notrigger Disable all triggers |
||
888 | * @return int >0 if OK, <0 if KO |
||
889 | */ |
||
890 | function delete_contact($rowid, $notrigger=0) |
||
891 | { |
||
892 | // phpcs:enable |
||
893 | global $user; |
||
894 | |||
895 | |||
896 | $this->db->begin(); |
||
897 | |||
898 | $sql = "DELETE FROM ".MAIN_DB_PREFIX."element_contact"; |
||
899 | $sql.= " WHERE rowid =".$rowid; |
||
900 | |||
901 | dol_syslog(get_class($this)."::delete_contact", LOG_DEBUG); |
||
902 | if ($this->db->query($sql)) |
||
903 | { |
||
904 | if (! $notrigger) |
||
905 | { |
||
906 | $result=$this->call_trigger(strtoupper($this->element).'_DELETE_CONTACT', $user); |
||
907 | if ($result < 0) { $this->db->rollback(); return -1; } |
||
908 | } |
||
909 | |||
910 | $this->db->commit(); |
||
911 | return 1; |
||
912 | } |
||
913 | else |
||
914 | { |
||
915 | $this->error=$this->db->lasterror(); |
||
916 | $this->db->rollback(); |
||
917 | return -1; |
||
918 | } |
||
919 | } |
||
920 | |||
921 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
922 | /** |
||
923 | * Delete all links between an object $this and all its contacts |
||
924 | * |
||
925 | * @param string $source '' or 'internal' or 'external' |
||
926 | * @param string $code Type of contact (code or id) |
||
927 | * @return int >0 if OK, <0 if KO |
||
928 | */ |
||
929 | function delete_linked_contact($source='',$code='') |
||
930 | { |
||
931 | // phpcs:enable |
||
932 | $temp = array(); |
||
933 | $typeContact = $this->liste_type_contact($source,'',0,0,$code); |
||
934 | |||
935 | foreach($typeContact as $key => $value) |
||
936 | { |
||
937 | array_push($temp,$key); |
||
938 | } |
||
939 | $listId = implode(",", $temp); |
||
940 | |||
941 | $sql = "DELETE FROM ".MAIN_DB_PREFIX."element_contact"; |
||
942 | $sql.= " WHERE element_id = ".$this->id; |
||
943 | if ($listId) |
||
944 | $sql.= " AND fk_c_type_contact IN (".$listId.")"; |
||
945 | |||
946 | dol_syslog(get_class($this)."::delete_linked_contact", LOG_DEBUG); |
||
947 | if ($this->db->query($sql)) |
||
948 | { |
||
949 | return 1; |
||
950 | } |
||
951 | else |
||
952 | { |
||
953 | $this->error=$this->db->lasterror(); |
||
954 | return -1; |
||
955 | } |
||
956 | } |
||
957 | |||
958 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
959 | /** |
||
960 | * Get array of all contacts for an object |
||
961 | * |
||
962 | * @param int $statut Status of links to get (-1=all) |
||
963 | * @param string $source Source of contact: external or thirdparty (llx_socpeople) or internal (llx_user) |
||
964 | * @param int $list 0:Return array contains all properties, 1:Return array contains just id |
||
965 | * @param string $code Filter on this code of contact type ('SHIPPING', 'BILLING', ...) |
||
966 | * @return array|int Array of contacts, -1 if error |
||
967 | */ |
||
968 | function liste_contact($statut=-1,$source='external',$list=0,$code='') |
||
969 | { |
||
970 | // phpcs:enable |
||
971 | global $langs; |
||
972 | |||
973 | $tab=array(); |
||
974 | |||
975 | $sql = "SELECT ec.rowid, ec.statut as statuslink, ec.fk_socpeople as id, ec.fk_c_type_contact"; // This field contains id of llx_socpeople or id of llx_user |
||
976 | if ($source == 'internal') $sql.=", '-1' as socid, t.statut as statuscontact, t.login, t.photo"; |
||
977 | if ($source == 'external' || $source == 'thirdparty') $sql.=", t.fk_soc as socid, t.statut as statuscontact"; |
||
978 | $sql.= ", t.civility as civility, t.lastname as lastname, t.firstname, t.email"; |
||
979 | $sql.= ", tc.source, tc.element, tc.code, tc.libelle"; |
||
980 | $sql.= " FROM ".MAIN_DB_PREFIX."c_type_contact tc"; |
||
981 | $sql.= ", ".MAIN_DB_PREFIX."element_contact ec"; |
||
982 | if ($source == 'internal') $sql.=" LEFT JOIN ".MAIN_DB_PREFIX."user t on ec.fk_socpeople = t.rowid"; |
||
983 | if ($source == 'external'|| $source == 'thirdparty') $sql.=" LEFT JOIN ".MAIN_DB_PREFIX."socpeople t on ec.fk_socpeople = t.rowid"; |
||
984 | $sql.= " WHERE ec.element_id =".$this->id; |
||
985 | $sql.= " AND ec.fk_c_type_contact=tc.rowid"; |
||
986 | $sql.= " AND tc.element='".$this->db->escape($this->element)."'"; |
||
987 | if ($code) $sql.= " AND tc.code = '".$this->db->escape($code)."'"; |
||
988 | if ($source == 'internal') $sql.= " AND tc.source = 'internal'"; |
||
989 | if ($source == 'external' || $source == 'thirdparty') $sql.= " AND tc.source = 'external'"; |
||
990 | $sql.= " AND tc.active=1"; |
||
991 | if ($statut >= 0) $sql.= " AND ec.statut = '".$statut."'"; |
||
992 | $sql.=" ORDER BY t.lastname ASC"; |
||
993 | |||
994 | dol_syslog(get_class($this)."::liste_contact", LOG_DEBUG); |
||
995 | $resql=$this->db->query($sql); |
||
996 | if ($resql) |
||
997 | { |
||
998 | $num=$this->db->num_rows($resql); |
||
999 | $i=0; |
||
1000 | while ($i < $num) |
||
1001 | { |
||
1002 | $obj = $this->db->fetch_object($resql); |
||
1003 | |||
1004 | if (! $list) |
||
1005 | { |
||
1006 | $transkey="TypeContact_".$obj->element."_".$obj->source."_".$obj->code; |
||
1007 | $libelle_type=($langs->trans($transkey)!=$transkey ? $langs->trans($transkey) : $obj->libelle); |
||
1008 | $tab[$i]=array('source'=>$obj->source,'socid'=>$obj->socid,'id'=>$obj->id, |
||
1009 | 'nom'=>$obj->lastname, // For backward compatibility |
||
1010 | 'civility'=>$obj->civility, 'lastname'=>$obj->lastname, 'firstname'=>$obj->firstname, 'email'=>$obj->email, 'login'=>$obj->login, 'photo'=>$obj->photo, 'statuscontact'=>$obj->statuscontact, |
||
1011 | 'rowid'=>$obj->rowid, 'code'=>$obj->code, 'libelle'=>$libelle_type, 'status'=>$obj->statuslink, 'fk_c_type_contact'=>$obj->fk_c_type_contact); |
||
1012 | } |
||
1013 | else |
||
1014 | { |
||
1015 | $tab[$i]=$obj->id; |
||
1016 | } |
||
1017 | |||
1018 | $i++; |
||
1019 | } |
||
1020 | |||
1021 | return $tab; |
||
1022 | } |
||
1023 | else |
||
1024 | { |
||
1025 | $this->error=$this->db->lasterror(); |
||
1026 | dol_print_error($this->db); |
||
1027 | return -1; |
||
1028 | } |
||
1029 | } |
||
1030 | |||
1031 | |||
1032 | /** |
||
1033 | * Update status of a contact linked to object |
||
1034 | * |
||
1035 | * @param int $rowid Id of link between object and contact |
||
1036 | * @return int <0 if KO, >=0 if OK |
||
1037 | */ |
||
1038 | function swapContactStatus($rowid) |
||
1039 | { |
||
1040 | $sql = "SELECT ec.datecreate, ec.statut, ec.fk_socpeople, ec.fk_c_type_contact,"; |
||
1041 | $sql.= " tc.code, tc.libelle"; |
||
1042 | //$sql.= ", s.fk_soc"; |
||
1043 | $sql.= " FROM (".MAIN_DB_PREFIX."element_contact as ec, ".MAIN_DB_PREFIX."c_type_contact as tc)"; |
||
1044 | //$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."socpeople as s ON ec.fk_socpeople=s.rowid"; // Si contact de type external, alors il est lie a une societe |
||
1045 | $sql.= " WHERE ec.rowid =".$rowid; |
||
1046 | $sql.= " AND ec.fk_c_type_contact=tc.rowid"; |
||
1047 | $sql.= " AND tc.element = '".$this->db->escape($this->element)."'"; |
||
1048 | |||
1049 | dol_syslog(get_class($this)."::swapContactStatus", LOG_DEBUG); |
||
1050 | $resql=$this->db->query($sql); |
||
1051 | if ($resql) |
||
1052 | { |
||
1053 | $obj = $this->db->fetch_object($resql); |
||
1054 | $newstatut = ($obj->statut == 4) ? 5 : 4; |
||
1055 | $result = $this->update_contact($rowid, $newstatut); |
||
1056 | $this->db->free($resql); |
||
1057 | return $result; |
||
1058 | } |
||
1059 | else |
||
1060 | { |
||
1061 | $this->error=$this->db->error(); |
||
1062 | dol_print_error($this->db); |
||
1063 | return -1; |
||
1064 | } |
||
1065 | } |
||
1066 | |||
1067 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
1068 | /** |
||
1069 | * Return array with list of possible values for type of contacts |
||
1070 | * |
||
1071 | * @param string $source 'internal', 'external' or 'all' |
||
1072 | * @param string $order Sort order by : 'position', 'code', 'rowid'... |
||
1073 | * @param int $option 0=Return array id->label, 1=Return array code->label |
||
1074 | * @param int $activeonly 0=all status of contact, 1=only the active |
||
1075 | * @param string $code Type of contact (Example: 'CUSTOMER', 'SERVICE') |
||
1076 | * @return array Array list of type of contacts (id->label if option=0, code->label if option=1) |
||
1077 | */ |
||
1078 | function liste_type_contact($source='internal', $order='position', $option=0, $activeonly=0, $code='') |
||
1079 | { |
||
1080 | // phpcs:enable |
||
1081 | global $langs; |
||
1082 | |||
1083 | if (empty($order)) $order='position'; |
||
1084 | if ($order == 'position') $order.=',code'; |
||
1085 | |||
1086 | $tab = array(); |
||
1087 | $sql = "SELECT DISTINCT tc.rowid, tc.code, tc.libelle, tc.position"; |
||
1088 | $sql.= " FROM ".MAIN_DB_PREFIX."c_type_contact as tc"; |
||
1089 | $sql.= " WHERE tc.element='".$this->db->escape($this->element)."'"; |
||
1090 | if ($activeonly == 1) $sql.= " AND tc.active=1"; // only the active types |
||
1091 | if (! empty($source) && $source != 'all') $sql.= " AND tc.source='".$this->db->escape($source)."'"; |
||
1092 | if (! empty($code)) $sql.= " AND tc.code='".$this->db->escape($code)."'"; |
||
1093 | $sql.= $this->db->order($order,'ASC'); |
||
1094 | |||
1095 | //print "sql=".$sql; |
||
1096 | $resql=$this->db->query($sql); |
||
1097 | if ($resql) |
||
1098 | { |
||
1099 | $num=$this->db->num_rows($resql); |
||
1100 | $i=0; |
||
1101 | while ($i < $num) |
||
1102 | { |
||
1103 | $obj = $this->db->fetch_object($resql); |
||
1104 | |||
1105 | $transkey="TypeContact_".$this->element."_".$source."_".$obj->code; |
||
1106 | $libelle_type=($langs->trans($transkey)!=$transkey ? $langs->trans($transkey) : $obj->libelle); |
||
1107 | if (empty($option)) $tab[$obj->rowid]=$libelle_type; |
||
1108 | else $tab[$obj->code]=$libelle_type; |
||
1109 | $i++; |
||
1110 | } |
||
1111 | return $tab; |
||
1112 | } |
||
1113 | else |
||
1114 | { |
||
1115 | $this->error=$this->db->lasterror(); |
||
1116 | //dol_print_error($this->db); |
||
1117 | return null; |
||
1118 | } |
||
1119 | } |
||
1120 | |||
1121 | /** |
||
1122 | * Return id of contacts for a source and a contact code. |
||
1123 | * Example: contact client de facturation ('external', 'BILLING') |
||
1124 | * Example: contact client de livraison ('external', 'SHIPPING') |
||
1125 | * Example: contact interne suivi paiement ('internal', 'SALESREPFOLL') |
||
1126 | * |
||
1127 | * @param string $source 'external' or 'internal' |
||
1128 | * @param string $code 'BILLING', 'SHIPPING', 'SALESREPFOLL', ... |
||
1129 | * @param int $status limited to a certain status |
||
1130 | * @return array List of id for such contacts |
||
1131 | */ |
||
1132 | function getIdContact($source,$code,$status=0) |
||
1133 | { |
||
1134 | global $conf; |
||
1135 | |||
1136 | $result=array(); |
||
1137 | $i=0; |
||
1138 | //cas particulier pour les expeditions |
||
1139 | if($this->element=='shipping' && $this->origin_id != 0) { |
||
1140 | $id=$this->origin_id; |
||
1141 | $element='commande'; |
||
1142 | } else if($this->element=='reception' && $this->origin_id != 0) { |
||
1143 | $id=$this->origin_id; |
||
1144 | $element='order_supplier'; |
||
1145 | } else { |
||
1146 | $id=$this->id; |
||
1147 | $element=$this->element; |
||
1148 | } |
||
1149 | |||
1150 | $sql = "SELECT ec.fk_socpeople"; |
||
1151 | $sql.= " FROM ".MAIN_DB_PREFIX."element_contact as ec,"; |
||
1152 | if ($source == 'internal') $sql.= " ".MAIN_DB_PREFIX."user as c,"; |
||
1153 | if ($source == 'external') $sql.= " ".MAIN_DB_PREFIX."socpeople as c,"; |
||
1154 | $sql.= " ".MAIN_DB_PREFIX."c_type_contact as tc"; |
||
1155 | $sql.= " WHERE ec.element_id = ".$id; |
||
1156 | $sql.= " AND ec.fk_socpeople = c.rowid"; |
||
1157 | if ($source == 'internal') $sql.= " AND c.entity IN (".getEntity('user').")"; |
||
1158 | if ($source == 'external') $sql.= " AND c.entity IN (".getEntity('societe').")"; |
||
1159 | $sql.= " AND ec.fk_c_type_contact = tc.rowid"; |
||
1160 | $sql.= " AND tc.element = '".$element."'"; |
||
1161 | $sql.= " AND tc.source = '".$source."'"; |
||
1162 | $sql.= " AND tc.code = '".$code."'"; |
||
1163 | $sql.= " AND tc.active = 1"; |
||
1164 | if ($status) $sql.= " AND ec.statut = ".$status; |
||
1165 | |||
1166 | dol_syslog(get_class($this)."::getIdContact", LOG_DEBUG); |
||
1167 | $resql=$this->db->query($sql); |
||
1168 | if ($resql) |
||
1169 | { |
||
1170 | while ($obj = $this->db->fetch_object($resql)) |
||
1171 | { |
||
1172 | $result[$i]=$obj->fk_socpeople; |
||
1173 | $i++; |
||
1174 | } |
||
1175 | } |
||
1176 | else |
||
1177 | { |
||
1178 | $this->error=$this->db->error(); |
||
1179 | return null; |
||
1180 | } |
||
1181 | |||
1182 | return $result; |
||
1183 | } |
||
1184 | |||
1185 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
1186 | /** |
||
1187 | * Load object contact with id=$this->contactid into $this->contact |
||
1188 | * |
||
1189 | * @param int $contactid Id du contact. Use this->contactid if empty. |
||
1190 | * @return int <0 if KO, >0 if OK |
||
1191 | */ |
||
1192 | function fetch_contact($contactid=null) |
||
1193 | { |
||
1194 | // phpcs:enable |
||
1195 | if (empty($contactid)) $contactid=$this->contactid; |
||
1196 | |||
1197 | if (empty($contactid)) return 0; |
||
1198 | |||
1199 | require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; |
||
1200 | $contact = new Contact($this->db); |
||
1201 | $result=$contact->fetch($contactid); |
||
1202 | $this->contact = $contact; |
||
1203 | return $result; |
||
1204 | } |
||
1205 | |||
1206 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
1207 | /** |
||
1208 | * Load the third party of object, from id $this->socid or $this->fk_soc, into this->thirdparty |
||
1209 | * |
||
1210 | * @param int $force_thirdparty_id Force thirdparty id |
||
1211 | * @return int <0 if KO, >0 if OK |
||
1212 | */ |
||
1213 | function fetch_thirdparty($force_thirdparty_id=0) |
||
1214 | { |
||
1215 | // phpcs:enable |
||
1216 | global $conf; |
||
1217 | |||
1218 | if (empty($this->socid) && empty($this->fk_soc) && empty($this->fk_thirdparty) && empty($force_thirdparty_id)) |
||
1219 | return 0; |
||
1220 | |||
1221 | require_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php'; |
||
1222 | |||
1223 | $idtofetch = isset($this->socid) ? $this->socid : (isset($this->fk_soc) ? $this->fk_soc : $this->fk_thirdparty); |
||
1224 | if ($force_thirdparty_id) |
||
1225 | $idtofetch = $force_thirdparty_id; |
||
1226 | |||
1227 | if ($idtofetch) { |
||
1228 | $thirdparty = new Societe($this->db); |
||
1229 | $result = $thirdparty->fetch($idtofetch); |
||
1230 | $this->thirdparty = $thirdparty; |
||
1231 | |||
1232 | // Use first price level if level not defined for third party |
||
1233 | if (!empty($conf->global->PRODUIT_MULTIPRICES) && empty($this->thirdparty->price_level)) { |
||
1234 | $this->thirdparty->price_level = 1; |
||
1235 | } |
||
1236 | |||
1237 | return $result; |
||
1238 | } else |
||
1239 | return -1; |
||
1240 | } |
||
1241 | |||
1242 | |||
1243 | /** |
||
1244 | * Looks for an object with ref matching the wildcard provided |
||
1245 | * It does only work when $this->table_ref_field is set |
||
1246 | * |
||
1247 | * @param string $ref Wildcard |
||
1248 | * @return int >1 = OK, 0 = Not found or table_ref_field not defined, <0 = KO |
||
1249 | */ |
||
1250 | public function fetchOneLike($ref) |
||
1251 | { |
||
1252 | if (!$this->table_ref_field) { |
||
1253 | return 0; |
||
1254 | } |
||
1255 | |||
1256 | $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.$this->table_element.' WHERE '.$this->table_ref_field.' LIKE "'.$this->db->escape($ref).'" LIMIT 1'; |
||
1257 | |||
1258 | $query = $this->db->query($sql); |
||
1259 | |||
1260 | if (!$this->db->num_rows($query)) { |
||
1261 | return 0; |
||
1262 | } |
||
1263 | |||
1264 | $result = $this->db->fetch_object($query); |
||
1265 | |||
1266 | return $this->fetch($result->rowid); |
||
1267 | } |
||
1268 | |||
1269 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
1270 | /** |
||
1271 | * Load data for barcode into properties ->barcode_type* |
||
1272 | * Properties ->barcode_type that is id of barcode. Type is used to find other properties, but |
||
1273 | * if it is not defined, ->element must be defined to know default barcode type. |
||
1274 | * |
||
1275 | * @return int <0 if KO, 0 if can't guess type of barcode (ISBN, EAN13...), >0 if OK (all barcode properties loaded) |
||
1276 | */ |
||
1277 | function fetch_barcode() |
||
1278 | { |
||
1279 | // phpcs:enable |
||
1280 | global $conf; |
||
1281 | |||
1282 | dol_syslog(get_class($this).'::fetch_barcode this->element='.$this->element.' this->barcode_type='.$this->barcode_type); |
||
1283 | |||
1284 | $idtype=$this->barcode_type; |
||
1285 | if (empty($idtype) && $idtype != '0') // If type of barcode no set, we try to guess. If set to '0' it means we forced to have type remain not defined |
||
1286 | { |
||
1287 | if ($this->element == 'product') $idtype = $conf->global->PRODUIT_DEFAULT_BARCODE_TYPE; |
||
1288 | else if ($this->element == 'societe') $idtype = $conf->global->GENBARCODE_BARCODETYPE_THIRDPARTY; |
||
1289 | else dol_syslog('Call fetch_barcode with barcode_type not defined and cant be guessed', LOG_WARNING); |
||
1290 | } |
||
1291 | |||
1292 | if ($idtype > 0) |
||
1293 | { |
||
1294 | if (empty($this->barcode_type) || empty($this->barcode_type_code) || empty($this->barcode_type_label) || empty($this->barcode_type_coder)) // If data not already loaded |
||
1295 | { |
||
1296 | $sql = "SELECT rowid, code, libelle as label, coder"; |
||
1297 | $sql.= " FROM ".MAIN_DB_PREFIX."c_barcode_type"; |
||
1298 | $sql.= " WHERE rowid = ".$idtype; |
||
1299 | dol_syslog(get_class($this).'::fetch_barcode', LOG_DEBUG); |
||
1300 | $resql = $this->db->query($sql); |
||
1301 | if ($resql) |
||
1302 | { |
||
1303 | $obj = $this->db->fetch_object($resql); |
||
1304 | $this->barcode_type = $obj->rowid; |
||
1305 | $this->barcode_type_code = $obj->code; |
||
1306 | $this->barcode_type_label = $obj->label; |
||
1307 | $this->barcode_type_coder = $obj->coder; |
||
1308 | return 1; |
||
1309 | } |
||
1310 | else |
||
1311 | { |
||
1312 | dol_print_error($this->db); |
||
1313 | return -1; |
||
1314 | } |
||
1315 | } |
||
1316 | } |
||
1317 | return 0; |
||
1318 | } |
||
1319 | |||
1320 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
1321 | /** |
||
1322 | * Load the project with id $this->fk_project into this->project |
||
1323 | * |
||
1324 | * @return int <0 if KO, >=0 if OK |
||
1325 | */ |
||
1326 | function fetch_projet() |
||
1327 | { |
||
1328 | // phpcs:enable |
||
1329 | include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; |
||
1330 | |||
1331 | if (empty($this->fk_project) && ! empty($this->fk_projet)) $this->fk_project = $this->fk_projet; // For backward compatibility |
||
1332 | if (empty($this->fk_project)) return 0; |
||
1333 | |||
1334 | $project = new Project($this->db); |
||
1335 | $result = $project->fetch($this->fk_project); |
||
1336 | |||
1337 | $this->projet = $project; // deprecated |
||
1338 | $this->project = $project; |
||
1339 | return $result; |
||
1340 | } |
||
1341 | |||
1342 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
1343 | /** |
||
1344 | * Load the product with id $this->fk_product into this->product |
||
1345 | * |
||
1346 | * @return int <0 if KO, >=0 if OK |
||
1347 | */ |
||
1348 | function fetch_product() |
||
1349 | { |
||
1350 | // phpcs:enable |
||
1351 | include_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; |
||
1352 | |||
1353 | if (empty($this->fk_product)) return 0; |
||
1354 | |||
1355 | $product = new Product($this->db); |
||
1356 | $result = $product->fetch($this->fk_product); |
||
1357 | |||
1358 | $this->product = $product; |
||
1359 | return $result; |
||
1360 | } |
||
1361 | |||
1362 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
1363 | /** |
||
1364 | * Load the user with id $userid into this->user |
||
1365 | * |
||
1366 | * @param int $userid Id du contact |
||
1367 | * @return int <0 if KO, >0 if OK |
||
1368 | */ |
||
1369 | function fetch_user($userid) |
||
1370 | { |
||
1371 | // phpcs:enable |
||
1372 | $user = new User($this->db); |
||
1373 | $result=$user->fetch($userid); |
||
1374 | $this->user = $user; |
||
1375 | return $result; |
||
1376 | } |
||
1377 | |||
1378 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
1379 | /** |
||
1380 | * Read linked origin object |
||
1381 | * |
||
1382 | * @return void |
||
1383 | */ |
||
1384 | function fetch_origin() |
||
1385 | { |
||
1386 | // phpcs:enable |
||
1387 | if ($this->origin == 'shipping') $this->origin = 'expedition'; |
||
1388 | if ($this->origin == 'delivery') $this->origin = 'livraison'; |
||
1389 | if ($this->origin == 'order_supplier') $this->origin = 'commandeFournisseur'; |
||
1390 | |||
1391 | $origin = $this->origin; |
||
1392 | |||
1393 | $classname = ucfirst($origin); |
||
1394 | $this->$origin = new $classname($this->db); |
||
1395 | $this->$origin->fetch($this->origin_id); |
||
1396 | } |
||
1397 | |||
1398 | /** |
||
1399 | * Load object from specific field |
||
1400 | * |
||
1401 | * @param string $table Table element or element line |
||
1402 | * @param string $field Field selected |
||
1403 | * @param string $key Import key |
||
1404 | * @param string $element Element name |
||
1405 | * @return int <0 if KO, >0 if OK |
||
1406 | */ |
||
1407 | function fetchObjectFrom($table, $field, $key, $element = null) |
||
1408 | { |
||
1409 | global $conf; |
||
1410 | |||
1411 | $result=false; |
||
1412 | |||
1413 | $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX.$table; |
||
1414 | $sql.= " WHERE ".$field." = '".$key."'"; |
||
1415 | if (! empty($element)) { |
||
1416 | $sql.= " AND entity IN (".getEntity($element).")"; |
||
1417 | } else { |
||
1418 | $sql.= " AND entity = ".$conf->entity; |
||
1419 | } |
||
1420 | |||
1421 | dol_syslog(get_class($this).'::fetchObjectFrom', LOG_DEBUG); |
||
1422 | $resql = $this->db->query($sql); |
||
1423 | if ($resql) |
||
1424 | { |
||
1425 | $row = $this->db->fetch_row($resql); |
||
1426 | // Test for avoid error -1 |
||
1427 | if ($row[0] > 0) { |
||
1428 | $result = $this->fetch($row[0]); |
||
1429 | } |
||
1430 | } |
||
1431 | |||
1432 | return $result; |
||
1433 | } |
||
1434 | |||
1435 | /** |
||
1436 | * Getter generic. Load value from a specific field |
||
1437 | * |
||
1438 | * @param string $table Table of element or element line |
||
1439 | * @param int $id Element id |
||
1440 | * @param string $field Field selected |
||
1441 | * @return int <0 if KO, >0 if OK |
||
1442 | */ |
||
1443 | function getValueFrom($table, $id, $field) |
||
1444 | { |
||
1445 | $result=false; |
||
1446 | if (!empty($id) && !empty($field) && !empty($table)) { |
||
1447 | $sql = "SELECT ".$field." FROM ".MAIN_DB_PREFIX.$table; |
||
1448 | $sql.= " WHERE rowid = ".$id; |
||
1449 | |||
1450 | dol_syslog(get_class($this).'::getValueFrom', LOG_DEBUG); |
||
1451 | $resql = $this->db->query($sql); |
||
1452 | if ($resql) |
||
1453 | { |
||
1454 | $row = $this->db->fetch_row($resql); |
||
1455 | $result = $row[0]; |
||
1456 | } |
||
1457 | } |
||
1458 | return $result; |
||
1459 | } |
||
1460 | |||
1461 | /** |
||
1462 | * Setter generic. Update a specific field into database. |
||
1463 | * Warning: Trigger is run only if param trigkey is provided. |
||
1464 | * |
||
1465 | * @param string $field Field to update |
||
1466 | * @param mixed $value New value |
||
1467 | * @param string $table To force other table element or element line (should not be used) |
||
1468 | * @param int $id To force other object id (should not be used) |
||
1469 | * @param string $format Data format ('text', 'date'). 'text' is used if not defined |
||
1470 | * @param string $id_field To force rowid field name. 'rowid' is used if not defined |
||
1471 | * @param User|string $fuser Update the user of last update field with this user. If not provided, current user is used except if value is 'none' |
||
1472 | * @param string $trigkey Trigger key to run (in most cases something like 'XXX_MODIFY') |
||
1473 | * @param string $fk_user_field Name of field to save user id making change |
||
1474 | * @return int <0 if KO, >0 if OK |
||
1475 | * @see updateExtraField |
||
1476 | */ |
||
1477 | function setValueFrom($field, $value, $table='', $id=null, $format='', $id_field='', $fuser=null, $trigkey='', $fk_user_field='fk_user_modif') |
||
1478 | { |
||
1479 | global $user,$langs,$conf; |
||
1480 | |||
1481 | if (empty($table)) $table=$this->table_element; |
||
1482 | if (empty($id)) $id=$this->id; |
||
1483 | if (empty($format)) $format='text'; |
||
1484 | if (empty($id_field)) $id_field='rowid'; |
||
1485 | |||
1486 | $error=0; |
||
1487 | |||
1488 | $this->db->begin(); |
||
1489 | |||
1490 | // Special case |
||
1491 | if ($table == 'product' && $field == 'note_private') $field='note'; |
||
1492 | if (in_array($table, array('actioncomm', 'adherent', 'advtargetemailing', 'cronjob', 'establishment'))) $fk_user_field = 'fk_user_mod'; |
||
1493 | |||
1494 | $sql = "UPDATE ".MAIN_DB_PREFIX.$table." SET "; |
||
1495 | |||
1496 | if ($format == 'text') $sql.= $field." = '".$this->db->escape($value)."'"; |
||
1497 | else if ($format == 'int') $sql.= $field." = ".$this->db->escape($value); |
||
1498 | else if ($format == 'date') $sql.= $field." = ".($value ? "'".$this->db->idate($value)."'" : "null"); |
||
1499 | |||
1500 | if ($fk_user_field) |
||
1501 | { |
||
1502 | if (! empty($fuser) && is_object($fuser)) $sql.=", ".$fk_user_field." = ".$fuser->id; |
||
1503 | elseif (empty($fuser) || $fuser != 'none') $sql.=", ".$fk_user_field." = ".$user->id; |
||
1504 | } |
||
1505 | |||
1506 | $sql.= " WHERE ".$id_field." = ".$id; |
||
1507 | |||
1508 | dol_syslog(get_class($this)."::".__FUNCTION__."", LOG_DEBUG); |
||
1509 | $resql = $this->db->query($sql); |
||
1510 | if ($resql) |
||
1511 | { |
||
1512 | if ($trigkey) |
||
1513 | { |
||
1514 | // call trigger with updated object values |
||
1515 | if (empty($this->fields) && method_exists($this, 'fetch')) |
||
1516 | { |
||
1517 | $result = $this->fetch($id); |
||
1518 | } |
||
1519 | else |
||
1520 | { |
||
1521 | $result = $this->fetchCommon($id); |
||
1522 | } |
||
1523 | if ($result >= 0) $result=$this->call_trigger($trigkey, (! empty($fuser) && is_object($fuser)) ? $fuser : $user); // This may set this->errors |
||
1524 | if ($result < 0) $error++; |
||
1525 | } |
||
1526 | |||
1527 | if (! $error) |
||
1528 | { |
||
1529 | if (property_exists($this, $field)) $this->$field = $value; |
||
1530 | $this->db->commit(); |
||
1531 | return 1; |
||
1532 | } |
||
1533 | else |
||
1534 | { |
||
1535 | $this->db->rollback(); |
||
1536 | return -2; |
||
1537 | } |
||
1538 | } |
||
1539 | else |
||
1540 | { |
||
1541 | $this->error=$this->db->lasterror(); |
||
1542 | $this->db->rollback(); |
||
1543 | return -1; |
||
1544 | } |
||
1545 | } |
||
1546 | |||
1547 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
1548 | /** |
||
1549 | * Load properties id_previous and id_next by comparing $fieldid with $this->ref |
||
1550 | * |
||
1551 | * @param string $filter Optional filter. Example: " AND (t.field1 = 'aa' OR t.field2 = 'bb')" |
||
1552 | * @param string $fieldid Name of field to use for the select MAX and MIN |
||
1553 | * @param int $nodbprefix Do not include DB prefix to forge table name |
||
1554 | * @return int <0 if KO, >0 if OK |
||
1555 | */ |
||
1556 | function load_previous_next_ref($filter, $fieldid, $nodbprefix=0) |
||
1557 | { |
||
1558 | // phpcs:enable |
||
1559 | global $conf, $user; |
||
1560 | |||
1561 | if (! $this->table_element) |
||
1562 | { |
||
1563 | dol_print_error('',get_class($this)."::load_previous_next_ref was called on objet with property table_element not defined"); |
||
1564 | return -1; |
||
1565 | } |
||
1566 | if ($fieldid == 'none') return 1; |
||
1567 | |||
1568 | // Security on socid |
||
1569 | $socid = 0; |
||
1570 | if ($user->societe_id > 0) $socid = $user->societe_id; |
||
1571 | |||
1572 | // this->ismultientitymanaged contains |
||
1573 | // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe |
||
1574 | $alias = 's'; |
||
1575 | if ($this->element == 'societe') $alias = 'te'; |
||
1576 | |||
1577 | $sql = "SELECT MAX(te.".$fieldid.")"; |
||
1578 | $sql.= " FROM ".(empty($nodbprefix)?MAIN_DB_PREFIX:'').$this->table_element." as te"; |
||
1579 | if ($this->element == 'user' && ! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) { |
||
1580 | $sql.= ",".MAIN_DB_PREFIX."usergroup_user as ug"; |
||
1581 | } |
||
1582 | if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 2) $sql.= ", ".MAIN_DB_PREFIX."societe as s"; // If we need to link to societe to limit select to entity |
||
1583 | else if ($this->restrictiononfksoc == 1 && $this->element != 'societe' && !$user->rights->societe->client->voir && !$socid) $sql.= ", ".MAIN_DB_PREFIX."societe as s"; // If we need to link to societe to limit select to socid |
||
1584 | else if ($this->restrictiononfksoc == 2 && $this->element != 'societe' && !$user->rights->societe->client->voir && !$socid) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON te.fk_soc = s.rowid"; // If we need to link to societe to limit select to socid |
||
1585 | if ($this->restrictiononfksoc && !$user->rights->societe->client->voir && !$socid) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON ".$alias.".rowid = sc.fk_soc"; |
||
1586 | $sql.= " WHERE te.".$fieldid." < '".$this->db->escape($this->ref)."'"; // ->ref must always be defined (set to id if field does not exists) |
||
1587 | if ($this->restrictiononfksoc == 1 && !$user->rights->societe->client->voir && !$socid) $sql.= " AND sc.fk_user = " .$user->id; |
||
1588 | if ($this->restrictiononfksoc == 2 && !$user->rights->societe->client->voir && !$socid) $sql.= " AND (sc.fk_user = " .$user->id.' OR te.fk_soc IS NULL)'; |
||
1589 | if (! empty($filter)) |
||
1590 | { |
||
1591 | if (! preg_match('/^\s*AND/i', $filter)) $sql.=" AND "; // For backward compatibility |
||
1592 | $sql.=$filter; |
||
1593 | } |
||
1594 | if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 2) $sql.= ' AND te.fk_soc = s.rowid'; // If we need to link to societe to limit select to entity |
||
1595 | else if ($this->restrictiononfksoc == 1 && $this->element != 'societe' && !$user->rights->societe->client->voir && !$socid) $sql.= ' AND te.fk_soc = s.rowid'; // If we need to link to societe to limit select to socid |
||
1596 | if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { |
||
1597 | if ($this->element == 'user' && ! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) { |
||
1598 | if (! empty($user->admin) && empty($user->entity) && $conf->entity == 1) { |
||
1599 | $sql.= " AND te.entity IS NOT NULL"; // Show all users |
||
1600 | } else { |
||
1601 | $sql.= " AND ug.fk_user = te.rowid"; |
||
1602 | $sql.= " AND ug.entity IN (".getEntity($this->element).")"; |
||
1603 | } |
||
1604 | } else { |
||
1605 | $sql.= ' AND te.entity IN ('.getEntity($this->element).')'; |
||
1606 | } |
||
1607 | } |
||
1608 | if ($this->restrictiononfksoc == 1 && $socid && $this->element != 'societe') $sql.= ' AND te.fk_soc = ' . $socid; |
||
1609 | if ($this->restrictiononfksoc == 2 && $socid && $this->element != 'societe') $sql.= ' AND (te.fk_soc = ' . $socid.' OR te.fk_soc IS NULL)'; |
||
1610 | if ($this->restrictiononfksoc && $socid && $this->element == 'societe') $sql.= ' AND te.rowid = ' . $socid; |
||
1611 | //print 'socid='.$socid.' restrictiononfksoc='.$this->restrictiononfksoc.' ismultientitymanaged = '.$this->ismultientitymanaged.' filter = '.$filter.' -> '.$sql."<br>"; |
||
1612 | |||
1613 | $result = $this->db->query($sql); |
||
1614 | if (! $result) |
||
1615 | { |
||
1616 | $this->error=$this->db->lasterror(); |
||
1617 | return -1; |
||
1618 | } |
||
1619 | $row = $this->db->fetch_row($result); |
||
1620 | $this->ref_previous = $row[0]; |
||
1621 | |||
1622 | |||
1623 | $sql = "SELECT MIN(te.".$fieldid.")"; |
||
1624 | $sql.= " FROM ".(empty($nodbprefix)?MAIN_DB_PREFIX:'').$this->table_element." as te"; |
||
1625 | if ($this->element == 'user' && ! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) { |
||
1626 | $sql.= ",".MAIN_DB_PREFIX."usergroup_user as ug"; |
||
1627 | } |
||
1628 | if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 2) $sql.= ", ".MAIN_DB_PREFIX."societe as s"; // If we need to link to societe to limit select to entity |
||
1629 | else if ($this->restrictiononfksoc == 1 && $this->element != 'societe' && !$user->rights->societe->client->voir && !$socid) $sql.= ", ".MAIN_DB_PREFIX."societe as s"; // If we need to link to societe to limit select to socid |
||
1630 | else if ($this->restrictiononfksoc == 2 && $this->element != 'societe' && !$user->rights->societe->client->voir && !$socid) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON te.fk_soc = s.rowid"; // If we need to link to societe to limit select to socid |
||
1631 | if ($this->restrictiononfksoc && !$user->rights->societe->client->voir && !$socid) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON ".$alias.".rowid = sc.fk_soc"; |
||
1632 | $sql.= " WHERE te.".$fieldid." > '".$this->db->escape($this->ref)."'"; // ->ref must always be defined (set to id if field does not exists) |
||
1633 | if ($this->restrictiononfksoc == 1 && !$user->rights->societe->client->voir && !$socid) $sql.= " AND sc.fk_user = " .$user->id; |
||
1634 | if ($this->restrictiononfksoc == 2 && !$user->rights->societe->client->voir && !$socid) $sql.= " AND (sc.fk_user = " .$user->id.' OR te.fk_soc IS NULL)'; |
||
1635 | if (! empty($filter)) |
||
1636 | { |
||
1637 | if (! preg_match('/^\s*AND/i', $filter)) $sql.=" AND "; // For backward compatibility |
||
1638 | $sql.=$filter; |
||
1639 | } |
||
1640 | if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 2) $sql.= ' AND te.fk_soc = s.rowid'; // If we need to link to societe to limit select to entity |
||
1641 | else if ($this->restrictiononfksoc == 1 && $this->element != 'societe' && !$user->rights->societe->client->voir && !$socid) $sql.= ' AND te.fk_soc = s.rowid'; // If we need to link to societe to limit select to socid |
||
1642 | if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { |
||
1643 | if ($this->element == 'user' && ! empty($conf->global->MULTICOMPANY_TRANSVERSE_MODE)) { |
||
1644 | if (! empty($user->admin) && empty($user->entity) && $conf->entity == 1) { |
||
1645 | $sql.= " AND te.entity IS NOT NULL"; // Show all users |
||
1646 | } else { |
||
1647 | $sql.= " AND ug.fk_user = te.rowid"; |
||
1648 | $sql.= " AND ug.entity IN (".getEntity($this->element).")"; |
||
1649 | } |
||
1650 | } else { |
||
1651 | $sql.= ' AND te.entity IN ('.getEntity($this->element).')'; |
||
1652 | } |
||
1653 | } |
||
1654 | if ($this->restrictiononfksoc == 1 && $socid && $this->element != 'societe') $sql.= ' AND te.fk_soc = ' . $socid; |
||
1655 | if ($this->restrictiononfksoc == 2 && $socid && $this->element != 'societe') $sql.= ' AND (te.fk_soc = ' . $socid.' OR te.fk_soc IS NULL)'; |
||
1656 | if ($this->restrictiononfksoc && $socid && $this->element == 'societe') $sql.= ' AND te.rowid = ' . $socid; |
||
1657 | //print 'socid='.$socid.' restrictiononfksoc='.$this->restrictiononfksoc.' ismultientitymanaged = '.$this->ismultientitymanaged.' filter = '.$filter.' -> '.$sql."<br>"; |
||
1658 | // Rem: Bug in some mysql version: SELECT MIN(rowid) FROM llx_socpeople WHERE rowid > 1 when one row in database with rowid=1, returns 1 instead of null |
||
1659 | |||
1660 | $result = $this->db->query($sql); |
||
1661 | if (! $result) |
||
1662 | { |
||
1663 | $this->error=$this->db->lasterror(); |
||
1664 | return -2; |
||
1665 | } |
||
1666 | $row = $this->db->fetch_row($result); |
||
1667 | $this->ref_next = $row[0]; |
||
1668 | |||
1669 | return 1; |
||
1670 | } |
||
1671 | |||
1672 | |||
1673 | /** |
||
1674 | * Return list of id of contacts of object |
||
1675 | * |
||
1676 | * @param string $source Source of contact: external (llx_socpeople) or internal (llx_user) or thirdparty (llx_societe) |
||
1677 | * @return array Array of id of contacts (if source=external or internal) |
||
1678 | * Array of id of third parties with at least one contact on object (if source=thirdparty) |
||
1679 | */ |
||
1680 | function getListContactId($source='external') |
||
1681 | { |
||
1682 | $contactAlreadySelected = array(); |
||
1683 | $tab = $this->liste_contact(-1,$source); |
||
1684 | $num=count($tab); |
||
1685 | $i = 0; |
||
1686 | while ($i < $num) |
||
1687 | { |
||
1688 | if ($source == 'thirdparty') $contactAlreadySelected[$i] = $tab[$i]['socid']; |
||
1689 | else $contactAlreadySelected[$i] = $tab[$i]['id']; |
||
1690 | $i++; |
||
1691 | } |
||
1692 | return $contactAlreadySelected; |
||
1693 | } |
||
1694 | |||
1695 | |||
1696 | /** |
||
1697 | * Link element with a project |
||
1698 | * |
||
1699 | * @param int $projectid Project id to link element to |
||
1700 | * @return int <0 if KO, >0 if OK |
||
1701 | */ |
||
1702 | function setProject($projectid) |
||
1703 | { |
||
1704 | if (! $this->table_element) |
||
1705 | { |
||
1706 | dol_syslog(get_class($this)."::setProject was called on objet with property table_element not defined",LOG_ERR); |
||
1707 | return -1; |
||
1708 | } |
||
1709 | |||
1710 | $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; |
||
1711 | if ($this->table_element == 'actioncomm') |
||
1712 | { |
||
1713 | if ($projectid) $sql.= ' SET fk_project = '.$projectid; |
||
1714 | else $sql.= ' SET fk_project = NULL'; |
||
1715 | $sql.= ' WHERE id = '.$this->id; |
||
1716 | } |
||
1717 | else |
||
1718 | { |
||
1719 | if ($projectid) $sql.= ' SET fk_projet = '.$projectid; |
||
1720 | else $sql.= ' SET fk_projet = NULL'; |
||
1721 | $sql.= ' WHERE rowid = '.$this->id; |
||
1722 | } |
||
1723 | |||
1724 | dol_syslog(get_class($this)."::setProject", LOG_DEBUG); |
||
1725 | if ($this->db->query($sql)) |
||
1726 | { |
||
1727 | $this->fk_project = $projectid; |
||
1728 | return 1; |
||
1729 | } |
||
1730 | else |
||
1731 | { |
||
1732 | dol_print_error($this->db); |
||
1733 | return -1; |
||
1734 | } |
||
1735 | } |
||
1736 | |||
1737 | /** |
||
1738 | * Change the payments methods |
||
1739 | * |
||
1740 | * @param int $id Id of new payment method |
||
1741 | * @return int >0 if OK, <0 if KO |
||
1742 | */ |
||
1743 | function setPaymentMethods($id) |
||
1744 | { |
||
1745 | dol_syslog(get_class($this).'::setPaymentMethods('.$id.')'); |
||
1746 | if ($this->statut >= 0 || $this->element == 'societe') |
||
1747 | { |
||
1748 | // TODO uniformize field name |
||
1749 | $fieldname = 'fk_mode_reglement'; |
||
1750 | if ($this->element == 'societe') $fieldname = 'mode_reglement'; |
||
1751 | if (get_class($this) == 'Fournisseur') $fieldname = 'mode_reglement_supplier'; |
||
1752 | |||
1753 | $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; |
||
1754 | $sql .= ' SET '.$fieldname.' = '.$id; |
||
1755 | $sql .= ' WHERE rowid='.$this->id; |
||
1756 | |||
1757 | if ($this->db->query($sql)) |
||
1758 | { |
||
1759 | $this->mode_reglement_id = $id; |
||
1760 | // for supplier |
||
1761 | if (get_class($this) == 'Fournisseur') $this->mode_reglement_supplier_id = $id; |
||
1762 | return 1; |
||
1763 | } |
||
1764 | else |
||
1765 | { |
||
1766 | dol_syslog(get_class($this).'::setPaymentMethods Erreur '.$sql.' - '.$this->db->error()); |
||
1767 | $this->error=$this->db->error(); |
||
1768 | return -1; |
||
1769 | } |
||
1770 | } |
||
1771 | else |
||
1772 | { |
||
1773 | dol_syslog(get_class($this).'::setPaymentMethods, status of the object is incompatible'); |
||
1774 | $this->error='Status of the object is incompatible '.$this->statut; |
||
1775 | return -2; |
||
1776 | } |
||
1777 | } |
||
1778 | |||
1779 | /** |
||
1780 | * Change the multicurrency code |
||
1781 | * |
||
1782 | * @param string $code multicurrency code |
||
1783 | * @return int >0 if OK, <0 if KO |
||
1784 | */ |
||
1785 | function setMulticurrencyCode($code) |
||
1786 | { |
||
1787 | dol_syslog(get_class($this).'::setMulticurrencyCode('.$id.')'); |
||
1788 | if ($this->statut >= 0 || $this->element == 'societe') |
||
1789 | { |
||
1790 | $fieldname = 'multicurrency_code'; |
||
1791 | |||
1792 | $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; |
||
1793 | $sql .= ' SET '.$fieldname." = '".$this->db->escape($code)."'"; |
||
1794 | $sql .= ' WHERE rowid='.$this->id; |
||
1795 | |||
1796 | if ($this->db->query($sql)) |
||
1797 | { |
||
1798 | $this->multicurrency_code = $code; |
||
1799 | |||
1800 | list($fk_multicurrency, $rate) = MultiCurrency::getIdAndTxFromCode($this->db, $code); |
||
1801 | if ($rate) $this->setMulticurrencyRate($rate,2); |
||
1802 | |||
1803 | return 1; |
||
1804 | } |
||
1805 | else |
||
1806 | { |
||
1807 | dol_syslog(get_class($this).'::setMulticurrencyCode Erreur '.$sql.' - '.$this->db->error()); |
||
1808 | $this->error=$this->db->error(); |
||
1809 | return -1; |
||
1810 | } |
||
1811 | } |
||
1812 | else |
||
1813 | { |
||
1814 | dol_syslog(get_class($this).'::setMulticurrencyCode, status of the object is incompatible'); |
||
1815 | $this->error='Status of the object is incompatible '.$this->statut; |
||
1816 | return -2; |
||
1817 | } |
||
1818 | } |
||
1819 | |||
1820 | /** |
||
1821 | * Change the multicurrency rate |
||
1822 | * |
||
1823 | * @param double $rate multicurrency rate |
||
1824 | * @param int $mode mode 1 : amounts in company currency will be recalculated, mode 2 : amounts in foreign currency |
||
1825 | * @return int >0 if OK, <0 if KO |
||
1826 | */ |
||
1827 | function setMulticurrencyRate($rate, $mode=1) |
||
1828 | { |
||
1829 | dol_syslog(get_class($this).'::setMulticurrencyRate('.$id.')'); |
||
1830 | if ($this->statut >= 0 || $this->element == 'societe') |
||
1831 | { |
||
1832 | $fieldname = 'multicurrency_tx'; |
||
1833 | |||
1834 | $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; |
||
1835 | $sql .= ' SET '.$fieldname.' = '.$rate; |
||
1836 | $sql .= ' WHERE rowid='.$this->id; |
||
1837 | |||
1838 | if ($this->db->query($sql)) |
||
1839 | { |
||
1840 | $this->multicurrency_tx = $rate; |
||
1841 | |||
1842 | // Update line price |
||
1843 | if (!empty($this->lines)) |
||
1844 | { |
||
1845 | foreach ($this->lines as &$line) |
||
1846 | { |
||
1847 | if($mode == 1) { |
||
1848 | $line->subprice = 0; |
||
1849 | } |
||
1850 | |||
1851 | switch ($this->element) { |
||
1852 | case 'propal': |
||
1853 | $this->updateline( |
||
1854 | $line->id, $line->subprice, $line->qty, $line->remise_percent, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, |
||
1855 | ($line->description?$line->description:$line->desc), 'HT', $line->info_bits, $line->special_code, $line->fk_parent_line, |
||
1856 | $line->skip_update_total, $line->fk_fournprice, $line->pa_ht, $line->label, $line->product_type, $line->date_start, |
||
1857 | $line->date_end, $line->array_options, $line->fk_unit, $line->multicurrency_subprice |
||
1858 | ); |
||
1859 | break; |
||
1860 | case 'commande': |
||
1861 | $this->updateline( |
||
1862 | $line->id, ($line->description?$line->description:$line->desc), $line->subprice, $line->qty, $line->remise_percent, |
||
1863 | $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->date_start, $line->date_end, |
||
1864 | $line->product_type, $line->fk_parent_line, $line->skip_update_total, $line->fk_fournprice, $line->pa_ht, $line->label, |
||
1865 | $line->special_code, $line->array_options, $line->fk_unit, $line->multicurrency_subprice |
||
1866 | ); |
||
1867 | break; |
||
1868 | case 'facture': |
||
1869 | $this->updateline( |
||
1870 | $line->id, ($line->description?$line->description:$line->desc), $line->subprice, $line->qty, $line->remise_percent, |
||
1871 | $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, |
||
1872 | $line->product_type, $line->fk_parent_line, $line->skip_update_total, $line->fk_fournprice, $line->pa_ht, $line->label, |
||
1873 | $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit, $line->multicurrency_subprice |
||
1874 | ); |
||
1875 | break; |
||
1876 | case 'supplier_proposal': |
||
1877 | $this->updateline( |
||
1878 | $line->id, $line->subprice, $line->qty, $line->remise_percent, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, |
||
1879 | ($line->description?$line->description:$line->desc), 'HT', $line->info_bits, $line->special_code, $line->fk_parent_line, |
||
1880 | $line->skip_update_total, $line->fk_fournprice, $line->pa_ht, $line->label, $line->product_type, $line->array_options, |
||
1881 | $line->ref_fourn, $line->multicurrency_subprice |
||
1882 | ); |
||
1883 | break; |
||
1884 | case 'order_supplier': |
||
1885 | $this->updateline( |
||
1886 | $line->id, ($line->description?$line->description:$line->desc), $line->subprice, $line->qty, $line->remise_percent, |
||
1887 | $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, false, |
||
1888 | $line->date_start, $line->date_end, $line->array_options, $line->fk_unit, $line->multicurrency_subprice |
||
1889 | ); |
||
1890 | break; |
||
1891 | case 'invoice_supplier': |
||
1892 | $this->updateline( |
||
1893 | $line->id, ($line->description?$line->description:$line->desc), $line->subprice, $line->tva_tx, $line->localtax1_tx, |
||
1894 | $line->localtax2_tx, $line->qty, 0, 'HT', $line->info_bits, $line->product_type, $line->remise_percent, false, |
||
1895 | $line->date_start, $line->date_end, $line->array_options, $line->fk_unit, $line->multicurrency_subprice |
||
1896 | ); |
||
1897 | break; |
||
1898 | default: |
||
1899 | dol_syslog(get_class($this).'::setMulticurrencyRate no updateline defined', LOG_DEBUG); |
||
1900 | break; |
||
1901 | } |
||
1902 | } |
||
1903 | } |
||
1904 | |||
1905 | return 1; |
||
1906 | } |
||
1907 | else |
||
1908 | { |
||
1909 | dol_syslog(get_class($this).'::setMulticurrencyRate Erreur '.$sql.' - '.$this->db->error()); |
||
1910 | $this->error=$this->db->error(); |
||
1911 | return -1; |
||
1912 | } |
||
1913 | } |
||
1914 | else |
||
1915 | { |
||
1916 | dol_syslog(get_class($this).'::setMulticurrencyRate, status of the object is incompatible'); |
||
1917 | $this->error='Status of the object is incompatible '.$this->statut; |
||
1918 | return -2; |
||
1919 | } |
||
1920 | } |
||
1921 | |||
1922 | /** |
||
1923 | * Change the payments terms |
||
1924 | * |
||
1925 | * @param int $id Id of new payment terms |
||
1926 | * @return int >0 if OK, <0 if KO |
||
1927 | */ |
||
1928 | function setPaymentTerms($id) |
||
1929 | { |
||
1930 | dol_syslog(get_class($this).'::setPaymentTerms('.$id.')'); |
||
1931 | if ($this->statut >= 0 || $this->element == 'societe') |
||
1932 | { |
||
1933 | // TODO uniformize field name |
||
1934 | $fieldname = 'fk_cond_reglement'; |
||
1935 | if ($this->element == 'societe') $fieldname = 'cond_reglement'; |
||
1936 | if (get_class($this) == 'Fournisseur') $fieldname = 'cond_reglement_supplier'; |
||
1937 | |||
1938 | $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; |
||
1939 | $sql .= ' SET '.$fieldname.' = '.$id; |
||
1940 | $sql .= ' WHERE rowid='.$this->id; |
||
1941 | |||
1942 | if ($this->db->query($sql)) |
||
1943 | { |
||
1944 | $this->cond_reglement_id = $id; |
||
1945 | // for supplier |
||
1946 | if (get_class($this) == 'Fournisseur') $this->cond_reglement_supplier_id = $id; |
||
1947 | $this->cond_reglement = $id; // for compatibility |
||
0 ignored issues
–
show
|
|||
1948 | return 1; |
||
1949 | } |
||
1950 | else |
||
1951 | { |
||
1952 | dol_syslog(get_class($this).'::setPaymentTerms Erreur '.$sql.' - '.$this->db->error()); |
||
1953 | $this->error=$this->db->error(); |
||
1954 | return -1; |
||
1955 | } |
||
1956 | } |
||
1957 | else |
||
1958 | { |
||
1959 | dol_syslog(get_class($this).'::setPaymentTerms, status of the object is incompatible'); |
||
1960 | $this->error='Status of the object is incompatible '.$this->statut; |
||
1961 | return -2; |
||
1962 | } |
||
1963 | } |
||
1964 | |||
1965 | /** |
||
1966 | * Define delivery address |
||
1967 | * @deprecated |
||
1968 | * |
||
1969 | * @param int $id Address id |
||
1970 | * @return int <0 si ko, >0 si ok |
||
1971 | */ |
||
1972 | function setDeliveryAddress($id) |
||
1973 | { |
||
1974 | $fieldname = 'fk_delivery_address'; |
||
1975 | if ($this->element == 'delivery' || $this->element == 'shipping') $fieldname = 'fk_address'; |
||
1976 | |||
1977 | $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element." SET ".$fieldname." = ".$id; |
||
1978 | $sql.= " WHERE rowid = ".$this->id." AND fk_statut = 0"; |
||
1979 | |||
1980 | if ($this->db->query($sql)) |
||
1981 | { |
||
1982 | $this->fk_delivery_address = $id; |
||
1983 | return 1; |
||
1984 | } |
||
1985 | else |
||
1986 | { |
||
1987 | $this->error=$this->db->error(); |
||
1988 | dol_syslog(get_class($this).'::setDeliveryAddress Erreur '.$sql.' - '.$this->error); |
||
1989 | return -1; |
||
1990 | } |
||
1991 | } |
||
1992 | |||
1993 | |||
1994 | /** |
||
1995 | * Change the shipping method |
||
1996 | * |
||
1997 | * @param int $shipping_method_id Id of shipping method |
||
1998 | * @param bool $notrigger false=launch triggers after, true=disable triggers |
||
1999 | * @param User $userused Object user |
||
2000 | * |
||
2001 | * @return int 1 if OK, 0 if KO |
||
2002 | */ |
||
2003 | function setShippingMethod($shipping_method_id, $notrigger=false, $userused=null) |
||
2004 | { |
||
2005 | global $user; |
||
2006 | |||
2007 | if (empty($userused)) $userused=$user; |
||
2008 | |||
2009 | $error = 0; |
||
2010 | |||
2011 | if (! $this->table_element) { |
||
2012 | dol_syslog(get_class($this)."::setShippingMethod was called on objet with property table_element not defined",LOG_ERR); |
||
2013 | return -1; |
||
2014 | } |
||
2015 | |||
2016 | $this->db->begin(); |
||
2017 | |||
2018 | if ($shipping_method_id<0) $shipping_method_id='NULL'; |
||
2019 | dol_syslog(get_class($this).'::setShippingMethod('.$shipping_method_id.')'); |
||
2020 | |||
2021 | $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element; |
||
2022 | $sql.= " SET fk_shipping_method = ".$shipping_method_id; |
||
2023 | $sql.= " WHERE rowid=".$this->id; |
||
2024 | $resql = $this->db->query($sql); |
||
2025 | if (! $resql) { |
||
2026 | dol_syslog(get_class($this).'::setShippingMethod Error ', LOG_DEBUG); |
||
2027 | $this->error = $this->db->lasterror(); |
||
2028 | $error++; |
||
2029 | } else { |
||
2030 | if (!$notrigger) |
||
2031 | { |
||
2032 | // Call trigger |
||
2033 | $this->context=array('shippingmethodupdate'=>1); |
||
2034 | $result = $this->call_trigger(strtoupper(get_class($this)) . '_MODIFY', $userused); |
||
2035 | if ($result < 0) $error++; |
||
2036 | // End call trigger |
||
2037 | } |
||
2038 | } |
||
2039 | if ($error) |
||
2040 | { |
||
2041 | $this->db->rollback(); |
||
2042 | return -1; |
||
2043 | } else { |
||
2044 | $this->shipping_method_id = ($shipping_method_id=='NULL')?null:$shipping_method_id; |
||
0 ignored issues
–
show
It seems like
$shipping_method_id == '...l : $shipping_method_id can also be of type string . However, the property $shipping_method_id is declared as type integer . Maybe add an additional type check?
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly. For example, imagine you have a variable Either this assignment is in error or a type check should be added for that assignment. class Id
{
public $id;
public function __construct($id)
{
$this->id = $id;
}
}
class Account
{
/** @var Id $id */
public $id;
}
$account_id = false;
if (starsAreRight()) {
$account_id = new Id(42);
}
$account = new Account();
if ($account instanceof Id)
{
$account->id = $account_id;
}
Loading history...
|
|||
2045 | $this->db->commit(); |
||
2046 | return 1; |
||
2047 | } |
||
2048 | } |
||
2049 | |||
2050 | |||
2051 | /** |
||
2052 | * Change the warehouse |
||
2053 | * |
||
2054 | * @param int $warehouse_id Id of warehouse |
||
2055 | * @return int 1 if OK, 0 if KO |
||
2056 | */ |
||
2057 | function setWarehouse($warehouse_id) |
||
2058 | { |
||
2059 | if (! $this->table_element) { |
||
2060 | dol_syslog(get_class($this)."::setWarehouse was called on objet with property table_element not defined",LOG_ERR); |
||
2061 | return -1; |
||
2062 | } |
||
2063 | if ($warehouse_id<0) $warehouse_id='NULL'; |
||
2064 | dol_syslog(get_class($this).'::setWarehouse('.$warehouse_id.')'); |
||
2065 | |||
2066 | $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element; |
||
2067 | $sql.= " SET fk_warehouse = ".$warehouse_id; |
||
2068 | $sql.= " WHERE rowid=".$this->id; |
||
2069 | |||
2070 | if ($this->db->query($sql)) { |
||
2071 | $this->warehouse_id = ($warehouse_id=='NULL')?null:$warehouse_id; |
||
2072 | return 1; |
||
2073 | } else { |
||
2074 | dol_syslog(get_class($this).'::setWarehouse Error ', LOG_DEBUG); |
||
2075 | $this->error=$this->db->error(); |
||
2076 | return 0; |
||
2077 | } |
||
2078 | } |
||
2079 | |||
2080 | |||
2081 | /** |
||
2082 | * Set last model used by doc generator |
||
2083 | * |
||
2084 | * @param User $user User object that make change |
||
2085 | * @param string $modelpdf Modele name |
||
2086 | * @return int <0 if KO, >0 if OK |
||
2087 | */ |
||
2088 | function setDocModel($user, $modelpdf) |
||
2089 | { |
||
2090 | if (! $this->table_element) |
||
2091 | { |
||
2092 | dol_syslog(get_class($this)."::setDocModel was called on objet with property table_element not defined",LOG_ERR); |
||
2093 | return -1; |
||
2094 | } |
||
2095 | |||
2096 | $newmodelpdf=dol_trunc($modelpdf,255); |
||
2097 | |||
2098 | $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element; |
||
2099 | $sql.= " SET model_pdf = '".$this->db->escape($newmodelpdf)."'"; |
||
2100 | $sql.= " WHERE rowid = ".$this->id; |
||
2101 | // if ($this->element == 'facture') $sql.= " AND fk_statut < 2"; |
||
2102 | // if ($this->element == 'propal') $sql.= " AND fk_statut = 0"; |
||
2103 | |||
2104 | dol_syslog(get_class($this)."::setDocModel", LOG_DEBUG); |
||
2105 | $resql=$this->db->query($sql); |
||
2106 | if ($resql) |
||
2107 | { |
||
2108 | $this->modelpdf=$modelpdf; |
||
2109 | return 1; |
||
2110 | } |
||
2111 | else |
||
2112 | { |
||
2113 | dol_print_error($this->db); |
||
2114 | return 0; |
||
2115 | } |
||
2116 | } |
||
2117 | |||
2118 | |||
2119 | /** |
||
2120 | * Change the bank account |
||
2121 | * |
||
2122 | * @param int $fk_account Id of bank account |
||
2123 | * @param bool $notrigger false=launch triggers after, true=disable triggers |
||
2124 | * @param User $userused Object user |
||
2125 | * @return int 1 if OK, 0 if KO |
||
2126 | */ |
||
2127 | function setBankAccount($fk_account, $notrigger=false, $userused=null) |
||
2128 | { |
||
2129 | global $user; |
||
2130 | |||
2131 | if (empty($userused)) $userused=$user; |
||
2132 | |||
2133 | $error = 0; |
||
2134 | |||
2135 | if (! $this->table_element) { |
||
2136 | dol_syslog(get_class($this)."::setBankAccount was called on objet with property table_element not defined",LOG_ERR); |
||
2137 | return -1; |
||
2138 | } |
||
2139 | $this->db->begin(); |
||
2140 | |||
2141 | if ($fk_account<0) $fk_account='NULL'; |
||
2142 | dol_syslog(get_class($this).'::setBankAccount('.$fk_account.')'); |
||
2143 | |||
2144 | $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element; |
||
2145 | $sql.= " SET fk_account = ".$fk_account; |
||
2146 | $sql.= " WHERE rowid=".$this->id; |
||
2147 | |||
2148 | $resql = $this->db->query($sql); |
||
2149 | if (! $resql) |
||
2150 | { |
||
2151 | dol_syslog(get_class($this).'::setBankAccount Error '.$sql.' - '.$this->db->error()); |
||
2152 | $this->error = $this->db->lasterror(); |
||
2153 | $error++; |
||
2154 | } |
||
2155 | else |
||
2156 | { |
||
2157 | if (!$notrigger) |
||
2158 | { |
||
2159 | // Call trigger |
||
2160 | $this->context=array('bankaccountupdate'=>1); |
||
2161 | $result = $this->call_trigger(strtoupper(get_class($this)) . '_MODIFY', $userused); |
||
2162 | if ($result < 0) $error++; |
||
2163 | // End call trigger |
||
2164 | } |
||
2165 | } |
||
2166 | if ($error) |
||
2167 | { |
||
2168 | $this->db->rollback(); |
||
2169 | return -1; |
||
2170 | } |
||
2171 | else |
||
2172 | { |
||
2173 | $this->fk_account = ($fk_account=='NULL')?null:$fk_account; |
||
0 ignored issues
–
show
It seems like
$fk_account == 'NULL' ? null : $fk_account can also be of type string . However, the property $fk_account is declared as type integer . Maybe add an additional type check?
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly. For example, imagine you have a variable Either this assignment is in error or a type check should be added for that assignment. class Id
{
public $id;
public function __construct($id)
{
$this->id = $id;
}
}
class Account
{
/** @var Id $id */
public $id;
}
$account_id = false;
if (starsAreRight()) {
$account_id = new Id(42);
}
$account = new Account();
if ($account instanceof Id)
{
$account->id = $account_id;
}
Loading history...
|
|||
2174 | $this->db->commit(); |
||
2175 | return 1; |
||
2176 | } |
||
2177 | } |
||
2178 | |||
2179 | |||
2180 | // TODO: Move line related operations to CommonObjectLine? |
||
2181 | |||
2182 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
2183 | /** |
||
2184 | * Save a new position (field rang) for details lines. |
||
2185 | * You can choose to set position for lines with already a position or lines without any position defined. |
||
2186 | * |
||
2187 | * @param boolean $renum True to renum all already ordered lines, false to renum only not already ordered lines. |
||
2188 | * @param string $rowidorder ASC or DESC |
||
2189 | * @param boolean $fk_parent_line Table with fk_parent_line field or not |
||
2190 | * @return int <0 if KO, >0 if OK |
||
2191 | */ |
||
2192 | function line_order($renum=false, $rowidorder='ASC', $fk_parent_line=true) |
||
2193 | { |
||
2194 | // phpcs:enable |
||
2195 | if (! $this->table_element_line) |
||
2196 | { |
||
2197 | dol_syslog(get_class($this)."::line_order was called on objet with property table_element_line not defined",LOG_ERR); |
||
2198 | return -1; |
||
2199 | } |
||
2200 | if (! $this->fk_element) |
||
2201 | { |
||
2202 | dol_syslog(get_class($this)."::line_order was called on objet with property fk_element not defined",LOG_ERR); |
||
2203 | return -1; |
||
2204 | } |
||
2205 | |||
2206 | // Count number of lines to reorder (according to choice $renum) |
||
2207 | $nl=0; |
||
2208 | $sql = 'SELECT count(rowid) FROM '.MAIN_DB_PREFIX.$this->table_element_line; |
||
2209 | $sql.= ' WHERE '.$this->fk_element.'='.$this->id; |
||
2210 | if (! $renum) $sql.= ' AND rang = 0'; |
||
2211 | if ($renum) $sql.= ' AND rang <> 0'; |
||
2212 | |||
2213 | dol_syslog(get_class($this)."::line_order", LOG_DEBUG); |
||
2214 | $resql = $this->db->query($sql); |
||
2215 | if ($resql) |
||
2216 | { |
||
2217 | $row = $this->db->fetch_row($resql); |
||
2218 | $nl = $row[0]; |
||
2219 | } |
||
2220 | else dol_print_error($this->db); |
||
2221 | if ($nl > 0) |
||
2222 | { |
||
2223 | // The goal of this part is to reorder all lines, with all children lines sharing the same |
||
2224 | // counter that parents. |
||
2225 | $rows=array(); |
||
2226 | |||
2227 | // We first search all lines that are parent lines (for multilevel details lines) |
||
2228 | $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.$this->table_element_line; |
||
2229 | $sql.= ' WHERE '.$this->fk_element.' = '.$this->id; |
||
2230 | if ($fk_parent_line) $sql.= ' AND fk_parent_line IS NULL'; |
||
2231 | $sql.= ' ORDER BY rang ASC, rowid '.$rowidorder; |
||
2232 | |||
2233 | dol_syslog(get_class($this)."::line_order search all parent lines", LOG_DEBUG); |
||
2234 | $resql = $this->db->query($sql); |
||
2235 | if ($resql) |
||
2236 | { |
||
2237 | $i=0; |
||
2238 | $num = $this->db->num_rows($resql); |
||
2239 | while ($i < $num) |
||
2240 | { |
||
2241 | $row = $this->db->fetch_row($resql); |
||
2242 | $rows[] = $row[0]; // Add parent line into array rows |
||
2243 | $childrens = $this->getChildrenOfLine($row[0]); |
||
2244 | if (! empty($childrens)) |
||
2245 | { |
||
2246 | foreach($childrens as $child) |
||
2247 | { |
||
2248 | array_push($rows, $child); |
||
2249 | } |
||
2250 | } |
||
2251 | $i++; |
||
2252 | } |
||
2253 | |||
2254 | // Now we set a new number for each lines (parent and children with children included into parent tree) |
||
2255 | if (! empty($rows)) |
||
2256 | { |
||
2257 | foreach($rows as $key => $row) |
||
2258 | { |
||
2259 | $this->updateRangOfLine($row, ($key+1)); |
||
2260 | } |
||
2261 | } |
||
2262 | } |
||
2263 | else |
||
2264 | { |
||
2265 | dol_print_error($this->db); |
||
2266 | } |
||
2267 | } |
||
2268 | return 1; |
||
2269 | } |
||
2270 | |||
2271 | /** |
||
2272 | * Get children of line |
||
2273 | * |
||
2274 | * @param int $id Id of parent line |
||
2275 | * @return array Array with list of children lines id |
||
2276 | */ |
||
2277 | function getChildrenOfLine($id) |
||
2278 | { |
||
2279 | $rows=array(); |
||
2280 | |||
2281 | $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.$this->table_element_line; |
||
2282 | $sql.= ' WHERE '.$this->fk_element.' = '.$this->id; |
||
2283 | $sql.= ' AND fk_parent_line = '.$id; |
||
2284 | $sql.= ' ORDER BY rang ASC'; |
||
2285 | |||
2286 | dol_syslog(get_class($this)."::getChildrenOfLine search children lines for line ".$id."", LOG_DEBUG); |
||
2287 | $resql = $this->db->query($sql); |
||
2288 | if ($resql) |
||
2289 | { |
||
2290 | $i=0; |
||
2291 | $num = $this->db->num_rows($resql); |
||
2292 | while ($i < $num) |
||
2293 | { |
||
2294 | $row = $this->db->fetch_row($resql); |
||
2295 | $rows[$i] = $row[0]; |
||
2296 | $i++; |
||
2297 | } |
||
2298 | } |
||
2299 | |||
2300 | return $rows; |
||
2301 | } |
||
2302 | |||
2303 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
2304 | /** |
||
2305 | * Update a line to have a lower rank |
||
2306 | * |
||
2307 | * @param int $rowid Id of line |
||
2308 | * @param boolean $fk_parent_line Table with fk_parent_line field or not |
||
2309 | * @return void |
||
2310 | */ |
||
2311 | function line_up($rowid, $fk_parent_line=true) |
||
2312 | { |
||
2313 | // phpcs:enable |
||
2314 | $this->line_order(false, 'ASC', $fk_parent_line); |
||
2315 | |||
2316 | // Get rang of line |
||
2317 | $rang = $this->getRangOfLine($rowid); |
||
2318 | |||
2319 | // Update position of line |
||
2320 | $this->updateLineUp($rowid, $rang); |
||
2321 | } |
||
2322 | |||
2323 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
2324 | /** |
||
2325 | * Update a line to have a higher rank |
||
2326 | * |
||
2327 | * @param int $rowid Id of line |
||
2328 | * @param boolean $fk_parent_line Table with fk_parent_line field or not |
||
2329 | * @return void |
||
2330 | */ |
||
2331 | function line_down($rowid, $fk_parent_line=true) |
||
2332 | { |
||
2333 | // phpcs:enable |
||
2334 | $this->line_order(false, 'ASC', $fk_parent_line); |
||
2335 | |||
2336 | // Get rang of line |
||
2337 | $rang = $this->getRangOfLine($rowid); |
||
2338 | |||
2339 | // Get max value for rang |
||
2340 | $max = $this->line_max(); |
||
2341 | |||
2342 | // Update position of line |
||
2343 | $this->updateLineDown($rowid, $rang, $max); |
||
2344 | } |
||
2345 | |||
2346 | /** |
||
2347 | * Update position of line (rang) |
||
2348 | * |
||
2349 | * @param int $rowid Id of line |
||
2350 | * @param int $rang Position |
||
2351 | * @return void |
||
2352 | */ |
||
2353 | function updateRangOfLine($rowid,$rang) |
||
2354 | { |
||
2355 | $fieldposition = 'rang'; |
||
2356 | if (in_array($this->table_element_line, array('ecm_files', 'emailcollector_emailcollectoraction'))) $fieldposition = 'position'; |
||
2357 | |||
2358 | $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element_line.' SET '.$fieldposition.' = '.$rang; |
||
2359 | $sql.= ' WHERE rowid = '.$rowid; |
||
2360 | |||
2361 | dol_syslog(get_class($this)."::updateRangOfLine", LOG_DEBUG); |
||
2362 | if (! $this->db->query($sql)) |
||
2363 | { |
||
2364 | dol_print_error($this->db); |
||
2365 | } |
||
2366 | } |
||
2367 | |||
2368 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
2369 | /** |
||
2370 | * Update position of line with ajax (rang) |
||
2371 | * |
||
2372 | * @param array $rows Array of rows |
||
2373 | * @return void |
||
2374 | */ |
||
2375 | function line_ajaxorder($rows) |
||
2376 | { |
||
2377 | // phpcs:enable |
||
2378 | $num = count($rows); |
||
2379 | for ($i = 0 ; $i < $num ; $i++) |
||
2380 | { |
||
2381 | $this->updateRangOfLine($rows[$i], ($i+1)); |
||
2382 | } |
||
2383 | } |
||
2384 | |||
2385 | /** |
||
2386 | * Update position of line up (rang) |
||
2387 | * |
||
2388 | * @param int $rowid Id of line |
||
2389 | * @param int $rang Position |
||
2390 | * @return void |
||
2391 | */ |
||
2392 | function updateLineUp($rowid,$rang) |
||
2393 | { |
||
2394 | if ($rang > 1) |
||
2395 | { |
||
2396 | $fieldposition = 'rang'; |
||
2397 | if (in_array($this->table_element_line, array('ecm_files', 'emailcollector_emailcollectoraction'))) $fieldposition = 'position'; |
||
2398 | |||
2399 | $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element_line.' SET '.$fieldposition.' = '.$rang ; |
||
2400 | $sql.= ' WHERE '.$this->fk_element.' = '.$this->id; |
||
2401 | $sql.= ' AND rang = '.($rang - 1); |
||
2402 | if ($this->db->query($sql) ) |
||
2403 | { |
||
2404 | $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element_line.' SET '.$fieldposition.' = '.($rang - 1); |
||
2405 | $sql.= ' WHERE rowid = '.$rowid; |
||
2406 | if (! $this->db->query($sql) ) |
||
2407 | { |
||
2408 | dol_print_error($this->db); |
||
2409 | } |
||
2410 | } |
||
2411 | else |
||
2412 | { |
||
2413 | dol_print_error($this->db); |
||
2414 | } |
||
2415 | } |
||
2416 | } |
||
2417 | |||
2418 | /** |
||
2419 | * Update position of line down (rang) |
||
2420 | * |
||
2421 | * @param int $rowid Id of line |
||
2422 | * @param int $rang Position |
||
2423 | * @param int $max Max |
||
2424 | * @return void |
||
2425 | */ |
||
2426 | function updateLineDown($rowid,$rang,$max) |
||
2427 | { |
||
2428 | if ($rang < $max) |
||
2429 | { |
||
2430 | $fieldposition = 'rang'; |
||
2431 | if (in_array($this->table_element_line, array('ecm_files', 'emailcollector_emailcollectoraction'))) $fieldposition = 'position'; |
||
2432 | |||
2433 | $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element_line.' SET '.$fieldposition.' = '.$rang; |
||
2434 | $sql.= ' WHERE '.$this->fk_element.' = '.$this->id; |
||
2435 | $sql.= ' AND rang = '.($rang+1); |
||
2436 | if ($this->db->query($sql) ) |
||
2437 | { |
||
2438 | $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element_line.' SET '.$fieldposition.' = '.($rang+1); |
||
2439 | $sql.= ' WHERE rowid = '.$rowid; |
||
2440 | if (! $this->db->query($sql) ) |
||
2441 | { |
||
2442 | dol_print_error($this->db); |
||
2443 | } |
||
2444 | } |
||
2445 | else |
||
2446 | { |
||
2447 | dol_print_error($this->db); |
||
2448 | } |
||
2449 | } |
||
2450 | } |
||
2451 | |||
2452 | /** |
||
2453 | * Get position of line (rang) |
||
2454 | * |
||
2455 | * @param int $rowid Id of line |
||
2456 | * @return int Value of rang in table of lines |
||
2457 | */ |
||
2458 | function getRangOfLine($rowid) |
||
2459 | { |
||
2460 | $sql = 'SELECT rang FROM '.MAIN_DB_PREFIX.$this->table_element_line; |
||
2461 | $sql.= ' WHERE rowid ='.$rowid; |
||
2462 | |||
2463 | dol_syslog(get_class($this)."::getRangOfLine", LOG_DEBUG); |
||
2464 | $resql = $this->db->query($sql); |
||
2465 | if ($resql) |
||
2466 | { |
||
2467 | $row = $this->db->fetch_row($resql); |
||
2468 | return $row[0]; |
||
2469 | } |
||
2470 | } |
||
2471 | |||
2472 | /** |
||
2473 | * Get rowid of the line relative to its position |
||
2474 | * |
||
2475 | * @param int $rang Rang value |
||
2476 | * @return int Rowid of the line |
||
2477 | */ |
||
2478 | function getIdOfLine($rang) |
||
2479 | { |
||
2480 | $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.$this->table_element_line; |
||
2481 | $sql.= ' WHERE '.$this->fk_element.' = '.$this->id; |
||
2482 | $sql.= ' AND rang = '.$rang; |
||
2483 | $resql = $this->db->query($sql); |
||
2484 | if ($resql) |
||
2485 | { |
||
2486 | $row = $this->db->fetch_row($resql); |
||
2487 | return $row[0]; |
||
2488 | } |
||
2489 | } |
||
2490 | |||
2491 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
2492 | /** |
||
2493 | * Get max value used for position of line (rang) |
||
2494 | * |
||
2495 | * @param int $fk_parent_line Parent line id |
||
2496 | * @return int Max value of rang in table of lines |
||
2497 | */ |
||
2498 | function line_max($fk_parent_line=0) |
||
2499 | { |
||
2500 | // phpcs:enable |
||
2501 | // Search the last rang with fk_parent_line |
||
2502 | if ($fk_parent_line) |
||
2503 | { |
||
2504 | $sql = 'SELECT max(rang) FROM '.MAIN_DB_PREFIX.$this->table_element_line; |
||
2505 | $sql.= ' WHERE '.$this->fk_element.' = '.$this->id; |
||
2506 | $sql.= ' AND fk_parent_line = '.$fk_parent_line; |
||
2507 | |||
2508 | dol_syslog(get_class($this)."::line_max", LOG_DEBUG); |
||
2509 | $resql = $this->db->query($sql); |
||
2510 | if ($resql) |
||
2511 | { |
||
2512 | $row = $this->db->fetch_row($resql); |
||
2513 | if (! empty($row[0])) |
||
2514 | { |
||
2515 | return $row[0]; |
||
2516 | } |
||
2517 | else |
||
2518 | { |
||
2519 | return $this->getRangOfLine($fk_parent_line); |
||
2520 | } |
||
2521 | } |
||
2522 | } |
||
2523 | // If not, search the last rang of element |
||
2524 | else |
||
2525 | { |
||
2526 | $sql = 'SELECT max(rang) FROM '.MAIN_DB_PREFIX.$this->table_element_line; |
||
2527 | $sql.= ' WHERE '.$this->fk_element.' = '.$this->id; |
||
2528 | |||
2529 | dol_syslog(get_class($this)."::line_max", LOG_DEBUG); |
||
2530 | $resql = $this->db->query($sql); |
||
2531 | if ($resql) |
||
2532 | { |
||
2533 | $row = $this->db->fetch_row($resql); |
||
2534 | return $row[0]; |
||
2535 | } |
||
2536 | } |
||
2537 | } |
||
2538 | |||
2539 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
2540 | /** |
||
2541 | * Update external ref of element |
||
2542 | * |
||
2543 | * @param string $ref_ext Update field ref_ext |
||
2544 | * @return int <0 if KO, >0 if OK |
||
2545 | */ |
||
2546 | function update_ref_ext($ref_ext) |
||
2547 | { |
||
2548 | // phpcs:enable |
||
2549 | if (! $this->table_element) |
||
2550 | { |
||
2551 | dol_syslog(get_class($this)."::update_ref_ext was called on objet with property table_element not defined", LOG_ERR); |
||
2552 | return -1; |
||
2553 | } |
||
2554 | |||
2555 | $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; |
||
2556 | $sql.= " SET ref_ext = '".$this->db->escape($ref_ext)."'"; |
||
2557 | $sql.= " WHERE ".(isset($this->table_rowid)?$this->table_rowid:'rowid')." = ". $this->id; |
||
2558 | |||
2559 | dol_syslog(get_class($this)."::update_ref_ext", LOG_DEBUG); |
||
2560 | if ($this->db->query($sql)) |
||
2561 | { |
||
2562 | $this->ref_ext = $ref_ext; |
||
2563 | return 1; |
||
2564 | } |
||
2565 | else |
||
2566 | { |
||
2567 | $this->error=$this->db->error(); |
||
2568 | return -1; |
||
2569 | } |
||
2570 | } |
||
2571 | |||
2572 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
2573 | /** |
||
2574 | * Update note of element |
||
2575 | * |
||
2576 | * @param string $note New value for note |
||
2577 | * @param string $suffix '', '_public' or '_private' |
||
2578 | * @return int <0 if KO, >0 if OK |
||
2579 | */ |
||
2580 | function update_note($note, $suffix='') |
||
2581 | { |
||
2582 | // phpcs:enable |
||
2583 | global $user; |
||
2584 | |||
2585 | if (! $this->table_element) |
||
2586 | { |
||
2587 | $this->error='update_note was called on objet with property table_element not defined'; |
||
2588 | dol_syslog(get_class($this)."::update_note was called on objet with property table_element not defined", LOG_ERR); |
||
2589 | return -1; |
||
2590 | } |
||
2591 | if (! in_array($suffix,array('','_public','_private'))) |
||
2592 | { |
||
2593 | $this->error='update_note Parameter suffix must be empty, \'_private\' or \'_public\''; |
||
2594 | dol_syslog(get_class($this)."::update_note Parameter suffix must be empty, '_private' or '_public'", LOG_ERR); |
||
2595 | return -2; |
||
2596 | } |
||
2597 | // Special cas |
||
2598 | //var_dump($this->table_element);exit; |
||
2599 | if ($this->table_element == 'product') $suffix=''; |
||
2600 | |||
2601 | $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element; |
||
2602 | $sql.= " SET note".$suffix." = ".(!empty($note)?("'".$this->db->escape($note)."'"):"NULL"); |
||
2603 | $sql.= " ,".(in_array($this->table_element, array('actioncomm', 'adherent', 'advtargetemailing', 'cronjob', 'establishment'))?"fk_user_mod":"fk_user_modif")." = ".$user->id; |
||
2604 | $sql.= " WHERE rowid =". $this->id; |
||
2605 | |||
2606 | dol_syslog(get_class($this)."::update_note", LOG_DEBUG); |
||
2607 | if ($this->db->query($sql)) |
||
2608 | { |
||
2609 | if ($suffix == '_public') $this->note_public = $note; |
||
2610 | else if ($suffix == '_private') $this->note_private = $note; |
||
2611 | else |
||
2612 | { |
||
2613 | $this->note = $note; // deprecated |
||
2614 | $this->note_private = $note; |
||
2615 | } |
||
2616 | return 1; |
||
2617 | } |
||
2618 | else |
||
2619 | { |
||
2620 | $this->error=$this->db->lasterror(); |
||
2621 | return -1; |
||
2622 | } |
||
2623 | } |
||
2624 | |||
2625 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
2626 | /** |
||
2627 | * Update public note (kept for backward compatibility) |
||
2628 | * |
||
2629 | * @param string $note New value for note |
||
2630 | * @return int <0 if KO, >0 if OK |
||
2631 | * @deprecated |
||
2632 | * @see update_note() |
||
2633 | */ |
||
2634 | function update_note_public($note) |
||
2635 | { |
||
2636 | // phpcs:enable |
||
2637 | return $this->update_note($note,'_public'); |
||
2638 | } |
||
2639 | |||
2640 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
2641 | /** |
||
2642 | * Update total_ht, total_ttc, total_vat, total_localtax1, total_localtax2 for an object (sum of lines). |
||
2643 | * Must be called at end of methods addline or updateline. |
||
2644 | * |
||
2645 | * @param int $exclspec >0 = Exclude special product (product_type=9) |
||
2646 | * @param string $roundingadjust 'none'=Do nothing, 'auto'=Use default method (MAIN_ROUNDOFTOTAL_NOT_TOTALOFROUND if defined, or '0'), '0'=Force mode total of rounding, '1'=Force mode rounding of total |
||
2647 | * @param int $nodatabaseupdate 1=Do not update database. Update only properties of object. |
||
2648 | * @param Societe $seller If roundingadjust is '0' or '1' or maybe 'auto', it means we recalculate total for lines before calculating total for object and for this, we need seller object. |
||
2649 | * @return int <0 if KO, >0 if OK |
||
2650 | */ |
||
2651 | function update_price($exclspec=0,$roundingadjust='none',$nodatabaseupdate=0,$seller=null) |
||
2652 | { |
||
2653 | // phpcs:enable |
||
2654 | global $conf, $hookmanager, $action; |
||
2655 | |||
2656 | // Some external module want no update price after a trigger because they have another method to calculate the total (ex: with an extrafield) |
||
2657 | $MODULE = ""; |
||
2658 | if ($this->element == 'propal') |
||
2659 | $MODULE = "MODULE_DISALLOW_UPDATE_PRICE_PROPOSAL"; |
||
2660 | elseif ($this->element == 'order') |
||
2661 | $MODULE = "MODULE_DISALLOW_UPDATE_PRICE_ORDER"; |
||
2662 | elseif ($this->element == 'facture') |
||
2663 | $MODULE = "MODULE_DISALLOW_UPDATE_PRICE_INVOICE"; |
||
2664 | elseif ($this->element == 'facture_fourn') |
||
2665 | $MODULE = "MODULE_DISALLOW_UPDATE_PRICE_SUPPLIER_INVOICE"; |
||
2666 | elseif ($this->element == 'order_supplier') |
||
2667 | $MODULE = "MODULE_DISALLOW_UPDATE_PRICE_SUPPLIER_ORDER"; |
||
2668 | elseif ($this->element == 'supplier_proposal') |
||
2669 | $MODULE = "MODULE_DISALLOW_UPDATE_PRICE_SUPPLIER_PROPOSAL"; |
||
2670 | |||
2671 | if (! empty($MODULE)) { |
||
2672 | if (! empty($conf->global->$MODULE)) { |
||
2673 | $modsactivated = explode(',', $conf->global->$MODULE); |
||
2674 | foreach ($modsactivated as $mod) { |
||
2675 | if ($conf->$mod->enabled) |
||
2676 | return 1; // update was disabled by specific setup |
||
2677 | } |
||
2678 | } |
||
2679 | } |
||
2680 | |||
2681 | include_once DOL_DOCUMENT_ROOT.'/core/lib/price.lib.php'; |
||
2682 | |||
2683 | if ($roundingadjust == '-1') $roundingadjust='auto'; // For backward compatibility |
||
2684 | |||
2685 | $forcedroundingmode=$roundingadjust; |
||
2686 | if ($forcedroundingmode == 'auto' && isset($conf->global->MAIN_ROUNDOFTOTAL_NOT_TOTALOFROUND)) $forcedroundingmode=$conf->global->MAIN_ROUNDOFTOTAL_NOT_TOTALOFROUND; |
||
2687 | elseif ($forcedroundingmode == 'auto') $forcedroundingmode='0'; |
||
2688 | |||
2689 | $error=0; |
||
2690 | |||
2691 | $multicurrency_tx = !empty($this->multicurrency_tx) ? $this->multicurrency_tx : 1; |
||
2692 | |||
2693 | // Define constants to find lines to sum |
||
2694 | $fieldtva='total_tva'; |
||
2695 | $fieldlocaltax1='total_localtax1'; |
||
2696 | $fieldlocaltax2='total_localtax2'; |
||
2697 | $fieldup='subprice'; |
||
2698 | if ($this->element == 'facture_fourn' || $this->element == 'invoice_supplier') |
||
2699 | { |
||
2700 | $fieldtva='tva'; |
||
2701 | $fieldup='pu_ht'; |
||
2702 | } |
||
2703 | if ($this->element == 'expensereport') |
||
2704 | { |
||
2705 | $fieldup='value_unit'; |
||
2706 | } |
||
2707 | |||
2708 | $sql = 'SELECT rowid, qty, '.$fieldup.' as up, remise_percent, total_ht, '.$fieldtva.' as total_tva, total_ttc, '.$fieldlocaltax1.' as total_localtax1, '.$fieldlocaltax2.' as total_localtax2,'; |
||
2709 | $sql.= ' tva_tx as vatrate, localtax1_tx, localtax2_tx, localtax1_type, localtax2_type, info_bits, product_type'; |
||
2710 | if ($this->table_element_line == 'facturedet') $sql.= ', situation_percent'; |
||
2711 | $sql.= ', multicurrency_total_ht, multicurrency_total_tva, multicurrency_total_ttc'; |
||
2712 | $sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element_line; |
||
2713 | $sql.= ' WHERE '.$this->fk_element.' = '.$this->id; |
||
2714 | if ($exclspec) |
||
2715 | { |
||
2716 | $product_field='product_type'; |
||
2717 | if ($this->table_element_line == 'contratdet') $product_field=''; // contratdet table has no product_type field |
||
2718 | if ($product_field) $sql.= ' AND '.$product_field.' <> 9'; |
||
2719 | } |
||
2720 | $sql.= ' ORDER by rowid'; // We want to be sure to always use same order of line to not change lines differently when option MAIN_ROUNDOFTOTAL_NOT_TOTALOFROUND is used |
||
2721 | |||
2722 | dol_syslog(get_class($this)."::update_price", LOG_DEBUG); |
||
2723 | $resql = $this->db->query($sql); |
||
2724 | if ($resql) |
||
2725 | { |
||
2726 | $this->total_ht = 0; |
||
2727 | $this->total_tva = 0; |
||
2728 | $this->total_localtax1 = 0; |
||
2729 | $this->total_localtax2 = 0; |
||
2730 | $this->total_ttc = 0; |
||
2731 | $total_ht_by_vats = array(); |
||
2732 | $total_tva_by_vats = array(); |
||
2733 | $total_ttc_by_vats = array(); |
||
2734 | $this->multicurrency_total_ht = 0; |
||
2735 | $this->multicurrency_total_tva = 0; |
||
2736 | $this->multicurrency_total_ttc = 0; |
||
2737 | |||
2738 | $num = $this->db->num_rows($resql); |
||
2739 | $i = 0; |
||
2740 | while ($i < $num) |
||
2741 | { |
||
2742 | $obj = $this->db->fetch_object($resql); |
||
2743 | |||
2744 | // Note: There is no check on detail line and no check on total, if $forcedroundingmode = 'none' |
||
2745 | $parameters=array('fk_element' => $obj->rowid); |
||
2746 | $reshook = $hookmanager->executeHooks('changeRoundingMode', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks |
||
2747 | |||
2748 | if (empty($reshook) && $forcedroundingmode == '0') // Check if data on line are consistent. This may solve lines that were not consistent because set with $forcedroundingmode='auto' |
||
2749 | { |
||
2750 | $localtax_array=array($obj->localtax1_type,$obj->localtax1_tx,$obj->localtax2_type,$obj->localtax2_tx); |
||
2751 | $tmpcal=calcul_price_total($obj->qty, $obj->up, $obj->remise_percent, $obj->vatrate, $obj->localtax1_tx, $obj->localtax2_tx, 0, 'HT', $obj->info_bits, $obj->product_type, $seller, $localtax_array, (isset($obj->situation_percent) ? $obj->situation_percent : 100), $multicurrency_tx); |
||
2752 | $diff=price2num($tmpcal[1] - $obj->total_tva, 'MT', 1); |
||
2753 | if ($diff) |
||
2754 | { |
||
2755 | $sqlfix="UPDATE ".MAIN_DB_PREFIX.$this->table_element_line." SET ".$fieldtva." = ".$tmpcal[1].", total_ttc = ".$tmpcal[2]." WHERE rowid = ".$obj->rowid; |
||
2756 | dol_syslog('We found unconsistent data into detailed line (difference of '.$diff.') for line rowid = '.$obj->rowid." (total vat of line calculated=".$tmpcal[1].", database=".$obj->total_tva."). We fix the total_vat and total_ttc of line by running sqlfix = ".$sqlfix); |
||
2757 | $resqlfix=$this->db->query($sqlfix); |
||
2758 | if (! $resqlfix) dol_print_error($this->db,'Failed to update line'); |
||
2759 | $obj->total_tva = $tmpcal[1]; |
||
2760 | $obj->total_ttc = $tmpcal[2]; |
||
2761 | // |
||
2762 | } |
||
2763 | } |
||
2764 | |||
2765 | $this->total_ht += $obj->total_ht; // The field visible at end of line detail |
||
2766 | $this->total_tva += $obj->total_tva; |
||
2767 | $this->total_localtax1 += $obj->total_localtax1; |
||
2768 | $this->total_localtax2 += $obj->total_localtax2; |
||
2769 | $this->total_ttc += $obj->total_ttc; |
||
2770 | $this->multicurrency_total_ht += $obj->multicurrency_total_ht; // The field visible at end of line detail |
||
2771 | $this->multicurrency_total_tva += $obj->multicurrency_total_tva; |
||
2772 | $this->multicurrency_total_ttc += $obj->multicurrency_total_ttc; |
||
2773 | |||
2774 | if (! isset($total_ht_by_vats[$obj->vatrate])) $total_ht_by_vats[$obj->vatrate]=0; |
||
2775 | if (! isset($total_tva_by_vats[$obj->vatrate])) $total_tva_by_vats[$obj->vatrate]=0; |
||
2776 | if (! isset($total_ttc_by_vats[$obj->vatrate])) $total_ttc_by_vats[$obj->vatrate]=0; |
||
2777 | $total_ht_by_vats[$obj->vatrate] += $obj->total_ht; |
||
2778 | $total_tva_by_vats[$obj->vatrate] += $obj->total_tva; |
||
2779 | $total_ttc_by_vats[$obj->vatrate] += $obj->total_ttc; |
||
2780 | |||
2781 | if ($forcedroundingmode == '1') // Check if we need adjustement onto line for vat. TODO This works on the company currency but not on multicurrency |
||
2782 | { |
||
2783 | $tmpvat=price2num($total_ht_by_vats[$obj->vatrate] * $obj->vatrate / 100, 'MT', 1); |
||
2784 | $diff=price2num($total_tva_by_vats[$obj->vatrate]-$tmpvat, 'MT', 1); |
||
2785 | //print 'Line '.$i.' rowid='.$obj->rowid.' vat_rate='.$obj->vatrate.' total_ht='.$obj->total_ht.' total_tva='.$obj->total_tva.' total_ttc='.$obj->total_ttc.' total_ht_by_vats='.$total_ht_by_vats[$obj->vatrate].' total_tva_by_vats='.$total_tva_by_vats[$obj->vatrate].' (new calculation = '.$tmpvat.') total_ttc_by_vats='.$total_ttc_by_vats[$obj->vatrate].($diff?" => DIFF":"")."<br>\n"; |
||
2786 | if ($diff) |
||
2787 | { |
||
2788 | if (abs($diff) > 0.1) { dol_syslog('A rounding difference was detected into TOTAL but is too high to be corrected', LOG_WARNING); exit; } |
||
2789 | $sqlfix="UPDATE ".MAIN_DB_PREFIX.$this->table_element_line." SET ".$fieldtva." = ".($obj->total_tva - $diff).", total_ttc = ".($obj->total_ttc - $diff)." WHERE rowid = ".$obj->rowid; |
||
2790 | dol_syslog('We found a difference of '.$diff.' for line rowid = '.$obj->rowid.". We fix the total_vat and total_ttc of line by running sqlfix = ".$sqlfix); |
||
2791 | $resqlfix=$this->db->query($sqlfix); |
||
2792 | if (! $resqlfix) dol_print_error($this->db,'Failed to update line'); |
||
2793 | $this->total_tva -= $diff; |
||
2794 | $this->total_ttc -= $diff; |
||
2795 | $total_tva_by_vats[$obj->vatrate] -= $diff; |
||
2796 | $total_ttc_by_vats[$obj->vatrate] -= $diff; |
||
2797 | } |
||
2798 | } |
||
2799 | |||
2800 | $i++; |
||
2801 | } |
||
2802 | |||
2803 | // Add revenue stamp to total |
||
2804 | $this->total_ttc += isset($this->revenuestamp)?$this->revenuestamp:0; |
||
2805 | $this->multicurrency_total_ttc += isset($this->revenuestamp)?($this->revenuestamp * $multicurrency_tx):0; |
||
2806 | |||
2807 | // Situations totals |
||
2808 | if ($this->situation_cycle_ref && $this->situation_counter > 1 && method_exists($this, 'get_prev_sits') && $this->type != $this::TYPE_CREDIT_NOTE ) |
||
2809 | { |
||
2810 | $prev_sits = $this->get_prev_sits(); |
||
2811 | |||
2812 | foreach ($prev_sits as $sit) { // $sit is an object Facture loaded with a fetch. |
||
2813 | $this->total_ht -= $sit->total_ht; |
||
2814 | $this->total_tva -= $sit->total_tva; |
||
2815 | $this->total_localtax1 -= $sit->total_localtax1; |
||
2816 | $this->total_localtax2 -= $sit->total_localtax2; |
||
2817 | $this->total_ttc -= $sit->total_ttc; |
||
2818 | $this->multicurrency_total_ht -= $sit->multicurrency_total_ht; |
||
2819 | $this->multicurrency_total_tva -= $sit->multicurrency_total_tva; |
||
2820 | $this->multicurrency_total_ttc -= $sit->multicurrency_total_ttc; |
||
2821 | } |
||
2822 | } |
||
2823 | |||
2824 | $this->db->free($resql); |
||
2825 | |||
2826 | // Now update global field total_ht, total_ttc and tva |
||
2827 | $fieldht='total_ht'; |
||
2828 | $fieldtva='tva'; |
||
2829 | $fieldlocaltax1='localtax1'; |
||
2830 | $fieldlocaltax2='localtax2'; |
||
2831 | $fieldttc='total_ttc'; |
||
2832 | // Specific code for backward compatibility with old field names |
||
2833 | if ($this->element == 'facture' || $this->element == 'facturerec') $fieldht='total'; |
||
2834 | if ($this->element == 'facture_fourn' || $this->element == 'invoice_supplier') $fieldtva='total_tva'; |
||
2835 | if ($this->element == 'propal') $fieldttc='total'; |
||
2836 | if ($this->element == 'expensereport') $fieldtva='total_tva'; |
||
2837 | if ($this->element == 'supplier_proposal') $fieldttc='total'; |
||
2838 | |||
2839 | if (empty($nodatabaseupdate)) |
||
2840 | { |
||
2841 | $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element.' SET'; |
||
2842 | $sql .= " ".$fieldht."='".price2num($this->total_ht)."',"; |
||
2843 | $sql .= " ".$fieldtva."='".price2num($this->total_tva)."',"; |
||
2844 | $sql .= " ".$fieldlocaltax1."='".price2num($this->total_localtax1)."',"; |
||
2845 | $sql .= " ".$fieldlocaltax2."='".price2num($this->total_localtax2)."',"; |
||
2846 | $sql .= " ".$fieldttc."='".price2num($this->total_ttc)."'"; |
||
2847 | $sql .= ", multicurrency_total_ht='".price2num($this->multicurrency_total_ht, 'MT', 1)."'"; |
||
2848 | $sql .= ", multicurrency_total_tva='".price2num($this->multicurrency_total_tva, 'MT', 1)."'"; |
||
2849 | $sql .= ", multicurrency_total_ttc='".price2num($this->multicurrency_total_ttc, 'MT', 1)."'"; |
||
2850 | $sql .= ' WHERE rowid = '.$this->id; |
||
2851 | |||
2852 | |||
2853 | dol_syslog(get_class($this)."::update_price", LOG_DEBUG); |
||
2854 | $resql=$this->db->query($sql); |
||
2855 | if (! $resql) |
||
2856 | { |
||
2857 | $error++; |
||
2858 | $this->error=$this->db->lasterror(); |
||
2859 | $this->errors[]=$this->db->lasterror(); |
||
2860 | } |
||
2861 | } |
||
2862 | |||
2863 | if (! $error) |
||
2864 | { |
||
2865 | return 1; |
||
2866 | } |
||
2867 | else |
||
2868 | { |
||
2869 | return -1; |
||
2870 | } |
||
2871 | } |
||
2872 | else |
||
2873 | { |
||
2874 | dol_print_error($this->db,'Bad request in update_price'); |
||
2875 | return -1; |
||
2876 | } |
||
2877 | } |
||
2878 | |||
2879 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
2880 | /** |
||
2881 | * Add objects linked in llx_element_element. |
||
2882 | * |
||
2883 | * @param string $origin Linked element type |
||
2884 | * @param int $origin_id Linked element id |
||
2885 | * @return int <=0 if KO, >0 if OK |
||
2886 | * @see fetchObjectLinked, updateObjectLinked, deleteObjectLinked |
||
2887 | */ |
||
2888 | function add_object_linked($origin=null, $origin_id=null) |
||
2889 | { |
||
2890 | // phpcs:enable |
||
2891 | $origin = (! empty($origin) ? $origin : $this->origin); |
||
2892 | $origin_id = (! empty($origin_id) ? $origin_id : $this->origin_id); |
||
2893 | |||
2894 | // Special case |
||
2895 | if ($origin == 'order') $origin='commande'; |
||
2896 | if ($origin == 'invoice') $origin='facture'; |
||
2897 | if ($origin == 'invoice_template') $origin='facturerec'; |
||
2898 | if ($origin == 'supplierorder') $origin='order_supplier'; |
||
2899 | $this->db->begin(); |
||
2900 | |||
2901 | $sql = "INSERT INTO ".MAIN_DB_PREFIX."element_element ("; |
||
2902 | $sql.= "fk_source"; |
||
2903 | $sql.= ", sourcetype"; |
||
2904 | $sql.= ", fk_target"; |
||
2905 | $sql.= ", targettype"; |
||
2906 | $sql.= ") VALUES ("; |
||
2907 | $sql.= $origin_id; |
||
2908 | $sql.= ", '".$this->db->escape($origin)."'"; |
||
2909 | $sql.= ", ".$this->id; |
||
2910 | $sql.= ", '".$this->db->escape($this->element)."'"; |
||
2911 | $sql.= ")"; |
||
2912 | |||
2913 | dol_syslog(get_class($this)."::add_object_linked", LOG_DEBUG); |
||
2914 | if ($this->db->query($sql)) |
||
2915 | { |
||
2916 | $this->db->commit(); |
||
2917 | return 1; |
||
2918 | } |
||
2919 | else |
||
2920 | { |
||
2921 | $this->error=$this->db->lasterror(); |
||
2922 | $this->db->rollback(); |
||
2923 | return 0; |
||
2924 | } |
||
2925 | } |
||
2926 | |||
2927 | /** |
||
2928 | * Fetch array of objects linked to current object (object of enabled modules only). Links are loaded into |
||
2929 | * this->linkedObjectsIds array and |
||
2930 | * this->linkedObjects array if $loadalsoobjects = 1 |
||
2931 | * Possible usage for parameters: |
||
2932 | * - all parameters empty -> we look all link to current object (current object can be source or target) |
||
2933 | * - source id+type -> will get target list linked to source |
||
2934 | * - target id+type -> will get source list linked to target |
||
2935 | * - source id+type + target type -> will get target list of the type |
||
2936 | * - target id+type + target source -> will get source list of the type |
||
2937 | * |
||
2938 | * @param int $sourceid Object source id (if not defined, id of object) |
||
2939 | * @param string $sourcetype Object source type (if not defined, element name of object) |
||
2940 | * @param int $targetid Object target id (if not defined, id of object) |
||
2941 | * @param string $targettype Object target type (if not defined, elemennt name of object) |
||
2942 | * @param string $clause 'OR' or 'AND' clause used when both source id and target id are provided |
||
2943 | * @param int $alsosametype 0=Return only links to object that differs from source type. 1=Include also link to objects of same type. |
||
2944 | * @param string $orderby SQL 'ORDER BY' clause |
||
2945 | * @param int $loadalsoobjects Load also array this->linkedObjects (Use 0 to increase performances) |
||
2946 | * @return int <0 if KO, >0 if OK |
||
2947 | * @see add_object_linked, updateObjectLinked, deleteObjectLinked |
||
2948 | */ |
||
2949 | function fetchObjectLinked($sourceid=null,$sourcetype='',$targetid=null,$targettype='',$clause='OR',$alsosametype=1,$orderby='sourcetype',$loadalsoobjects=1) |
||
2950 | { |
||
2951 | global $conf; |
||
2952 | |||
2953 | $this->linkedObjectsIds=array(); |
||
2954 | $this->linkedObjects=array(); |
||
2955 | |||
2956 | $justsource=false; |
||
2957 | $justtarget=false; |
||
2958 | $withtargettype=false; |
||
2959 | $withsourcetype=false; |
||
2960 | |||
2961 | if (! empty($sourceid) && ! empty($sourcetype) && empty($targetid)) |
||
2962 | { |
||
2963 | $justsource=true; // the source (id and type) is a search criteria |
||
2964 | if (! empty($targettype)) $withtargettype=true; |
||
2965 | } |
||
2966 | if (! empty($targetid) && ! empty($targettype) && empty($sourceid)) |
||
2967 | { |
||
2968 | $justtarget=true; // the target (id and type) is a search criteria |
||
2969 | if (! empty($sourcetype)) $withsourcetype=true; |
||
2970 | } |
||
2971 | |||
2972 | $sourceid = (! empty($sourceid) ? $sourceid : $this->id); |
||
2973 | $targetid = (! empty($targetid) ? $targetid : $this->id); |
||
2974 | $sourcetype = (! empty($sourcetype) ? $sourcetype : $this->element); |
||
2975 | $targettype = (! empty($targettype) ? $targettype : $this->element); |
||
2976 | |||
2977 | /*if (empty($sourceid) && empty($targetid)) |
||
2978 | { |
||
2979 | dol_syslog('Bad usage of function. No source nor target id defined (nor as parameter nor as object id)', LOG_ERR); |
||
2980 | return -1; |
||
2981 | }*/ |
||
2982 | |||
2983 | // Links between objects are stored in table element_element |
||
2984 | $sql = 'SELECT rowid, fk_source, sourcetype, fk_target, targettype'; |
||
2985 | $sql.= ' FROM '.MAIN_DB_PREFIX.'element_element'; |
||
2986 | $sql.= " WHERE "; |
||
2987 | if ($justsource || $justtarget) |
||
2988 | { |
||
2989 | if ($justsource) |
||
2990 | { |
||
2991 | $sql.= "fk_source = ".$sourceid." AND sourcetype = '".$sourcetype."'"; |
||
2992 | if ($withtargettype) $sql.= " AND targettype = '".$targettype."'"; |
||
2993 | } |
||
2994 | else if ($justtarget) |
||
2995 | { |
||
2996 | $sql.= "fk_target = ".$targetid." AND targettype = '".$targettype."'"; |
||
2997 | if ($withsourcetype) $sql.= " AND sourcetype = '".$sourcetype."'"; |
||
2998 | } |
||
2999 | } |
||
3000 | else |
||
3001 | { |
||
3002 | $sql.= "(fk_source = ".$sourceid." AND sourcetype = '".$sourcetype."')"; |
||
3003 | $sql.= " ".$clause." (fk_target = ".$targetid." AND targettype = '".$targettype."')"; |
||
3004 | } |
||
3005 | $sql .= ' ORDER BY '.$orderby; |
||
3006 | |||
3007 | dol_syslog(get_class($this)."::fetchObjectLink", LOG_DEBUG); |
||
3008 | $resql = $this->db->query($sql); |
||
3009 | if ($resql) |
||
3010 | { |
||
3011 | $num = $this->db->num_rows($resql); |
||
3012 | $i = 0; |
||
3013 | while ($i < $num) |
||
3014 | { |
||
3015 | $obj = $this->db->fetch_object($resql); |
||
3016 | if ($justsource || $justtarget) |
||
3017 | { |
||
3018 | if ($justsource) |
||
3019 | { |
||
3020 | $this->linkedObjectsIds[$obj->targettype][$obj->rowid]=$obj->fk_target; |
||
3021 | } |
||
3022 | else if ($justtarget) |
||
3023 | { |
||
3024 | $this->linkedObjectsIds[$obj->sourcetype][$obj->rowid]=$obj->fk_source; |
||
3025 | } |
||
3026 | } |
||
3027 | else |
||
3028 | { |
||
3029 | if ($obj->fk_source == $sourceid && $obj->sourcetype == $sourcetype) |
||
3030 | { |
||
3031 | $this->linkedObjectsIds[$obj->targettype][$obj->rowid]=$obj->fk_target; |
||
3032 | } |
||
3033 | if ($obj->fk_target == $targetid && $obj->targettype == $targettype) |
||
3034 | { |
||
3035 | $this->linkedObjectsIds[$obj->sourcetype][$obj->rowid]=$obj->fk_source; |
||
3036 | } |
||
3037 | } |
||
3038 | $i++; |
||
3039 | } |
||
3040 | |||
3041 | if (! empty($this->linkedObjectsIds)) |
||
3042 | { |
||
3043 | $tmparray = $this->linkedObjectsIds; |
||
3044 | foreach($tmparray as $objecttype => $objectids) // $objecttype is a module name ('facture', 'mymodule', ...) or a module name with a suffix ('project_task', 'mymodule_myobj', ...) |
||
3045 | { |
||
3046 | // Parse element/subelement (ex: project_task, cabinetmed_consultation, ...) |
||
3047 | $module = $element = $subelement = $objecttype; |
||
3048 | if ($objecttype != 'supplier_proposal' && $objecttype != 'order_supplier' && $objecttype != 'invoice_supplier' |
||
3049 | && preg_match('/^([^_]+)_([^_]+)/i',$objecttype,$regs)) |
||
3050 | { |
||
3051 | $module = $element = $regs[1]; |
||
3052 | $subelement = $regs[2]; |
||
3053 | } |
||
3054 | |||
3055 | $classpath = $element.'/class'; |
||
3056 | // To work with non standard classpath or module name |
||
3057 | if ($objecttype == 'facture') { |
||
3058 | $classpath = 'compta/facture/class'; |
||
3059 | } |
||
3060 | else if ($objecttype == 'facturerec') { |
||
3061 | $classpath = 'compta/facture/class'; $module = 'facture'; |
||
3062 | } |
||
3063 | else if ($objecttype == 'propal') { |
||
3064 | $classpath = 'comm/propal/class'; |
||
3065 | } |
||
3066 | else if ($objecttype == 'supplier_proposal') { |
||
3067 | $classpath = 'supplier_proposal/class'; |
||
3068 | } |
||
3069 | else if ($objecttype == 'shipping') { |
||
3070 | $classpath = 'expedition/class'; $subelement = 'expedition'; $module = 'expedition_bon'; |
||
3071 | } |
||
3072 | else if ($objecttype == 'delivery') { |
||
3073 | $classpath = 'livraison/class'; $subelement = 'livraison'; $module = 'livraison_bon'; |
||
3074 | } |
||
3075 | else if ($objecttype == 'invoice_supplier' || $objecttype == 'order_supplier') { |
||
3076 | $classpath = 'fourn/class'; $module = 'fournisseur'; |
||
3077 | } |
||
3078 | else if ($objecttype == 'fichinter') { |
||
3079 | $classpath = 'fichinter/class'; $subelement = 'fichinter'; $module = 'ficheinter'; |
||
3080 | } |
||
3081 | else if ($objecttype == 'subscription') { |
||
3082 | $classpath = 'adherents/class'; $module = 'adherent'; |
||
3083 | } |
||
3084 | |||
3085 | // Set classfile |
||
3086 | $classfile = strtolower($subelement); $classname = ucfirst($subelement); |
||
3087 | |||
3088 | if ($objecttype == 'order') { |
||
3089 | $classfile = 'commande'; $classname = 'Commande'; |
||
3090 | } |
||
3091 | else if ($objecttype == 'invoice_supplier') { |
||
3092 | $classfile = 'fournisseur.facture'; $classname = 'FactureFournisseur'; |
||
3093 | } |
||
3094 | else if ($objecttype == 'order_supplier') { |
||
3095 | $classfile = 'fournisseur.commande'; $classname = 'CommandeFournisseur'; |
||
3096 | } |
||
3097 | else if ($objecttype == 'supplier_proposal') { |
||
3098 | $classfile = 'supplier_proposal'; $classname = 'SupplierProposal'; |
||
3099 | } |
||
3100 | else if ($objecttype == 'facturerec') { |
||
3101 | $classfile = 'facture-rec'; $classname = 'FactureRec'; |
||
3102 | } |
||
3103 | else if ($objecttype == 'subscription') { |
||
3104 | $classfile = 'subscription'; $classname = 'Subscription'; |
||
3105 | } |
||
3106 | |||
3107 | // Here $module, $classfile and $classname are set |
||
3108 | if ($conf->$module->enabled && (($element != $this->element) || $alsosametype)) |
||
3109 | { |
||
3110 | if ($loadalsoobjects) |
||
3111 | { |
||
3112 | dol_include_once('/'.$classpath.'/'.$classfile.'.class.php'); |
||
3113 | //print '/'.$classpath.'/'.$classfile.'.class.php '.class_exists($classname); |
||
3114 | if (class_exists($classname)) |
||
3115 | { |
||
3116 | foreach($objectids as $i => $objectid) // $i is rowid into llx_element_element |
||
3117 | { |
||
3118 | $object = new $classname($this->db); |
||
3119 | $ret = $object->fetch($objectid); |
||
3120 | if ($ret >= 0) |
||
3121 | { |
||
3122 | $this->linkedObjects[$objecttype][$i] = $object; |
||
3123 | } |
||
3124 | } |
||
3125 | } |
||
3126 | } |
||
3127 | } |
||
3128 | else |
||
3129 | { |
||
3130 | unset($this->linkedObjectsIds[$objecttype]); |
||
3131 | } |
||
3132 | } |
||
3133 | } |
||
3134 | return 1; |
||
3135 | } |
||
3136 | else |
||
3137 | { |
||
3138 | dol_print_error($this->db); |
||
3139 | return -1; |
||
3140 | } |
||
3141 | } |
||
3142 | |||
3143 | /** |
||
3144 | * Update object linked of a current object |
||
3145 | * |
||
3146 | * @param int $sourceid Object source id |
||
3147 | * @param string $sourcetype Object source type |
||
3148 | * @param int $targetid Object target id |
||
3149 | * @param string $targettype Object target type |
||
3150 | * @return int >0 if OK, <0 if KO |
||
3151 | * @see add_object_linked, fetObjectLinked, deleteObjectLinked |
||
3152 | */ |
||
3153 | function updateObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='') |
||
3154 | { |
||
3155 | $updatesource=false; |
||
3156 | $updatetarget=false; |
||
3157 | |||
3158 | if (! empty($sourceid) && ! empty($sourcetype) && empty($targetid) && empty($targettype)) $updatesource=true; |
||
3159 | else if (empty($sourceid) && empty($sourcetype) && ! empty($targetid) && ! empty($targettype)) $updatetarget=true; |
||
3160 | |||
3161 | $sql = "UPDATE ".MAIN_DB_PREFIX."element_element SET "; |
||
3162 | if ($updatesource) |
||
3163 | { |
||
3164 | $sql.= "fk_source = ".$sourceid; |
||
3165 | $sql.= ", sourcetype = '".$this->db->escape($sourcetype)."'"; |
||
3166 | $sql.= " WHERE fk_target = ".$this->id; |
||
3167 | $sql.= " AND targettype = '".$this->db->escape($this->element)."'"; |
||
3168 | } |
||
3169 | else if ($updatetarget) |
||
3170 | { |
||
3171 | $sql.= "fk_target = ".$targetid; |
||
3172 | $sql.= ", targettype = '".$this->db->escape($targettype)."'"; |
||
3173 | $sql.= " WHERE fk_source = ".$this->id; |
||
3174 | $sql.= " AND sourcetype = '".$this->db->escape($this->element)."'"; |
||
3175 | } |
||
3176 | |||
3177 | dol_syslog(get_class($this)."::updateObjectLinked", LOG_DEBUG); |
||
3178 | if ($this->db->query($sql)) |
||
3179 | { |
||
3180 | return 1; |
||
3181 | } |
||
3182 | else |
||
3183 | { |
||
3184 | $this->error=$this->db->lasterror(); |
||
3185 | return -1; |
||
3186 | } |
||
3187 | } |
||
3188 | |||
3189 | /** |
||
3190 | * Delete all links between an object $this |
||
3191 | * |
||
3192 | * @param int $sourceid Object source id |
||
3193 | * @param string $sourcetype Object source type |
||
3194 | * @param int $targetid Object target id |
||
3195 | * @param string $targettype Object target type |
||
3196 | * @param int $rowid Row id of line to delete. If defined, other parameters are not used. |
||
3197 | * @return int >0 if OK, <0 if KO |
||
3198 | * @see add_object_linked, updateObjectLinked, fetchObjectLinked |
||
3199 | */ |
||
3200 | function deleteObjectLinked($sourceid=null, $sourcetype='', $targetid=null, $targettype='', $rowid='') |
||
3201 | { |
||
3202 | $deletesource=false; |
||
3203 | $deletetarget=false; |
||
3204 | |||
3205 | if (! empty($sourceid) && ! empty($sourcetype) && empty($targetid) && empty($targettype)) $deletesource=true; |
||
3206 | else if (empty($sourceid) && empty($sourcetype) && ! empty($targetid) && ! empty($targettype)) $deletetarget=true; |
||
3207 | |||
3208 | $sourceid = (! empty($sourceid) ? $sourceid : $this->id); |
||
3209 | $sourcetype = (! empty($sourcetype) ? $sourcetype : $this->element); |
||
3210 | $targetid = (! empty($targetid) ? $targetid : $this->id); |
||
3211 | $targettype = (! empty($targettype) ? $targettype : $this->element); |
||
3212 | |||
3213 | $sql = "DELETE FROM ".MAIN_DB_PREFIX."element_element"; |
||
3214 | $sql.= " WHERE"; |
||
3215 | if ($rowid > 0) |
||
3216 | { |
||
3217 | $sql.=" rowid = ".$rowid; |
||
3218 | } |
||
3219 | else |
||
3220 | { |
||
3221 | if ($deletesource) |
||
3222 | { |
||
3223 | $sql.= " fk_source = ".$sourceid." AND sourcetype = '".$this->db->escape($sourcetype)."'"; |
||
3224 | $sql.= " AND fk_target = ".$this->id." AND targettype = '".$this->db->escape($this->element)."'"; |
||
3225 | } |
||
3226 | else if ($deletetarget) |
||
3227 | { |
||
3228 | $sql.= " fk_target = ".$targetid." AND targettype = '".$this->db->escape($targettype)."'"; |
||
3229 | $sql.= " AND fk_source = ".$this->id." AND sourcetype = '".$this->db->escape($this->element)."'"; |
||
3230 | } |
||
3231 | else |
||
3232 | { |
||
3233 | $sql.= " (fk_source = ".$this->id." AND sourcetype = '".$this->db->escape($this->element)."')"; |
||
3234 | $sql.= " OR"; |
||
3235 | $sql.= " (fk_target = ".$this->id." AND targettype = '".$this->db->escape($this->element)."')"; |
||
3236 | } |
||
3237 | } |
||
3238 | |||
3239 | dol_syslog(get_class($this)."::deleteObjectLinked", LOG_DEBUG); |
||
3240 | if ($this->db->query($sql)) |
||
3241 | { |
||
3242 | return 1; |
||
3243 | } |
||
3244 | else |
||
3245 | { |
||
3246 | $this->error=$this->db->lasterror(); |
||
3247 | $this->errors[]=$this->error; |
||
3248 | return -1; |
||
3249 | } |
||
3250 | } |
||
3251 | |||
3252 | /** |
||
3253 | * Set status of an object |
||
3254 | * |
||
3255 | * @param int $status Status to set |
||
3256 | * @param int $elementId Id of element to force (use this->id by default) |
||
3257 | * @param string $elementType Type of element to force (use this->table_element by default) |
||
3258 | * @param string $trigkey Trigger key to use for trigger |
||
3259 | * @return int <0 if KO, >0 if OK |
||
3260 | */ |
||
3261 | function setStatut($status, $elementId=null, $elementType='', $trigkey='') |
||
3262 | { |
||
3263 | global $user,$langs,$conf; |
||
3264 | |||
3265 | $savElementId=$elementId; // To be used later to know if we were using the method using the id of this or not. |
||
3266 | |||
3267 | $elementId = (!empty($elementId)?$elementId:$this->id); |
||
3268 | $elementTable = (!empty($elementType)?$elementType:$this->table_element); |
||
3269 | |||
3270 | $this->db->begin(); |
||
3271 | |||
3272 | $fieldstatus="fk_statut"; |
||
3273 | if ($elementTable == 'facture_rec') $fieldstatus="suspended"; |
||
3274 | if ($elementTable == 'mailing') $fieldstatus="statut"; |
||
3275 | if ($elementTable == 'cronjob') $fieldstatus="status"; |
||
3276 | if ($elementTable == 'user') $fieldstatus="statut"; |
||
3277 | if ($elementTable == 'expensereport') $fieldstatus="fk_statut"; |
||
3278 | if ($elementTable == 'commande_fournisseur_dispatch') $fieldstatus="status"; |
||
3279 | |||
3280 | $sql = "UPDATE ".MAIN_DB_PREFIX.$elementTable; |
||
3281 | $sql.= " SET ".$fieldstatus." = ".$status; |
||
3282 | // If status = 1 = validated, update also fk_user_valid |
||
3283 | if ($status == 1 && $elementTable == 'expensereport') $sql.=", fk_user_valid = ".$user->id; |
||
3284 | $sql.= " WHERE rowid=".$elementId; |
||
3285 | |||
3286 | dol_syslog(get_class($this)."::setStatut", LOG_DEBUG); |
||
3287 | if ($this->db->query($sql)) |
||
3288 | { |
||
3289 | $error = 0; |
||
3290 | |||
3291 | // Try autoset of trigkey |
||
3292 | if (empty($trigkey)) |
||
3293 | { |
||
3294 | if ($this->element == 'supplier_proposal' && $status == 2) $trigkey='SUPPLIER_PROPOSAL_SIGN'; // 2 = SupplierProposal::STATUS_SIGNED. Can't use constant into this generic class |
||
3295 | if ($this->element == 'supplier_proposal' && $status == 3) $trigkey='SUPPLIER_PROPOSAL_REFUSE'; // 3 = SupplierProposal::STATUS_REFUSED. Can't use constant into this generic class |
||
3296 | if ($this->element == 'supplier_proposal' && $status == 4) $trigkey='SUPPLIER_PROPOSAL_CLOSE'; // 4 = SupplierProposal::STATUS_CLOSED. Can't use constant into this generic class |
||
3297 | if ($this->element == 'fichinter' && $status == 3) $trigkey='FICHINTER_CLASSIFY_DONE'; |
||
3298 | if ($this->element == 'fichinter' && $status == 2) $trigkey='FICHINTER_CLASSIFY_BILLED'; |
||
3299 | if ($this->element == 'fichinter' && $status == 1) $trigkey='FICHINTER_CLASSIFY_UNBILLED'; |
||
3300 | } |
||
3301 | |||
3302 | if ($trigkey) |
||
3303 | { |
||
3304 | // Appel des triggers |
||
3305 | include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php'; |
||
3306 | $interface=new Interfaces($this->db); |
||
3307 | $result=$interface->run_triggers($trigkey,$this,$user,$langs,$conf); |
||
3308 | if ($result < 0) { |
||
3309 | $error++; $this->errors=$interface->errors; |
||
3310 | } |
||
3311 | // Fin appel triggers |
||
3312 | } |
||
3313 | |||
3314 | if (! $error) |
||
3315 | { |
||
3316 | $this->db->commit(); |
||
3317 | |||
3318 | if (empty($savElementId)) // If the element we update was $this (so $elementId is null) |
||
3319 | { |
||
3320 | $this->statut = $status; |
||
3321 | $this->status = $status; |
||
3322 | } |
||
3323 | |||
3324 | return 1; |
||
3325 | } |
||
3326 | else |
||
3327 | { |
||
3328 | $this->db->rollback(); |
||
3329 | dol_syslog(get_class($this)."::setStatus ".$this->error,LOG_ERR); |
||
3330 | return -1; |
||
3331 | } |
||
3332 | } |
||
3333 | else |
||
3334 | { |
||
3335 | $this->error=$this->db->lasterror(); |
||
3336 | $this->db->rollback(); |
||
3337 | return -1; |
||
3338 | } |
||
3339 | } |
||
3340 | |||
3341 | |||
3342 | /** |
||
3343 | * Load type of canvas of an object if it exists |
||
3344 | * |
||
3345 | * @param int $id Record id |
||
3346 | * @param string $ref Record ref |
||
3347 | * @return int <0 if KO, 0 if nothing done, >0 if OK |
||
3348 | */ |
||
3349 | function getCanvas($id=0,$ref='') |
||
3350 | { |
||
3351 | global $conf; |
||
3352 | |||
3353 | if (empty($id) && empty($ref)) return 0; |
||
3354 | if (! empty($conf->global->MAIN_DISABLE_CANVAS)) return 0; // To increase speed. Not enabled by default. |
||
3355 | |||
3356 | // Clean parameters |
||
3357 | $ref = trim($ref); |
||
3358 | |||
3359 | $sql = "SELECT rowid, canvas"; |
||
3360 | $sql.= " FROM ".MAIN_DB_PREFIX.$this->table_element; |
||
3361 | $sql.= " WHERE entity IN (".getEntity($this->element).")"; |
||
3362 | if (! empty($id)) $sql.= " AND rowid = ".$id; |
||
3363 | if (! empty($ref)) $sql.= " AND ref = '".$this->db->escape($ref)."'"; |
||
3364 | |||
3365 | $resql = $this->db->query($sql); |
||
3366 | if ($resql) |
||
3367 | { |
||
3368 | $obj = $this->db->fetch_object($resql); |
||
3369 | if ($obj) |
||
3370 | { |
||
3371 | $this->canvas = $obj->canvas; |
||
3372 | return 1; |
||
3373 | } |
||
3374 | else return 0; |
||
3375 | } |
||
3376 | else |
||
3377 | { |
||
3378 | dol_print_error($this->db); |
||
3379 | return -1; |
||
3380 | } |
||
3381 | } |
||
3382 | |||
3383 | |||
3384 | /** |
||
3385 | * Get special code of a line |
||
3386 | * |
||
3387 | * @param int $lineid Id of line |
||
3388 | * @return int Special code |
||
3389 | */ |
||
3390 | function getSpecialCode($lineid) |
||
3391 | { |
||
3392 | $sql = 'SELECT special_code FROM '.MAIN_DB_PREFIX.$this->table_element_line; |
||
3393 | $sql.= ' WHERE rowid = '.$lineid; |
||
3394 | $resql = $this->db->query($sql); |
||
3395 | if ($resql) |
||
3396 | { |
||
3397 | $row = $this->db->fetch_row($resql); |
||
3398 | return $row[0]; |
||
3399 | } |
||
3400 | } |
||
3401 | |||
3402 | /** |
||
3403 | * Function to check if an object is used by others. |
||
3404 | * Check is done into this->childtables. There is no check into llx_element_element. |
||
3405 | * |
||
3406 | * @param int $id Force id of object |
||
3407 | * @return int <0 if KO, 0 if not used, >0 if already used |
||
3408 | */ |
||
3409 | function isObjectUsed($id=0) |
||
3410 | { |
||
3411 | global $langs; |
||
3412 | |||
3413 | if (empty($id)) $id=$this->id; |
||
3414 | |||
3415 | // Check parameters |
||
3416 | if (! isset($this->childtables) || ! is_array($this->childtables) || count($this->childtables) == 0) |
||
3417 | { |
||
3418 | dol_print_error('Called isObjectUsed on a class with property this->childtables not defined'); |
||
3419 | return -1; |
||
3420 | } |
||
3421 | |||
3422 | $arraytoscan = $this->childtables; |
||
3423 | // For backward compatibility, we check if array is old format array('table1', 'table2', ...) |
||
3424 | $tmparray=array_keys($this->childtables); |
||
3425 | if (is_numeric($tmparray[0])) |
||
3426 | { |
||
3427 | $arraytoscan = array_flip($this->childtables); |
||
3428 | } |
||
3429 | |||
3430 | // Test if child exists |
||
3431 | $haschild=0; |
||
3432 | foreach($arraytoscan as $table => $elementname) |
||
3433 | { |
||
3434 | //print $id.'-'.$table.'-'.$elementname.'<br>'; |
||
3435 | // Check if third party can be deleted |
||
3436 | $sql = "SELECT COUNT(*) as nb from ".MAIN_DB_PREFIX.$table; |
||
3437 | $sql.= " WHERE ".$this->fk_element." = ".$id; |
||
3438 | $resql=$this->db->query($sql); |
||
3439 | if ($resql) |
||
3440 | { |
||
3441 | $obj=$this->db->fetch_object($resql); |
||
3442 | if ($obj->nb > 0) |
||
3443 | { |
||
3444 | $langs->load("errors"); |
||
3445 | //print 'Found into table '.$table.', type '.$langs->transnoentitiesnoconv($elementname).', haschild='.$haschild; |
||
3446 | $haschild += $obj->nb; |
||
3447 | if (is_numeric($elementname)) // old usage |
||
3448 | { |
||
3449 | $this->errors[]=$langs->trans("ErrorRecordHasAtLeastOneChildOfType", $table); |
||
3450 | } |
||
3451 | else // new usage: $elementname=Translation key |
||
3452 | { |
||
3453 | $this->errors[]=$langs->trans("ErrorRecordHasAtLeastOneChildOfType", $langs->transnoentitiesnoconv($elementname)); |
||
3454 | } |
||
3455 | break; // We found at least one, we stop here |
||
3456 | } |
||
3457 | } |
||
3458 | else |
||
3459 | { |
||
3460 | $this->errors[]=$this->db->lasterror(); |
||
3461 | return -1; |
||
3462 | } |
||
3463 | } |
||
3464 | if ($haschild > 0) |
||
3465 | { |
||
3466 | $this->errors[]="ErrorRecordHasChildren"; |
||
3467 | return $haschild; |
||
3468 | } |
||
3469 | else return 0; |
||
3470 | } |
||
3471 | |||
3472 | /** |
||
3473 | * Function to say how many lines object contains |
||
3474 | * |
||
3475 | * @param int $predefined -1=All, 0=Count free product/service only, 1=Count predefined product/service only, 2=Count predefined product, 3=Count predefined service |
||
3476 | * @return int <0 if KO, 0 if no predefined products, nb of lines with predefined products if found |
||
3477 | */ |
||
3478 | function hasProductsOrServices($predefined=-1) |
||
3479 | { |
||
3480 | $nb=0; |
||
3481 | |||
3482 | foreach($this->lines as $key => $val) |
||
3483 | { |
||
3484 | $qualified=0; |
||
3485 | if ($predefined == -1) $qualified=1; |
||
3486 | if ($predefined == 1 && $val->fk_product > 0) $qualified=1; |
||
3487 | if ($predefined == 0 && $val->fk_product <= 0) $qualified=1; |
||
3488 | if ($predefined == 2 && $val->fk_product > 0 && $val->product_type==0) $qualified=1; |
||
3489 | if ($predefined == 3 && $val->fk_product > 0 && $val->product_type==1) $qualified=1; |
||
3490 | if ($qualified) $nb++; |
||
3491 | } |
||
3492 | dol_syslog(get_class($this).'::hasProductsOrServices we found '.$nb.' qualified lines of products/servcies'); |
||
3493 | return $nb; |
||
3494 | } |
||
3495 | |||
3496 | /** |
||
3497 | * Function that returns the total amount HT of discounts applied for all lines. |
||
3498 | * |
||
3499 | * @return float |
||
3500 | */ |
||
3501 | function getTotalDiscount() |
||
3502 | { |
||
3503 | $total_discount=0.00; |
||
3504 | |||
3505 | $sql = "SELECT subprice as pu_ht, qty, remise_percent, total_ht"; |
||
3506 | $sql.= " FROM ".MAIN_DB_PREFIX.$this->table_element."det"; |
||
3507 | $sql.= " WHERE ".$this->fk_element." = ".$this->id; |
||
3508 | |||
3509 | dol_syslog(get_class($this).'::getTotalDiscount', LOG_DEBUG); |
||
3510 | $resql = $this->db->query($sql); |
||
3511 | if ($resql) |
||
3512 | { |
||
3513 | $num=$this->db->num_rows($resql); |
||
3514 | $i=0; |
||
3515 | while ($i < $num) |
||
3516 | { |
||
3517 | $obj = $this->db->fetch_object($resql); |
||
3518 | |||
3519 | $pu_ht = $obj->pu_ht; |
||
3520 | $qty= $obj->qty; |
||
3521 | $total_ht = $obj->total_ht; |
||
3522 | |||
3523 | $total_discount_line = floatval(price2num(($pu_ht * $qty) - $total_ht, 'MT')); |
||
3524 | $total_discount += $total_discount_line; |
||
3525 | |||
3526 | $i++; |
||
3527 | } |
||
3528 | } |
||
3529 | |||
3530 | //print $total_discount; exit; |
||
3531 | return price2num($total_discount); |
||
3532 | } |
||
3533 | |||
3534 | |||
3535 | /** |
||
3536 | * Return into unit=0, the calculated total of weight and volume of all lines * qty |
||
3537 | * Calculate by adding weight and volume of each product line, so properties ->volume/volume_units/weight/weight_units must be loaded on line. |
||
3538 | * |
||
3539 | * @return array array('weight'=>...,'volume'=>...) |
||
3540 | */ |
||
3541 | function getTotalWeightVolume() |
||
3542 | { |
||
3543 | $totalWeight = 0; |
||
3544 | $totalVolume = 0; |
||
3545 | // defined for shipment only |
||
3546 | $totalOrdered = ''; |
||
3547 | // defined for shipment only |
||
3548 | $totalToShip = ''; |
||
3549 | |||
3550 | foreach ($this->lines as $line) |
||
3551 | { |
||
3552 | if (isset($line->qty_asked)) |
||
3553 | { |
||
3554 | if (empty($totalOrdered)) $totalOrdered=0; // Avoid warning because $totalOrdered is '' |
||
3555 | $totalOrdered+=$line->qty_asked; // defined for shipment only |
||
3556 | } |
||
3557 | if (isset($line->qty_shipped)) |
||
3558 | { |
||
3559 | if (empty($totalToShip)) $totalToShip=0; // Avoid warning because $totalToShip is '' |
||
3560 | $totalToShip+=$line->qty_shipped; // defined for shipment only |
||
3561 | }else if ($line->element == 'commandefournisseurdispatch' && isset($line->qty)) |
||
3562 | { |
||
3563 | if (empty($totalToShip)) $totalToShip=0; |
||
3564 | $totalToShip+=$line->qty; // defined for reception only |
||
3565 | } |
||
3566 | |||
3567 | // Define qty, weight, volume, weight_units, volume_units |
||
3568 | if ($this->element == 'shipping') { |
||
3569 | // for shipments |
||
3570 | $qty = $line->qty_shipped ? $line->qty_shipped : 0; |
||
3571 | } |
||
3572 | else { |
||
3573 | $qty = $line->qty ? $line->qty : 0; |
||
3574 | } |
||
3575 | |||
3576 | $weight = $line->weight ? $line->weight : 0; |
||
3577 | ($weight==0 && !empty($line->product->weight))? $weight=$line->product->weight: 0; |
||
3578 | $volume = $line->volume ? $line->volume : 0; |
||
3579 | ($volume==0 && !empty($line->product->volume))? $volume=$line->product->volume: 0; |
||
3580 | |||
3581 | $weight_units=$line->weight_units; |
||
3582 | ($weight_units==0 && !empty($line->product->weight_units))? $weight_units=$line->product->weight_units: 0; |
||
3583 | $volume_units=$line->volume_units; |
||
3584 | ($volume_units==0 && !empty($line->product->volume_units))? $volume_units=$line->product->volume_units: 0; |
||
3585 | |||
3586 | $weightUnit=0; |
||
3587 | $volumeUnit=0; |
||
3588 | if (! empty($weight_units)) $weightUnit = $weight_units; |
||
3589 | if (! empty($volume_units)) $volumeUnit = $volume_units; |
||
3590 | |||
3591 | if (empty($totalWeight)) $totalWeight=0; // Avoid warning because $totalWeight is '' |
||
3592 | if (empty($totalVolume)) $totalVolume=0; // Avoid warning because $totalVolume is '' |
||
3593 | |||
3594 | //var_dump($line->volume_units); |
||
3595 | if ($weight_units < 50) // >50 means a standard unit (power of 10 of official unit), > 50 means an exotic unit (like inch) |
||
3596 | { |
||
3597 | $trueWeightUnit=pow(10, $weightUnit); |
||
3598 | $totalWeight += $weight * $qty * $trueWeightUnit; |
||
3599 | } |
||
3600 | else { |
||
3601 | if ($weight_units == 99) { |
||
3602 | // conversion 1 Pound = 0.45359237 KG |
||
3603 | $trueWeightUnit = 0.45359237; |
||
3604 | $totalWeight += $weight * $qty * $trueWeightUnit; |
||
3605 | } elseif ($weight_units == 98) { |
||
3606 | // conversion 1 Ounce = 0.0283495 KG |
||
3607 | $trueWeightUnit = 0.0283495; |
||
3608 | $totalWeight += $weight * $qty * $trueWeightUnit; |
||
3609 | } |
||
3610 | else |
||
3611 | $totalWeight += $weight * $qty; // This may be wrong if we mix different units |
||
3612 | } |
||
3613 | if ($volume_units < 50) // >50 means a standard unit (power of 10 of official unit), > 50 means an exotic unit (like inch) |
||
3614 | { |
||
3615 | //print $line->volume."x".$line->volume_units."x".($line->volume_units < 50)."x".$volumeUnit; |
||
3616 | $trueVolumeUnit=pow(10, $volumeUnit); |
||
3617 | //print $line->volume; |
||
3618 | $totalVolume += $volume * $qty * $trueVolumeUnit; |
||
3619 | } |
||
3620 | else |
||
3621 | { |
||
3622 | $totalVolume += $volume * $qty; // This may be wrong if we mix different units |
||
3623 | } |
||
3624 | } |
||
3625 | |||
3626 | return array('weight'=>$totalWeight, 'volume'=>$totalVolume, 'ordered'=>$totalOrdered, 'toship'=>$totalToShip); |
||
3627 | } |
||
3628 | |||
3629 | |||
3630 | /** |
||
3631 | * Set extra parameters |
||
3632 | * |
||
3633 | * @return int <0 if KO, >0 if OK |
||
3634 | */ |
||
3635 | function setExtraParameters() |
||
3636 | { |
||
3637 | $this->db->begin(); |
||
3638 | |||
3639 | $extraparams = (! empty($this->extraparams) ? json_encode($this->extraparams) : null); |
||
3640 | |||
3641 | $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element; |
||
3642 | $sql.= " SET extraparams = ".(! empty($extraparams) ? "'".$this->db->escape($extraparams)."'" : "null"); |
||
3643 | $sql.= " WHERE rowid = ".$this->id; |
||
3644 | |||
3645 | dol_syslog(get_class($this)."::setExtraParameters", LOG_DEBUG); |
||
3646 | $resql = $this->db->query($sql); |
||
3647 | if (! $resql) |
||
3648 | { |
||
3649 | $this->error=$this->db->lasterror(); |
||
3650 | $this->db->rollback(); |
||
3651 | return -1; |
||
3652 | } |
||
3653 | else |
||
3654 | { |
||
3655 | $this->db->commit(); |
||
3656 | return 1; |
||
3657 | } |
||
3658 | } |
||
3659 | |||
3660 | |||
3661 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
3662 | /** |
||
3663 | * Return incoterms informations |
||
3664 | * TODO Use a cache for label get |
||
3665 | * |
||
3666 | * @return string incoterms info |
||
3667 | */ |
||
3668 | function display_incoterms() |
||
3669 | { |
||
3670 | // phpcs:enable |
||
3671 | $out = ''; |
||
3672 | $this->libelle_incoterms = ''; |
||
3673 | if (!empty($this->fk_incoterms)) |
||
3674 | { |
||
3675 | $sql = 'SELECT code FROM '.MAIN_DB_PREFIX.'c_incoterms WHERE rowid = '.(int) $this->fk_incoterms; |
||
3676 | $result = $this->db->query($sql); |
||
3677 | if ($result) |
||
3678 | { |
||
3679 | $res = $this->db->fetch_object($result); |
||
3680 | $out .= $res->code; |
||
3681 | } |
||
3682 | } |
||
3683 | |||
3684 | $out .= (($res->code && $this->location_incoterms)?' - ':'').$this->location_incoterms; |
||
3685 | |||
3686 | return $out; |
||
3687 | } |
||
3688 | |||
3689 | /** |
||
3690 | * Return incoterms informations for pdf display |
||
3691 | * |
||
3692 | * @return string incoterms info |
||
3693 | */ |
||
3694 | function getIncotermsForPDF() |
||
3695 | { |
||
3696 | $sql = 'SELECT code FROM '.MAIN_DB_PREFIX.'c_incoterms WHERE rowid = '.(int) $this->fk_incoterms; |
||
3697 | $resql = $this->db->query($sql); |
||
3698 | if ($resql) |
||
3699 | { |
||
3700 | $num = $this->db->num_rows($resql); |
||
3701 | if ($num > 0) |
||
3702 | { |
||
3703 | $res = $this->db->fetch_object($resql); |
||
3704 | return 'Incoterm : '.$res->code.' - '.$this->location_incoterms; |
||
3705 | } |
||
3706 | else |
||
3707 | { |
||
3708 | return ''; |
||
3709 | } |
||
3710 | } |
||
3711 | else |
||
3712 | { |
||
3713 | $this->errors[] = $this->db->lasterror(); |
||
3714 | return false; |
||
3715 | } |
||
3716 | } |
||
3717 | |||
3718 | /** |
||
3719 | * Define incoterms values of current object |
||
3720 | * |
||
3721 | * @param int $id_incoterm Id of incoterm to set or '' to remove |
||
3722 | * @param string $location location of incoterm |
||
3723 | * @return int <0 if KO, >0 if OK |
||
3724 | */ |
||
3725 | function setIncoterms($id_incoterm, $location) |
||
3726 | { |
||
3727 | if ($this->id && $this->table_element) |
||
3728 | { |
||
3729 | $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element; |
||
3730 | $sql.= " SET fk_incoterms = ".($id_incoterm > 0 ? $id_incoterm : "null"); |
||
3731 | $sql.= ", location_incoterms = ".($id_incoterm > 0 ? "'".$this->db->escape($location)."'" : "null"); |
||
3732 | $sql.= " WHERE rowid = " . $this->id; |
||
3733 | dol_syslog(get_class($this).'::setIncoterms', LOG_DEBUG); |
||
3734 | $resql=$this->db->query($sql); |
||
3735 | if ($resql) |
||
3736 | { |
||
3737 | $this->fk_incoterms = $id_incoterm; |
||
3738 | $this->location_incoterms = $location; |
||
3739 | |||
3740 | $sql = 'SELECT libelle FROM '.MAIN_DB_PREFIX.'c_incoterms WHERE rowid = '.(int) $this->fk_incoterms; |
||
3741 | $res = $this->db->query($sql); |
||
3742 | if ($res) |
||
3743 | { |
||
3744 | $obj = $this->db->fetch_object($res); |
||
3745 | $this->libelle_incoterms = $obj->libelle; |
||
3746 | } |
||
3747 | return 1; |
||
3748 | } |
||
3749 | else |
||
3750 | { |
||
3751 | $this->errors[] = $this->db->lasterror(); |
||
3752 | return -1; |
||
3753 | } |
||
3754 | } |
||
3755 | else return -1; |
||
3756 | } |
||
3757 | |||
3758 | |||
3759 | // -------------------- |
||
3760 | // TODO: All functions here must be redesigned and moved as they are not business functions but output functions |
||
3761 | // -------------------- |
||
3762 | |||
3763 | /* This is to show add lines */ |
||
3764 | |||
3765 | /** |
||
3766 | * Show add free and predefined products/services form |
||
3767 | * |
||
3768 | * @param int $dateSelector 1=Show also date range input fields |
||
3769 | * @param Societe $seller Object thirdparty who sell |
||
3770 | * @param Societe $buyer Object thirdparty who buy |
||
3771 | * @return void |
||
3772 | */ |
||
3773 | function formAddObjectLine($dateSelector, $seller, $buyer) |
||
3774 | { |
||
3775 | global $conf,$user,$langs,$object,$hookmanager; |
||
3776 | global $form,$bcnd,$var; |
||
3777 | |||
3778 | // Line extrafield |
||
3779 | require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; |
||
3780 | $extrafieldsline = new ExtraFields($this->db); |
||
3781 | $extralabelslines=$extrafieldsline->fetch_name_optionals_label($this->table_element_line); |
||
3782 | |||
3783 | // Output template part (modules that overwrite templates must declare this into descriptor) |
||
3784 | // Use global variables + $dateSelector + $seller and $buyer |
||
3785 | $dirtpls=array_merge($conf->modules_parts['tpl'],array('/core/tpl')); |
||
3786 | foreach($dirtpls as $reldir) |
||
3787 | { |
||
3788 | $tpl = dol_buildpath($reldir.'/objectline_create.tpl.php'); |
||
3789 | if (empty($conf->file->strict_mode)) { |
||
3790 | $res=@include $tpl; |
||
3791 | } else { |
||
3792 | $res=include $tpl; // for debug |
||
3793 | } |
||
3794 | if ($res) break; |
||
3795 | } |
||
3796 | } |
||
3797 | |||
3798 | |||
3799 | |||
3800 | /* This is to show array of line of details */ |
||
3801 | |||
3802 | |||
3803 | /** |
||
3804 | * Return HTML table for object lines |
||
3805 | * TODO Move this into an output class file (htmlline.class.php) |
||
3806 | * If lines are into a template, title must also be into a template |
||
3807 | * But for the moment we don't know if it's possible as we keep a method available on overloaded objects. |
||
3808 | * |
||
3809 | * @param string $action Action code |
||
3810 | * @param string $seller Object of seller third party |
||
3811 | * @param string $buyer Object of buyer third party |
||
3812 | * @param int $selected Object line selected |
||
3813 | * @param int $dateSelector 1=Show also date range input fields |
||
3814 | * @return void |
||
3815 | */ |
||
3816 | function printObjectLines($action, $seller, $buyer, $selected=0, $dateSelector=0) |
||
3817 | { |
||
3818 | global $conf, $hookmanager, $langs, $user; |
||
3819 | // TODO We should not use global var for this ! |
||
3820 | global $inputalsopricewithtax, $usemargins, $disableedit, $disablemove, $disableremove, $outputalsopricetotalwithtax; |
||
3821 | |||
3822 | // Define usemargins |
||
3823 | $usemargins=0; |
||
3824 | if (! empty($conf->margin->enabled) && ! empty($this->element) && in_array($this->element,array('facture','propal','commande'))) $usemargins=1; |
||
3825 | |||
3826 | $num = count($this->lines); |
||
3827 | |||
3828 | // Line extrafield |
||
3829 | require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; |
||
3830 | $extrafieldsline = new ExtraFields($this->db); |
||
3831 | $extralabelslines=$extrafieldsline->fetch_name_optionals_label($this->table_element_line); |
||
3832 | |||
3833 | $parameters = array('num'=>$num,'i'=>$i,'dateSelector'=>$dateSelector,'seller'=>$seller,'buyer'=>$buyer,'selected'=>$selected, 'extrafieldsline'=>$extrafieldsline); |
||
3834 | $reshook = $hookmanager->executeHooks('printObjectLineTitle', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks |
||
3835 | if (empty($reshook)) |
||
3836 | { |
||
3837 | // Title line |
||
3838 | print "<thead>\n"; |
||
3839 | |||
3840 | print '<tr class="liste_titre nodrag nodrop">'; |
||
3841 | |||
3842 | // Adds a line numbering column |
||
3843 | if (! empty($conf->global->MAIN_VIEW_LINE_NUMBER)) print '<td class="linecolnum" align="center" width="5"> </td>'; |
||
3844 | |||
3845 | // Description |
||
3846 | print '<td class="linecoldescription">'.$langs->trans('Description').'</td>'; |
||
3847 | |||
3848 | if ($this->element == 'supplier_proposal' || $this->element == 'order_supplier' || $this->element == 'invoice_supplier') |
||
3849 | { |
||
3850 | print '<td class="linerefsupplier"><span id="title_fourn_ref">'.$langs->trans("SupplierRef").'</span></td>'; |
||
3851 | } |
||
3852 | |||
3853 | // VAT |
||
3854 | print '<td class="linecolvat" align="right" width="80">'.$langs->trans('VAT').'</td>'; |
||
3855 | |||
3856 | // Price HT |
||
3857 | print '<td class="linecoluht" align="right" width="80">'.$langs->trans('PriceUHT').'</td>'; |
||
3858 | |||
3859 | // Multicurrency |
||
3860 | if (!empty($conf->multicurrency->enabled) && $this->multicurrency_code != $conf->currency) print '<td class="linecoluht_currency" align="right" width="80">'.$langs->trans('PriceUHTCurrency', $this->multicurrency_code).'</td>'; |
||
3861 | |||
3862 | if ($inputalsopricewithtax) print '<td align="right" width="80">'.$langs->trans('PriceUTTC').'</td>'; |
||
3863 | |||
3864 | // Qty |
||
3865 | print '<td class="linecolqty" align="right">'.$langs->trans('Qty').'</td>'; |
||
3866 | |||
3867 | if($conf->global->PRODUCT_USE_UNITS) |
||
3868 | { |
||
3869 | print '<td class="linecoluseunit" align="left">'.$langs->trans('Unit').'</td>'; |
||
3870 | } |
||
3871 | |||
3872 | // Reduction short |
||
3873 | print '<td class="linecoldiscount" align="right">'.$langs->trans('ReductionShort').'</td>'; |
||
3874 | |||
3875 | if ($this->situation_cycle_ref) { |
||
3876 | print '<td class="linecolcycleref" align="right">' . $langs->trans('Progress') . '</td>'; |
||
3877 | } |
||
3878 | |||
3879 | if ($usemargins && ! empty($conf->margin->enabled) && empty($user->societe_id)) |
||
3880 | { |
||
3881 | if (!empty($user->rights->margins->creer)) |
||
3882 | { |
||
3883 | if ($conf->global->MARGIN_TYPE == "1") |
||
3884 | print '<td class="linecolmargin1 margininfos" align="right" width="80">'.$langs->trans('BuyingPrice').'</td>'; |
||
3885 | else |
||
3886 | print '<td class="linecolmargin1 margininfos" align="right" width="80">'.$langs->trans('CostPrice').'</td>'; |
||
3887 | } |
||
3888 | |||
3889 | if (! empty($conf->global->DISPLAY_MARGIN_RATES) && $user->rights->margins->liretous) |
||
3890 | print '<td class="linecolmargin2 margininfos" align="right" width="50">'.$langs->trans('MarginRate').'</td>'; |
||
3891 | if (! empty($conf->global->DISPLAY_MARK_RATES) && $user->rights->margins->liretous) |
||
3892 | print '<td class="linecolmargin2 margininfos" align="right" width="50">'.$langs->trans('MarkRate').'</td>'; |
||
3893 | } |
||
3894 | |||
3895 | // Total HT |
||
3896 | print '<td class="linecolht" align="right">'.$langs->trans('TotalHTShort').'</td>'; |
||
3897 | |||
3898 | // Multicurrency |
||
3899 | if (!empty($conf->multicurrency->enabled) && $this->multicurrency_code != $conf->currency) print '<td class="linecoltotalht_currency" align="right">'.$langs->trans('TotalHTShortCurrency', $this->multicurrency_code).'</td>'; |
||
3900 | |||
3901 | if ($outputalsopricetotalwithtax) print '<td align="right" width="80">'.$langs->trans('TotalTTCShort').'</td>'; |
||
3902 | |||
3903 | print '<td class="linecoledit"></td>'; // No width to allow autodim |
||
3904 | |||
3905 | print '<td class="linecoldelete" width="10"></td>'; |
||
3906 | |||
3907 | print '<td class="linecolmove" width="10"></td>'; |
||
3908 | |||
3909 | if($action == 'selectlines') |
||
3910 | { |
||
3911 | print '<td class="linecolcheckall" align="center">'; |
||
3912 | print '<input type="checkbox" class="linecheckboxtoggle" />'; |
||
3913 | print '<script type="text/javascript">$(document).ready(function() {$(".linecheckboxtoggle").click(function() {var checkBoxes = $(".linecheckbox");checkBoxes.prop("checked", this.checked);})});</script>'; |
||
3914 | print '</td>'; |
||
3915 | } |
||
3916 | |||
3917 | print "</tr>\n"; |
||
3918 | print "</thead>\n"; |
||
3919 | } |
||
3920 | |||
3921 | $var = true; |
||
3922 | $i = 0; |
||
3923 | |||
3924 | print "<tbody>\n"; |
||
3925 | foreach ($this->lines as $line) |
||
3926 | { |
||
3927 | //Line extrafield |
||
3928 | $line->fetch_optionals(); |
||
3929 | |||
3930 | //if (is_object($hookmanager) && (($line->product_type == 9 && ! empty($line->special_code)) || ! empty($line->fk_parent_line))) |
||
3931 | if (is_object($hookmanager)) // Old code is commented on preceding line. |
||
3932 | { |
||
3933 | if (empty($line->fk_parent_line)) |
||
3934 | { |
||
3935 | $parameters = array('line'=>$line,'var'=>$var,'num'=>$num,'i'=>$i,'dateSelector'=>$dateSelector,'seller'=>$seller,'buyer'=>$buyer,'selected'=>$selected, 'extrafieldsline'=>$extrafieldsline); |
||
3936 | $reshook = $hookmanager->executeHooks('printObjectLine', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks |
||
3937 | } |
||
3938 | else |
||
3939 | { |
||
3940 | $parameters = array('line'=>$line,'var'=>$var,'num'=>$num,'i'=>$i,'dateSelector'=>$dateSelector,'seller'=>$seller,'buyer'=>$buyer,'selected'=>$selected, 'extrafieldsline'=>$extrafieldsline, 'fk_parent_line'=>$line->fk_parent_line); |
||
3941 | $reshook = $hookmanager->executeHooks('printObjectSubLine', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks |
||
3942 | } |
||
3943 | } |
||
3944 | if (empty($reshook)) |
||
3945 | { |
||
3946 | $this->printObjectLine($action,$line,$var,$num,$i,$dateSelector,$seller,$buyer,$selected,$extrafieldsline); |
||
3947 | } |
||
3948 | |||
3949 | $i++; |
||
3950 | } |
||
3951 | print "</tbody>\n"; |
||
3952 | } |
||
3953 | |||
3954 | /** |
||
3955 | * Return HTML content of a detail line |
||
3956 | * TODO Move this into an output class file (htmlline.class.php) |
||
3957 | * |
||
3958 | * @param string $action GET/POST action |
||
3959 | * @param CommonObjectLine $line Selected object line to output |
||
3960 | * @param string $var Is it a an odd line (true) |
||
3961 | * @param int $num Number of line (0) |
||
3962 | * @param int $i I |
||
3963 | * @param int $dateSelector 1=Show also date range input fields |
||
3964 | * @param string $seller Object of seller third party |
||
3965 | * @param string $buyer Object of buyer third party |
||
3966 | * @param int $selected Object line selected |
||
3967 | * @param int $extrafieldsline Object of extrafield line attribute |
||
3968 | * @return void |
||
3969 | */ |
||
3970 | function printObjectLine($action,$line,$var,$num,$i,$dateSelector,$seller,$buyer,$selected=0,$extrafieldsline=0) |
||
3971 | { |
||
3972 | global $conf,$langs,$user,$object,$hookmanager; |
||
3973 | global $form,$bc,$bcdd; |
||
3974 | global $object_rights, $disableedit, $disablemove, $disableremove; // TODO We should not use global var for this ! |
||
3975 | |||
3976 | $object_rights = $this->getRights(); |
||
3977 | |||
3978 | $element=$this->element; |
||
3979 | |||
3980 | $text=''; $description=''; $type=0; |
||
3981 | |||
3982 | // Show product and description |
||
3983 | $type=(! empty($line->product_type)?$line->product_type:$line->fk_product_type); |
||
3984 | // Try to enhance type detection using date_start and date_end for free lines where type was not saved. |
||
3985 | if (! empty($line->date_start)) $type=1; // deprecated |
||
3986 | if (! empty($line->date_end)) $type=1; // deprecated |
||
3987 | |||
3988 | // Ligne en mode visu |
||
3989 | if ($action != 'editline' || $selected != $line->id) |
||
3990 | { |
||
3991 | // Product |
||
3992 | if ($line->fk_product > 0) |
||
3993 | { |
||
3994 | $product_static = new Product($this->db); |
||
3995 | $product_static->fetch($line->fk_product); |
||
3996 | |||
3997 | $product_static->ref = $line->ref; //can change ref in hook |
||
3998 | $product_static->label = $line->label; //can change label in hook |
||
3999 | $text=$product_static->getNomUrl(1); |
||
4000 | |||
4001 | // Define output language and label |
||
4002 | if (! empty($conf->global->MAIN_MULTILANGS)) |
||
4003 | { |
||
4004 | if (! is_object($this->thirdparty)) |
||
4005 | { |
||
4006 | dol_print_error('','Error: Method printObjectLine was called on an object and object->fetch_thirdparty was not done before'); |
||
4007 | return; |
||
4008 | } |
||
4009 | |||
4010 | $prod = new Product($this->db); |
||
4011 | $prod->fetch($line->fk_product); |
||
4012 | |||
4013 | $outputlangs = $langs; |
||
4014 | $newlang=''; |
||
4015 | if (empty($newlang) && GETPOST('lang_id','aZ09')) $newlang=GETPOST('lang_id','aZ09'); |
||
4016 | if (! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE) && empty($newlang)) $newlang=$this->thirdparty->default_lang; // For language to language of customer |
||
4017 | if (! empty($newlang)) |
||
4018 | { |
||
4019 | $outputlangs = new Translate("",$conf); |
||
4020 | $outputlangs->setDefaultLang($newlang); |
||
4021 | } |
||
4022 | |||
4023 | $label = (! empty($prod->multilangs[$outputlangs->defaultlang]["label"])) ? $prod->multilangs[$outputlangs->defaultlang]["label"] : $line->product_label; |
||
4024 | } |
||
4025 | else |
||
4026 | { |
||
4027 | $label = $line->product_label; |
||
4028 | } |
||
4029 | |||
4030 | $text.= ' - '.(! empty($line->label)?$line->label:$label); |
||
4031 | $description.=(! empty($conf->global->PRODUIT_DESC_IN_FORM)?'':dol_htmlentitiesbr($line->description)); // Description is what to show on popup. We shown nothing if already into desc. |
||
4032 | } |
||
4033 | |||
4034 | $line->pu_ttc = price2num($line->subprice * (1 + ($line->tva_tx/100)), 'MU'); |
||
4035 | |||
4036 | // Output template part (modules that overwrite templates must declare this into descriptor) |
||
4037 | // Use global variables + $dateSelector + $seller and $buyer |
||
4038 | $dirtpls=array_merge($conf->modules_parts['tpl'],array('/core/tpl')); |
||
4039 | foreach($dirtpls as $reldir) |
||
4040 | { |
||
4041 | $tpl = dol_buildpath($reldir.'/objectline_view.tpl.php'); |
||
4042 | if (empty($conf->file->strict_mode)) { |
||
4043 | $res=@include $tpl; |
||
4044 | } else { |
||
4045 | $res=include $tpl; // for debug |
||
4046 | } |
||
4047 | if ($res) break; |
||
4048 | } |
||
4049 | } |
||
4050 | |||
4051 | // Ligne en mode update |
||
4052 | if ($this->statut == 0 && $action == 'editline' && $selected == $line->id) |
||
4053 | { |
||
4054 | $label = (! empty($line->label) ? $line->label : (($line->fk_product > 0) ? $line->product_label : '')); |
||
4055 | $placeholder=' placeholder="'.$langs->trans("Label").'"'; |
||
4056 | |||
4057 | $line->pu_ttc = price2num($line->subprice * (1 + ($line->tva_tx/100)), 'MU'); |
||
4058 | |||
4059 | // Output template part (modules that overwrite templates must declare this into descriptor) |
||
4060 | // Use global variables + $dateSelector + $seller and $buyer |
||
4061 | $dirtpls=array_merge($conf->modules_parts['tpl'],array('/core/tpl')); |
||
4062 | foreach($dirtpls as $reldir) |
||
4063 | { |
||
4064 | $tpl = dol_buildpath($reldir.'/objectline_edit.tpl.php'); |
||
4065 | if (empty($conf->file->strict_mode)) { |
||
4066 | $res=@include $tpl; |
||
4067 | } else { |
||
4068 | $res=include $tpl; // for debug |
||
4069 | } |
||
4070 | if ($res) break; |
||
4071 | } |
||
4072 | } |
||
4073 | } |
||
4074 | |||
4075 | |||
4076 | /* This is to show array of line of details of source object */ |
||
4077 | |||
4078 | |||
4079 | /** |
||
4080 | * Return HTML table table of source object lines |
||
4081 | * TODO Move this and previous function into output html class file (htmlline.class.php). |
||
4082 | * If lines are into a template, title must also be into a template |
||
4083 | * But for the moment we don't know if it's possible, so we keep the method available on overloaded objects. |
||
4084 | * |
||
4085 | * @param string $restrictlist ''=All lines, 'services'=Restrict to services only |
||
4086 | * @return void |
||
4087 | */ |
||
4088 | function printOriginLinesList($restrictlist='') |
||
4089 | { |
||
4090 | global $langs, $hookmanager, $conf; |
||
4091 | |||
4092 | print '<tr class="liste_titre">'; |
||
4093 | print '<td>'.$langs->trans('Ref').'</td>'; |
||
4094 | print '<td>'.$langs->trans('Description').'</td>'; |
||
4095 | print '<td align="right">'.$langs->trans('VATRate').'</td>'; |
||
4096 | print '<td align="right">'.$langs->trans('PriceUHT').'</td>'; |
||
4097 | if (!empty($conf->multicurrency->enabled)) print '<td align="right">'.$langs->trans('PriceUHTCurrency').'</td>'; |
||
4098 | print '<td align="right">'.$langs->trans('Qty').'</td>'; |
||
4099 | if($conf->global->PRODUCT_USE_UNITS) |
||
4100 | { |
||
4101 | print '<td align="left">'.$langs->trans('Unit').'</td>'; |
||
4102 | } |
||
4103 | print '<td align="right">'.$langs->trans('ReductionShort').'</td></tr>'; |
||
4104 | |||
4105 | $var = true; |
||
4106 | $i = 0; |
||
4107 | |||
4108 | if (! empty($this->lines)) |
||
4109 | { |
||
4110 | foreach ($this->lines as $line) |
||
4111 | { |
||
4112 | if (is_object($hookmanager) && (($line->product_type == 9 && ! empty($line->special_code)) || ! empty($line->fk_parent_line))) |
||
4113 | { |
||
4114 | if (empty($line->fk_parent_line)) |
||
4115 | { |
||
4116 | $parameters=array('line'=>$line,'var'=>$var,'i'=>$i); |
||
4117 | $action=''; |
||
4118 | $hookmanager->executeHooks('printOriginObjectLine',$parameters,$this,$action); // Note that $action and $object may have been modified by some hooks |
||
4119 | } |
||
4120 | } |
||
4121 | else |
||
4122 | { |
||
4123 | $this->printOriginLine($line, $var, $restrictlist); |
||
4124 | } |
||
4125 | |||
4126 | $i++; |
||
4127 | } |
||
4128 | } |
||
4129 | } |
||
4130 | |||
4131 | /** |
||
4132 | * Return HTML with a line of table array of source object lines |
||
4133 | * TODO Move this and previous function into output html class file (htmlline.class.php). |
||
4134 | * If lines are into a template, title must also be into a template |
||
4135 | * But for the moment we don't know if it's possible as we keep a method available on overloaded objects. |
||
4136 | * |
||
4137 | * @param CommonObjectLine $line Line |
||
4138 | * @param string $var Var |
||
4139 | * @param string $restrictlist ''=All lines, 'services'=Restrict to services only (strike line if not) |
||
4140 | * @return void |
||
4141 | */ |
||
4142 | function printOriginLine($line, $var, $restrictlist='') |
||
4143 | { |
||
4144 | global $langs, $conf; |
||
4145 | |||
4146 | //var_dump($line); |
||
4147 | if (!empty($line->date_start)) |
||
4148 | { |
||
4149 | $date_start=$line->date_start; |
||
4150 | } |
||
4151 | else |
||
4152 | { |
||
4153 | $date_start=$line->date_debut_prevue; |
||
4154 | if ($line->date_debut_reel) $date_start=$line->date_debut_reel; |
||
4155 | } |
||
4156 | if (!empty($line->date_end)) |
||
4157 | { |
||
4158 | $date_end=$line->date_end; |
||
4159 | } |
||
4160 | else |
||
4161 | { |
||
4162 | $date_end=$line->date_fin_prevue; |
||
4163 | if ($line->date_fin_reel) $date_end=$line->date_fin_reel; |
||
4164 | } |
||
4165 | |||
4166 | $this->tpl['label'] = ''; |
||
4167 | if (! empty($line->fk_parent_line)) $this->tpl['label'].= img_picto('', 'rightarrow'); |
||
4168 | |||
4169 | if (($line->info_bits & 2) == 2) // TODO Not sure this is used for source object |
||
4170 | { |
||
4171 | $discount=new DiscountAbsolute($this->db); |
||
4172 | $discount->fk_soc = $this->socid; |
||
4173 | $this->tpl['label'].= $discount->getNomUrl(0,'discount'); |
||
4174 | } |
||
4175 | else if (! empty($line->fk_product)) |
||
4176 | { |
||
4177 | $productstatic = new Product($this->db); |
||
4178 | $productstatic->id = $line->fk_product; |
||
4179 | $productstatic->ref = $line->ref; |
||
4180 | $productstatic->type = $line->fk_product_type; |
||
4181 | if(empty($productstatic->ref)){ |
||
4182 | $line->fetch_product(); |
||
4183 | $productstatic = $line->product; |
||
4184 | } |
||
4185 | |||
4186 | $this->tpl['label'].= $productstatic->getNomUrl(1); |
||
4187 | $this->tpl['label'].= ' - '.(! empty($line->label)?$line->label:$line->product_label); |
||
4188 | // Dates |
||
4189 | if ($line->product_type == 1 && ($date_start || $date_end)) |
||
4190 | { |
||
4191 | $this->tpl['label'].= get_date_range($date_start,$date_end); |
||
4192 | } |
||
4193 | } |
||
4194 | else |
||
4195 | { |
||
4196 | $this->tpl['label'].= ($line->product_type == -1 ? ' ' : ($line->product_type == 1 ? img_object($langs->trans(''),'service') : img_object($langs->trans(''),'product'))); |
||
4197 | if (!empty($line->desc)) { |
||
4198 | $this->tpl['label'].=$line->desc; |
||
4199 | }else { |
||
4200 | $this->tpl['label'].= ($line->label ? ' '.$line->label : ''); |
||
4201 | } |
||
4202 | |||
4203 | // Dates |
||
4204 | if ($line->product_type == 1 && ($date_start || $date_end)) |
||
4205 | { |
||
4206 | $this->tpl['label'].= get_date_range($date_start,$date_end); |
||
4207 | } |
||
4208 | } |
||
4209 | |||
4210 | if (! empty($line->desc)) |
||
4211 | { |
||
4212 | if ($line->desc == '(CREDIT_NOTE)') // TODO Not sure this is used for source object |
||
4213 | { |
||
4214 | $discount=new DiscountAbsolute($this->db); |
||
4215 | $discount->fetch($line->fk_remise_except); |
||
4216 | $this->tpl['description'] = $langs->transnoentities("DiscountFromCreditNote",$discount->getNomUrl(0)); |
||
4217 | } |
||
4218 | elseif ($line->desc == '(DEPOSIT)') // TODO Not sure this is used for source object |
||
4219 | { |
||
4220 | $discount=new DiscountAbsolute($this->db); |
||
4221 | $discount->fetch($line->fk_remise_except); |
||
4222 | $this->tpl['description'] = $langs->transnoentities("DiscountFromDeposit",$discount->getNomUrl(0)); |
||
4223 | } |
||
4224 | elseif ($line->desc == '(EXCESS RECEIVED)') |
||
4225 | { |
||
4226 | $discount=new DiscountAbsolute($this->db); |
||
4227 | $discount->fetch($line->fk_remise_except); |
||
4228 | $this->tpl['description'] = $langs->transnoentities("DiscountFromExcessReceived",$discount->getNomUrl(0)); |
||
4229 | } |
||
4230 | elseif ($line->desc == '(EXCESS PAID)') |
||
4231 | { |
||
4232 | $discount=new DiscountAbsolute($this->db); |
||
4233 | $discount->fetch($line->fk_remise_except); |
||
4234 | $this->tpl['description'] = $langs->transnoentities("DiscountFromExcessPaid",$discount->getNomUrl(0)); |
||
4235 | } |
||
4236 | else |
||
4237 | { |
||
4238 | $this->tpl['description'] = dol_trunc($line->desc,60); |
||
4239 | } |
||
4240 | } |
||
4241 | else |
||
4242 | { |
||
4243 | $this->tpl['description'] = ' '; |
||
4244 | } |
||
4245 | |||
4246 | // VAT Rate |
||
4247 | $this->tpl['vat_rate'] = vatrate($line->tva_tx, true); |
||
4248 | $this->tpl['vat_rate'] .= (($line->info_bits & 1) == 1) ? '*' : ''; |
||
4249 | if (! empty($line->vat_src_code) && ! preg_match('/\(/', $this->tpl['vat_rate'])) $this->tpl['vat_rate'].=' ('.$line->vat_src_code.')'; |
||
4250 | |||
4251 | $this->tpl['price'] = price($line->subprice); |
||
4252 | $this->tpl['multicurrency_price'] = price($line->multicurrency_subprice); |
||
4253 | $this->tpl['qty'] = (($line->info_bits & 2) != 2) ? $line->qty : ' '; |
||
4254 | if ($conf->global->PRODUCT_USE_UNITS) $this->tpl['unit'] = $langs->transnoentities($line->getLabelOfUnit('long')); |
||
4255 | $this->tpl['remise_percent'] = (($line->info_bits & 2) != 2) ? vatrate($line->remise_percent, true) : ' '; |
||
4256 | |||
4257 | // Is the line strike or not |
||
4258 | $this->tpl['strike']=0; |
||
4259 | if ($restrictlist == 'services' && $line->product_type != Product::TYPE_SERVICE) $this->tpl['strike']=1; |
||
4260 | |||
4261 | // Output template part (modules that overwrite templates must declare this into descriptor) |
||
4262 | // Use global variables + $dateSelector + $seller and $buyer |
||
4263 | $dirtpls=array_merge($conf->modules_parts['tpl'],array('/core/tpl')); |
||
4264 | foreach($dirtpls as $reldir) |
||
4265 | { |
||
4266 | $tpl = dol_buildpath($reldir.'/originproductline.tpl.php'); |
||
4267 | if (empty($conf->file->strict_mode)) { |
||
4268 | $res=@include $tpl; |
||
4269 | } else { |
||
4270 | $res=include $tpl; // for debug |
||
4271 | } |
||
4272 | if ($res) break; |
||
4273 | } |
||
4274 | } |
||
4275 | |||
4276 | |||
4277 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
4278 | /** |
||
4279 | * Add resources to the current object : add entry into llx_element_resources |
||
4280 | * Need $this->element & $this->id |
||
4281 | * |
||
4282 | * @param int $resource_id Resource id |
||
4283 | * @param string $resource_type 'resource' |
||
4284 | * @param int $busy Busy or not |
||
4285 | * @param int $mandatory Mandatory or not |
||
4286 | * @return int <=0 if KO, >0 if OK |
||
4287 | */ |
||
4288 | function add_element_resource($resource_id, $resource_type, $busy=0, $mandatory=0) |
||
4289 | { |
||
4290 | // phpcs:enable |
||
4291 | $this->db->begin(); |
||
4292 | |||
4293 | $sql = "INSERT INTO ".MAIN_DB_PREFIX."element_resources ("; |
||
4294 | $sql.= "resource_id"; |
||
4295 | $sql.= ", resource_type"; |
||
4296 | $sql.= ", element_id"; |
||
4297 | $sql.= ", element_type"; |
||
4298 | $sql.= ", busy"; |
||
4299 | $sql.= ", mandatory"; |
||
4300 | $sql.= ") VALUES ("; |
||
4301 | $sql.= $resource_id; |
||
4302 | $sql.= ", '".$this->db->escape($resource_type)."'"; |
||
4303 | $sql.= ", '".$this->db->escape($this->id)."'"; |
||
4304 | $sql.= ", '".$this->db->escape($this->element)."'"; |
||
4305 | $sql.= ", '".$this->db->escape($busy)."'"; |
||
4306 | $sql.= ", '".$this->db->escape($mandatory)."'"; |
||
4307 | $sql.= ")"; |
||
4308 | |||
4309 | dol_syslog(get_class($this)."::add_element_resource", LOG_DEBUG); |
||
4310 | if ($this->db->query($sql)) |
||
4311 | { |
||
4312 | $this->db->commit(); |
||
4313 | return 1; |
||
4314 | } |
||
4315 | else |
||
4316 | { |
||
4317 | $this->error=$this->db->lasterror(); |
||
4318 | $this->db->rollback(); |
||
4319 | return 0; |
||
4320 | } |
||
4321 | } |
||
4322 | |||
4323 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
4324 | /** |
||
4325 | * Delete a link to resource line |
||
4326 | * |
||
4327 | * @param int $rowid Id of resource line to delete |
||
4328 | * @param int $element element name (for trigger) TODO: use $this->element into commonobject class |
||
4329 | * @param int $notrigger Disable all triggers |
||
4330 | * @return int >0 if OK, <0 if KO |
||
4331 | */ |
||
4332 | function delete_resource($rowid, $element, $notrigger=0) |
||
4333 | { |
||
4334 | // phpcs:enable |
||
4335 | global $user; |
||
4336 | |||
4337 | $this->db->begin(); |
||
4338 | |||
4339 | $sql = "DELETE FROM ".MAIN_DB_PREFIX."element_resources"; |
||
4340 | $sql.= " WHERE rowid=".$rowid; |
||
4341 | |||
4342 | dol_syslog(get_class($this)."::delete_resource", LOG_DEBUG); |
||
4343 | |||
4344 | $resql=$this->db->query($sql); |
||
4345 | if (! $resql) |
||
4346 | { |
||
4347 | $this->error=$this->db->lasterror(); |
||
4348 | $this->db->rollback(); |
||
4349 | return -1; |
||
4350 | } |
||
4351 | else |
||
4352 | { |
||
4353 | if (! $notrigger) |
||
4354 | { |
||
4355 | $result=$this->call_trigger(strtoupper($element).'_DELETE_RESOURCE', $user); |
||
4356 | if ($result < 0) { $this->db->rollback(); return -1; } |
||
4357 | } |
||
4358 | $this->db->commit(); |
||
4359 | return 1; |
||
4360 | } |
||
4361 | } |
||
4362 | |||
4363 | |||
4364 | /** |
||
4365 | * Overwrite magic function to solve problem of cloning object that are kept as references |
||
4366 | * |
||
4367 | * @return void |
||
4368 | */ |
||
4369 | function __clone() |
||
4370 | { |
||
4371 | // Force a copy of this->lines, otherwise it will point to same object. |
||
4372 | if (isset($this->lines) && is_array($this->lines)) |
||
4373 | { |
||
4374 | $nboflines=count($this->lines); |
||
4375 | for($i=0; $i < $nboflines; $i++) |
||
4376 | { |
||
4377 | $this->lines[$i] = clone $this->lines[$i]; |
||
4378 | } |
||
4379 | } |
||
4380 | } |
||
4381 | |||
4382 | /** |
||
4383 | * Common function for all objects extending CommonObject for generating documents |
||
4384 | * |
||
4385 | * @param string $modelspath Relative folder where generators are placed |
||
4386 | * @param string $modele Generator to use. Caller must set it to obj->modelpdf or GETPOST('modelpdf') for example. |
||
4387 | * @param Translate $outputlangs Output language to use |
||
4388 | * @param int $hidedetails 1 to hide details. 0 by default |
||
4389 | * @param int $hidedesc 1 to hide product description. 0 by default |
||
4390 | * @param int $hideref 1 to hide product reference. 0 by default |
||
4391 | * @param null|array $moreparams Array to provide more information |
||
4392 | * @return int >0 if OK, <0 if KO |
||
4393 | * @see addFileIntoDatabaseIndex |
||
4394 | */ |
||
4395 | protected function commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null) |
||
4396 | { |
||
4397 | global $conf, $langs, $user; |
||
4398 | |||
4399 | $srctemplatepath=''; |
||
4400 | |||
4401 | // Increase limit for PDF build |
||
4402 | $err=error_reporting(); |
||
4403 | error_reporting(0); |
||
4404 | @set_time_limit(120); |
||
4405 | error_reporting($err); |
||
4406 | |||
4407 | // If selected model is a filename template (then $modele="modelname" or "modelname:filename") |
||
4408 | $tmp=explode(':',$modele,2); |
||
4409 | if (! empty($tmp[1])) |
||
4410 | { |
||
4411 | $modele=$tmp[0]; |
||
4412 | $srctemplatepath=$tmp[1]; |
||
4413 | } |
||
4414 | |||
4415 | // Search template files |
||
4416 | $file=''; $classname=''; $filefound=0; |
||
4417 | $dirmodels=array('/'); |
||
4418 | if (is_array($conf->modules_parts['models'])) $dirmodels=array_merge($dirmodels,$conf->modules_parts['models']); |
||
4419 | foreach($dirmodels as $reldir) |
||
4420 | { |
||
4421 | foreach(array('doc','pdf') as $prefix) |
||
4422 | { |
||
4423 | if (in_array(get_class($this), array('Adherent'))) $file = $prefix."_".$modele.".class.php"; // Member module use prefix_module.class.php |
||
4424 | else $file = $prefix."_".$modele.".modules.php"; |
||
4425 | |||
4426 | // On verifie l'emplacement du modele |
||
4427 | $file=dol_buildpath($reldir.$modelspath.$file,0); |
||
4428 | if (file_exists($file)) |
||
4429 | { |
||
4430 | $filefound=1; |
||
4431 | $classname=$prefix.'_'.$modele; |
||
4432 | break; |
||
4433 | } |
||
4434 | } |
||
4435 | if ($filefound) break; |
||
4436 | } |
||
4437 | |||
4438 | // If generator was found |
||
4439 | if ($filefound) |
||
4440 | { |
||
4441 | global $db; // Required to solve a conception default in commonstickergenerator.class.php making an include of code using $db |
||
4442 | |||
4443 | require_once $file; |
||
4444 | |||
4445 | $obj = new $classname($this->db); |
||
4446 | |||
4447 | // If generator is ODT, we must have srctemplatepath defined, if not we set it. |
||
4448 | if ($obj->type == 'odt' && empty($srctemplatepath)) |
||
4449 | { |
||
4450 | $varfortemplatedir=$obj->scandir; |
||
4451 | if ($varfortemplatedir && ! empty($conf->global->$varfortemplatedir)) |
||
4452 | { |
||
4453 | $dirtoscan=$conf->global->$varfortemplatedir; |
||
4454 | |||
4455 | $listoffiles=array(); |
||
4456 | |||
4457 | // Now we add first model found in directories scanned |
||
4458 | $listofdir=explode(',',$dirtoscan); |
||
4459 | foreach($listofdir as $key => $tmpdir) |
||
4460 | { |
||
4461 | $tmpdir=trim($tmpdir); |
||
4462 | $tmpdir=preg_replace('/DOL_DATA_ROOT/',DOL_DATA_ROOT,$tmpdir); |
||
4463 | if (! $tmpdir) { unset($listofdir[$key]); continue; } |
||
4464 | if (is_dir($tmpdir)) |
||
4465 | { |
||
4466 | $tmpfiles=dol_dir_list($tmpdir,'files',0,'\.od(s|t)$','','name',SORT_ASC,0); |
||
4467 | if (count($tmpfiles)) $listoffiles=array_merge($listoffiles,$tmpfiles); |
||
4468 | } |
||
4469 | } |
||
4470 | |||
4471 | if (count($listoffiles)) |
||
4472 | { |
||
4473 | foreach($listoffiles as $record) |
||
4474 | { |
||
4475 | $srctemplatepath=$record['fullname']; |
||
4476 | break; |
||
4477 | } |
||
4478 | } |
||
4479 | } |
||
4480 | |||
4481 | if (empty($srctemplatepath)) |
||
4482 | { |
||
4483 | $this->error='ErrorGenerationAskedForOdtTemplateWithSrcFileNotDefined'; |
||
4484 | return -1; |
||
4485 | } |
||
4486 | } |
||
4487 | |||
4488 | if ($obj->type == 'odt' && ! empty($srctemplatepath)) |
||
4489 | { |
||
4490 | if (! dol_is_file($srctemplatepath)) |
||
4491 | { |
||
4492 | $this->error='ErrorGenerationAskedForOdtTemplateWithSrcFileNotFound'; |
||
4493 | return -1; |
||
4494 | } |
||
4495 | } |
||
4496 | |||
4497 | // We save charset_output to restore it because write_file can change it if needed for |
||
4498 | // output format that does not support UTF8. |
||
4499 | $sav_charset_output=$outputlangs->charset_output; |
||
4500 | |||
4501 | if (in_array(get_class($this), array('Adherent'))) |
||
4502 | { |
||
4503 | $arrayofrecords = array(); // The write_file of templates of adherent class need this var |
||
4504 | $resultwritefile = $obj->write_file($this, $outputlangs, $srctemplatepath, 'member', 1, $moreparams); |
||
4505 | } |
||
4506 | else |
||
4507 | { |
||
4508 | $resultwritefile = $obj->write_file($this, $outputlangs, $srctemplatepath, $hidedetails, $hidedesc, $hideref, $moreparams); |
||
4509 | } |
||
4510 | // After call of write_file $obj->result['fullpath'] is set with generated file. It will be used to update the ECM database index. |
||
4511 | |||
4512 | if ($resultwritefile > 0) |
||
4513 | { |
||
4514 | $outputlangs->charset_output=$sav_charset_output; |
||
4515 | |||
4516 | // We delete old preview |
||
4517 | require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; |
||
4518 | dol_delete_preview($this); |
||
4519 | |||
4520 | // Index file in database |
||
4521 | if (! empty($obj->result['fullpath'])) |
||
4522 | { |
||
4523 | $destfull = $obj->result['fullpath']; |
||
4524 | $upload_dir = dirname($destfull); |
||
4525 | $destfile = basename($destfull); |
||
4526 | $rel_dir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $upload_dir); |
||
4527 | |||
4528 | if (! preg_match('/[\\/]temp[\\/]|[\\/]thumbs|\.meta$/', $rel_dir)) // If not a tmp dir |
||
4529 | { |
||
4530 | $filename = basename($destfile); |
||
4531 | $rel_dir = preg_replace('/[\\/]$/', '', $rel_dir); |
||
4532 | $rel_dir = preg_replace('/^[\\/]/', '', $rel_dir); |
||
4533 | |||
4534 | include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php'; |
||
4535 | $ecmfile=new EcmFiles($this->db); |
||
4536 | $result = $ecmfile->fetch(0, '', ($rel_dir?$rel_dir.'/':'').$filename); |
||
4537 | |||
4538 | // Set the public "share" key |
||
4539 | $setsharekey = false; |
||
4540 | if ($this->element == 'propal') |
||
4541 | { |
||
4542 | $useonlinesignature = $conf->global->MAIN_FEATURES_LEVEL; // Replace this with 1 when feature to make online signature is ok |
||
4543 | if ($useonlinesignature) $setsharekey=true; |
||
4544 | if (! empty($conf->global->PROPOSAL_ALLOW_EXTERNAL_DOWNLOAD)) $setsharekey=true; |
||
4545 | } |
||
4546 | if ($this->element == 'commande' && ! empty($conf->global->ORDER_ALLOW_EXTERNAL_DOWNLOAD)) $setsharekey=true; |
||
4547 | if ($this->element == 'facture' && ! empty($conf->global->INVOICE_ALLOW_EXTERNAL_DOWNLOAD)) $setsharekey=true; |
||
4548 | if ($this->element == 'bank_account' && ! empty($conf->global->BANK_ACCOUNT_ALLOW_EXTERNAL_DOWNLOAD)) $setsharekey=true; |
||
4549 | |||
4550 | if ($setsharekey) |
||
4551 | { |
||
4552 | if (empty($ecmfile->share)) // Because object not found or share not set yet |
||
4553 | { |
||
4554 | require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; |
||
4555 | $ecmfile->share = getRandomPassword(true); |
||
4556 | } |
||
4557 | } |
||
4558 | |||
4559 | if ($result > 0) |
||
4560 | { |
||
4561 | $ecmfile->label = md5_file(dol_osencode($destfull)); // hash of file content |
||
4562 | $ecmfile->fullpath_orig = ''; |
||
4563 | $ecmfile->gen_or_uploaded = 'generated'; |
||
4564 | $ecmfile->description = ''; // indexed content |
||
4565 | $ecmfile->keyword = ''; // keyword content |
||
4566 | $result = $ecmfile->update($user); |
||
4567 | if ($result < 0) |
||
4568 | { |
||
4569 | setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings'); |
||
4570 | } |
||
4571 | } |
||
4572 | else |
||
4573 | { |
||
4574 | $ecmfile->entity = $conf->entity; |
||
4575 | $ecmfile->filepath = $rel_dir; |
||
4576 | $ecmfile->filename = $filename; |
||
4577 | $ecmfile->label = md5_file(dol_osencode($destfull)); // hash of file content |
||
4578 | $ecmfile->fullpath_orig = ''; |
||
4579 | $ecmfile->gen_or_uploaded = 'generated'; |
||
4580 | $ecmfile->description = ''; // indexed content |
||
4581 | $ecmfile->keyword = ''; // keyword content |
||
4582 | $ecmfile->src_object_type = $this->table_element; |
||
4583 | $ecmfile->src_object_id = $this->id; |
||
4584 | |||
4585 | $result = $ecmfile->create($user); |
||
4586 | if ($result < 0) |
||
4587 | { |
||
4588 | setEventMessages($ecmfile->error, $ecmfile->errors, 'warnings'); |
||
4589 | } |
||
4590 | } |
||
4591 | |||
4592 | /*$this->result['fullname']=$destfull; |
||
4593 | $this->result['filepath']=$ecmfile->filepath; |
||
4594 | $this->result['filename']=$ecmfile->filename;*/ |
||
4595 | //var_dump($obj->update_main_doc_field);exit; |
||
4596 | |||
4597 | // Update the last_main_doc field into main object (if documenent generator has property ->update_main_doc_field set) |
||
4598 | $update_main_doc_field=0; |
||
4599 | if (! empty($obj->update_main_doc_field)) $update_main_doc_field=1; |
||
4600 | if ($update_main_doc_field && ! empty($this->table_element)) |
||
4601 | { |
||
4602 | $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element." SET last_main_doc = '".($ecmfile->filepath.'/'.$ecmfile->filename)."'"; |
||
4603 | $sql.= ' WHERE rowid = '.$this->id; |
||
4604 | $resql = $this->db->query($sql); |
||
4605 | if (! $resql) dol_print_error($this->db); |
||
4606 | } |
||
4607 | } |
||
4608 | } |
||
4609 | else |
||
4610 | { |
||
4611 | dol_syslog('Method ->write_file was called on object '.get_class($obj).' and return a success but the return array ->result["fullpath"] was not set.', LOG_WARNING); |
||
4612 | } |
||
4613 | |||
4614 | // Success in building document. We build meta file. |
||
4615 | dol_meta_create($this); |
||
4616 | |||
4617 | return 1; |
||
4618 | } |
||
4619 | else |
||
4620 | { |
||
4621 | $outputlangs->charset_output=$sav_charset_output; |
||
4622 | dol_print_error($this->db, "Error generating document for ".__CLASS__.". Error: ".$obj->error, $obj->errors); |
||
4623 | return -1; |
||
4624 | } |
||
4625 | } |
||
4626 | else |
||
4627 | { |
||
4628 | $this->error=$langs->trans("Error")." ".$langs->trans("ErrorFileDoesNotExists",$file); |
||
4629 | dol_print_error('',$this->error); |
||
4630 | return -1; |
||
4631 | } |
||
4632 | } |
||
4633 | |||
4634 | /** |
||
4635 | * Build thumb |
||
4636 | * @TODO Move this into files.lib.php |
||
4637 | * |
||
4638 | * @param string $file Path file in UTF8 to original file to create thumbs from. |
||
4639 | * @return void |
||
4640 | */ |
||
4641 | function addThumbs($file) |
||
4642 | { |
||
4643 | global $maxwidthsmall, $maxheightsmall, $maxwidthmini, $maxheightmini, $quality; |
||
4644 | |||
4645 | require_once DOL_DOCUMENT_ROOT .'/core/lib/images.lib.php'; // This define also $maxwidthsmall, $quality, ... |
||
4646 | |||
4647 | $file_osencoded=dol_osencode($file); |
||
4648 | if (file_exists($file_osencoded)) |
||
4649 | { |
||
4650 | // Create small thumbs for company (Ratio is near 16/9) |
||
4651 | // Used on logon for example |
||
4652 | vignette($file_osencoded, $maxwidthsmall, $maxheightsmall, '_small', $quality); |
||
4653 | |||
4654 | // Create mini thumbs for company (Ratio is near 16/9) |
||
4655 | // Used on menu or for setup page for example |
||
4656 | vignette($file_osencoded, $maxwidthmini, $maxheightmini, '_mini', $quality); |
||
4657 | } |
||
4658 | } |
||
4659 | |||
4660 | |||
4661 | /* Functions common to commonobject and commonobjectline */ |
||
4662 | |||
4663 | /* For default values */ |
||
4664 | |||
4665 | /** |
||
4666 | * Return the default value to use for a field when showing the create form of object. |
||
4667 | * Return values in this order: |
||
4668 | * 1) If parameter is available into POST, we return it first. |
||
4669 | * 2) If not but an alternate value was provided as parameter of function, we return it. |
||
4670 | * 3) If not but a constant $conf->global->OBJECTELEMENT_FIELDNAME is set, we return it (It is better to use the dedicated table). |
||
4671 | * 4) Return value found into database (TODO No yet implemented) |
||
4672 | * |
||
4673 | * @param string $fieldname Name of field |
||
4674 | * @param string $alternatevalue Alternate value to use |
||
4675 | * @return string|string[] Default value (can be an array if the GETPOST return an array) |
||
4676 | **/ |
||
4677 | function getDefaultCreateValueFor($fieldname, $alternatevalue=null) |
||
4678 | { |
||
4679 | global $conf, $_POST; |
||
4680 | |||
4681 | // If param here has been posted, we use this value first. |
||
4682 | if (isset($_POST[$fieldname])) return GETPOST($fieldname, 2); |
||
4683 | |||
4684 | if (isset($alternatevalue)) return $alternatevalue; |
||
4685 | |||
4686 | $newelement=$this->element; |
||
4687 | if ($newelement == 'facture') $newelement='invoice'; |
||
4688 | if ($newelement == 'commande') $newelement='order'; |
||
4689 | if (empty($newelement)) |
||
4690 | { |
||
4691 | dol_syslog("Ask a default value using common method getDefaultCreateValueForField on an object with no property ->element defined. Return empty string.", LOG_WARNING); |
||
4692 | return ''; |
||
4693 | } |
||
4694 | |||
4695 | $keyforfieldname=strtoupper($newelement.'_DEFAULT_'.$fieldname); |
||
4696 | //var_dump($keyforfieldname); |
||
4697 | if (isset($conf->global->$keyforfieldname)) return $conf->global->$keyforfieldname; |
||
4698 | |||
4699 | // TODO Ad here a scan into table llx_overwrite_default with a filter on $this->element and $fieldname |
||
4700 | } |
||
4701 | |||
4702 | |||
4703 | /* For triggers */ |
||
4704 | |||
4705 | |||
4706 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
4707 | /** |
||
4708 | * Call trigger based on this instance. |
||
4709 | * Some context information may also be provided into array property this->context. |
||
4710 | * NB: Error from trigger are stacked in interface->errors |
||
4711 | * NB2: If return code of triggers are < 0, action calling trigger should cancel all transaction. |
||
4712 | * |
||
4713 | * @param string $trigger_name trigger's name to execute |
||
4714 | * @param User $user Object user |
||
4715 | * @return int Result of run_triggers |
||
4716 | */ |
||
4717 | function call_trigger($trigger_name, $user) |
||
4718 | { |
||
4719 | // phpcs:enable |
||
4720 | global $langs,$conf; |
||
4721 | |||
4722 | include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php'; |
||
4723 | $interface=new Interfaces($this->db); |
||
4724 | $result=$interface->run_triggers($trigger_name,$this,$user,$langs,$conf); |
||
4725 | |||
4726 | if ($result < 0) |
||
4727 | { |
||
4728 | if (!empty($this->errors)) |
||
4729 | { |
||
4730 | $this->errors=array_unique(array_merge($this->errors,$interface->errors)); // We use array_unique because when a trigger call another trigger on same object, this->errors is added twice. |
||
4731 | } |
||
4732 | else |
||
4733 | { |
||
4734 | $this->errors=$interface->errors; |
||
4735 | } |
||
4736 | } |
||
4737 | return $result; |
||
4738 | } |
||
4739 | |||
4740 | |||
4741 | /* Functions for extrafields */ |
||
4742 | |||
4743 | |||
4744 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
4745 | /** |
||
4746 | * Function to get extra fields of an object into $this->array_options |
||
4747 | * This method is in most cases called by method fetch of objects but you can call it separately. |
||
4748 | * |
||
4749 | * @param int $rowid Id of line. Use the id of object if not defined. Deprecated. Function must be called without parameters. |
||
4750 | * @param array $optionsArray Array resulting of call of extrafields->fetch_name_optionals_label(). Deprecated. Function must be called without parameters. |
||
4751 | * @return int <0 if error, 0 if no values of extrafield to find nor found, 1 if an attribute is found and value loaded |
||
4752 | */ |
||
4753 | function fetch_optionals($rowid=null, $optionsArray=null) |
||
4754 | { |
||
4755 | // phpcs:enable |
||
4756 | if (empty($rowid)) $rowid=$this->id; |
||
4757 | |||
4758 | // To avoid SQL errors. Probably not the better solution though |
||
4759 | if (!$this->table_element) { |
||
4760 | return 0; |
||
4761 | } |
||
4762 | |||
4763 | $this->array_options=array(); |
||
4764 | |||
4765 | if (! is_array($optionsArray)) |
||
4766 | { |
||
4767 | // If $extrafields is not a known object, we initialize it. Best practice is to have $extrafields defined into card.php or list.php page. |
||
4768 | // TODO Use of existing $extrafield is not yet ready (must mutualize code that use extrafields in form first) |
||
4769 | // global $extrafields; |
||
4770 | //if (! is_object($extrafields)) |
||
4771 | //{ |
||
4772 | // require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; |
||
4773 | $extrafields = new ExtraFields(); |
||
4774 | //} |
||
4775 | |||
4776 | // Load array of extrafields for elementype = $this->table_element |
||
4777 | if (empty($extrafields->attributes[$this->table_element]['loaded'])) |
||
4778 | { |
||
4779 | $extrafields->fetch_name_optionals_label($this->table_element); |
||
4780 | } |
||
4781 | $optionsArray = (! empty($extrafields->attributes[$this->table_element]['label'])?$extrafields->attributes[$this->table_element]['label']:null); |
||
4782 | } |
||
4783 | else |
||
4784 | { |
||
4785 | global $extrafields; |
||
4786 | dol_syslog("Warning: fetch_optionals was called with param optionsArray defined when you should pass null now", LOG_WARNING); |
||
4787 | } |
||
4788 | |||
4789 | $table_element = $this->table_element; |
||
4790 | if ($table_element == 'categorie') $table_element = 'categories'; // For compatibility |
||
4791 | |||
4792 | // Request to get complementary values |
||
4793 | if (is_array($optionsArray) && count($optionsArray) > 0) |
||
4794 | { |
||
4795 | $sql = "SELECT rowid"; |
||
4796 | foreach ($optionsArray as $name => $label) |
||
4797 | { |
||
4798 | if (empty($extrafields->attributes[$this->table_element]['type'][$name]) || $extrafields->attributes[$this->table_element]['type'][$name] != 'separate') |
||
4799 | { |
||
4800 | $sql.= ", ".$name; |
||
4801 | } |
||
4802 | } |
||
4803 | $sql.= " FROM ".MAIN_DB_PREFIX.$table_element."_extrafields"; |
||
4804 | $sql.= " WHERE fk_object = ".$rowid; |
||
4805 | |||
4806 | //dol_syslog(get_class($this)."::fetch_optionals get extrafields data for ".$this->table_element, LOG_DEBUG); // Too verbose |
||
4807 | $resql=$this->db->query($sql); |
||
4808 | if ($resql) |
||
4809 | { |
||
4810 | $this->array_options = array(); |
||
4811 | $numrows=$this->db->num_rows($resql); |
||
4812 | if ($numrows) |
||
4813 | { |
||
4814 | $tab = $this->db->fetch_array($resql); |
||
4815 | |||
4816 | foreach ($tab as $key => $value) |
||
4817 | { |
||
4818 | // Test fetch_array ! is_int($key) because fetch_array result is a mix table with Key as alpha and Key as int (depend db engine) |
||
4819 | if ($key != 'rowid' && $key != 'tms' && $key != 'fk_member' && ! is_int($key)) |
||
4820 | { |
||
4821 | // we can add this attribute to object |
||
4822 | if (! empty($extrafields) && in_array($extrafields->attributes[$this->table_element]['type'][$key], array('date','datetime'))) |
||
4823 | { |
||
4824 | //var_dump($extrafields->attributes[$this->table_element]['type'][$key]); |
||
4825 | $this->array_options["options_".$key]=$this->db->jdate($value); |
||
4826 | } |
||
4827 | else |
||
4828 | { |
||
4829 | $this->array_options["options_".$key]=$value; |
||
4830 | } |
||
4831 | |||
4832 | //var_dump('key '.$key.' '.$value.' type='.$extrafields->attributes[$this->table_element]['type'][$key].' '.$this->array_options["options_".$key]); |
||
4833 | } |
||
4834 | } |
||
4835 | } |
||
4836 | |||
4837 | $this->db->free($resql); |
||
4838 | |||
4839 | if ($numrows) return $numrows; |
||
4840 | else return 0; |
||
4841 | } |
||
4842 | else |
||
4843 | { |
||
4844 | dol_print_error($this->db); |
||
4845 | return -1; |
||
4846 | } |
||
4847 | } |
||
4848 | return 0; |
||
4849 | } |
||
4850 | |||
4851 | /** |
||
4852 | * Delete all extra fields values for the current object. |
||
4853 | * |
||
4854 | * @return int <0 if KO, >0 if OK |
||
4855 | */ |
||
4856 | function deleteExtraFields() |
||
4857 | { |
||
4858 | $this->db->begin(); |
||
4859 | |||
4860 | $table_element = $this->table_element; |
||
4861 | if ($table_element == 'categorie') $table_element = 'categories'; // For compatibility |
||
4862 | |||
4863 | $sql_del = "DELETE FROM ".MAIN_DB_PREFIX.$table_element."_extrafields WHERE fk_object = ".$this->id; |
||
4864 | dol_syslog(get_class($this)."::deleteExtraFields delete", LOG_DEBUG); |
||
4865 | $resql=$this->db->query($sql_del); |
||
4866 | if (! $resql) |
||
4867 | { |
||
4868 | $this->error=$this->db->lasterror(); |
||
4869 | $this->db->rollback(); |
||
4870 | return -1; |
||
4871 | } |
||
4872 | else |
||
4873 | { |
||
4874 | $this->db->commit(); |
||
4875 | return 1; |
||
4876 | } |
||
4877 | } |
||
4878 | |||
4879 | /** |
||
4880 | * Add/Update all extra fields values for the current object. |
||
4881 | * Data to describe values to insert/update are stored into $this->array_options=array('options_codeforfield1'=>'valueforfield1', 'options_codeforfield2'=>'valueforfield2', ...) |
||
4882 | * This function delete record with all extrafields and insert them again from the array $this->array_options. |
||
4883 | * |
||
4884 | * @param string $trigger If defined, call also the trigger (for example COMPANY_MODIFY) |
||
4885 | * @param User $userused Object user |
||
4886 | * @return int -1=error, O=did nothing, 1=OK |
||
4887 | * @see updateExtraField, setValueFrom |
||
4888 | */ |
||
4889 | function insertExtraFields($trigger='', $userused=null) |
||
4890 | { |
||
4891 | global $conf,$langs,$user; |
||
4892 | |||
4893 | if (empty($userused)) $userused=$user; |
||
4894 | |||
4895 | $error=0; |
||
4896 | |||
4897 | if (! empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) return 0; // For avoid conflicts if trigger used |
||
4898 | |||
4899 | if (! empty($this->array_options)) |
||
4900 | { |
||
4901 | // Check parameters |
||
4902 | $langs->load('admin'); |
||
4903 | require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; |
||
4904 | $extrafields = new ExtraFields($this->db); |
||
4905 | $target_extrafields=$extrafields->fetch_name_optionals_label($this->table_element); |
||
4906 | |||
4907 | //Eliminate copied source object extra_fields that do not exist in target object |
||
4908 | $new_array_options=array(); |
||
4909 | foreach ($this->array_options as $key => $value) { |
||
4910 | if (in_array(substr($key,8), array_keys($target_extrafields))) // We remove the 'options_' from $key for test |
||
4911 | $new_array_options[$key] = $value; |
||
4912 | elseif (in_array($key, array_keys($target_extrafields))) // We test on $key that does not contains the 'options_' prefix |
||
4913 | $new_array_options['options_'.$key] = $value; |
||
4914 | } |
||
4915 | |||
4916 | foreach($new_array_options as $key => $value) |
||
4917 | { |
||
4918 | $attributeKey = substr($key,8); // Remove 'options_' prefix |
||
4919 | $attributeType = $extrafields->attributes[$this->table_element]['type'][$attributeKey]; |
||
4920 | $attributeLabel = $extrafields->attributes[$this->table_element]['label'][$attributeKey]; |
||
4921 | $attributeParam = $extrafields->attributes[$this->table_element]['param'][$attributeKey]; |
||
4922 | $attributeRequired = $extrafields->attributes[$this->table_element]['required'][$attributeKey]; |
||
4923 | |||
4924 | if ($attributeRequired) |
||
4925 | { |
||
4926 | $mandatorypb=false; |
||
4927 | if ($attributeType == 'link' && $this->array_options[$key] == '-1') $mandatorypb=true; |
||
4928 | if ($this->array_options[$key] === '') $mandatorypb=true; |
||
4929 | if ($mandatorypb) |
||
4930 | { |
||
4931 | dol_syslog($this->error); |
||
4932 | $this->errors[]=$langs->trans('ErrorFieldRequired', $attributeLabel); |
||
4933 | return -1; |
||
4934 | } |
||
4935 | } |
||
4936 | |||
4937 | //dol_syslog("attributeLabel=".$attributeLabel, LOG_DEBUG); |
||
4938 | //dol_syslog("attributeType=".$attributeType, LOG_DEBUG); |
||
4939 | |||
4940 | switch ($attributeType) |
||
4941 | { |
||
4942 | case 'int': |
||
4943 | if (!is_numeric($value) && $value!='') |
||
4944 | { |
||
4945 | $this->errors[]=$langs->trans("ExtraFieldHasWrongValue", $attributeLabel); |
||
4946 | return -1; |
||
4947 | } |
||
4948 | elseif ($value=='') |
||
4949 | { |
||
4950 | $new_array_options[$key] = null; |
||
4951 | } |
||
4952 | break; |
||
4953 | case 'double': |
||
4954 | $value = price2num($value); |
||
4955 | if (!is_numeric($value) && $value!='') |
||
4956 | { |
||
4957 | dol_syslog($langs->trans("ExtraFieldHasWrongValue")." sur ".$attributeLabel."(".$value."is not '".$attributeType."')", LOG_DEBUG); |
||
4958 | $this->errors[]=$langs->trans("ExtraFieldHasWrongValue", $attributeLabel); |
||
4959 | return -1; |
||
4960 | } |
||
4961 | elseif ($value=='') |
||
4962 | { |
||
4963 | $new_array_options[$key] = null; |
||
4964 | } |
||
4965 | //dol_syslog("double value"." sur ".$attributeLabel."(".$value." is '".$attributeType."')", LOG_DEBUG); |
||
4966 | $new_array_options[$key] = $value; |
||
4967 | break; |
||
4968 | /*case 'select': // Not required, we chosed value='0' for undefined values |
||
4969 | if ($value=='-1') |
||
4970 | { |
||
4971 | $this->array_options[$key] = null; |
||
4972 | } |
||
4973 | break;*/ |
||
4974 | case 'password': |
||
4975 | $algo=''; |
||
4976 | if ($this->array_options[$key] != '' && is_array($extrafields->attributes[$this->table_element]['param'][$attributeKey]['options'])) |
||
4977 | { |
||
4978 | // If there is an encryption choice, we use it to crypt data before insert |
||
4979 | $tmparrays = array_keys($extrafields->attributes[$this->table_element]['param'][$attributeKey]['options']); |
||
4980 | $algo=reset($tmparrays); |
||
4981 | if ($algo != '') |
||
4982 | { |
||
4983 | //global $action; // $action may be 'create', 'update', 'update_extras'... |
||
4984 | //var_dump($action); |
||
4985 | //var_dump($this->oldcopy);exit; |
||
4986 | if (is_object($this->oldcopy)) // If this->oldcopy is not defined, we can't know if we change attribute or not, so we must keep value |
||
4987 | { |
||
4988 | //var_dump($this->oldcopy->array_options[$key]); var_dump($this->array_options[$key]); |
||
4989 | if ($this->array_options[$key] == $this->oldcopy->array_options[$key]) // If old value crypted in database is same than submited new value, it means we don't change it, so we don't update. |
||
4990 | { |
||
4991 | $new_array_options[$key] = $this->array_options[$key]; // Value is kept |
||
4992 | } |
||
4993 | else |
||
4994 | { |
||
4995 | // var_dump($algo); |
||
4996 | $newvalue = dol_hash($this->array_options[$key], $algo); |
||
4997 | $new_array_options[$key] = $newvalue; |
||
4998 | } |
||
4999 | } |
||
5000 | else |
||
5001 | { |
||
5002 | $new_array_options[$key] = $this->array_options[$key]; // Value is kept |
||
5003 | } |
||
5004 | } |
||
5005 | } |
||
5006 | else // Common usage |
||
5007 | { |
||
5008 | $new_array_options[$key] = $this->array_options[$key]; |
||
5009 | } |
||
5010 | break; |
||
5011 | case 'price': |
||
5012 | $new_array_options[$key] = price2num($this->array_options[$key]); |
||
5013 | break; |
||
5014 | case 'date': |
||
5015 | $new_array_options[$key] = $this->db->idate($this->array_options[$key]); |
||
5016 | break; |
||
5017 | case 'datetime': |
||
5018 | // If data is a string instead of a timestamp, we convert it |
||
5019 | if (! is_int($this->array_options[$key])) { |
||
5020 | $this->array_options[$key] = strtotime($this->array_options[$key]); |
||
5021 | } |
||
5022 | $new_array_options[$key] = $this->db->idate($this->array_options[$key]); |
||
5023 | break; |
||
5024 | case 'link': |
||
5025 | $param_list=array_keys($attributeParam['options']); |
||
5026 | // 0 : ObjectName |
||
5027 | // 1 : classPath |
||
5028 | $InfoFieldList = explode(":", $param_list[0]); |
||
5029 | dol_include_once($InfoFieldList[1]); |
||
5030 | if ($InfoFieldList[0] && class_exists($InfoFieldList[0])) |
||
5031 | { |
||
5032 | if ($value == '-1') // -1 is key for no defined in combo list of objects |
||
5033 | { |
||
5034 | $new_array_options[$key]=''; |
||
5035 | } |
||
5036 | elseif ($value) |
||
5037 | { |
||
5038 | $object = new $InfoFieldList[0]($this->db); |
||
5039 | if (is_numeric($value)) $res=$object->fetch($value); |
||
5040 | else $res=$object->fetch('',$value); |
||
5041 | |||
5042 | if ($res > 0) $new_array_options[$key]=$object->id; |
||
5043 | else |
||
5044 | { |
||
5045 | $this->error="Id/Ref '".$value."' for object '".$object->element."' not found"; |
||
5046 | $this->db->rollback(); |
||
5047 | return -1; |
||
5048 | } |
||
5049 | } |
||
5050 | } |
||
5051 | else |
||
5052 | { |
||
5053 | dol_syslog('Error bad setup of extrafield', LOG_WARNING); |
||
5054 | } |
||
5055 | break; |
||
5056 | } |
||
5057 | } |
||
5058 | |||
5059 | $this->db->begin(); |
||
5060 | |||
5061 | $table_element = $this->table_element; |
||
5062 | if ($table_element == 'categorie') $table_element = 'categories'; // For compatibility |
||
5063 | |||
5064 | $sql_del = "DELETE FROM ".MAIN_DB_PREFIX.$table_element."_extrafields WHERE fk_object = ".$this->id; |
||
5065 | dol_syslog(get_class($this)."::insertExtraFields delete", LOG_DEBUG); |
||
5066 | $this->db->query($sql_del); |
||
5067 | |||
5068 | $sql = "INSERT INTO ".MAIN_DB_PREFIX.$table_element."_extrafields (fk_object"; |
||
5069 | foreach($new_array_options as $key => $value) |
||
5070 | { |
||
5071 | $attributeKey = substr($key,8); // Remove 'options_' prefix |
||
5072 | // Add field of attribut |
||
5073 | if ($extrafields->attributes[$this->table_element]['type'][$attributeKey] != 'separate') // Only for other type than separator |
||
5074 | $sql.=",".$attributeKey; |
||
5075 | } |
||
5076 | $sql .= ") VALUES (".$this->id; |
||
5077 | |||
5078 | foreach($new_array_options as $key => $value) |
||
5079 | { |
||
5080 | $attributeKey = substr($key,8); // Remove 'options_' prefix |
||
5081 | // Add field of attribute |
||
5082 | if ($extrafields->attributes[$this->table_element]['type'][$attributeKey] != 'separate') // Only for other type than separator) |
||
5083 | { |
||
5084 | if ($new_array_options[$key] != '') |
||
5085 | { |
||
5086 | $sql.=",'".$this->db->escape($new_array_options[$key])."'"; |
||
5087 | } |
||
5088 | else |
||
5089 | { |
||
5090 | $sql.=",null"; |
||
5091 | } |
||
5092 | } |
||
5093 | } |
||
5094 | $sql.=")"; |
||
5095 | |||
5096 | dol_syslog(get_class($this)."::insertExtraFields insert", LOG_DEBUG); |
||
5097 | $resql = $this->db->query($sql); |
||
5098 | if (! $resql) |
||
5099 | { |
||
5100 | $this->error=$this->db->lasterror(); |
||
5101 | $error++; |
||
5102 | } |
||
5103 | |||
5104 | if (! $error && $trigger) |
||
5105 | { |
||
5106 | // Call trigger |
||
5107 | $this->context=array('extrafieldaddupdate'=>1); |
||
5108 | $result=$this->call_trigger($trigger, $userused); |
||
5109 | if ($result < 0) $error++; |
||
5110 | // End call trigger |
||
5111 | } |
||
5112 | |||
5113 | if ($error) |
||
5114 | { |
||
5115 | $this->db->rollback(); |
||
5116 | return -1; |
||
5117 | } |
||
5118 | else |
||
5119 | { |
||
5120 | $this->db->commit(); |
||
5121 | return 1; |
||
5122 | } |
||
5123 | } |
||
5124 | else return 0; |
||
5125 | } |
||
5126 | |||
5127 | /** |
||
5128 | * Update an extra field value for the current object. |
||
5129 | * Data to describe values to update are stored into $this->array_options=array('options_codeforfield1'=>'valueforfield1', 'options_codeforfield2'=>'valueforfield2', ...) |
||
5130 | * |
||
5131 | * @param string $key Key of the extrafield (without starting 'options_') |
||
5132 | * @param string $trigger If defined, call also the trigger (for example COMPANY_MODIFY) |
||
5133 | * @param User $userused Object user |
||
5134 | * @return int -1=error, O=did nothing, 1=OK |
||
5135 | * @see setValueFrom, insertExtraFields |
||
5136 | */ |
||
5137 | function updateExtraField($key, $trigger=null, $userused=null) |
||
5138 | { |
||
5139 | global $conf,$langs,$user; |
||
5140 | |||
5141 | if (empty($userused)) $userused=$user; |
||
5142 | |||
5143 | $error=0; |
||
5144 | |||
5145 | if (! empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) return 0; // For avoid conflicts if trigger used |
||
5146 | |||
5147 | if (! empty($this->array_options) && isset($this->array_options["options_".$key])) |
||
5148 | { |
||
5149 | // Check parameters |
||
5150 | $langs->load('admin'); |
||
5151 | require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; |
||
5152 | $extrafields = new ExtraFields($this->db); |
||
5153 | $target_extrafields=$extrafields->fetch_name_optionals_label($this->table_element); |
||
5154 | |||
5155 | $value=$this->array_options["options_".$key]; |
||
5156 | |||
5157 | $attributeType = $extrafields->attributes[$this->table_element]['type'][$key]; |
||
5158 | $attributeLabel = $extrafields->attributes[$this->table_element]['label'][$key]; |
||
5159 | $attributeParam = $extrafields->attributes[$this->table_element]['param'][$key]; |
||
5160 | $attributeRequired = $extrafields->attributes[$this->table_element]['required'][$key]; |
||
5161 | |||
5162 | //dol_syslog("attributeLabel=".$attributeLabel, LOG_DEBUG); |
||
5163 | //dol_syslog("attributeType=".$attributeType, LOG_DEBUG); |
||
5164 | |||
5165 | switch ($attributeType) |
||
5166 | { |
||
5167 | case 'int': |
||
5168 | if (!is_numeric($value) && $value!='') |
||
5169 | { |
||
5170 | $this->errors[]=$langs->trans("ExtraFieldHasWrongValue",$attributeLabel); |
||
5171 | return -1; |
||
5172 | } |
||
5173 | elseif ($value=='') |
||
5174 | { |
||
5175 | $this->array_options["options_".$key] = null; |
||
5176 | } |
||
5177 | break; |
||
5178 | case 'double': |
||
5179 | $value = price2num($value); |
||
5180 | if (!is_numeric($value) && $value!='') |
||
5181 | { |
||
5182 | dol_syslog($langs->trans("ExtraFieldHasWrongValue")." sur ".$attributeLabel."(".$value."is not '".$attributeType."')", LOG_DEBUG); |
||
5183 | $this->errors[]=$langs->trans("ExtraFieldHasWrongValue", $attributeLabel); |
||
5184 | return -1; |
||
5185 | } |
||
5186 | elseif ($value=='') |
||
5187 | { |
||
5188 | $this->array_options["options_".$key] = null; |
||
5189 | } |
||
5190 | //dol_syslog("double value"." sur ".$attributeLabel."(".$value." is '".$attributeType."')", LOG_DEBUG); |
||
5191 | $this->array_options["options_".$key] = $value; |
||
5192 | break; |
||
5193 | /*case 'select': // Not required, we chosed value='0' for undefined values |
||
5194 | if ($value=='-1') |
||
5195 | { |
||
5196 | $this->array_options[$key] = null; |
||
5197 | } |
||
5198 | break;*/ |
||
5199 | case 'price': |
||
5200 | $this->array_options["options_".$key] = price2num($this->array_options["options_".$key]); |
||
5201 | break; |
||
5202 | case 'date': |
||
5203 | $this->array_options["options_".$key]=$this->db->idate($this->array_options["options_".$key]); |
||
5204 | break; |
||
5205 | case 'datetime': |
||
5206 | $this->array_options["options_".$key]=$this->db->idate($this->array_options["options_".$key]); |
||
5207 | break; |
||
5208 | case 'link': |
||
5209 | $param_list=array_keys($attributeParam['options']); |
||
5210 | // 0 : ObjectName |
||
5211 | // 1 : classPath |
||
5212 | $InfoFieldList = explode(":", $param_list[0]); |
||
5213 | dol_include_once($InfoFieldList[1]); |
||
5214 | if ($value) |
||
5215 | { |
||
5216 | $object = new $InfoFieldList[0]($this->db); |
||
5217 | $object->fetch(0,$value); |
||
5218 | $this->array_options["options_".$key]=$object->id; |
||
5219 | } |
||
5220 | break; |
||
5221 | } |
||
5222 | |||
5223 | $this->db->begin(); |
||
5224 | $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element."_extrafields SET ".$key."='".$this->db->escape($this->array_options["options_".$key])."'"; |
||
5225 | $sql .= " WHERE fk_object = ".$this->id; |
||
5226 | $resql = $this->db->query($sql); |
||
5227 | if (! $resql) |
||
5228 | { |
||
5229 | $error++; |
||
5230 | $this->error=$this->db->lasterror(); |
||
5231 | } |
||
5232 | |||
5233 | if (! $error && $trigger) |
||
5234 | { |
||
5235 | // Call trigger |
||
5236 | $this->context=array('extrafieldupdate'=>1); |
||
5237 | $result=$this->call_trigger($trigger, $userused); |
||
5238 | if ($result < 0) $error++; |
||
5239 | // End call trigger |
||
5240 | } |
||
5241 | |||
5242 | if ($error) |
||
5243 | { |
||
5244 | dol_syslog(get_class($this) . "::".__METHOD__ . $this->error, LOG_ERR); |
||
5245 | $this->db->rollback(); |
||
5246 | return -1; |
||
5247 | } |
||
5248 | else |
||
5249 | { |
||
5250 | $this->db->commit(); |
||
5251 | return 1; |
||
5252 | } |
||
5253 | } |
||
5254 | else return 0; |
||
5255 | } |
||
5256 | |||
5257 | |||
5258 | /** |
||
5259 | * Return HTML string to put an input field into a page |
||
5260 | * Code very similar with showInputField of extra fields |
||
5261 | * |
||
5262 | * @param array $val Array of properties for field to show |
||
5263 | * @param string $key Key of attribute |
||
5264 | * @param string $value Preselected value to show (for date type it must be in timestamp format, for amount or price it must be a php numeric value) |
||
5265 | * @param string $moreparam To add more parameters on html input tag |
||
5266 | * @param string $keysuffix Prefix string to add into name and id of field (can be used to avoid duplicate names) |
||
5267 | * @param string $keyprefix Suffix string to add into name and id of field (can be used to avoid duplicate names) |
||
5268 | * @param string|int $morecss Value for css to define style/length of field. May also be a numeric. |
||
5269 | * @return string |
||
5270 | */ |
||
5271 | function showInputField($val, $key, $value, $moreparam='', $keysuffix='', $keyprefix='', $morecss=0) |
||
5272 | { |
||
5273 | global $conf,$langs,$form; |
||
5274 | |||
5275 | if (! is_object($form)) |
||
5276 | { |
||
5277 | require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; |
||
5278 | $form=new Form($this->db); |
||
5279 | } |
||
5280 | |||
5281 | $val=$this->fields[$key]; |
||
5282 | |||
5283 | $out=''; |
||
5284 | $type=''; |
||
5285 | $param = array(); |
||
5286 | $param['options']=array(); |
||
5287 | $size =$this->fields[$key]['size']; |
||
5288 | // Because we work on extrafields |
||
5289 | if(preg_match('/^integer:(.*):(.*)/i', $val['type'], $reg)){ |
||
5290 | $param['options']=array($reg[1].':'.$reg[2]=>'N'); |
||
5291 | $type ='link'; |
||
5292 | } elseif(preg_match('/^link:(.*):(.*)/i', $val['type'], $reg)) { |
||
5293 | $param['options']=array($reg[1].':'.$reg[2]=>'N'); |
||
5294 | $type ='link'; |
||
5295 | } elseif(preg_match('/^sellist:(.*):(.*):(.*):(.*)/i', $val['type'], $reg)) { |
||
5296 | $param['options']=array($reg[1].':'.$reg[2].':'.$reg[3].':'.$reg[4]=>'N'); |
||
5297 | $type ='sellist'; |
||
5298 | } elseif(preg_match('/varchar\((\d+)\)/', $val['type'],$reg)) { |
||
5299 | $param['options']=array(); |
||
5300 | $type ='varchar'; |
||
5301 | $size=$reg[1]; |
||
5302 | } elseif(preg_match('/varchar/', $val['type'])) { |
||
5303 | $param['options']=array(); |
||
5304 | $type ='varchar'; |
||
5305 | } elseif(is_array($this->fields[$key]['arrayofkeyval'])) { |
||
5306 | $param['options']=$this->fields[$key]['arrayofkeyval']; |
||
5307 | $type ='select'; |
||
5308 | } else { |
||
5309 | $param['options']=array(); |
||
5310 | $type =$this->fields[$key]['type']; |
||
5311 | } |
||
5312 | |||
5313 | $label=$this->fields[$key]['label']; |
||
5314 | //$elementtype=$this->fields[$key]['elementtype']; // Seems not used |
||
5315 | $default=$this->fields[$key]['default']; |
||
5316 | $computed=$this->fields[$key]['computed']; |
||
5317 | $unique=$this->fields[$key]['unique']; |
||
5318 | $required=$this->fields[$key]['required']; |
||
5319 | |||
5320 | $langfile=$this->fields[$key]['langfile']; |
||
5321 | $list=$this->fields[$key]['list']; |
||
5322 | $hidden=abs($this->fields[$key]['visible'])!=1?1:0; |
||
5323 | |||
5324 | $objectid = $this->id; |
||
5325 | |||
5326 | |||
5327 | if ($computed) |
||
5328 | { |
||
5329 | if (! preg_match('/^search_/', $keyprefix)) return '<span class="opacitymedium">'.$langs->trans("AutomaticallyCalculated").'</span>'; |
||
5330 | else return ''; |
||
5331 | } |
||
5332 | |||
5333 | |||
5334 | // Use in priority showsize from parameters, then $val['css'] then autodefine |
||
5335 | if (empty($morecss) && ! empty($val['css'])) |
||
5336 | { |
||
5337 | $showsize = $val['css']; |
||
5338 | } |
||
5339 | if (empty($morecss)) |
||
5340 | { |
||
5341 | if ($type == 'date') |
||
5342 | { |
||
5343 | $morecss = 'minwidth100imp'; |
||
5344 | } |
||
5345 | elseif ($type == 'datetime') |
||
5346 | { |
||
5347 | $morecss = 'minwidth200imp'; |
||
5348 | } |
||
5349 | elseif (in_array($type,array('int','integer','price')) || preg_match('/^double(\([0-9],[0-9]\)){0,1}/',$type)) |
||
5350 | { |
||
5351 | $morecss = 'maxwidth75'; |
||
5352 | }elseif ($type == 'url') |
||
5353 | { |
||
5354 | $morecss='minwidth400'; |
||
5355 | } |
||
5356 | elseif ($type == 'boolean') |
||
5357 | { |
||
5358 | $morecss=''; |
||
5359 | } |
||
5360 | else |
||
5361 | { |
||
5362 | if (round($size) < 12) |
||
5363 | { |
||
5364 | $morecss = 'minwidth100'; |
||
5365 | } |
||
5366 | else if (round($size) <= 48) |
||
5367 | { |
||
5368 | $morecss = 'minwidth200'; |
||
5369 | } |
||
5370 | else |
||
5371 | { |
||
5372 | $morecss = 'minwidth400'; |
||
5373 | } |
||
5374 | } |
||
5375 | } |
||
5376 | |||
5377 | if (in_array($type,array('date','datetime'))) |
||
5378 | { |
||
5379 | $tmp=explode(',',$size); |
||
5380 | $newsize=$tmp[0]; |
||
5381 | |||
5382 | $showtime = in_array($type,array('datetime')) ? 1 : 0; |
||
5383 | |||
5384 | // Do not show current date when field not required (see selectDate() method) |
||
5385 | if (!$required && $value == '') $value = '-1'; |
||
5386 | |||
5387 | // TODO Must also support $moreparam |
||
5388 | $out = $form->selectDate($value, $keyprefix.$key.$keysuffix, $showtime, $showtime, $required, '', 1, (($keyprefix != 'search_' && $keyprefix != 'search_options_') ? 1 : 0), 0, 1); |
||
5389 | } |
||
5390 | elseif (in_array($type,array('int','integer'))) |
||
5391 | { |
||
5392 | $tmp=explode(',',$size); |
||
5393 | $newsize=$tmp[0]; |
||
5394 | $out='<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" maxlength="'.$newsize.'" value="'.dol_escape_htmltag($value).'"'.($moreparam?$moreparam:'').'>'; |
||
5395 | } |
||
5396 | elseif (preg_match('/varchar/', $type)) |
||
5397 | { |
||
5398 | $out='<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" maxlength="'.$size.'" value="'.dol_escape_htmltag($value).'"'.($moreparam?$moreparam:'').'>'; |
||
5399 | } |
||
5400 | elseif (in_array($type, array('mail', 'phone', 'url'))) |
||
5401 | { |
||
5402 | $out='<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.dol_escape_htmltag($value).'" '.($moreparam?$moreparam:'').'>'; |
||
5403 | } |
||
5404 | elseif ($type == 'text') |
||
5405 | { |
||
5406 | if (! preg_match('/search_/', $keyprefix)) // If keyprefix is search_ or search_options_, we must just use a simple text field |
||
5407 | { |
||
5408 | require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; |
||
5409 | $doleditor=new DolEditor($keyprefix.$key.$keysuffix,$value,'',200,'dolibarr_notes','In',false,false,false,ROWS_5,'90%'); |
||
5410 | $out=$doleditor->Create(1); |
||
5411 | } |
||
5412 | else |
||
5413 | { |
||
5414 | $out='<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.dol_escape_htmltag($value).'" '.($moreparam?$moreparam:'').'>'; |
||
5415 | } |
||
5416 | } |
||
5417 | elseif ($type == 'html') |
||
5418 | { |
||
5419 | if (! preg_match('/search_/', $keyprefix)) // If keyprefix is search_ or search_options_, we must just use a simple text field |
||
5420 | { |
||
5421 | require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; |
||
5422 | $doleditor=new DolEditor($keyprefix.$key.$keysuffix,$value,'',200,'dolibarr_notes','In',false,false,! empty($conf->fckeditor->enabled) && $conf->global->FCKEDITOR_ENABLE_SOCIETE,ROWS_5,'90%'); |
||
5423 | $out=$doleditor->Create(1); |
||
5424 | } |
||
5425 | else |
||
5426 | { |
||
5427 | $out='<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.dol_escape_htmltag($value).'" '.($moreparam?$moreparam:'').'>'; |
||
5428 | } |
||
5429 | } |
||
5430 | elseif ($type == 'boolean') |
||
5431 | { |
||
5432 | $checked=''; |
||
5433 | if (!empty($value)) { |
||
5434 | $checked=' checked value="1" '; |
||
5435 | } else { |
||
5436 | $checked=' value="1" '; |
||
5437 | } |
||
5438 | $out='<input type="checkbox" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.$checked.' '.($moreparam?$moreparam:'').'>'; |
||
5439 | } |
||
5440 | elseif ($type == 'price') |
||
5441 | { |
||
5442 | if (!empty($value)) { // $value in memory is a php numeric, we format it into user number format. |
||
5443 | $value=price($value); |
||
5444 | } |
||
5445 | $out='<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.$value.'" '.($moreparam?$moreparam:'').'> '.$langs->getCurrencySymbol($conf->currency); |
||
5446 | } |
||
5447 | elseif (preg_match('/^double(\([0-9],[0-9]\)){0,1}/',$type)) |
||
5448 | { |
||
5449 | if (!empty($value)) { // $value in memory is a php numeric, we format it into user number format. |
||
5450 | $value=price($value); |
||
5451 | } |
||
5452 | $out='<input type="text" class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.$value.'" '.($moreparam?$moreparam:'').'> '; |
||
5453 | } |
||
5454 | elseif ($type == 'select') |
||
5455 | { |
||
5456 | $out = ''; |
||
5457 | if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->MAIN_EXTRAFIELDS_USE_SELECT2)) |
||
5458 | { |
||
5459 | include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php'; |
||
5460 | $out.= ajax_combobox($keyprefix.$key.$keysuffix, array(), 0); |
||
5461 | } |
||
5462 | |||
5463 | $out.='<select class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam?$moreparam:'').'>'; |
||
5464 | if((! isset($this->fields[$key]['default'])) ||($this->fields[$key]['notnull']!=1))$out.='<option value="0"> </option>'; |
||
5465 | foreach ($param['options'] as $key => $val) |
||
5466 | { |
||
5467 | if ((string) $key == '') continue; |
||
5468 | list($val, $parent) = explode('|', $val); |
||
5469 | $out.='<option value="'.$key.'"'; |
||
5470 | $out.= (((string) $value == (string) $key)?' selected':''); |
||
5471 | $out.= (!empty($parent)?' parent="'.$parent.'"':''); |
||
5472 | $out.='>'.$val.'</option>'; |
||
5473 | } |
||
5474 | $out.='</select>'; |
||
5475 | } |
||
5476 | elseif ($type == 'sellist') |
||
5477 | { |
||
5478 | $out = ''; |
||
5479 | if (! empty($conf->use_javascript_ajax) && ! empty($conf->global->MAIN_EXTRAFIELDS_USE_SELECT2)) |
||
5480 | { |
||
5481 | include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php'; |
||
5482 | $out.= ajax_combobox($keyprefix.$key.$keysuffix, array(), 0); |
||
5483 | } |
||
5484 | |||
5485 | $out.='<select class="flat '.$morecss.' maxwidthonsmartphone" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam?$moreparam:'').'>'; |
||
5486 | if (is_array($param['options'])) |
||
5487 | { |
||
5488 | $param_list=array_keys($param['options']); |
||
5489 | $InfoFieldList = explode(":", $param_list[0]); |
||
5490 | $parentName=''; |
||
5491 | $parentField=''; |
||
5492 | // 0 : tableName |
||
5493 | // 1 : label field name |
||
5494 | // 2 : key fields name (if differ of rowid) |
||
5495 | // 3 : key field parent (for dependent lists) |
||
5496 | // 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value |
||
5497 | $keyList=(empty($InfoFieldList[2])?'rowid':$InfoFieldList[2].' as rowid'); |
||
5498 | |||
5499 | |||
5500 | if (count($InfoFieldList) > 4 && ! empty($InfoFieldList[4])) |
||
5501 | { |
||
5502 | if (strpos($InfoFieldList[4], 'extra.') !== false) |
||
5503 | { |
||
5504 | $keyList='main.'.$InfoFieldList[2].' as rowid'; |
||
5505 | } else { |
||
5506 | $keyList=$InfoFieldList[2].' as rowid'; |
||
5507 | } |
||
5508 | } |
||
5509 | if (count($InfoFieldList) > 3 && ! empty($InfoFieldList[3])) |
||
5510 | { |
||
5511 | list($parentName, $parentField) = explode('|', $InfoFieldList[3]); |
||
5512 | $keyList.= ', '.$parentField; |
||
5513 | } |
||
5514 | |||
5515 | $fields_label = explode('|',$InfoFieldList[1]); |
||
5516 | if (is_array($fields_label)) |
||
5517 | { |
||
5518 | $keyList .=', '; |
||
5519 | $keyList .= implode(', ', $fields_label); |
||
5520 | } |
||
5521 | |||
5522 | $sqlwhere=''; |
||
5523 | $sql = 'SELECT '.$keyList; |
||
5524 | $sql.= ' FROM '.MAIN_DB_PREFIX .$InfoFieldList[0]; |
||
5525 | if (!empty($InfoFieldList[4])) |
||
5526 | { |
||
5527 | // can use SELECT request |
||
5528 | if (strpos($InfoFieldList[4], '$SEL$')!==false) { |
||
5529 | $InfoFieldList[4]=str_replace('$SEL$','SELECT',$InfoFieldList[4]); |
||
5530 | } |
||
5531 | |||
5532 | // current object id can be use into filter |
||
5533 | if (strpos($InfoFieldList[4], '$ID$')!==false && !empty($objectid)) { |
||
5534 | $InfoFieldList[4]=str_replace('$ID$',$objectid,$InfoFieldList[4]); |
||
5535 | } else { |
||
5536 | $InfoFieldList[4]=str_replace('$ID$','0',$InfoFieldList[4]); |
||
5537 | } |
||
5538 | //We have to join on extrafield table |
||
5539 | if (strpos($InfoFieldList[4], 'extra')!==false) |
||
5540 | { |
||
5541 | $sql.= ' as main, '.MAIN_DB_PREFIX .$InfoFieldList[0].'_extrafields as extra'; |
||
5542 | $sqlwhere.= ' WHERE extra.fk_object=main.'.$InfoFieldList[2]. ' AND '.$InfoFieldList[4]; |
||
5543 | } |
||
5544 | else |
||
5545 | { |
||
5546 | $sqlwhere.= ' WHERE '.$InfoFieldList[4]; |
||
5547 | } |
||
5548 | } |
||
5549 | else |
||
5550 | { |
||
5551 | $sqlwhere.= ' WHERE 1=1'; |
||
5552 | } |
||
5553 | // Some tables may have field, some other not. For the moment we disable it. |
||
5554 | if (in_array($InfoFieldList[0],array('tablewithentity'))) |
||
5555 | { |
||
5556 | $sqlwhere.= ' AND entity = '.$conf->entity; |
||
5557 | } |
||
5558 | $sql.=$sqlwhere; |
||
5559 | //print $sql; |
||
5560 | |||
5561 | $sql .= ' ORDER BY ' . implode(', ', $fields_label); |
||
5562 | |||
5563 | dol_syslog(get_class($this).'::showInputField type=sellist', LOG_DEBUG); |
||
5564 | $resql = $this->db->query($sql); |
||
5565 | if ($resql) |
||
5566 | { |
||
5567 | $out.='<option value="0"> </option>'; |
||
5568 | $num = $this->db->num_rows($resql); |
||
5569 | $i = 0; |
||
5570 | while ($i < $num) |
||
5571 | { |
||
5572 | $labeltoshow=''; |
||
5573 | $obj = $this->db->fetch_object($resql); |
||
5574 | |||
5575 | // Several field into label (eq table:code|libelle:rowid) |
||
5576 | $notrans = false; |
||
5577 | $fields_label = explode('|',$InfoFieldList[1]); |
||
5578 | if (is_array($fields_label)) |
||
5579 | { |
||
5580 | $notrans = true; |
||
5581 | foreach ($fields_label as $field_toshow) |
||
5582 | { |
||
5583 | $labeltoshow.= $obj->$field_toshow.' '; |
||
5584 | } |
||
5585 | } |
||
5586 | else |
||
5587 | { |
||
5588 | $labeltoshow=$obj->{$InfoFieldList[1]}; |
||
5589 | } |
||
5590 | $labeltoshow=dol_trunc($labeltoshow,45); |
||
5591 | |||
5592 | if ($value == $obj->rowid) |
||
5593 | { |
||
5594 | foreach ($fields_label as $field_toshow) |
||
5595 | { |
||
5596 | $translabel=$langs->trans($obj->$field_toshow); |
||
5597 | if ($translabel!=$obj->$field_toshow) { |
||
5598 | $labeltoshow=dol_trunc($translabel,18).' '; |
||
5599 | }else { |
||
5600 | $labeltoshow=dol_trunc($obj->$field_toshow,18).' '; |
||
5601 | } |
||
5602 | } |
||
5603 | $out.='<option value="'.$obj->rowid.'" selected>'.$labeltoshow.'</option>'; |
||
5604 | } |
||
5605 | else |
||
5606 | { |
||
5607 | if (! $notrans) |
||
5608 | { |
||
5609 | $translabel=$langs->trans($obj->{$InfoFieldList[1]}); |
||
5610 | if ($translabel!=$obj->{$InfoFieldList[1]}) { |
||
5611 | $labeltoshow=dol_trunc($translabel,18); |
||
5612 | } |
||
5613 | else { |
||
5614 | $labeltoshow=dol_trunc($obj->{$InfoFieldList[1]},18); |
||
5615 | } |
||
5616 | } |
||
5617 | if (empty($labeltoshow)) $labeltoshow='(not defined)'; |
||
5618 | if ($value==$obj->rowid) |
||
5619 | { |
||
5620 | $out.='<option value="'.$obj->rowid.'" selected>'.$labeltoshow.'</option>'; |
||
5621 | } |
||
5622 | |||
5623 | if (!empty($InfoFieldList[3]) && $parentField) |
||
5624 | { |
||
5625 | $parent = $parentName.':'.$obj->{$parentField}; |
||
5626 | } |
||
5627 | |||
5628 | $out.='<option value="'.$obj->rowid.'"'; |
||
5629 | $out.= ($value==$obj->rowid?' selected':''); |
||
5630 | $out.= (!empty($parent)?' parent="'.$parent.'"':''); |
||
5631 | $out.='>'.$labeltoshow.'</option>'; |
||
5632 | } |
||
5633 | |||
5634 | $i++; |
||
5635 | } |
||
5636 | $this->db->free($resql); |
||
5637 | } |
||
5638 | else { |
||
5639 | print 'Error in request '.$sql.' '.$this->db->lasterror().'. Check setup of extra parameters.<br>'; |
||
5640 | } |
||
5641 | } |
||
5642 | $out.='</select>'; |
||
5643 | } |
||
5644 | elseif ($type == 'checkbox') |
||
5645 | { |
||
5646 | $value_arr=explode(',',$value); |
||
5647 | $out=$form->multiselectarray($keyprefix.$key.$keysuffix, (empty($param['options'])?null:$param['options']), $value_arr, '', 0, '', 0, '100%'); |
||
5648 | } |
||
5649 | elseif ($type == 'radio') |
||
5650 | { |
||
5651 | $out=''; |
||
5652 | foreach ($param['options'] as $keyopt => $val) |
||
5653 | { |
||
5654 | $out.='<input class="flat '.$morecss.'" type="radio" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" '.($moreparam?$moreparam:''); |
||
5655 | $out.=' value="'.$keyopt.'"'; |
||
5656 | $out.=' id="'.$keyprefix.$key.$keysuffix.'_'.$keyopt.'"'; |
||
5657 | $out.= ($value==$keyopt?'checked':''); |
||
5658 | $out.='/><label for="'.$keyprefix.$key.$keysuffix.'_'.$keyopt.'">'.$val.'</label><br>'; |
||
5659 | } |
||
5660 | } |
||
5661 | elseif ($type == 'chkbxlst') |
||
5662 | { |
||
5663 | if (is_array($value)) { |
||
5664 | $value_arr = $value; |
||
5665 | } |
||
5666 | else { |
||
5667 | $value_arr = explode(',', $value); |
||
5668 | } |
||
5669 | |||
5670 | if (is_array($param['options'])) { |
||
5671 | $param_list = array_keys($param['options']); |
||
5672 | $InfoFieldList = explode(":", $param_list[0]); |
||
5673 | $parentName=''; |
||
5674 | $parentField=''; |
||
5675 | // 0 : tableName |
||
5676 | // 1 : label field name |
||
5677 | // 2 : key fields name (if differ of rowid) |
||
5678 | // 3 : key field parent (for dependent lists) |
||
5679 | // 4 : where clause filter on column or table extrafield, syntax field='value' or extra.field=value |
||
5680 | $keyList = (empty($InfoFieldList[2]) ? 'rowid' : $InfoFieldList[2] . ' as rowid'); |
||
5681 | |||
5682 | if (count($InfoFieldList) > 3 && ! empty($InfoFieldList[3])) { |
||
5683 | list ( $parentName, $parentField ) = explode('|', $InfoFieldList[3]); |
||
5684 | $keyList .= ', ' . $parentField; |
||
5685 | } |
||
5686 | if (count($InfoFieldList) > 4 && ! empty($InfoFieldList[4])) { |
||
5687 | if (strpos($InfoFieldList[4], 'extra.') !== false) { |
||
5688 | $keyList = 'main.' . $InfoFieldList[2] . ' as rowid'; |
||
5689 | } else { |
||
5690 | $keyList = $InfoFieldList[2] . ' as rowid'; |
||
5691 | } |
||
5692 | } |
||
5693 | |||
5694 | $fields_label = explode('|', $InfoFieldList[1]); |
||
5695 | if (is_array($fields_label)) { |
||
5696 | $keyList .= ', '; |
||
5697 | $keyList .= implode(', ', $fields_label); |
||
5698 | } |
||
5699 | |||
5700 | $sqlwhere = ''; |
||
5701 | $sql = 'SELECT ' . $keyList; |
||
5702 | $sql .= ' FROM ' . MAIN_DB_PREFIX . $InfoFieldList[0]; |
||
5703 | if (! empty($InfoFieldList[4])) { |
||
5704 | |||
5705 | // can use SELECT request |
||
5706 | if (strpos($InfoFieldList[4], '$SEL$')!==false) { |
||
5707 | $InfoFieldList[4]=str_replace('$SEL$','SELECT',$InfoFieldList[4]); |
||
5708 | } |
||
5709 | |||
5710 | // current object id can be use into filter |
||
5711 | if (strpos($InfoFieldList[4], '$ID$')!==false && !empty($objectid)) { |
||
5712 | $InfoFieldList[4]=str_replace('$ID$',$objectid,$InfoFieldList[4]); |
||
5713 | } else { |
||
5714 | $InfoFieldList[4]=str_replace('$ID$','0',$InfoFieldList[4]); |
||
5715 | } |
||
5716 | |||
5717 | // We have to join on extrafield table |
||
5718 | if (strpos($InfoFieldList[4], 'extra') !== false) { |
||
5719 | $sql .= ' as main, ' . MAIN_DB_PREFIX . $InfoFieldList[0] . '_extrafields as extra'; |
||
5720 | $sqlwhere .= ' WHERE extra.fk_object=main.' . $InfoFieldList[2] . ' AND ' . $InfoFieldList[4]; |
||
5721 | } else { |
||
5722 | $sqlwhere .= ' WHERE ' . $InfoFieldList[4]; |
||
5723 | } |
||
5724 | } else { |
||
5725 | $sqlwhere .= ' WHERE 1=1'; |
||
5726 | } |
||
5727 | // Some tables may have field, some other not. For the moment we disable it. |
||
5728 | if (in_array($InfoFieldList[0], array ('tablewithentity'))) |
||
5729 | { |
||
5730 | $sqlwhere .= ' AND entity = ' . $conf->entity; |
||
5731 | } |
||
5732 | // $sql.=preg_replace('/^ AND /','',$sqlwhere); |
||
5733 | // print $sql; |
||
5734 | |||
5735 | $sql .= $sqlwhere; |
||
5736 | dol_syslog(get_class($this) . '::showInputField type=chkbxlst',LOG_DEBUG); |
||
5737 | $resql = $this->db->query($sql); |
||
5738 | if ($resql) { |
||
5739 | $num = $this->db->num_rows($resql); |
||
5740 | $i = 0; |
||
5741 | |||
5742 | $data=array(); |
||
5743 | |||
5744 | while ( $i < $num ) { |
||
5745 | $labeltoshow = ''; |
||
5746 | $obj = $this->db->fetch_object($resql); |
||
5747 | |||
5748 | $notrans = false; |
||
5749 | // Several field into label (eq table:code|libelle:rowid) |
||
5750 | $fields_label = explode('|', $InfoFieldList[1]); |
||
5751 | if (is_array($fields_label)) { |
||
5752 | $notrans = true; |
||
5753 | foreach ( $fields_label as $field_toshow ) { |
||
5754 | $labeltoshow .= $obj->$field_toshow . ' '; |
||
5755 | } |
||
5756 | } else { |
||
5757 | $labeltoshow = $obj->{$InfoFieldList[1]}; |
||
5758 | } |
||
5759 | $labeltoshow = dol_trunc($labeltoshow, 45); |
||
5760 | |||
5761 | if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) { |
||
5762 | foreach ( $fields_label as $field_toshow ) { |
||
5763 | $translabel = $langs->trans($obj->$field_toshow); |
||
5764 | if ($translabel != $obj->$field_toshow) { |
||
5765 | $labeltoshow = dol_trunc($translabel, 18) . ' '; |
||
5766 | } else { |
||
5767 | $labeltoshow = dol_trunc($obj->$field_toshow, 18) . ' '; |
||
5768 | } |
||
5769 | } |
||
5770 | |||
5771 | $data[$obj->rowid]=$labeltoshow; |
||
5772 | } else { |
||
5773 | if (! $notrans) { |
||
5774 | $translabel = $langs->trans($obj->{$InfoFieldList[1]}); |
||
5775 | if ($translabel != $obj->{$InfoFieldList[1]}) { |
||
5776 | $labeltoshow = dol_trunc($translabel, 18); |
||
5777 | } else { |
||
5778 | $labeltoshow = dol_trunc($obj->{$InfoFieldList[1]}, 18); |
||
5779 | } |
||
5780 | } |
||
5781 | if (empty($labeltoshow)) |
||
5782 | $labeltoshow = '(not defined)'; |
||
5783 | |||
5784 | if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) { |
||
5785 | $data[$obj->rowid]=$labeltoshow; |
||
5786 | } |
||
5787 | |||
5788 | if (! empty($InfoFieldList[3]) && $parentField) { |
||
5789 | $parent = $parentName . ':' . $obj->{$parentField}; |
||
5790 | } |
||
5791 | |||
5792 | $data[$obj->rowid]=$labeltoshow; |
||
5793 | } |
||
5794 | |||
5795 | $i ++; |
||
5796 | } |
||
5797 | $this->db->free($resql); |
||
5798 | |||
5799 | $out=$form->multiselectarray($keyprefix.$key.$keysuffix, $data, $value_arr, '', 0, '', 0, '100%'); |
||
5800 | } else { |
||
5801 | print 'Error in request ' . $sql . ' ' . $this->db->lasterror() . '. Check setup of extra parameters.<br>'; |
||
5802 | } |
||
5803 | } |
||
5804 | } |
||
5805 | elseif ($type == 'link') |
||
5806 | { |
||
5807 | $param_list=array_keys($param['options']); // $param_list='ObjectName:classPath' |
||
5808 | $showempty=(($required && $default != '')?0:1); |
||
5809 | $out=$form->selectForForms($param_list[0], $keyprefix.$key.$keysuffix, $value, $showempty); |
||
5810 | if ($conf->global->MAIN_FEATURES_LEVEL >= 2) |
||
5811 | { |
||
5812 | list($class,$classfile)=explode(':',$param_list[0]); |
||
5813 | if (file_exists(dol_buildpath(dirname(dirname($classfile)).'/card.php'))) $url_path=dol_buildpath(dirname(dirname($classfile)).'/card.php',1); |
||
5814 | else $url_path=dol_buildpath(dirname(dirname($classfile)).'/'.$class.'_card.php',1); |
||
5815 | $out.='<a class="butActionNew" href="'.$url_path.'?action=create&backtopage='.$_SERVER['PHP_SELF'].'"><span class="fa fa-plus-circle valignmiddle"></span></a>'; |
||
5816 | // TODO Add Javascript code to add input fields contents to new elements urls |
||
5817 | } |
||
5818 | } |
||
5819 | elseif ($type == 'password') |
||
5820 | { |
||
5821 | // If prefix is 'search_', field is used as a filter, we use a common text field. |
||
5822 | $out='<input type="'.($keyprefix=='search_'?'text':'password').'" class="flat '.$morecss.'" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'" value="'.$value.'" '.($moreparam?$moreparam:'').'>'; |
||
5823 | } |
||
5824 | elseif ($type == 'array') |
||
5825 | { |
||
5826 | $newval = $val; |
||
5827 | $newval['type'] = 'varchar(256)'; |
||
5828 | |||
5829 | $out=''; |
||
5830 | |||
5831 | $inputs = array(); |
||
5832 | if(! empty($value)) { |
||
5833 | foreach($value as $option) { |
||
5834 | $out.= '<span><a class="'.dol_escape_htmltag($keyprefix.$key.$keysuffix).'_del" href="javascript:;"><span class="fa fa-minus-circle valignmiddle"></span></a> '; |
||
5835 | $out.= $this->showInputField($newval, $keyprefix.$key.$keysuffix.'[]', $option, $moreparam, '', '', $showsize).'<br></span>'; |
||
5836 | } |
||
5837 | } |
||
5838 | |||
5839 | $out.= '<a id="'.dol_escape_htmltag($keyprefix.$key.$keysuffix).'_add" href="javascript:;"><span class="fa fa-plus-circle valignmiddle"></span></a>'; |
||
5840 | |||
5841 | $newInput = '<span><a class="'.dol_escape_htmltag($keyprefix.$key.$keysuffix).'_del" href="javascript:;"><span class="fa fa-minus-circle valignmiddle"></span></a> '; |
||
5842 | $newInput.= $this->showInputField($newval, $keyprefix.$key.$keysuffix.'[]', '', $moreparam, '', '', $showsize).'<br></span>'; |
||
5843 | |||
5844 | if(! empty($conf->use_javascript_ajax)) { |
||
5845 | $out.= ' |
||
5846 | <script type="text/javascript"> |
||
5847 | $(document).ready(function() { |
||
5848 | $("a#'.dol_escape_js($keyprefix.$key.$keysuffix).'_add").click(function() { |
||
5849 | $("'.dol_escape_js($newInput).'").insertBefore(this); |
||
5850 | }); |
||
5851 | |||
5852 | $(document).on("click", "a.'.dol_escape_js($keyprefix.$key.$keysuffix).'_del", function() { |
||
5853 | $(this).parent().remove(); |
||
5854 | }); |
||
5855 | }); |
||
5856 | </script>'; |
||
5857 | } |
||
5858 | } |
||
5859 | if (!empty($hidden)) { |
||
5860 | $out='<input type="hidden" value="'.$value.'" name="'.$keyprefix.$key.$keysuffix.'" id="'.$keyprefix.$key.$keysuffix.'"/>'; |
||
5861 | } |
||
5862 | /* Add comments |
||
5863 | if ($type == 'date') $out.=' (YYYY-MM-DD)'; |
||
5864 | elseif ($type == 'datetime') $out.=' (YYYY-MM-DD HH:MM:SS)'; |
||
5865 | */ |
||
5866 | return $out; |
||
5867 | } |
||
5868 | |||
5869 | /** |
||
5870 | * Return HTML string to show a field into a page |
||
5871 | * Code very similar with showOutputField of extra fields |
||
5872 | * |
||
5873 | * @param array $val Array of properties of field to show |
||
5874 | * @param string $key Key of attribute |
||
5875 | * @param string $value Preselected value to show (for date type it must be in timestamp format, for amount or price it must be a php numeric value) |
||
5876 | * @param string $moreparam To add more parametes on html input tag |
||
5877 | * @param string $keysuffix Prefix string to add into name and id of field (can be used to avoid duplicate names) |
||
5878 | * @param string $keyprefix Suffix string to add into name and id of field (can be used to avoid duplicate names) |
||
5879 | * @param mixed $showsize Value for css to define size. May also be a numeric. |
||
5880 | * @return string |
||
5881 | */ |
||
5882 | function showOutputField($val, $key, $value, $moreparam='', $keysuffix='', $keyprefix='', $showsize=0) |
||
5883 | { |
||
5884 | global $conf,$langs,$form; |
||
5885 | |||
5886 | if (! is_object($form)) |
||
5887 | { |
||
5888 | require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; |
||
5889 | $form=new Form($this->db); |
||
5890 | } |
||
5891 | |||
5892 | $objectid = $this->id; |
||
5893 | $label = $val['label']; |
||
5894 | $type = $val['type']; |
||
5895 | $size = $val['css']; |
||
5896 | |||
5897 | // Convert var to be able to share same code than showOutputField of extrafields |
||
5898 | if (preg_match('/varchar\((\d+)\)/', $type, $reg)) |
||
5899 | { |
||
5900 | $type = 'varchar'; // convert varchar(xx) int varchar |
||
5901 | $size = $reg[1]; |
||
5902 | } |
||
5903 | elseif (preg_match('/varchar/', $type)) $type = 'varchar'; // convert varchar(xx) int varchar |
||
5904 | if (is_array($val['arrayofkeyval'])) $type='select'; |
||
5905 | if (preg_match('/^integer:(.*):(.*)/i', $val['type'], $reg)) $type='link'; |
||
5906 | |||
5907 | $default=$val['default']; |
||
5908 | $computed=$val['computed']; |
||
5909 | $unique=$val['unique']; |
||
5910 | $required=$val['required']; |
||
5911 | $param=$val['param']; |
||
5912 | if (is_array($val['arrayofkeyval'])) $param['options'] = $val['arrayofkeyval']; |
||
5913 | if (preg_match('/^integer:(.*):(.*)/i', $val['type'], $reg)) |
||
5914 | { |
||
5915 | $type='link'; |
||
5916 | $param['options']=array($reg[1].':'.$reg[2]=>$reg[1].':'.$reg[2]); |
||
5917 | } |
||
5918 | $langfile=$val['langfile']; |
||
5919 | $list=$val['list']; |
||
5920 | $help=$val['help']; |
||
5921 | $hidden=(($val['visible'] == 0) ? 1 : 0); // If zero, we are sure it is hidden, otherwise we show. If it depends on mode (view/create/edit form or list, this must be filtered by caller) |
||
5922 | |||
5923 | if ($hidden) return ''; |
||
5924 | |||
5925 | // If field is a computed field, value must become result of compute |
||
5926 | if ($computed) |
||
5927 | { |
||
5928 | // Make the eval of compute string |
||
5929 | //var_dump($computed); |
||
5930 | $value = dol_eval($computed, 1, 0); |
||
5931 | } |
||
5932 | |||
5933 | if (empty($showsize)) |
||
5934 | { |
||
5935 | if ($type == 'date') |
||
5936 | { |
||
5937 | //$showsize=10; |
||
5938 | $showsize = 'minwidth100imp'; |
||
5939 | } |
||
5940 | elseif ($type == 'datetime') |
||
5941 | { |
||
5942 | //$showsize=19; |
||
5943 | $showsize = 'minwidth200imp'; |
||
5944 | } |
||
5945 | elseif (in_array($type,array('int','double','price'))) |
||
5946 | { |
||
5947 | //$showsize=10; |
||
5948 | $showsize = 'maxwidth75'; |
||
5949 | } |
||
5950 | elseif ($type == 'url') |
||
5951 | { |
||
5952 | $showsize='minwidth400'; |
||
5953 | } |
||
5954 | elseif ($type == 'boolean') |
||
5955 | { |
||
5956 | $showsize=''; |
||
5957 | } |
||
5958 | else |
||
5959 | { |
||
5960 | if (round($size) < 12) |
||
5961 | { |
||
5962 | $showsize = 'minwidth100'; |
||
5963 | } |
||
5964 | else if (round($size) <= 48) |
||
5965 | { |
||
5966 | $showsize = 'minwidth200'; |
||
5967 | } |
||
5968 | else |
||
5969 | { |
||
5970 | //$showsize=48; |
||
5971 | $showsize = 'minwidth400'; |
||
5972 | } |
||
5973 | } |
||
5974 | } |
||
5975 | |||
5976 | // Format output value differently according to properties of field |
||
5977 | if ($key == 'ref' && method_exists($this, 'getNomUrl')) $value=$this->getNomUrl(1, '', 0, '', 1); |
||
5978 | elseif ($key == 'status' && method_exists($this, 'getLibStatut')) $value=$this->getLibStatut(3); |
||
5979 | elseif ($type == 'date') |
||
5980 | { |
||
5981 | if(! empty($value)) { |
||
5982 | $value=dol_print_date($value,'day'); |
||
5983 | } else { |
||
5984 | $value=''; |
||
5985 | } |
||
5986 | } |
||
5987 | elseif ($type == 'datetime') |
||
5988 | { |
||
5989 | if(! empty($value)) { |
||
5990 | $value=dol_print_date($value,'dayhour'); |
||
5991 | } else { |
||
5992 | $value=''; |
||
5993 | } |
||
5994 | } |
||
5995 | elseif ($type == 'double') |
||
5996 | { |
||
5997 | if (!empty($value)) { |
||
5998 | $value=price($value); |
||
5999 | } |
||
6000 | } |
||
6001 | elseif ($type == 'boolean') |
||
6002 | { |
||
6003 | $checked=''; |
||
6004 | if (!empty($value)) { |
||
6005 | $checked=' checked '; |
||
6006 | } |
||
6007 | $value='<input type="checkbox" '.$checked.' '.($moreparam?$moreparam:'').' readonly disabled>'; |
||
6008 | } |
||
6009 | elseif ($type == 'mail') |
||
6010 | { |
||
6011 | $value=dol_print_email($value,0,0,0,64,1,1); |
||
6012 | } |
||
6013 | elseif ($type == 'url') |
||
6014 | { |
||
6015 | $value=dol_print_url($value,'_blank',32,1); |
||
6016 | } |
||
6017 | elseif ($type == 'phone') |
||
6018 | { |
||
6019 | $value=dol_print_phone($value, '', 0, 0, '', ' ', 1); |
||
6020 | } |
||
6021 | elseif ($type == 'price') |
||
6022 | { |
||
6023 | $value=price($value,0,$langs,0,0,-1,$conf->currency); |
||
6024 | } |
||
6025 | elseif ($type == 'select') |
||
6026 | { |
||
6027 | $value=$param['options'][$value]; |
||
6028 | } |
||
6029 | elseif ($type == 'sellist') |
||
6030 | { |
||
6031 | $param_list=array_keys($param['options']); |
||
6032 | $InfoFieldList = explode(":", $param_list[0]); |
||
6033 | |||
6034 | $selectkey="rowid"; |
||
6035 | $keyList='rowid'; |
||
6036 | |||
6037 | if (count($InfoFieldList)>=3) |
||
6038 | { |
||
6039 | $selectkey = $InfoFieldList[2]; |
||
6040 | $keyList=$InfoFieldList[2].' as rowid'; |
||
6041 | } |
||
6042 | |||
6043 | $fields_label = explode('|',$InfoFieldList[1]); |
||
6044 | if(is_array($fields_label)) { |
||
6045 | $keyList .=', '; |
||
6046 | $keyList .= implode(', ', $fields_label); |
||
6047 | } |
||
6048 | |||
6049 | $sql = 'SELECT '.$keyList; |
||
6050 | $sql.= ' FROM '.MAIN_DB_PREFIX .$InfoFieldList[0]; |
||
6051 | if (strpos($InfoFieldList[4], 'extra')!==false) |
||
6052 | { |
||
6053 | $sql.= ' as main'; |
||
6054 | } |
||
6055 | if ($selectkey=='rowid' && empty($value)) { |
||
6056 | $sql.= " WHERE ".$selectkey."=0"; |
||
6057 | } elseif ($selectkey=='rowid') { |
||
6058 | $sql.= " WHERE ".$selectkey."=".$this->db->escape($value); |
||
6059 | }else { |
||
6060 | $sql.= " WHERE ".$selectkey."='".$this->db->escape($value)."'"; |
||
6061 | } |
||
6062 | |||
6063 | //$sql.= ' AND entity = '.$conf->entity; |
||
6064 | |||
6065 | dol_syslog(get_class($this).':showOutputField:$type=sellist', LOG_DEBUG); |
||
6066 | $resql = $this->db->query($sql); |
||
6067 | if ($resql) |
||
6068 | { |
||
6069 | $value=''; // value was used, so now we reste it to use it to build final output |
||
6070 | |||
6071 | $obj = $this->db->fetch_object($resql); |
||
6072 | |||
6073 | // Several field into label (eq table:code|libelle:rowid) |
||
6074 | $fields_label = explode('|',$InfoFieldList[1]); |
||
6075 | |||
6076 | if(is_array($fields_label) && count($fields_label)>1) |
||
6077 | { |
||
6078 | foreach ($fields_label as $field_toshow) |
||
6079 | { |
||
6080 | $translabel=''; |
||
6081 | if (!empty($obj->$field_toshow)) { |
||
6082 | $translabel=$langs->trans($obj->$field_toshow); |
||
6083 | } |
||
6084 | if ($translabel!=$field_toshow) { |
||
6085 | $value.=dol_trunc($translabel,18).' '; |
||
6086 | }else { |
||
6087 | $value.=$obj->$field_toshow.' '; |
||
6088 | } |
||
6089 | } |
||
6090 | } |
||
6091 | else |
||
6092 | { |
||
6093 | $translabel=''; |
||
6094 | if (!empty($obj->{$InfoFieldList[1]})) { |
||
6095 | $translabel=$langs->trans($obj->{$InfoFieldList[1]}); |
||
6096 | } |
||
6097 | if ($translabel!=$obj->{$InfoFieldList[1]}) { |
||
6098 | $value=dol_trunc($translabel,18); |
||
6099 | }else { |
||
6100 | $value=$obj->{$InfoFieldList[1]}; |
||
6101 | } |
||
6102 | } |
||
6103 | } |
||
6104 | else dol_syslog(get_class($this).'::showOutputField error '.$this->db->lasterror(), LOG_WARNING); |
||
6105 | } |
||
6106 | elseif ($type == 'radio') |
||
6107 | { |
||
6108 | $value=$param['options'][$value]; |
||
6109 | } |
||
6110 | elseif ($type == 'checkbox') |
||
6111 | { |
||
6112 | $value_arr=explode(',',$value); |
||
6113 | $value=''; |
||
6114 | if (is_array($value_arr) && count($value_arr)>0) |
||
6115 | { |
||
6116 | foreach ($value_arr as $keyval=>$valueval) { |
||
6117 | $toprint[]='<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #aaa">'.$param['options'][$valueval].'</li>'; |
||
6118 | } |
||
6119 | $value='<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>'; |
||
6120 | } |
||
6121 | } |
||
6122 | elseif ($type == 'chkbxlst') |
||
6123 | { |
||
6124 | $value_arr = explode(',', $value); |
||
6125 | |||
6126 | $param_list = array_keys($param['options']); |
||
6127 | $InfoFieldList = explode(":", $param_list[0]); |
||
6128 | |||
6129 | $selectkey = "rowid"; |
||
6130 | $keyList = 'rowid'; |
||
6131 | |||
6132 | if (count($InfoFieldList) >= 3) { |
||
6133 | $selectkey = $InfoFieldList[2]; |
||
6134 | $keyList = $InfoFieldList[2] . ' as rowid'; |
||
6135 | } |
||
6136 | |||
6137 | $fields_label = explode('|', $InfoFieldList[1]); |
||
6138 | if (is_array($fields_label)) { |
||
6139 | $keyList .= ', '; |
||
6140 | $keyList .= implode(', ', $fields_label); |
||
6141 | } |
||
6142 | |||
6143 | $sql = 'SELECT ' . $keyList; |
||
6144 | $sql .= ' FROM ' . MAIN_DB_PREFIX . $InfoFieldList[0]; |
||
6145 | if (strpos($InfoFieldList[4], 'extra') !== false) { |
||
6146 | $sql .= ' as main'; |
||
6147 | } |
||
6148 | // $sql.= " WHERE ".$selectkey."='".$this->db->escape($value)."'"; |
||
6149 | // $sql.= ' AND entity = '.$conf->entity; |
||
6150 | |||
6151 | dol_syslog(get_class($this) . ':showOutputField:$type=chkbxlst',LOG_DEBUG); |
||
6152 | $resql = $this->db->query($sql); |
||
6153 | if ($resql) { |
||
6154 | $value = ''; // value was used, so now we reste it to use it to build final output |
||
6155 | $toprint=array(); |
||
6156 | while ( $obj = $this->db->fetch_object($resql) ) { |
||
6157 | |||
6158 | // Several field into label (eq table:code|libelle:rowid) |
||
6159 | $fields_label = explode('|', $InfoFieldList[1]); |
||
6160 | if (is_array($value_arr) && in_array($obj->rowid, $value_arr)) { |
||
6161 | if (is_array($fields_label) && count($fields_label) > 1) { |
||
6162 | foreach ( $fields_label as $field_toshow ) { |
||
6163 | $translabel = ''; |
||
6164 | if (! empty($obj->$field_toshow)) { |
||
6165 | $translabel = $langs->trans($obj->$field_toshow); |
||
6166 | } |
||
6167 | if ($translabel != $field_toshow) { |
||
6168 | $toprint[]='<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #aaa">'.dol_trunc($translabel, 18).'</li>'; |
||
6169 | } else { |
||
6170 | $toprint[]='<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #aaa">'.$obj->$field_toshow.'</li>'; |
||
6171 | } |
||
6172 | } |
||
6173 | } else { |
||
6174 | $translabel = ''; |
||
6175 | if (! empty($obj->{$InfoFieldList[1]})) { |
||
6176 | $translabel = $langs->trans($obj->{$InfoFieldList[1]}); |
||
6177 | } |
||
6178 | if ($translabel != $obj->{$InfoFieldList[1]}) { |
||
6179 | $toprint[]='<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #aaa">'.dol_trunc($translabel, 18).'</li>'; |
||
6180 | } else { |
||
6181 | $toprint[]='<li class="select2-search-choice-dolibarr noborderoncategories" style="background: #aaa">'.$obj->{$InfoFieldList[1]}.'</li>'; |
||
6182 | } |
||
6183 | } |
||
6184 | } |
||
6185 | } |
||
6186 | $value='<div class="select2-container-multi-dolibarr" style="width: 90%;"><ul class="select2-choices-dolibarr">'.implode(' ', $toprint).'</ul></div>'; |
||
6187 | } else { |
||
6188 | dol_syslog(get_class($this) . '::showOutputField error ' . $this->db->lasterror(), LOG_WARNING); |
||
6189 | } |
||
6190 | } |
||
6191 | elseif ($type == 'link') |
||
6192 | { |
||
6193 | $out=''; |
||
6194 | |||
6195 | // only if something to display (perf) |
||
6196 | if ($value) |
||
6197 | { |
||
6198 | $param_list=array_keys($param['options']); // $param_list='ObjectName:classPath' |
||
6199 | |||
6200 | $InfoFieldList = explode(":", $param_list[0]); |
||
6201 | $classname=$InfoFieldList[0]; |
||
6202 | $classpath=$InfoFieldList[1]; |
||
6203 | $getnomurlparam=(empty($InfoFieldList[2]) ? 3 : $InfoFieldList[2]); |
||
6204 | if (! empty($classpath)) |
||
6205 | { |
||
6206 | dol_include_once($InfoFieldList[1]); |
||
6207 | if ($classname && class_exists($classname)) |
||
6208 | { |
||
6209 | $object = new $classname($this->db); |
||
6210 | $object->fetch($value); |
||
6211 | $value=$object->getNomUrl($getnomurlparam); |
||
6212 | } |
||
6213 | } |
||
6214 | else |
||
6215 | { |
||
6216 | dol_syslog('Error bad setup of extrafield', LOG_WARNING); |
||
6217 | return 'Error bad setup of extrafield'; |
||
6218 | } |
||
6219 | } |
||
6220 | else $value=''; |
||
6221 | } |
||
6222 | elseif ($type == 'text' || $type == 'html') |
||
6223 | { |
||
6224 | $value=dol_htmlentitiesbr($value); |
||
6225 | } |
||
6226 | elseif ($type == 'password') |
||
6227 | { |
||
6228 | $value=preg_replace('/./i','*',$value); |
||
6229 | } |
||
6230 | elseif ($type == 'array') |
||
6231 | { |
||
6232 | $value = implode('<br>', $value); |
||
6233 | } |
||
6234 | |||
6235 | //print $type.'-'.$size; |
||
6236 | $out=$value; |
||
6237 | |||
6238 | return $out; |
||
6239 | } |
||
6240 | |||
6241 | |||
6242 | /** |
||
6243 | * Function to show lines of extrafields with output datas |
||
6244 | * |
||
6245 | * @param Extrafields $extrafields Extrafield Object |
||
6246 | * @param string $mode Show output (view) or input (edit) for extrafield |
||
6247 | * @param array $params Optional parameters. Example: array('style'=>'class="oddeven"', 'colspan'=>$colspan) |
||
6248 | * @param string $keysuffix Suffix string to add after name and id of field (can be used to avoid duplicate names) |
||
6249 | * @param string $keyprefix Prefix string to add before name and id of field (can be used to avoid duplicate names) |
||
6250 | * @param string $onetrtd All fields in same tr td |
||
6251 | * @return string |
||
6252 | */ |
||
6253 | function showOptionals($extrafields, $mode='view', $params=null, $keysuffix='', $keyprefix='', $onetrtd=0) |
||
6254 | { |
||
6255 | global $db, $conf, $langs, $action, $form; |
||
6256 | |||
6257 | if (! is_object($form)) $form=new Form($db); |
||
6258 | |||
6259 | $out = ''; |
||
6260 | |||
6261 | if (is_array($extrafields->attributes[$this->table_element]['label']) && count($extrafields->attributes[$this->table_element]['label']) > 0) |
||
6262 | { |
||
6263 | $out .= "\n"; |
||
6264 | $out .= '<!-- showOptionalsInput --> '; |
||
6265 | $out .= "\n"; |
||
6266 | |||
6267 | $e = 0; |
||
6268 | foreach($extrafields->attributes[$this->table_element]['label'] as $key=>$label) |
||
6269 | { |
||
6270 | // Show only the key field in params |
||
6271 | if (is_array($params) && array_key_exists('onlykey',$params) && $key != $params['onlykey']) continue; |
||
6272 | |||
6273 | $enabled = 1; |
||
6274 | if ($enabled && isset($extrafields->attributes[$this->table_element]['list'][$key])) |
||
6275 | { |
||
6276 | $enabled = dol_eval($extrafields->attributes[$this->table_element]['list'][$key], 1); |
||
6277 | } |
||
6278 | |||
6279 | $perms = 1; |
||
6280 | if ($perms && isset($extrafields->attributes[$this->table_element]['perms'][$key])) |
||
6281 | { |
||
6282 | $perms = dol_eval($extrafields->attributes[$this->table_element]['perms'][$key], 1); |
||
6283 | } |
||
6284 | |||
6285 | if (($mode == 'create' || $mode == 'edit') && abs($enabled) != 1 && abs($enabled) != 3) continue; // <> -1 and <> 1 and <> 3 = not visible on forms, only on list |
||
6286 | if (empty($perms)) continue; |
||
6287 | |||
6288 | // Load language if required |
||
6289 | if (! empty($extrafields->attributes[$this->table_element]['langfile'][$key])) $langs->load($extrafields->attributes[$this->table_element]['langfile'][$key]); |
||
6290 | |||
6291 | $colspan='3'; |
||
6292 | if (is_array($params) && count($params)>0) { |
||
6293 | if (array_key_exists('colspan',$params)) { |
||
6294 | $colspan=$params['colspan']; |
||
6295 | } |
||
6296 | } |
||
6297 | |||
6298 | switch($mode) { |
||
6299 | case "view": |
||
6300 | $value=$this->array_options["options_".$key.$keysuffix]; |
||
6301 | break; |
||
6302 | case "edit": |
||
6303 | $getposttemp = GETPOST($keyprefix.'options_'.$key.$keysuffix, 'none'); // GETPOST can get value from GET, POST or setup of default values. |
||
6304 | // GETPOST("options_" . $key) can be 'abc' or array(0=>'abc') |
||
6305 | if (is_array($getposttemp) || $getposttemp != '' || GETPOSTISSET($keyprefix.'options_'.$key.$keysuffix)) |
||
6306 | { |
||
6307 | if (is_array($getposttemp)) { |
||
6308 | // $getposttemp is an array but following code expects a comma separated string |
||
6309 | $value = implode(",", $getposttemp); |
||
6310 | } else { |
||
6311 | $value = $getposttemp; |
||
6312 | } |
||
6313 | } else { |
||
6314 | $value = $this->array_options["options_" . $key]; // No GET, no POST, no default value, so we take value of object. |
||
6315 | } |
||
6316 | //var_dump($keyprefix.' - '.$key.' - '.$keysuffix.' - '.$keyprefix.'options_'.$key.$keysuffix.' - '.$this->array_options["options_".$key.$keysuffix].' - '.$getposttemp.' - '.$value); |
||
6317 | break; |
||
6318 | } |
||
6319 | |||
6320 | if ($extrafields->attributes[$this->table_element]['type'][$key] == 'separate') |
||
6321 | { |
||
6322 | $out .= $extrafields->showSeparator($key, $this); |
||
6323 | } |
||
6324 | else |
||
6325 | { |
||
6326 | $csstyle=''; |
||
6327 | $class=(!empty($extrafields->attributes[$this->table_element]['hidden'][$key]) ? 'hideobject ' : ''); |
||
6328 | if (is_array($params) && count($params)>0) { |
||
6329 | if (array_key_exists('style',$params)) { |
||
6330 | $csstyle=$params['style']; |
||
6331 | } |
||
6332 | } |
||
6333 | |||
6334 | // add html5 elements |
||
6335 | $domData = ' data-element="extrafield"'; |
||
6336 | $domData .= ' data-targetelement="'.$this->element.'"'; |
||
6337 | $domData .= ' data-targetid="'.$this->id.'"'; |
||
6338 | |||
6339 | $html_id = !empty($this->id) ? 'extrarow-'.$this->element.'_'.$key.'_'.$this->id : ''; |
||
6340 | |||
6341 | $out .= '<tr id="'.$html_id.'" '.$csstyle.' class="'.$class.$this->element.'_extras_'.$key.'" '.$domData.' >'; |
||
6342 | |||
6343 | if (! empty($conf->global->MAIN_EXTRAFIELDS_USE_TWO_COLUMS) && ($e % 2) == 0) |
||
6344 | { |
||
6345 | if (! empty($conf->global->MAIN_EXTRAFIELDS_USE_TWO_COLUMS) && ($e % 2) == 0) { $colspan='0'; } |
||
6346 | } |
||
6347 | |||
6348 | if ($action == 'selectlines') { $colspan++; } |
||
6349 | |||
6350 | // Convert date into timestamp format (value in memory must be a timestamp) |
||
6351 | if (in_array($extrafields->attributes[$this->table_element]['type'][$key],array('date','datetime'))) |
||
6352 | { |
||
6353 | $datenotinstring = $this->array_options['options_' . $key]; |
||
6354 | if (! is_numeric($this->array_options['options_' . $key])) // For backward compatibility |
||
6355 | { |
||
6356 | $datenotinstring = $this->db->jdate($datenotinstring); |
||
6357 | } |
||
6358 | $value = GETPOSTISSET($keyprefix.'options_'.$key.$keysuffix)?dol_mktime(GETPOST($keyprefix.'options_'.$key.$keysuffix."hour", 'int', 3), GETPOST($keyprefix.'options_'.$key.$keysuffix."min",'int',3), 0, GETPOST($keyprefix.'options_'.$key.$keysuffix."month",'int',3), GETPOST($keyprefix.'options_'.$key.$keysuffix."day",'int',3), GETPOST($keyprefix.'options_'.$key.$keysuffix."year",'int',3)):$datenotinstring; |
||
6359 | } |
||
6360 | // Convert float submited string into real php numeric (value in memory must be a php numeric) |
||
6361 | if (in_array($extrafields->attributes[$this->table_element]['type'][$key],array('price','double'))) |
||
6362 | { |
||
6363 | $value = GETPOSTISSET($keyprefix.'options_'.$key.$keysuffix)?price2num(GETPOST($keyprefix.'options_'.$key.$keysuffix, 'alpha', 3)):$this->array_options['options_'.$key]; |
||
6364 | } |
||
6365 | |||
6366 | $labeltoshow = $langs->trans($label); |
||
6367 | |||
6368 | $out .= '<td class="titlefield'; |
||
6369 | if (GETPOST('action','none') == 'create') $out.='create'; |
||
6370 | if ($mode != 'view' && ! empty($extrafields->attributes[$this->table_element]['required'][$key])) $out .= ' fieldrequired'; |
||
6371 | $out .= '">'; |
||
6372 | if (! empty($extrafields->attributes[$object->table_element]['help'][$key])) $out .= $form->textwithpicto($labeltoshow, $extrafields->attributes[$object->table_element]['help'][$key]); |
||
6373 | else $out .= $labeltoshow; |
||
6374 | $out .= '</td>'; |
||
6375 | |||
6376 | $html_id = !empty($this->id) ? $this->element.'_extras_'.$key.'_'.$this->id : ''; |
||
6377 | $out .='<td id="'.$html_id.'" class="'.$this->element.'_extras_'.$key.'" '.($colspan?' colspan="'.$colspan.'"':'').'>'; |
||
6378 | |||
6379 | switch($mode) { |
||
6380 | case "view": |
||
6381 | $out .= $extrafields->showOutputField($key, $value); |
||
6382 | break; |
||
6383 | case "edit": |
||
6384 | $out .= $extrafields->showInputField($key, $value, '', $keysuffix, '', 0, $this->id); |
||
6385 | break; |
||
6386 | } |
||
6387 | |||
6388 | $out .= '</td>'; |
||
6389 | |||
6390 | if (! empty($conf->global->MAIN_EXTRAFIELDS_USE_TWO_COLUMS) && (($e % 2) == 1)) $out .= '</tr>'; |
||
6391 | else $out .= '</tr>'; |
||
6392 | $e++; |
||
6393 | } |
||
6394 | } |
||
6395 | $out .= "\n"; |
||
6396 | // Add code to manage list depending on others |
||
6397 | if (! empty($conf->use_javascript_ajax)) { |
||
6398 | $out .= ' |
||
6399 | <script type="text/javascript"> |
||
6400 | jQuery(document).ready(function() { |
||
6401 | function showOptions(child_list, parent_list) |
||
6402 | { |
||
6403 | var val = $("select[name=\"options_"+parent_list+"\"]").val(); |
||
6404 | var parentVal = parent_list + ":" + val; |
||
6405 | if(val > 0) { |
||
6406 | $("select[name=\""+child_list+"\"] option[parent]").hide(); |
||
6407 | $("select[name=\""+child_list+"\"] option[parent=\""+parentVal+"\"]").show(); |
||
6408 | } else { |
||
6409 | $("select[name=\""+child_list+"\"] option").show(); |
||
6410 | } |
||
6411 | } |
||
6412 | function setListDependencies() { |
||
6413 | jQuery("select option[parent]").parent().each(function() { |
||
6414 | var child_list = $(this).attr("name"); |
||
6415 | var parent = $(this).find("option[parent]:first").attr("parent"); |
||
6416 | var infos = parent.split(":"); |
||
6417 | var parent_list = infos[0]; |
||
6418 | $("select[name=\""+parent_list+"\"]").change(function() { |
||
6419 | showOptions(child_list, parent_list); |
||
6420 | }); |
||
6421 | }); |
||
6422 | } |
||
6423 | |||
6424 | setListDependencies(); |
||
6425 | }); |
||
6426 | </script>'."\n"; |
||
6427 | $out .= '<!-- /showOptionalsInput --> '."\n"; |
||
6428 | } |
||
6429 | } |
||
6430 | return $out; |
||
6431 | } |
||
6432 | |||
6433 | |||
6434 | /** |
||
6435 | * Returns the rights used for this class |
||
6436 | * @return stdClass |
||
6437 | */ |
||
6438 | public function getRights() |
||
6439 | { |
||
6440 | global $user; |
||
6441 | |||
6442 | $element = $this->element; |
||
6443 | if ($element == 'facturerec') $element='facture'; |
||
6444 | |||
6445 | return $user->rights->{$element}; |
||
6446 | } |
||
6447 | |||
6448 | /** |
||
6449 | * Function used to replace a thirdparty id with another one. |
||
6450 | * This function is meant to be called from replaceThirdparty with the appropiate tables |
||
6451 | * Column name fk_soc MUST be used to identify thirdparties |
||
6452 | * |
||
6453 | * @param DoliDB $db Database handler |
||
6454 | * @param int $origin_id Old thirdparty id (the thirdparty to delete) |
||
6455 | * @param int $dest_id New thirdparty id (the thirdparty that will received element of the other) |
||
6456 | * @param string[] $tables Tables that need to be changed |
||
6457 | * @param int $ignoreerrors Ignore errors. Return true even if errors. We need this when replacement can fails like for categories (categorie of old thirdparty may already exists on new one) |
||
6458 | * @return bool True if success, False if error |
||
6459 | */ |
||
6460 | public static function commonReplaceThirdparty(DoliDB $db, $origin_id, $dest_id, array $tables, $ignoreerrors=0) |
||
6461 | { |
||
6462 | foreach ($tables as $table) |
||
6463 | { |
||
6464 | $sql = 'UPDATE '.MAIN_DB_PREFIX.$table.' SET fk_soc = '.$dest_id.' WHERE fk_soc = '.$origin_id; |
||
6465 | |||
6466 | if (! $db->query($sql)) |
||
6467 | { |
||
6468 | if ($ignoreerrors) return true; // TODO Not enough. If there is A-B on kept thirdarty and B-C on old one, we must get A-B-C after merge. Not A-B. |
||
6469 | //$this->errors = $db->lasterror(); |
||
6470 | return false; |
||
6471 | } |
||
6472 | } |
||
6473 | |||
6474 | return true; |
||
6475 | } |
||
6476 | |||
6477 | /** |
||
6478 | * Get buy price to use for margin calculation. This function is called when buy price is unknown. |
||
6479 | * Set buy price = sell price if ForceBuyingPriceIfNull configured, |
||
6480 | * else if calculation MARGIN_TYPE = 'costprice' and costprice is defined, use costprice as buyprice |
||
6481 | * else if calculation MARGIN_TYPE = 'pmp' and pmp is calculated, use pmp as buyprice |
||
6482 | * else set min buy price as buy price |
||
6483 | * |
||
6484 | * @param float $unitPrice Product unit price |
||
6485 | * @param float $discountPercent Line discount percent |
||
6486 | * @param int $fk_product Product id |
||
6487 | * @return float <0 if KO, buyprice if OK |
||
6488 | */ |
||
6489 | public function defineBuyPrice($unitPrice = 0.0, $discountPercent = 0.0, $fk_product = 0) |
||
6490 | { |
||
6491 | global $conf; |
||
6492 | |||
6493 | $buyPrice = 0; |
||
6494 | |||
6495 | if (($unitPrice > 0) && (isset($conf->global->ForceBuyingPriceIfNull) && $conf->global->ForceBuyingPriceIfNull == 1)) // In most cases, test here is false |
||
6496 | { |
||
6497 | $buyPrice = $unitPrice * (1 - $discountPercent / 100); |
||
6498 | } |
||
6499 | else |
||
6500 | { |
||
6501 | // Get cost price for margin calculation |
||
6502 | if (! empty($fk_product)) |
||
6503 | { |
||
6504 | if (isset($conf->global->MARGIN_TYPE) && $conf->global->MARGIN_TYPE == 'costprice') |
||
6505 | { |
||
6506 | require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; |
||
6507 | $product = new Product($this->db); |
||
6508 | $result = $product->fetch($fk_product); |
||
6509 | if ($result <= 0) |
||
6510 | { |
||
6511 | $this->errors[] = 'ErrorProductIdDoesNotExists'; |
||
6512 | return -1; |
||
6513 | } |
||
6514 | if ($product->cost_price > 0) |
||
6515 | { |
||
6516 | $buyPrice = $product->cost_price; |
||
6517 | } |
||
6518 | else if ($product->pmp > 0) |
||
6519 | { |
||
6520 | $buyPrice = $product->pmp; |
||
6521 | } |
||
6522 | } |
||
6523 | else if (isset($conf->global->MARGIN_TYPE) && $conf->global->MARGIN_TYPE == 'pmp') |
||
6524 | { |
||
6525 | require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; |
||
6526 | $product = new Product($this->db); |
||
6527 | $result = $product->fetch($fk_product); |
||
6528 | if ($result <= 0) |
||
6529 | { |
||
6530 | $this->errors[] = 'ErrorProductIdDoesNotExists'; |
||
6531 | return -1; |
||
6532 | } |
||
6533 | if ($product->pmp > 0) |
||
6534 | { |
||
6535 | $buyPrice = $product->pmp; |
||
6536 | } |
||
6537 | } |
||
6538 | |||
6539 | if (empty($buyPrice) && isset($conf->global->MARGIN_TYPE) && in_array($conf->global->MARGIN_TYPE, array('1','pmp','costprice'))) |
||
6540 | { |
||
6541 | require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php'; |
||
6542 | $productFournisseur = new ProductFournisseur($this->db); |
||
6543 | if (($result = $productFournisseur->find_min_price_product_fournisseur($fk_product)) > 0) |
||
6544 | { |
||
6545 | $buyPrice = $productFournisseur->fourn_unitprice; |
||
6546 | } |
||
6547 | else if ($result < 0) |
||
6548 | { |
||
6549 | $this->errors[] = $productFournisseur->error; |
||
6550 | return -2; |
||
6551 | } |
||
6552 | } |
||
6553 | } |
||
6554 | } |
||
6555 | return $buyPrice; |
||
6556 | } |
||
6557 | |||
6558 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.NotCamelCaps |
||
6559 | /** |
||
6560 | * Show photos of an object (nbmax maximum), into several columns |
||
6561 | * |
||
6562 | * @param string $modulepart 'product', 'ticket', ... |
||
6563 | * @param string $sdir Directory to scan (full absolute path) |
||
6564 | * @param int $size 0=original size, 1='small' use thumbnail if possible |
||
6565 | * @param int $nbmax Nombre maximum de photos (0=pas de max) |
||
6566 | * @param int $nbbyrow Number of image per line or -1 to use div. Used only if size=1. |
||
6567 | * @param int $showfilename 1=Show filename |
||
6568 | * @param int $showaction 1=Show icon with action links (resize, delete) |
||
6569 | * @param int $maxHeight Max height of original image when size='small' (so we can use original even if small requested). If 0, always use 'small' thumb image. |
||
6570 | * @param int $maxWidth Max width of original image when size='small' |
||
6571 | * @param int $nolink Do not add a href link to view enlarged imaged into a new tab |
||
6572 | * @param int $notitle Do not add title tag on image |
||
6573 | * @param int $usesharelink Use the public shared link of image (if not available, the 'nophoto' image will be shown instead) |
||
6574 | * @return string Html code to show photo. Number of photos shown is saved in this->nbphoto |
||
6575 | */ |
||
6576 | function show_photos($modulepart, $sdir, $size=0, $nbmax=0, $nbbyrow=5, $showfilename=0, $showaction=0, $maxHeight=120, $maxWidth=160, $nolink=0, $notitle=0, $usesharelink=0) |
||
6577 | { |
||
6578 | // phpcs:enable |
||
6579 | global $conf,$user,$langs; |
||
6580 | |||
6581 | include_once DOL_DOCUMENT_ROOT .'/core/lib/files.lib.php'; |
||
6582 | include_once DOL_DOCUMENT_ROOT .'/core/lib/images.lib.php'; |
||
6583 | |||
6584 | $sortfield='position_name'; |
||
6585 | $sortorder='asc'; |
||
6586 | |||
6587 | $dir = $sdir . '/'; |
||
6588 | $pdir = '/'; |
||
6589 | if ($modulepart == 'ticket') |
||
6590 | { |
||
6591 | $dir .= get_exdir(0, 0, 0, 0, $this, $modulepart).$this->track_id.'/'; |
||
6592 | $pdir .= get_exdir(0, 0, 0, 0, $this, $modulepart).$this->track_id.'/'; |
||
6593 | } |
||
6594 | else |
||
6595 | { |
||
6596 | $dir .= get_exdir(0, 0, 0, 0, $this, $modulepart).$this->ref.'/'; |
||
6597 | $pdir .= get_exdir(0, 0, 0, 0, $this, $modulepart).$this->ref.'/'; |
||
6598 | } |
||
6599 | |||
6600 | // For backward compatibility |
||
6601 | if ($modulepart == 'product' && ! empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) |
||
6602 | { |
||
6603 | $dir = $sdir . '/'. get_exdir($this->id,2,0,0,$this,$modulepart) . $this->id ."/photos/"; |
||
6604 | $pdir = '/' . get_exdir($this->id,2,0,0,$this,$modulepart) . $this->id ."/photos/"; |
||
6605 | } |
||
6606 | |||
6607 | // Defined relative dir to DOL_DATA_ROOT |
||
6608 | $relativedir = ''; |
||
6609 | if ($dir) |
||
6610 | { |
||
6611 | $relativedir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $dir); |
||
6612 | $relativedir = preg_replace('/^[\\/]/','',$relativedir); |
||
6613 | $relativedir = preg_replace('/[\\/]$/','',$relativedir); |
||
6614 | } |
||
6615 | |||
6616 | $dirthumb = $dir.'thumbs/'; |
||
6617 | $pdirthumb = $pdir.'thumbs/'; |
||
6618 | |||
6619 | $return ='<!-- Photo -->'."\n"; |
||
6620 | $nbphoto=0; |
||
6621 | |||
6622 | $filearray=dol_dir_list($dir,"files",0,'','(\.meta|_preview.*\.png)$',$sortfield,(strtolower($sortorder)=='desc'?SORT_DESC:SORT_ASC),1); |
||
6623 | |||
6624 | /*if (! empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) // For backward compatiblity, we scan also old dirs |
||
6625 | { |
||
6626 | $filearrayold=dol_dir_list($dirold,"files",0,'','(\.meta|_preview.*\.png)$',$sortfield,(strtolower($sortorder)=='desc'?SORT_DESC:SORT_ASC),1); |
||
6627 | $filearray=array_merge($filearray, $filearrayold); |
||
6628 | }*/ |
||
6629 | |||
6630 | completeFileArrayWithDatabaseInfo($filearray, $relativedir); |
||
6631 | |||
6632 | if (count($filearray)) |
||
6633 | { |
||
6634 | if ($sortfield && $sortorder) |
||
6635 | { |
||
6636 | $filearray=dol_sort_array($filearray, $sortfield, $sortorder); |
||
6637 | } |
||
6638 | |||
6639 | foreach($filearray as $key => $val) |
||
6640 | { |
||
6641 | $photo=''; |
||
6642 | $file = $val['name']; |
||
6643 | |||
6644 | //if (! utf8_check($file)) $file=utf8_encode($file); // To be sure file is stored in UTF8 in memory |
||
6645 | |||
6646 | //if (dol_is_file($dir.$file) && image_format_supported($file) >= 0) |
||
6647 | if (image_format_supported($file) >= 0) |
||
6648 | { |
||
6649 | $nbphoto++; |
||
6650 | $photo = $file; |
||
6651 | $viewfilename = $file; |
||
6652 | |||
6653 | if ($size == 1 || $size == 'small') { // Format vignette |
||
6654 | |||
6655 | // Find name of thumb file |
||
6656 | $photo_vignette=basename(getImageFileNameForSize($dir.$file, '_small')); |
||
6657 | if (! dol_is_file($dirthumb.$photo_vignette)) $photo_vignette=''; |
||
6658 | |||
6659 | // Get filesize of original file |
||
6660 | $imgarray=dol_getImageSize($dir.$photo); |
||
6661 | |||
6662 | if ($nbbyrow > 0) |
||
6663 | { |
||
6664 | if ($nbphoto == 1) $return.= '<table width="100%" valign="top" align="center" border="0" cellpadding="2" cellspacing="2">'; |
||
6665 | |||
6666 | if ($nbphoto % $nbbyrow == 1) $return.= '<tr align=center valign=middle border=1>'; |
||
6667 | $return.= '<td width="'.ceil(100/$nbbyrow).'%" class="photo">'; |
||
6668 | } |
||
6669 | else if ($nbbyrow < 0) $return .= '<div class="inline-block">'; |
||
6670 | |||
6671 | $return.= "\n"; |
||
6672 | |||
6673 | $relativefile=preg_replace('/^\//', '', $pdir.$photo); |
||
6674 | if (empty($nolink)) |
||
6675 | { |
||
6676 | $urladvanced=getAdvancedPreviewUrl($modulepart, $relativefile, 0, 'entity='.$this->entity); |
||
6677 | if ($urladvanced) $return.='<a href="'.$urladvanced.'">'; |
||
6678 | else $return.= '<a href="'.DOL_URL_ROOT.'/viewimage.php?modulepart='.$modulepart.'&entity='.$this->entity.'&file='.urlencode($pdir.$photo).'" class="aphoto" target="_blank">'; |
||
6679 | } |
||
6680 | |||
6681 | // Show image (width height=$maxHeight) |
||
6682 | // Si fichier vignette disponible et image source trop grande, on utilise la vignette, sinon on utilise photo origine |
||
6683 | $alt=$langs->transnoentitiesnoconv('File').': '.$relativefile; |
||
6684 | $alt.=' - '.$langs->transnoentitiesnoconv('Size').': '.$imgarray['width'].'x'.$imgarray['height']; |
||
6685 | if ($notitle) $alt=''; |
||
6686 | |||
6687 | if ($usesharelink) |
||
6688 | { |
||
6689 | if ($val['share']) |
||
6690 | { |
||
6691 | if (empty($maxHeight) || $photo_vignette && $imgarray['height'] > $maxHeight) |
||
6692 | { |
||
6693 | $return.= '<!-- Show original file (thumb not yet available with shared links) -->'; |
||
6694 | $return.= '<img class="photo photowithmargin" border="0" height="'.$maxHeight.'" src="'.DOL_URL_ROOT.'/viewimage.php?hashp='.urlencode($val['share']).'" title="'.dol_escape_htmltag($alt).'">'; |
||
6695 | } |
||
6696 | else { |
||
6697 | $return.= '<!-- Show original file -->'; |
||
6698 | $return.= '<img class="photo photowithmargin" border="0" height="'.$maxHeight.'" src="'.DOL_URL_ROOT.'/viewimage.php?hashp='.urlencode($val['share']).'" title="'.dol_escape_htmltag($alt).'">'; |
||
6699 | } |
||
6700 | } |
||
6701 | else |
||
6702 | { |
||
6703 | $return.= '<!-- Show nophoto file (because file is not shared) -->'; |
||
6704 | $return.= '<img class="photo photowithmargin" border="0" height="'.$maxHeight.'" src="'.DOL_URL_ROOT.'/public/theme/common/nophoto.png" title="'.dol_escape_htmltag($alt).'">'; |
||
6705 | } |
||
6706 | } |
||
6707 | else |
||
6708 | { |
||
6709 | if (empty($maxHeight) || $photo_vignette && $imgarray['height'] > $maxHeight) |
||
6710 | { |
||
6711 | $return.= '<!-- Show thumb -->'; |
||
6712 | $return.= '<img class="photo photowithmargin" border="0" height="'.$maxHeight.'" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart='.$modulepart.'&entity='.$this->entity.'&file='.urlencode($pdirthumb.$photo_vignette).'" title="'.dol_escape_htmltag($alt).'">'; |
||
6713 | } |
||
6714 | else { |
||
6715 | $return.= '<!-- Show original file -->'; |
||
6716 | $return.= '<img class="photo photowithmargin" border="0" height="'.$maxHeight.'" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart='.$modulepart.'&entity='.$this->entity.'&file='.urlencode($pdir.$photo).'" title="'.dol_escape_htmltag($alt).'">'; |
||
6717 | } |
||
6718 | } |
||
6719 | |||
6720 | if (empty($nolink)) $return.= '</a>'; |
||
6721 | $return.="\n"; |
||
6722 | |||
6723 | if ($showfilename) $return.= '<br>'.$viewfilename; |
||
6724 | if ($showaction) |
||
6725 | { |
||
6726 | $return.= '<br>'; |
||
6727 | // On propose la generation de la vignette si elle n'existe pas et si la taille est superieure aux limites |
||
6728 | if ($photo_vignette && (image_format_supported($photo) > 0) && ($this->imgWidth > $maxWidth || $this->imgHeight > $maxHeight)) |
||
6729 | { |
||
6730 | $return.= '<a href="'.$_SERVER["PHP_SELF"].'?id='.$this->id.'&action=addthumb&file='.urlencode($pdir.$viewfilename).'">'.img_picto($langs->trans('GenerateThumb'),'refresh').' </a>'; |
||
6731 | } |
||
6732 | // Special cas for product |
||
6733 | if ($modulepart == 'product' && ($user->rights->produit->creer || $user->rights->service->creer)) |
||
6734 | { |
||
6735 | // Link to resize |
||
6736 | $return.= '<a href="'.DOL_URL_ROOT.'/core/photos_resize.php?modulepart='.urlencode('produit|service').'&id='.$this->id.'&file='.urlencode($pdir.$viewfilename).'" title="'.dol_escape_htmltag($langs->trans("Resize")).'">'.img_picto($langs->trans("Resize"), 'resize', '').'</a> '; |
||
6737 | |||
6738 | // Link to delete |
||
6739 | $return.= '<a href="'.$_SERVER["PHP_SELF"].'?id='.$this->id.'&action=delete&file='.urlencode($pdir.$viewfilename).'">'; |
||
6740 | $return.= img_delete().'</a>'; |
||
6741 | } |
||
6742 | } |
||
6743 | $return.= "\n"; |
||
6744 | |||
6745 | if ($nbbyrow > 0) |
||
6746 | { |
||
6747 | $return.= '</td>'; |
||
6748 | if (($nbphoto % $nbbyrow) == 0) $return.= '</tr>'; |
||
6749 | } |
||
6750 | else if ($nbbyrow < 0) $return.='</div>'; |
||
6751 | } |
||
6752 | |||
6753 | if (empty($size)) { // Format origine |
||
6754 | $return.= '<img class="photo photowithmargin" border="0" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart='.$modulepart.'&entity='.$this->entity.'&file='.urlencode($pdir.$photo).'">'; |
||
6755 | |||
6756 | if ($showfilename) $return.= '<br>'.$viewfilename; |
||
6757 | if ($showaction) |
||
6758 | { |
||
6759 | // Special case for product |
||
6760 | if ($modulepart == 'product' && ($user->rights->produit->creer || $user->rights->service->creer)) |
||
6761 | { |
||
6762 | // Link to resize |
||
6763 | $return.= '<a href="'.DOL_URL_ROOT.'/core/photos_resize.php?modulepart='.urlencode('produit|service').'&id='.$this->id.'&file='.urlencode($pdir.$viewfilename).'" title="'.dol_escape_htmltag($langs->trans("Resize")).'">'.img_picto($langs->trans("Resize"), 'resize', '').'</a> '; |
||
6764 | |||
6765 | // Link to delete |
||
6766 | $return.= '<a href="'.$_SERVER["PHP_SELF"].'?id='.$this->id.'&action=delete&file='.urlencode($pdir.$viewfilename).'">'; |
||
6767 | $return.= img_delete().'</a>'; |
||
6768 | } |
||
6769 | } |
||
6770 | } |
||
6771 | |||
6772 | // On continue ou on arrete de boucler ? |
||
6773 | if ($nbmax && $nbphoto >= $nbmax) break; |
||
6774 | } |
||
6775 | } |
||
6776 | |||
6777 | if ($size==1 || $size=='small') |
||
6778 | { |
||
6779 | if ($nbbyrow > 0) |
||
6780 | { |
||
6781 | // Ferme tableau |
||
6782 | while ($nbphoto % $nbbyrow) |
||
6783 | { |
||
6784 | $return.= '<td width="'.ceil(100/$nbbyrow).'%"> </td>'; |
||
6785 | $nbphoto++; |
||
6786 | } |
||
6787 | |||
6788 | if ($nbphoto) $return.= '</table>'; |
||
6789 | } |
||
6790 | } |
||
6791 | } |
||
6792 | |||
6793 | $this->nbphoto = $nbphoto; |
||
6794 | |||
6795 | return $return; |
||
6796 | } |
||
6797 | |||
6798 | |||
6799 | /** |
||
6800 | * Function test if type is array |
||
6801 | * |
||
6802 | * @param array $info content informations of field |
||
6803 | * @return bool |
||
6804 | */ |
||
6805 | protected function isArray($info) |
||
6806 | { |
||
6807 | if(is_array($info)) |
||
6808 | { |
||
6809 | if(isset($info['type']) && $info['type']=='array') return true; |
||
6810 | else return false; |
||
6811 | } |
||
6812 | else return false; |
||
6813 | } |
||
6814 | |||
6815 | /** |
||
6816 | * Function test if type is null |
||
6817 | * |
||
6818 | * @param array $info content informations of field |
||
6819 | * @return bool |
||
6820 | */ |
||
6821 | protected function isNull($info) |
||
6822 | { |
||
6823 | if(is_array($info)) |
||
6824 | { |
||
6825 | if(isset($info['type']) && $info['type']=='null') return true; |
||
6826 | else return false; |
||
6827 | } |
||
6828 | else return false; |
||
6829 | } |
||
6830 | |||
6831 | /** |
||
6832 | * Function test if type is date |
||
6833 | * |
||
6834 | * @param array $info content informations of field |
||
6835 | * @return bool |
||
6836 | */ |
||
6837 | public function isDate($info) |
||
6838 | { |
||
6839 | if(isset($info['type']) && ($info['type']=='date' || $info['type']=='datetime' || $info['type']=='timestamp')) return true; |
||
6840 | else return false; |
||
6841 | } |
||
6842 | |||
6843 | /** |
||
6844 | * Function test if type is integer |
||
6845 | * |
||
6846 | * @param array $info content informations of field |
||
6847 | * @return bool |
||
6848 | */ |
||
6849 | public function isInt($info) |
||
6850 | { |
||
6851 | if(is_array($info)) |
||
6852 | { |
||
6853 | if(isset($info['type']) && ($info['type']=='int' || preg_match('/^integer/i',$info['type']) ) ) return true; |
||
6854 | else return false; |
||
6855 | } |
||
6856 | else return false; |
||
6857 | } |
||
6858 | |||
6859 | /** |
||
6860 | * Function test if type is float |
||
6861 | * |
||
6862 | * @param array $info content informations of field |
||
6863 | * @return bool |
||
6864 | */ |
||
6865 | public function isFloat($info) |
||
6866 | { |
||
6867 | if(is_array($info)) |
||
6868 | { |
||
6869 | if (isset($info['type']) && (preg_match('/^(double|real)/i', $info['type']))) return true; |
||
6870 | else return false; |
||
6871 | } |
||
6872 | else return false; |
||
6873 | } |
||
6874 | |||
6875 | /** |
||
6876 | * Function test if type is text |
||
6877 | * |
||
6878 | * @param array $info content informations of field |
||
6879 | * @return bool |
||
6880 | */ |
||
6881 | public function isText($info) |
||
6882 | { |
||
6883 | if(is_array($info)) |
||
6884 | { |
||
6885 | if(isset($info['type']) && $info['type']=='text') return true; |
||
6886 | else return false; |
||
6887 | } |
||
6888 | else return false; |
||
6889 | } |
||
6890 | |||
6891 | /** |
||
6892 | * Function test if is indexed |
||
6893 | * |
||
6894 | * @param array $info content informations of field |
||
6895 | * @return bool |
||
6896 | */ |
||
6897 | protected function isIndex($info) |
||
6898 | { |
||
6899 | if(is_array($info)) |
||
6900 | { |
||
6901 | if(isset($info['index']) && $info['index']==true) return true; |
||
6902 | else return false; |
||
6903 | } |
||
6904 | else return false; |
||
6905 | } |
||
6906 | |||
6907 | /** |
||
6908 | * Function to prepare the values to insert. |
||
6909 | * Note $this->${field} are set by the page that make the createCommon or the updateCommon. |
||
6910 | * |
||
6911 | * @return array |
||
6912 | */ |
||
6913 | protected function setSaveQuery() |
||
6914 | { |
||
6915 | global $conf; |
||
6916 | |||
6917 | $queryarray=array(); |
||
6918 | foreach ($this->fields as $field=>$info) // Loop on definition of fields |
||
6919 | { |
||
6920 | // Depending on field type ('datetime', ...) |
||
6921 | if($this->isDate($info)) |
||
6922 | { |
||
6923 | if(empty($this->{$field})) |
||
6924 | { |
||
6925 | $queryarray[$field] = null; |
||
6926 | } |
||
6927 | else |
||
6928 | { |
||
6929 | $queryarray[$field] = $this->db->idate($this->{$field}); |
||
6930 | } |
||
6931 | } |
||
6932 | else if($this->isArray($info)) |
||
6933 | { |
||
6934 | if(! empty($this->{$field})) { |
||
6935 | if(! is_array($this->{$field})) { |
||
6936 | $this->{$field} = array($this->{$field}); |
||
6937 | } |
||
6938 | $queryarray[$field] = serialize($this->{$field}); |
||
6939 | } else { |
||
6940 | $queryarray[$field] = null; |
||
6941 | } |
||
6942 | } |
||
6943 | else if($this->isInt($info)) |
||
6944 | { |
||
6945 | if ($field == 'entity' && is_null($this->{$field})) $queryarray[$field]=$conf->entity; |
||
6946 | else |
||
6947 | { |
||
6948 | $queryarray[$field] = (int) price2num($this->{$field}); |
||
6949 | if (empty($queryarray[$field])) $queryarray[$field]=0; // May be reset to null later if property 'notnull' is -1 for this field. |
||
6950 | } |
||
6951 | } |
||
6952 | else if($this->isFloat($info)) |
||
6953 | { |
||
6954 | $queryarray[$field] = (double) price2num($this->{$field}); |
||
6955 | if (empty($queryarray[$field])) $queryarray[$field]=0; |
||
6956 | } |
||
6957 | else |
||
6958 | { |
||
6959 | $queryarray[$field] = $this->{$field}; |
||
6960 | } |
||
6961 | |||
6962 | if ($info['type'] == 'timestamp' && empty($queryarray[$field])) unset($queryarray[$field]); |
||
6963 | if (! empty($info['notnull']) && $info['notnull'] == -1 && empty($queryarray[$field])) $queryarray[$field] = null; |
||
6964 | } |
||
6965 | |||
6966 | return $queryarray; |
||
6967 | } |
||
6968 | |||
6969 | /** |
||
6970 | * Function to load data from a SQL pointer into properties of current object $this |
||
6971 | * |
||
6972 | * @param stdClass $obj Contain data of object from database |
||
6973 | * @return void |
||
6974 | */ |
||
6975 | protected function setVarsFromFetchObj(&$obj) |
||
6976 | { |
||
6977 | foreach ($this->fields as $field => $info) |
||
6978 | { |
||
6979 | if($this->isDate($info)) |
||
6980 | { |
||
6981 | if(empty($obj->{$field}) || $obj->{$field} === '0000-00-00 00:00:00' || $obj->{$field} === '1000-01-01 00:00:00') $this->{$field} = 0; |
||
6982 | else $this->{$field} = strtotime($obj->{$field}); |
||
6983 | } |
||
6984 | elseif($this->isArray($info)) |
||
6985 | { |
||
6986 | if(! empty($obj->{$field})) { |
||
6987 | $this->{$field} = @unserialize($obj->{$field}); |
||
6988 | // Hack for data not in UTF8 |
||
6989 | if($this->{$field } === false) @unserialize(utf8_decode($obj->{$field})); |
||
6990 | } else { |
||
6991 | $this->{$field} = array(); |
||
6992 | } |
||
6993 | } |
||
6994 | elseif($this->isInt($info)) |
||
6995 | { |
||
6996 | if ($field == 'rowid') $this->id = (int) $obj->{$field}; |
||
6997 | else $this->{$field} = (int) $obj->{$field}; |
||
6998 | } |
||
6999 | elseif($this->isFloat($info)) |
||
7000 | { |
||
7001 | $this->{$field} = (double) $obj->{$field}; |
||
7002 | } |
||
7003 | elseif($this->isNull($info)) |
||
7004 | { |
||
7005 | $val = $obj->{$field}; |
||
7006 | // zero is not null |
||
7007 | $this->{$field} = (is_null($val) || (empty($val) && $val!==0 && $val!=='0') ? null : $val); |
||
7008 | } |
||
7009 | else |
||
7010 | { |
||
7011 | $this->{$field} = $obj->{$field}; |
||
7012 | } |
||
7013 | } |
||
7014 | |||
7015 | // If there is no 'ref' field, we force property ->ref to ->id for a better compatibility with common functions. |
||
7016 | if (! isset($this->fields['ref']) && isset($this->id)) $this->ref = $this->id; |
||
7017 | } |
||
7018 | |||
7019 | /** |
||
7020 | * Function to concat keys of fields |
||
7021 | * |
||
7022 | * @return string |
||
7023 | */ |
||
7024 | protected function getFieldList() |
||
7025 | { |
||
7026 | $keys = array_keys($this->fields); |
||
7027 | return implode(',', $keys); |
||
7028 | } |
||
7029 | |||
7030 | /** |
||
7031 | * Add quote to field value if necessary |
||
7032 | * |
||
7033 | * @param string|int $value Value to protect |
||
7034 | * @param array $fieldsentry Properties of field |
||
7035 | * @return string |
||
7036 | */ |
||
7037 | protected function quote($value, $fieldsentry) |
||
7038 | { |
||
7039 | if (is_null($value)) return 'NULL'; |
||
7040 | else if (preg_match('/^(int|double|real)/i', $fieldsentry['type'])) return $this->db->escape("$value"); |
||
7041 | else return "'".$this->db->escape($value)."'"; |
||
7042 | } |
||
7043 | |||
7044 | |||
7045 | /** |
||
7046 | * Create object into database |
||
7047 | * |
||
7048 | * @param User $user User that creates |
||
7049 | * @param bool $notrigger false=launch triggers after, true=disable triggers |
||
7050 | * @return int <0 if KO, Id of created object if OK |
||
7051 | */ |
||
7052 | public function createCommon(User $user, $notrigger = false) |
||
7053 | { |
||
7054 | global $langs; |
||
7055 | |||
7056 | $error = 0; |
||
7057 | |||
7058 | $now=dol_now(); |
||
7059 | |||
7060 | $fieldvalues = $this->setSaveQuery(); |
||
7061 | if (array_key_exists('date_creation', $fieldvalues) && empty($fieldvalues['date_creation'])) $fieldvalues['date_creation']=$this->db->idate($now); |
||
7062 | if (array_key_exists('fk_user_creat', $fieldvalues) && ! ($fieldvalues['fk_user_creat'] > 0)) $fieldvalues['fk_user_creat']=$user->id; |
||
7063 | unset($fieldvalues['rowid']); // The field 'rowid' is reserved field name for autoincrement field so we don't need it into insert. |
||
7064 | |||
7065 | $keys=array(); |
||
7066 | $values = array(); |
||
7067 | foreach ($fieldvalues as $k => $v) { |
||
7068 | $keys[$k] = $k; |
||
7069 | $value = $this->fields[$k]; |
||
7070 | $values[$k] = $this->quote($v, $value); |
||
7071 | } |
||
7072 | |||
7073 | // Clean and check mandatory |
||
7074 | foreach($keys as $key) |
||
7075 | { |
||
7076 | // If field is an implicit foreign key field |
||
7077 | if (preg_match('/^integer:/i', $this->fields[$key]['type']) && $values[$key] == '-1') $values[$key]=''; |
||
7078 | if (! empty($this->fields[$key]['foreignkey']) && $values[$key] == '-1') $values[$key]=''; |
||
7079 | |||
7080 | //var_dump($key.'-'.$values[$key].'-'.($this->fields[$key]['notnull'] == 1)); |
||
7081 | if (isset($this->fields[$key]['notnull']) && $this->fields[$key]['notnull'] == 1 && ! isset($values[$key]) && is_null($val['default'])) |
||
7082 | { |
||
7083 | $error++; |
||
7084 | $this->errors[]=$langs->trans("ErrorFieldRequired", $this->fields[$key]['label']); |
||
7085 | } |
||
7086 | |||
7087 | // If field is an implicit foreign key field |
||
7088 | if (preg_match('/^integer:/i', $this->fields[$key]['type']) && empty($values[$key])) $values[$key]='null'; |
||
7089 | if (! empty($this->fields[$key]['foreignkey']) && empty($values[$key])) $values[$key]='null'; |
||
7090 | } |
||
7091 | |||
7092 | if ($error) return -1; |
||
7093 | |||
7094 | $this->db->begin(); |
||
7095 | |||
7096 | if (! $error) |
||
7097 | { |
||
7098 | $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element; |
||
7099 | $sql.= ' ('.implode( ", ", $keys ).')'; |
||
7100 | $sql.= ' VALUES ('.implode( ", ", $values ).')'; |
||
7101 | |||
7102 | $res = $this->db->query($sql); |
||
7103 | if ($res===false) { |
||
7104 | $error++; |
||
7105 | $this->errors[] = $this->db->lasterror(); |
||
7106 | } |
||
7107 | } |
||
7108 | |||
7109 | if (! $error) |
||
7110 | { |
||
7111 | $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . $this->table_element); |
||
7112 | } |
||
7113 | |||
7114 | // Create extrafields |
||
7115 | if (! $error) |
||
7116 | { |
||
7117 | $result=$this->insertExtraFields(); |
||
7118 | if ($result < 0) $error++; |
||
7119 | } |
||
7120 | |||
7121 | // Triggers |
||
7122 | if (! $error && ! $notrigger) |
||
7123 | { |
||
7124 | // Call triggers |
||
7125 | $result=$this->call_trigger(strtoupper(get_class($this)).'_CREATE',$user); |
||
7126 | if ($result < 0) { $error++; } |
||
7127 | // End call triggers |
||
7128 | } |
||
7129 | |||
7130 | // Commit or rollback |
||
7131 | if ($error) { |
||
7132 | $this->db->rollback(); |
||
7133 | return -1; |
||
7134 | } else { |
||
7135 | $this->db->commit(); |
||
7136 | return $this->id; |
||
7137 | } |
||
7138 | } |
||
7139 | |||
7140 | |||
7141 | /** |
||
7142 | * Load object in memory from the database |
||
7143 | * |
||
7144 | * @param int $id Id object |
||
7145 | * @param string $ref Ref |
||
7146 | * @param string $morewhere More SQL filters (' AND ...') |
||
7147 | * @return int <0 if KO, 0 if not found, >0 if OK |
||
7148 | */ |
||
7149 | public function fetchCommon($id, $ref = null, $morewhere = '') |
||
7150 | { |
||
7151 | if (empty($id) && empty($ref) && empty($morewhere)) return -1; |
||
7152 | |||
7153 | $sql = 'SELECT '.$this->getFieldList(); |
||
7154 | $sql.= ' FROM '.MAIN_DB_PREFIX.$this->table_element; |
||
7155 | |||
7156 | if (!empty($id)) $sql.= ' WHERE rowid = '.$id; |
||
7157 | elseif (!empty($ref)) $sql.= " WHERE ref = ".$this->quote($ref, $this->fields['ref']); |
||
7158 | else $sql.=' WHERE 1 = 1'; // usage with empty id and empty ref is very rare |
||
7159 | if ($morewhere) $sql.= $morewhere; |
||
7160 | $sql.=' LIMIT 1'; // This is a fetch, to be sure to get only one record |
||
7161 | |||
7162 | $res = $this->db->query($sql); |
||
7163 | if ($res) |
||
7164 | { |
||
7165 | $obj = $this->db->fetch_object($res); |
||
7166 | if ($obj) |
||
7167 | { |
||
7168 | $this->setVarsFromFetchObj($obj); |
||
7169 | return $this->id; |
||
7170 | } |
||
7171 | else |
||
7172 | { |
||
7173 | return 0; |
||
7174 | } |
||
7175 | } |
||
7176 | else |
||
7177 | { |
||
7178 | $this->error = $this->db->lasterror(); |
||
7179 | $this->errors[] = $this->error; |
||
7180 | return -1; |
||
7181 | } |
||
7182 | } |
||
7183 | |||
7184 | /** |
||
7185 | * Update object into database |
||
7186 | * |
||
7187 | * @param User $user User that modifies |
||
7188 | * @param bool $notrigger false=launch triggers after, true=disable triggers |
||
7189 | * @return int <0 if KO, >0 if OK |
||
7190 | */ |
||
7191 | public function updateCommon(User $user, $notrigger = false) |
||
7192 | { |
||
7193 | global $conf, $langs; |
||
7194 | |||
7195 | $error = 0; |
||
7196 | |||
7197 | $now=dol_now(); |
||
7198 | |||
7199 | $fieldvalues = $this->setSaveQuery(); |
||
7200 | if (array_key_exists('date_modification', $fieldvalues) && empty($fieldvalues['date_modification'])) $fieldvalues['date_modification']=$this->db->idate($now); |
||
7201 | if (array_key_exists('fk_user_modif', $fieldvalues) && ! ($fieldvalues['fk_user_modif'] > 0)) $fieldvalues['fk_user_modif']=$user->id; |
||
7202 | unset($fieldvalues['rowid']); // The field 'rowid' is reserved field name for autoincrement field so we don't need it into update. |
||
7203 | |||
7204 | $keys=array(); |
||
7205 | $values = array(); |
||
7206 | foreach ($fieldvalues as $k => $v) { |
||
7207 | $keys[$k] = $k; |
||
7208 | $value = $this->fields[$k]; |
||
7209 | $values[$k] = $this->quote($v, $value); |
||
7210 | $tmp[] = $k.'='.$this->quote($v, $this->fields[$k]); |
||
7211 | } |
||
7212 | |||
7213 | // Clean and check mandatory |
||
7214 | foreach($keys as $key) |
||
7215 | { |
||
7216 | if (preg_match('/^integer:/i', $this->fields[$key]['type']) && $values[$key] == '-1') $values[$key]=''; // This is an implicit foreign key field |
||
7217 | if (! empty($this->fields[$key]['foreignkey']) && $values[$key] == '-1') $values[$key]=''; // This is an explicit foreign key field |
||
7218 | |||
7219 | //var_dump($key.'-'.$values[$key].'-'.($this->fields[$key]['notnull'] == 1)); |
||
7220 | /* |
||
7221 | if ($this->fields[$key]['notnull'] == 1 && empty($values[$key])) |
||
7222 | { |
||
7223 | $error++; |
||
7224 | $this->errors[]=$langs->trans("ErrorFieldRequired", $this->fields[$key]['label']); |
||
7225 | }*/ |
||
7226 | } |
||
7227 | |||
7228 | $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element.' SET '.implode( ',', $tmp ).' WHERE rowid='.$this->id ; |
||
7229 | |||
7230 | $this->db->begin(); |
||
7231 | if (! $error) |
||
7232 | { |
||
7233 | $res = $this->db->query($sql); |
||
7234 | if ($res===false) |
||
7235 | { |
||
7236 | $error++; |
||
7237 | $this->errors[] = $this->db->lasterror(); |
||
7238 | } |
||
7239 | } |
||
7240 | |||
7241 | // Update extrafield |
||
7242 | if (! $error && empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && is_array($this->array_options) && count($this->array_options)>0) |
||
7243 | { |
||
7244 | $result=$this->insertExtraFields(); |
||
7245 | if ($result < 0) |
||
7246 | { |
||
7247 | $error++; |
||
7248 | } |
||
7249 | } |
||
7250 | |||
7251 | // Triggers |
||
7252 | if (! $error && ! $notrigger) |
||
7253 | { |
||
7254 | // Call triggers |
||
7255 | $result=$this->call_trigger(strtoupper(get_class($this)).'_MODIFY',$user); |
||
7256 | if ($result < 0) { $error++; } //Do also here what you must do to rollback action if trigger fail |
||
7257 | // End call triggers |
||
7258 | } |
||
7259 | |||
7260 | // Commit or rollback |
||
7261 | if ($error) { |
||
7262 | $this->db->rollback(); |
||
7263 | return -1; |
||
7264 | } else { |
||
7265 | $this->db->commit(); |
||
7266 | return $this->id; |
||
7267 | } |
||
7268 | } |
||
7269 | |||
7270 | /** |
||
7271 | * Delete object in database |
||
7272 | * |
||
7273 | * @param User $user User that deletes |
||
7274 | * @param bool $notrigger false=launch triggers after, true=disable triggers |
||
7275 | * @param int $forcechilddeletion 0=no, 1=Force deletion of children |
||
7276 | * @return int <=0 if KO, >0 if OK |
||
7277 | */ |
||
7278 | public function deleteCommon(User $user, $notrigger=false, $forcechilddeletion=0) |
||
7279 | { |
||
7280 | $error=0; |
||
7281 | |||
7282 | $this->db->begin(); |
||
7283 | |||
7284 | if ($forcechilddeletion) |
||
7285 | { |
||
7286 | foreach($this->childtables as $table) |
||
7287 | { |
||
7288 | $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$table.' WHERE '.$this->fk_element.' = '.$this->id; |
||
7289 | $resql = $this->db->query($sql); |
||
7290 | if (! $resql) |
||
7291 | { |
||
7292 | $this->error=$this->db->lasterror(); |
||
7293 | $this->errors[]=$this->error; |
||
7294 | $this->db->rollback(); |
||
7295 | return -1; |
||
7296 | } |
||
7297 | } |
||
7298 | } |
||
7299 | elseif (! empty($this->fk_element) && ! empty($this->childtables)) // If object has childs linked with a foreign key field, we check all child tables. |
||
7300 | { |
||
7301 | $objectisused = $this->isObjectUsed($this->id); |
||
7302 | if (! empty($objectisused)) |
||
7303 | { |
||
7304 | dol_syslog(get_class($this)."::deleteCommon Can't delete record as it has some child", LOG_WARNING); |
||
7305 | $this->error='ErrorRecordHasChildren'; |
||
7306 | $this->errors[]=$this->error; |
||
7307 | $this->db->rollback(); |
||
7308 | return 0; |
||
7309 | } |
||
7310 | } |
||
7311 | |||
7312 | if (! $error) { |
||
7313 | if (! $notrigger) { |
||
7314 | // Call triggers |
||
7315 | $result=$this->call_trigger(strtoupper(get_class($this)).'_DELETE', $user); |
||
7316 | if ($result < 0) { $error++; } // Do also here what you must do to rollback action if trigger fail |
||
7317 | // End call triggers |
||
7318 | } |
||
7319 | } |
||
7320 | |||
7321 | if (! $error && ! empty($this->isextrafieldmanaged)) |
||
7322 | { |
||
7323 | $sql = "DELETE FROM " . MAIN_DB_PREFIX . $this->table_element."_extrafields"; |
||
7324 | $sql.= " WHERE fk_object=" . $this->id; |
||
7325 | |||
7326 | $resql = $this->db->query($sql); |
||
7327 | if (! $resql) |
||
7328 | { |
||
7329 | $this->errors[] = $this->db->lasterror(); |
||
7330 | $error++; |
||
7331 | } |
||
7332 | } |
||
7333 | |||
7334 | if (! $error) |
||
7335 | { |
||
7336 | $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.' WHERE rowid='.$this->id; |
||
7337 | |||
7338 | $res = $this->db->query($sql); |
||
7339 | if($res===false) { |
||
7340 | $error++; |
||
7341 | $this->errors[] = $this->db->lasterror(); |
||
7342 | } |
||
7343 | } |
||
7344 | |||
7345 | // Commit or rollback |
||
7346 | if ($error) { |
||
7347 | $this->db->rollback(); |
||
7348 | return -1; |
||
7349 | } else { |
||
7350 | $this->db->commit(); |
||
7351 | return 1; |
||
7352 | } |
||
7353 | } |
||
7354 | |||
7355 | /** |
||
7356 | * Initialise object with example values |
||
7357 | * Id must be 0 if object instance is a specimen |
||
7358 | * |
||
7359 | * @return void |
||
7360 | */ |
||
7361 | public function initAsSpecimenCommon() |
||
7362 | { |
||
7363 | $this->id = 0; |
||
7364 | |||
7365 | // TODO... |
||
7366 | } |
||
7367 | |||
7368 | |||
7369 | /* Part for comments */ |
||
7370 | |||
7371 | /** |
||
7372 | * Load comments linked with current task |
||
7373 | * @return boolean 1 if ok |
||
7374 | */ |
||
7375 | public function fetchComments() |
||
7376 | { |
||
7377 | require_once DOL_DOCUMENT_ROOT.'/core/class/comment.class.php'; |
||
7378 | |||
7379 | $comment = new Comment($this->db); |
||
7380 | $result=$comment->fetchAllFor($this->element, $this->id); |
||
7381 | if ($result<0) { |
||
7382 | $this->errors=array_merge($this->errors, $comment->errors); |
||
7383 | return -1; |
||
7384 | } else { |
||
7385 | $this->comments = $comment->comments; |
||
7386 | } |
||
7387 | return count($this->comments); |
||
7388 | } |
||
7389 | |||
7390 | /** |
||
7391 | * Return nb comments already posted |
||
7392 | * |
||
7393 | * @return int |
||
7394 | */ |
||
7395 | public function getNbComments() |
||
7396 | { |
||
7397 | return count($this->comments); |
||
7398 | } |
||
7399 | |||
7400 | /** |
||
7401 | * Trim object parameters |
||
7402 | * @param string[] $parameters array of parameters to trim |
||
7403 | * |
||
7404 | * @return void |
||
7405 | */ |
||
7406 | public function trimParameters($parameters) |
||
7407 | { |
||
7408 | if (!is_array($parameters)) return; |
||
7409 | foreach ($parameters as $parameter) { |
||
7410 | if (isset($this->$parameter)) { |
||
7411 | $this->$parameter = trim($this->$parameter); |
||
7412 | } |
||
7413 | } |
||
7414 | } |
||
7415 | } |
||
7416 |
This property has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.