dolibarr  17.0.4
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  // Customer Invoice/Facture / Payment
144  if (isModEnabled('facture')) {
145  $this->trackedevents['BILL_VALIDATE'] = 'logBILL_VALIDATE';
146  $this->trackedevents['BILL_DELETE'] = 'logBILL_DELETE';
147  $this->trackedevents['BILL_SENTBYMAIL'] = 'logBILL_SENTBYMAIL';
148  $this->trackedevents['DOC_DOWNLOAD'] = 'BlockedLogBillDownload';
149  $this->trackedevents['DOC_PREVIEW'] = 'BlockedLogBillPreview';
150  $this->trackedevents['PAYMENT_CUSTOMER_CREATE'] = 'logPAYMENT_CUSTOMER_CREATE';
151  $this->trackedevents['PAYMENT_CUSTOMER_DELETE'] = 'logPAYMENT_CUSTOMER_DELETE';
152  }
153 
154  /* Supplier
155  // Supplier Invoice / Payment
156  if (isModEnabled("fournisseur")) {
157  $this->trackedevents['BILL_SUPPLIER_VALIDATE']='BlockedLogSupplierBillValidate';
158  $this->trackedevents['BILL_SUPPLIER_DELETE']='BlockedLogSupplierBillDelete';
159  $this->trackedevents['BILL_SUPPLIER_SENTBYMAIL']='BlockedLogSupplierBillSentByEmail'; // Trigger key does not exists, we want just into array to list it as done
160  $this->trackedevents['SUPPLIER_DOC_DOWNLOAD']='BlockedLogSupplierBillDownload'; // Trigger key does not exists, we want just into array to list it as done
161  $this->trackedevents['SUPPLIER_DOC_PREVIEW']='BlockedLogSupplierBillPreview'; // Trigger key does not exists, we want just into array to list it as done
162  $this->trackedevents['PAYMENT_SUPPLIER_CREATE']='BlockedLogSupplierBillPaymentCreate';
163  $this->trackedevents['PAYMENT_SUPPLIER_DELETE']='BlockedLogsupplierBillPaymentCreate';
164  }
165  */
166 
167  // Donation
168  if (isModEnabled('don')) {
169  $this->trackedevents['DON_VALIDATE'] = 'logDON_VALIDATE';
170  $this->trackedevents['DON_DELETE'] = 'logDON_DELETE';
171  //$this->trackedevents['DON_SENTBYMAIL']='logDON_SENTBYMAIL';
172  $this->trackedevents['DONATION_PAYMENT_CREATE'] = 'logDONATION_PAYMENT_CREATE';
173  $this->trackedevents['DONATION_PAYMENT_DELETE'] = 'logDONATION_PAYMENT_DELETE';
174  }
175 
176  /*
177  // Salary
178  if (!empty($conf->salary->enabled)) {
179  $this->trackedevents['PAYMENT_SALARY_CREATE']='BlockedLogSalaryPaymentCreate';
180  $this->trackedevents['PAYMENT_SALARY_MODIFY']='BlockedLogSalaryPaymentCreate';
181  $this->trackedevents['PAYMENT_SALARY_DELETE']='BlockedLogSalaryPaymentCreate';
182  }
183  */
184 
185  // Members
186  if (isModEnabled('adherent')) {
187  $this->trackedevents['MEMBER_SUBSCRIPTION_CREATE'] = 'logMEMBER_SUBSCRIPTION_CREATE';
188  $this->trackedevents['MEMBER_SUBSCRIPTION_MODIFY'] = 'logMEMBER_SUBSCRIPTION_MODIFY';
189  $this->trackedevents['MEMBER_SUBSCRIPTION_DELETE'] = 'logMEMBER_SUBSCRIPTION_DELETE';
190  }
191 
192  // Bank
193  if (isModEnabled("banque")) {
194  $this->trackedevents['PAYMENT_VARIOUS_CREATE'] = 'logPAYMENT_VARIOUS_CREATE';
195  $this->trackedevents['PAYMENT_VARIOUS_MODIFY'] = 'logPAYMENT_VARIOUS_MODIFY';
196  $this->trackedevents['PAYMENT_VARIOUS_DELETE'] = 'logPAYMENT_VARIOUS_DELETE';
197  }
198 
199  // Cashdesk
200  // $conf->global->BANK_ENABLE_POS_CASHCONTROL must be set to 1 by all external POS modules
201  $moduleposenabled = (!empty($conf->cashdesk->enabled) || !empty($conf->takepos->enabled) || !empty($conf->global->BANK_ENABLE_POS_CASHCONTROL));
202  if ($moduleposenabled) {
203  $this->trackedevents['CASHCONTROL_VALIDATE'] = 'logCASHCONTROL_VALIDATE';
204  }
205 
206  // Add more action to track from a conf variable
207  // For example: STOCK_MOVEMENT,...
208  if (!empty($conf->global->BLOCKEDLOG_ADD_ACTIONS_SUPPORTED)) {
209  $tmparrayofmoresupportedevents = explode(',', $conf->global->BLOCKEDLOG_ADD_ACTIONS_SUPPORTED);
210  foreach ($tmparrayofmoresupportedevents as $val) {
211  $this->trackedevents[$val] = 'log'.$val;
212  }
213  }
214 
215  return 1;
216  }
217 
223  public function getObjectLink()
224  {
225  global $langs;
226 
227  if ($this->element === 'facture') {
228  require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
229 
230  $object = new Facture($this->db);
231  if ($object->fetch($this->fk_object) > 0) {
232  return $object->getNomUrl(1);
233  } else {
234  $this->error++;
235  }
236  }
237  if ($this->element === 'invoice_supplier') {
238  require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
239 
240  $object = new FactureFournisseur($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') {
247  require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
248 
249  $object = new Paiement($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_supplier') {
256  require_once DOL_DOCUMENT_ROOT.'/fourn/class/paiementfourn.class.php';
257 
258  $object = new PaiementFourn($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_donation') {
265  require_once DOL_DOCUMENT_ROOT.'/don/class/paymentdonation.class.php';
266 
267  $object = new PaymentDonation($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 === 'payment_various') {
274  require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/paymentvarious.class.php';
275 
276  $object = new PaymentVarious($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 === 'don' || $this->element === 'donation') {
283  require_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php';
284 
285  $object = new Don($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 === 'subscription') {
292  require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
293 
294  $object = new Subscription($this->db);
295  if ($object->fetch($this->fk_object) > 0) {
296  return $object->getNomUrl(1);
297  } else {
298  $this->error++;
299  }
300  } elseif ($this->element === 'cashcontrol') {
301  require_once DOL_DOCUMENT_ROOT.'/compta/cashcontrol/class/cashcontrol.class.php';
302 
303  $object = new CashControl($this->db);
304  if ($object->fetch($this->fk_object) > 0) {
305  return $object->getNomUrl(1);
306  } else {
307  $this->error++;
308  }
309  } elseif ($this->element === 'stockmouvement') {
310  require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
311 
312  $object = new MouvementStock($this->db);
313  if ($object->fetch($this->fk_object) > 0) {
314  return $object->getNomUrl(1);
315  } else {
316  $this->error++;
317  }
318  } elseif ($this->action == 'MODULE_SET') {
319  return '<i class="opacitymedium">'.$langs->trans("BlockedLogEnabled").'</i>';
320  } elseif ($this->action == 'MODULE_RESET') {
321  if ($this->signature == '0000000000') {
322  return '<i class="opacitymedium">'.$langs->trans("BlockedLogDisabled").'</i>';
323  } else {
324  return '<i class="opacitymedium">'.$langs->trans("BlockedLogDisabledBis").'</i>';
325  }
326  }
327 
328  return '<i class="opacitymedium">'.$langs->trans('ImpossibleToReloadObject', $this->element, $this->fk_object).'</i>';
329  }
330 
335  public function getUser()
336  {
337  global $langs, $cachedUser;
338 
339  if (empty($cachedUser)) {
340  $cachedUser = array();
341  }
342 
343  if (empty($cachedUser[$this->fk_user])) {
344  $u = new User($this->db);
345  if ($u->fetch($this->fk_user) > 0) {
346  $cachedUser[$this->fk_user] = $u;
347  }
348  }
349 
350  if (!empty($cachedUser[$this->fk_user])) {
351  return $cachedUser[$this->fk_user]->getNomUrl(1);
352  }
353 
354  return $langs->trans('ImpossibleToRetrieveUser', $this->fk_user);
355  }
356 
366  public function setObjectData(&$object, $action, $amounts, $fuser = null)
367  {
368  global $langs, $user, $mysoc;
369 
370  if (is_object($fuser)) {
371  $user = $fuser;
372  }
373 
374  // Generic fields
375 
376  // action
377  $this->action = $action;
378  // amount
379  $this->amounts = $amounts;
380  // date
381  if ($object->element == 'payment' || $object->element == 'payment_supplier') {
382  $this->date_object = empty($object->datepaye) ? $object->date : $object->datepaye;
383  } elseif ($object->element == 'payment_salary') {
384  $this->date_object = $object->datev;
385  } elseif ($object->element == 'payment_donation' || $object->element == 'payment_various') {
386  $this->date_object = empty($object->datepaid) ? $object->datep : $object->datepaid;
387  } elseif ($object->element == 'subscription') {
388  $this->date_object = $object->dateh;
389  } elseif ($object->element == 'cashcontrol') {
390  $this->date_object = $object->date_creation;
391  } elseif (property_exists($object, 'date')) {
392  // Generic case
393  $this->date_object = $object->date;
394  } elseif (property_exists($object, 'datem')) {
395  // Generic case (second chance, for example for stock movement)
396  $this->date_object = $object->datem;
397  }
398 
399  // ref
400  $this->ref_object = ((!empty($object->newref)) ? $object->newref : $object->ref); // newref is set when validating a draft, ref is set in other cases
401  // type of object
402  $this->element = $object->element;
403  // id of object
404  $this->fk_object = $object->id;
405 
406 
407  // Set object_data
408  $this->object_data = new stdClass();
409  // Add fields to exclude
410  $arrayoffieldstoexclude = array(
411  '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',
412  'table_element_line', 'ismultientitymanaged', 'isextrafieldmanaged',
413  'array_languages',
414  'childtables',
415  'contact_ids',
416  'context',
417  'labelStatus',
418  'labelStatusShort',
419  'linkedObjectsIds',
420  'linkedObjects',
421  'fk_delivery_address',
422  'projet', // There is already ->fk_project
423  'restrictiononfksoc',
424  'specimen',
425  );
426  // Add more fields to exclude depending on object type
427  if ($this->element == 'cashcontrol') {
428  $arrayoffieldstoexclude = array_merge($arrayoffieldstoexclude, array(
429  'name', 'lastname', 'firstname', 'region', 'region_id', 'region_code', 'state', 'state_id', 'state_code', 'country', 'country_id', 'country_code',
430  'total_ht', 'total_tva', 'total_ttc', 'total_localtax1', 'total_localtax2',
431  'barcode_type', 'barcode_type_code', 'barcode_type_label', 'barcode_type_coder', 'mode_reglement_id', 'cond_reglement_id', 'mode_reglement', 'cond_reglement', 'shipping_method_id',
432  'fk_incoterms', 'label_incoterms', 'location_incoterms', 'lines'));
433  }
434 
435  // Add thirdparty info
436  if (empty($object->thirdparty) && method_exists($object, 'fetch_thirdparty')) {
437  $object->fetch_thirdparty();
438  }
439  if (!empty($object->thirdparty)) {
440  $this->object_data->thirdparty = new stdClass();
441 
442  foreach ($object->thirdparty as $key => $value) {
443  if (in_array($key, $arrayoffieldstoexclude)) {
444  continue; // Discard some properties
445  }
446  if (!in_array($key, array(
447  'name', 'name_alias', 'ref_ext', 'address', 'zip', 'town', 'state_code', 'country_code', 'idprof1', 'idprof2', 'idprof3', 'idprof4', 'idprof5', 'idprof6', 'phone', 'fax', 'email', 'barcode',
448  'tva_intra', 'localtax1_assuj', 'localtax1_value', 'localtax2_assuj', 'localtax2_value', 'managers', 'capital', 'typent_code', 'forme_juridique_code', 'code_client', 'code_fournisseur'
449  ))) {
450  continue; // Discard if not into a dedicated list
451  }
452  if (!is_object($value) && !is_null($value) && $value !== '') {
453  $this->object_data->thirdparty->$key = $value;
454  }
455  }
456  }
457 
458  // Add company info
459  if (!empty($mysoc)) {
460  $this->object_data->mycompany = new stdClass();
461 
462  foreach ($mysoc as $key => $value) {
463  if (in_array($key, $arrayoffieldstoexclude)) {
464  continue; // Discard some properties
465  }
466  if (!in_array($key, array(
467  'name', 'name_alias', 'ref_ext', 'address', 'zip', 'town', 'state_code', 'country_code', 'idprof1', 'idprof2', 'idprof3', 'idprof4', 'idprof5', 'idprof6', 'phone', 'fax', 'email', 'barcode',
468  'tva_intra', 'localtax1_assuj', 'localtax1_value', 'localtax2_assuj', 'localtax2_value', 'managers', 'capital', 'typent_code', 'forme_juridique_code', 'code_client', 'code_fournisseur'
469  ))) {
470  continue; // Discard if not into a dedicated list
471  }
472  if (!is_object($value) && !is_null($value) && $value !== '') {
473  $this->object_data->mycompany->$key = $value;
474  }
475  }
476  }
477 
478  // Add user info
479  if (!empty($user)) {
480  $this->fk_user = $user->id;
481  $this->user_fullname = $user->getFullName($langs);
482  }
483 
484  // Field specific to object
485  if ($this->element == 'facture') {
486  foreach ($object as $key => $value) {
487  if (in_array($key, $arrayoffieldstoexclude)) {
488  continue; // Discard some properties
489  }
490  if (!in_array($key, array(
491  'ref', 'ref_client', 'ref_supplier', 'date', 'datef', 'datev', 'type', 'total_ht', 'total_tva', 'total_ttc', 'localtax1', 'localtax2', 'revenuestamp', 'datepointoftax', 'note_public', 'lines'
492  ))) {
493  continue; // Discard if not into a dedicated list
494  }
495  if ($key == 'lines') {
496  $lineid = 0;
497  foreach ($value as $tmpline) { // $tmpline is object FactureLine
498  $lineid++;
499  foreach ($tmpline as $keyline => $valueline) {
500  if (!in_array($keyline, array(
501  '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'
502  ))) {
503  continue; // Discard if not into a dedicated list
504  }
505 
506  if (empty($this->object_data->invoiceline[$lineid]) || !is_object($this->object_data->invoiceline[$lineid])) { // To avoid warning
507  $this->object_data->invoiceline[$lineid] = new stdClass();
508  }
509 
510  if (!is_object($valueline) && !is_null($valueline) && $valueline !== '') {
511  $this->object_data->invoiceline[$lineid]->$keyline = $valueline;
512  }
513  }
514  }
515  } elseif (!is_object($value) && !is_null($value) && $value !== '') {
516  $this->object_data->$key = $value;
517  }
518  }
519 
520  if (!empty($object->newref)) {
521  $this->object_data->ref = $object->newref;
522  }
523  } elseif ($this->element == 'invoice_supplier') {
524  foreach ($object as $key => $value) {
525  if (in_array($key, $arrayoffieldstoexclude)) {
526  continue; // Discard some properties
527  }
528  if (!in_array($key, array(
529  'ref', 'ref_client', 'ref_supplier', 'date', 'datef', 'type', 'total_ht', 'total_tva', 'total_ttc', 'localtax1', 'localtax2', 'revenuestamp', 'datepointoftax', 'note_public'
530  ))) {
531  continue; // Discard if not into a dedicated list
532  }
533  if (!is_object($value) && !is_null($value) && $value !== '') {
534  $this->object_data->$key = $value;
535  }
536  }
537 
538  if (!empty($object->newref)) {
539  $this->object_data->ref = $object->newref;
540  }
541  } elseif ($this->element == 'payment' || $this->element == 'payment_supplier' || $this->element == 'payment_donation' || $this->element == 'payment_various') {
542  $datepayment = $object->datepaye ? $object->datepaye : ($object->datepaid ? $object->datepaid : $object->datep);
543  $paymenttypeid = $object->paiementid ? $object->paiementid : ($object->paymenttype ? $object->paymenttype : $object->type_payment);
544 
545  $this->object_data->ref = $object->ref;
546  $this->object_data->date = $datepayment;
547  $this->object_data->type_code = dol_getIdFromCode($this->db, $paymenttypeid, 'c_paiement', 'id', 'code');
548 
549  if (!empty($object->num_payment)) {
550  $this->object_data->payment_num = $object->num_payment;
551  }
552  if (!empty($object->note_private)) {
553  $this->object_data->note_private = $object->note_private;
554  }
555  //$this->object_data->fk_account = $object->fk_account;
556  //var_dump($this->object_data);exit;
557 
558  $totalamount = 0;
559 
560  // Loop on each invoice payment amount (payment_part)
561  if (is_array($object->amounts) && !empty($object->amounts)) {
562  $paymentpartnumber = 0;
563  foreach ($object->amounts as $objid => $amount) {
564  if (empty($amount)) {
565  continue;
566  }
567 
568  $totalamount += $amount;
569 
570  $tmpobject = null;
571  if ($this->element == 'payment_supplier') {
572  include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
573  $tmpobject = new FactureFournisseur($this->db);
574  } elseif ($this->element == 'payment') {
575  include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
576  $tmpobject = new Facture($this->db);
577  } elseif ($this->element == 'payment_donation') {
578  include_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php';
579  $tmpobject = new Don($this->db);
580  } elseif ($this->element == 'payment_various') {
581  include_once DOL_DOCUMENT_ROOT.'/compta/bank/class/paymentvarious.class.php';
582  $tmpobject = new PaymentVarious($this->db);
583  }
584 
585  if (!is_object($tmpobject)) {
586  continue;
587  }
588 
589  $result = $tmpobject->fetch($objid);
590 
591  if ($result <= 0) {
592  $this->error = $tmpobject->error;
593  $this->errors = $tmpobject->errors;
594  dol_syslog("Failed to fetch object with id ".$objid, LOG_ERR);
595  return -1;
596  }
597 
598  $paymentpart = new stdClass();
599  $paymentpart->amount = $amount;
600 
601  if (!in_array($this->element, array('payment_donation', 'payment_various'))) {
602  $result = $tmpobject->fetch_thirdparty();
603  if ($result == 0) {
604  $this->error = 'Failed to fetch thirdparty for object with id '.$tmpobject->id;
605  $this->errors[] = $this->error;
606  dol_syslog("Failed to fetch thirdparty for object with id ".$tmpobject->id, LOG_ERR);
607  return -1;
608  } elseif ($result < 0) {
609  $this->error = $tmpobject->error;
610  $this->errors = $tmpobject->errors;
611  return -1;
612  }
613 
614  $paymentpart->thirdparty = new stdClass();
615  foreach ($tmpobject->thirdparty as $key => $value) {
616  if (in_array($key, $arrayoffieldstoexclude)) {
617  continue; // Discard some properties
618  }
619  if (!in_array($key, array(
620  'name', 'name_alias', 'ref_ext', 'address', 'zip', 'town', 'state_code', 'country_code', 'idprof1', 'idprof2', 'idprof3', 'idprof4', 'idprof5', 'idprof6', 'phone', 'fax', 'email', 'barcode',
621  'tva_intra', 'localtax1_assuj', 'localtax1_value', 'localtax2_assuj', 'localtax2_value', 'managers', 'capital', 'typent_code', 'forme_juridique_code', 'code_client', 'code_fournisseur'
622  ))) {
623  continue; // Discard if not into a dedicated list
624  }
625  if (!is_object($value) && !is_null($value) && $value !== '') {
626  $paymentpart->thirdparty->$key = $value;
627  }
628  }
629  }
630 
631  // Init object to avoid warnings
632  if ($this->element == 'payment_donation') {
633  $paymentpart->donation = new stdClass();
634  } else {
635  $paymentpart->invoice = new stdClass();
636  }
637 
638  if ($this->element != 'payment_various') {
639  foreach ($tmpobject as $key => $value) {
640  if (in_array($key, $arrayoffieldstoexclude)) {
641  continue; // Discard some properties
642  }
643  if (!in_array($key, array(
644  'ref', 'ref_client', 'ref_supplier', 'date', 'datef', 'type', 'total_ht', 'total_tva', 'total_ttc', 'localtax1', 'localtax2', 'revenuestamp', 'datepointoftax', 'note_public'
645  ))) {
646  continue; // Discard if not into a dedicated list
647  }
648  if (!is_object($value) && !is_null($value) && $value !== '') {
649  if ($this->element == 'payment_donation') {
650  $paymentpart->donation->$key = $value;
651  } elseif ($this->element == 'payment_various') {
652  $paymentpart->various->$key = $value;
653  } else {
654  $paymentpart->invoice->$key = $value;
655  }
656  }
657  }
658 
659  $paymentpartnumber++; // first payment will be 1
660  $this->object_data->payment_part[$paymentpartnumber] = $paymentpart;
661  }
662  }
663  } elseif (!empty($object->amount)) {
664  $totalamount = $object->amount;
665  }
666 
667  $this->object_data->amount = $totalamount;
668 
669  if (!empty($object->newref)) {
670  $this->object_data->ref = $object->newref;
671  }
672  } elseif ($this->element == 'payment_salary') {
673  $this->object_data->amounts = array($object->amount);
674 
675  if (!empty($object->newref)) {
676  $this->object_data->ref = $object->newref;
677  }
678  } elseif ($this->element == 'subscription') {
679  foreach ($object as $key => $value) {
680  if (in_array($key, $arrayoffieldstoexclude)) {
681  continue; // Discard some properties
682  }
683  if (!in_array($key, array(
684  'id', 'datec', 'dateh', 'datef', 'fk_adherent', 'amount', 'import_key', 'statut', 'note'
685  ))) {
686  continue; // Discard if not into a dedicated list
687  }
688  if (!is_object($value) && !is_null($value) && $value !== '') {
689  $this->object_data->$key = $value;
690  }
691  }
692 
693  if (!empty($object->newref)) {
694  $this->object_data->ref = $object->newref;
695  }
696  } elseif ($this->element == 'stockmouvement') {
697  foreach ($object as $key => $value) {
698  if (in_array($key, $arrayoffieldstoexclude)) {
699  continue; // Discard some properties
700  }
701  if (!is_object($value) && !is_null($value) && $value !== '') {
702  $this->object_data->$key = $value;
703  }
704  }
705  } else {
706  // Generic case
707  foreach ($object as $key => $value) {
708  if (in_array($key, $arrayoffieldstoexclude)) {
709  continue; // Discard some properties
710  }
711  if (!is_object($value) && !is_null($value) && $value !== '') {
712  $this->object_data->$key = $value;
713  }
714  }
715 
716  if (!empty($object->newref)) {
717  $this->object_data->ref = $object->newref;
718  }
719  }
720 
721  return 1;
722  }
723 
730  public function fetch($id)
731  {
732  global $langs;
733 
734  if (empty($id)) {
735  $this->error = 'BadParameter';
736  return -1;
737  }
738 
739  $sql = "SELECT b.rowid, b.date_creation, b.signature, b.signature_line, b.amounts, b.action, b.element, b.fk_object, b.entity,";
740  $sql .= " b.certified, b.tms, b.fk_user, b.user_fullname, b.date_object, b.ref_object, b.object_data, b.object_version";
741  $sql .= " FROM ".MAIN_DB_PREFIX."blockedlog as b";
742  if ($id) {
743  $sql .= " WHERE b.rowid = ".((int) $id);
744  }
745 
746  $resql = $this->db->query($sql);
747  if ($resql) {
748  $obj = $this->db->fetch_object($resql);
749  if ($obj) {
750  $this->id = $obj->rowid;
751  $this->entity = $obj->entity;
752  $this->ref = $obj->rowid;
753 
754  $this->date_creation = $this->db->jdate($obj->date_creation);
755  $this->tms = $this->db->jdate($obj->tms);
756 
757  $this->amounts = (double) $obj->amounts;
758  $this->action = $obj->action;
759  $this->element = $obj->element;
760 
761  $this->fk_object = $obj->fk_object;
762  $this->date_object = $this->db->jdate($obj->date_object);
763  $this->ref_object = $obj->ref_object;
764 
765  $this->fk_user = $obj->fk_user;
766  $this->user_fullname = $obj->user_fullname;
767 
768  $this->object_data = $this->dolDecodeBlockedData($obj->object_data);
769  $this->object_version = $obj->object_version;
770 
771  $this->signature = $obj->signature;
772  $this->signature_line = $obj->signature_line;
773  $this->certified = ($obj->certified == 1);
774 
775  return 1;
776  } else {
777  $langs->load("blockedlog");
778  $this->error = $langs->trans("RecordNotFound");
779  return 0;
780  }
781  } else {
782  $this->error = $this->db->error();
783  return -1;
784  }
785  }
786 
787 
795  public function dolDecodeBlockedData($data, $mode = 0)
796  {
797  try {
798  //include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
799  $aaa = unserialize($data);
800  } catch (Exception $e) {
801  //print $e->getErrs);
802  }
803  return $aaa;
804  }
805 
806 
812  public function setCertified()
813  {
814 
815  $res = $this->db->query("UPDATE ".MAIN_DB_PREFIX."blockedlog SET certified=1 WHERE rowid=".((int) $this->id));
816  if (!$res) {
817  return false;
818  }
819 
820  return true;
821  }
822 
830  public function create($user, $forcesignature = '')
831  {
832  global $conf, $langs, $hookmanager;
833 
834  $langs->load('blockedlog');
835 
836  $error = 0;
837 
838  // Clean data
839  $this->amounts = (double) $this->amounts;
840 
841  dol_syslog(get_class($this).'::create action='.$this->action.' fk_user='.$this->fk_user.' user_fullname='.$this->user_fullname, LOG_DEBUG);
842 
843  // Check parameters/properties
844  if (!isset($this->amounts)) { // amount can be 0 for some events (like when module is disabled)
845  $this->error = $langs->trans("BlockLogNeedAmountsValue");
846  dol_syslog($this->error, LOG_WARNING);
847  return -1;
848  }
849 
850  if (empty($this->element)) {
851  $this->error = $langs->trans("BlockLogNeedElement");
852  dol_syslog($this->error, LOG_WARNING);
853  return -2;
854  }
855 
856  if (empty($this->action)) {
857  $this->error = $langs->trans("BadParameterWhenCallingCreateOfBlockedLog");
858  dol_syslog($this->error, LOG_WARNING);
859  return -3;
860  }
861  if (empty($this->fk_user)) {
862  $this->user_fullname = '(Anonymous)';
863  }
864 
865  $this->date_creation = dol_now();
866 
867  $this->db->begin();
868 
869  $previoushash = $this->getPreviousHash(1, 0); // This get last record and lock database until insert is done
870 
871  $keyforsignature = $this->buildKeyForSignature();
872 
873  include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
874 
875  $this->signature_line = dol_hash($keyforsignature, '5'); // Not really usefull
876  $this->signature = dol_hash($previoushash.$keyforsignature, '5');
877  if ($forcesignature) {
878  $this->signature = $forcesignature;
879  }
880  //var_dump($keyforsignature);var_dump($previoushash);var_dump($this->signature_line);var_dump($this->signature);
881 
882  $sql = "INSERT INTO ".MAIN_DB_PREFIX."blockedlog (";
883  $sql .= " date_creation,";
884  $sql .= " action,";
885  $sql .= " amounts,";
886  $sql .= " signature,";
887  $sql .= " signature_line,";
888  $sql .= " element,";
889  $sql .= " fk_object,";
890  $sql .= " date_object,";
891  $sql .= " ref_object,";
892  $sql .= " object_data,";
893  $sql .= " object_version,";
894  $sql .= " certified,";
895  $sql .= " fk_user,";
896  $sql .= " user_fullname,";
897  $sql .= " entity";
898  $sql .= ") VALUES (";
899  $sql .= "'".$this->db->idate($this->date_creation)."',";
900  $sql .= "'".$this->db->escape($this->action)."',";
901  $sql .= $this->amounts.",";
902  $sql .= "'".$this->db->escape($this->signature)."',";
903  $sql .= "'".$this->db->escape($this->signature_line)."',";
904  $sql .= "'".$this->db->escape($this->element)."',";
905  $sql .= $this->fk_object.",";
906  $sql .= "'".$this->db->idate($this->date_object)."',";
907  $sql .= "'".$this->db->escape($this->ref_object)."',";
908  $sql .= "'".$this->db->escape(serialize($this->object_data))."',";
909  $sql .= "'".$this->db->escape($this->object_version)."',";
910  $sql .= "0,";
911  $sql .= $this->fk_user.",";
912  $sql .= "'".$this->db->escape($this->user_fullname)."',";
913  $sql .= ($this->entity ? $this->entity : $conf->entity);
914  $sql .= ")";
915 
916  $res = $this->db->query($sql);
917  if ($res) {
918  $id = $this->db->last_insert_id(MAIN_DB_PREFIX."blockedlog");
919 
920  if ($id > 0) {
921  $this->id = $id;
922 
923  $this->db->commit();
924 
925  return $this->id;
926  } else {
927  $this->db->rollback();
928  return -2;
929  }
930  } else {
931  $this->error = $this->db->error();
932  $this->db->rollback();
933  return -1;
934  }
935 
936  // The commit will release the lock so we can insert nex record
937  }
938 
946  public function checkSignature($previoushash = '', $returnarray = 0)
947  {
948  if (empty($previoushash)) {
949  $previoushash = $this->getPreviousHash(0, $this->id);
950  }
951  // Recalculate hash
952  $keyforsignature = $this->buildKeyForSignature();
953 
954  //$signature_line = dol_hash($keyforsignature, '5'); // Not really usefull
955  $signature = dol_hash($previoushash.$keyforsignature, '5');
956  //var_dump($previoushash); var_dump($keyforsignature); var_dump($signature_line); var_dump($signature);
957 
958  $res = ($signature === $this->signature);
959 
960  if (!$res) {
961  $this->error = 'Signature KO';
962  }
963 
964  if ($returnarray) {
965  if ($returnarray == 1) {
966  unset($keyforsignature);
967  return array('checkresult' => $res, 'calculatedsignature' => $signature, 'previoushash' => $previoushash);
968  } else { // Consume much memory ($keyforsignature is a large var)
969  return array('checkresult' => $res, 'calculatedsignature' => $signature, 'previoushash' => $previoushash, 'keyforsignature'=>$keyforsignature);
970  }
971  } else {
972  unset($keyforsignature);
973  return $res;
974  }
975  }
976 
984  private function buildKeyForSignature()
985  {
986  //print_r($this->object_data);
987  if (((int) $this->object_version) > 12) {
988  return $this->date_creation.'|'.$this->action.'|'.$this->amounts.'|'.$this->ref_object.'|'.$this->date_object.'|'.$this->user_fullname.'|'.print_r($this->object_data, true);
989  } else {
990  return $this->date_creation.'|'.$this->action.'|'.$this->amounts.'|'.$this->ref_object.'|'.$this->date_object.'|'.$this->user_fullname.'|'.print_r($this->object_data, true);
991  }
992  }
993 
994 
1002  public function getPreviousHash($withlock = 0, $beforeid = 0)
1003  {
1004  global $conf;
1005 
1006  $previoussignature = '';
1007 
1008  $sql = "SELECT rowid, signature FROM ".MAIN_DB_PREFIX."blockedlog";
1009  $sql .= " WHERE entity=".$conf->entity;
1010  if ($beforeid) {
1011  $sql .= " AND rowid < ".(int) $beforeid;
1012  }
1013  $sql .= " ORDER BY rowid DESC LIMIT 1";
1014  $sql .= ($withlock ? " FOR UPDATE " : "");
1015 
1016  $resql = $this->db->query($sql);
1017  if ($resql) {
1018  $obj = $this->db->fetch_object($resql);
1019  if ($obj) {
1020  $previoussignature = $obj->signature;
1021  }
1022  } else {
1023  dol_print_error($this->db);
1024  exit;
1025  }
1026 
1027  if (empty($previoussignature)) {
1028  // First signature line (line 0)
1029  $previoussignature = $this->getSignature();
1030  }
1031 
1032  return $previoussignature;
1033  }
1034 
1051  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 = '')
1052  {
1053  global $conf;
1054  //global $cachedlogs;
1055 
1056  /* $cachedlogs allow fastest search */
1057  //if (empty($cachedlogs)) $cachedlogs = array();
1058 
1059  if ($element == 'all') {
1060  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
1061  WHERE entity=".$conf->entity;
1062  } elseif ($element == 'not_certified') {
1063  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
1064  WHERE entity=".$conf->entity." AND certified = 0";
1065  } elseif ($element == 'just_certified') {
1066  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
1067  WHERE entity=".$conf->entity." AND certified = 1";
1068  } else {
1069  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
1070  WHERE entity=".$conf->entity." AND element='".$this->db->escape($element)."'";
1071  }
1072 
1073  if ($fk_object) {
1074  $sql .= natural_search("rowid", $fk_object, 1);
1075  }
1076  if ($search_fk_user > 0) {
1077  $sql .= natural_search("fk_user", $search_fk_user, 2);
1078  }
1079  if ($search_start > 0) {
1080  $sql .= " AND date_creation >= '".$this->db->idate($search_start)."'";
1081  }
1082  if ($search_end > 0) {
1083  $sql .= " AND date_creation <= '".$this->db->idate($search_end)."'";
1084  }
1085  if ($search_ref != '') {
1086  $sql .= natural_search("ref_object", $search_ref);
1087  }
1088  if ($search_amount != '') {
1089  $sql .= natural_search("amounts", $search_amount, 1);
1090  }
1091  if ($search_code != '' && $search_code != '-1') {
1092  $sql .= natural_search("action", $search_code, 3);
1093  }
1094 
1095  $sql .= $this->db->order($sortfield, $sortorder);
1096  $sql .= $this->db->plimit($limit + 1); // We want more, because we will stop into loop later with error if we reach max
1097 
1098  $res = $this->db->query($sql);
1099  if ($res) {
1100  $results = array();
1101 
1102  $i = 0;
1103  while ($obj = $this->db->fetch_object($res)) {
1104  $i++;
1105  if ($i > $limit) {
1106  // Too many record, we will consume too much memory
1107  return -2;
1108  }
1109 
1110  //if (!isset($cachedlogs[$obj->rowid]))
1111  //{
1112  $b = new BlockedLog($this->db);
1113  $b->fetch($obj->rowid);
1114  //$b->loadTrackedEvents();
1115  //$cachedlogs[$obj->rowid] = $b;
1116  //}
1117 
1118  //$results[] = $cachedlogs[$obj->rowid];
1119  $results[] = $b;
1120  }
1121 
1122  return $results;
1123  }
1124 
1125  return -1;
1126  }
1127 
1133  public function getSignature()
1134  {
1135  global $db, $conf, $mysoc;
1136 
1137  if (empty($conf->global->BLOCKEDLOG_ENTITY_FINGERPRINT)) { // creation of a unique fingerprint
1138  require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
1139  require_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
1140  require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
1141 
1142  $fingerprint = dol_hash(print_r($mysoc, true).getRandomPassword(1), '5');
1143 
1144  dolibarr_set_const($db, 'BLOCKEDLOG_ENTITY_FINGERPRINT', $fingerprint, 'chaine', 0, 'Numeric Unique Fingerprint', $conf->entity);
1145 
1146  $conf->global->BLOCKEDLOG_ENTITY_FINGERPRINT = $fingerprint;
1147  }
1148 
1149  return $conf->global->BLOCKEDLOG_ENTITY_FINGERPRINT;
1150  }
1151 
1152 
1159  public function alreadyUsed($ignoresystem = 0)
1160  {
1161  global $conf;
1162 
1163  $result = false;
1164 
1165  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog";
1166  $sql .= " WHERE entity = ".$conf->entity;
1167  if ($ignoresystem) {
1168  $sql .= " AND action not in ('MODULE_SET','MODULE_RESET')";
1169  }
1170  $sql .= $this->db->plimit(1);
1171 
1172  $res = $this->db->query($sql);
1173  if ($res !== false) {
1174  $obj = $this->db->fetch_object($res);
1175  if ($obj) {
1176  $result = true;
1177  }
1178  } else {
1179  dol_print_error($this->db);
1180  }
1181 
1182  dol_syslog("Module Blockedlog alreadyUsed with ignoresystem=".$ignoresystem." is ".$result);
1183 
1184  return $result;
1185  }
1186 }
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:632
$object ref
Definition: info.php:78
Class to manage Blocked Log.
getSignature()
Return the signature (hash) of the "genesis-block" (Block 0).
getObjectLink()
Try to retrieve source object (it it still exists).
alreadyUsed($ignoresystem=0)
Check if module was already used or not for at least one recording.
buildKeyForSignature()
Return a string for signature.
create($user, $forcesignature='')
Create blocked log in database.
loadTrackedEvents()
Load list of tracked events into $this->trackedevents.
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)
__construct(DoliDB $db)
Constructor.
setObjectData(&$object, $action, $amounts, $fuser=null)
Populate properties of log from object data.
getPreviousHash($withlock=0, $beforeid=0)
Get previous signature/hash in chain.
checkSignature($previoushash='', $returnarray=0)
Check if current signature still correct compared to the value in chain.
dolDecodeBlockedData($data, $mode=0)
Decode data.
fetch($id)
Get object from database.
setCertified()
Set block certified by authority.
Class to manage cash fence.
Class to manage Dolibarr database access.
Class to manage donations.
Definition: don.class.php:39
Class to manage suppliers invoices.
Class to manage invoices.
Class to manage stock movements.
Class to manage payments for supplier invoices.
Class to manage payments of customer invoices.
Class to manage payments of donations.
Class to manage various payments.
Class to manage subscriptions of foundation members.
Class to manage Dolibarr users.
Definition: user.class.php:47
if(isModEnabled('facture') &&!empty($user->rights->facture->lire)) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("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->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $resql
Social contributions to pay.
Definition: index.php:745
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
natural_search($fields, $value, $mode=0, $nofirstand=0)
Generate natural SQL search string for a criteria (this criteria can be tested on one or several fiel...
dol_now($mode='auto')
Return date for now.
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='')
Return an id or code from a code or id.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
getRandomPassword($generic=false, $replaceambiguouschars=null, $length=32)
Return a generated password using default module.
dol_hash($chain, $type='0')
Returns a hash (non reversible encryption) of a string.
$conf db
API class for accounts.
Definition: inc.php:41