dolibarr  16.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  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <https://www.gnu.org/licenses/>.
18  *
19  * See https://medium.com/@lhartikk/a-blockchain-in-200-lines-of-code-963cc1cc0e54
20  */
21 
22 
27 {
32  public $id;
33 
38  public $entity;
39 
43  public $error = '';
44 
48  public $errors = array();
49 
54  public $signature = '';
55 
60  public $signature_line = '';
61 
62  public $amounts = null;
63 
68  public $action = '';
69 
74  public $element = '';
75 
80  public $fk_object = 0;
81 
86  public $certified = false;
87 
92  public $fk_user = 0;
93 
97  public $date_creation;
98 
102  public $date_modification;
103 
104  public $date_object = 0;
105 
106  public $ref_object = '';
107 
108  public $object_data = null;
109  public $object_version = '';
110 
111  public $user_fullname = '';
112 
117  public $trackedevents = array();
118 
119 
120 
126  public function __construct(DoliDB $db)
127  {
128  $this->db = $db;
129  }
130 
131 
137  public function loadTrackedEvents()
138  {
139  global $conf;
140 
141  $this->trackedevents = array();
142 
143  if (isModEnabled('facture')) {
144  $this->trackedevents['BILL_VALIDATE'] = 'logBILL_VALIDATE';
145  $this->trackedevents['BILL_DELETE'] = 'logBILL_DELETE';
146  $this->trackedevents['BILL_SENTBYMAIL'] = 'logBILL_SENTBYMAIL';
147  $this->trackedevents['DOC_DOWNLOAD'] = 'BlockedLogBillDownload';
148  $this->trackedevents['DOC_PREVIEW'] = 'BlockedLogBillPreview';
149  $this->trackedevents['PAYMENT_CUSTOMER_CREATE'] = 'logPAYMENT_CUSTOMER_CREATE';
150  $this->trackedevents['PAYMENT_CUSTOMER_DELETE'] = 'logPAYMENT_CUSTOMER_DELETE';
151  }
152 
153  /* Supplier
154  if (!empty($conf->fournisseur->enabled)) {
155  $this->trackedevents['BILL_SUPPLIER_VALIDATE']='BlockedLogSupplierBillValidate';
156  $this->trackedevents['BILL_SUPPLIER_DELETE']='BlockedLogSupplierBillDelete';
157  $this->trackedevents['BILL_SUPPLIER_SENTBYMAIL']='BlockedLogSupplierBillSentByEmail'; // Trigger key does not exists, we want just into array to list it as done
158  $this->trackedevents['SUPPLIER_DOC_DOWNLOAD']='BlockedLogSupplierBillDownload'; // Trigger key does not exists, we want just into array to list it as done
159  $this->trackedevents['SUPPLIER_DOC_PREVIEW']='BlockedLogSupplierBillPreview'; // Trigger key does not exists, we want just into array to list it as done
160 
161  $this->trackedevents['PAYMENT_SUPPLIER_CREATE']='BlockedLogSupplierBillPaymentCreate';
162  $this->trackedevents['PAYMENT_SUPPLIER_DELETE']='BlockedLogsupplierBillPaymentCreate';
163  }
164  */
165 
166  if (!empty($conf->don->enabled)) {
167  $this->trackedevents['DON_VALIDATE'] = 'logDON_VALIDATE';
168  $this->trackedevents['DON_DELETE'] = 'logDON_DELETE';
169  //$this->trackedevents['DON_SENTBYMAIL']='logDON_SENTBYMAIL';
170  $this->trackedevents['DONATION_PAYMENT_CREATE'] = 'logDONATION_PAYMENT_CREATE';
171  $this->trackedevents['DONATION_PAYMENT_DELETE'] = 'logDONATION_PAYMENT_DELETE';
172  }
173 
174  /*
175  if (!empty($conf->salary->enabled)) {
176  $this->trackedevents['PAYMENT_SALARY_CREATE']='BlockedLogSalaryPaymentCreate';
177  $this->trackedevents['PAYMENT_SALARY_MODIFY']='BlockedLogSalaryPaymentCreate';
178  $this->trackedevents['PAYMENT_SALARY_DELETE']='BlockedLogSalaryPaymentCreate';
179  }
180  */
181 
182  if (!empty($conf->adherent->enabled)) {
183  $this->trackedevents['MEMBER_SUBSCRIPTION_CREATE'] = 'logMEMBER_SUBSCRIPTION_CREATE';
184  $this->trackedevents['MEMBER_SUBSCRIPTION_MODIFY'] = 'logMEMBER_SUBSCRIPTION_MODIFY';
185  $this->trackedevents['MEMBER_SUBSCRIPTION_DELETE'] = 'logMEMBER_SUBSCRIPTION_DELETE';
186  }
187  if (!empty($conf->banque->enabled)) {
188  $this->trackedevents['PAYMENT_VARIOUS_CREATE'] = 'logPAYMENT_VARIOUS_CREATE';
189  $this->trackedevents['PAYMENT_VARIOUS_MODIFY'] = 'logPAYMENT_VARIOUS_MODIFY';
190  $this->trackedevents['PAYMENT_VARIOUS_DELETE'] = 'logPAYMENT_VARIOUS_DELETE';
191  }
192  // $conf->global->BANK_ENABLE_POS_CASHCONTROL must be set to 1 by all external POS modules
193  $moduleposenabled = (!empty($conf->cashdesk->enabled) || !empty($conf->takepos->enabled) || !empty($conf->global->BANK_ENABLE_POS_CASHCONTROL));
194  if ($moduleposenabled) {
195  $this->trackedevents['CASHCONTROL_VALIDATE'] = 'logCASHCONTROL_VALIDATE';
196  }
197 
198  // Add more action to track from a conf variable
199  if (!empty($conf->global->BLOCKEDLOG_ADD_ACTIONS_SUPPORTED)) {
200  $tmparrayofmoresupportedevents = explode(',', $conf->global->BLOCKEDLOG_ADD_ACTIONS_SUPPORTED);
201  foreach ($tmparrayofmoresupportedevents as $val) {
202  $this->trackedevents[$val] = 'log'.$val;
203  }
204  }
205 
206  return 1;
207  }
208 
214  public function getObjectLink()
215  {
216  global $langs;
217 
218  if ($this->element === 'facture') {
219  require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
220 
221  $object = new Facture($this->db);
222  if ($object->fetch($this->fk_object) > 0) {
223  return $object->getNomUrl(1);
224  } else {
225  $this->error++;
226  }
227  }
228  if ($this->element === 'invoice_supplier') {
229  require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
230 
231  $object = new FactureFournisseur($this->db);
232  if ($object->fetch($this->fk_object) > 0) {
233  return $object->getNomUrl(1);
234  } else {
235  $this->error++;
236  }
237  } elseif ($this->element === 'payment') {
238  require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
239 
240  $object = new Paiement($this->db);
241  if ($object->fetch($this->fk_object) > 0) {
242  return $object->getNomUrl(1);
243  } else {
244  $this->error++;
245  }
246  } elseif ($this->element === 'payment_supplier') {
247  require_once DOL_DOCUMENT_ROOT.'/fourn/class/paiementfourn.class.php';
248 
249  $object = new PaiementFourn($this->db);
250  if ($object->fetch($this->fk_object) > 0) {
251  return $object->getNomUrl(1);
252  } else {
253  $this->error++;
254  }
255  } elseif ($this->element === 'payment_donation') {
256  require_once DOL_DOCUMENT_ROOT.'/don/class/paymentdonation.class.php';
257 
258  $object = new PaymentDonation($this->db);
259  if ($object->fetch($this->fk_object) > 0) {
260  return $object->getNomUrl(1);
261  } else {
262  $this->error++;
263  }
264  } elseif ($this->element === 'payment_various') {
265  require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/paymentvarious.class.php';
266 
267  $object = new PaymentVarious($this->db);
268  if ($object->fetch($this->fk_object) > 0) {
269  return $object->getNomUrl(1);
270  } else {
271  $this->error++;
272  }
273  } elseif ($this->element === 'don' || $this->element === 'donation') {
274  require_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php';
275 
276  $object = new Don($this->db);
277  if ($object->fetch($this->fk_object) > 0) {
278  return $object->getNomUrl(1);
279  } else {
280  $this->error++;
281  }
282  } elseif ($this->element === 'subscription') {
283  require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
284 
285  $object = new Subscription($this->db);
286  if ($object->fetch($this->fk_object) > 0) {
287  return $object->getNomUrl(1);
288  } else {
289  $this->error++;
290  }
291  } elseif ($this->element === 'cashcontrol') {
292  require_once DOL_DOCUMENT_ROOT.'/compta/cashcontrol/class/cashcontrol.class.php';
293 
294  $object = new CashControl($this->db);
295  if ($object->fetch($this->fk_object) > 0) {
296  return $object->getNomUrl(1);
297  } else {
298  $this->error++;
299  }
300  } elseif ($this->action == 'MODULE_SET') {
301  return '<i class="opacitymedium">'.$langs->trans("BlockedLogEnabled").'</i>';
302  } elseif ($this->action == 'MODULE_RESET') {
303  if ($this->signature == '0000000000') {
304  return '<i class="opacitymedium">'.$langs->trans("BlockedLogDisabled").'</i>';
305  } else {
306  return '<i class="opacitymedium">'.$langs->trans("BlockedLogDisabledBis").'</i>';
307  }
308  }
309 
310  return '<i class="opacitymedium">'.$langs->trans('ImpossibleToReloadObject', $this->element, $this->fk_object).'</i>';
311  }
312 
317  public function getUser()
318  {
319  global $langs, $cachedUser;
320 
321  if (empty($cachedUser)) {
322  $cachedUser = array();
323  }
324 
325  if (empty($cachedUser[$this->fk_user])) {
326  $u = new User($this->db);
327  if ($u->fetch($this->fk_user) > 0) {
328  $cachedUser[$this->fk_user] = $u;
329  }
330  }
331 
332  if (!empty($cachedUser[$this->fk_user])) {
333  return $cachedUser[$this->fk_user]->getNomUrl(1);
334  }
335 
336  return $langs->trans('ImpossibleToRetrieveUser', $this->fk_user);
337  }
338 
348  public function setObjectData(&$object, $action, $amounts, $fuser = null)
349  {
350  global $langs, $user, $mysoc;
351 
352  if (is_object($fuser)) {
353  $user = $fuser;
354  }
355 
356  // Generic fields
357 
358  // action
359  $this->action = $action;
360  // amount
361  $this->amounts = $amounts;
362  // date
363  if ($object->element == 'payment' || $object->element == 'payment_supplier') {
364  $this->date_object = $object->datepaye;
365  } elseif ($object->element == 'payment_salary') {
366  $this->date_object = $object->datev;
367  } elseif ($object->element == 'payment_donation' || $object->element == 'payment_various') {
368  $this->date_object = $object->datepaid ? $object->datepaid : $object->datep;
369  } elseif ($object->element == 'subscription') {
370  $this->date_object = $object->dateh;
371  } elseif ($object->element == 'cashcontrol') {
372  $this->date_object = $object->date_creation;
373  } else {
374  $this->date_object = $object->date;
375  }
376  // ref
377  $this->ref_object = ((!empty($object->newref)) ? $object->newref : $object->ref); // newref is set when validating a draft, ref is set in other cases
378  // type of object
379  $this->element = $object->element;
380  // id of object
381  $this->fk_object = $object->id;
382 
383 
384  // Set object_data
385  $this->object_data = new stdClass();
386  // Add fields to exclude
387  $arrayoffieldstoexclude = array(
388  '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',
389  'table_element_line', 'ismultientitymanaged', 'isextrafieldmanaged',
390  'linkedObjectsIds',
391  'linkedObjects',
392  'fk_delivery_address',
393  'context',
394  'projet' // There is already ->fk_project
395  );
396  // Add more fields to exclude depending on object type
397  if ($this->element == 'cashcontrol') {
398  $arrayoffieldstoexclude = array_merge($arrayoffieldstoexclude, array(
399  'name', 'lastname', 'firstname', 'region', 'region_id', 'region_code', 'state', 'state_id', 'state_code', 'country', 'country_id', 'country_code',
400  'total_ht', 'total_tva', 'total_ttc', 'total_localtax1', 'total_localtax2',
401  'barcode_type', 'barcode_type_code', 'barcode_type_label', 'barcode_type_coder', 'mode_reglement_id', 'cond_reglement_id', 'mode_reglement', 'cond_reglement', 'shipping_method_id',
402  'fk_incoterms', 'label_incoterms', 'location_incoterms', 'lines'));
403  }
404 
405  // Add thirdparty info
406  if (empty($object->thirdparty) && method_exists($object, 'fetch_thirdparty')) {
407  $object->fetch_thirdparty();
408  }
409  if (!empty($object->thirdparty)) {
410  $this->object_data->thirdparty = new stdClass();
411 
412  foreach ($object->thirdparty as $key => $value) {
413  if (in_array($key, $arrayoffieldstoexclude)) {
414  continue; // Discard some properties
415  }
416  if (!in_array($key, array(
417  'name', 'name_alias', 'ref_ext', 'address', 'zip', 'town', 'state_code', 'country_code', 'idprof1', 'idprof2', 'idprof3', 'idprof4', 'idprof5', 'idprof6', 'phone', 'fax', 'email', 'barcode',
418  'tva_intra', 'localtax1_assuj', 'localtax1_value', 'localtax2_assuj', 'localtax2_value', 'managers', 'capital', 'typent_code', 'forme_juridique_code', 'code_client', 'code_fournisseur'
419  ))) {
420  continue; // Discard if not into a dedicated list
421  }
422  if (!is_object($value) && !is_null($value) && $value !== '') {
423  $this->object_data->thirdparty->{$key} = $value;
424  }
425  }
426  }
427 
428  // Add company info
429  if (!empty($mysoc)) {
430  $this->object_data->mycompany = new stdClass();
431 
432  foreach ($mysoc as $key => $value) {
433  if (in_array($key, $arrayoffieldstoexclude)) {
434  continue; // Discard some properties
435  }
436  if (!in_array($key, array(
437  'name', 'name_alias', 'ref_ext', 'address', 'zip', 'town', 'state_code', 'country_code', 'idprof1', 'idprof2', 'idprof3', 'idprof4', 'idprof5', 'idprof6', 'phone', 'fax', 'email', 'barcode',
438  'tva_intra', 'localtax1_assuj', 'localtax1_value', 'localtax2_assuj', 'localtax2_value', 'managers', 'capital', 'typent_code', 'forme_juridique_code', 'code_client', 'code_fournisseur'
439  ))) {
440  continue; // Discard if not into a dedicated list
441  }
442  if (!is_object($value) && !is_null($value) && $value !== '') {
443  $this->object_data->mycompany->{$key} = $value;
444  }
445  }
446  }
447 
448  // Add user info
449  if (!empty($user)) {
450  $this->fk_user = $user->id;
451  $this->user_fullname = $user->getFullName($langs);
452  }
453 
454  // Field specific to object
455  if ($this->element == 'facture') {
456  foreach ($object as $key => $value) {
457  if (in_array($key, $arrayoffieldstoexclude)) {
458  continue; // Discard some properties
459  }
460  if (!in_array($key, array(
461  'ref', 'ref_client', 'ref_supplier', 'date', 'datef', 'datev', 'type', 'total_ht', 'total_tva', 'total_ttc', 'localtax1', 'localtax2', 'revenuestamp', 'datepointoftax', 'note_public', 'lines'
462  ))) {
463  continue; // Discard if not into a dedicated list
464  }
465  if ($key == 'lines') {
466  $lineid = 0;
467  foreach ($value as $tmpline) { // $tmpline is object FactureLine
468  $lineid++;
469  foreach ($tmpline as $keyline => $valueline) {
470  if (!in_array($keyline, array(
471  'ref', 'multicurrency_code', 'multicurrency_total_ht', 'multicurrency_total_tva', 'multicurrency_total_ttc', 'qty', 'product_type', 'vat_src_code', 'tva_tx', 'info_bits', 'localtax1_tx', 'localtax2_tx', 'total_ht', 'total_tva', 'total_ttc', 'total_localtax1', 'total_localtax2'
472  ))) {
473  continue; // Discard if not into a dedicated list
474  }
475 
476  if (empty($this->object_data->invoiceline[$lineid]) || !is_object($this->object_data->invoiceline[$lineid])) { // To avoid warning
477  $this->object_data->invoiceline[$lineid] = new stdClass();
478  }
479 
480  if (!is_object($valueline) && !is_null($valueline) && $valueline !== '') {
481  $this->object_data->invoiceline[$lineid]->{$keyline} = $valueline;
482  }
483  }
484  }
485  } elseif (!is_object($value) && !is_null($value) && $value !== '') {
486  $this->object_data->{$key} = $value;
487  }
488  }
489 
490  if (!empty($object->newref)) {
491  $this->object_data->ref = $object->newref;
492  }
493  } elseif ($this->element == 'invoice_supplier') {
494  foreach ($object as $key => $value) {
495  if (in_array($key, $arrayoffieldstoexclude)) {
496  continue; // Discard some properties
497  }
498  if (!in_array($key, array(
499  'ref', 'ref_client', 'ref_supplier', 'date', 'datef', 'type', 'total_ht', 'total_tva', 'total_ttc', 'localtax1', 'localtax2', 'revenuestamp', 'datepointoftax', 'note_public'
500  ))) {
501  continue; // Discard if not into a dedicated list
502  }
503  if (!is_object($value) && !is_null($value) && $value !== '') {
504  $this->object_data->{$key} = $value;
505  }
506  }
507 
508  if (!empty($object->newref)) {
509  $this->object_data->ref = $object->newref;
510  }
511  } elseif ($this->element == 'payment' || $this->element == 'payment_supplier' || $this->element == 'payment_donation' || $this->element == 'payment_various') {
512  $datepayment = $object->datepaye ? $object->datepaye : ($object->datepaid ? $object->datepaid : $object->datep);
513  $paymenttypeid = $object->paiementid ? $object->paiementid : ($object->paymenttype ? $object->paymenttype : $object->type_payment);
514 
515  $this->object_data->ref = $object->ref;
516  $this->object_data->date = $datepayment;
517  $this->object_data->type_code = dol_getIdFromCode($this->db, $paymenttypeid, 'c_paiement', 'id', 'code');
518 
519  if (!empty($object->num_payment)) {
520  $this->object_data->payment_num = $object->num_payment;
521  }
522  if (!empty($object->note_private)) {
523  $this->object_data->note_private = $object->note_private;
524  }
525  //$this->object_data->fk_account = $object->fk_account;
526  //var_dump($this->object_data);exit;
527 
528  $totalamount = 0;
529 
530  // Loop on each invoice payment amount
531  if (is_array($object->amounts) && !empty($object->amounts)) {
532  $paymentpartnumber = 0;
533  foreach ($object->amounts as $objid => $amount) {
534  if (empty($amount)) {
535  continue;
536  }
537 
538  $totalamount += $amount;
539 
540  $tmpobject = null;
541  if ($this->element == 'payment_supplier') {
542  include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
543  $tmpobject = new FactureFournisseur($this->db);
544  } elseif ($this->element == 'payment') {
545  include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
546  $tmpobject = new Facture($this->db);
547  } elseif ($this->element == 'payment_donation') {
548  include_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php';
549  $tmpobject = new Don($this->db);
550  } elseif ($this->element == 'payment_various') {
551  include_once DOL_DOCUMENT_ROOT.'/compta/bank/class/paymentvarious.class.php';
552  $tmpobject = new PaymentVarious($this->db);
553  }
554 
555  if (!is_object($tmpobject)) {
556  continue;
557  }
558 
559  $result = $tmpobject->fetch($objid);
560 
561  if ($result <= 0) {
562  $this->error = $tmpobject->error;
563  $this->errors = $tmpobject->errors;
564  dol_syslog("Failed to fetch object with id ".$objid, LOG_ERR);
565  return -1;
566  }
567 
568  $paymentpart = new stdClass();
569  $paymentpart->amount = $amount;
570 
571  if (!in_array($this->element, array('payment_donation', 'payment_various'))) {
572  $result = $tmpobject->fetch_thirdparty();
573  if ($result == 0) {
574  $this->error = 'Failed to fetch thirdparty for object with id '.$tmpobject->id;
575  $this->errors[] = $this->error;
576  dol_syslog("Failed to fetch thirdparty for object with id ".$tmpobject->id, LOG_ERR);
577  return -1;
578  } elseif ($result < 0) {
579  $this->error = $tmpobject->error;
580  $this->errors = $tmpobject->errors;
581  return -1;
582  }
583 
584  $paymentpart->thirdparty = new stdClass();
585  foreach ($tmpobject->thirdparty as $key => $value) {
586  if (in_array($key, $arrayoffieldstoexclude)) {
587  continue; // Discard some properties
588  }
589  if (!in_array($key, array(
590  'name', 'name_alias', 'ref_ext', 'address', 'zip', 'town', 'state_code', 'country_code', 'idprof1', 'idprof2', 'idprof3', 'idprof4', 'idprof5', 'idprof6', 'phone', 'fax', 'email', 'barcode',
591  'tva_intra', 'localtax1_assuj', 'localtax1_value', 'localtax2_assuj', 'localtax2_value', 'managers', 'capital', 'typent_code', 'forme_juridique_code', 'code_client', 'code_fournisseur'
592  ))) {
593  continue; // Discard if not into a dedicated list
594  }
595  if (!is_object($value) && !is_null($value) && $value !== '') {
596  $paymentpart->thirdparty->{$key} = $value;
597  }
598  }
599  }
600 
601  // Init object to avoid warnings
602  if ($this->element == 'payment_donation') {
603  $paymentpart->donation = new stdClass();
604  } else {
605  $paymentpart->invoice = new stdClass();
606  }
607 
608  if ($this->element != 'payment_various') {
609  foreach ($tmpobject as $key => $value) {
610  if (in_array($key, $arrayoffieldstoexclude)) {
611  continue; // Discard some properties
612  }
613  if (!in_array($key, array(
614  'ref', 'ref_client', 'ref_supplier', 'date', 'datef', 'type', 'total_ht', 'total_tva', 'total_ttc', 'localtax1', 'localtax2', 'revenuestamp', 'datepointoftax', 'note_public'
615  ))) {
616  continue; // Discard if not into a dedicated list
617  }
618  if (!is_object($value) && !is_null($value) && $value !== '') {
619  if ($this->element == 'payment_donation') {
620  $paymentpart->donation->{$key} = $value;
621  } elseif ($this->element == 'payment_various') {
622  $paymentpart->various->{$key} = $value;
623  } else {
624  $paymentpart->invoice->{$key} = $value;
625  }
626  }
627  }
628 
629  $paymentpartnumber++; // first payment will be 1
630  $this->object_data->payment_part[$paymentpartnumber] = $paymentpart;
631  }
632  }
633  } elseif (!empty($object->amount)) {
634  $totalamount = $object->amount;
635  }
636 
637  $this->object_data->amount = $totalamount;
638 
639  if (!empty($object->newref)) {
640  $this->object_data->ref = $object->newref;
641  }
642  } elseif ($this->element == 'payment_salary') {
643  $this->object_data->amounts = array($object->amount);
644 
645  if (!empty($object->newref)) {
646  $this->object_data->ref = $object->newref;
647  }
648  } elseif ($this->element == 'subscription') {
649  foreach ($object as $key => $value) {
650  if (in_array($key, $arrayoffieldstoexclude)) {
651  continue; // Discard some properties
652  }
653  if (!in_array($key, array(
654  'id', 'datec', 'dateh', 'datef', 'fk_adherent', 'amount', 'import_key', 'statut', 'note'
655  ))) {
656  continue; // Discard if not into a dedicated list
657  }
658  if (!is_object($value) && !is_null($value) && $value !== '') {
659  $this->object_data->{$key} = $value;
660  }
661  }
662 
663  if (!empty($object->newref)) {
664  $this->object_data->ref = $object->newref;
665  }
666  } else // Generic case
667  {
668  foreach ($object as $key => $value) {
669  if (in_array($key, $arrayoffieldstoexclude)) {
670  continue; // Discard some properties
671  }
672  if (!is_object($value) && !is_null($value) && $value !== '') {
673  $this->object_data->{$key} = $value;
674  }
675  }
676 
677  if (!empty($object->newref)) {
678  $this->object_data->ref = $object->newref;
679  }
680  }
681 
682  return 1;
683  }
684 
691  public function fetch($id)
692  {
693  global $langs;
694 
695  if (empty($id)) {
696  $this->error = 'BadParameter';
697  return -1;
698  }
699 
700  $sql = "SELECT b.rowid, b.date_creation, b.signature, b.signature_line, b.amounts, b.action, b.element, b.fk_object, b.entity,";
701  $sql .= " b.certified, b.tms, b.fk_user, b.user_fullname, b.date_object, b.ref_object, b.object_data, b.object_version";
702  $sql .= " FROM ".MAIN_DB_PREFIX."blockedlog as b";
703  if ($id) {
704  $sql .= " WHERE b.rowid = ".((int) $id);
705  }
706 
707  $resql = $this->db->query($sql);
708  if ($resql) {
709  $obj = $this->db->fetch_object($resql);
710  if ($obj) {
711  $this->id = $obj->rowid;
712  $this->entity = $obj->entity;
713  $this->ref = $obj->rowid;
714 
715  $this->date_creation = $this->db->jdate($obj->date_creation);
716  $this->tms = $this->db->jdate($obj->tms);
717 
718  $this->amounts = (double) $obj->amounts;
719  $this->action = $obj->action;
720  $this->element = $obj->element;
721 
722  $this->fk_object = $obj->fk_object;
723  $this->date_object = $this->db->jdate($obj->date_object);
724  $this->ref_object = $obj->ref_object;
725 
726  $this->fk_user = $obj->fk_user;
727  $this->user_fullname = $obj->user_fullname;
728 
729  $this->object_data = $this->dolDecodeBlockedData($obj->object_data);
730  $this->object_version = $obj->object_version;
731 
732  $this->signature = $obj->signature;
733  $this->signature_line = $obj->signature_line;
734  $this->certified = ($obj->certified == 1);
735 
736  return 1;
737  } else {
738  $langs->load("blockedlog");
739  $this->error = $langs->trans("RecordNotFound");
740  return 0;
741  }
742  } else {
743  $this->error = $this->db->error();
744  return -1;
745  }
746  }
747 
748 
756  public function dolDecodeBlockedData($data, $mode = 0)
757  {
758  try {
759  //include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
760  $aaa = unserialize($data);
761  } catch (Exception $e) {
762  //print $e->getErrs);
763  }
764  return $aaa;
765  }
766 
767 
773  public function setCertified()
774  {
775 
776  $res = $this->db->query("UPDATE ".MAIN_DB_PREFIX."blockedlog SET certified=1 WHERE rowid=".((int) $this->id));
777  if (!$res) {
778  return false;
779  }
780 
781  return true;
782  }
783 
791  public function create($user, $forcesignature = '')
792  {
793  global $conf, $langs, $hookmanager;
794 
795  $langs->load('blockedlog');
796 
797  $error = 0;
798 
799  // Clean data
800  $this->amounts = (double) $this->amounts;
801 
802  dol_syslog(get_class($this).'::create action='.$this->action.' fk_user='.$this->fk_user.' user_fullname='.$this->user_fullname, LOG_DEBUG);
803 
804  // Check parameters/properties
805  if (!isset($this->amounts)) { // amount can be 0 for some events (like when module is disabled)
806  $this->error = $langs->trans("BlockLogNeedAmountsValue");
807  dol_syslog($this->error, LOG_WARNING);
808  return -1;
809  }
810 
811  if (empty($this->element)) {
812  $this->error = $langs->trans("BlockLogNeedElement");
813  dol_syslog($this->error, LOG_WARNING);
814  return -2;
815  }
816 
817  if (empty($this->action)) {
818  $this->error = $langs->trans("BadParameterWhenCallingCreateOfBlockedLog");
819  dol_syslog($this->error, LOG_WARNING);
820  return -3;
821  }
822  if (empty($this->fk_user)) {
823  $this->user_fullname = '(Anonymous)';
824  }
825 
826  $this->date_creation = dol_now();
827 
828  $this->db->begin();
829 
830  $previoushash = $this->getPreviousHash(1, 0); // This get last record and lock database until insert is done
831 
832  $keyforsignature = $this->buildKeyForSignature();
833 
834  include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
835 
836  $this->signature_line = dol_hash($keyforsignature, '5'); // Not really usefull
837  $this->signature = dol_hash($previoushash.$keyforsignature, '5');
838  if ($forcesignature) {
839  $this->signature = $forcesignature;
840  }
841  //var_dump($keyforsignature);var_dump($previoushash);var_dump($this->signature_line);var_dump($this->signature);
842 
843  $sql = "INSERT INTO ".MAIN_DB_PREFIX."blockedlog (";
844  $sql .= " date_creation,";
845  $sql .= " action,";
846  $sql .= " amounts,";
847  $sql .= " signature,";
848  $sql .= " signature_line,";
849  $sql .= " element,";
850  $sql .= " fk_object,";
851  $sql .= " date_object,";
852  $sql .= " ref_object,";
853  $sql .= " object_data,";
854  $sql .= " object_version,";
855  $sql .= " certified,";
856  $sql .= " fk_user,";
857  $sql .= " user_fullname,";
858  $sql .= " entity";
859  $sql .= ") VALUES (";
860  $sql .= "'".$this->db->idate($this->date_creation)."',";
861  $sql .= "'".$this->db->escape($this->action)."',";
862  $sql .= $this->amounts.",";
863  $sql .= "'".$this->db->escape($this->signature)."',";
864  $sql .= "'".$this->db->escape($this->signature_line)."',";
865  $sql .= "'".$this->db->escape($this->element)."',";
866  $sql .= $this->fk_object.",";
867  $sql .= "'".$this->db->idate($this->date_object)."',";
868  $sql .= "'".$this->db->escape($this->ref_object)."',";
869  $sql .= "'".$this->db->escape(serialize($this->object_data))."',";
870  $sql .= "'".$this->db->escape($this->object_version)."',";
871  $sql .= "0,";
872  $sql .= $this->fk_user.",";
873  $sql .= "'".$this->db->escape($this->user_fullname)."',";
874  $sql .= ($this->entity ? $this->entity : $conf->entity);
875  $sql .= ")";
876 
877  $res = $this->db->query($sql);
878  if ($res) {
879  $id = $this->db->last_insert_id(MAIN_DB_PREFIX."blockedlog");
880 
881  if ($id > 0) {
882  $this->id = $id;
883 
884  $this->db->commit();
885 
886  return $this->id;
887  } else {
888  $this->db->rollback();
889  return -2;
890  }
891  } else {
892  $this->error = $this->db->error();
893  $this->db->rollback();
894  return -1;
895  }
896 
897  // The commit will release the lock so we can insert nex record
898  }
899 
907  public function checkSignature($previoushash = '', $returnarray = 0)
908  {
909  if (empty($previoushash)) {
910  $previoushash = $this->getPreviousHash(0, $this->id);
911  }
912  // Recalculate hash
913  $keyforsignature = $this->buildKeyForSignature();
914 
915  //$signature_line = dol_hash($keyforsignature, '5'); // Not really usefull
916  $signature = dol_hash($previoushash.$keyforsignature, '5');
917  //var_dump($previoushash); var_dump($keyforsignature); var_dump($signature_line); var_dump($signature);
918 
919  $res = ($signature === $this->signature);
920 
921  if (!$res) {
922  $this->error = 'Signature KO';
923  }
924 
925  if ($returnarray) {
926  if ($returnarray == 1) {
927  unset($keyforsignature);
928  return array('checkresult' => $res, 'calculatedsignature' => $signature, 'previoushash' => $previoushash);
929  } else { // Consume much memory ($keyforsignature is a large var)
930  return array('checkresult' => $res, 'calculatedsignature' => $signature, 'previoushash' => $previoushash, 'keyforsignature'=>$keyforsignature);
931  }
932  } else {
933  unset($keyforsignature);
934  return $res;
935  }
936  }
937 
945  private function buildKeyForSignature()
946  {
947  //print_r($this->object_data);
948  if (((int) $this->object_version) > 12) {
949  return $this->date_creation.'|'.$this->action.'|'.$this->amounts.'|'.$this->ref_object.'|'.$this->date_object.'|'.$this->user_fullname.'|'.print_r($this->object_data, true);
950  } else {
951  return $this->date_creation.'|'.$this->action.'|'.$this->amounts.'|'.$this->ref_object.'|'.$this->date_object.'|'.$this->user_fullname.'|'.print_r($this->object_data, true);
952  }
953  }
954 
955 
963  public function getPreviousHash($withlock = 0, $beforeid = 0)
964  {
965  global $conf;
966 
967  $previoussignature = '';
968 
969  $sql = "SELECT rowid, signature FROM ".MAIN_DB_PREFIX."blockedlog";
970  $sql .= " WHERE entity=".$conf->entity;
971  if ($beforeid) {
972  $sql .= " AND rowid < ".(int) $beforeid;
973  }
974  $sql .= " ORDER BY rowid DESC LIMIT 1";
975  $sql .= ($withlock ? " FOR UPDATE " : "");
976 
977  $resql = $this->db->query($sql);
978  if ($resql) {
979  $obj = $this->db->fetch_object($resql);
980  if ($obj) {
981  $previoussignature = $obj->signature;
982  }
983  } else {
984  dol_print_error($this->db);
985  exit;
986  }
987 
988  if (empty($previoussignature)) {
989  // First signature line (line 0)
990  $previoussignature = $this->getSignature();
991  }
992 
993  return $previoussignature;
994  }
995 
1012  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 = '')
1013  {
1014  global $conf;
1015  //global $cachedlogs;
1016 
1017  /* $cachedlogs allow fastest search */
1018  //if (empty($cachedlogs)) $cachedlogs = array();
1019 
1020  if ($element == 'all') {
1021  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
1022  WHERE entity=".$conf->entity;
1023  } elseif ($element == 'not_certified') {
1024  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
1025  WHERE entity=".$conf->entity." AND certified = 0";
1026  } elseif ($element == 'just_certified') {
1027  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
1028  WHERE entity=".$conf->entity." AND certified = 1";
1029  } else {
1030  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
1031  WHERE entity=".$conf->entity." AND element='".$this->db->escape($element)."'";
1032  }
1033 
1034  if ($fk_object) {
1035  $sql .= natural_search("rowid", $fk_object, 1);
1036  }
1037  if ($search_fk_user > 0) {
1038  $sql .= natural_search("fk_user", $search_fk_user, 2);
1039  }
1040  if ($search_start > 0) {
1041  $sql .= " AND date_creation >= '".$this->db->idate($search_start)."'";
1042  }
1043  if ($search_end > 0) {
1044  $sql .= " AND date_creation <= '".$this->db->idate($search_end)."'";
1045  }
1046  if ($search_ref != '') {
1047  $sql .= natural_search("ref_object", $search_ref);
1048  }
1049  if ($search_amount != '') {
1050  $sql .= natural_search("amounts", $search_amount, 1);
1051  }
1052  if ($search_code != '' && $search_code != '-1') {
1053  $sql .= natural_search("action", $search_code, 3);
1054  }
1055 
1056  $sql .= $this->db->order($sortfield, $sortorder);
1057  $sql .= $this->db->plimit($limit + 1); // We want more, because we will stop into loop later with error if we reach max
1058 
1059  $res = $this->db->query($sql);
1060  if ($res) {
1061  $results = array();
1062 
1063  $i = 0;
1064  while ($obj = $this->db->fetch_object($res)) {
1065  $i++;
1066  if ($i > $limit) {
1067  // Too many record, we will consume too much memory
1068  return -2;
1069  }
1070 
1071  //if (!isset($cachedlogs[$obj->rowid]))
1072  //{
1073  $b = new BlockedLog($this->db);
1074  $b->fetch($obj->rowid);
1075  //$b->loadTrackedEvents();
1076  //$cachedlogs[$obj->rowid] = $b;
1077  //}
1078 
1079  //$results[] = $cachedlogs[$obj->rowid];
1080  $results[] = $b;
1081  }
1082 
1083  return $results;
1084  }
1085 
1086  return -1;
1087  }
1088 
1094  public function getSignature()
1095  {
1096  global $db, $conf, $mysoc;
1097 
1098  if (empty($conf->global->BLOCKEDLOG_ENTITY_FINGERPRINT)) { // creation of a unique fingerprint
1099  require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
1100  require_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
1101  require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
1102 
1103  $fingerprint = dol_hash(print_r($mysoc, true).getRandomPassword(1), '5');
1104 
1105  dolibarr_set_const($db, 'BLOCKEDLOG_ENTITY_FINGERPRINT', $fingerprint, 'chaine', 0, 'Numeric Unique Fingerprint', $conf->entity);
1106 
1107  $conf->global->BLOCKEDLOG_ENTITY_FINGERPRINT = $fingerprint;
1108  }
1109 
1110  return $conf->global->BLOCKEDLOG_ENTITY_FINGERPRINT;
1111  }
1112 
1113 
1120  public function alreadyUsed($ignoresystem = 0)
1121  {
1122  global $conf;
1123 
1124  $result = false;
1125 
1126  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog";
1127  $sql .= " WHERE entity = ".$conf->entity;
1128  if ($ignoresystem) {
1129  $sql .= " AND action not in ('MODULE_SET','MODULE_RESET')";
1130  }
1131  $sql .= $this->db->plimit(1);
1132 
1133  $res = $this->db->query($sql);
1134  if ($res !== false) {
1135  $obj = $this->db->fetch_object($res);
1136  if ($obj) {
1137  $result = true;
1138  }
1139  } else {
1140  dol_print_error($this->db);
1141  }
1142 
1143  dol_syslog("Module Blockedlog alreadyUsed with ignoresystem=".$ignoresystem." is ".$result);
1144 
1145  return $result;
1146  }
1147 }
BlockedLog\setObjectData
setObjectData(&$object, $action, $amounts, $fuser=null)
Populate properties of log from object data.
Definition: blockedlog.class.php:348
db
$conf db
API class for accounts.
Definition: inc.php:41
CashControl
Class to manage cash fence.
Definition: cashcontrol.class.php:30
DoliDB
Class to manage Dolibarr database access.
Definition: DoliDB.class.php:30
BlockedLog\dolDecodeBlockedData
dolDecodeBlockedData($data, $mode=0)
Decode data.
Definition: blockedlog.class.php:756
FactureFournisseur
Class to manage suppliers invoices.
Definition: fournisseur.facture.class.php:53
dol_print_error
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
Definition: functions.lib.php:4844
PaymentDonation
Class to manage payments of donations.
Definition: paymentdonation.class.php:30
BlockedLog\buildKeyForSignature
buildKeyForSignature()
Return a string for signature.
Definition: blockedlog.class.php:945
ref
$object ref
Definition: info.php:77
Don
Class to manage donations.
Definition: don.class.php:38
Facture
Class to manage invoices.
Definition: facture.class.php:60
BlockedLog\getSignature
getSignature()
Return the signature (hash) of the "genesis-block" (Block 0).
Definition: blockedlog.class.php:1094
BlockedLog\setCertified
setCertified()
Set block certified by authority.
Definition: blockedlog.class.php:773
getRandomPassword
getRandomPassword($generic=false, $replaceambiguouschars=null, $length=32)
Return a generated password using default module.
Definition: security2.lib.php:454
PaymentVarious
Class to manage various payments.
Definition: paymentvarious.class.php:32
dol_hash
dol_hash($chain, $type='0')
Returns a hash of a string.
Definition: security.lib.php:104
Exception
BlockedLog\fetch
fetch($id)
Get object from database.
Definition: blockedlog.class.php:691
BlockedLog
Class to manage Blocked Log.
Definition: blockedlog.class.php:26
dol_getIdFromCode
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='')
Return an id or code from a code or id.
Definition: functions.lib.php:8535
BlockedLog\alreadyUsed
alreadyUsed($ignoresystem=0)
Check if module was already used or not for at least one recording.
Definition: blockedlog.class.php:1120
dol_syslog
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
Definition: functions.lib.php:1603
BlockedLog\getPreviousHash
getPreviousHash($withlock=0, $beforeid=0)
Get previous signature/hash in chain.
Definition: blockedlog.class.php:963
Subscription
Class to manage subscriptions of foundation members.
Definition: subscription.class.php:33
isModEnabled
isModEnabled($module)
Is Dolibarr module enabled.
Definition: functions.lib.php:105
BlockedLog\getObjectLink
getObjectLink()
Try to retrieve source object (it it still exists).
Definition: blockedlog.class.php:214
dolibarr_set_const
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).
Definition: admin.lib.php:627
PaiementFourn
Class to manage payments for supplier invoices.
Definition: paiementfourn.class.php:37
User
Class to manage Dolibarr users.
Definition: user.class.php:44
BlockedLog\getUser
getUser()
Definition: blockedlog.class.php:317
Paiement
Class to manage payments of customer invoices.
Definition: paiement.class.php:41
natural_search
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...
Definition: functions.lib.php:9420
BlockedLog\getLog
getLog($element, $fk_object, $limit=0, $sortfield='', $sortorder='', $search_fk_user=-1, $search_start=-1, $search_end=-1, $search_ref='', $search_amount='', $search_code='')
Return array of log objects (with criterias)
Definition: blockedlog.class.php:1012
BlockedLog\__construct
__construct(DoliDB $db)
Constructor.
Definition: blockedlog.class.php:126
dol_now
dol_now($mode='auto')
Return date for now.
Definition: functions.lib.php:2845
$resql
if(isModEnabled('facture') &&!empty($user->rights->facture->lire)) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->lire)||(isModEnabled('supplier_invoice') && $user->rights->supplier_invoice->lire)) if(isModEnabled('don') &&!empty($user->rights->don->lire)) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $resql
Social contributions to pay.
Definition: index.php:742
BlockedLog\loadTrackedEvents
loadTrackedEvents()
Load list of tracked events into $this->trackedevents.
Definition: blockedlog.class.php:137
BlockedLog\create
create($user, $forcesignature='')
Create blocked log in database.
Definition: blockedlog.class.php:791
BlockedLog\checkSignature
checkSignature($previoushash='', $returnarray=0)
Check if current signature still correct compared to the value in chain.
Definition: blockedlog.class.php:907