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