dolibarr 22.0.5
blockedlog.class.php
1<?php
2/* Copyright (C) 2017 ATM Consulting <contact@atm-consulting.fr>
3 * Copyright (C) 2017-2020 Laurent Destailleur <eldy@destailleur.fr>
4 * Copyright (C) 2022 charlene benke <charlene@patas-monkey.com>
5 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
6 * Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 *
21 * See https://medium.com/@lhartikk/a-blockchain-in-200-lines-of-code-963cc1cc0e54
22 */
23
24
29{
33 public $db;
34
39 public $id;
40
45 public $entity;
46
50 public $error = '';
51
55 public $errors = array();
56
61 public $signature = '';
62
67 public $signature_line = '';
68
72 public $amounts = null;
73
78 public $action = '';
79
84 public $element = '';
85
90 public $fk_object = 0;
91
96 public $certified = false;
97
102 public $fk_user = 0;
103
107 public $date_creation;
108
112 public $date_modification;
113
117 public $date_object = 0;
118
122 public $ref_object = '';
123
127 public $object_data = null;
128
132 public $object_version = '';
133
137 public $user_fullname = '';
138
142 public $debuginfo;
143
148 public $trackedevents = array();
149
150
151
157 public function __construct(DoliDB $db)
158 {
159 $this->db = $db;
160 }
161
162
168 public function loadTrackedEvents()
169 {
170 global $langs;
171
172 $this->trackedevents = array();
173
174 // Customer Invoice/Facture / Payment
175 if (isModEnabled('invoice')) {
176 $this->trackedevents['BILL_VALIDATE'] = array('id' => 'BILL_VALIDATE', 'label' => 'logBILL_VALIDATE', 'labelhtml' => img_picto('', 'bill', 'class="pictofixedwidth").').$langs->trans('logBILL_VALIDATE'));
177 //$this->trackedevents['BILL_UPDATE'] = array('id' => 'BILL_VALIDATE', 'label' => 'logBILL_UPDATE', 'labelhtml' => img_picto('', 'bill', 'class="pictofixedwidth").').$langs->trans('logBILL_UPDATE'));
178 $this->trackedevents['BILL_SENTBYMAIL'] = array('id' => 'BILL_SENTBYMAIL', 'label' => 'logBILL_SENTBYMAIL', 'labelhtml' => img_picto('', 'bill', 'class="pictofixedwidth").').$langs->trans('logBILL_SENTBYMAIL'));
179 $this->trackedevents['DOC_DOWNLOAD'] = array('id' => 'DOC_DOWNLOAD', 'label' => 'BlockedLogBillDownload', 'labelhtml' => img_picto('', 'bill', 'class="pictofixedwidth").').$langs->trans('BlockedLogBillDownload'));
180 $this->trackedevents['DOC_PREVIEW'] = array('id' => 'DOC_PREVIEW', 'label' => 'BlockedLogBillPreview', 'labelhtml' => img_picto('', 'bill', 'class="pictofixedwidth").').$langs->trans('BlockedLogBillPreview'));
181 $this->trackedevents['PAYMENT_CUSTOMER_CREATE'] = array('id' => 'PAYMENT_CUSTOMER_CREATE', 'label' => 'logPAYMENT_CUSTOMER_CREATE', 'labelhtml' => img_picto('', 'bill', 'class="pictofixedwidth").').$langs->trans('logPAYMENT_CUSTOMER_CREATE'));
182 $this->trackedevents['PAYMENT_CUSTOMER_DELETE'] = array('id' => 'PAYMENT_CUSTOMER_DELETE', 'label' => 'logPAYMENT_CUSTOMER_DELETE', 'labelhtml' => img_picto('', 'bill', 'class="pictofixedwidth").').$langs->trans('logPAYMENT_CUSTOMER_DELETE'));
183 }
184
185 /* Supplier
186 // Supplier Invoice / Payment
187 if (isModEnabled("fournisseur")) {
188 $this->trackedevents['BILL_SUPPLIER_VALIDATE']='BlockedLogSupplierBillValidate';
189 $this->trackedevents['BILL_SUPPLIER_DELETE']='BlockedLogSupplierBillDelete';
190 $this->trackedevents['BILL_SUPPLIER_SENTBYMAIL']='BlockedLogSupplierBillSentByEmail'; // Trigger key does not exists, we want just into array to list it as done
191 $this->trackedevents['SUPPLIER_DOC_DOWNLOAD']='BlockedLogSupplierBillDownload'; // Trigger key does not exists, we want just into array to list it as done
192 $this->trackedevents['SUPPLIER_DOC_PREVIEW']='BlockedLogSupplierBillPreview'; // Trigger key does not exists, we want just into array to list it as done
193 $this->trackedevents['PAYMENT_SUPPLIER_CREATE']='BlockedLogSupplierBillPaymentCreate';
194 $this->trackedevents['PAYMENT_SUPPLIER_DELETE']='BlockedLogsupplierBillPaymentCreate';
195 }
196 */
197
198 // Donation
199 if (isModEnabled('don')) {
200 $this->trackedevents['DON_VALIDATE'] = 'logDON_VALIDATE';
201 $this->trackedevents['DON_DELETE'] = 'logDON_DELETE';
202 //$this->trackedevents['DON_SENTBYMAIL']='logDON_SENTBYMAIL';
203 $this->trackedevents['DONATION_PAYMENT_CREATE'] = 'logDONATION_PAYMENT_CREATE';
204 $this->trackedevents['DONATION_PAYMENT_DELETE'] = 'logDONATION_PAYMENT_DELETE';
205 }
206
207 /*
208 // Salary
209 if (isModEnabled('salary')) {
210 $this->trackedevents['PAYMENT_SALARY_CREATE']='BlockedLogSalaryPaymentCreate';
211 $this->trackedevents['PAYMENT_SALARY_MODIFY']='BlockedLogSalaryPaymentCreate';
212 $this->trackedevents['PAYMENT_SALARY_DELETE']='BlockedLogSalaryPaymentCreate';
213 }
214 */
215
216 // Members
217 if (isModEnabled('member')) {
218 $this->trackedevents['MEMBER_SUBSCRIPTION_CREATE'] = 'logMEMBER_SUBSCRIPTION_CREATE';
219 $this->trackedevents['MEMBER_SUBSCRIPTION_MODIFY'] = 'logMEMBER_SUBSCRIPTION_MODIFY';
220 $this->trackedevents['MEMBER_SUBSCRIPTION_DELETE'] = 'logMEMBER_SUBSCRIPTION_DELETE';
221 }
222
223 // Bank
224 if (isModEnabled("bank")) {
225 $this->trackedevents['PAYMENT_VARIOUS_CREATE'] = 'logPAYMENT_VARIOUS_CREATE';
226 $this->trackedevents['PAYMENT_VARIOUS_MODIFY'] = 'logPAYMENT_VARIOUS_MODIFY';
227 $this->trackedevents['PAYMENT_VARIOUS_DELETE'] = 'logPAYMENT_VARIOUS_DELETE';
228 }
229
230 // Cashdesk
231 // $conf->global->BANK_ENABLE_POS_CASHCONTROL must be set to 1 by all external POS modules
232 $moduleposenabled = (isModEnabled('cashdesk') || isModEnabled('takepos') || getDolGlobalString('BANK_ENABLE_POS_CASHCONTROL'));
233 if ($moduleposenabled) {
234 $this->trackedevents['CASHCONTROL_VALIDATE'] = 'logCASHCONTROL_VALIDATE';
235 }
236
237 // Add more action to track from a conf variable
238 // For example: STOCK_MOVEMENT,...
239 if (getDolGlobalString('BLOCKEDLOG_ADD_ACTIONS_SUPPORTED')) {
240 $tmparrayofmoresupportedevents = explode(',', getDolGlobalString('BLOCKEDLOG_ADD_ACTIONS_SUPPORTED'));
241 foreach ($tmparrayofmoresupportedevents as $val) {
242 $this->trackedevents[$val] = 'log'.$val;
243 }
244 }
245
246 $this->trackedevents['BLOCKEDLOG_EXPORT'] = 'logBLOCKEDLOG_EXPORT';
247
248 return 1;
249 }
250
256 public function getObjectLink()
257 {
258 global $langs;
259
260 if ($this->element === 'facture') {
261 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
262
263 $object = new Facture($this->db);
264 if ($object->fetch($this->fk_object) > 0) {
265 return $object->getNomUrl(1);
266 } else {
267 $this->error = (string) (((int) $this->error) + 1);
268 }
269 }
270 if ($this->element === 'invoice_supplier') {
271 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
272
273 $object = new FactureFournisseur($this->db);
274 if ($object->fetch($this->fk_object) > 0) {
275 return $object->getNomUrl(1);
276 } else {
277 $this->error = (string) (((int) $this->error) + 1);
278 }
279 } elseif ($this->element === 'payment') {
280 require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
281
282 $object = new Paiement($this->db);
283 if ($object->fetch($this->fk_object) > 0) {
284 return $object->getNomUrl(1);
285 } else {
286 $this->error = (string) (((int) $this->error) + 1);
287 }
288 } elseif ($this->element === 'payment_supplier') {
289 require_once DOL_DOCUMENT_ROOT.'/fourn/class/paiementfourn.class.php';
290
291 $object = new PaiementFourn($this->db);
292 if ($object->fetch($this->fk_object) > 0) {
293 return $object->getNomUrl(1);
294 } else {
295 $this->error = (string) (((int) $this->error) + 1);
296 }
297 } elseif ($this->element === 'payment_donation') {
298 require_once DOL_DOCUMENT_ROOT.'/don/class/paymentdonation.class.php';
299
300 $object = new PaymentDonation($this->db);
301 if ($object->fetch($this->fk_object) > 0) {
302 return $object->getNomUrl(1);
303 } else {
304 $this->error = (string) (((int) $this->error) + 1);
305 }
306 } elseif ($this->element === 'payment_various') {
307 require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/paymentvarious.class.php';
308
309 $object = new PaymentVarious($this->db);
310 if ($object->fetch($this->fk_object) > 0) {
311 return $object->getNomUrl(1);
312 } else {
313 $this->error = (string) (((int) $this->error) + 1);
314 }
315 } elseif ($this->element === 'don' || $this->element === 'donation') {
316 require_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php';
317
318 $object = new Don($this->db);
319 if ($object->fetch($this->fk_object) > 0) {
320 return $object->getNomUrl(1);
321 } else {
322 $this->error = (string) (((int) $this->error) + 1);
323 }
324 } elseif ($this->element === 'subscription') {
325 require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
326
327 $object = new Subscription($this->db);
328 if ($object->fetch($this->fk_object) > 0) {
329 return $object->getNomUrl(1);
330 } else {
331 $this->error = (string) (((int) $this->error) + 1);
332 }
333 } elseif ($this->element === 'cashcontrol') {
334 require_once DOL_DOCUMENT_ROOT.'/compta/cashcontrol/class/cashcontrol.class.php';
335
336 $object = new CashControl($this->db);
337 if ($object->fetch($this->fk_object) > 0) {
338 return $object->getNomUrl(1);
339 } else {
340 $this->error = (string) (((int) $this->error) + 1);
341 }
342 } elseif ($this->element === 'stockmouvement') {
343 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
344
345 $object = new MouvementStock($this->db);
346 if ($object->fetch($this->fk_object) > 0) {
347 return $object->getNomUrl(1);
348 } else {
349 $this->error = (string) (((int) $this->error) + 1);
350 }
351 } elseif ($this->element === 'project') {
352 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
353
354 $object = new Project($this->db);
355 if ($object->fetch($this->fk_object) > 0) {
356 return $object->getNomUrl(1);
357 } else {
358 $this->error = (string) (((int) $this->error) + 1);
359 }
360 } elseif ($this->action == 'BLOCKEDLOG_EXPORT') {
361 return '<i class="opacitymedium">'.$langs->trans("logBLOCKEDLOG_EXPORT").'</i>';
362 } elseif ($this->action == 'MODULE_SET') {
363 return '<i class="opacitymedium">'.$langs->trans("BlockedLogEnabled").'</i>';
364 } elseif ($this->action == 'MODULE_RESET') {
365 if ($this->signature == '0000000000') {
366 return '<i class="opacitymedium">'.$langs->trans("BlockedLogDisabled").'</i>';
367 } else {
368 return '<i class="opacitymedium">'.$langs->trans("BlockedLogDisabledBis").'</i>';
369 }
370 }
371
372 return '<i class="opacitymedium">'.$langs->trans('ImpossibleToReloadObject', $this->element, $this->fk_object).'</i>';
373 }
374
380 public function getUser()
381 {
382 global $langs, $cachedUser;
383
384 if (empty($cachedUser)) {
385 $cachedUser = array();
386 }
387
388 if (empty($cachedUser[$this->fk_user])) {
389 $u = new User($this->db);
390 if ($u->fetch($this->fk_user) > 0) {
391 $cachedUser[$this->fk_user] = $u;
392 }
393 }
394
395 if (!empty($cachedUser[$this->fk_user])) {
396 return $cachedUser[$this->fk_user]->getNomUrl(1);
397 }
398
399 return $langs->trans('ImpossibleToRetrieveUser', $this->fk_user);
400 }
401
411 public function setObjectData(&$object, $action, $amounts, $fuser = null)
412 {
413 global $langs, $user, $mysoc;
414
415 if (is_object($fuser)) {
416 $user = $fuser;
417 }
418
419 // Generic fields
420
421 // action
422 $this->action = $action;
423 // amount
424 $this->amounts = $amounts;
425 // date
426 if ($object->element == 'payment' || $object->element == 'payment_supplier') {
427 '@phan-var-force Paiement|PaiementFourn $object';
428 $this->date_object = empty($object->datepaye) ? $object->date : $object->datepaye;
429 } elseif ($object->element == 'payment_salary') {
430 '@phan-var-force PaymentSalary $object';
431 $this->date_object = $object->datev;
432 } elseif ($object->element == 'payment_donation' || $object->element == 'payment_various') {
433 '@phan-var-force PaymentDonation $object';
434 $this->date_object = empty($object->datepaid) ? $object->datep : $object->datepaid;
435 } elseif ($object->element == 'subscription') {
436 '@phan-var-force Subscription $object';
437 $this->date_object = $object->dateh;
438 } elseif ($object->element == 'cashcontrol') {
439 '@phan-var-force CashControl $object';
440 $this->date_object = $object->date_creation;
441 } elseif (property_exists($object, 'date')) {
442 // Generic case
443 $this->date_object = $object->date; // @phan-suppress-current-line PhanUndeclaredProperty
444 } elseif (property_exists($object, 'datem')) {
445 // Generic case (second chance, for example for stock movement)
446 $this->date_object = $object->datem; // @phan-suppress-current-line PhanUndeclaredProperty
447 }
448
449 // ref
450 $this->ref_object = ((!empty($object->newref)) ? $object->newref : $object->ref); // newref is set when validating a draft, ref is set in other cases
451 // type of object
452 $this->element = $object->element;
453 // id of object
454 $this->fk_object = $object->id;
455
456
457 // Set object_data
458 $this->object_data = new stdClass();
459 // Add fields to exclude
460 $arrayoffieldstoexclude = array(
461 'table_element', 'fields', 'ref_previous', 'ref_next', 'origin', 'origin_id', 'oldcopy', 'picto', 'error', 'errors', 'model_pdf', 'modelpdf', 'last_main_doc', 'civility_id', 'contact', 'contact_id',
462 'table_element_line', 'ismultientitymanaged', 'isextrafieldmanaged',
463 'array_languages',
464 'childtables',
465 'contact_ids',
466 'context',
467 'labelStatus',
468 'labelStatusShort',
469 'linkedObjectsIds',
470 'linkedObjects',
471 'fk_delivery_address',
472 'projet', // There is already ->fk_project
473 'restrictiononfksoc',
474 'specimen',
475 );
476 // Add more fields to exclude depending on object type
477 if ($this->element == 'cashcontrol') {
478 $arrayoffieldstoexclude = array_merge($arrayoffieldstoexclude, array(
479 'name', 'lastname', 'firstname', 'region', 'region_id', 'region_code', 'state', 'state_id', 'state_code', 'country', 'country_id', 'country_code',
480 'total_ht', 'total_tva', 'total_ttc', 'total_localtax1', 'total_localtax2',
481 'barcode_type', 'barcode_type_code', 'barcode_type_label', 'barcode_type_coder', 'mode_reglement_id', 'cond_reglement_id', 'mode_reglement', 'cond_reglement', 'shipping_method_id',
482 'fk_incoterms', 'label_incoterms', 'location_incoterms', 'lines'));
483 }
484
485 // Add thirdparty info
486 if (empty($object->thirdparty) && method_exists($object, 'fetch_thirdparty')) {
487 $object->fetch_thirdparty();
488 }
489 if (!empty($object->thirdparty)) {
490 $this->object_data->thirdparty = new stdClass();
491
492 foreach ($object->thirdparty as $key => $value) {
493 if (in_array($key, $arrayoffieldstoexclude)) {
494 continue; // Discard some properties
495 }
496 if (!in_array($key, array(
497 'name', 'name_alias', 'ref_ext', 'address', 'zip', 'town', 'state_code', 'country_code', 'idprof1', 'idprof2', 'idprof3', 'idprof4', 'idprof5', 'idprof6', 'phone', 'fax', 'email', 'barcode',
498 'tva_intra', 'localtax1_assuj', 'localtax1_value', 'localtax2_assuj', 'localtax2_value', 'managers', 'capital', 'typent_code', 'forme_juridique_code', 'code_client', 'code_fournisseur'
499 ))) {
500 continue; // Discard if not into a dedicated list
501 }
502 if (!is_object($value) && !is_null($value) && $value !== '') {
503 $this->object_data->thirdparty->$key = $value;
504 }
505 }
506 }
507
508 // Add company info
509 if (!empty($mysoc)) {
510 $this->object_data->mycompany = new stdClass();
511
512 foreach ($mysoc as $key => $value) {
513 if (in_array($key, $arrayoffieldstoexclude)) {
514 continue; // Discard some properties
515 }
516 if (!in_array($key, array(
517 'name', 'name_alias', 'ref_ext', 'address', 'zip', 'town', 'state_code', 'country_code', 'idprof1', 'idprof2', 'idprof3', 'idprof4', 'idprof5', 'idprof6', 'phone', 'fax', 'email', 'barcode',
518 'tva_intra', 'localtax1_assuj', 'localtax1_value', 'localtax2_assuj', 'localtax2_value', 'managers', 'capital', 'typent_code', 'forme_juridique_code', 'code_client', 'code_fournisseur'
519 ))) {
520 continue; // Discard if not into a dedicated list
521 }
522 if (!is_object($value) && !is_null($value) && $value !== '') {
523 $this->object_data->mycompany->$key = $value;
524 }
525 }
526 }
527
528 // Add user info
529 if (!empty($user)) {
530 $this->fk_user = $user->id;
531 $this->user_fullname = $user->getFullName($langs);
532 }
533
534 // Field specific to object
535 if ($this->element == 'facture') {
536 '@phan-var-force Facture $object';
537 foreach ($object as $key => $value) {
538 if (in_array($key, $arrayoffieldstoexclude)) {
539 continue; // Discard some properties
540 }
541 if (!in_array($key, array(
542 'ref', 'ref_client', 'ref_supplier', 'date', 'datef', 'datev', 'type', 'total_ht', 'total_tva', 'total_ttc', 'localtax1', 'localtax2', 'revenuestamp', 'datepointoftax', 'note_public', 'lines',
543 'module_source', 'pos_source'
544 ))) {
545 continue; // Discard if not into a dedicated list
546 }
547 if ($key == 'lines') {
548 $lineid = 0;
549 foreach ($value as $tmpline) { // $tmpline is object FactureLine
550 $lineid++;
551 foreach ($tmpline as $keyline => $valueline) {
552 if (!in_array($keyline, array(
553 'ref', 'product_type', 'product_label',
554 'qty',
555 'subprice',
556 'vat_src_code', 'tva_tx', 'localtax1_tx', 'localtax2_tx',
557 'total_ht', 'total_tva', 'total_ttc', 'total_localtax1', 'total_localtax2',
558 'multicurrency_code', 'multicurrency_total_ht', 'multicurrency_total_tva', 'multicurrency_total_ttc',
559 'info_bits', 'special_code',
560 ))) {
561 continue; // Discard if not into a dedicated list
562 }
563
564 if (empty($this->object_data->invoiceline[$lineid]) || !is_object($this->object_data->invoiceline[$lineid])) { // To avoid warning
565 $this->object_data->invoiceline[$lineid] = new stdClass();
566 }
567
568 if (!is_object($valueline) && !is_null($valueline) && $valueline !== '') {
569 $this->object_data->invoiceline[$lineid]->$keyline = $valueline;
570 }
571 }
572 }
573 } elseif (!is_object($value) && !is_null($value) && $value !== '') {
574 $this->object_data->$key = $value;
575 }
576 }
577
578 if (!empty($object->newref)) {
579 $this->object_data->ref = $object->newref;
580 }
581 } elseif ($this->element == 'invoice_supplier') {
582 '@phan-var-force FactureFournisseur $object';
583 foreach ($object as $key => $value) {
584 if (in_array($key, $arrayoffieldstoexclude)) {
585 continue; // Discard some properties
586 }
587 if (!in_array($key, array(
588 'ref', 'ref_client', 'ref_supplier', 'date', 'datef', 'type', 'total_ht', 'total_tva', 'total_ttc', 'localtax1', 'localtax2', 'revenuestamp', 'datepointoftax', 'note_public'
589 ))) {
590 continue; // Discard if not into a dedicated list
591 }
592 if (!is_object($value) && !is_null($value) && $value !== '') {
593 $this->object_data->$key = $value;
594 }
595 }
596
597 if (!empty($object->newref)) {
598 $this->object_data->ref = $object->newref;
599 }
600 } elseif ($this->element == 'payment' || $this->element == 'payment_supplier' || $this->element == 'payment_donation' || $this->element == 'payment_various') {
601 '@phan-var-force Paiement|PaiementFourn|PaymentDonation|PaymentVarious $object';
602 $datepayment = $object->datepaye ? $object->datepaye : ($object->datepaid ? $object->datepaid : $object->datep);
603 $paymenttypeid = $object->paiementid ? $object->paiementid : ($object->paymenttype ? $object->paymenttype : $object->type_payment);
604
605 $this->object_data->ref = $object->ref;
606 $this->object_data->date = $datepayment;
607 $this->object_data->type_code = dol_getIdFromCode($this->db, $paymenttypeid, 'c_paiement', 'id', 'code');
608
609 if (!empty($object->num_payment)) {
610 $this->object_data->payment_num = $object->num_payment;
611 }
612 if (!empty($object->note_private)) {
613 $this->object_data->note_private = $object->note_private;
614 }
615 //$this->object_data->fk_account = $object->fk_account;
616 //var_dump($this->object_data);exit;
617
618 $totalamount = 0;
619
620 // Loop on each invoice payment amount (payment_part)
621 if (is_array($object->amounts) && !empty($object->amounts)) {
622 $paymentpartnumber = 0;
623 foreach ($object->amounts as $objid => $amount) {
624 if (empty($amount)) {
625 continue;
626 }
627
628 $totalamount += $amount;
629
630 $tmpobject = null;
631 if ($this->element == 'payment_supplier') {
632 include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
633 $tmpobject = new FactureFournisseur($this->db);
634 } elseif ($this->element == 'payment') {
635 include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
636 $tmpobject = new Facture($this->db);
637 } elseif ($this->element == 'payment_donation') {
638 include_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php';
639 $tmpobject = new Don($this->db);
640 } elseif ($this->element == 'payment_various') {
641 include_once DOL_DOCUMENT_ROOT.'/compta/bank/class/paymentvarious.class.php';
642 $tmpobject = new PaymentVarious($this->db);
643 }
644
645 if (!is_object($tmpobject)) {
646 continue;
647 }
648
649 $result = $tmpobject->fetch($objid);
650
651 if ($result <= 0) {
652 $this->error = $tmpobject->error;
653 $this->errors = $tmpobject->errors;
654 dol_syslog("Failed to fetch object with id ".$objid, LOG_ERR);
655 return -1;
656 }
657
658 $paymentpart = new stdClass();
659 $paymentpart->amount = $amount;
660
661 if (!in_array($this->element, array('payment_donation', 'payment_various'))) {
662 $result = $tmpobject->fetch_thirdparty();
663 if ($result == 0) {
664 $this->error = 'Failed to fetch thirdparty for object with id '.$tmpobject->id;
665 $this->errors[] = $this->error;
666 dol_syslog("Failed to fetch thirdparty for object with id ".$tmpobject->id, LOG_ERR);
667 return -1;
668 } elseif ($result < 0) {
669 $this->error = $tmpobject->error;
670 $this->errors = $tmpobject->errors;
671 return -1;
672 }
673
674 $paymentpart->thirdparty = new stdClass();
675 foreach ($tmpobject->thirdparty as $key => $value) {
676 if (in_array($key, $arrayoffieldstoexclude)) {
677 continue; // Discard some properties
678 }
679 if (!in_array($key, array(
680 'name', 'name_alias', 'ref_ext', 'address', 'zip', 'town', 'state_code', 'country_code', 'idprof1', 'idprof2', 'idprof3', 'idprof4', 'idprof5', 'idprof6', 'phone', 'fax', 'email', 'barcode',
681 'tva_intra', 'localtax1_assuj', 'localtax1_value', 'localtax2_assuj', 'localtax2_value', 'managers', 'capital', 'typent_code', 'forme_juridique_code', 'code_client', 'code_fournisseur'
682 ))) {
683 continue; // Discard if not into a dedicated list
684 }
685 if (!is_object($value) && !is_null($value) && $value !== '') {
686 $paymentpart->thirdparty->$key = $value;
687 }
688 }
689 }
690
691 // Init object to avoid warnings
692 if ($this->element == 'payment_donation') {
693 $paymentpart->donation = new stdClass();
694 } else {
695 $paymentpart->invoice = new stdClass();
696 }
697
698 if ($this->element != 'payment_various') {
699 foreach ($tmpobject as $key => $value) {
700 if (in_array($key, $arrayoffieldstoexclude)) {
701 continue; // Discard some properties
702 }
703 if (!in_array($key, array(
704 'ref', 'ref_client', 'ref_supplier', 'date', 'datef', 'type', 'total_ht', 'total_tva', 'total_ttc', 'localtax1', 'localtax2', 'revenuestamp', 'datepointoftax', 'note_public'
705 ))) {
706 continue; // Discard if not into a dedicated list
707 }
708 if (!is_object($value) && !is_null($value) && $value !== '') {
709 if ($this->element == 'payment_donation') {
710 $paymentpart->donation->$key = $value;
711 } elseif ($this->element == 'payment_various') {
712 $paymentpart->various->$key = $value;
713 } else {
714 $paymentpart->invoice->$key = $value;
715 }
716 }
717 }
718
719 $paymentpartnumber++; // first payment will be 1
720 $this->object_data->payment_part[$paymentpartnumber] = $paymentpart;
721 }
722 }
723 } elseif (!empty($object->amount)) {
724 $totalamount = $object->amount;
725 }
726
727 $this->object_data->amount = $totalamount;
728
729 if (!empty($object->newref)) {
730 $this->object_data->ref = $object->newref;
731 }
732 } elseif ($this->element == 'payment_salary') {
733 '@phan-var-force PaymentSalary $object';
734 $this->object_data->amounts = array($object->amount);
735
736 if (!empty($object->newref)) {
737 $this->object_data->ref = $object->newref;
738 }
739 } elseif ($this->element == 'subscription') {
740 '@phan-var-force Subscription $object';
741 foreach ($object as $key => $value) {
742 if (in_array($key, $arrayoffieldstoexclude)) {
743 continue; // Discard some properties
744 }
745 if (!in_array($key, array(
746 'id', 'datec', 'dateh', 'datef', 'fk_adherent', 'amount', 'import_key', 'statut', 'note'
747 ))) {
748 continue; // Discard if not into a dedicated list
749 }
750 if (!is_object($value) && !is_null($value) && $value !== '') {
751 $this->object_data->$key = $value;
752 }
753 }
754
755 if (!empty($object->newref)) {
756 $this->object_data->ref = $object->newref;
757 }
758 } elseif ($this->element == 'stockmouvement') {
759 '@phan-var-force StockTransfer $object';
760 foreach ($object as $key => $value) {
761 if (in_array($key, $arrayoffieldstoexclude)) {
762 continue; // Discard some properties
763 }
764 if (!is_object($value) && !is_null($value) && $value !== '') {
765 $this->object_data->$key = $value;
766 }
767 }
768 } else {
769 // Generic case
770 foreach ($object as $key => $value) {
771 if (in_array($key, $arrayoffieldstoexclude)) {
772 continue; // Discard some properties
773 }
774 if (!is_object($value) && !is_null($value) && $value !== '') {
775 $this->object_data->$key = $value;
776 }
777 }
778
779 if (!empty($object->newref)) {
780 $this->object_data->ref = $object->newref;
781 }
782 }
783
784 // A trick to be sure all the object_data is an associative array
785 // json_encode and json_decode are not able to manage mixed object (with array/object, only full arrays or full objects)
786 $this->object_data = json_decode(json_encode($this->object_data, JSON_FORCE_OBJECT), false);
787
788 return 1;
789 }
790
797 public function fetch($id)
798 {
799 global $langs;
800
801 if (empty($id)) {
802 $this->error = 'BadParameter';
803 return -1;
804 }
805
806 $sql = "SELECT b.rowid, b.date_creation, b.signature, b.signature_line, b.amounts, b.action, b.element, b.fk_object, b.entity,";
807 $sql .= " b.certified, b.tms, b.fk_user, b.user_fullname, b.date_object, b.ref_object, b.object_data, b.object_version";
808 $sql .= " FROM ".MAIN_DB_PREFIX."blockedlog as b";
809 if ($id) {
810 $sql .= " WHERE b.rowid = ".((int) $id);
811 }
812
813 $resql = $this->db->query($sql);
814 if ($resql) {
815 $obj = $this->db->fetch_object($resql);
816 if ($obj) {
817 $this->id = $obj->rowid;
818 $this->entity = $obj->entity;
819
820 $this->date_creation = $this->db->jdate($obj->date_creation);
821 $this->date_modification = $this->db->jdate($obj->tms);
822
823 $this->amounts = (float) $obj->amounts;
824 $this->action = $obj->action;
825 $this->element = $obj->element;
826
827 $this->fk_object = $obj->fk_object;
828 $this->date_object = $this->db->jdate($obj->date_object);
829 $this->ref_object = $obj->ref_object;
830
831 $this->fk_user = $obj->fk_user;
832 $this->user_fullname = $obj->user_fullname;
833
834 $this->object_data = $this->dolDecodeBlockedData($obj->object_data);
835 $this->object_version = $obj->object_version;
836
837 $this->signature = $obj->signature;
838 $this->signature_line = $obj->signature_line;
839 $this->certified = ($obj->certified == 1);
840
841 return 1;
842 } else {
843 $langs->load("errors");
844 $this->error = $langs->trans("ErrorRecordNotFound");
845 return 0;
846 }
847 } else {
848 $this->error = $this->db->error();
849 return -1;
850 }
851 }
852
853
861 public function dolEncodeBlockedData($data, $mode = 0)
862 {
863 $aaa = '';
864 try {
865 $aaa = json_encode($data);
866 } catch (Exception $e) {
867 // print $e->getErrs);
868 }
869
870 return $aaa;
871 }
872
873
881 public function dolDecodeBlockedData($data, $mode = 0)
882 {
883 $aaa = null;
884 try {
885 $aaa = (object) jsonOrUnserialize($data);
886 } catch (Exception $e) {
887 // print $e->getErrs);
888 }
889
890 return $aaa;
891 }
892
893
899 public function setCertified()
900 {
901 $res = $this->db->query("UPDATE ".MAIN_DB_PREFIX."blockedlog SET certified=1 WHERE rowid=".((int) $this->id));
902 if (!$res) {
903 return false;
904 }
905
906 return true;
907 }
908
916 public function create($user, $forcesignature = '')
917 {
918 global $conf, $langs;
919
920 $langs->load('blockedlog');
921
922 // Clean data
923 $this->amounts = (float) $this->amounts;
924
925 dol_syslog(get_class($this).'::create action='.$this->action.' fk_user='.$this->fk_user.' user_fullname='.$this->user_fullname, LOG_DEBUG);
926
927 // Check parameters/properties
928 if (!isset($this->amounts)) { // amount can be 0 for some events (like when module is disabled)
929 $this->error = $langs->trans("BlockLogNeedAmountsValue");
930 dol_syslog($this->error, LOG_WARNING);
931 return -1;
932 }
933
934 if (empty($this->element)) {
935 $this->error = $langs->trans("BlockLogNeedElement");
936 dol_syslog($this->error, LOG_WARNING);
937 return -2;
938 }
939
940 if (empty($this->action)) {
941 $this->error = $langs->trans("BadParameterWhenCallingCreateOfBlockedLog");
942 dol_syslog($this->error, LOG_WARNING);
943 return -3;
944 }
945 if (empty($this->fk_user)) {
946 $this->user_fullname = '(Anonymous)';
947 }
948
949 $this->date_creation = dol_now();
950
951 $this->object_version = DOL_VERSION;
952
953
954 $this->db->begin();
955
956 $previoushash = $this->getPreviousHash(1, 0); // This get last record and lock database until insert is done and transaction closed
957
958 $concatenatedata = $this->buildKeyForSignature(); // All the information for the hash (meta data + data saved)
959
960 $this->debuginfo = $this->buildFirstPartOfKeyForSignature();
961
962 include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
963
964 $this->signature_line = dol_hash($concatenatedata, '5'); // Not really useful
965 $this->signature = dol_hash($previoushash.$concatenatedata, '5');
966 if ($forcesignature) {
967 $this->signature = $forcesignature;
968 }
969 //var_dump($concatenatedata);var_dump($previoushash);var_dump($this->signature_line);var_dump($this->signature);
970
971 $sql = "INSERT INTO ".MAIN_DB_PREFIX."blockedlog (";
972 $sql .= " date_creation,";
973 $sql .= " action,";
974 $sql .= " amounts,";
975 $sql .= " signature,";
976 $sql .= " signature_line,";
977 $sql .= " element,";
978 $sql .= " fk_object,";
979 $sql .= " date_object,";
980 $sql .= " ref_object,";
981 $sql .= " object_data,";
982 $sql .= " object_version,";
983 $sql .= " certified,";
984 $sql .= " fk_user,";
985 $sql .= " user_fullname,";
986 $sql .= " entity,";
987 $sql .= " debuginfo"; // Only stored
988 $sql .= ") VALUES (";
989 $sql .= "'".$this->db->idate($this->date_creation)."',";
990 $sql .= "'".$this->db->escape($this->action)."',";
991 $sql .= $this->amounts.",";
992 $sql .= "'".$this->db->escape($this->signature)."',";
993 $sql .= "'".$this->db->escape($this->signature_line)."',";
994 $sql .= "'".$this->db->escape($this->element)."',";
995 $sql .= (int) $this->fk_object.",";
996 $sql .= "'".$this->db->idate($this->date_object)."',";
997 $sql .= "'".$this->db->escape($this->ref_object)."',";
998 $sql .= "'".$this->db->escape($this->dolEncodeBlockedData($this->object_data))."',";
999 $sql .= "'".$this->db->escape($this->object_version)."',";
1000 $sql .= "0,";
1001 $sql .= $this->fk_user.",";
1002 $sql .= "'".$this->db->escape($this->user_fullname)."',";
1003 $sql .= ($this->entity ? $this->entity : $conf->entity).",";
1004 $sql .= "'".$this->db->escape($this->debuginfo)."'";
1005 $sql .= ")";
1006
1007 /*
1008 $a = serialize($this->object_data); $a2 = unserialize($a); $a4 = print_r($a2, true);
1009 $b = json_encode($this->object_data); $b2 = json_decode($b); $b4 = print_r($b2, true);
1010 var_dump($a4 == print_r($this->object_data, true) ? 'a=a' : 'a not = a');
1011 var_dump($b4 == print_r($this->object_data, true) ? 'b=b' : 'b not = b');
1012 exit;
1013 */
1014
1015 $res = $this->db->query($sql);
1016 if ($res) {
1017 $id = $this->db->last_insert_id(MAIN_DB_PREFIX."blockedlog");
1018
1019 if ($id > 0) {
1020 $this->id = $id;
1021
1022 $this->db->commit();
1023
1024 return $this->id;
1025 } else {
1026 $this->db->rollback();
1027 return -2;
1028 }
1029 } else {
1030 $this->error = $this->db->error();
1031 $this->db->rollback();
1032 return -1;
1033 }
1034
1035 // The commit will release the lock so we can insert nex record
1036 }
1037
1045 public function checkSignature($previoushash = '', $returnarray = 0)
1046 {
1047 if (empty($previoushash)) {
1048 $previoushash = $this->getPreviousHash(0, $this->id);
1049 }
1050
1051 // Build the string for the signature
1052 $concatenatedata = $this->buildKeyForSignature();
1053
1054 //$signature_line = dol_hash($concatenatedata, '5'); // Not really useful
1055 $signature = dol_hash($previoushash.$concatenatedata, 'sha256');
1056 //var_dump($previoushash); var_dump($concatenatedata); var_dump($signature_line); var_dump($signature);
1057
1058 $res = ($signature === $this->signature);
1059
1060 if (!$res) {
1061 $this->error = 'Signature KO';
1062 }
1063
1064 if ($returnarray) {
1065 if ($returnarray == 1) {
1066 unset($concatenatedata);
1067 return array('checkresult' => $res, 'calculatedsignature' => $signature, 'previoushash' => $previoushash);
1068 } else { // Consume much memory ($concatenatedata is a large var)
1069 return array('checkresult' => $res, 'calculatedsignature' => $signature, 'previoushash' => $previoushash, 'keyforsignature' => $concatenatedata);
1070 }
1071 } else {
1072 unset($concatenatedata);
1073 return $res;
1074 }
1075 }
1076
1084 private function buildKeyForSignature()
1085 {
1086 //print_r($this->object_data);
1087 if (((int) $this->object_version) >= 18) {
1088 // Note: $this->amounts can be '0', '1.1', '1.123'; // All 0 at end should have been removed already
1089 return $this->buildFirstPartOfKeyForSignature().'|'.json_encode($this->object_data, JSON_FORCE_OBJECT);
1090 } else {
1091 return $this->buildFirstPartOfKeyForSignature().'|'.print_r($this->object_data, true);
1092 }
1093 }
1094
1103 {
1104 // Note: $this->amounts can be '0', '1.1', '1.123'; // All 0 at end should have been removed already
1105 //if (((int) $this->object_version) >= 18) {
1106 return $this->date_creation.'|'.$this->action.'|'.$this->amounts.'|'.$this->ref_object.'|'.$this->date_object.'|'.$this->user_fullname;
1107 }
1108
1109
1117 public function getPreviousHash($withlock = 0, $beforeid = 0)
1118 {
1119 global $conf;
1120
1121 $previoussignature = '';
1122
1123 // Fast search of previous record by searching with beforeid - 1. This is very fast and will work 99% of time.
1124 if ($beforeid) {
1125 $sql = "SELECT rowid, signature FROM ".MAIN_DB_PREFIX."blockedlog";
1126 $sql .= " WHERE entity = ".((int) $conf->entity);
1127 $sql .= " AND rowid = ".((int) $beforeid - 1);
1128 $sql .= ($withlock ? " FOR UPDATE " : "");
1129
1130 $resql = $this->db->query($sql);
1131 if ($resql) {
1132 $obj = $this->db->fetch_object($resql);
1133 if ($obj) {
1134 $previoussignature = $obj->signature;
1135 }
1136 } else {
1137 dol_print_error($this->db);
1138 exit;
1139 }
1140 }
1141
1142 if (empty($previoussignature)) {
1143 $sql = "SELECT rowid, signature FROM ".MAIN_DB_PREFIX."blockedlog";
1144 if ($beforeid) {
1145 $sql .= $this->db->hintindex('entity_rowid', 1);
1146 }
1147 $sql .= " WHERE entity = ".((int) $conf->entity);
1148 if ($beforeid) {
1149 $sql .= " AND rowid < ".(int) $beforeid;
1150 }
1151 $sql .= " ORDER BY rowid DESC LIMIT 1";
1152 $sql .= ($withlock ? " FOR UPDATE " : "");
1153
1154 $resql = $this->db->query($sql);
1155 if ($resql) {
1156 $obj = $this->db->fetch_object($resql);
1157 if ($obj) {
1158 $previoussignature = $obj->signature;
1159 }
1160 } else {
1161 dol_print_error($this->db);
1162 exit;
1163 }
1164 }
1165
1166 if (empty($previoussignature)) {
1167 // First signature line (line 0)
1168 $previoussignature = $this->getSignature();
1169 }
1170
1171 return $previoussignature;
1172 }
1173
1191 public function getLog($element, $fk_object, $limit = 0, $sortfield = '', $sortorder = '', $search_fk_user = -1, $search_start = -1, $search_end = -1, $search_ref = '', $search_amount = '', $search_code = '', $search_signature = '')
1192 {
1193 global $conf;
1194 //global $cachedlogs;
1195
1196 /* $cachedlogs allow fastest search */
1197 //if (empty($cachedlogs)) $cachedlogs = array();
1198
1199 if ($element == 'all') {
1200 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
1201 WHERE entity = ".$conf->entity;
1202 } elseif ($element == 'not_certified') {
1203 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
1204 WHERE entity = ".$conf->entity." AND certified = 0";
1205 } elseif ($element == 'just_certified') {
1206 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
1207 WHERE entity = ".$conf->entity." AND certified = 1";
1208 } else {
1209 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
1210 WHERE entity = ".$conf->entity." AND element = '".$this->db->escape($element)."'";
1211 }
1212
1213 if ($fk_object) {
1214 $sql .= natural_search("rowid", (string) $fk_object, 1);
1215 }
1216 if ($search_fk_user > 0) {
1217 $sql .= natural_search("fk_user", (string) $search_fk_user, 2);
1218 }
1219 if ($search_start > 0) {
1220 $sql .= " AND date_creation >= '".$this->db->idate($search_start)."'";
1221 }
1222 if ($search_end > 0) {
1223 $sql .= " AND date_creation <= '".$this->db->idate($search_end)."'";
1224 }
1225 if ($search_ref != '') {
1226 $sql .= natural_search("ref_object", $search_ref);
1227 }
1228 if ($search_amount != '') {
1229 $sql .= natural_search("amounts", $search_amount, 1);
1230 }
1231 if ($search_signature != '') {
1232 $sql .= natural_search("signature", $search_signature, 0);
1233 }
1234 if (is_array($search_code)) {
1235 if (!empty($search_code)) {
1236 $sql .= natural_search("action", implode(',', $search_code), 3);
1237 }
1238 } else {
1239 if ($search_code != '' && $search_code != '-1') {
1240 $sql .= natural_search("action", $search_code, 3);
1241 }
1242 }
1243
1244 $sql .= $this->db->order($sortfield, $sortorder);
1245 $sql .= $this->db->plimit($limit + 1); // We want more, because we will stop into loop later with error if we reach max
1246
1247 $res = $this->db->query($sql);
1248 if ($res) {
1249 $results = array();
1250
1251 $i = 0;
1252 while ($obj = $this->db->fetch_object($res)) {
1253 $i++;
1254 if ($i > $limit) {
1255 // Too many record, we will consume too much memory
1256 return -2;
1257 }
1258
1259 //if (!isset($cachedlogs[$obj->rowid]))
1260 //{
1261 $b = new BlockedLog($this->db);
1262 $b->fetch($obj->rowid);
1263 //$b->loadTrackedEvents();
1264 //$cachedlogs[$obj->rowid] = $b;
1265 //}
1266
1267 //$results[] = $cachedlogs[$obj->rowid];
1268 $results[] = $b;
1269 }
1270
1271 return $results;
1272 }
1273
1274 return -1;
1275 }
1276
1282 public function getSignature()
1283 {
1284 global $db, $conf, $mysoc;
1285
1286 if (!getDolGlobalString('BLOCKEDLOG_ENTITY_FINGERPRINT')) { // creation of a unique fingerprint
1287 require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
1288 require_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
1289 require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
1290
1291 $fingerprint = dol_hash(print_r($mysoc, true).getRandomPassword(true), '5');
1292
1293 dolibarr_set_const($db, 'BLOCKEDLOG_ENTITY_FINGERPRINT', $fingerprint, 'chaine', 0, 'Numeric Unique Fingerprint', $conf->entity);
1294
1295 $conf->global->BLOCKEDLOG_ENTITY_FINGERPRINT = $fingerprint;
1296 }
1297
1298 return $conf->global->BLOCKEDLOG_ENTITY_FINGERPRINT;
1299 }
1300
1301
1308 public function alreadyUsed($ignoresystem = 0)
1309 {
1310 global $conf;
1311
1312 $result = false;
1313
1314 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog";
1315 $sql .= " WHERE entity = ".((int) $conf->entity);
1316 if ($ignoresystem) {
1317 $sql .= " AND action not in ('MODULE_SET','MODULE_RESET')";
1318 }
1319 $sql .= $this->db->plimit(1);
1320
1321 $res = $this->db->query($sql);
1322 if ($res !== false) {
1323 $obj = $this->db->fetch_object($res);
1324 if ($obj) {
1325 $result = true;
1326 }
1327 } else {
1328 dol_print_error($this->db);
1329 }
1330
1331 dol_syslog("Module Blockedlog alreadyUsed(ignoresystem=".$ignoresystem.") returns ".json_encode($result));
1332
1333 return $result;
1334 }
1335}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:67
dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $note='', $entity=1)
Insert a parameter (key,value) into database (delete old key then insert it again).
Class to manage Blocked Log.
getSignature()
Return the signature (hash) of the "genesis-block" (Block 0).
getLog($element, $fk_object, $limit=0, $sortfield='', $sortorder='', $search_fk_user=-1, $search_start=-1, $search_end=-1, $search_ref='', $search_amount='', $search_code='', $search_signature='')
Return array of log objects (with criteria)
getObjectLink()
Try to retrieve source object (it it still exists).
alreadyUsed($ignoresystem=0)
Check if module was already used or not for at least one recording.
buildKeyForSignature()
Return a string for signature.
create($user, $forcesignature='')
Create blocked log in database.
dolEncodeBlockedData($data, $mode=0)
Encode data.
loadTrackedEvents()
Load list of tracked events into $this->trackedevents.
__construct(DoliDB $db)
Constructor.
setObjectData(&$object, $action, $amounts, $fuser=null)
Populate properties of an unalterable log entry from object data.
getPreviousHash($withlock=0, $beforeid=0)
Get previous signature/hash in chain.
checkSignature($previoushash='', $returnarray=0)
Check if current signature still correct compared to the value in chain.
dolDecodeBlockedData($data, $mode=0)
Decode data.
fetch($id)
Get object from database.
getUser()
Try to retrieve user author.
setCertified()
Set block certified by authority.
buildFirstPartOfKeyForSignature()
Return first part of string for signature.
Class to manage cash fence.
Class to manage Dolibarr database access.
Class to manage donations.
Definition don.class.php:41
Class to manage suppliers invoices.
Class to manage invoices.
Class to manage stock movements.
Class to manage payments for supplier invoices.
Class to manage payments of customer invoices.
Class to manage payments of donations.
Class to manage various payments.
Class to manage projects.
Class to manage subscriptions of foundation members.
Class to manage Dolibarr users.
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='', $useCache=true)
Return an id or code from a code or id.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
natural_search($fields, $value, $mode=0, $nofirstand=0)
Generate natural SQL search string for a criteria (this criteria can be tested on one or several fiel...
dol_now($mode='auto')
Return date for now.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
jsonOrUnserialize($stringtodecode)
Decode an encode string.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
getRandomPassword($generic=false, $replaceambiguouschars=null, $length=32)
Return a generated password using default module.
dol_hash($chain, $type='0', $nosalt=0, $mode=0)
Returns a hash (non reversible encryption) of a string.