dolibarr  9.0.0
blockedlog.class.php
1 <?php
2 /* Copyright (C) 2017 ATM Consulting <contact@atm-consulting.fr>
3  * Copyright (C) 2017 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 <http://www.gnu.org/licenses/>.
17  *
18  * See https://medium.com/@lhartikk/a-blockchain-in-200-lines-of-code-963cc1cc0e54
19  */
20 
21 /*ini_set('unserialize_callback_func', 'mycallback');
22 
23 function mycallback($classname)
24 {
25  //var_dump($classname);
26  include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
27 
28 }*/
29 
30 
31 
36 {
41  public $id;
42 
47  public $entity;
48 
52  public $error = '';
53 
57  public $errors = array();
58 
63  public $signature = '';
64 
69  public $signature_line = '';
70 
71  public $amounts = null;
72 
77  public $action = '';
78 
83  public $element = '';
84 
89  public $fk_object = 0;
90 
95  public $certified = false;
96 
101  public $fk_user = 0;
102 
103  public $date_creation;
104  public $date_modification;
105 
106  public $date_object = 0;
107 
108  public $ref_object = '';
109 
110  public $object_data = null;
111  public $user_fullname='';
112 
117  public $trackedevents = array();
118 
119 
120 
126  public function __construct(DoliDB $db)
127  {
128  global $conf;
129 
130  $this->db = $db;
131 
132  $this->trackedevents = array();
133 
134  if ($conf->facture->enabled) $this->trackedevents['BILL_VALIDATE']='logBILL_VALIDATE';
135  if ($conf->facture->enabled) $this->trackedevents['BILL_DELETE']='logBILL_DELETE';
136  if ($conf->facture->enabled) $this->trackedevents['BILL_SENTBYMAIL']='logBILL_SENTBYMAIL';
137  if ($conf->facture->enabled) $this->trackedevents['DOC_DOWNLOAD']='BlockedLogBillDownload';
138  if ($conf->facture->enabled) $this->trackedevents['DOC_PREVIEW']='BlockedLogBillPreview';
139 
140  if ($conf->facture->enabled) $this->trackedevents['PAYMENT_CUSTOMER_CREATE']='logPAYMENT_CUSTOMER_CREATE';
141  if ($conf->facture->enabled) $this->trackedevents['PAYMENT_CUSTOMER_DELETE']='logPAYMENT_CUSTOMER_DELETE';
142 
143  /* Supplier
144  if ($conf->fournisseur->enabled) $this->trackedevents['BILL_SUPPLIER_VALIDATE']='BlockedLogSupplierBillValidate';
145  if ($conf->fournisseur->enabled) $this->trackedevents['BILL_SUPPLIER_DELETE']='BlockedLogSupplierBillDelete';
146  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
147  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
148  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
149 
150  if ($conf->fournisseur->enabled) $this->trackedevents['PAYMENT_SUPPLIER_CREATE']='BlockedLogSupplierBillPaymentCreate';
151  if ($conf->fournisseur->enabled) $this->trackedevents['PAYMENT_SUPPLIER_DELETE']='BlockedLogsupplierBillPaymentCreate';
152  */
153 
154  if ($conf->don->enabled) $this->trackedevents['DON_VALIDATE']='logDON_VALIDATE';
155  if ($conf->don->enabled) $this->trackedevents['DON_DELETE']='logDON_DELETE';
156  //if ($conf->don->enabled) $this->trackedevents['DON_SENTBYMAIL']='logDON_SENTBYMAIL';
157 
158  if ($conf->don->enabled) $this->trackedevents['DONATION_PAYMENT_CREATE']='logDONATION_PAYMENT_CREATE';
159  if ($conf->don->enabled) $this->trackedevents['DONATION_PAYMENT_DELETE']='logDONATION_PAYMENT_DELETE';
160 
161  /*
162  if ($conf->salary->enabled) $this->trackedevents['PAYMENT_SALARY_CREATE']='BlockedLogSalaryPaymentCreate';
163  if ($conf->salary->enabled) $this->trackedevents['PAYMENT_SALARY_MODIFY']='BlockedLogSalaryPaymentCreate';
164  if ($conf->salary->enabled) $this->trackedevents['PAYMENT_SALARY_DELETE']='BlockedLogSalaryPaymentCreate';
165  */
166 
167  if ($conf->adherent->enabled) $this->trackedevents['MEMBER_SUBSCRIPTION_CREATE']='logMEMBER_SUBSCRIPTION_CREATE';
168  if ($conf->adherent->enabled) $this->trackedevents['MEMBER_SUBSCRIPTION_MODIFY']='logMEMBER_SUBSCRIPTION_MODIFY';
169  if ($conf->adherent->enabled) $this->trackedevents['MEMBER_SUBSCRIPTION_DELETE']='logMEMBER_SUBSCRIPTION_DELETE';
170 
171 
172  if ($conf->banque->enabled) $this->trackedevents['PAYMENT_VARIOUS_CREATE']='logPAYMENT_VARIOUS_CREATE';
173  if ($conf->banque->enabled) $this->trackedevents['PAYMENT_VARIOUS_MODIFY']='logPAYMENT_VARIOUS_MODIFY';
174  if ($conf->banque->enabled) $this->trackedevents['PAYMENT_VARIOUS_DELETE']='logPAYMENT_VARIOUS_DELETE';
175 
176  // $conf->global->BANK_ENABLE_POS_CASHCONTROL must be set to 1 by all POS modules
177  $moduleposenabled = ($conf->cashdesk->enabled || $conf->takepos->enabled || ! empty($conf->global->BANK_ENABLE_POS_CASHCONTROL));
178  if ($moduleposenabled) $this->trackedevents['CASHCONTROL_VALIDATE']='logCASHCONTROL_VALIDATE';
179  }
180 
185  public function getObjectLink()
186  {
187  global $langs;
188 
189  if($this->element === 'facture') {
190  require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
191 
192  $object = new Facture($this->db);
193  if ($object->fetch($this->fk_object)>0) {
194  return $object->getNomUrl(1);
195  }
196  else{
197  $this->error++;
198  }
199  }
200  if($this->element === 'invoice_supplier') {
201  require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
202 
203  $object = new FactureFournisseur($this->db);
204  if ($object->fetch($this->fk_object)>0) {
205  return $object->getNomUrl(1);
206  }
207  else{
208  $this->error++;
209  }
210  }
211  else if($this->element === 'payment') {
212  require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
213 
214  $object = new Paiement($this->db);
215  if ($object->fetch($this->fk_object)>0) {
216  return $object->getNomUrl(1);
217  }
218  else{
219  $this->error++;
220  }
221  }
222  else if($this->element === 'payment_supplier') {
223  require_once DOL_DOCUMENT_ROOT.'/fourn/class/paiementfourn.class.php';
224 
225  $object = new PaiementFourn($this->db);
226  if ($object->fetch($this->fk_object)>0) {
227  return $object->getNomUrl(1);
228  }
229  else{
230  $this->error++;
231  }
232  }
233  else if($this->element === 'payment_donation') {
234  require_once DOL_DOCUMENT_ROOT.'/don/class/paymentdonation.class.php';
235 
236  $object = new PaymentDonation($this->db);
237  if ($object->fetch($this->fk_object)>0) {
238  return $object->getNomUrl(1);
239  }
240  else{
241  $this->error++;
242  }
243  }
244  else if($this->element === 'payment_various') {
245  require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/paymentvarious.class.php';
246 
247  $object = new PaymentVarious($this->db);
248  if ($object->fetch($this->fk_object)>0) {
249  return $object->getNomUrl(1);
250  }
251  else{
252  $this->error++;
253  }
254  }
255  else if($this->element === 'don' || $this->element === 'donation') {
256  require_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php';
257 
258  $object = new Don($this->db);
259  if ($object->fetch($this->fk_object)>0) {
260  return $object->getNomUrl(1);
261  }
262  else{
263  $this->error++;
264  }
265  }
266  else if($this->element === 'subscription') {
267  require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
268 
269  $object = new Subscription($this->db);
270  if ($object->fetch($this->fk_object)>0) {
271  return $object->getNomUrl(1);
272  }
273  else{
274  $this->error++;
275  }
276  }
277  else if($this->element === 'cashcontrol') {
278  require_once DOL_DOCUMENT_ROOT.'/compta/cashcontrol/class/cashcontrol.class.php';
279 
280  $object = new CashControl($this->db);
281  if ($object->fetch($this->fk_object)>0) {
282  return $object->getNomUrl(1);
283  }
284  else{
285  $this->error++;
286  }
287  }
288  else if ($this->action == 'MODULE_SET')
289  {
290  return '<i class="opacitymedium">System to track events into unalterable logs were enabled</i>';
291  }
292  else if ($this->action == 'MODULE_RESET')
293  {
294  if ($this->signature == '0000000000')
295  {
296  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>';
297  }
298  else
299  {
300  return '<i class="opacitymedium">System to track events into unalterable logs were disabled. This is possible because no record were done yet.</i>';
301  }
302  }
303 
304  return '<i class="opacitymedium">'.$langs->trans('ImpossibleToReloadObject', $this->element, $this->fk_object).'</i>';
305  }
306 
311  public function getUser()
312  {
313  global $langs, $cachedUser;
314 
315  if(empty($cachedUser))$cachedUser=array();
316 
317  if(empty($cachedUser[$this->fk_user])) {
318  $u=new User($this->db);
319  if($u->fetch($this->fk_user)>0) {
320  $cachedUser[$this->fk_user] = $u;
321  }
322  }
323 
324  if(!empty($cachedUser[$this->fk_user])) {
325  return $cachedUser[$this->fk_user]->getNomUrl(1);
326  }
327 
328  return $langs->trans('ImpossibleToRetrieveUser', $this->fk_user);
329  }
330 
340  public function setObjectData(&$object, $action, $amounts, $fuser = null)
341  {
342  global $langs, $user, $mysoc;
343 
344  if (is_object($fuser)) $user = $fuser;
345 
346  // Generic fields
347 
348  // action
349  $this->action = $action;
350  // amount
351  $this->amounts= $amounts;
352  // date
353  if ($object->element == 'payment' || $object->element == 'payment_supplier')
354  {
355  $this->date_object = $object->datepaye;
356  }
357  elseif ($object->element=='payment_salary')
358  {
359  $this->date_object = $object->datev;
360  }
361  elseif ($object->element == 'payment_donation' || $object->element == 'payment_various')
362  {
363  $this->date_object = $object->datepaid?$object->datepaid:$object->datep;
364  }
365  elseif ($object->element=='subscription')
366  {
367  $this->date_object = $object->dateh;
368  }
369  elseif ($object->element=='cashcontrol')
370  {
371  $this->date_object = $object->date_creation;
372  }
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','modelpdf','last_main_doc','civility_id','contact','contact_id',
389  'table_element_line','ismultientitymanaged','isextrafieldmanaged',
390  'linkedObjectsIds','linkedObjects','fk_delivery_address',
391  'context',
392  'projet' // There is already ->fk_project
393  );
394  // Add more fields to exclude depending on object type
395  if ($this->element == 'cashcontrol')
396  {
397  $arrayoffieldstoexclude = array_merge($arrayoffieldstoexclude, array(
398  'name','lastname','firstname','region','region_id','region_code','state','state_id','state_code','country','country_id','country_code',
399  'total_ht','total_tva','total_ttc','total_localtax1','total_localtax2',
400  'barcode_type','barcode_type_code','barcode_type_label','barcode_type_coder','mode_reglement_id','cond_reglement_id','mode_reglement','cond_reglement','shipping_method_id',
401  'fk_incoterms','libelle_incoterms','location_incoterms','lines')
402  );
403  }
404 
405  // Add thirdparty info
406  if (empty($object->thirdparty) && method_exists($object, 'fetch_thirdparty')) $object->fetch_thirdparty();
407  if (! empty($object->thirdparty))
408  {
409  $this->object_data->thirdparty = new stdClass();
410 
411  foreach($object->thirdparty as $key=>$value)
412  {
413  if (in_array($key, $arrayoffieldstoexclude)) continue; // Discard some properties
414  if (! in_array($key, array(
415  'name','name_alias','ref_ext','address','zip','town','state_code','country_code','idprof1','idprof2','idprof3','idprof4','idprof5','idprof6','phone','fax','email','barcode',
416  'tva_intra', 'localtax1_assuj', 'localtax1_value', 'localtax2_assuj', 'localtax2_value', 'managers', 'capital', 'typent_code', 'forme_juridique_code', 'code_client', 'code_fournisseur'
417  ))) continue; // Discard if not into a dedicated list
418  if (!is_object($value)) $this->object_data->thirdparty->{$key} = $value;
419  }
420  }
421 
422  // Add company info
423  if (! empty($mysoc))
424  {
425  $this->object_data->mycompany = new stdClass();
426 
427  foreach($mysoc as $key=>$value)
428  {
429  if (in_array($key, $arrayoffieldstoexclude)) continue; // Discard some properties
430  if (! in_array($key, array(
431  'name','name_alias','ref_ext','address','zip','town','state_code','country_code','idprof1','idprof2','idprof3','idprof4','idprof5','idprof6','phone','fax','email','barcode',
432  'tva_intra', 'localtax1_assuj', 'localtax1_value', 'localtax2_assuj', 'localtax2_value', 'managers', 'capital', 'typent_code', 'forme_juridique_code', 'code_client', 'code_fournisseur'
433  ))) continue; // Discard if not into a dedicated list
434  if (!is_object($value)) $this->object_data->mycompany->{$key} = $value;
435  }
436  }
437 
438  // Add user info
439  if (! empty($user))
440  {
441  $this->fk_user = $user->id;
442  $this->user_fullname = $user->getFullName($langs);
443  }
444 
445  // Field specific to object
446  if ($this->element == 'facture')
447  {
448  foreach($object as $key=>$value)
449  {
450  if (in_array($key, $arrayoffieldstoexclude)) continue; // Discard some properties
451  if (! in_array($key, array(
452  'ref','facnumber','ref_client','ref_supplier','date','datef','type','total_ht','total_tva','total_ttc','localtax1','localtax2','revenuestamp','datepointoftax','note_public','lines'
453  ))) continue; // Discard if not into a dedicated list
454  if ($key == 'lines')
455  {
456  $lineid=0;
457  foreach($value as $tmpline) // $tmpline is object FactureLine
458  {
459  $lineid++;
460  foreach($tmpline as $keyline => $valueline)
461  {
462  if (! in_array($keyline, array(
463  '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'
464  ))) continue; // Discard if not into a dedicated list
465 
466  if (! is_object($this->object_data->invoiceline[$lineid])) $this->object_data->invoiceline[$lineid] = new stdClass();
467 
468  $this->object_data->invoiceline[$lineid]->{$keyline} = $valueline;
469  }
470  }
471  }
472  else if (!is_object($value)) $this->object_data->{$key} = $value;
473  }
474 
475  if (! empty($object->newref)) $this->object_data->ref = $object->newref;
476  }
477  elseif ($this->element == 'invoice_supplier')
478  {
479  foreach($object as $key=>$value)
480  {
481  if (in_array($key, $arrayoffieldstoexclude)) continue; // Discard some properties
482  if (! in_array($key, array(
483  'ref','facnumber','ref_client','ref_supplier','date','datef','type','total_ht','total_tva','total_ttc','localtax1','localtax2','revenuestamp','datepointoftax','note_public'
484  ))) continue; // Discard if not into a dedicated list
485  if (!is_object($value)) $this->object_data->{$key} = $value;
486  }
487 
488  if (! empty($object->newref)) $this->object_data->ref = $object->newref;
489  }
490  elseif ($this->element == 'payment' || $this->element == 'payment_supplier' || $this->element == 'payment_donation' || $this->element == 'payment_various')
491  {
492  $datepayment = $object->datepaye?$object->datepaye:($object->datepaid?$object->datepaid:$object->datep);
493  $paymenttypeid = $object->paiementid?$object->paiementid:($object->paymenttype?$object->paymenttype:$object->type_payment);
494 
495  $this->object_data->ref = $object->ref;
496  $this->object_data->date = $datepayment;
497  $this->object_data->type_code = dol_getIdFromCode($this->db, $paymenttypeid, 'c_paiement', 'id', 'code');
498  $this->object_data->payment_num = ($object->num_paiement?$object->num_paiement:$object->num_payment);
499  //$this->object_data->fk_account = $object->fk_account;
500  $this->object_data->note = $object->note;
501  //var_dump($this->object_data);exit;
502 
503  $totalamount=0;
504 
505  if (! is_array($object->amounts) && $object->amount)
506  {
507  $object->amounts=array($object->id => $object->amount);
508  }
509 
510  $paymentpartnumber=0;
511  foreach($object->amounts as $objid => $amount)
512  {
513  if (empty($amount)) continue;
514 
515  $totalamount += $amount;
516 
517  $tmpobject = null;
518  if ($this->element == 'payment_supplier')
519  {
520  include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
521  $tmpobject = new FactureFournisseur($this->db);
522  }
523  elseif ($this->element == 'payment')
524  {
525  include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
526  $tmpobject = new Facture($this->db);
527  }
528  elseif ($this->element == 'payment_donation')
529  {
530  include_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php';
531  $tmpobject = new Don($this->db);
532  }
533  elseif ($this->element == 'payment_various')
534  {
535  include_once DOL_DOCUMENT_ROOT.'/compta/bank/class/paymentvarious.class.php';
536  $tmpobject = new PaymentVarious($this->db);
537  }
538 
539  if (! is_object($tmpobject))
540  {
541  continue;
542  }
543 
544  $result = $tmpobject->fetch($objid);
545 
546  if ($result <= 0)
547  {
548  $this->error = $tmpobject->error;
549  $this->errors = $tmpobject->errors;
550  dol_syslog("Failed to fetch object with id ".$objid, LOG_ERR);
551  return -1;
552  }
553 
554  $paymentpart = new stdClass();
555  $paymentpart->amount = $amount;
556 
557  if (! in_array($this->element, array('payment_donation', 'payment_various')))
558  {
559  $result = $tmpobject->fetch_thirdparty();
560  if ($result == 0)
561  {
562  $this->error='Failed to fetch thirdparty for object with id '.$tmpobject->id;
563  $this->errors[] = $this->error;
564  dol_syslog("Failed to fetch thirdparty for object with id ".$tmpobject->id, LOG_ERR);
565  return -1;
566  }
567  elseif ($result < 0)
568  {
569  $this->error = $tmpobject->error;
570  $this->errors = $tmpobject->errors;
571  return -1;
572  }
573 
574  $paymentpart->thirdparty = new stdClass();
575  foreach($tmpobject->thirdparty as $key=>$value)
576  {
577  if (in_array($key, $arrayoffieldstoexclude)) continue; // Discard some properties
578  if (! in_array($key, array(
579  'name','name_alias','ref_ext','address','zip','town','state_code','country_code','idprof1','idprof2','idprof3','idprof4','idprof5','idprof6','phone','fax','email','barcode',
580  'tva_intra', 'localtax1_assuj', 'localtax1_value', 'localtax2_assuj', 'localtax2_value', 'managers', 'capital', 'typent_code', 'forme_juridique_code', 'code_client', 'code_fournisseur'
581  ))) continue; // Discard if not into a dedicated list
582  if (!is_object($value)) $paymentpart->thirdparty->{$key} = $value;
583  }
584  }
585 
586  // Init object to avoid warnings
587  if ($this->element == 'payment_donation') $paymentpart->donation = new stdClass();
588  else $paymentpart->invoice = new stdClass();
589 
590  if ($this->element != 'payment_various')
591  {
592  foreach($tmpobject as $key=>$value)
593  {
594  if (in_array($key, $arrayoffieldstoexclude)) continue; // Discard some properties
595  if (! in_array($key, array(
596  'ref','facnumber','ref_client','ref_supplier','date','datef','type','total_ht','total_tva','total_ttc','localtax1','localtax2','revenuestamp','datepointoftax','note_public'
597  ))) continue; // Discard if not into a dedicated list
598  if (!is_object($value))
599  {
600  if ($this->element == 'payment_donation') $paymentpart->donation->{$key} = $value;
601  elseif ($this->element == 'payment_various') $paymentpart->various->{$key} = $value;
602  else $paymentpart->invoice->{$key} = $value;
603  }
604  }
605 
606  $paymentpartnumber++; // first payment will be 1
607  $this->object_data->payment_part[$paymentpartnumber] = $paymentpart;
608  }
609  }
610 
611  $this->object_data->amount = $totalamount;
612 
613  if (! empty($object->newref)) $this->object_data->ref = $object->newref;
614  }
615  elseif($this->element == 'payment_salary')
616  {
617  $this->object_data->amounts = array($object->amount);
618 
619  if (! empty($object->newref)) $this->object_data->ref = $object->newref;
620  }
621  elseif($this->element == 'subscription')
622  {
623  foreach($object as $key=>$value)
624  {
625  if (in_array($key, $arrayoffieldstoexclude)) continue; // Discard some properties
626  if (! in_array($key, array(
627  'id','datec','dateh','datef','fk_adherent','amount','import_key','statut','note'
628  ))) continue; // Discard if not into a dedicated list
629  if (!is_object($value)) $this->object_data->{$key} = $value;
630  }
631 
632  if (! empty($object->newref)) $this->object_data->ref = $object->newref;
633  }
634  else // Generic case
635  {
636  foreach($object as $key=>$value)
637  {
638  if (in_array($key, $arrayoffieldstoexclude)) continue; // Discard some properties
639  if (!is_object($value)) $this->object_data->{$key} = $value;
640  }
641 
642  if (! empty($object->newref)) $this->object_data->ref = $object->newref;
643  }
644 
645  return 1;
646  }
647 
654  public function fetch($id)
655  {
656 
657  global $langs;
658 
659  dol_syslog(get_class($this)."::fetch id=".$id, LOG_DEBUG);
660 
661  if (empty($id))
662  {
663  $this->error='BadParameter';
664  return -1;
665  }
666 
667  $langs->load("blockedlog");
668 
669  $sql = "SELECT b.rowid, b.date_creation, b.signature, b.signature_line, b.amounts, b.action, b.element, b.fk_object, b.entity,";
670  $sql.= " b.certified, b.tms, b.fk_user, b.user_fullname, b.date_object, b.ref_object, b.object_data";
671  $sql.= " FROM ".MAIN_DB_PREFIX."blockedlog as b";
672  if ($id) $sql.= " WHERE b.rowid = ". $id;
673 
674  $resql=$this->db->query($sql);
675  if ($resql)
676  {
677  if ($this->db->num_rows($resql))
678  {
679  $obj = $this->db->fetch_object($resql);
680 
681  $this->id = $obj->rowid;
682  $this->entity = $obj->entity;
683  $this->ref = $obj->rowid;
684 
685  $this->date_creation = $this->db->jdate($obj->date_creation);
686  $this->tms = $this->db->jdate($obj->tms);
687 
688  $this->amounts = (double) $obj->amounts;
689  $this->action = $obj->action;
690  $this->element = $obj->element;
691 
692  $this->fk_object = $obj->fk_object;
693  $this->date_object = $this->db->jdate($obj->date_object);
694  $this->ref_object = $obj->ref_object;
695 
696  $this->fk_user = $obj->fk_user;
697  $this->user_fullname = $obj->user_fullname;
698 
699  $this->object_data = $this->dolDecodeBlockedData($obj->object_data);
700 
701  $this->signature = $obj->signature;
702  $this->signature_line = $obj->signature_line;
703  $this->certified = ($obj->certified == 1);
704 
705  return 1;
706  }
707  else
708  {
709  $this->error=$langs->trans("RecordNotFound");
710  return 0;
711  }
712  }
713  else
714  {
715  $this->error=$this->db->error();
716  return -1;
717  }
718  }
719 
720 
728  public function dolDecodeBlockedData($data, $mode=0)
729  {
730  try
731  {
732  //include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
733  //include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
734  $aaa = unserialize($data);
735  //$aaa = unserialize($data);
736  }
737  catch(Exception $e)
738  {
739  //print $e->getErrs);
740  }
741  return $aaa;
742  }
743 
744 
750  public function setCertified()
751  {
752 
753  $res = $this->db->query("UPDATE ".MAIN_DB_PREFIX."blockedlog SET certified=1 WHERE rowid=".$this->id);
754  if($res===false) return false;
755 
756  return true;
757  }
758 
766  public function create($user, $forcesignature='')
767  {
768 
769  global $conf,$langs,$hookmanager;
770 
771  $langs->load('blockedlog');
772 
773  $error=0;
774 
775  // Clean data
776  $this->amounts=(double) $this->amounts;
777 
778  dol_syslog(get_class($this).'::create action='.$this->action.' fk_user='.$this->fk_user.' user_fullname='.$this->user_fullname, LOG_DEBUG);
779 
780  // Check parameters/properties
781  if (! isset($this->amounts)) // amount can be 0 for some events (like when module is disabled)
782  {
783  $this->error=$langs->trans("BlockLogNeedAmountsValue");
784  dol_syslog($this->error, LOG_WARNING);
785  return -1;
786  }
787 
788  if (empty($this->element)) {
789  $this->error=$langs->trans("BlockLogNeedElement");
790  dol_syslog($this->error, LOG_WARNING);
791  return -2;
792  }
793 
794  if (empty($this->action)) {
795  $this->error=$langs->trans("BadParameterWhenCallingCreateOfBlockedLog");
796  dol_syslog($this->error, LOG_WARNING);
797  return -3;
798  }
799  if (empty($this->fk_user)) $this->user_fullname='(Anonymous)';
800 
801  $this->date_creation = dol_now();
802 
803  $this->db->begin();
804 
805  $previoushash = $this->getPreviousHash(1, 0); // This get last record and lock database until insert is done
806 
807  $keyforsignature = $this->buildKeyForSignature();
808 
809  $this->signature_line = dol_hash($keyforsignature, '5'); // Not really usefull
810  $this->signature = dol_hash($previoushash . $keyforsignature, '5');
811  if ($forcesignature) $this->signature = $forcesignature;
812  //var_dump($keyforsignature);var_dump($previoushash);var_dump($this->signature_line);var_dump($this->signature);
813 
814  $sql = "INSERT INTO ".MAIN_DB_PREFIX."blockedlog (";
815  $sql.= " date_creation,";
816  $sql.= " action,";
817  $sql.= " amounts,";
818  $sql.= " signature,";
819  $sql.= " signature_line,";
820  $sql.= " element,";
821  $sql.= " fk_object,";
822  $sql.= " date_object,";
823  $sql.= " ref_object,";
824  $sql.= " object_data,";
825  $sql.= " certified,";
826  $sql.= " fk_user,";
827  $sql.= " user_fullname,";
828  $sql.= " entity";
829  $sql.= ") VALUES (";
830  $sql.= "'".$this->db->idate($this->date_creation)."',";
831  $sql.= "'".$this->db->escape($this->action)."',";
832  $sql.= $this->amounts.",";
833  $sql.= "'".$this->db->escape($this->signature)."',";
834  $sql.= "'".$this->db->escape($this->signature_line)."',";
835  $sql.= "'".$this->db->escape($this->element)."',";
836  $sql.= $this->fk_object.",";
837  $sql.= "'".$this->db->idate($this->date_object)."',";
838  $sql.= "'".$this->db->escape($this->ref_object)."',";
839  $sql.= "'".$this->db->escape(serialize($this->object_data))."',";
840  $sql.= "0,";
841  $sql.= $this->fk_user.",";
842  $sql.= "'".$this->db->escape($this->user_fullname)."',";
843  $sql.= ($this->entity ? $this->entity : $conf->entity);
844  $sql.= ")";
845 
846  $res = $this->db->query($sql);
847  if ($res)
848  {
849  $id = $this->db->last_insert_id(MAIN_DB_PREFIX."blockedlog");
850 
851  if ($id > 0)
852  {
853  $this->id = $id;
854 
855  $this->db->commit();
856 
857  return $this->id;
858  }
859  else
860  {
861  $this->db->rollback();
862  return -2;
863  }
864  }
865  else
866  {
867  $this->error=$this->db->error();
868  $this->db->rollback();
869  return -1;
870  }
871 
872  // The commit will release the lock so we can insert nex record
873  }
874 
881  public function checkSignature($previoushash='')
882  {
883  if (empty($previoushash))
884  {
885  $previoushash = $this->getPreviousHash(0, $this->id);
886  }
887  // Recalculate hash
888  $keyforsignature = $this->buildKeyForSignature();
889 
890  $signature_line = dol_hash($keyforsignature, '5'); // Not really usefull
891  $signature = dol_hash($previoushash . $keyforsignature, '5');
892  //var_dump($previoushash); var_dump($keyforsignature); var_dump($signature_line); var_dump($signature);
893 
894  $res = ($signature === $this->signature);
895 
896  if (!$res) {
897  $this->error = 'Signature KO';
898  }
899 
900  return $res;
901  }
902 
910  private function buildKeyForSignature()
911  {
912  //print_r($this->object_data);
913  return $this->date_creation.'|'.$this->action.'|'.$this->amounts.'|'.$this->ref_object.'|'.$this->date_object.'|'.$this->user_fullname.'|'.print_r($this->object_data, true);
914  }
915 
916 
924  public function getPreviousHash($withlock=0, $beforeid=0)
925  {
926  global $conf;
927 
928  $previoussignature='';
929 
930  $sql = "SELECT rowid, signature FROM ".MAIN_DB_PREFIX."blockedlog";
931  $sql.= " WHERE entity=".$conf->entity;
932  if ($beforeid) $sql.= " AND rowid < ".(int) $beforeid;
933  $sql.=" ORDER BY rowid DESC LIMIT 1";
934  $sql.=($withlock ? " FOR UPDATE ": "");
935 
936  $resql = $this->db->query($sql);
937  if ($resql) {
938  $obj = $this->db->fetch_object($resql);
939  if ($obj)
940  {
941  $previoussignature = $obj->signature;
942  }
943  }
944  else
945  {
946  dol_print_error($this->db);
947  exit;
948  }
949 
950  if (empty($previoussignature))
951  {
952  // First signature line (line 0)
953  $previoussignature = $this->getSignature();
954  }
955 
956  return $previoussignature;
957  }
958 
975  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='')
976  {
977  global $conf, $cachedlogs;
978 
979  /* $cachedlogs allow fastest search */
980  if (empty($cachedlogs)) $cachedlogs=array();
981 
982  if ($element=='all') {
983 
984  $sql="SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
985  WHERE entity=".$conf->entity;
986  }
987  else if ($element=='not_certified') {
988  $sql="SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
989  WHERE entity=".$conf->entity." AND certified = 0";
990  }
991  else if ($element=='just_certified') {
992  $sql="SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
993  WHERE entity=".$conf->entity." AND certified = 1";
994  }
995  else{
996  $sql="SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
997  WHERE entity=".$conf->entity." AND element='".$element."' AND fk_object=".(int) $fk_object;
998  }
999 
1000  if ($search_fk_user > 0) $sql.=natural_search("fk_user", $search_fk_user, 2);
1001  if ($search_start > 0) $sql.=" AND date_creation >= '".$this->db->idate($search_start)."'";
1002  if ($search_end > 0) $sql.=" AND date_creation <= '".$this->db->idate($search_end)."'";
1003  if ($search_ref != '') $sql.=natural_search("ref_object", $search_ref);
1004  if ($search_amount != '') $sql.=natural_search("amounts", $search_amount, 1);
1005  if ($search_code != '' && $search_code != '-1') $sql.=natural_search("action", $search_code, 3);
1006 
1007  $sql.=$this->db->order($sortfield, $sortorder);
1008  $sql.=$this->db->plimit($limit+1); // We want more, because we will stop into loop later with error if we reach max
1009 
1010  $res = $this->db->query($sql);
1011  if($res) {
1012 
1013  $results=array();
1014 
1015  $i = 0;
1016  while ($obj = $this->db->fetch_object($res))
1017  {
1018  $i++;
1019  if ($i > $limit)
1020  {
1021  // Too many record, we will consume too much memory
1022  return -2;
1023  }
1024 
1025  if (!isset($cachedlogs[$obj->rowid]))
1026  {
1027  $b=new BlockedLog($this->db);
1028  $b->fetch($obj->rowid);
1029 
1030  $cachedlogs[$obj->rowid] = $b;
1031  }
1032 
1033  $results[] = $cachedlogs[$obj->rowid];
1034  }
1035 
1036  return $results;
1037  }
1038 
1039  return -1;
1040  }
1041 
1047  public function getSignature()
1048  {
1049  global $db,$conf,$mysoc;
1050 
1051  if (empty($conf->global->BLOCKEDLOG_ENTITY_FINGERPRINT)) { // creation of a unique fingerprint
1052 
1053  require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
1054  require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
1055 
1056  $fingerprint = dol_hash(print_r($mysoc,true).getRandomPassword(1), '5');
1057 
1058  dolibarr_set_const($db, 'BLOCKEDLOG_ENTITY_FINGERPRINT', $fingerprint, 'chaine',0,'Numeric Unique Fingerprint', $conf->entity);
1059 
1060  $conf->global->BLOCKEDLOG_ENTITY_FINGERPRINT=$fingerprint;
1061  }
1062 
1063  return $conf->global->BLOCKEDLOG_ENTITY_FINGERPRINT;
1064  }
1065 
1066 
1073  function alreadyUsed($ignoresystem=0)
1074  {
1075  global $conf;
1076 
1077  $result = false;
1078 
1079  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog";
1080  $sql.= " WHERE entity = ".$conf->entity;
1081  if ($ignoresystem) $sql.=" AND action not in ('MODULE_SET','MODULE_RESET')";
1082  $sql.= $this->db->plimit(1);
1083 
1084  $res = $this->db->query($sql);
1085  if ($res!==false)
1086  {
1087  $obj = $this->db->fetch_object($res);
1088  if ($obj) $result = true;
1089  }
1090  else dol_print_error($this->db);
1091 
1092  dol_syslog("Module Blockedlog alreadyUsed with ignoresystem=".$ignoresystem." is ".$result);
1093 
1094  return $result;
1095  }
1096 }
buildKeyForSignature()
Return a string for signature.
__construct(DoliDB $db)
Constructor.
alreadyUsed($ignoresystem=0)
Check if module was already used or not for at least one recording.
if(! empty($conf->facture->enabled) && $user->rights->facture->lire) if(! empty($conf->fournisseur->enabled) && $user->rights->fournisseur->facture->lire) if(! empty($conf->don->enabled) && $user->rights->societe->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) && $user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1053
Class to manage various payments.
getPreviousHash($withlock=0, $beforeid=0)
Get previous signature/hash in chain.
getSignature()
Return the signature (hash) of the "genesis-block" (Block 0).
checkSignature($previoushash='')
Check if current signature still correct compared to the value in chain.
setObjectData(&$object, $action, $amounts, $fuser=null)
Populate properties of log from object data.
getUser()
try to retrieve user author
Class to manage cash fence.
Class to manage Dolibarr users.
Definition: user.class.php:41
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0)
Return an id or code from a code or id.
Class to manage Dolibarr database access.
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:510
fetch($id)
Get object from database.
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)
dol_print_error($db='', $error='', $errors=null)
Affiche message erreur system avec toutes les informations pour faciliter le diagnostic et la remonte...
Class to manage suppliers invoices.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='')
Write log message into outputs.
getObjectLink()
Try to retrieve source object (it it still exists)
Class to manage Blocked Log.
Class to manage payments of customer invoices.
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.
dol_now($mode='gmt')
Return date for now.
Class to manage subscriptions of foundation members.
getRandomPassword($generic=false)
Return a generated password using default module.
Class to manage payments of donations.
Class to manage donations.
Definition: don.class.php:35
create($user, $forcesignature='')
Create blocked log in database.
dol_hash($chain, $type='0')
Returns a hash of a string.
Class to manage invoices.
Class to manage payments for supplier invoices.
setCertified()
Set block certified by authority.