dolibarr  18.0.0
adherent.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2002-2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2002-2003 Jean-Louis Bergamo <jlb@j1b.org>
4  * Copyright (C) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net>
5  * Copyright (C) 2004 Sebastien Di Cintio <sdicintio@ressource-toi.org>
6  * Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
7  * Copyright (C) 2009-2017 Regis Houssin <regis.houssin@inodbox.com>
8  * Copyright (C) 2014-2018 Alexandre Spangaro <aspangaro@open-dsi.fr>
9  * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
10  * Copyright (C) 2015-2023 Frédéric France <frederic.france@netlogic.fr>
11  * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
12  * Copyright (C) 2016 Juanjo Menent <jmenent@2byte.es>
13  * Copyright (C) 2018-2019 Thibault FOUCART <support@ptibogxiv.net>
14  * Copyright (C) 2019 Nicolas ZABOURI <info@inovea-conseil.com>
15  * Copyright (C) 2020 Josep Lluís Amador <joseplluis@lliuretic.cat>
16  * Copyright (C) 2021 Waël Almoman <info@almoman.com>
17  * Copyright (C) 2021 Philippe Grand <philippe.grand@atoo-net.com>
18  *
19  * This program is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation; either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program. If not, see <https://www.gnu.org/licenses/>.
31  */
32 
38 require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
39 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
40 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
41 require_once DOL_DOCUMENT_ROOT.'/core/class/commonpeople.class.php';
42 
43 
47 class Adherent extends CommonObject
48 {
49  use CommonPeople;
50 
54  public $element = 'member';
55 
59  public $table_element = 'adherent';
60 
65  public $ismultientitymanaged = 1;
66 
70  public $isextrafieldmanaged = 1;
71 
75  public $picto = 'member';
76 
77 
78  public $mesgs;
79 
83  public $login;
84 
88  public $pass;
89 
93  public $pass_indatabase;
94 
98  public $pass_indatabase_crypted;
99 
103  public $fullname;
104 
108  public $civility_id;
109  public $civility_code;
110  public $civility;
111 
117  public $societe;
118 
122  public $company;
123 
129  public $fk_soc;
130 
134  public $socid;
135 
139  public $address;
140 
144  public $zip;
145 
149  public $town;
150 
154  public $state_id;
155 
159  public $state_code;
160 
164  public $state;
165 
169  public $email;
170 
174  public $url;
175 
179  public $socialnetworks;
180 
186  public $skype;
187 
193  public $twitter;
194 
200  public $facebook;
201 
207  public $linkedin;
208 
212  public $phone;
213 
217  public $phone_perso;
218 
222  public $phone_pro;
223 
227  public $phone_mobile;
228 
232  public $fax;
233 
237  public $poste;
238 
242  public $morphy;
243 
247  public $public;
248 
253  public $default_lang;
254 
258  public $photo;
259 
265  public $datec;
266 
272  public $datem;
273 
274  public $datevalid;
275 
279  public $gender;
280 
281  public $birth;
282 
286  public $typeid;
287 
291  public $type;
292 
296  public $need_subscription;
297 
301  public $user_id;
302 
306  public $user_login;
307 
308  public $datefin;
309 
310 
311  // Fields loaded by fetch_subscriptions() from member table
312 
313  public $first_subscription_date;
314 
315  public $first_subscription_date_start;
316 
317  public $first_subscription_date_end;
318 
319  public $first_subscription_amount;
320 
321  public $last_subscription_date;
322 
323  public $last_subscription_date_start;
324 
325  public $last_subscription_date_end;
326 
327  public $last_subscription_amount;
328 
329  public $subscriptions = array();
330 
334  public $ip;
335 
336  // Fields loaded by fetchPartnerships() from partnership table
337 
338  public $partnerships = array();
339 
340 
344  public $oldcopy;
345 
349  public $entity;
350 
354  public $fields = array(
355  'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 10),
356  'ref' => array('type' => 'varchar(30)', 'label' => 'Ref', 'default' => 1, 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 12, 'index' => 1),
357  'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => 1, 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 15, 'index' => 1),
358  'ref_ext' => array('type' => 'varchar(128)', 'label' => 'Ref ext', 'enabled' => 1, 'visible' => 0, 'position' => 20),
359  'civility' => array('type' => 'varchar(6)', 'label' => 'Civility', 'enabled' => 1, 'visible' => -1, 'position' => 25),
360  'lastname' => array('type' => 'varchar(50)', 'label' => 'Lastname', 'enabled' => 1, 'visible' => -1, 'position' => 30, 'showoncombobox'=>1),
361  'firstname' => array('type' => 'varchar(50)', 'label' => 'Firstname', 'enabled' => 1, 'visible' => -1, 'position' => 35, 'showoncombobox'=>1),
362  'login' => array('type' => 'varchar(50)', 'label' => 'Login', 'enabled' => 1, 'visible' => -1, 'position' => 40),
363  'gender' => array('type' => 'varchar(10)', 'label' => 'Gender', 'enabled' => 1, 'visible' => -1, 'position' => 250),
364  'pass' => array('type' => 'varchar(50)', 'label' => 'Pass', 'enabled' => 1, 'visible' => -1, 'position' => 45),
365  'pass_crypted' => array('type' => 'varchar(128)', 'label' => 'Pass crypted', 'enabled' => 1, 'visible' => -1, 'position' => 50),
366  'fk_adherent_type' => array('type' => 'integer', 'label' => 'Fk adherent type', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 55),
367  'morphy' => array('type' => 'varchar(3)', 'label' => 'MorPhy', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 60),
368  'societe' => array('type' => 'varchar(128)', 'label' => 'Societe', 'enabled' => 1, 'visible' => -1, 'position' => 65, 'showoncombobox'=>2),
369  'fk_soc' => array('type' => 'integer:Societe:societe/class/societe.class.php', 'label' => 'ThirdParty', 'enabled' => 1, 'visible' => -1, 'position' => 70),
370  'address' => array('type' => 'text', 'label' => 'Address', 'enabled' => 1, 'visible' => -1, 'position' => 75),
371  'zip' => array('type' => 'varchar(10)', 'label' => 'Zip', 'enabled' => 1, 'visible' => -1, 'position' => 80),
372  'town' => array('type' => 'varchar(50)', 'label' => 'Town', 'enabled' => 1, 'visible' => -1, 'position' => 85),
373  'state_id' => array('type' => 'integer', 'label' => 'State id', 'enabled' => 1, 'visible' => -1, 'position' => 90),
374  'country' => array('type' => 'integer:Ccountry:core/class/ccountry.class.php', 'label' => 'Country', 'enabled' => 1, 'visible' => -1, 'position' => 95),
375  'email' => array('type' => 'varchar(255)', 'label' => 'Email', 'enabled' => 1, 'visible' => -1, 'position' => 100),
376  'url' =>array('type'=>'varchar(255)', 'label'=>'Url', 'enabled'=>1, 'visible'=>-1, 'position'=>110),
377  'socialnetworks' => array('type' => 'text', 'label' => 'Socialnetworks', 'enabled' => 1, 'visible' => -1, 'position' => 105),
378  'phone' => array('type' => 'varchar(30)', 'label' => 'Phone', 'enabled' => 1, 'visible' => -1, 'position' => 115),
379  'phone_perso' => array('type' => 'varchar(30)', 'label' => 'Phone perso', 'enabled' => 1, 'visible' => -1, 'position' => 120),
380  'phone_mobile' => array('type' => 'varchar(30)', 'label' => 'Phone mobile', 'enabled' => 1, 'visible' => -1, 'position' => 125),
381  'birth' => array('type' => 'date', 'label' => 'DateOfBirth', 'enabled' => 1, 'visible' => -1, 'position' => 130),
382  'photo' => array('type' => 'varchar(255)', 'label' => 'Photo', 'enabled' => 1, 'visible' => -1, 'position' => 135),
383  'public' => array('type' => 'smallint(6)', 'label' => 'Public', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 145),
384  'datefin' => array('type' => 'datetime', 'label' => 'DateEnd', 'enabled' => 1, 'visible' => -1, 'position' => 150),
385  'default_lang' =>array('type'=>'varchar(6)', 'label'=>'Default lang', 'enabled'=>1, 'visible'=>-1, 'position'=> 153),
386  'note_public' => array('type' => 'text', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 155),
387  'note_private' => array('type' => 'text', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 160),
388  'datevalid' => array('type' => 'datetime', 'label' => 'DateValidation', 'enabled' => 1, 'visible' => -1, 'position' => 165),
389  'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -1, 'position' => 170),
390  'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 175),
391  'fk_user_author' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'Fk user author', 'enabled' => 1, 'visible' => -1, 'position' => 180),
392  'fk_user_mod' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'Fk user mod', 'enabled' => 1, 'visible' => -1, 'position' => 185),
393  'fk_user_valid' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserValidation', 'enabled' => 1, 'visible' => -1, 'position' => 190),
394  'canvas' => array('type' => 'varchar(32)', 'label' => 'Canvas', 'enabled' => 1, 'visible' => -1, 'position' => 195),
395  'statut' => array('type' => 'smallint(6)', 'label' => 'Statut', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 500,
396  'arrayofkeyval' => array(-1 => 'Draft', 1 => 'Validated', 0 => 'MemberStatusResiliatedShort', -2 => 'MemberStatusExcludedShort')),
397  'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'visible' => 0, 'position' => 800),
398  'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -2, 'position' => 805)
399  );
400 
404  const STATUS_DRAFT = -1;
408  const STATUS_VALIDATED = 1;
412  const STATUS_RESILIATED = 0;
416  const STATUS_EXCLUDED = -2;
417 
418 
424  public function __construct($db)
425  {
426  $this->db = $db;
427  $this->statut = self::STATUS_DRAFT;
428  $this->status = $this->statut;
429  // l'adherent n'est pas public par defaut
430  $this->public = 0;
431  // les champs optionnels sont vides
432  $this->array_options = array();
433  }
434 
435 
436  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
455  public function send_an_email($text, $subject, $filename_list = array(), $mimetype_list = array(), $mimefilename_list = array(), $addr_cc = "", $addr_bcc = "", $deliveryreceipt = 0, $msgishtml = -1, $errors_to = '', $moreinheader = '')
456  {
457  // phpcs:enable
458  dol_syslog('Warning using deprecated Adherent::send_an_email', LOG_WARNING);
459 
460  return $this->sendEmail($text, $subject, $filename_list, $mimetype_list, $mimefilename_list, $addr_cc, $addr_bcc, $deliveryreceipt, $msgishtml, $errors_to, $moreinheader);
461  }
462 
480  public function sendEmail($text, $subject, $filename_list = array(), $mimetype_list = array(), $mimefilename_list = array(), $addr_cc = "", $addr_bcc = "", $deliveryreceipt = 0, $msgishtml = -1, $errors_to = '', $moreinheader = '')
481  {
482  global $conf, $langs;
483 
484  // Detect if message is HTML
485  if ($msgishtml == -1) {
486  $msgishtml = 0;
487  if (dol_textishtml($text, 0)) {
488  $msgishtml = 1;
489  }
490  }
491 
492  dol_syslog('send_an_email msgishtml='.$msgishtml);
493 
494  $texttosend = $this->makeSubstitution($text);
495  $subjecttosend = $this->makeSubstitution($subject);
496  if ($msgishtml) {
497  $texttosend = dol_htmlentitiesbr($texttosend);
498  }
499 
500  // Envoi mail confirmation
501  $from = $conf->email_from;
502  if (!empty(getDolGlobalString('ADHERENT_MAIL_FROM'))) {
503  $from = getDolGlobalString('ADHERENT_MAIL_FROM');
504  }
505 
506  $trackid = 'mem'.$this->id;
507 
508  // Send email (substitutionarray must be done just before this)
509  include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
510  $mailfile = new CMailFile($subjecttosend, $this->email, $from, $texttosend, $filename_list, $mimetype_list, $mimefilename_list, $addr_cc, $addr_bcc, $deliveryreceipt, $msgishtml, '', '', $trackid, $moreinheader);
511  if ($mailfile->sendfile()) {
512  return 1;
513  } else {
514  $this->error = $langs->trans("ErrorFailedToSendMail", $from, $this->email).'. '.$mailfile->error;
515  return -1;
516  }
517  }
518 
519 
526  public function makeSubstitution($text)
527  {
528  global $conf, $langs;
529 
530  $birthday = dol_print_date($this->birth, 'day');
531 
532  $msgishtml = 0;
533  if (dol_textishtml($text, 1)) {
534  $msgishtml = 1;
535  }
536 
537  $infos = '';
538  if ($this->civility_id) {
539  $infos .= $langs->transnoentities("UserTitle").": ".$this->getCivilityLabel()."\n";
540  }
541  $infos .= $langs->transnoentities("id").": ".$this->id."\n";
542  $infos .= $langs->transnoentities("ref").": ".$this->ref."\n";
543  $infos .= $langs->transnoentities("Lastname").": ".$this->lastname."\n";
544  $infos .= $langs->transnoentities("Firstname").": ".$this->firstname."\n";
545  $infos .= $langs->transnoentities("Company").": ".$this->company."\n";
546  $infos .= $langs->transnoentities("Address").": ".$this->address."\n";
547  $infos .= $langs->transnoentities("Zip").": ".$this->zip."\n";
548  $infos .= $langs->transnoentities("Town").": ".$this->town."\n";
549  $infos .= $langs->transnoentities("Country").": ".$this->country."\n";
550  $infos .= $langs->transnoentities("EMail").": ".$this->email."\n";
551  $infos .= $langs->transnoentities("PhonePro").": ".$this->phone."\n";
552  $infos .= $langs->transnoentities("PhonePerso").": ".$this->phone_perso."\n";
553  $infos .= $langs->transnoentities("PhoneMobile").": ".$this->phone_mobile."\n";
554  if (empty($conf->global->ADHERENT_LOGIN_NOT_REQUIRED)) {
555  $infos .= $langs->transnoentities("Login").": ".$this->login."\n";
556  $infos .= $langs->transnoentities("Password").": ".$this->pass."\n";
557  }
558  $infos .= $langs->transnoentities("Birthday").": ".$birthday."\n";
559  $infos .= $langs->transnoentities("Photo").": ".$this->photo."\n";
560  $infos .= $langs->transnoentities("Public").": ".yn($this->public);
561 
562  // Substitutions
563  $substitutionarray = array(
564  '__ID__' => $this->id,
565  '__REF__' => $this->ref,
566  '__MEMBER_ID__' => $this->id,
567  '__CIVILITY__' => $this->getCivilityLabel(),
568  '__FIRSTNAME__' => $msgishtml ? dol_htmlentitiesbr($this->firstname) : ($this->firstname ? $this->firstname : ''),
569  '__LASTNAME__' => $msgishtml ? dol_htmlentitiesbr($this->lastname) : ($this->lastname ? $this->lastname : ''),
570  '__FULLNAME__' => $msgishtml ? dol_htmlentitiesbr($this->getFullName($langs)) : $this->getFullName($langs),
571  '__COMPANY__' => $msgishtml ? dol_htmlentitiesbr($this->company) : ($this->company ? $this->company : ''),
572  '__ADDRESS__' => $msgishtml ? dol_htmlentitiesbr($this->address) : ($this->address ? $this->address : ''),
573  '__ZIP__' => $msgishtml ? dol_htmlentitiesbr($this->zip) : ($this->zip ? $this->zip : ''),
574  '__TOWN__' => $msgishtml ? dol_htmlentitiesbr($this->town) : ($this->town ? $this->town : ''),
575  '__COUNTRY__' => $msgishtml ? dol_htmlentitiesbr($this->country) : ($this->country ? $this->country : ''),
576  '__EMAIL__' => $msgishtml ? dol_htmlentitiesbr($this->email) : ($this->email ? $this->email : ''),
577  '__BIRTH__' => $msgishtml ? dol_htmlentitiesbr($birthday) : ($birthday ? $birthday : ''),
578  '__PHOTO__' => $msgishtml ? dol_htmlentitiesbr($this->photo) : ($this->photo ? $this->photo : ''),
579  '__LOGIN__' => $msgishtml ? dol_htmlentitiesbr($this->login) : ($this->login ? $this->login : ''),
580  '__PASSWORD__' => $msgishtml ? dol_htmlentitiesbr($this->pass) : ($this->pass ? $this->pass : ''),
581  '__PHONE__' => $msgishtml ? dol_htmlentitiesbr($this->phone) : ($this->phone ? $this->phone : ''),
582  '__PHONEPRO__' => $msgishtml ? dol_htmlentitiesbr($this->phone_perso) : ($this->phone_perso ? $this->phone_perso : ''),
583  '__PHONEMOBILE__' => $msgishtml ? dol_htmlentitiesbr($this->phone_mobile) : ($this->phone_mobile ? $this->phone_mobile : ''),
584  '__TYPE__' => $msgishtml ? dol_htmlentitiesbr($this->type) : ($this->type ? $this->type : '')
585  );
586 
587  complete_substitutions_array($substitutionarray, $langs, $this);
588 
589  return make_substitutions($text, $substitutionarray, $langs);
590  }
591 
592 
600  public function getmorphylib($morphy = '', $addbadge = 0)
601  {
602  global $langs;
603 
604  // Clean var
605  if (!$morphy) {
606  $morphy = $this->morphy;
607  }
608 
609  if ($addbadge) {
610  $s = '';
611  $labeltoshowm = $langs->trans("Moral");
612  $labeltoshowp = $langs->trans("Physical");
613  if ($morphy == 'phy') {
614  $labeltoshow = $labeltoshowp;
615  if ($addbadge == 2) {
616  $labeltoshow = dol_strtoupper(dolGetFirstLetters($labeltoshowp));
617  if ($labeltoshow == dol_strtoupper(dolGetFirstLetters($labeltoshowm))) {
618  $labeltoshow = dol_strtoupper(dolGetFirstLetters($labeltoshowp, 2));
619  }
620  }
621  $s .= '<span class="member-individual-back paddingleftimp paddingrightimp" title="'.$langs->trans("Physical").'">'.$labeltoshow.'</span>';
622  }
623  if ($morphy == 'mor') {
624  $labeltoshow = $labeltoshowm;
625  if ($addbadge == 2) {
626  $labeltoshow = dol_strtoupper(dolGetFirstLetters($labeltoshowm));
627  if ($labeltoshow == dol_strtoupper(dolGetFirstLetters($labeltoshowp))) {
628  $labeltoshow = dol_strtoupper(dolGetFirstLetters($labeltoshowm, 2));
629  }
630  }
631  $s .= '<span class="member-company-back paddingleftimp paddingrightimp" title="'.$langs->trans("Moral").'">'.$labeltoshow.'</span>';
632  }
633  } else {
634  if ($morphy == 'phy') {
635  $s = $langs->trans("Physical");
636  } elseif ($morphy == 'mor') {
637  $s = $langs->trans("Moral");
638  }
639  }
640 
641  return $s;
642  }
643 
651  public function create($user, $notrigger = 0)
652  {
653  global $conf, $langs, $mysoc;
654 
655  $error = 0;
656 
657  $now = dol_now();
658 
659  // Clean parameters
660  $this->import_key = trim($this->import_key);
661 
662  // Check parameters
663  if (!empty($conf->global->ADHERENT_MAIL_REQUIRED) && !isValidEMail($this->email)) {
664  $langs->load("errors");
665  $this->error = $langs->trans("ErrorBadEMail", $this->email);
666  return -1;
667  }
668  if (!$this->datec) {
669  $this->datec = $now;
670  }
671  if (empty($conf->global->ADHERENT_LOGIN_NOT_REQUIRED)) {
672  if (empty($this->login)) {
673  $this->error = $langs->trans("ErrorWrongValueForParameterX", "Login");
674  return -1;
675  }
676  }
677 
678  $this->db->begin();
679 
680  // Insert member
681  $sql = "INSERT INTO ".MAIN_DB_PREFIX."adherent";
682  $sql .= " (ref, datec,login,fk_user_author,fk_user_mod,fk_user_valid,morphy,fk_adherent_type,entity,import_key, ip)";
683  $sql .= " VALUES (";
684  $sql .= " '(PROV)'";
685  $sql .= ", '".$this->db->idate($this->datec)."'";
686  $sql .= ", ".($this->login ? "'".$this->db->escape($this->login)."'" : "null");
687  $sql .= ", ".($user->id > 0 ? $user->id : "null"); // Can be null because member can be created by a guest or a script
688  $sql .= ", null, null, '".$this->db->escape($this->morphy)."'";
689  $sql .= ", ".((int) $this->typeid);
690  $sql .= ", ".$conf->entity;
691  $sql .= ", ".(!empty($this->import_key) ? "'".$this->db->escape($this->import_key)."'" : "null");
692  $sql .= ", ".(!empty($this->ip) ? "'".$this->db->escape($this->ip)."'" : "null");
693  $sql .= ")";
694 
695  dol_syslog(get_class($this)."::create", LOG_DEBUG);
696  $result = $this->db->query($sql);
697  if ($result) {
698  $id = $this->db->last_insert_id(MAIN_DB_PREFIX."adherent");
699  if ($id > 0) {
700  $this->id = $id;
701  if (getDolGlobalString('MEMBER_CODEMEMBER_ADDON') == '') {
702  // keep old numbering
703  $this->ref = (string) $id;
704  } else {
705  // auto code
706  $modfile = dol_buildpath('core/modules/member/'.getDolGlobalString('MEMBER_CODEMEMBER_ADDON').'.php', 0);
707  try {
708  require_once $modfile;
709  $modname = getDolGlobalString('MEMBER_CODEMEMBER_ADDON');
710  $modCodeMember = new $modname;
711  $this->ref = $modCodeMember->getNextValue($mysoc, $this);
712  } catch (Exception $e) {
713  dol_syslog($e->getMessage(), LOG_ERR);
714  $error++;
715  }
716  }
717 
718  // Update minor fields
719  $result = $this->update($user, 1, 1, 0, 0, 'add'); // nosync is 1 to avoid update data of user
720  if ($result < 0) {
721  $this->db->rollback();
722  return -1;
723  }
724 
725  // Add link to user
726  if ($this->user_id) {
727  // Add link to user
728  $sql = "UPDATE ".MAIN_DB_PREFIX."user SET";
729  $sql .= " fk_member = ".((int) $this->id);
730  $sql .= " WHERE rowid = ".((int) $this->user_id);
731  dol_syslog(get_class($this)."::create", LOG_DEBUG);
732  $resql = $this->db->query($sql);
733  if (!$resql) {
734  $this->error = 'Failed to update user to make link with member';
735  $this->db->rollback();
736  return -4;
737  }
738  }
739 
740  if (!$notrigger) {
741  // Call trigger
742  $result = $this->call_trigger('MEMBER_CREATE', $user);
743  if ($result < 0) {
744  $error++;
745  }
746  // End call triggers
747  }
748 
749  if (count($this->errors)) {
750  dol_syslog(get_class($this)."::create ".implode(',', $this->errors), LOG_ERR);
751  $this->db->rollback();
752  return -3;
753  } else {
754  $this->db->commit();
755  return $this->id;
756  }
757  } else {
758  $this->error = 'Failed to get last insert id';
759  dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
760  $this->db->rollback();
761  return -2;
762  }
763  } else {
764  $this->error = $this->db->error();
765  $this->db->rollback();
766  return -1;
767  }
768  }
769 
770 
782  public function update($user, $notrigger = 0, $nosyncuser = 0, $nosyncuserpass = 0, $nosyncthirdparty = 0, $action = 'update')
783  {
784  global $conf, $langs, $hookmanager;
785 
786  require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
787 
788  $nbrowsaffected = 0;
789  $error = 0;
790 
791  dol_syslog(get_class($this)."::update notrigger=".$notrigger.", nosyncuser=".$nosyncuser.", nosyncuserpass=".$nosyncuserpass." nosyncthirdparty=".$nosyncthirdparty.", email=".$this->email);
792 
793  // Clean parameters
794  $this->lastname = trim($this->lastname) ? trim($this->lastname) : trim($this->lastname);
795  $this->firstname = trim($this->firstname) ? trim($this->firstname) : trim($this->firstname);
796  $this->gender = trim($this->gender);
797  $this->address = ($this->address ? $this->address : $this->address);
798  $this->zip = ($this->zip ? $this->zip : $this->zip);
799  $this->town = ($this->town ? $this->town : $this->town);
800  $this->country_id = ($this->country_id > 0 ? $this->country_id : $this->country_id);
801  $this->state_id = ($this->state_id > 0 ? $this->state_id : $this->state_id);
802  $this->note_public = ($this->note_public ? $this->note_public : $this->note_public);
803  $this->note_private = ($this->note_private ? $this->note_private : $this->note_private);
804  $this->url = $this->url ?clean_url($this->url, 0) : '';
805  $this->setUpperOrLowerCase();
806  // Check parameters
807  if (!empty($conf->global->ADHERENT_MAIL_REQUIRED) && !isValidEMail($this->email)) {
808  $langs->load("errors");
809  $this->error = $langs->trans("ErrorBadEMail", $this->email);
810  return -1;
811  }
812 
813  $this->db->begin();
814 
815  $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
816  $sql .= " ref = '".$this->db->escape($this->ref)."'";
817  $sql .= ", civility = ".($this->civility_id ? "'".$this->db->escape($this->civility_id)."'" : "null");
818  $sql .= ", firstname = ".($this->firstname ? "'".$this->db->escape($this->firstname)."'" : "null");
819  $sql .= ", lastname = ".($this->lastname ? "'".$this->db->escape($this->lastname)."'" : "null");
820  $sql .= ", gender = ".($this->gender != -1 ? "'".$this->db->escape($this->gender)."'" : "null"); // 'man' or 'woman'
821  $sql .= ", login = ".($this->login ? "'".$this->db->escape($this->login)."'" : "null");
822  $sql .= ", societe = ".($this->company ? "'".$this->db->escape($this->company)."'" : ($this->societe ? "'".$this->db->escape($this->societe)."'" : "null"));
823  if ($this->socid) {
824  $sql .= ", fk_soc = ".($this->socid > 0 ? $this->db->escape($this->socid) : "null"); // Must be modified only when creating from a third-party
825  }
826  $sql .= ", address = ".($this->address ? "'".$this->db->escape($this->address)."'" : "null");
827  $sql .= ", zip = ".($this->zip ? "'".$this->db->escape($this->zip)."'" : "null");
828  $sql .= ", town = ".($this->town ? "'".$this->db->escape($this->town)."'" : "null");
829  $sql .= ", country = ".($this->country_id > 0 ? $this->db->escape($this->country_id) : "null");
830  $sql .= ", state_id = ".($this->state_id > 0 ? $this->db->escape($this->state_id) : "null");
831  $sql .= ", email = '".$this->db->escape($this->email)."'";
832  $sql .= ", url = ".(!empty($this->url) ? "'".$this->db->escape($this->url)."'" : "null");
833  $sql .= ", socialnetworks = ".($this->socialnetworks ? "'".$this->db->escape(json_encode($this->socialnetworks))."'" : "null");
834  $sql .= ", phone = ".($this->phone ? "'".$this->db->escape($this->phone)."'" : "null");
835  $sql .= ", phone_perso = ".($this->phone_perso ? "'".$this->db->escape($this->phone_perso)."'" : "null");
836  $sql .= ", phone_mobile = ".($this->phone_mobile ? "'".$this->db->escape($this->phone_mobile)."'" : "null");
837  $sql .= ", note_private = ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "null");
838  $sql .= ", note_public = ".($this->note_public ? "'".$this->db->escape($this->note_public)."'" : "null");
839  $sql .= ", photo = ".($this->photo ? "'".$this->db->escape($this->photo)."'" : "null");
840  $sql .= ", public = '".$this->db->escape($this->public)."'";
841  $sql .= ", statut = ".$this->db->escape($this->statut);
842  $sql .= ", default_lang = ".(!empty($this->default_lang) ? "'".$this->db->escape($this->default_lang)."'" : "null");
843  $sql .= ", fk_adherent_type = ".$this->db->escape($this->typeid);
844  $sql .= ", morphy = '".$this->db->escape($this->morphy)."'";
845  $sql .= ", birth = ".($this->birth ? "'".$this->db->idate($this->birth)."'" : "null");
846 
847  if ($this->datefin) {
848  $sql .= ", datefin = '".$this->db->idate($this->datefin)."'"; // Must be modified only when deleting a subscription
849  }
850  if ($this->datevalid) {
851  $sql .= ", datevalid = '".$this->db->idate($this->datevalid)."'"; // Must be modified only when validating a member
852  }
853  $sql .= ", fk_user_mod = ".($user->id > 0 ? $user->id : 'null'); // Can be null because member can be create by a guest
854  $sql .= " WHERE rowid = ".((int) $this->id);
855 
856  // If we change the type of membership, we set also label of new type
857  if (!empty($this->oldcopy) && $this->typeid != $this->oldcopy->typeid) {
858  $sql2 = "SELECT libelle as label";
859  $sql2 .= " FROM ".MAIN_DB_PREFIX."adherent_type";
860  $sql2 .= " WHERE rowid = ".((int) $this->typeid);
861  $resql2 = $this->db->query($sql2);
862  if ($resql2) {
863  while ($obj = $this->db->fetch_object($resql2)) {
864  $this->type = $obj->label;
865  }
866  }
867  }
868 
869  dol_syslog(get_class($this)."::update update member", LOG_DEBUG);
870  $resql = $this->db->query($sql);
871  if ($resql) {
872  unset($this->country_code);
873  unset($this->country);
874  unset($this->state_code);
875  unset($this->state);
876 
877  $nbrowsaffected += $this->db->affected_rows($resql);
878 
879  $action = 'update';
880 
881  // Actions on extra fields
882  if (!$error) {
883  $result = $this->insertExtraFields();
884  if ($result < 0) {
885  $error++;
886  }
887  }
888 
889  // Update password
890  if (!$error && $this->pass) {
891  dol_syslog(get_class($this)."::update update password");
892  if ($this->pass != $this->pass_indatabase && $this->pass != $this->pass_indatabase_crypted) {
893  $isencrypted = empty($conf->global->DATABASE_PWD_ENCRYPTED) ? 0 : 1;
894 
895  // If password to set differs from the one found into database
896  $result = $this->setPassword($user, $this->pass, $isencrypted, $notrigger, $nosyncuserpass);
897  if (!$nbrowsaffected) {
898  $nbrowsaffected++;
899  }
900  }
901  }
902 
903  // Remove links to user and replace with new one
904  if (!$error) {
905  dol_syslog(get_class($this)."::update update link to user");
906  $sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = NULL WHERE fk_member = ".((int) $this->id);
907  dol_syslog(get_class($this)."::update", LOG_DEBUG);
908  $resql = $this->db->query($sql);
909  if (!$resql) {
910  $this->error = $this->db->error();
911  $this->db->rollback();
912  return -5;
913  }
914  // If there is a user linked to this member
915  if ($this->user_id > 0) {
916  $sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = ".((int) $this->id)." WHERE rowid = ".((int) $this->user_id);
917  dol_syslog(get_class($this)."::update", LOG_DEBUG);
918  $resql = $this->db->query($sql);
919  if (!$resql) {
920  $this->error = $this->db->error();
921  $this->db->rollback();
922  return -5;
923  }
924  }
925  }
926 
927  if (!$error && $nbrowsaffected) { // If something has change in main data
928  // Update information on linked user if it is an update
929  if (!$error && $this->user_id > 0 && !$nosyncuser) {
930  require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
931 
932  dol_syslog(get_class($this)."::update update linked user");
933 
934  $luser = new User($this->db);
935  $result = $luser->fetch($this->user_id);
936 
937  if ($result >= 0) {
938  //var_dump($this->user_login);exit;
939  //var_dump($this->login);exit;
940 
941  // If option ADHERENT_LOGIN_NOT_REQUIRED is on, there is no login of member, so we do not overwrite user login to keep existing one.
942  if (empty($conf->global->ADHERENT_LOGIN_NOT_REQUIRED)) {
943  $luser->login = $this->login;
944  }
945 
946  $luser->ref = $this->ref;
947  $luser->civility_id = $this->civility_id;
948  $luser->firstname = $this->firstname;
949  $luser->lastname = $this->lastname;
950  $luser->gender = $this->gender;
951  $luser->pass = $this->pass;
952  //$luser->socid=$this->fk_soc; // We do not enable this. This may transform a user into an external user.
953 
954  $luser->birth = $this->birth;
955 
956  $luser->address = $this->address;
957  $luser->zip = $this->zip;
958  $luser->town = $this->town;
959  $luser->country_id = $this->country_id;
960  $luser->state_id = $this->state_id;
961 
962  $luser->email = $this->email;
963  $luser->socialnetworks = $this->socialnetworks;
964  $luser->office_phone = $this->phone;
965  $luser->user_mobile = $this->phone_mobile;
966 
967  $luser->lang = $this->default_lang;
968 
969  $luser->fk_member = $this->id;
970 
971  $result = $luser->update($user, 0, 1, 1); // Use nosync to 1 to avoid cyclic updates
972  if ($result < 0) {
973  $this->error = $luser->error;
974  dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
975  $error++;
976  }
977  } else {
978  $this->error = $luser->error;
979  $error++;
980  }
981  }
982 
983  // Update information on linked thirdparty if it is an update
984  if (!$error && $this->fk_soc > 0 && !$nosyncthirdparty) {
985  require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
986 
987  dol_syslog(get_class($this)."::update update linked thirdparty");
988 
989  // This member is linked with a thirdparty, so we also update thirdparty informations
990  // if this is an update.
991  $lthirdparty = new Societe($this->db);
992  $result = $lthirdparty->fetch($this->fk_soc);
993 
994  if ($result > 0) {
995  $lthirdparty->address = $this->address;
996  $lthirdparty->zip = $this->zip;
997  $lthirdparty->town = $this->town;
998  $lthirdparty->email = $this->email;
999  $lthirdparty->socialnetworks = $this->socialnetworks;
1000  $lthirdparty->phone = $this->phone;
1001  $lthirdparty->state_id = $this->state_id;
1002  $lthirdparty->country_id = $this->country_id;
1003  //$lthirdparty->phone_mobile=$this->phone_mobile;
1004  $lthirdparty->default_lang = $this->default_lang;
1005 
1006  $result = $lthirdparty->update($this->fk_soc, $user, 0, 1, 1, 'update'); // Use sync to 0 to avoid cyclic updates
1007 
1008  if ($result < 0) {
1009  $this->error = $lthirdparty->error;
1010  $this->errors = $lthirdparty->errors;
1011  dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
1012  $error++;
1013  }
1014  } elseif ($result < 0) {
1015  $this->error = $lthirdparty->error;
1016  $error++;
1017  }
1018  }
1019  }
1020 
1021  if (!$error && !$notrigger) {
1022  // Call trigger
1023  $result = $this->call_trigger('MEMBER_MODIFY', $user);
1024  if ($result < 0) {
1025  $error++;
1026  }
1027  // End call triggers
1028  }
1029 
1030  if (!$error) {
1031  $this->db->commit();
1032  return $nbrowsaffected;
1033  } else {
1034  $this->db->rollback();
1035  return -1;
1036  }
1037  } else {
1038  $this->db->rollback();
1039  $this->error = $this->db->lasterror();
1040  return -2;
1041  }
1042  }
1043 
1044 
1045  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1053  public function update_end_date($user)
1054  {
1055  // phpcs:enable
1056  $this->db->begin();
1057 
1058  // Search for last subscription id and end date
1059  $sql = "SELECT rowid, datec as dateop, dateadh as datedeb, datef as datefin";
1060  $sql .= " FROM ".MAIN_DB_PREFIX."subscription";
1061  $sql .= " WHERE fk_adherent = ".((int) $this->id);
1062  $sql .= " ORDER by dateadh DESC"; // Sort by start subscription date
1063 
1064  dol_syslog(get_class($this)."::update_end_date", LOG_DEBUG);
1065  $resql = $this->db->query($sql);
1066  if ($resql) {
1067  $obj = $this->db->fetch_object($resql);
1068  $dateop = $this->db->jdate($obj->dateop);
1069  $datedeb = $this->db->jdate($obj->datedeb);
1070  $datefin = $this->db->jdate($obj->datefin);
1071 
1072  $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
1073  $sql .= " datefin=".($datefin != '' ? "'".$this->db->idate($datefin)."'" : "null");
1074  $sql .= " WHERE rowid = ".((int) $this->id);
1075 
1076  dol_syslog(get_class($this)."::update_end_date", LOG_DEBUG);
1077  $resql = $this->db->query($sql);
1078  if ($resql) {
1079  $this->last_subscription_date = $dateop;
1080  $this->last_subscription_date_start = $datedeb;
1081  $this->last_subscription_date_end = $datefin;
1082  $this->datefin = $datefin;
1083  $this->db->commit();
1084  return 1;
1085  } else {
1086  $this->db->rollback();
1087  return -1;
1088  }
1089  } else {
1090  $this->error = $this->db->lasterror();
1091  $this->db->rollback();
1092  return -1;
1093  }
1094  }
1095 
1104  public function delete($rowid, $user, $notrigger = 0)
1105  {
1106  global $conf, $langs;
1107 
1108  $result = 0;
1109  $error = 0;
1110  $errorflag = 0;
1111 
1112  // Check parameters
1113  if (empty($rowid)) {
1114  $rowid = $this->id;
1115  }
1116 
1117  $this->db->begin();
1118 
1119  if (!$error && !$notrigger) {
1120  // Call trigger
1121  $result = $this->call_trigger('MEMBER_DELETE', $user);
1122  if ($result < 0) {
1123  $error++;
1124  }
1125  // End call triggers
1126  }
1127 
1128  // Remove category
1129  $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_member WHERE fk_member = ".((int) $rowid);
1130  dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1131  $resql = $this->db->query($sql);
1132  if (!$resql) {
1133  $error++;
1134  $this->error .= $this->db->lasterror();
1135  $errorflag = -1;
1136  }
1137 
1138  // Remove subscription
1139  if (!$error) {
1140  $sql = "DELETE FROM ".MAIN_DB_PREFIX."subscription WHERE fk_adherent = ".((int) $rowid);
1141  dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1142  $resql = $this->db->query($sql);
1143  if (!$resql) {
1144  $error++;
1145  $this->error .= $this->db->lasterror();
1146  $errorflag = -2;
1147  }
1148  }
1149 
1150  // Remove linked user
1151  if (!$error) {
1152  $ret = $this->setUserId(0);
1153  if ($ret < 0) {
1154  $error++;
1155  $this->error .= $this->db->lasterror();
1156  $errorflag = -3;
1157  }
1158  }
1159 
1160  // Removed extrafields
1161  if (!$error) {
1162  $result = $this->deleteExtraFields();
1163  if ($result < 0) {
1164  $error++;
1165  $errorflag = -4;
1166  dol_syslog(get_class($this)."::delete erreur ".$errorflag." ".$this->error, LOG_ERR);
1167  }
1168  }
1169 
1170  // Remove adherent
1171  if (!$error) {
1172  $sql = "DELETE FROM ".MAIN_DB_PREFIX."adherent WHERE rowid = ".((int) $rowid);
1173  dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1174  $resql = $this->db->query($sql);
1175  if (!$resql) {
1176  $error++;
1177  $this->error .= $this->db->lasterror();
1178  $errorflag = -5;
1179  }
1180  }
1181 
1182  if (!$error) {
1183  $this->db->commit();
1184  return 1;
1185  } else {
1186  $this->db->rollback();
1187  return $errorflag;
1188  }
1189  }
1190 
1191 
1202  public function setPassword($user, $password = '', $isencrypted = 0, $notrigger = 0, $nosyncuser = 0)
1203  {
1204  global $conf, $langs;
1205 
1206  $error = 0;
1207 
1208  dol_syslog(get_class($this)."::setPassword user=".$user->id." password=".preg_replace('/./i', '*', $password)." isencrypted=".$isencrypted);
1209 
1210  // If new password not provided, we generate one
1211  if (!$password) {
1212  require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
1213  $password = getRandomPassword(false);
1214  }
1215 
1216  // Crypt password
1217  $password_crypted = dol_hash($password);
1218 
1219  $password_indatabase = '';
1220  if (!$isencrypted) {
1221  $password_indatabase = $password;
1222  }
1223 
1224  $this->db->begin();
1225 
1226  // Mise a jour
1227  $sql = "UPDATE ".MAIN_DB_PREFIX."adherent";
1228  $sql .= " SET pass_crypted = '".$this->db->escape($password_crypted)."'";
1229  //if (!empty($conf->global->DATABASE_PWD_ENCRYPTED))
1230  if ($isencrypted) {
1231  $sql .= ", pass = null";
1232  } else {
1233  $sql .= ", pass = '".$this->db->escape($password_indatabase)."'";
1234  }
1235  $sql .= " WHERE rowid = ".((int) $this->id);
1236 
1237  //dol_syslog("Adherent::Password sql=hidden");
1238  dol_syslog(get_class($this)."::setPassword", LOG_DEBUG);
1239  $result = $this->db->query($sql);
1240  if ($result) {
1241  $nbaffectedrows = $this->db->affected_rows($result);
1242 
1243  if ($nbaffectedrows) {
1244  $this->pass = $password;
1245  $this->pass_indatabase = $password_indatabase;
1246  $this->pass_indatabase_crypted = $password_crypted;
1247 
1248  if ($this->user_id && !$nosyncuser) {
1249  require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
1250 
1251  // This member is linked with a user, so we also update users informations
1252  // if this is an update.
1253  $luser = new User($this->db);
1254  $result = $luser->fetch($this->user_id);
1255 
1256  if ($result >= 0) {
1257  $result = $luser->setPassword($user, $this->pass, 0, 0, 1);
1258  if (is_numeric($result) && $result < 0) {
1259  $this->error = $luser->error;
1260  dol_syslog(get_class($this)."::setPassword ".$this->error, LOG_ERR);
1261  $error++;
1262  }
1263  } else {
1264  $this->error = $luser->error;
1265  $error++;
1266  }
1267  }
1268 
1269  if (!$error && !$notrigger) {
1270  // Call trigger
1271  $result = $this->call_trigger('MEMBER_NEW_PASSWORD', $user);
1272  if ($result < 0) {
1273  $error++;
1274  $this->db->rollback();
1275  return -1;
1276  }
1277  // End call triggers
1278  }
1279 
1280  $this->db->commit();
1281  return $this->pass;
1282  } else {
1283  $this->db->rollback();
1284  return 0;
1285  }
1286  } else {
1287  $this->db->rollback();
1288  dol_print_error($this->db);
1289  return -1;
1290  }
1291  }
1292 
1293 
1300  public function setUserId($userid)
1301  {
1302  global $conf, $langs;
1303 
1304  $this->db->begin();
1305 
1306  // If user is linked to this member, remove old link to this member
1307  $sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = NULL WHERE fk_member = ".((int) $this->id);
1308  dol_syslog(get_class($this)."::setUserId", LOG_DEBUG);
1309  $resql = $this->db->query($sql);
1310  if (!$resql) {
1311  $this->error = $this->db->error();
1312  $this->db->rollback();
1313  return -1;
1314  }
1315 
1316  // Set link to user
1317  if ($userid > 0) {
1318  $sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = ".((int) $this->id);
1319  $sql .= " WHERE rowid = ".((int) $userid);
1320  dol_syslog(get_class($this)."::setUserId", LOG_DEBUG);
1321  $resql = $this->db->query($sql);
1322  if (!$resql) {
1323  $this->error = $this->db->error();
1324  $this->db->rollback();
1325  return -2;
1326  }
1327  }
1328 
1329  $this->db->commit();
1330 
1331  return 1;
1332  }
1333 
1334 
1341  public function setThirdPartyId($thirdpartyid)
1342  {
1343  global $conf, $langs;
1344 
1345  $this->db->begin();
1346 
1347  // Remove link to third party onto any other members
1348  if ($thirdpartyid > 0) {
1349  $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET fk_soc = null";
1350  $sql .= " WHERE fk_soc = ".((int) $thirdpartyid);
1351  $sql .= " AND entity = ".$conf->entity;
1352  dol_syslog(get_class($this)."::setThirdPartyId", LOG_DEBUG);
1353  $resql = $this->db->query($sql);
1354  }
1355 
1356  // Add link to third party for current member
1357  $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET fk_soc = ".($thirdpartyid > 0 ? $thirdpartyid : 'null');
1358  $sql .= " WHERE rowid = ".((int) $this->id);
1359 
1360  dol_syslog(get_class($this)."::setThirdPartyId", LOG_DEBUG);
1361  $resql = $this->db->query($sql);
1362  if ($resql) {
1363  $this->db->commit();
1364  return 1;
1365  } else {
1366  $this->error = $this->db->error();
1367  $this->db->rollback();
1368  return -1;
1369  }
1370  }
1371 
1372 
1373  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1380  public function fetch_login($login)
1381  {
1382  // phpcs:enable
1383  global $conf;
1384 
1385  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."adherent";
1386  $sql .= " WHERE login='".$this->db->escape($login)."'";
1387  $sql .= " AND entity = ".$conf->entity;
1388 
1389  $resql = $this->db->query($sql);
1390  if ($resql) {
1391  if ($this->db->num_rows($resql)) {
1392  $obj = $this->db->fetch_object($resql);
1393  $this->fetch($obj->rowid);
1394  }
1395  } else {
1396  dol_print_error($this->db);
1397  }
1398  }
1399 
1400  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1408  public function fetch_name($firstname, $lastname)
1409  {
1410  // phpcs:enable
1411  global $conf;
1412 
1413  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."adherent";
1414  $sql .= " WHERE firstname='".$this->db->escape($firstname)."'";
1415  $sql .= " AND lastname='".$this->db->escape($lastname)."'";
1416  $sql .= " AND entity = ".$conf->entity;
1417 
1418  $resql = $this->db->query($sql);
1419  if ($resql) {
1420  if ($this->db->num_rows($resql)) {
1421  $obj = $this->db->fetch_object($resql);
1422  $this->fetch($obj->rowid);
1423  }
1424  } else {
1425  dol_print_error($this->db);
1426  }
1427  }
1428 
1440  public function fetch($rowid, $ref = '', $fk_soc = '', $ref_ext = '', $fetch_optionals = true, $fetch_subscriptions = true)
1441  {
1442  global $langs;
1443 
1444  $sql = "SELECT d.rowid, d.ref, d.ref_ext, d.civility as civility_code, d.gender, d.firstname, d.lastname,";
1445  $sql .= " d.societe as company, d.fk_soc, d.statut, d.public, d.address, d.zip, d.town, d.note_private,";
1446  $sql .= " d.note_public,";
1447  $sql .= " d.email, d.url, d.socialnetworks, d.phone, d.phone_perso, d.phone_mobile, d.login, d.pass, d.pass_crypted,";
1448  $sql .= " d.photo, d.fk_adherent_type, d.morphy, d.entity,";
1449  $sql .= " d.datec as datec,";
1450  $sql .= " d.tms as datem,";
1451  $sql .= " d.datefin as datefin, d.default_lang,";
1452  $sql .= " d.birth as birthday,";
1453  $sql .= " d.datevalid as datev,";
1454  $sql .= " d.country,";
1455  $sql .= " d.state_id,";
1456  $sql .= " d.model_pdf,";
1457  $sql .= " c.rowid as country_id, c.code as country_code, c.label as country,";
1458  $sql .= " dep.nom as state, dep.code_departement as state_code,";
1459  $sql .= " t.libelle as type, t.subscription as subscription,";
1460  $sql .= " u.rowid as user_id, u.login as user_login";
1461  $sql .= " FROM ".MAIN_DB_PREFIX."adherent_type as t, ".MAIN_DB_PREFIX."adherent as d";
1462  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as c ON d.country = c.rowid";
1463  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as dep ON d.state_id = dep.rowid";
1464  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u ON d.rowid = u.fk_member";
1465  $sql .= " WHERE d.fk_adherent_type = t.rowid";
1466  if ($rowid) {
1467  $sql .= " AND d.rowid=".((int) $rowid);
1468  } elseif ($ref || $fk_soc) {
1469  $sql .= " AND d.entity IN (".getEntity('adherent').")";
1470  if ($ref) {
1471  $sql .= " AND d.ref='".$this->db->escape($ref)."'";
1472  } elseif ($fk_soc > 0) {
1473  $sql .= " AND d.fk_soc=".((int) $fk_soc);
1474  }
1475  } elseif ($ref_ext) {
1476  $sql .= " AND d.ref_ext='".$this->db->escape($ref_ext)."'";
1477  }
1478 
1479  dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
1480  $resql = $this->db->query($sql);
1481  if ($resql) {
1482  if ($this->db->num_rows($resql)) {
1483  $obj = $this->db->fetch_object($resql);
1484 
1485  $this->entity = $obj->entity;
1486  $this->id = $obj->rowid;
1487  $this->ref = $obj->ref;
1488  $this->ref_ext = $obj->ref_ext;
1489 
1490  $this->civility_id = $obj->civility_code; // Bad. Kept for backard compatibility
1491  $this->civility_code = $obj->civility_code;
1492  $this->civility = $obj->civility_code ? ($langs->trans("Civility".$obj->civility_code) != ("Civility".$obj->civility_code) ? $langs->trans("Civility".$obj->civility_code) : $obj->civility_code) : '';
1493 
1494  $this->firstname = $obj->firstname;
1495  $this->lastname = $obj->lastname;
1496  $this->gender = $obj->gender;
1497  $this->login = $obj->login;
1498  $this->societe = $obj->company;
1499  $this->company = $obj->company;
1500  $this->socid = $obj->fk_soc;
1501  $this->fk_soc = $obj->fk_soc; // For backward compatibility
1502  $this->address = $obj->address;
1503  $this->zip = $obj->zip;
1504  $this->town = $obj->town;
1505 
1506  $this->pass = $obj->pass;
1507  $this->pass_indatabase = $obj->pass;
1508  $this->pass_indatabase_crypted = $obj->pass_crypted;
1509 
1510  $this->state_id = $obj->state_id;
1511  $this->state_code = $obj->state_id ? $obj->state_code : '';
1512  $this->state = $obj->state_id ? $obj->state : '';
1513 
1514  $this->country_id = $obj->country_id;
1515  $this->country_code = $obj->country_code;
1516  if ($langs->trans("Country".$obj->country_code) != "Country".$obj->country_code) {
1517  $this->country = $langs->transnoentitiesnoconv("Country".$obj->country_code);
1518  } else {
1519  $this->country = $obj->country;
1520  }
1521 
1522  $this->phone = $obj->phone;
1523  $this->phone_perso = $obj->phone_perso;
1524  $this->phone_mobile = $obj->phone_mobile;
1525  $this->email = $obj->email;
1526  $this->url = $obj->url;
1527 
1528  $this->socialnetworks = ($obj->socialnetworks ? (array) json_decode($obj->socialnetworks, true) : array());
1529 
1530  $this->photo = $obj->photo;
1531  $this->statut = $obj->statut;
1532  $this->status = $obj->statut;
1533  $this->public = $obj->public;
1534 
1535  $this->datec = $this->db->jdate($obj->datec);
1536  $this->date_creation = $this->db->jdate($obj->datec);
1537  $this->datem = $this->db->jdate($obj->datem);
1538  $this->date_modification = $this->db->jdate($obj->datem);
1539  $this->datefin = $this->db->jdate($obj->datefin);
1540  $this->datevalid = $this->db->jdate($obj->datev);
1541  $this->date_validation = $this->db->jdate($obj->datev);
1542  $this->birth = $this->db->jdate($obj->birthday);
1543 
1544  $this->default_lang = $obj->default_lang;
1545 
1546  $this->note_private = $obj->note_private;
1547  $this->note_public = $obj->note_public;
1548  $this->morphy = $obj->morphy;
1549 
1550  $this->typeid = $obj->fk_adherent_type;
1551  $this->type = $obj->type;
1552  $this->need_subscription = $obj->subscription;
1553 
1554  $this->user_id = $obj->user_id;
1555  $this->user_login = $obj->user_login;
1556 
1557  $this->model_pdf = $obj->model_pdf;
1558 
1559  // Retrieve all extrafield
1560  // fetch optionals attributes and labels
1561  if ($fetch_optionals) {
1562  $this->fetch_optionals();
1563  }
1564 
1565  // Load other properties
1566  if ($fetch_subscriptions) {
1567  $result = $this->fetch_subscriptions();
1568  }
1569 
1570  return $this->id;
1571  } else {
1572  return 0;
1573  }
1574  } else {
1575  $this->error = $this->db->lasterror();
1576  return -1;
1577  }
1578  }
1579 
1580 
1581  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1590  public function fetch_subscriptions()
1591  {
1592  // phpcs:enable
1593  global $langs;
1594 
1595  require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
1596 
1597  $sql = "SELECT c.rowid, c.fk_adherent, c.fk_type, c.subscription, c.note as note_public, c.fk_bank,";
1598  $sql .= " c.tms as datem,";
1599  $sql .= " c.datec as datec,";
1600  $sql .= " c.dateadh as dateh,";
1601  $sql .= " c.datef as datef";
1602  $sql .= " FROM ".MAIN_DB_PREFIX."subscription as c";
1603  $sql .= " WHERE c.fk_adherent = ".((int) $this->id);
1604  $sql .= " ORDER BY c.dateadh";
1605  dol_syslog(get_class($this)."::fetch_subscriptions", LOG_DEBUG);
1606 
1607  $resql = $this->db->query($sql);
1608  if ($resql) {
1609  $this->subscriptions = array();
1610 
1611  $i = 0;
1612  while ($obj = $this->db->fetch_object($resql)) {
1613  if ($i == 0) {
1614  $this->first_subscription_date = $this->db->jdate($obj->datec);
1615  $this->first_subscription_date_start = $this->db->jdate($obj->dateh);
1616  $this->first_subscription_date_end = $this->db->jdate($obj->datef);
1617  $this->first_subscription_amount = $obj->subscription;
1618  }
1619  $this->last_subscription_date = $this->db->jdate($obj->datec);
1620  $this->last_subscription_date_start = $this->db->jdate($obj->dateh);
1621  $this->last_subscription_date_end = $this->db->jdate($obj->datef);
1622  $this->last_subscription_amount = $obj->subscription;
1623 
1624  $subscription = new Subscription($this->db);
1625  $subscription->id = $obj->rowid;
1626  $subscription->fk_adherent = $obj->fk_adherent;
1627  $subscription->fk_type = $obj->fk_type;
1628  $subscription->amount = $obj->subscription;
1629  $subscription->note = $obj->note_public;
1630  $subscription->note_public = $obj->note_public;
1631  $subscription->fk_bank = $obj->fk_bank;
1632  $subscription->datem = $this->db->jdate($obj->datem);
1633  $subscription->datec = $this->db->jdate($obj->datec);
1634  $subscription->dateh = $this->db->jdate($obj->dateh);
1635  $subscription->datef = $this->db->jdate($obj->datef);
1636 
1637  $this->subscriptions[] = $subscription;
1638 
1639  $i++;
1640  }
1641  return 1;
1642  } else {
1643  $this->error = $this->db->error().' sql='.$sql;
1644  return -1;
1645  }
1646  }
1647 
1648 
1655  public function fetchPartnerships($mode)
1656  {
1657  global $langs;
1658 
1659  require_once DOL_DOCUMENT_ROOT.'/partnership/class/partnership.class.php';
1660 
1661 
1662  $this->partnerships[] = array();
1663 
1664  return 1;
1665  }
1666 
1667 
1683  public function subscription($date, $amount, $accountid = 0, $operation = '', $label = '', $num_chq = '', $emetteur_nom = '', $emetteur_banque = '', $datesubend = 0, $fk_type = null)
1684  {
1685  global $conf, $langs, $user;
1686 
1687  require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
1688 
1689  $error = 0;
1690 
1691  // Clean parameters
1692  if (!$amount) {
1693  $amount = 0;
1694  }
1695 
1696  $this->db->begin();
1697 
1698  if ($datesubend) {
1699  $datefin = $datesubend;
1700  } else {
1701  // If no end date, end date = date + 1 year - 1 day
1702  $datefin = dol_time_plus_duree($date, 1, 'y');
1703  $datefin = dol_time_plus_duree($datefin, -1, 'd');
1704  }
1705 
1706  // Create subscription
1707  $subscription = new Subscription($this->db);
1708  $subscription->fk_adherent = $this->id;
1709  $subscription->dateh = $date; // Date of new subscription
1710  $subscription->datef = $datefin; // End data of new subscription
1711  $subscription->amount = $amount;
1712  $subscription->note = $label; // deprecated
1713  $subscription->note_public = $label;
1714  $subscription->fk_type = $fk_type;
1715 
1716  $rowid = $subscription->create($user);
1717  if ($rowid > 0) {
1718  // Update denormalized subscription end date (read database subscription to find values)
1719  // This will also update this->datefin
1720  $result = $this->update_end_date($user);
1721  if ($result > 0) {
1722  // Change properties of object (used by triggers)
1723  $this->last_subscription_date = dol_now();
1724  $this->last_subscription_date_start = $date;
1725  $this->last_subscription_date_end = $datefin;
1726  $this->last_subscription_amount = $amount;
1727  }
1728 
1729  if (!$error) {
1730  $this->db->commit();
1731  return $rowid;
1732  } else {
1733  $this->db->rollback();
1734  return -2;
1735  }
1736  } else {
1737  $this->setErrorsFromObject($subscription);
1738  $this->db->rollback();
1739  return -1;
1740  }
1741  }
1742 
1743 
1763  public function subscriptionComplementaryActions($subscriptionid, $option, $accountid, $datesubscription, $paymentdate, $operation, $label, $amount, $num_chq, $emetteur_nom = '', $emetteur_banque = '', $autocreatethirdparty = 0, $ext_payment_id = '', $ext_payment_site = '')
1764  {
1765  global $conf, $langs, $user, $mysoc;
1766 
1767  $error = 0;
1768 
1769  $this->invoice = null; // This will contains invoice if an invoice is created
1770 
1771  dol_syslog("subscriptionComplementaryActions subscriptionid=".$subscriptionid." option=".$option." accountid=".$accountid." datesubscription=".$datesubscription." paymentdate=".
1772  $paymentdate." label=".$label." amount=".$amount." num_chq=".$num_chq." autocreatethirdparty=".$autocreatethirdparty);
1773 
1774  // Insert into bank account directlty (if option choosed for) + link to llx_subscription if option is 'bankdirect'
1775  if ($option == 'bankdirect' && $accountid) {
1776  require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
1777 
1778  $acct = new Account($this->db);
1779  $result = $acct->fetch($accountid);
1780 
1781  $dateop = $paymentdate;
1782 
1783  $insertid = $acct->addline($dateop, $operation, $label, $amount, $num_chq, '', $user, $emetteur_nom, $emetteur_banque);
1784  if ($insertid > 0) {
1785  $inserturlid = $acct->add_url_line($insertid, $this->id, DOL_URL_ROOT.'/adherents/card.php?rowid=', $this->getFullname($langs), 'member');
1786  if ($inserturlid > 0) {
1787  // Update table subscription
1788  $sql = "UPDATE ".MAIN_DB_PREFIX."subscription SET fk_bank=".((int) $insertid);
1789  $sql .= " WHERE rowid=".((int) $subscriptionid);
1790 
1791  dol_syslog("subscription::subscription", LOG_DEBUG);
1792  $resql = $this->db->query($sql);
1793  if (!$resql) {
1794  $error++;
1795  $this->error = $this->db->lasterror();
1796  $this->errors[] = $this->error;
1797  }
1798  } else {
1799  $error++;
1800  $this->setErrorsFromObject($acct);
1801  }
1802  } else {
1803  $error++;
1804  $this->setErrorsFromObject($acct);
1805  }
1806  }
1807 
1808  // If option choosed, we create invoice
1809  if (($option == 'bankviainvoice' && $accountid) || $option == 'invoiceonly') {
1810  require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
1811  require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/paymentterm.class.php';
1812 
1813  $invoice = new Facture($this->db);
1814  $customer = new Societe($this->db);
1815 
1816  if (!$error) {
1817  if (!($this->fk_soc > 0)) { // If not yet linked to a company
1818  if ($autocreatethirdparty) {
1819  // Create a linked thirdparty to member
1820  $companyalias = '';
1821  $fullname = $this->getFullName($langs);
1822 
1823  if ($this->morphy == 'mor') {
1824  $companyname = $this->company;
1825  if (!empty($fullname)) {
1826  $companyalias = $fullname;
1827  }
1828  } else {
1829  $companyname = $fullname;
1830  if (!empty($this->company)) {
1831  $companyalias = $this->company;
1832  }
1833  }
1834 
1835  $result = $customer->create_from_member($this, $companyname, $companyalias);
1836  if ($result < 0) {
1837  $this->error = $customer->error;
1838  $this->errors = $customer->errors;
1839  $error++;
1840  } else {
1841  $this->fk_soc = $result;
1842  }
1843  } else {
1844  $langs->load("errors");
1845  $this->error = $langs->trans("ErrorMemberNotLinkedToAThirpartyLinkOrCreateFirst");
1846  $this->errors[] = $this->error;
1847  $error++;
1848  }
1849  }
1850  }
1851  if (!$error) {
1852  $result = $customer->fetch($this->fk_soc);
1853  if ($result <= 0) {
1854  $this->error = $customer->error;
1855  $this->errors = $customer->errors;
1856  $error++;
1857  }
1858  }
1859 
1860  if (!$error) {
1861  // Create draft invoice
1862  $invoice->type = Facture::TYPE_STANDARD;
1863  $invoice->cond_reglement_id = $customer->cond_reglement_id;
1864  if (empty($invoice->cond_reglement_id)) {
1865  $paymenttermstatic = new PaymentTerm($this->db);
1866  $invoice->cond_reglement_id = $paymenttermstatic->getDefaultId();
1867  if (empty($invoice->cond_reglement_id)) {
1868  $error++;
1869  $this->error = 'ErrorNoPaymentTermRECEPFound';
1870  $this->errors[] = $this->error;
1871  }
1872  }
1873  $invoice->socid = $this->fk_soc;
1874  //$invoice->date = $datesubscription;
1875  $invoice->date = dol_now();
1876 
1877  // Possibility to add external linked objects with hooks
1878  $invoice->linked_objects['subscription'] = $subscriptionid;
1879  if (!empty($_POST['other_linked_objects']) && is_array($_POST['other_linked_objects'])) {
1880  $invoice->linked_objects = array_merge($invoice->linked_objects, $_POST['other_linked_objects']);
1881  }
1882 
1883  $result = $invoice->create($user);
1884  if ($result <= 0) {
1885  $this->error = $invoice->error;
1886  $this->errors = $invoice->errors;
1887  $error++;
1888  } else {
1889  $this->invoice = $invoice;
1890  }
1891  }
1892 
1893  if (!$error) {
1894  // Add line to draft invoice
1895  $idprodsubscription = 0;
1896  if (!empty($conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS) && (isModEnabled("product") || isModEnabled("service"))) {
1897  $idprodsubscription = $conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS;
1898  }
1899 
1900  $vattouse = 0;
1901  if (isset($conf->global->ADHERENT_VAT_FOR_SUBSCRIPTIONS) && $conf->global->ADHERENT_VAT_FOR_SUBSCRIPTIONS == 'defaultforfoundationcountry') {
1902  $vattouse = get_default_tva($mysoc, $mysoc, $idprodsubscription);
1903  }
1904  //print xx".$vattouse." - ".$mysoc." - ".$customer;exit;
1905  $result = $invoice->addline($label, 0, 1, $vattouse, 0, 0, $idprodsubscription, 0, $datesubscription, '', 0, 0, '', 'TTC', $amount, 1);
1906  if ($result <= 0) {
1907  $this->error = $invoice->error;
1908  $this->errors = $invoice->errors;
1909  $error++;
1910  }
1911  }
1912 
1913  if (!$error) {
1914  // Validate invoice
1915  $result = $invoice->validate($user);
1916  if ($result <= 0) {
1917  $this->error = $invoice->error;
1918  $this->errors = $invoice->errors;
1919  $error++;
1920  }
1921  }
1922 
1923  if (!$error) {
1924  // TODO Link invoice with subscription ?
1925  }
1926 
1927  // Add payment onto invoice
1928  if (!$error && $option == 'bankviainvoice' && $accountid) {
1929  require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
1930  require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
1931  require_once DOL_DOCUMENT_ROOT.'/core/lib/functions.lib.php';
1932 
1933  $amounts = array();
1934  $amounts[$invoice->id] = price2num($amount);
1935 
1936  $paiement = new Paiement($this->db);
1937  $paiement->datepaye = $paymentdate;
1938  $paiement->amounts = $amounts;
1939  $paiement->paiementcode = $operation;
1940  $paiement->paiementid = dol_getIdFromCode($this->db, $operation, 'c_paiement', 'code', 'id', 1);
1941  $paiement->num_payment = $num_chq;
1942  $paiement->note_public = $label;
1943  $paiement->ext_payment_id = $ext_payment_id;
1944  $paiement->ext_payment_site = $ext_payment_site;
1945 
1946  if (!$error) {
1947  // Create payment line for invoice
1948  $paiement_id = $paiement->create($user);
1949  if (!($paiement_id > 0)) {
1950  $this->error = $paiement->error;
1951  $this->errors = $paiement->errors;
1952  $error++;
1953  }
1954  }
1955 
1956  if (!$error) {
1957  // Add transaction into bank account
1958  $bank_line_id = $paiement->addPaymentToBank($user, 'payment', '(SubscriptionPayment)', $accountid, $emetteur_nom, $emetteur_banque);
1959  if (!($bank_line_id > 0)) {
1960  $this->error = $paiement->error;
1961  $this->errors = $paiement->errors;
1962  $error++;
1963  }
1964  }
1965 
1966  if (!$error && !empty($bank_line_id)) {
1967  // Update fk_bank into subscription table
1968  $sql = 'UPDATE '.MAIN_DB_PREFIX.'subscription SET fk_bank='.((int) $bank_line_id);
1969  $sql .= ' WHERE rowid='.((int) $subscriptionid);
1970 
1971  $result = $this->db->query($sql);
1972  if (!$result) {
1973  $error++;
1974  }
1975  }
1976 
1977  if (!$error) {
1978  // Set invoice as paid
1979  $invoice->setPaid($user);
1980  }
1981  }
1982 
1983  if (!$error) {
1984  // Define output language
1985  $outputlangs = $langs;
1986  $newlang = '';
1987  $lang_id = GETPOST('lang_id');
1988  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && !empty($lang_id)) {
1989  $newlang = $lang_id;
1990  }
1991  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1992  $newlang = $customer->default_lang;
1993  }
1994  if (!empty($newlang)) {
1995  $outputlangs = new Translate("", $conf);
1996  $outputlangs->setDefaultLang($newlang);
1997  }
1998  // Generate PDF (whatever is option MAIN_DISABLE_PDF_AUTOUPDATE) so we can include it into email
1999  //if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
2000 
2001  $invoice->generateDocument($invoice->model_pdf, $outputlangs);
2002  }
2003  }
2004 
2005  if ($error) {
2006  return -1;
2007  } else {
2008  return 1;
2009  }
2010  }
2011 
2012 
2019  public function validate($user)
2020  {
2021  global $langs, $conf;
2022 
2023  $error = 0;
2024  $now = dol_now();
2025 
2026  // Check parameters
2027  if ($this->statut == self::STATUS_VALIDATED) {
2028  dol_syslog(get_class($this)."::validate statut of member does not allow this", LOG_WARNING);
2029  return 0;
2030  }
2031 
2032  $this->db->begin();
2033 
2034  $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
2035  $sql .= " statut = ".self::STATUS_VALIDATED;
2036  $sql .= ", datevalid = '".$this->db->idate($now)."'";
2037  $sql .= ", fk_user_valid = ".((int) $user->id);
2038  $sql .= " WHERE rowid = ".((int) $this->id);
2039 
2040  dol_syslog(get_class($this)."::validate", LOG_DEBUG);
2041  $result = $this->db->query($sql);
2042  if ($result) {
2043  $this->statut = self::STATUS_VALIDATED;
2044 
2045  // Call trigger
2046  $result = $this->call_trigger('MEMBER_VALIDATE', $user);
2047  if ($result < 0) {
2048  $error++;
2049  $this->db->rollback();
2050  return -1;
2051  }
2052  // End call triggers
2053 
2054  $this->datevalid = $now;
2055 
2056  $this->db->commit();
2057  return 1;
2058  } else {
2059  $this->error = $this->db->error();
2060  $this->db->rollback();
2061  return -1;
2062  }
2063  }
2064 
2065 
2072  public function resiliate($user)
2073  {
2074  global $langs, $conf;
2075 
2076  $error = 0;
2077 
2078  // Check parameters
2079  if ($this->statut == self::STATUS_RESILIATED) {
2080  dol_syslog(get_class($this)."::resiliate statut of member does not allow this", LOG_WARNING);
2081  return 0;
2082  }
2083 
2084  $this->db->begin();
2085 
2086  $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
2087  $sql .= " statut = ".self::STATUS_RESILIATED;
2088  $sql .= ", fk_user_valid=".$user->id;
2089  $sql .= " WHERE rowid = ".((int) $this->id);
2090 
2091  $result = $this->db->query($sql);
2092  if ($result) {
2093  $this->statut = self::STATUS_RESILIATED;
2094 
2095  // Call trigger
2096  $result = $this->call_trigger('MEMBER_RESILIATE', $user);
2097  if ($result < 0) {
2098  $error++;
2099  $this->db->rollback();
2100  return -1;
2101  }
2102  // End call triggers
2103 
2104  $this->db->commit();
2105  return 1;
2106  } else {
2107  $this->error = $this->db->error();
2108  $this->db->rollback();
2109  return -1;
2110  }
2111  }
2112 
2122  public function exclude($user)
2123  {
2124  global $langs, $conf;
2125 
2126  $error = 0;
2127 
2128  // Check parameters
2129  if ($this->statut == self::STATUS_EXCLUDED) {
2130  dol_syslog(get_class($this)."::resiliate statut of member does not allow this", LOG_WARNING);
2131  return 0;
2132  }
2133 
2134  $this->db->begin();
2135 
2136  $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
2137  $sql .= " statut = ".self::STATUS_EXCLUDED;
2138  $sql .= ", fk_user_valid=".$user->id;
2139  $sql .= " WHERE rowid = ".((int) $this->id);
2140 
2141  $result = $this->db->query($sql);
2142  if ($result) {
2143  $this->statut = self::STATUS_EXCLUDED;
2144 
2145  // Call trigger
2146  $result = $this->call_trigger('MEMBER_EXCLUDE', $user);
2147  if ($result < 0) {
2148  $error++;
2149  $this->db->rollback();
2150  return -1;
2151  }
2152  // End call triggers
2153 
2154  $this->db->commit();
2155  return 1;
2156  } else {
2157  $this->error = $this->db->error();
2158  $this->db->rollback();
2159  return -1;
2160  }
2161  }
2162 
2163  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2169  public function add_to_abo()
2170  {
2171  // phpcs:enable
2172  global $conf, $langs;
2173 
2174  include_once DOL_DOCUMENT_ROOT.'/mailmanspip/class/mailmanspip.class.php';
2175  $mailmanspip = new MailmanSpip($this->db);
2176 
2177  $err = 0;
2178 
2179  // mailman
2180  if (!empty($conf->global->ADHERENT_USE_MAILMAN) && isModEnabled('mailmanspip')) {
2181  $result = $mailmanspip->add_to_mailman($this);
2182 
2183  if ($result < 0) {
2184  if (!empty($mailmanspip->error)) {
2185  $this->errors[] = $mailmanspip->error;
2186  }
2187  $err += 1;
2188  }
2189  foreach ($mailmanspip->mladded_ko as $tmplist => $tmpemail) {
2190  $langs->load("errors");
2191  $this->errors[] = $langs->trans("ErrorFailedToAddToMailmanList", $tmpemail, $tmplist);
2192  }
2193  foreach ($mailmanspip->mladded_ok as $tmplist => $tmpemail) {
2194  $langs->load("mailmanspip");
2195  $this->mesgs[] = $langs->trans("SuccessToAddToMailmanList", $tmpemail, $tmplist);
2196  }
2197  }
2198 
2199  // spip
2200  if (!empty($conf->global->ADHERENT_USE_SPIP) && isModEnabled('mailmanspip')) {
2201  $result = $mailmanspip->add_to_spip($this);
2202  if ($result < 0) {
2203  $this->errors[] = $mailmanspip->error;
2204  $err += 1;
2205  }
2206  }
2207  if ($err) {
2208  return -$err;
2209  } else {
2210  return 1;
2211  }
2212  }
2213 
2214 
2215  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2221  public function del_to_abo()
2222  {
2223  // phpcs:enable
2224  global $conf, $langs;
2225 
2226  include_once DOL_DOCUMENT_ROOT.'/mailmanspip/class/mailmanspip.class.php';
2227  $mailmanspip = new MailmanSpip($this->db);
2228 
2229  $err = 0;
2230 
2231  // mailman
2232  if (!empty($conf->global->ADHERENT_USE_MAILMAN)) {
2233  $result = $mailmanspip->del_to_mailman($this);
2234  if ($result < 0) {
2235  if (!empty($mailmanspip->error)) {
2236  $this->errors[] = $mailmanspip->error;
2237  }
2238  $err += 1;
2239  }
2240 
2241  foreach ($mailmanspip->mlremoved_ko as $tmplist => $tmpemail) {
2242  $langs->load("errors");
2243  $this->errors[] = $langs->trans("ErrorFailedToRemoveToMailmanList", $tmpemail, $tmplist);
2244  }
2245  foreach ($mailmanspip->mlremoved_ok as $tmplist => $tmpemail) {
2246  $langs->load("mailmanspip");
2247  $this->mesgs[] = $langs->trans("SuccessToRemoveToMailmanList", $tmpemail, $tmplist);
2248  }
2249  }
2250 
2251  if ($conf->global->ADHERENT_USE_SPIP && isModEnabled('mailmanspip')) {
2252  $result = $mailmanspip->del_to_spip($this);
2253  if ($result < 0) {
2254  $this->errors[] = $mailmanspip->error;
2255  $err += 1;
2256  }
2257  }
2258  if ($err) {
2259  // error
2260  return -$err;
2261  } else {
2262  return 1;
2263  }
2264  }
2265 
2266 
2272  public function getCivilityLabel()
2273  {
2274  global $langs;
2275  $langs->load("dict");
2276 
2277  $code = (empty($this->civility_id) ? '' : $this->civility_id);
2278  if (empty($code)) {
2279  return '';
2280  }
2281  return $langs->getLabelFromKey($this->db, "Civility".$code, "c_civility", "code", "label", $code);
2282  }
2283 
2290  public function getTooltipContentArray($params)
2291  {
2292  global $conf, $langs;
2293 
2294  $langs->loadLangs(['members', 'companies']);
2295  $nofetch = !empty($params['nofetch']);
2296 
2297  $datas = array();
2298 
2299  if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
2300  $langs->load("users");
2301  return ['optimize' => $langs->trans("ShowUser")];
2302  }
2303  if (!empty($this->photo)) {
2304  $photo = '<div class="photointooltip floatright">';
2305  $photo .= Form::showphoto('memberphoto', $this, 80, 0, 0, 'photoref photowithmargin photologintooltip', 'small', 0, 1);
2306  $photo .= '</div>';
2307  $datas['photo'] = $photo;
2308  }
2309 
2310  $datas['divopen'] = '<div class="centpercent">';
2311  $datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("Member").'</u> '.$this->getLibStatut(4);
2312  if (!empty($this->morphy)) {
2313  $datas['picto'] .= '&nbsp;' . $this->getmorphylib('', 1);
2314  }
2315  if (!empty($this->ref)) {
2316  $datas['ref'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
2317  }
2318  if (!empty($this->login)) {
2319  $datas['login'] = '<br><b>'.$langs->trans('Login').':</b> '.$this->login;
2320  }
2321  if (!empty($this->firstname) || !empty($this->lastname)) {
2322  $datas['name'] = '<br><b>'.$langs->trans('Name').':</b> '.$this->getFullName($langs);
2323  }
2324  if (!empty($this->company)) {
2325  $datas['company'] = '<br><b>'.$langs->trans('Company').':</b> '.$this->company;
2326  }
2327  if (!empty($this->email)) {
2328  $datas['email'] = '<br><b>'.$langs->trans("EMail").':</b> '.$this->email;
2329  }
2330  $datas['address'] = '<br><b>'.$langs->trans("Address").':</b> '.dol_format_address($this, 1, ' ', $langs);
2331  // show categories for this record only in ajax to not overload lists
2332  if (isModEnabled('categorie') && !$nofetch) {
2333  require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
2334  $form = new Form($this->db);
2335  $datas['categories'] = '<br>' . $form->showCategories($this->id, Categorie::TYPE_MEMBER, 1);
2336  }
2337  $datas['divclose'] = '</div>';
2338 
2339  return $datas;
2340  }
2341 
2355  public function getNomUrl($withpictoimg = 0, $maxlen = 0, $option = 'card', $mode = '', $morecss = '', $save_lastsearch_value = -1, $notooltip = 0, $addlinktonotes = 0)
2356  {
2357  global $conf, $langs, $hookmanager;
2358 
2359  if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) && $withpictoimg) {
2360  $withpictoimg = 0;
2361  }
2362 
2363  $result = '';
2364  $linkstart = '';
2365  $linkend = '';
2366  $classfortooltip = 'classfortooltip';
2367  $dataparams = '';
2368  $params = [
2369  'id' => $this->id,
2370  'objecttype' => $this->element,
2371  'option' => $option,
2372  'nofetch' => 1,
2373  ];
2374  if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
2375  $classfortooltip = 'classforajaxtooltip';
2376  $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
2377  $label = '';
2378  } else {
2379  $label = implode($this->getTooltipContentArray($params));
2380  }
2381 
2382  $url = DOL_URL_ROOT.'/adherents/card.php?rowid='.((int) $this->id);
2383  if ($option == 'subscription') {
2384  $url = DOL_URL_ROOT.'/adherents/subscription.php?rowid='.((int) $this->id);
2385  }
2386 
2387  if ($option != 'nolink') {
2388  // Add param to save lastsearch_values or not
2389  $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
2390  if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
2391  $add_save_lastsearch_values = 1;
2392  }
2393  if ($add_save_lastsearch_values) {
2394  $url .= '&save_lastsearch_values=1';
2395  }
2396  }
2397 
2398  $linkstart .= '<a href="'.$url.'"';
2399  $linkclose = "";
2400  if (empty($notooltip)) {
2401  if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
2402  $langs->load("users");
2403  $label = $langs->trans("ShowUser");
2404  $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
2405  }
2406  $linkclose .= ($label ? ' title="'.dol_escape_htmltag($label, 1).'"' : ' title="tocomplete"');
2407  $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
2408  }
2409 
2410  $linkstart .= $linkclose.'>';
2411  $linkend = '</a>';
2412 
2413  $result .= $linkstart;
2414  if ($withpictoimg) {
2415  $result .= '<div class="inline-block nopadding valignmiddle">';
2416  }
2417  if ($withpictoimg) {
2418  $paddafterimage = '';
2419  if (abs($withpictoimg) == 1 || abs($withpictoimg) == 4) {
2420  $morecss .= ' paddingrightonly';
2421  }
2422  // Only picto
2423  if ($withpictoimg > 0) {
2424  $picto = '<span class="nopadding'.($morecss ? ' userimg'.$morecss : '').'">'.img_object('', 'user', $paddafterimage.' '.($notooltip ? '' : $dataparams), 0, 0, $notooltip ? 0 : 1).'</span>';
2425  } else {
2426  // Picto must be a photo
2427  $picto = '<span class="nopadding'.($morecss ? ' userimg'.$morecss : '').'"'.($paddafterimage ? ' '.$paddafterimage : '').'>';
2428  $picto .= Form::showphoto('memberphoto', $this, 0, 0, 0, 'userphoto'.(($withpictoimg == -3 || $withpictoimg == -4) ? 'small' : ''), 'mini', 0, 1);
2429  $picto .= '</span>';
2430  }
2431  $result .= $picto;
2432  }
2433  if (($withpictoimg > -2 && $withpictoimg != 2) || $withpictoimg == -4) {
2434  if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
2435  $result .= '<span class="nopadding valignmiddle'.((!isset($this->statut) || $this->statut) ? '' : ' strikefordisabled').
2436  ($morecss ? ' usertext'.$morecss : '').'">';
2437  }
2438  if ($mode == 'login') {
2439  $result .= dol_trunc($this->login, $maxlen);
2440  } elseif ($mode == 'ref') {
2441  $result .= $this->ref;
2442  } else {
2443  $result .= $this->getFullName($langs, '', ($mode == 'firstname' ? 2 : ($mode == 'lastname' ? 4 : -1)), $maxlen);
2444  }
2445  if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
2446  $result .= '</span>';
2447  }
2448  }
2449  if ($withpictoimg) {
2450  $result .= '</div>';
2451  }
2452  $result .= $linkend;
2453 
2454  if ($addlinktonotes) {
2455  if ($this->note_private) {
2456  $notetoshow = $langs->trans("ViewPrivateNote").':<br>'.dol_string_nohtmltag($this->note_private, 1);
2457  $result .= ' <span class="note inline-block">';
2458  $result .= '<a href="'.DOL_URL_ROOT.'/adherents/note.php?id='.$this->id.'" class="classfortooltip" title="'.dol_escape_htmltag($notetoshow).'">';
2459  $result .= img_picto('', 'note');
2460  $result .= '</a>';
2461  $result .= '</span>';
2462  }
2463  }
2464  global $action;
2465  $hookmanager->initHooks(array($this->element . 'dao'));
2466  $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
2467  $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
2468  if ($reshook > 0) {
2469  $result = $hookmanager->resPrint;
2470  } else {
2471  $result .= $hookmanager->resPrint;
2472  }
2473  return $result;
2474  }
2475 
2482  public function getLibStatut($mode = 0)
2483  {
2484  return $this->LibStatut($this->statut, $this->need_subscription, $this->datefin, $mode);
2485  }
2486 
2487  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2497  public function LibStatut($status, $need_subscription, $date_end_subscription, $mode = 0)
2498  {
2499  // phpcs:enable
2500  global $langs;
2501  $langs->load("members");
2502 
2503  $statusType = '';
2504  $labelStatus = '';
2505  $labelStatusShort = '';
2506 
2507  if ($status == self::STATUS_DRAFT) {
2508  $statusType = 'status0';
2509  $labelStatus = $langs->trans("MemberStatusDraft");
2510  $labelStatusShort = $langs->trans("MemberStatusDraftShort");
2511  } elseif ($status >= self::STATUS_VALIDATED) {
2512  if ($need_subscription === 0) {
2513  $statusType = 'status4';
2514  $labelStatus = $langs->trans("MemberStatusNoSubscription");
2515  $labelStatusShort = $langs->trans("MemberStatusNoSubscriptionShort");
2516  } elseif (!$date_end_subscription) {
2517  $statusType = 'status1';
2518  $labelStatus = $langs->trans("WaitingSubscription");
2519  $labelStatusShort = $langs->trans("WaitingSubscriptionShort");
2520  } elseif ($date_end_subscription < dol_now()) { // expired
2521  $statusType = 'status8';
2522  $labelStatus = $langs->trans("MemberStatusActiveLate");
2523  $labelStatusShort = $langs->trans("MemberStatusActiveLateShort");
2524  } else {
2525  $statusType = 'status4';
2526  $labelStatus = $langs->trans("MemberStatusPaid");
2527  $labelStatusShort = $langs->trans("MemberStatusPaidShort");
2528  }
2529  } elseif ($status == self::STATUS_RESILIATED) {
2530  $statusType = 'status6';
2531  $labelStatus = $langs->transnoentitiesnoconv("MemberStatusResiliated");
2532  $labelStatusShort = $langs->transnoentitiesnoconv("MemberStatusResiliatedShort");
2533  } elseif ($status == self::STATUS_EXCLUDED) {
2534  $statusType = 'status10';
2535  $labelStatus = $langs->transnoentitiesnoconv("MemberStatusExcluded");
2536  $labelStatusShort = $langs->transnoentitiesnoconv("MemberStatusExcludedShort");
2537  }
2538 
2539  return dolGetStatus($labelStatus, $labelStatusShort, '', $statusType, $mode);
2540  }
2541 
2542 
2543  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2549  public function load_state_board()
2550  {
2551  // phpcs:enable
2552  global $conf;
2553 
2554  $this->nb = array();
2555 
2556  $sql = "SELECT count(a.rowid) as nb";
2557  $sql .= " FROM ".MAIN_DB_PREFIX."adherent as a";
2558  $sql .= " WHERE a.statut > 0";
2559  $sql .= " AND a.entity IN (".getEntity('adherent').")";
2560 
2561  $resql = $this->db->query($sql);
2562  if ($resql) {
2563  while ($obj = $this->db->fetch_object($resql)) {
2564  $this->nb["members"] = $obj->nb;
2565  }
2566  $this->db->free($resql);
2567  return 1;
2568  } else {
2569  dol_print_error($this->db);
2570  $this->error = $this->db->error();
2571  return -1;
2572  }
2573  }
2574 
2575  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2583  public function load_board($user, $mode)
2584  {
2585  // phpcs:enable
2586  global $conf, $langs;
2587 
2588  if ($user->socid) {
2589  return -1; // protection pour eviter appel par utilisateur externe
2590  }
2591 
2592  $now = dol_now();
2593 
2594  $sql = "SELECT a.rowid, a.datefin, a.statut";
2595  $sql .= " FROM ".MAIN_DB_PREFIX."adherent as a";
2596  $sql .= ", ".MAIN_DB_PREFIX."adherent_type as t";
2597  $sql .= " WHERE a.fk_adherent_type = t.rowid";
2598  if ($mode == 'expired') {
2599  $sql .= " AND a.statut = ".self::STATUS_VALIDATED;
2600  $sql .= " AND a.entity IN (".getEntity('adherent').")";
2601  $sql .= " AND ((a.datefin IS NULL or a.datefin < '".$this->db->idate($now)."') AND t.subscription = '1')";
2602  } elseif ($mode == 'shift') {
2603  $sql .= " AND a.statut = ".self::STATUS_DRAFT;
2604  $sql .= " AND a.entity IN (".getEntity('adherent').")";
2605  }
2606 
2607  $resql = $this->db->query($sql);
2608  if ($resql) {
2609  $langs->load("members");
2610 
2611  $warning_delay = 0;
2612  $url = '';
2613  $label = '';
2614  $labelShort = '';
2615 
2616  if ($mode == 'expired') {
2617  $warning_delay = $conf->adherent->subscription->warning_delay / 60 / 60 / 24;
2618  $label = $langs->trans("MembersWithSubscriptionToReceive");
2619  $labelShort = $langs->trans("MembersWithSubscriptionToReceiveShort");
2620  $url = DOL_URL_ROOT.'/adherents/list.php?mainmenu=members&amp;statut='.self::STATUS_VALIDATED.'&amp;filter=outofdate';
2621  } elseif ($mode == 'shift') {
2622  $warning_delay = $conf->adherent->subscription->warning_delay / 60 / 60 / 24;
2623  $url = DOL_URL_ROOT.'/adherents/list.php?mainmenu=members&amp;statut='.self::STATUS_DRAFT;
2624  $label = $langs->trans("MembersListToValid");
2625  $labelShort = $langs->trans("ToValidate");
2626  }
2627 
2628  $response = new WorkboardResponse();
2629  $response->warning_delay = $warning_delay;
2630  $response->label = $label;
2631  $response->labelShort = $labelShort;
2632  $response->url = $url;
2633  $response->img = img_object('', "user");
2634 
2635  $adherentstatic = new Adherent($this->db);
2636 
2637  while ($obj = $this->db->fetch_object($resql)) {
2638  $response->nbtodo++;
2639 
2640  $adherentstatic->datefin = $this->db->jdate($obj->datefin);
2641  $adherentstatic->statut = $obj->statut;
2642 
2643  if ($adherentstatic->hasDelay()) {
2644  $response->nbtodolate++;
2645  }
2646  }
2647 
2648  return $response;
2649  } else {
2650  dol_print_error($this->db);
2651  $this->error = $this->db->error();
2652  return -1;
2653  }
2654  }
2655 
2656 
2668  public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
2669  {
2670  global $conf, $langs;
2671 
2672  $langs->load("orders");
2673 
2674  if (!dol_strlen($modele)) {
2675  $modele = 'standard';
2676 
2677  if ($this->model_pdf) {
2678  $modele = $this->model_pdf;
2679  } elseif (!empty($conf->global->ADHERENT_ADDON_PDF)) {
2680  $modele = $conf->global->ADHERENT_ADDON_PDF;
2681  }
2682  }
2683 
2684  $modelpath = "core/modules/member/doc/";
2685 
2686  return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
2687  }
2688 
2689 
2697  public function initAsSpecimen()
2698  {
2699  global $user, $langs;
2700  $now = dol_now();
2701 
2702  // Initialise parametres
2703  $this->id = 0;
2704  $this->ref = 'ABC001';
2705  $this->entity = 1;
2706  $this->specimen = 1;
2707  $this->civility_id = 0;
2708  $this->lastname = 'DOLIBARR';
2709  $this->firstname = 'SPECIMEN';
2710  $this->gender = 'man';
2711  $this->login = 'dolibspec';
2712  $this->pass = 'dolibspec';
2713  $this->company = 'Societe ABC';
2714  $this->address = '61 jump street';
2715  $this->zip = '75000';
2716  $this->town = 'Paris';
2717  $this->country_id = 1;
2718  $this->country_code = 'FR';
2719  $this->country = 'France';
2720  $this->morphy = 'mor';
2721  $this->email = 'specimen@specimen.com';
2722  $this->socialnetworks = array(
2723  'skype' => 'skypepseudo',
2724  'twitter' => 'twitterpseudo',
2725  'facebook' => 'facebookpseudo',
2726  'linkedin' => 'linkedinpseudo',
2727  );
2728  $this->phone = '0999999999';
2729  $this->phone_perso = '0999999998';
2730  $this->phone_mobile = '0999999997';
2731  $this->note_public = 'This is a public note';
2732  $this->note_private = 'This is a private note';
2733  $this->birth = $now;
2734  $this->photo = '';
2735  $this->public = 1;
2736  $this->statut = self::STATUS_DRAFT;
2737 
2738  $this->datefin = $now;
2739  $this->datevalid = $now;
2740  $this->default_lang = '';
2741 
2742  $this->typeid = 1; // Id type adherent
2743  $this->type = 'Type adherent'; // Libelle type adherent
2744  $this->need_subscription = 0;
2745 
2746  $this->first_subscription_date = $now;
2747  $this->first_subscription_date_start = $this->first_subscription_date;
2748  $this->first_subscription_date_end = dol_time_plus_duree($this->first_subscription_date_start, 1, 'y');
2749  $this->first_subscription_amount = 10;
2750 
2751  $this->last_subscription_date = $this->first_subscription_date;
2752  $this->last_subscription_date_start = $this->first_subscription_date;
2753  $this->last_subscription_date_end = dol_time_plus_duree($this->last_subscription_date_start, 1, 'y');
2754  $this->last_subscription_amount = 10;
2755  return 1;
2756  }
2757 
2758 
2759  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2760  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
2770  public function _load_ldap_dn($info, $mode = 0)
2771  {
2772  // phpcs:enable
2773  global $conf;
2774  $dn = '';
2775  if ($mode == 0) {
2776  $dn = $conf->global->LDAP_KEY_MEMBERS."=".$info[$conf->global->LDAP_KEY_MEMBERS].",".$conf->global->LDAP_MEMBER_DN;
2777  }
2778  if ($mode == 1) {
2779  $dn = $conf->global->LDAP_MEMBER_DN;
2780  }
2781  if ($mode == 2) {
2782  $dn = $conf->global->LDAP_KEY_MEMBERS."=".$info[$conf->global->LDAP_KEY_MEMBERS];
2783  }
2784  return $dn;
2785  }
2786 
2787 
2788  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2789  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
2795  public function _load_ldap_info()
2796  {
2797  // phpcs:enable
2798  global $conf, $langs;
2799 
2800  $info = array();
2801  $socialnetworks = getArrayOfSocialNetworks();
2802  $keymodified = false;
2803 
2804  // Object classes
2805  $info["objectclass"] = explode(',', $conf->global->LDAP_MEMBER_OBJECT_CLASS);
2806 
2807  $this->fullname = $this->getFullName($langs);
2808 
2809  // For avoid ldap error when firstname and lastname are empty
2810  if ($this->morphy == 'mor' && (empty($this->fullname) || $this->fullname == $this->company)) {
2811  $this->fullname = $this->company;
2812  $this->lastname = $this->company;
2813  }
2814 
2815  // Possible LDAP KEY (constname => varname)
2816  $ldapkey = array(
2817  'LDAP_MEMBER_FIELD_FULLNAME' => 'fullname',
2818  'LDAP_MEMBER_FIELD_NAME' => 'lastname',
2819  'LDAP_MEMBER_FIELD_LOGIN' => 'login',
2820  'LDAP_MEMBER_FIELD_LOGIN_SAMBA' => 'login',
2821  'LDAP_MEMBER_FIELD_MAIL' => 'email'
2822  );
2823 
2824  // Member
2825  foreach ($ldapkey as $constname => $varname) {
2826  if (!empty($this->$varname) && !empty($conf->global->$constname)) {
2827  $info[$conf->global->$constname] = $this->$varname;
2828 
2829  // Check if it is the LDAP key and if its value has been changed
2830  if (!empty($conf->global->LDAP_KEY_MEMBERS) && $conf->global->LDAP_KEY_MEMBERS == $conf->global->$constname) {
2831  if (!empty($this->oldcopy) && $this->$varname != $this->oldcopy->$varname) {
2832  $keymodified = true; // For check if LDAP key has been modified
2833  }
2834  }
2835  }
2836  }
2837  if ($this->firstname && !empty($conf->global->LDAP_MEMBER_FIELD_FIRSTNAME)) {
2838  $info[$conf->global->LDAP_MEMBER_FIELD_FIRSTNAME] = $this->firstname;
2839  }
2840  if ($this->poste && !empty($conf->global->LDAP_MEMBER_FIELD_TITLE)) {
2841  $info[$conf->global->LDAP_MEMBER_FIELD_TITLE] = $this->poste;
2842  }
2843  if ($this->company && !empty($conf->global->LDAP_MEMBER_FIELD_COMPANY)) {
2844  $info[$conf->global->LDAP_MEMBER_FIELD_COMPANY] = $this->company;
2845  }
2846  if ($this->address && !empty($conf->global->LDAP_MEMBER_FIELD_ADDRESS)) {
2847  $info[$conf->global->LDAP_MEMBER_FIELD_ADDRESS] = $this->address;
2848  }
2849  if ($this->zip && !empty($conf->global->LDAP_MEMBER_FIELD_ZIP)) {
2850  $info[$conf->global->LDAP_MEMBER_FIELD_ZIP] = $this->zip;
2851  }
2852  if ($this->town && !empty($conf->global->LDAP_MEMBER_FIELD_TOWN)) {
2853  $info[$conf->global->LDAP_MEMBER_FIELD_TOWN] = $this->town;
2854  }
2855  if ($this->country_code && !empty($conf->global->LDAP_MEMBER_FIELD_COUNTRY)) {
2856  $info[$conf->global->LDAP_MEMBER_FIELD_COUNTRY] = $this->country_code;
2857  }
2858  foreach ($socialnetworks as $key => $value) {
2859  if ($this->socialnetworks[$value['label']] && !empty($conf->global->{'LDAP_MEMBER_FIELD_'.strtoupper($value['label'])})) {
2860  $info[$conf->global->{'LDAP_MEMBER_FIELD_'.strtoupper($value['label'])}] = $this->socialnetworks[$value['label']];
2861  }
2862  }
2863  if ($this->phone && !empty($conf->global->LDAP_MEMBER_FIELD_PHONE)) {
2864  $info[$conf->global->LDAP_MEMBER_FIELD_PHONE] = $this->phone;
2865  }
2866  if ($this->phone_perso && !empty($conf->global->LDAP_MEMBER_FIELD_PHONE_PERSO)) {
2867  $info[$conf->global->LDAP_MEMBER_FIELD_PHONE_PERSO] = $this->phone_perso;
2868  }
2869  if ($this->phone_mobile && !empty($conf->global->LDAP_MEMBER_FIELD_MOBILE)) {
2870  $info[$conf->global->LDAP_MEMBER_FIELD_MOBILE] = $this->phone_mobile;
2871  }
2872  if ($this->fax && !empty($conf->global->LDAP_MEMBER_FIELD_FAX)) {
2873  $info[$conf->global->LDAP_MEMBER_FIELD_FAX] = $this->fax;
2874  }
2875  if ($this->note_private && !empty($conf->global->LDAP_MEMBER_FIELD_DESCRIPTION)) {
2876  $info[$conf->global->LDAP_MEMBER_FIELD_DESCRIPTION] = dol_string_nohtmltag($this->note_private, 2);
2877  }
2878  if ($this->note_public && !empty($conf->global->LDAP_MEMBER_FIELD_NOTE_PUBLIC)) {
2879  $info[$conf->global->LDAP_MEMBER_FIELD_NOTE_PUBLIC] = dol_string_nohtmltag($this->note_public, 2);
2880  }
2881  if ($this->birth && !empty($conf->global->LDAP_MEMBER_FIELD_BIRTHDATE)) {
2882  $info[$conf->global->LDAP_MEMBER_FIELD_BIRTHDATE] = dol_print_date($this->birth, 'dayhourldap');
2883  }
2884  if (isset($this->statut) && !empty($conf->global->LDAP_FIELD_MEMBER_STATUS)) {
2885  $info[$conf->global->LDAP_FIELD_MEMBER_STATUS] = $this->statut;
2886  }
2887  if ($this->datefin && !empty($conf->global->LDAP_FIELD_MEMBER_END_LASTSUBSCRIPTION)) {
2888  $info[$conf->global->LDAP_FIELD_MEMBER_END_LASTSUBSCRIPTION] = dol_print_date($this->datefin, 'dayhourldap');
2889  }
2890 
2891  // When password is modified
2892  if (!empty($this->pass)) {
2893  if (!empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD)) {
2894  $info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD] = $this->pass; // this->pass = mot de passe non crypte
2895  }
2896  if (!empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED)) {
2897  $info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED] = dol_hash($this->pass, 'openldap'); // Create OpenLDAP password (see LDAP_PASSWORD_HASH_TYPE)
2898  }
2899  } elseif ($conf->global->LDAP_SERVER_PROTOCOLVERSION !== '3') {
2900  // Set LDAP password if possible
2901  // If ldap key is modified and LDAPv3 we use ldap_rename function for avoid lose encrypt password
2902  if (!empty($conf->global->DATABASE_PWD_ENCRYPTED)) {
2903  // Just for the default MD5 !
2904  if (empty($conf->global->MAIN_SECURITY_HASH_ALGO)) {
2905  if ($this->pass_indatabase_crypted && !empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED)) {
2906  // Create OpenLDAP MD5 password from Dolibarr MD5 password
2907  // Note: This suppose that "pass_indatabase_crypted" is a md5 (guaranted by the previous test if "(empty($conf->global->MAIN_SECURITY_HASH_ALGO))"
2908  $info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED] = dolGetLdapPasswordHash($this->pass_indatabase_crypted, 'md5frommd5');
2909  }
2910  }
2911  } elseif (!empty($this->pass_indatabase)) {
2912  // Use $this->pass_indatabase value if exists
2913  if (!empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD)) {
2914  $info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD] = $this->pass_indatabase; // $this->pass_indatabase = mot de passe non crypte
2915  }
2916  if (!empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED)) {
2917  $info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED] = dol_hash($this->pass_indatabase, 'openldap'); // Create OpenLDAP password (see LDAP_PASSWORD_HASH_TYPE)
2918  }
2919  }
2920  }
2921 
2922  // Subscriptions
2923  if ($this->first_subscription_date && !empty($conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_DATE)) {
2924  $info[$conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_DATE] = dol_print_date($this->first_subscription_date, 'dayhourldap');
2925  }
2926  if (isset($this->first_subscription_amount) && !empty($conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_AMOUNT)) {
2927  $info[$conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_AMOUNT] = $this->first_subscription_amount;
2928  }
2929  if ($this->last_subscription_date && !empty($conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_DATE)) {
2930  $info[$conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_DATE] = dol_print_date($this->last_subscription_date, 'dayhourldap');
2931  }
2932  if (isset($this->last_subscription_amount) && !empty($conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_AMOUNT)) {
2933  $info[$conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_AMOUNT] = $this->last_subscription_amount;
2934  }
2935 
2936  return $info;
2937  }
2938 
2939 
2946  public function info($id)
2947  {
2948  $sql = 'SELECT a.rowid, a.datec as datec,';
2949  $sql .= ' a.datevalid as datev,';
2950  $sql .= ' a.tms as datem,';
2951  $sql .= ' a.fk_user_author, a.fk_user_valid, a.fk_user_mod';
2952  $sql .= ' FROM '.MAIN_DB_PREFIX.'adherent as a';
2953  $sql .= ' WHERE a.rowid = '.((int) $id);
2954 
2955  dol_syslog(get_class($this)."::info", LOG_DEBUG);
2956  $result = $this->db->query($sql);
2957  if ($result) {
2958  if ($this->db->num_rows($result)) {
2959  $obj = $this->db->fetch_object($result);
2960  $this->id = $obj->rowid;
2961 
2962  $this->user_creation_id = $obj->fk_user_author;
2963  $this->user_validation_id = $obj->fk_user_valid;
2964  $this->user_modification_id = $obj->fk_user_mod;
2965  $this->date_creation = $this->db->jdate($obj->datec);
2966  $this->date_validation = $this->db->jdate($obj->datev);
2967  $this->date_modification = $this->db->jdate($obj->datem);
2968  }
2969 
2970  $this->db->free($result);
2971  } else {
2972  dol_print_error($this->db);
2973  }
2974  }
2975 
2981  public function getNbOfEMailings()
2982  {
2983  $sql = "SELECT count(mc.email) as nb";
2984  $sql .= " FROM ".MAIN_DB_PREFIX."mailing_cibles as mc";
2985  $sql .= " WHERE mc.email = '".$this->db->escape($this->email)."'";
2986  $sql .= " AND mc.statut NOT IN (-1,0)"; // -1 erreur, 0 non envoye, 1 envoye avec succes
2987 
2988  $resql = $this->db->query($sql);
2989  if ($resql) {
2990  $obj = $this->db->fetch_object($resql);
2991  $nb = $obj->nb;
2992 
2993  $this->db->free($resql);
2994  return $nb;
2995  } else {
2996  $this->error = $this->db->error();
2997  return -1;
2998  }
2999  }
3000 
3011  public function setCategories($categories)
3012  {
3013  require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
3014  return parent::setCategoriesCommon($categories, Categorie::TYPE_MEMBER);
3015  }
3016 
3025  public static function replaceThirdparty($db, $origin_id, $dest_id)
3026  {
3027  $tables = array('adherent');
3028 
3029  return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
3030  }
3031 
3037  public function hasDelay()
3038  {
3039  global $conf;
3040 
3041  //Only valid members
3042  if ($this->statut != self::STATUS_VALIDATED) {
3043  return false;
3044  }
3045  if (!$this->datefin) {
3046  return false;
3047  }
3048 
3049  $now = dol_now();
3050 
3051  return $this->datefin < ($now - $conf->adherent->subscription->warning_delay);
3052  }
3053 
3054 
3062  public function sendReminderForExpiredSubscription($daysbeforeendlist = '10')
3063  {
3064  global $conf, $langs, $mysoc, $user;
3065 
3066  $error = 0;
3067  $this->output = '';
3068  $this->error = '';
3069 
3070  $blockingerrormsg = '';
3071 
3072  if (!isModEnabled('adherent')) { // Should not happen. If module disabled, cron job should not be visible.
3073  $langs->load("agenda");
3074  $this->output = $langs->trans('ModuleNotEnabled', $langs->transnoentitiesnoconv("Adherent"));
3075  return 0;
3076  }
3077  if (empty($conf->global->MEMBER_REMINDER_EMAIL)) {
3078  $langs->load("agenda");
3079  $this->output = $langs->trans('EventRemindersByEmailNotEnabled', $langs->transnoentitiesnoconv("Adherent"));
3080  return 0;
3081  }
3082 
3083  $now = dol_now();
3084  $nbok = 0;
3085  $nbko = 0;
3086 
3087  $listofmembersok = array();
3088  $listofmembersko = array();
3089 
3090  $arraydaysbeforeend = explode(';', $daysbeforeendlist);
3091  foreach ($arraydaysbeforeend as $daysbeforeend) { // Loop on each delay
3092  dol_syslog(__METHOD__.' - Process delta = '.$daysbeforeend, LOG_DEBUG);
3093 
3094  if (!is_numeric($daysbeforeend)) {
3095  $blockingerrormsg = "Value for delta is not a numeric value";
3096  $nbko++;
3097  break;
3098  }
3099 
3100  $tmp = dol_getdate($now);
3101  $datetosearchfor = dol_time_plus_duree(dol_mktime(0, 0, 0, $tmp['mon'], $tmp['mday'], $tmp['year'], 'tzserver'), $daysbeforeend, 'd');
3102 
3103  $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'adherent';
3104  $sql .= " WHERE entity = ".((int) $conf->entity); // Do not use getEntity('adherent').")" here, we want the batch to be on its entity only;
3105  $sql .= " AND datefin = '".$this->db->idate($datetosearchfor)."'";
3106  //$sql .= " LIMIT 10000";
3107 
3108  $resql = $this->db->query($sql);
3109  if ($resql) {
3110  $num_rows = $this->db->num_rows($resql);
3111 
3112  include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
3113  $adherent = new Adherent($this->db);
3114  $formmail = new FormMail($this->db);
3115 
3116  $i = 0;
3117  while ($i < $num_rows) {
3118  $obj = $this->db->fetch_object($resql);
3119 
3120  $adherent->fetch($obj->rowid, '', '', '', true, true);
3121 
3122  if (empty($adherent->email)) {
3123  $nbko++;
3124  $listofmembersko[$adherent->id] = $adherent->id;
3125  } else {
3126  $adherent->fetch_thirdparty();
3127 
3128  // Language code to use ($languagecodeformember) is default language of thirdparty, if no thirdparty, the language found from country of member then country of thirdparty, and if still not found we use the language of company.
3129  $languagefromcountrycode = getLanguageCodeFromCountryCode($adherent->country_code ? $adherent->country_code : $adherent->thirdparty->country_code);
3130  $languagecodeformember = (empty($adherent->thirdparty->default_lang) ? ($languagefromcountrycode ? $languagefromcountrycode : $mysoc->default_lang) : $adherent->thirdparty->default_lang);
3131 
3132  // Send reminder email
3133  $outputlangs = new Translate('', $conf);
3134  $outputlangs->setDefaultLang($languagecodeformember);
3135  $outputlangs->loadLangs(array("main", "members"));
3136  dol_syslog("sendReminderForExpiredSubscription Language for member id ".$adherent->id." set to ".$outputlangs->defaultlang." mysoc->default_lang=".$mysoc->default_lang);
3137 
3138  $arraydefaultmessage = null;
3139  $labeltouse = getDolGlobalString('ADHERENT_EMAIL_TEMPLATE_REMIND_EXPIRATION');
3140 
3141  if (!empty($labeltouse)) {
3142  $arraydefaultmessage = $formmail->getEMailTemplate($this->db, 'member', $user, $outputlangs, 0, 1, $labeltouse);
3143  }
3144 
3145  if (!empty($labeltouse) && is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) {
3146  $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $adherent);
3147  //if (is_array($adherent->thirdparty)) $substitutionarraycomp = ...
3148  complete_substitutions_array($substitutionarray, $outputlangs, $adherent);
3149 
3150  $subject = make_substitutions($arraydefaultmessage->topic, $substitutionarray, $outputlangs);
3151  $msg = make_substitutions($arraydefaultmessage->content, $substitutionarray, $outputlangs);
3152  $from = getDolGlobalString('ADHERENT_MAIL_FROM');
3153  $to = $adherent->email;
3154  $cc = getDolGlobalString('ADHERENT_CC_MAIL_FROM');
3155 
3156  $trackid = 'mem'.$adherent->id;
3157  $moreinheader = 'X-Dolibarr-Info: sendReminderForExpiredSubscription'."\r\n";
3158 
3159  include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
3160  $cmail = new CMailFile($subject, $to, $from, $msg, array(), array(), array(), $cc, '', 0, 1, '', '', $trackid, $moreinheader);
3161  $result = $cmail->sendfile();
3162  if (!$result) {
3163  $error++;
3164  $this->error .= $cmail->error.' ';
3165  if (!is_null($cmail->errors)) {
3166  $this->errors += $cmail->errors;
3167  }
3168  $nbko++;
3169  $listofmembersko[$adherent->id] = $adherent->id;
3170  } else {
3171  $nbok++;
3172  $listofmembersok[$adherent->id] = $adherent->id;
3173 
3174  $message = $msg;
3175  $sendto = $to;
3176  $sendtocc = '';
3177  $sendtobcc = '';
3178  $actioncode = 'EMAIL';
3179  $extraparams = '';
3180 
3181  $actionmsg = '';
3182  $actionmsg2 = $langs->transnoentities('MailSentBy').' '.CMailFile::getValidAddress($from, 4, 0, 1).' '.$langs->transnoentities('To').' '.CMailFile::getValidAddress($sendto, 4, 0, 1);
3183  if ($message) {
3184  $actionmsg = $langs->transnoentities('MailFrom').': '.dol_escape_htmltag($from);
3185  $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTo').': '.dol_escape_htmltag($sendto));
3186  if ($sendtocc) {
3187  $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('Bcc').": ".dol_escape_htmltag($sendtocc));
3188  }
3189  $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTopic').": ".$subject);
3190  $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('TextUsedInTheMessageBody').":");
3191  $actionmsg = dol_concatdesc($actionmsg, $message);
3192  }
3193 
3194  require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
3195 
3196  // Insert record of emails sent
3197  $actioncomm = new ActionComm($this->db);
3198 
3199  $actioncomm->type_code = 'AC_OTH_AUTO'; // Type of event ('AC_OTH', 'AC_OTH_AUTO', 'AC_XXX'...)
3200  $actioncomm->code = 'AC_'.$actioncode;
3201  $actioncomm->label = $actionmsg2;
3202  $actioncomm->note_private = $actionmsg;
3203  $actioncomm->fk_project = 0;
3204  $actioncomm->datep = $now;
3205  $actioncomm->datef = $now;
3206  $actioncomm->percentage = -1; // Not applicable
3207  $actioncomm->socid = $adherent->thirdparty->id;
3208  $actioncomm->contact_id = 0;
3209  $actioncomm->authorid = $user->id; // User saving action
3210  $actioncomm->userownerid = $user->id; // Owner of action
3211  // Fields when action is en email (content should be added into note)
3212  $actioncomm->email_msgid = $cmail->msgid;
3213  $actioncomm->email_from = $from;
3214  $actioncomm->email_sender = '';
3215  $actioncomm->email_to = $to;
3216  $actioncomm->email_tocc = $sendtocc;
3217  $actioncomm->email_tobcc = $sendtobcc;
3218  $actioncomm->email_subject = $subject;
3219  $actioncomm->errors_to = '';
3220 
3221  $actioncomm->fk_element = $adherent->id;
3222  $actioncomm->elementtype = $adherent->element;
3223 
3224  $actioncomm->extraparams = $extraparams;
3225 
3226  $actioncomm->create($user);
3227  }
3228  } else {
3229  //$blockingerrormsg = "Can't find email template with label=".$labeltouse.", to use for the reminding email";
3230 
3231  $error++;
3232  $this->error .= "Can't find email template with label=".$labeltouse.", to use for the reminding email ";
3233 
3234  $nbko++;
3235  $listofmembersko[$adherent->id] = $adherent->id;
3236 
3237  break;
3238  }
3239  }
3240 
3241  $i++;
3242  }
3243  } else {
3244  $this->error = $this->db->lasterror();
3245  return 1;
3246  }
3247  }
3248 
3249  if ($blockingerrormsg) {
3250  $this->error = $blockingerrormsg;
3251  return 1;
3252  } else {
3253  $this->output = 'Found '.($nbok + $nbko).' members to send reminder to.';
3254  $this->output .= ' Send email successfuly to '.$nbok.' members';
3255  if (is_array($listofmembersok)) {
3256  $listofids = '';
3257  $i = 0;
3258  foreach ($listofmembersok as $idmember) {
3259  if ($i > 100) {
3260  $listofids .= ', ...';
3261  break;
3262  }
3263  if (empty($listofids)) {
3264  $listofids .= ' [';
3265  } else {
3266  $listofids .= ', ';
3267  }
3268  $listofids .= $idmember;
3269  $i++;
3270  }
3271  if ($listofids) {
3272  $listofids .= ']';
3273  }
3274 
3275  $this->output .= ($listofids ? ' ids='.$listofids : '');
3276  }
3277  if ($nbko) {
3278  $this->output .= ' - Canceled for '.$nbko.' member (no email or email sending error)';
3279  if (is_array($listofmembersko)) {
3280  $listofids = '';
3281  $i = 0;
3282  foreach ($listofmembersko as $idmember) {
3283  if ($i > 100) {
3284  $listofids .= ', ...';
3285  break;
3286  }
3287  if (empty($listofids)) {
3288  $listofids .= ' [';
3289  } else {
3290  $listofids .= ', ';
3291  }
3292  $listofids .= $idmember;
3293  $i++;
3294  }
3295  if ($listofids) {
3296  $listofids .= ']';
3297  }
3298  $this->output .= ($listofids ? ' ids='.$listofids : '');
3299  }
3300  }
3301  }
3302 
3303  return $nbko;
3304  }
3305 
3313  public function getKanbanView($option = '', $arraydata = null)
3314  {
3315  $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
3316 
3317  $return = '<div class="box-flex-item box-flex-grow-zero">';
3318  $return .= '<div class="info-box info-box-sm">';
3319  $return .= '<span class="info-box-icon bg-infobox-action">';
3320  if (property_exists($this, 'photo') || !empty($this->photo)) {
3321  $return.= Form::showphoto('memberphoto', $this, 0, 60, 0, 'photokanban photoref photowithmargin photologintooltip', 'small', 0, 1);
3322  } else {
3323  $return .= img_picto('', 'user');
3324  }
3325  $return .= '</span>';
3326  $return .= '<div class="info-box-content">';
3327  $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).'</span>';
3328  $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
3329  if (property_exists($this, 'type')) {
3330  $return .= '<br><span class="info-box-label opacitymedium">'.$this->type.'</span>';
3331  }
3332  if (method_exists($this, 'getmorphylib')) {
3333  $return .= '<br><span class="info-box-label">'.$this->getmorphylib('', 2).'</span>';
3334  }
3335  if (method_exists($this, 'getLibStatut')) {
3336  $return .= '<br><div class="info-box-status margintoponly">'.$this->getLibStatut(3).'</div>';
3337  }
3338  $return .= '</div>';
3339  $return .= '</div>';
3340  $return .= '</div>';
3341  return $return;
3342  }
3343 }
$object ref
Definition: info.php:78
Class to manage bank accounts.
Class to manage agenda events (actions)
Class to manage members of a foundation.
setThirdPartyId($thirdpartyid)
Set link to a third party.
hasDelay()
Return if a member is late (subscription late) or not.
exclude($user)
Functiun to exlude (set adherent.status to -2) a member TODO A private note should be added to know w...
add_to_abo()
Function to add member into external tools mailing-list, spip, etc.
sendReminderForExpiredSubscription($daysbeforeendlist='10')
Send reminders by emails before subscription end CAN BE A CRON TASK.
_load_ldap_dn($info, $mode=0)
Retourne chaine DN complete dans l'annuaire LDAP pour l'objet.
update($user, $notrigger=0, $nosyncuser=0, $nosyncuserpass=0, $nosyncthirdparty=0, $action='update')
Update a member in database (standard information and password)
setCategories($categories)
Sets object to supplied categories.
getTooltipContentArray($params)
getTooltipContentArray
getNbOfEMailings()
Return number of mass Emailing received by this member with its email.
update_end_date($user)
Update denormalized last subscription date.
static replaceThirdparty($db, $origin_id, $dest_id)
Function used to replace a thirdparty id with another one.
makeSubstitution($text)
Make substitution of tags into text with value of current object.
const STATUS_EXCLUDED
Excluded.
LibStatut($status, $need_subscription, $date_end_subscription, $mode=0)
Renvoi le libelle d'un statut donne.
fetch_name($firstname, $lastname)
Method to load member from its name.
initAsSpecimen()
Initialise an instance with random values.
del_to_abo()
Function to delete a member from external tools like mailing-list, spip, etc.
resiliate($user)
Fonction qui resilie un adherent.
getCivilityLabel()
Return civility label of a member.
getmorphylib($morphy='', $addbadge=0)
Return translated label by the nature of a adherent (physical or moral)
sendEmail($text, $subject, $filename_list=array(), $mimetype_list=array(), $mimefilename_list=array(), $addr_cc="", $addr_bcc="", $deliveryreceipt=0, $msgishtml=-1, $errors_to='', $moreinheader='')
Function sending an email to the current member with the text supplied in parameter.
fetchPartnerships($mode)
Function to get partnerships array.
load_board($user, $mode)
Load indicators for dashboard (this->nbtodo and this->nbtodolate)
setPassword($user, $password='', $isencrypted=0, $notrigger=0, $nosyncuser=0)
Change password of a user.
getKanbanView($option='', $arraydata=null)
Return clicable link of object (with eventually picto)
const STATUS_DRAFT
Draft status.
const STATUS_RESILIATED
Resiliated.
fetch_login($login)
Method to load member from its login.
create($user, $notrigger=0)
Create a member into database.
_load_ldap_info()
Initialise tableau info (tableau des attributs LDAP)
getLibStatut($mode=0)
Retourne le libelle du statut d'un adherent (brouillon, valide, resilie, exclu)
info($id)
Load type info information in the member object.
__construct($db)
Constructor.
subscription($date, $amount, $accountid=0, $operation='', $label='', $num_chq='', $emetteur_nom='', $emetteur_banque='', $datesubend=0, $fk_type=null)
Insert subscription into database and eventually add links to banks, mailman, etc....
send_an_email($text, $subject, $filename_list=array(), $mimetype_list=array(), $mimefilename_list=array(), $addr_cc="", $addr_bcc="", $deliveryreceipt=0, $msgishtml=-1, $errors_to='', $moreinheader='')
Function sending an email to the current member with the text supplied in parameter.
getNomUrl($withpictoimg=0, $maxlen=0, $option='card', $mode='', $morecss='', $save_lastsearch_value=-1, $notooltip=0, $addlinktonotes=0)
Return clicable name (with picto eventually)
generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
Create a document onto disk according to template module.
subscriptionComplementaryActions($subscriptionid, $option, $accountid, $datesubscription, $paymentdate, $operation, $label, $amount, $num_chq, $emetteur_nom='', $emetteur_banque='', $autocreatethirdparty=0, $ext_payment_id='', $ext_payment_site='')
Do complementary actions after subscription recording.
setUserId($userid)
Set link to a user.
load_state_board()
Charge indicateurs this->nb de tableau de bord.
fetch($rowid, $ref='', $fk_soc='', $ref_ext='', $fetch_optionals=true, $fetch_subscriptions=true)
Load member from database.
const STATUS_VALIDATED
Validated status.
fetch_subscriptions()
Function to get member subscriptions data: subscriptions, first_subscription_date,...
validate($user)
Function that validate a member.
Class to send emails (with attachments or not) Usage: $mailfile = new CMailFile($subject,...
static getValidAddress($address, $format, $encode=0, $maxnumberofemail=0)
Return a formatted address string for SMTP protocol.
Parent class of all other business classes (invoices, contracts, proposals, orders,...
fetch_optionals($rowid=null, $optionsArray=null)
Function to get extra fields of an object into $this->array_options This method is in most cases call...
commonGenerateDocument($modelspath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams=null)
Common function for all objects extending CommonObject for generating documents.
setErrorsFromObject($object)
setErrorsFromObject
deleteExtraFields()
Delete all extra fields values for the current object.
static commonReplaceThirdparty(DoliDB $dbs, $origin_id, $dest_id, array $tables, $ignoreerrors=0)
Function used to replace a thirdparty id with another one.
insertExtraFields($trigger='', $userused=null)
Add/Update all extra fields values for the current object.
call_trigger($triggerName, $user)
Call trigger based on this instance.
Class to manage invoices.
const TYPE_STANDARD
Standard invoice.
Class to manage generation of HTML components Only common components must be here.
static showphoto($modulepart, $object, $width=100, $height=0, $caneditfield=0, $cssclass='photowithmargin', $imagesize='', $addlinktofullsize=1, $cache=0, $forcecapture='', $noexternsourceoverwrite=0)
Classe permettant la generation du formulaire html d'envoi de mail unitaire Usage: $formail = new For...
Class to manage mailman and spip.
Class to manage payments of customer invoices.
Class to manage payment terms records in dictionary.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage subscriptions of foundation members.
Class to manage translations.
Class to manage Dolibarr users.
Definition: user.class.php:48
trait CommonPeople
Superclass for thirdparties, contacts, members or users.
getFullName($langs, $option=0, $nameorder=-1, $maxlen=0)
Return full name (civility+' '+name+' '+lastname)
setUpperOrLowerCase()
Set to upper or ucwords/lower if needed.
if(isModEnabled('facture') && $user->hasRight('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') && $user->hasRight('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)) $sql
Social contributions to pay.
Definition: index.php:746
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition: date.lib.php:122
clean_url($url, $http=1)
Clean an url string.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
getLanguageCodeFromCountryCode($countrycode)
Return default language from country code.
yn($yesno, $case=1, $color=0)
Return yes or no in current language.
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
dol_format_address($object, $withcountry=0, $sep="\n", $outputlangs='', $mode=0, $extralangcode='')
Return a formated address (part address/zip/town/state) according to country rules.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='')
Return an id or code from a code or id.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
dolGetFirstLetters($s, $nbofchar=1)
Return first letters of a strings.
dol_strtoupper($string, $encoding="UTF-8")
Convert a string to upper.
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
make_substitutions($text, $substitutionarray, $outputlangs=null, $converttextinhtmlifnecessary=0)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
getArrayOfSocialNetworks()
Get array of social network dictionary.
dol_textishtml($msg, $option=0)
Return if a text is a html content.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
getCommonSubstitutionArray($outputlangs, $onlykey=0, $exclude=null, $object=null, $include=null)
Return array of possible common substitutions.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that return vat rate of a product line (according to seller, buyer and product vat rate) VAT...
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:120
getRandomPassword($generic=false, $replaceambiguouschars=null, $length=32)
Return a generated password using default module.
dolGetLdapPasswordHash($password, $type='md5')
Returns a specific ldap hash of a password.
dol_hash($chain, $type='0')
Returns a hash (non reversible encryption) of a string.