dolibarr 25.0.0-alpha
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 <alexandre@inovea-conseil.com>
9 * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
10 * Copyright (C) 2015-2026 Frédéric France <frederic.france@free.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 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 3 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program. If not, see <https://www.gnu.org/licenses/>.
32 */
33
39require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
40require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
41require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
42require_once DOL_DOCUMENT_ROOT.'/core/class/commonpeople.class.php';
43
44
49{
50 use CommonPeople;
51
55 public $element = 'member';
56
60 public $table_element = 'adherent';
61
65 public $picto = 'member';
66
70 public $mesgs;
71
75 public $login;
76
80 public $pass;
81
85 public $pass_indatabase;
86
90 public $pass_indatabase_crypted;
91
95 public $fullname;
96
101 public $civility_id;
102
106 public $civility_code;
107
111 public $civility;
112
118 public $societe;
119
123 public $company;
124
130 public $fk_soc;
131
135 public $socid;
136
140 public $socialnetworks;
141
145 public $phone;
146
150 public $phone_perso;
151
155 public $phone_pro;
156
160 public $phone_mobile;
161
165 public $fax;
166
170 public $poste;
171
175 public $morphy;
176
180 public $public;
181
186 public $default_lang;
187
191 public $photo;
192
198 public $datec;
199
205 public $datem;
206
210 public $datevalid;
211
215 public $gender;
216
220 public $birth;
221
225 public $typeid;
226
230 public $type;
231
235 public $need_subscription;
236
240 public $user_id;
241
245 public $user_login;
246
250 public $datefin;
251
252
253 // Fields loaded by fetch_subscriptions() from member table
254
258 public $first_subscription_date;
259
263 public $first_subscription_date_start;
264
268 public $first_subscription_date_end;
269
273 public $first_subscription_amount;
274
278 public $last_subscription_date;
279
283 public $last_subscription_date_start;
284
288 public $last_subscription_date_end;
289
293 public $last_subscription_amount;
294
298 public $subscriptions = array();
299
303 public $ip;
304
305 // Fields loaded by fetchPartnerships() from partnership table
306
310 public $partnerships = array();
311
315 public $invoice;
316
358 public $fields = array(
359 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 10),
360 'ref' => array('type' => 'varchar(30)', 'label' => 'Ref', 'default' => '1', 'enabled' => 1, 'visible' => 1, 'notnull' => 1, 'position' => 12, 'index' => 1),
361 'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => '1', 'enabled' => 1, 'visible' => 3, 'notnull' => 1, 'position' => 15, 'index' => 1),
362 'ref_ext' => array('type' => 'varchar(128)', 'label' => 'RefExt', 'enabled' => 1, 'visible' => 0, 'position' => 20),
363 'civility' => array('type' => 'varchar(6)', 'label' => 'Civility', 'enabled' => 1, 'visible' => -1, 'position' => 25),
364 'lastname' => array('type' => 'varchar(50)', 'label' => 'Lastname', 'enabled' => 1, 'visible' => 1, 'position' => 30, 'showoncombobox' => 1),
365 'firstname' => array('type' => 'varchar(50)', 'label' => 'Firstname', 'enabled' => 1, 'visible' => 1, 'position' => 35, 'showoncombobox' => 1),
366 'login' => array('type' => 'varchar(50)', 'label' => 'Login', 'enabled' => 1, 'visible' => -1, 'position' => 40),
367 'pass' => array('type' => 'varchar(50)', 'label' => 'Pass', 'enabled' => 1, 'visible' => 3, 'position' => 45),
368 'pass_crypted' => array('type' => 'varchar(128)', 'label' => 'Pass crypted', 'enabled' => 1, 'visible' => 3, 'position' => 50),
369 'morphy' => array('type' => 'varchar(3)', 'label' => 'MemberNature', 'enabled' => 1, 'visible' => 1, 'notnull' => 1, 'position' => 55),
370 'fk_adherent_type' => array('type' => 'integer', 'label' => 'MemberType', 'enabled' => 1, 'visible' => 1, 'notnull' => 1, 'position' => 60),
371 'societe' => array('type' => 'varchar(128)', 'label' => 'Societe', 'enabled' => 1, 'visible' => 1, 'position' => 65, 'showoncombobox' => 2),
372 'fk_soc' => array('type' => 'integer:Societe:societe/class/societe.class.php', 'label' => 'LinkedToDolibarrThirdParty', 'enabled' => 1, 'visible' => 1, 'position' => 70),
373 'address' => array('type' => 'text', 'label' => 'Address', 'enabled' => 1, 'visible' => -1, 'position' => 75),
374 'zip' => array('type' => 'varchar(10)', 'label' => 'Zip', 'enabled' => 1, 'visible' => -1, 'position' => 80),
375 'town' => array('type' => 'varchar(50)', 'label' => 'Town', 'enabled' => 1, 'visible' => -1, 'position' => 85),
376 'state_id' => array('type' => 'integer', 'label' => 'State', 'enabled' => 1, 'visible' => -1, 'position' => 90),
377 'country' => array('type' => 'integer:Ccountry:core/class/ccountry.class.php', 'label' => 'Country', 'enabled' => 1, 'visible' => 1, 'position' => 95),
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 'email' => array('type' => 'varchar(255)', 'label' => 'Email', 'enabled' => 1, 'visible' => 1, 'position' => 126),
382 'url' => array('type' => 'varchar(255)', 'label' => 'Url', 'enabled' => 1, 'visible' => -1, 'position' => 127),
383 'socialnetworks' => array('type' => 'text', 'label' => 'Socialnetworks', 'enabled' => 1, 'visible' => 3, 'position' => 128),
384 'birth' => array('type' => 'date', 'label' => 'DateOfBirth', 'enabled' => 1, 'visible' => -1, 'position' => 130),
385 'gender' => array('type' => 'varchar(10)', 'label' => 'Gender', 'enabled' => 1, 'visible' => -1, 'position' => 132),
386 'photo' => array('type' => 'varchar(255)', 'label' => 'Photo', 'enabled' => 1, 'visible' => -1, 'position' => 135),
387 'public' => array('type' => 'smallint(6)', 'label' => 'Public', 'enabled' => 1, 'visible' => 3, 'notnull' => 1, 'position' => 145),
388 'datefin' => array('type' => 'datetime', 'label' => 'DateEnd', 'enabled' => 1, 'visible' => 1, 'position' => 150),
389 'default_lang' => array('type' => 'varchar(6)', 'label' => 'Default lang', 'enabled' => 1, 'visible' => -1, 'position' => 153),
390 'note_public' => array('type' => 'text', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 155),
391 'note_private' => array('type' => 'text', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 160),
392 'datevalid' => array('type' => 'datetime', 'label' => 'DateValidation', 'enabled' => 1, 'visible' => -1, 'position' => 165),
393 'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -1, 'position' => 170),
394 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 175),
395 'fk_user_author' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserCreation', 'enabled' => 1, 'visible' => 3, 'position' => 180),
396 'fk_user_mod' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserModification', 'enabled' => 1, 'visible' => 3, 'position' => 185),
397 'fk_user_valid' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserValidation', 'enabled' => 1, 'visible' => 3, 'position' => 190),
398 'canvas' => array('type' => 'varchar(32)', 'label' => 'Canvas', 'enabled' => 1, 'visible' => 0, 'position' => 195),
399 'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'visible' => 0, 'position' => 800),
400 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -2, 'position' => 805),
401 'statut' => array('type' => 'smallint(6)', 'label' => 'Statut', 'enabled' => 1, 'visible' => 1, 'notnull' => 1, 'position' => 1000, 'arrayofkeyval' => array(-1 => 'Draft', 1 => 'Validated', 0 => 'MemberStatusResiliatedShort', -2 => 'MemberStatusExcludedShort'))
402 );
403
407 const STATUS_DRAFT = -1;
419 const STATUS_EXCLUDED = -2;
420
421
427 public function __construct($db)
428 {
429 $this->db = $db;
430 $this->statut = self::STATUS_DRAFT;
431 $this->status = self::STATUS_DRAFT;
432 // l'adherent n'est pas public par default
433 $this->public = 0;
434 $this->ismultientitymanaged = 1;
435 $this->isextrafieldmanaged = 1;
436 // Optional fields are empty
437 $this->array_options = array();
438
439 $this->fields['ref_ext']['visible'] = getDolGlobalInt('MAIN_LIST_SHOW_REF_EXT');
440 }
441
442
443 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
462 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 = '')
463 {
464 // phpcs:enable
465 dol_syslog('Warning using deprecated Adherent::send_an_email', LOG_WARNING);
466
467 return $this->sendEmail($text, $subject, $filename_list, $mimetype_list, $mimefilename_list, $addr_cc, $addr_bcc, $deliveryreceipt, $msgishtml, $errors_to, $moreinheader);
468 }
469
487 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 = '')
488 {
489 global $conf, $langs;
490
491 // Detect if message is HTML
492 if ($msgishtml == -1) {
493 $msgishtml = 0;
494 if (dol_textishtml($text, 0)) {
495 $msgishtml = 1;
496 }
497 }
498
499 dol_syslog('sendEmail msgishtml='.$msgishtml);
500
501 $texttosend = $this->makeSubstitution($text);
502 $subjecttosend = $this->makeSubstitution($subject);
503 if ($msgishtml) {
504 $texttosend = dol_htmlentitiesbr($texttosend);
505 }
506
507 // Send mail confirmation
508 $email_from = getDolGlobalString('ADHERENT_MAIL_FROM', $conf->email_from);
509
510 $trackid = 'mem'.$this->id;
511
512 // Send email (substitutionarray must be done just before this)
513 include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
514 $mailfile = new CMailFile($subjecttosend, (string) $this->email, $email_from, $texttosend, $filename_list, $mimetype_list, $mimefilename_list, $addr_cc, $addr_bcc, $deliveryreceipt, $msgishtml, '', '', $trackid, $moreinheader);
515 if ($mailfile->sendfile()) {
516 return 1;
517 } else {
518 $this->error = $langs->trans("ErrorFailedToSendMail", $email_from, (string) $this->email).'. '.$mailfile->error;
519 return -1;
520 }
521 }
522
523
530 public function makeSubstitution($text)
531 {
532 global $langs;
533
534 $birthday = dol_print_date($this->birth, 'day');
535 $photo = isset($this->photo) ? $this->photo : '';
536 $login = isset($this->login) ? $this->login : '';
537 $type = isset($this->type) ? $this->type : '';
538 $pass = isset($this->pass) ? $this->pass : '';
539
540 $msgishtml = 0;
541 if (dol_textishtml($text, 1)) {
542 $msgishtml = 1;
543 }
544
545 $infos = '';
546 if ($this->civility_id) {
547 $infos .= $langs->transnoentities("UserTitle").": ".$this->getCivilityLabel()."\n";
548 }
549 $infos .= $langs->transnoentities("Id").": ".$this->id."\n";
550 $infos .= $langs->transnoentities("Ref").": ".$this->ref."\n";
551 $infos .= $langs->transnoentities("Lastname").": ".$this->lastname."\n";
552 $infos .= $langs->transnoentities("Firstname").": ".$this->firstname."\n";
553 $infos .= $langs->transnoentities("Company").": ".$this->company."\n";
554 $infos .= $langs->transnoentities("Address").": ".$this->address."\n";
555 $infos .= $langs->transnoentities("Zip").": ".$this->zip."\n";
556 $infos .= $langs->transnoentities("Town").": ".$this->town."\n";
557 $infos .= $langs->transnoentities("Country").": ".$this->country."\n";
558 $infos .= $langs->transnoentities("EMail").": ".$this->email."\n";
559 $infos .= $langs->transnoentities("PhonePro").": ".$this->phone."\n";
560 $infos .= $langs->transnoentities("PhonePerso").": ".$this->phone_perso."\n";
561 $infos .= $langs->transnoentities("PhoneMobile").": ".$this->phone_mobile."\n";
562 if (!getDolGlobalString('ADHERENT_LOGIN_NOT_REQUIRED')) {
563 $infos .= $langs->transnoentities("Login").": ".$login."\n";
564 $infos .= $langs->transnoentities("Password").": ".$pass."\n";
565 }
566 $infos .= $langs->transnoentities("Birthday").": ".$birthday."\n";
567 $infos .= $langs->transnoentities("Photo").": ".$photo."\n";
568 $infos .= $langs->transnoentities("Public").": ".yn($this->public);
569
570 // Substitutions
571 $substitutionarray = array(
572 '__ID__' => $this->id,
573 '__REF__' => $this->ref,
574 '__MEMBER_ID__' => $this->id,
575 '__CIVILITY__' => $this->getCivilityLabel(),
576 '__FIRSTNAME__' => $msgishtml ? dol_htmlentitiesbr($this->firstname) : ($this->firstname ? $this->firstname : ''),
577 '__LASTNAME__' => $msgishtml ? dol_htmlentitiesbr($this->lastname) : ($this->lastname ? $this->lastname : ''),
578 '__FULLNAME__' => $msgishtml ? dol_htmlentitiesbr($this->getFullName($langs)) : $this->getFullName($langs),
579 '__COMPANY__' => $msgishtml ? dol_htmlentitiesbr((string) $this->company) : ($this->company ? $this->company : ''),
580 '__ADDRESS__' => $msgishtml ? dol_htmlentitiesbr((string) $this->address) : ($this->address ? $this->address : ''),
581 '__ZIP__' => $msgishtml ? dol_htmlentitiesbr((string) $this->zip) : ($this->zip ? $this->zip : ''),
582 '__TOWN__' => $msgishtml ? dol_htmlentitiesbr((string) $this->town) : ($this->town ? $this->town : ''),
583 '__COUNTRY__' => $msgishtml ? dol_htmlentitiesbr($this->country) : ($this->country ? $this->country : ''),
584 '__EMAIL__' => $msgishtml ? dol_htmlentitiesbr((string) $this->email) : ($this->email ? $this->email : ''),
585 '__BIRTH__' => $msgishtml ? dol_htmlentitiesbr($birthday) : ($birthday ? $birthday : ''),
586 '__PHOTO__' => $msgishtml ? dol_htmlentitiesbr($photo) : $photo,
587 '__LOGIN__' => $msgishtml ? dol_htmlentitiesbr($login) : $login,
588 '__PASSWORD__' => $msgishtml ? dol_htmlentitiesbr($pass) : $pass,
589 '__PHONE__' => $msgishtml ? dol_htmlentitiesbr($this->phone) : ($this->phone ? $this->phone : ''),
590 '__PHONEPRO__' => $msgishtml ? dol_htmlentitiesbr($this->phone_perso) : ($this->phone_perso ? $this->phone_perso : ''),
591 '__PHONEMOBILE__' => $msgishtml ? dol_htmlentitiesbr($this->phone_mobile) : ($this->phone_mobile ? $this->phone_mobile : ''),
592 '__TYPE__' => $msgishtml ? dol_htmlentitiesbr($type) : $type,
593 );
594
595 complete_substitutions_array($substitutionarray, $langs, $this);
596
597 return make_substitutions($text, $substitutionarray, $langs);
598 }
599
600
608 public function getmorphylib($morphy = '', $addbadge = 0)
609 {
610 global $langs;
611 $s = '';
612
613 // Clean var
614 if (!$morphy) {
615 $morphy = $this->morphy;
616 }
617
618 if ($addbadge) {
619 $labeltoshowm = $langs->trans("Moral");
620 $labeltoshowp = $langs->trans("Physical");
621 if ($morphy == 'phy') {
622 $labeltoshow = $labeltoshowp;
623 if ($addbadge == 2) {
624 $labeltoshow = dol_strtoupper(dolGetFirstLetters($labeltoshowp));
625 if ($labeltoshow == dol_strtoupper(dolGetFirstLetters($labeltoshowm))) {
626 $labeltoshow = dol_strtoupper(dolGetFirstLetters($labeltoshowp, 2));
627 }
628 }
629 $s .= '<span class="member-individual-back paddingleftimp paddingrightimp" title="'.$langs->trans("Physical").'">'.$labeltoshow.'</span>';
630 }
631 if ($morphy == 'mor') {
632 $labeltoshow = $labeltoshowm;
633 if ($addbadge == 2) {
634 $labeltoshow = dol_strtoupper(dolGetFirstLetters($labeltoshowm));
635 if ($labeltoshow == dol_strtoupper(dolGetFirstLetters($labeltoshowp))) {
636 $labeltoshow = dol_strtoupper(dolGetFirstLetters($labeltoshowm, 2));
637 }
638 }
639 $s .= '<span class="member-company-back paddingleftimp paddingrightimp" title="'.$langs->trans("Moral").'">'.$labeltoshow.'</span>';
640 }
641 } else {
642 if ($morphy == 'phy') {
643 $s = $langs->trans("Physical");
644 } elseif ($morphy == 'mor') {
645 $s = $langs->trans("Moral");
646 }
647 }
648
649 return $s;
650 }
651
659 public function create($user, $notrigger = 0)
660 {
661 global $langs, $mysoc;
662
663 $error = 0;
664
665 $now = dol_now();
666
667 // Clean parameters
668 if (isset($this->import_key)) {
669 $this->import_key = trim($this->import_key);
670 }
671
672 // Check parameters
673 if (getDolGlobalString('ADHERENT_MAIL_REQUIRED') && !isValidEmail((string) $this->email)) {
674 $langs->load("errors");
675 $this->error = $langs->trans("ErrorBadEMail", (string) $this->email);
676 return -1;
677 }
678 if (!$this->datec) {
679 $this->datec = $now;
680 }
681 if (!getDolGlobalString('ADHERENT_LOGIN_NOT_REQUIRED')) {
682 if (empty($this->login)) {
683 $this->error = $langs->trans("ErrorWrongValueForParameterX", "Login");
684 return -1;
685 }
686 }
687
688 // setEntity will set entity with the right value if empty or change it for the right value if multicompany module is active
689 $this->entity = setEntity($this);
690
691 $this->db->begin();
692
693 // Insert member
694 $sql = "INSERT INTO ".MAIN_DB_PREFIX."adherent";
695 $sql .= " (ref, datec, login, fk_user_author, fk_user_mod, fk_user_valid, morphy, fk_adherent_type, entity, import_key, ip)";
696 $sql .= " VALUES (";
697 $sql .= " '(PROV)'";
698 $sql .= ", '".$this->db->idate($this->datec)."'";
699 $sql .= ", ".($this->login ? "'".$this->db->escape($this->login)."'" : "null");
700 $sql .= ", ".($user->id > 0 ? ((int) $user->id) : "null"); // Can be null because member can be created by a guest or a script
701 $sql .= ", null, null, '".$this->db->escape($this->morphy)."'";
702 $sql .= ", ".((int) $this->typeid);
703 $sql .= ", ".((int) $this->entity);
704 $sql .= ", ".(!empty($this->import_key) ? "'".$this->db->escape($this->import_key)."'" : "null");
705 $sql .= ", ".(!empty($this->ip) ? "'".$this->db->escape($this->ip)."'" : "null");
706 $sql .= ")";
707
708 dol_syslog(get_class($this)."::create", LOG_DEBUG);
709 $result = $this->db->query($sql);
710 if ($result) {
711 $id = $this->db->last_insert_id(MAIN_DB_PREFIX."adherent");
712 if ($id > 0) {
713 $this->id = $id;
714
715 $modulenum = getDolGlobalString('MEMBER_CODEMEMBER_ADDON', 'mod_member_simple');
716
717 $modfile = dol_buildpath('core/modules/member/'.$modulenum.'.php', 0);
718 try {
719 require_once $modfile;
720 $modname = $modulenum;
721 $modCodeMember = new $modname();
722 '@phan-var-force ModeleNumRefMembers $modCodeMember';
724 $this->ref = $modCodeMember->getNextValue($mysoc, $this);
725 } catch (Exception $e) {
726 dol_syslog($e->getMessage(), LOG_ERR);
727 $error++;
728 }
729
730 // Update minor fields
731 $result = $this->update($user, 1, 1, 0, 0, 'add'); // nosync is 1 to avoid update data of user
732 if ($result < 0) {
733 $this->db->rollback();
734 return -1;
735 }
736
737 // Add link to user
738 if ($this->user_id) {
739 // Add link to user
740 $sql = "UPDATE ".MAIN_DB_PREFIX."user SET";
741 $sql .= " fk_member = ".((int) $this->id);
742 $sql .= " WHERE rowid = ".((int) $this->user_id);
743 dol_syslog(get_class($this)."::create", LOG_DEBUG);
744 $resql = $this->db->query($sql);
745 if (!$resql) {
746 $this->error = 'Failed to update user to make link with member';
747 $this->db->rollback();
748 return -4;
749 }
750 }
751
752 if (!$notrigger) {
753 // Call trigger
754 $result = $this->call_trigger('MEMBER_CREATE', $user);
755 if ($result < 0) {
756 $error++;
757 }
758 // End call triggers
759 }
760
761 if (count($this->errors)) {
762 dol_syslog(get_class($this)."::create ".implode(',', $this->errors), LOG_ERR);
763 $this->db->rollback();
764 return -3;
765 } else {
766 $this->db->commit();
767 return $this->id;
768 }
769 } else {
770 $this->error = 'Failed to get last insert id';
771 dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
772 $this->db->rollback();
773 return -2;
774 }
775 } else {
776 $this->error = $this->db->error();
777 $this->db->rollback();
778 return -1;
779 }
780 }
781
782
794 public function update($user, $notrigger = 0, $nosyncuser = 0, $nosyncuserpass = 0, $nosyncthirdparty = 0, $action = 'update')
795 {
796 global $langs, $hookmanager;
797
798 require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
799
800 if (empty($this->country_id) && !empty($this->country_code)) {
801 $country_id = getCountry($this->country_code, '3');
802 $this->country_id = is_int($country_id) ? $country_id : 0;
803 }
804
805 $nbrowsaffected = 0;
806 $error = 0;
807
808 dol_syslog(get_class($this)."::update notrigger=".$notrigger.", nosyncuser=".$nosyncuser.", nosyncuserpass=".$nosyncuserpass." nosyncthirdparty=".$nosyncthirdparty.", email=".$this->email);
809
810 // Clean parameters
811 $this->lastname = trim($this->lastname) ? trim($this->lastname) : trim($this->lastname);
812 $this->firstname = trim($this->firstname) ? trim($this->firstname) : trim($this->firstname);
813 if (isset($this->gender)) {
814 $this->gender = trim($this->gender);
815 }
816 // $this->address = ($this->address ? $this->address : $this->address);
817 // $this->zip = ($this->zip ? $this->zip : $this->zip);
818 // $this->town = ($this->town ? $this->town : $this->town);
819 // $this->country_id = ($this->country_id > 0 ? $this->country_id : $this->country_id);
820 // $this->state_id = ($this->state_id > 0 ? $this->state_id : $this->state_id);
821 // $this->note_public = ($this->note_public ? $this->note_public : $this->note_public);
822 // $this->note_private = ($this->note_private ? $this->note_private : $this->note_private);
823 $this->url = $this->url ? clean_url($this->url, 0) : '';
824 $this->setUpperOrLowerCase();
825
826 // Check parameters
827 if (getDolGlobalString('ADHERENT_MAIL_REQUIRED') && !isValidEmail((string) $this->email)) {
828 $langs->load("errors");
829 $this->error = $langs->trans("ErrorBadEMail", (string) $this->email);
830 return -1;
831 }
832
833 $this->db->begin();
834
835 $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
836 $sql .= " ref = '".$this->db->escape($this->ref)."'";
837 $sql .= ", ref_ext = ".(empty($this->ref_ext) ? "null" : "'".$this->db->escape($this->ref_ext)."'");
838 $sql .= ", civility = ".($this->civility_id ? "'".$this->db->escape($this->civility_id)."'" : "null");
839 $sql .= ", firstname = ".($this->firstname ? "'".$this->db->escape($this->firstname)."'" : "null");
840 $sql .= ", lastname = ".($this->lastname ? "'".$this->db->escape($this->lastname)."'" : "null");
841 $sql .= ", gender = ".($this->gender != -1 ? "'".$this->db->escape($this->gender)."'" : "null"); // 'man' or 'woman'
842 $sql .= ", login = ".($this->login ? "'".$this->db->escape($this->login)."'" : "null");
843 $sql .= ", societe = ".($this->company ? "'".$this->db->escape($this->company)."'" : ($this->societe ? "'".$this->db->escape($this->societe)."'" : "null"));
844 if ($this->socid) {
845 $sql .= ", fk_soc = ".($this->socid > 0 ? (int) $this->socid : "null"); // Must be modified only when creating from a third-party
846 }
847 $sql .= ", address = ".($this->address ? "'".$this->db->escape($this->address)."'" : "null");
848 $sql .= ", zip = ".($this->zip ? "'".$this->db->escape($this->zip)."'" : "null");
849 $sql .= ", town = ".($this->town ? "'".$this->db->escape($this->town)."'" : "null");
850 $sql .= ", country = ".($this->country_id > 0 ? (int) $this->country_id : "null");
851 $sql .= ", state_id = ".($this->state_id > 0 ? (int) $this->state_id : "null");
852 $sql .= ", email = '".$this->db->escape((string) $this->email)."'";
853 $sql .= ", url = ".(!empty($this->url) ? "'".$this->db->escape($this->url)."'" : "null");
854 $sql .= ", socialnetworks = ".($this->socialnetworks ? "'".$this->db->escape(json_encode($this->socialnetworks))."'" : "null");
855 $sql .= ", phone = ".($this->phone ? "'".$this->db->escape($this->phone)."'" : "null");
856 $sql .= ", phone_perso = ".($this->phone_perso ? "'".$this->db->escape($this->phone_perso)."'" : "null");
857 $sql .= ", phone_mobile = ".($this->phone_mobile ? "'".$this->db->escape($this->phone_mobile)."'" : "null");
858 $sql .= ", note_private = ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "null");
859 $sql .= ", note_public = ".($this->note_public ? "'".$this->db->escape($this->note_public)."'" : "null");
860 $sql .= ", photo = ".($this->photo ? "'".$this->db->escape($this->photo)."'" : "null");
861 $sql .= ", public = ".(int) $this->public;
862 $sql .= ", statut = ".(int) $this->statut;
863 $sql .= ", default_lang = ".(!empty($this->default_lang) ? "'".$this->db->escape($this->default_lang)."'" : "null");
864 $sql .= ", fk_adherent_type = ".(int) $this->typeid;
865 $sql .= ", morphy = '".$this->db->escape($this->morphy)."'";
866 $sql .= ", birth = ".($this->birth ? "'".$this->db->idate($this->birth)."'" : "null");
867
868 if ($this->datefin) {
869 $sql .= ", datefin = '".$this->db->idate($this->datefin)."'"; // Must be modified only when deleting a subscription
870 }
871 if ($this->datevalid) {
872 $sql .= ", datevalid = '".$this->db->idate($this->datevalid)."'"; // Must be modified only when validating a member
873 }
874 $sql .= ", fk_user_mod = ".($user->id > 0 ? ((int) $user->id) : 'null'); // Can be null because member can be create by a guest
875 $sql .= " WHERE rowid = ".((int) $this->id);
876
877 // If we change the type of membership, we set also label of new type..
878 '@phan-var-force Adherent $oldcopy';
879 if (!empty($this->oldcopy) && $this->typeid != $this->oldcopy->typeid) {
880 $sql2 = "SELECT libelle as label";
881 $sql2 .= " FROM ".MAIN_DB_PREFIX."adherent_type";
882 $sql2 .= " WHERE rowid = ".((int) $this->typeid);
883 $resql2 = $this->db->query($sql2);
884 if ($resql2) {
885 while ($obj = $this->db->fetch_object($resql2)) {
886 $this->type = $obj->label;
887 }
888 }
889 }
890
891 dol_syslog(get_class($this)."::update update member", LOG_DEBUG);
892 $resql = $this->db->query($sql);
893 if ($resql) {
894 unset($this->country_code);
895 unset($this->country);
896 unset($this->state_code);
897 unset($this->state);
898
899 $nbrowsaffected += $this->db->affected_rows($resql);
900
901 $action = 'update';
902
903 // Actions on extra fields
904 $result = $this->insertExtraFields();
905 if ($result < 0) {
906 $error++;
907 }
908
909 // Update password
910 if (!$error && $this->pass) {
911 dol_syslog(get_class($this)."::update update password");
912 if ($this->pass != $this->pass_indatabase && $this->pass != $this->pass_indatabase_crypted) {
913 $isencrypted = getDolGlobalString('DATABASE_PWD_ENCRYPTED') ? 1 : 0;
914
915 // If password to set differs from the one found into database
916 $result = $this->setPassword($user, $this->pass, $isencrypted, $notrigger, $nosyncuserpass);
917 if (!$nbrowsaffected) {
918 $nbrowsaffected++;
919 }
920 }
921 }
922
923 // Remove links to user and replace with new one
924 if (!$error) {
925 dol_syslog(get_class($this)."::update update link to user");
926 $sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = NULL WHERE fk_member = ".((int) $this->id);
927 dol_syslog(get_class($this)."::update", LOG_DEBUG);
928 $resql = $this->db->query($sql);
929 if (!$resql) {
930 $this->error = $this->db->error();
931 $this->db->rollback();
932 return -5;
933 }
934 // If there is a user linked to this member
935 if ($this->user_id > 0) {
936 $sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = ".((int) $this->id)." WHERE rowid = ".((int) $this->user_id);
937 dol_syslog(get_class($this)."::update", LOG_DEBUG);
938 $resql = $this->db->query($sql);
939 if (!$resql) {
940 $this->error = $this->db->error();
941 $this->db->rollback();
942 return -5;
943 }
944 }
945 }
946
947 if (!$error && $nbrowsaffected) { // If something has change in main data
948 // Update information on linked user if it is an update
949 if ($this->user_id > 0 && !$nosyncuser) {
950 require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
951
952 dol_syslog(get_class($this)."::update update linked user");
953
954 $luser = new User($this->db);
955 $result = $luser->fetch($this->user_id);
956
957 if ($result >= 0) {
958 // 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.
959 if (!getDolGlobalString('ADHERENT_LOGIN_NOT_REQUIRED')) {
960 $luser->login = $this->login;
961 }
962
963 $luser->ref = $this->ref;
964 $luser->civility_id = $this->civility_id;
965 $luser->firstname = $this->firstname;
966 $luser->lastname = $this->lastname;
967 $luser->gender = $this->gender;
968 $luser->pass = isset($this->pass) ? $this->pass : '';
969 //$luser->socid=$this->fk_soc; // We do not enable this. This may transform a user into an external user.
970
971 $luser->birth = $this->birth;
972
973 $luser->address = $this->address;
974 $luser->zip = $this->zip;
975 $luser->town = $this->town;
976 $luser->country_id = $this->country_id;
977 $luser->state_id = $this->state_id;
978
979 $luser->email = $this->email;
980 $luser->socialnetworks = $this->socialnetworks;
981 $luser->office_phone = $this->phone;
982 $luser->user_mobile = $this->phone_mobile;
983
984 $luser->lang = $this->default_lang;
985
986 $luser->fk_member = $this->id;
987
988 $result = $luser->update($user, 0, 1, 1); // Use nosync to 1 to avoid cyclic updates
989 if ($result < 0) {
990 $this->error = $luser->error;
991 dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
992 $error++;
993 }
994 } else {
995 $this->error = $luser->error;
996 $error++;
997 }
998 }
999
1000 // Update information on linked thirdparty if it is an update
1001 if (!$error && $this->socid > 0 && !$nosyncthirdparty) {
1002 require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
1003
1004 dol_syslog(get_class($this)."::update update linked thirdparty");
1005
1006 // This member is linked with a thirdparty, so we also update thirdparty information
1007 // if this is an update.
1008 $lthirdparty = new Societe($this->db);
1009 $result = $lthirdparty->fetch($this->socid);
1010
1011 if ($result > 0) {
1012 $lthirdparty->address = $this->address;
1013 $lthirdparty->zip = $this->zip;
1014 $lthirdparty->town = $this->town;
1015 $lthirdparty->email = $this->email;
1016 $lthirdparty->socialnetworks = $this->socialnetworks;
1017 $lthirdparty->phone = $this->phone;
1018 $lthirdparty->state_id = $this->state_id;
1019 $lthirdparty->country_id = $this->country_id;
1020 //$lthirdparty->phone_mobile=$this->phone_mobile;
1021 $lthirdparty->default_lang = $this->default_lang;
1022
1023 $result = $lthirdparty->update($this->socid, $user, 0, 1, 1, 'update'); // Use sync to 0 to avoid cyclic updates
1024
1025 if ($result < 0) {
1026 $this->error = $lthirdparty->error;
1027 $this->errors = $lthirdparty->errors;
1028 dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
1029 $error++;
1030 }
1031 } elseif ($result < 0) {
1032 $this->error = $lthirdparty->error;
1033 $error++;
1034 }
1035 }
1036 }
1037
1038 if (!$error && !$notrigger) {
1039 // Call trigger
1040 $result = $this->call_trigger('MEMBER_MODIFY', $user);
1041 if ($result < 0) {
1042 $error++;
1043 }
1044 // End call triggers
1045 }
1046
1047 if (!$error) {
1048 $this->db->commit();
1049 return $nbrowsaffected;
1050 } else {
1051 $this->db->rollback();
1052 return -1;
1053 }
1054 } else {
1055 $this->db->rollback();
1056 $this->error = $this->db->lasterror();
1057 return -2;
1058 }
1059 }
1060
1061
1062 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1070 public function update_end_date($user)
1071 {
1072 // phpcs:enable
1073 $this->db->begin();
1074
1075 // Search for last subscription id and end date
1076 $sql = "SELECT rowid, datec as dateop, dateadh as datedeb, datef as datefin";
1077 $sql .= " FROM ".MAIN_DB_PREFIX."subscription";
1078 $sql .= " WHERE fk_adherent = ".((int) $this->id);
1079 $sql .= " ORDER by dateadh DESC"; // Sort by start subscription date
1080
1081 dol_syslog(get_class($this)."::update_end_date", LOG_DEBUG);
1082 $resql = $this->db->query($sql);
1083 if ($resql) {
1084 $obj = $this->db->fetch_object($resql);
1085 $dateop = $this->db->jdate($obj->dateop);
1086 $datedeb = $this->db->jdate($obj->datedeb);
1087 $datefin = $this->db->jdate($obj->datefin);
1088
1089 $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
1090 $sql .= " datefin=".($datefin != '' ? "'".$this->db->idate($datefin)."'" : "null");
1091 $sql .= " WHERE rowid = ".((int) $this->id);
1092
1093 dol_syslog(get_class($this)."::update_end_date", LOG_DEBUG);
1094 $resql = $this->db->query($sql);
1095 if ($resql) {
1096 $this->last_subscription_date = $dateop;
1097 $this->last_subscription_date_start = $datedeb;
1098 $this->last_subscription_date_end = $datefin;
1099 $this->datefin = $datefin;
1100 $this->db->commit();
1101 return 1;
1102 } else {
1103 $this->db->rollback();
1104 return -1;
1105 }
1106 } else {
1107 $this->error = $this->db->lasterror();
1108 $this->db->rollback();
1109 return -1;
1110 }
1111 }
1112
1120 public function delete($user, $notrigger = 0)
1121 {
1122 $result = 0;
1123 $error = 0;
1124 $errorflag = 0;
1125
1126 // Check parameters
1127 $rowid = $this->id;
1128
1129 $this->db->begin();
1130
1131 if (!$notrigger) {
1132 // Call trigger
1133 $result = $this->call_trigger('MEMBER_DELETE', $user);
1134 if ($result < 0) {
1135 $error++;
1136 }
1137 // End call triggers
1138 }
1139
1140 // Remove category
1141 $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_member WHERE fk_member = ".((int) $rowid);
1142 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1143 $resql = $this->db->query($sql);
1144 if (!$resql) {
1145 $error++;
1146 $this->error .= $this->db->lasterror();
1147 $errorflag = -1;
1148 }
1149
1150 // Remove subscription
1151 if (!$error) {
1152 $sql = "DELETE FROM ".MAIN_DB_PREFIX."subscription WHERE fk_adherent = ".((int) $rowid);
1153 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1154 $resql = $this->db->query($sql);
1155 if (!$resql) {
1156 $error++;
1157 $this->error .= $this->db->lasterror();
1158 $errorflag = -2;
1159 }
1160 }
1161
1162 // Remove linked user
1163 if (!$error) {
1164 $ret = $this->setUserId(0);
1165 if ($ret < 0) {
1166 $error++;
1167 $this->error .= $this->db->lasterror();
1168 $errorflag = -3;
1169 }
1170 }
1171
1172 // Removed extrafields
1173 if (!$error) {
1174 $result = $this->deleteExtraFields();
1175 if ($result < 0) {
1176 $error++;
1177 $errorflag = -4;
1178 dol_syslog(get_class($this)."::delete erreur ".$errorflag." ".$this->error, LOG_ERR);
1179 }
1180 }
1181
1182 // Remove adherent
1183 if (!$error) {
1184 $sql = "DELETE FROM ".MAIN_DB_PREFIX."adherent WHERE rowid = ".((int) $rowid);
1185 dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1186 $resql = $this->db->query($sql);
1187 if (!$resql) {
1188 $error++;
1189 $this->error .= $this->db->lasterror();
1190 $errorflag = -5;
1191 }
1192 }
1193
1194 if (!$error) {
1195 $this->db->commit();
1196 return 1;
1197 } else {
1198 $this->db->rollback();
1199 return $errorflag;
1200 }
1201 }
1202
1213 public function mergeMembers($member_origin_id)
1214 {
1215 global $conf, $langs, $hookmanager, $user, $action;
1216
1217 $error = 0;
1218 $member_origin = new Adherent($this->db); // The member that we will delete
1219
1220 dol_syslog("mergeMembers merge member id=".$member_origin_id." (will be deleted) into the member id=".$this->id);
1221 if ($member_origin->fetch($member_origin_id) < 1) {
1222 $this->error = $langs->trans('ErrorRecordNotFound');
1223 $error++;
1224 }
1225
1226 if (!$error) {
1227 $this->db->begin();
1228 $listofproperties = array(
1229 'ref_ext', 'civility', 'lastname', 'firstname', 'morphy', 'societe', 'socid', 'user_id','address',
1230 'zip', 'town', 'state_id', 'country', 'phone', 'phone_perso', 'phone_mobile', 'email',
1231 'url', 'socialnetworks', 'birth', 'gender', 'photo', 'public', 'datefin', 'default_lang',
1232 'canvas', 'model_pdf', 'import_key'
1233 );
1234 foreach ($listofproperties as $property) {
1235 if (empty($this->$property)) {
1236 $this->$property = $member_origin->$property;
1237 }
1238 }
1239
1240 // Concat some data
1241 $listofproperties = array(
1242 'note_public', 'note_private'
1243 );
1244 foreach ($listofproperties as $property) {
1245 $this->$property = dol_concatdesc($this->$property, $member_origin->$property);
1246 }
1247
1248 // Merge extrafields
1249 if (is_array($member_origin->array_options)) {
1250 foreach ($member_origin->array_options as $key => $val) {
1251 if (empty($this->array_options[$key])) {
1252 $this->array_options[$key] = $val;
1253 }
1254 }
1255 }
1256
1257 // Merge categories
1258 include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1259 $static_cat = new Categorie($this->db);
1260 $custcats_ori = $static_cat->containing($member_origin->id, 'member', 'id');
1261 $custcats = $static_cat->containing($this->id, 'member', 'id');
1262 $custcats = array_merge($custcats, $custcats_ori);
1263 $this->setCategories($custcats);
1264
1265 $result = $this->update($user, 1, 1, 1, 1, 'merge');
1266 if ($result < 0) {
1267 $error++;
1268 }
1269
1270 // Merge subscriptions
1271 if (!$error && $member_origin->fetch_subscriptions() < 1) {
1272 $error++;
1273 }
1274
1275 if (!$error) {
1276 foreach ($member_origin->subscriptions as $key => $subscription) {
1277 $subscription->fk_adherent = $this->id;
1278 $result = $subscription->update($user);
1279 if ($result < 0) {
1280 $error++;
1281 break;
1282 }
1283 }
1284 }
1285
1286 // External modules should update their ones too
1287 if (!$error) {
1288 $parameters = array('member_origin' => $member_origin->id, 'member_dest' => $this->id);
1289 $reshook = $hookmanager->executeHooks('replaceMember', $parameters, $this, $action);
1290
1291 if ($reshook < 0) {
1292 $this->setErrorsFromObject($hookmanager);
1293 $error++;
1294 }
1295 }
1296
1297 if (!$error) {
1298 $this->context = array('merge' => 1, 'mergefromid' => $member_origin->id);
1299
1300 // Call trigger
1301 $result = $this->call_trigger('MEMBER_MODIFY', $user);
1302 if ($result < 0) {
1303 $error++;
1304 }
1305 // End call triggers
1306 }
1307
1308 if (!$error) {
1309 // We finally remove the old member
1310 if ($member_origin->delete($user) < 1) {
1311 $this->setErrorsFromObject($member_origin);
1312 $error++;
1313 }
1314 }
1315
1316 if (!$error) {
1317 // Move files from the dir of the third party to delete into the dir of the third party to keep
1318 if (!empty($conf->adherent->multidir_output[$this->entity])) {
1319 $srcdir = $conf->adherent->multidir_output[$this->entity]."/".$member_origin->id;
1320 $destdir = $conf->adherent->multidir_output[$this->entity]."/".$this->id;
1321
1322 if (dol_is_dir($srcdir)) {
1323 $dirlist = dol_dir_list($srcdir, 'files', 1);
1324 foreach ($dirlist as $filetomove) {
1325 $destfile = $destdir.'/'.$filetomove['relativename'];
1326 $result = dol_move($filetomove['fullname'], $destfile, '0', 0, 0, 1);
1327 if (!$result) {
1328 $error++;
1329 }
1330 }
1331 }
1332 }
1333 }
1334
1335 if (!$error) {
1336 $this->db->commit();
1337 return 0;
1338 } else {
1339 $langs->load("errors");
1340 $this->error = $langs->trans('ErrorMembersMerge');
1341 $this->db->rollback();
1342 return -1;
1343 }
1344 }
1345 return -1;
1346 }
1347
1358 public function setPassword($user, $password = '', $isencrypted = 0, $notrigger = 0, $nosyncuser = 0)
1359 {
1360 global $conf, $langs;
1361
1362 $error = 0;
1363
1364 dol_syslog(get_class($this)."::setPassword user=".$user->id." password=".preg_replace('/./i', '*', $password)." isencrypted=".$isencrypted);
1365
1366 // If new password not provided, we generate one
1367 if (!$password) {
1368 require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
1369 $password = getRandomPassword(false);
1370 }
1371
1372 // Crypt password
1373 $password_crypted = dol_hash($password);
1374
1375 $password_indatabase = '';
1376 if (!$isencrypted) {
1377 $password_indatabase = $password;
1378 }
1379
1380 $this->db->begin();
1381
1382 // Mise a jour
1383 $sql = "UPDATE ".MAIN_DB_PREFIX."adherent";
1384 $sql .= " SET pass_crypted = '".$this->db->escape($password_crypted)."'";
1385 if ($isencrypted) {
1386 $sql .= ", pass = null";
1387 } else {
1388 $sql .= ", pass = '".$this->db->escape($password_indatabase)."'";
1389 }
1390 $sql .= " WHERE rowid = ".((int) $this->id);
1391
1392 //dol_syslog("Adherent::Password sql=hidden");
1393 dol_syslog(get_class($this)."::setPassword", LOG_DEBUG);
1394 $result = $this->db->query($sql);
1395 if ($result) {
1396 $nbaffectedrows = $this->db->affected_rows($result);
1397
1398 if ($nbaffectedrows) {
1399 $this->pass = $password;
1400 $this->pass_indatabase = $password_indatabase;
1401 $this->pass_indatabase_crypted = $password_crypted;
1402
1403 if ($this->user_id && !$nosyncuser) {
1404 require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
1405
1406 // This member is linked with a user, so we also update users information
1407 // if this is an update.
1408 $luser = new User($this->db);
1409 $result = $luser->fetch($this->user_id);
1410
1411 if ($result >= 0) {
1412 $result = $luser->setPassword($user, $this->pass, 0, 0, 1);
1413 if (is_int($result) && $result < 0) {
1414 $this->error = $luser->error;
1415 dol_syslog(get_class($this)."::setPassword ".$this->error, LOG_ERR);
1416 $error++;
1417 }
1418 } else {
1419 $this->error = $luser->error;
1420 $error++;
1421 }
1422 }
1423
1424 if (!$error && !$notrigger) {
1425 // Call trigger
1426 $result = $this->call_trigger('MEMBER_NEW_PASSWORD', $user);
1427 if ($result < 0) {
1428 $error++;
1429 $this->db->rollback();
1430 return -1;
1431 }
1432 // End call triggers
1433 }
1434
1435 $this->db->commit();
1436 return $this->pass;
1437 } else {
1438 $this->db->rollback();
1439 return 0;
1440 }
1441 } else {
1442 $this->db->rollback();
1443 dol_print_error($this->db);
1444 return -1;
1445 }
1446 }
1447
1448
1455 public function setUserId($userid)
1456 {
1457 global $conf, $langs;
1458
1459 $this->db->begin();
1460
1461 // If user is linked to this member, remove old link to this member
1462 $sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = NULL WHERE fk_member = ".((int) $this->id);
1463 dol_syslog(get_class($this)."::setUserId", LOG_DEBUG);
1464 $resql = $this->db->query($sql);
1465 if (!$resql) {
1466 $this->error = $this->db->error();
1467 $this->db->rollback();
1468 return -1;
1469 }
1470
1471 // Set link to user
1472 if ($userid > 0) {
1473 $sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = ".((int) $this->id);
1474 $sql .= " WHERE rowid = ".((int) $userid);
1475 dol_syslog(get_class($this)."::setUserId", LOG_DEBUG);
1476 $resql = $this->db->query($sql);
1477 if (!$resql) {
1478 $this->error = $this->db->error();
1479 $this->db->rollback();
1480 return -2;
1481 }
1482 }
1483
1484 $this->db->commit();
1485
1486 return 1;
1487 }
1488
1489
1496 public function setThirdPartyId($thirdpartyid)
1497 {
1498 global $conf, $langs;
1499
1500 $this->db->begin();
1501
1502 // Remove link to third party onto any other members
1503 if ($thirdpartyid > 0) {
1504 $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET fk_soc = null";
1505 $sql .= " WHERE fk_soc = ".((int) $thirdpartyid);
1506 $sql .= " AND entity = ".((int) $conf->entity);
1507 dol_syslog(get_class($this)."::setThirdPartyId", LOG_DEBUG);
1508 $resql = $this->db->query($sql);
1509 }
1510
1511 // Add link to third party for current member
1512 $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET fk_soc = ".($thirdpartyid > 0 ? (int) $thirdpartyid : 'null');
1513 $sql .= " WHERE rowid = ".((int) $this->id);
1514
1515 dol_syslog(get_class($this)."::setThirdPartyId", LOG_DEBUG);
1516 $resql = $this->db->query($sql);
1517 if ($resql) {
1518 $this->db->commit();
1519 return 1;
1520 } else {
1521 $this->error = $this->db->error();
1522 $this->db->rollback();
1523 return -1;
1524 }
1525 }
1526
1527
1528 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1535 public function fetch_login($login)
1536 {
1537 // phpcs:enable
1538 global $conf;
1539
1540 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."adherent";
1541 $sql .= " WHERE login='".$this->db->escape($login)."'";
1542 $sql .= " AND entity = ".((int) $conf->entity);
1543
1544 $resql = $this->db->query($sql);
1545 if ($resql) {
1546 if ($this->db->num_rows($resql)) {
1547 $obj = $this->db->fetch_object($resql);
1548 $this->fetch($obj->rowid);
1549 }
1550 } else {
1551 dol_print_error($this->db);
1552 }
1553 }
1554
1555 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1563 public function fetch_name($firstname, $lastname)
1564 {
1565 // phpcs:enable
1566 global $conf;
1567
1568 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."adherent";
1569 $sql .= " WHERE firstname='".$this->db->escape($firstname)."'";
1570 $sql .= " AND lastname='".$this->db->escape($lastname)."'";
1571 $sql .= " AND entity = ".((int) $conf->entity);
1572
1573 $resql = $this->db->query($sql);
1574 if ($resql) {
1575 if ($this->db->num_rows($resql)) {
1576 $obj = $this->db->fetch_object($resql);
1577 $this->fetch($obj->rowid);
1578 }
1579 } else {
1580 dol_print_error($this->db);
1581 }
1582 }
1583
1595 public function fetch($rowid, $ref = '', $socid = 0, $ref_ext = '', $fetch_optionals = true, $fetch_subscriptions = true)
1596 {
1597 global $langs;
1598
1599 $sql = "SELECT d.rowid, d.ref, d.ref_ext, d.civility as civility_code, d.gender, d.firstname, d.lastname,";
1600 $sql .= " d.societe as company, d.fk_soc as socid, d.statut, d.public, d.address, d.zip, d.town, d.note_private,";
1601 $sql .= " d.note_public,";
1602 $sql .= " d.email, d.url, d.socialnetworks, d.phone, d.phone_perso, d.phone_mobile, d.login, d.pass, d.pass_crypted,";
1603 $sql .= " d.photo, d.fk_adherent_type, d.morphy, d.entity,";
1604 $sql .= " d.datec as datec,";
1605 $sql .= " GREATEST(d.tms, aef.tms) as datem,";
1606 $sql .= " d.datefin as datefin, d.default_lang,";
1607 $sql .= " d.birth as birthday,";
1608 $sql .= " d.datevalid as datev,";
1609 $sql .= " d.country,";
1610 $sql .= " d.state_id,";
1611 $sql .= " d.model_pdf,";
1612 $sql .= " c.rowid as country_id, c.code as country_code, c.label as country,";
1613 $sql .= " dep.nom as state, dep.code_departement as state_code,";
1614 $sql .= " t.libelle as type, t.subscription as subscription,";
1615 $sql .= " u.rowid as user_id, u.login as user_login";
1616 $sql .= " FROM ".MAIN_DB_PREFIX."adherent_type as t, ".MAIN_DB_PREFIX."adherent as d";
1617 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'adherent_extrafields as aef ON aef.fk_object = d.rowid';
1618 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as c ON d.country = c.rowid";
1619 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as dep ON d.state_id = dep.rowid";
1620 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u ON d.rowid = u.fk_member";
1621 $sql .= " WHERE d.fk_adherent_type = t.rowid";
1622 if ($rowid) {
1623 $sql .= " AND d.rowid=".((int) $rowid);
1624 } elseif ($ref || $socid) {
1625 $sql .= " AND d.entity IN (".getEntity('adherent').")";
1626 if ($ref) {
1627 $sql .= " AND d.ref='".$this->db->escape($ref)."'";
1628 } elseif ($socid > 0) {
1629 $sql .= " AND d.fk_soc=".((int) $socid);
1630 }
1631 } elseif ($ref_ext) {
1632 $sql .= " AND d.ref_ext='".$this->db->escape($ref_ext)."'";
1633 }
1634
1635 dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
1636 $resql = $this->db->query($sql);
1637 if ($resql) {
1638 if ($this->db->num_rows($resql)) {
1639 $obj = $this->db->fetch_object($resql);
1640
1641 $this->entity = $obj->entity;
1642 $this->id = $obj->rowid;
1643 $this->ref = $obj->ref;
1644 $this->ref_ext = $obj->ref_ext;
1645
1646 $this->civility_id = $obj->civility_code; // Bad. Kept for backward compatibility
1647 $this->civility_code = $obj->civility_code;
1648 $this->civility = $obj->civility_code ? ($langs->trans("Civility".$obj->civility_code) != "Civility".$obj->civility_code ? $langs->trans("Civility".$obj->civility_code) : $obj->civility_code) : '';
1649
1650 $this->firstname = $obj->firstname;
1651 $this->lastname = $obj->lastname;
1652 $this->gender = $obj->gender;
1653 $this->login = $obj->login;
1654 $this->societe = $obj->company;
1655 $this->company = $obj->company;
1656 $this->socid = $obj->socid;
1657 $this->fk_soc = $obj->socid; // For backward compatibility
1658 $this->address = $obj->address;
1659 $this->zip = $obj->zip;
1660 $this->town = $obj->town;
1661
1662 $this->pass = $obj->pass;
1663 $this->pass_indatabase = $obj->pass;
1664 $this->pass_indatabase_crypted = $obj->pass_crypted;
1665
1666 $this->state_id = $obj->state_id;
1667 $this->state_code = $obj->state_id ? $obj->state_code : '';
1668 $this->state = $obj->state_id ? $obj->state : '';
1669
1670 $this->country_id = $obj->country_id;
1671 $this->country_code = $obj->country_code;
1672 if ($langs->trans("Country".$obj->country_code) != "Country".$obj->country_code) {
1673 $this->country = $langs->transnoentitiesnoconv("Country".$obj->country_code);
1674 } else {
1675 $this->country = $obj->country;
1676 }
1677
1678 $this->phone = $obj->phone;
1679 $this->phone_perso = $obj->phone_perso;
1680 $this->phone_mobile = $obj->phone_mobile;
1681 $this->email = $obj->email;
1682 $this->url = $obj->url;
1683
1684 $this->socialnetworks = ($obj->socialnetworks ? (array) json_decode($obj->socialnetworks, true) : array());
1685
1686 $this->photo = $obj->photo;
1687 $this->statut = $obj->statut;
1688 $this->status = $obj->statut;
1689 $this->public = $obj->public;
1690
1691 $this->datec = $this->db->jdate($obj->datec);
1692 $this->date_creation = $this->db->jdate($obj->datec);
1693 $this->datem = $this->db->jdate($obj->datem);
1694 $this->date_modification = $this->db->jdate($obj->datem);
1695 $this->datefin = $this->db->jdate($obj->datefin);
1696 $this->datevalid = $this->db->jdate($obj->datev);
1697 $this->date_validation = $this->db->jdate($obj->datev);
1698 $this->birth = $this->db->jdate($obj->birthday);
1699
1700 $this->default_lang = $obj->default_lang;
1701
1702 $this->note_private = $obj->note_private;
1703 $this->note_public = $obj->note_public;
1704 $this->morphy = $obj->morphy;
1705
1706 $this->typeid = $obj->fk_adherent_type;
1707 $this->type = $obj->type;
1708 $this->need_subscription = $obj->subscription;
1709
1710 $this->user_id = $obj->user_id;
1711 $this->user_login = $obj->user_login;
1712
1713 $this->model_pdf = $obj->model_pdf;
1714
1715 // Retrieve all extrafield
1716 // fetch optionals attributes and labels
1717 if ($fetch_optionals) {
1718 $this->fetch_optionals();
1719 }
1720
1721 // Load other properties
1722 if ($fetch_subscriptions) {
1723 $result = $this->fetch_subscriptions();
1724 }
1725
1726 return $this->id;
1727 } else {
1728 return 0;
1729 }
1730 } else {
1731 $this->error = $this->db->lasterror();
1732 return -1;
1733 }
1734 }
1735
1736
1737 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1746 public function fetch_subscriptions()
1747 {
1748 // phpcs:enable
1749 require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
1750
1751 $sql = "SELECT c.rowid, c.fk_adherent, c.fk_type, c.subscription, c.note as note_public, c.fk_bank,";
1752 $sql .= " c.tms as datem,";
1753 $sql .= " c.datec as datec,";
1754 $sql .= " c.dateadh as dateh,";
1755 $sql .= " c.datef as datef";
1756 $sql .= " FROM ".MAIN_DB_PREFIX."subscription as c";
1757 $sql .= " WHERE c.fk_adherent = ".((int) $this->id);
1758 $sql .= " ORDER BY c.dateadh";
1759 dol_syslog(get_class($this)."::fetch_subscriptions", LOG_DEBUG);
1760
1761 $resql = $this->db->query($sql);
1762 if ($resql) {
1763 $this->subscriptions = array();
1764
1765 $i = 0;
1766 while ($obj = $this->db->fetch_object($resql)) {
1767 if ($i == 0) {
1768 $this->first_subscription_date = $this->db->jdate($obj->datec);
1769 $this->first_subscription_date_start = $this->db->jdate($obj->dateh);
1770 $this->first_subscription_date_end = $this->db->jdate($obj->datef);
1771 $this->first_subscription_amount = $obj->subscription;
1772 }
1773 $this->last_subscription_date = $this->db->jdate($obj->datec);
1774 $this->last_subscription_date_start = $this->db->jdate($obj->dateh);
1775 $this->last_subscription_date_end = $this->db->jdate($obj->datef);
1776 $this->last_subscription_amount = (float) $obj->subscription;
1777
1778 $subscription = new Subscription($this->db);
1779 $subscription->id = $obj->rowid;
1780 $subscription->fk_adherent = $obj->fk_adherent;
1781 $subscription->fk_type = $obj->fk_type;
1782 $subscription->amount = (float) $obj->subscription;
1783 $subscription->note = $obj->note_public;
1784 $subscription->note_public = $obj->note_public;
1785 $subscription->fk_bank = $obj->fk_bank;
1786 $subscription->datem = $this->db->jdate($obj->datem);
1787 $subscription->datec = $this->db->jdate($obj->datec);
1788 $subscription->dateh = $this->db->jdate($obj->dateh);
1789 $subscription->datef = $this->db->jdate($obj->datef);
1790
1791 $this->subscriptions[] = $subscription;
1792
1793 $i++;
1794 }
1795 return 1;
1796 } else {
1797 $this->error = $this->db->error().' sql='.$sql;
1798 return -1;
1799 }
1800 }
1801
1802
1809 public function fetchPartnerships($mode)
1810 {
1811 require_once DOL_DOCUMENT_ROOT.'/partnership/class/partnership.class.php';
1812
1813
1814 $this->partnerships[] = array();
1815
1816 return 1;
1817 }
1818
1819
1836 public function subscription($date, $amount, $accountid = 0, $operation = '', $label = '', $num_chq = '', $emetteur_nom = '', $emetteur_banque = '', $datesubend = 0, $fk_type = null, $ref_ext = '')
1837 {
1838 global $user;
1839
1840 require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
1841
1842 $error = 0;
1843
1844 // Clean parameters
1845 if (!$amount) {
1846 $amount = 0;
1847 }
1848
1849 $this->db->begin();
1850
1851 if ($datesubend) {
1852 $datefin = $datesubend;
1853 } else {
1854 // If no end date, end date = date + 1 year - 1 day
1855 $datefin = dol_time_plus_duree($date, 1, 'y');
1856 $datefin = dol_time_plus_duree($datefin, -1, 'd');
1857 }
1858
1859 // Create subscription
1860 $subscription = new Subscription($this->db);
1861 $subscription->fk_adherent = $this->id;
1862 $subscription->dateh = $date; // Date of new subscription
1863 $subscription->datef = $datefin; // End data of new subscription
1864 $subscription->amount = $amount;
1865 $subscription->note_public = $label;
1866 $subscription->note_private = '';
1867 $subscription->fk_type = $fk_type;
1868 $subscription->ref_ext = $ref_ext;
1869
1870 if (empty($subscription->user_creation_id)) {
1871 $subscription->user_creation_id = $user->id;
1872 }
1873
1874 $rowid = $subscription->create($user);
1875 if ($rowid > 0) {
1876 // Update denormalized subscription end date (read database subscription to find values)
1877 // This will also update this->datefin
1878 $result = $this->update_end_date($user);
1879 if ($result > 0) {
1880 // Change properties of object (used by triggers)
1881 $this->last_subscription_date = dol_now();
1882 $this->last_subscription_date_start = $date;
1883 $this->last_subscription_date_end = $datefin;
1884 $this->last_subscription_amount = $amount;
1885 } else {
1886 $error++;
1887 }
1888
1889 if (!$error) {
1890 $this->db->commit();
1891 return $rowid;
1892 } else {
1893 $this->db->rollback();
1894 return -2;
1895 }
1896 } else {
1897 $this->setErrorsFromObject($subscription);
1898 $this->db->rollback();
1899 return -1;
1900 }
1901 }
1902
1903
1923 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 = '')
1924 {
1925 global $conf, $langs, $user, $mysoc;
1926
1927 $error = 0;
1928
1929 $this->invoice = null; // This will contains invoice if an invoice is created
1930
1931 dol_syslog("subscriptionComplementaryActions subscriptionid=".$subscriptionid." option=".$option." accountid=".$accountid." datesubscription=".$datesubscription." paymentdate=".
1932 $paymentdate." label=".$label." amount=".$amount." num_chq=".$num_chq." autocreatethirdparty=".$autocreatethirdparty);
1933
1934 // Insert into bank account directlty (if option chosen for) + link to llx_subscription if option is 'bankdirect'
1935 if ($option == 'bankdirect' && $accountid) {
1936 require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
1937
1938 $acct = new Account($this->db);
1939 $result = $acct->fetch($accountid);
1940
1941 $dateop = $paymentdate;
1942
1943 $insertid = $acct->addline($dateop, $operation, $label, $amount, $num_chq, 0, $user, $emetteur_nom, $emetteur_banque);
1944 if ($insertid > 0) {
1945 $inserturlid = $acct->add_url_line($insertid, $this->id, DOL_URL_ROOT.'/adherents/card.php?rowid=', $this->getFullName($langs), 'member');
1946 if ($inserturlid > 0) {
1947 // Update table subscription
1948 $sql = "UPDATE ".MAIN_DB_PREFIX."subscription SET fk_bank=".((int) $insertid);
1949 $sql .= " WHERE rowid=".((int) $subscriptionid);
1950
1951 dol_syslog("subscription::subscription", LOG_DEBUG);
1952 $resql = $this->db->query($sql);
1953 if (!$resql) {
1954 $error++;
1955 $this->error = $this->db->lasterror();
1956 $this->errors[] = $this->error;
1957 }
1958 } else {
1959 $error++;
1960 $this->setErrorsFromObject($acct);
1961 }
1962 } else {
1963 $error++;
1964 $this->setErrorsFromObject($acct);
1965 }
1966 }
1967
1968 // If option chosen, we create invoice
1969 if (($option == 'bankviainvoice' && $accountid) || $option == 'invoiceonly') {
1970 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
1971 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/paymentterm.class.php';
1972
1973 $invoice = new Facture($this->db);
1974 $customer = new Societe($this->db);
1975
1976 if (!$error) {
1977 if (!($this->socid > 0)) { // If not yet linked to a company
1978 if ($autocreatethirdparty) {
1979 // Create a linked thirdparty to member
1980 $companyalias = '';
1981 $fullname = $this->getFullName($langs);
1982
1983 if ($this->morphy == 'mor') {
1984 $companyname = $this->company;
1985 if (!empty($fullname)) {
1986 $companyalias = $fullname;
1987 }
1988 } else {
1989 $companyname = $fullname;
1990 if (!empty($this->company)) {
1991 $companyalias = $this->company;
1992 }
1993 }
1994
1995 $result = $customer->create_from_member($this, (string) $companyname, $companyalias);
1996 if ($result < 0) {
1997 $this->error = $customer->error;
1998 $this->errors = $customer->errors;
1999 $error++;
2000 } else {
2001 $this->fk_soc = $result;
2002 $this->socid = $result;
2003 }
2004 } else {
2005 $langs->load("errors");
2006 $this->error = $langs->trans("ErrorMemberNotLinkedToAThirpartyLinkOrCreateFirst");
2007 $this->errors[] = $this->error;
2008 $error++;
2009 }
2010 }
2011 }
2012 if (!$error) {
2013 $result = $customer->fetch($this->socid);
2014 if ($result <= 0) {
2015 $this->error = $customer->error;
2016 $this->errors = $customer->errors;
2017 $error++;
2018 }
2019 }
2020
2021 if (!$error) {
2022 // Create draft invoice
2023 $invoice->type = Facture::TYPE_STANDARD;
2024 $invoice->cond_reglement_id = $customer->cond_reglement_id;
2025 if (empty($invoice->cond_reglement_id)) {
2026 $paymenttermstatic = new PaymentTerm($this->db);
2027 $invoice->cond_reglement_id = $paymenttermstatic->getDefaultId();
2028 if (empty($invoice->cond_reglement_id)) {
2029 $error++;
2030 $this->error = 'ErrorNoPaymentTermRECEPFound';
2031 $this->errors[] = $this->error;
2032 }
2033 }
2034 $invoice->socid = $this->socid;
2035 // set customer's payment bank account on the invoice
2036 if (!empty($customer->fk_account)) {
2037 $invoice->fk_account = $customer->fk_account;
2038 } elseif (getDolGlobalString('FACTURE_RIB_NUMBER')) {
2039 // set default bank account from invoice module settings
2040 $invoice->fk_account = (int) getDolGlobalString('FACTURE_RIB_NUMBER');
2041 }
2042 //set customer's payment method on the invoice
2043 if (!empty($customer->mode_reglement_id)) {
2044 $invoice->mode_reglement_id = $customer->mode_reglement_id;
2045 }
2046 //$invoice->date = $datesubscription;
2047 $invoice->date = dol_now();
2048
2049 // Possibility to add external linked objects with hooks
2050 $invoice->linked_objects['subscription'] = $subscriptionid;
2051 if (GETPOSTISARRAY('other_linked_objects')) {
2052 $invoice->linked_objects = array_merge($invoice->linked_objects, GETPOST('other_linked_objects', 'array:int'));
2053 }
2054
2055 $result = $invoice->create($user);
2056 if ($result <= 0) {
2057 $this->setErrorsFromObject($invoice);
2058 $error++;
2059 } else {
2060 $this->invoice = $invoice;
2061 }
2062 }
2063
2064 if (!$error) {
2065 // Add line to draft invoice
2066 $idprodsubscription = 0;
2067 if (getDolGlobalString('ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS') && (isModEnabled("product") || isModEnabled("service"))) {
2068 $idprodsubscription = getDolGlobalString('ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS');
2069 }
2070
2071 $vattouse = 0;
2072 if (getDolGlobalString('ADHERENT_VAT_FOR_SUBSCRIPTIONS') == 'defaultforfoundationcountry') {
2073 $vattouse = get_default_tva($mysoc, $mysoc, $idprodsubscription);
2074 }
2075 //print xx".$vattouse." - ".$mysoc." - ".$customer;exit;
2076 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
2077 $result = $invoice->addline($label, 0, 1, $vattouse, 0, 0, $idprodsubscription, 0, $datesubscription, '', 0, 0, 0, 'TTC', $amount, 1);
2078 if ($result <= 0) {
2079 $this->setErrorsFromObject($invoice);
2080 $error++;
2081 }
2082 }
2083
2084 if (!$error) {
2085 // Validate invoice
2086 $result = $invoice->validate($user);
2087 if ($result <= 0) {
2088 $this->setErrorsFromObject($invoice);
2089 $error++;
2090 }
2091 }
2092
2093 if (!$error) {
2094 // TODO Link invoice with subscription ?
2095 }
2096
2097 // Add payment onto invoice
2098 if (!$error && $option == 'bankviainvoice' && $accountid) {
2099 require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
2100 require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
2101
2102 $amounts = array();
2103 $amounts[$invoice->id] = (float) price2num($amount);
2104
2105 $paiement = new Paiement($this->db);
2106 $paiement->datepaye = $paymentdate;
2107 $paiement->amounts = $amounts;
2108 $paiement->paiementcode = $operation;
2109 $paiement->paiementid = dol_getIdFromCode($this->db, $operation, 'c_paiement', 'code', 'id', 1);
2110 $paiement->num_payment = $num_chq;
2111 $paiement->note_public = $label;
2112 $paiement->ext_payment_id = $ext_payment_id;
2113 $paiement->ext_payment_site = $ext_payment_site;
2114
2115 // Create payment line for invoice
2116 $paiement_id = $paiement->create($user);
2117 if (!($paiement_id > 0)) {
2118 $this->setErrorsFromObject($paiement);
2119 $error++;
2120 }
2121
2122 if (!$error) {
2123 // Add transaction into bank account
2124 $bank_line_id = $paiement->addPaymentToBank($user, 'payment', '(SubscriptionPayment)', $accountid, $emetteur_nom, $emetteur_banque);
2125 if (!($bank_line_id > 0)) {
2126 $this->setErrorsFromObject($paiement);
2127 $error++;
2128 }
2129 }
2130
2131 if (!$error && !empty($bank_line_id)) {
2132 // Update fk_bank into subscription table
2133 $sql = 'UPDATE '.MAIN_DB_PREFIX.'subscription SET fk_bank='.((int) $bank_line_id);
2134 $sql .= ' WHERE rowid='.((int) $subscriptionid);
2135
2136 $result = $this->db->query($sql);
2137 if (!$result) {
2138 $error++;
2139 }
2140 }
2141
2142 if (!$error) {
2143 // Set invoice as paid
2144 $invoice->setPaid($user);
2145 }
2146 }
2147
2148 if (!$error) {
2149 // Define output language
2150 $outputlangs = $langs;
2151 $newlang = '';
2152 $lang_id = GETPOST('lang_id');
2153 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && !empty($lang_id)) {
2154 $newlang = $lang_id;
2155 }
2156 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
2157 $newlang = $customer->default_lang;
2158 }
2159 if (!empty($newlang)) {
2160 $outputlangs = new Translate("", $conf);
2161 $outputlangs->setDefaultLang($newlang);
2162 }
2163 // Generate PDF (whatever is option MAIN_DISABLE_PDF_AUTOUPDATE) so we can include it into email
2164 //if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE'))
2165
2166 $invoice->fetch($invoice->id); // Reload invoice object data
2167 $invoice->generateDocument($invoice->model_pdf, $outputlangs);
2168 }
2169 }
2170
2171 if ($error) {
2172 return -1;
2173 } else {
2174 return 1;
2175 }
2176 }
2177
2178
2186 public function validate($user, $notrigger = 0)
2187 {
2188 global $langs, $conf;
2189
2190 $error = 0;
2191 $now = dol_now();
2192
2193 // Check parameters
2194 if ($this->status == self::STATUS_VALIDATED) {
2195 dol_syslog(get_class($this)."::validate statut of member does not allow this", LOG_WARNING);
2196 return 0;
2197 }
2198
2199 $this->db->begin();
2200
2201 $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
2202 $sql .= " statut = ".self::STATUS_VALIDATED;
2203 $sql .= ", datevalid = '".$this->db->idate($now)."'";
2204 $sql .= ", fk_user_valid = ".((int) $user->id);
2205 $sql .= " WHERE rowid = ".((int) $this->id);
2206
2207 dol_syslog(get_class($this)."::validate", LOG_DEBUG);
2208 $result = $this->db->query($sql);
2209 if ($result) {
2210 $this->statut = self::STATUS_VALIDATED;
2212
2213 // Call trigger
2214 if (!$notrigger) {
2215 $result = $this->call_trigger('MEMBER_VALIDATE', $user);
2216 if ($result < 0) {
2217 $error++;
2218 $this->db->rollback();
2219 return -1;
2220 }
2221 }
2222 // End call triggers
2223
2224 $this->datevalid = $now;
2225
2226 $this->db->commit();
2227 return 1;
2228 } else {
2229 $this->error = $this->db->error();
2230 $this->db->rollback();
2231 return -1;
2232 }
2233 }
2234
2235
2242 public function resiliate($user)
2243 {
2244 global $langs, $conf;
2245
2246 $error = 0;
2247
2248 // Check parameters
2249 if ($this->status == self::STATUS_RESILIATED) {
2250 dol_syslog(get_class($this)."::resiliate statut of member does not allow this", LOG_WARNING);
2251 return 0;
2252 }
2253
2254 $this->db->begin();
2255
2256 $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
2257 $sql .= " statut = ".((int) self::STATUS_RESILIATED);
2258 $sql .= ", fk_user_valid = ".((int) $user->id);
2259 $sql .= " WHERE rowid = ".((int) $this->id);
2260
2261 $result = $this->db->query($sql);
2262 if ($result) {
2263 $this->statut = self::STATUS_RESILIATED;
2265
2266 // Call trigger
2267 $result = $this->call_trigger('MEMBER_RESILIATE', $user);
2268 if ($result < 0) {
2269 $error++;
2270 $this->db->rollback();
2271 return -1;
2272 }
2273 // End call triggers
2274
2275 $this->db->commit();
2276 return 1;
2277 } else {
2278 $this->error = $this->db->error();
2279 $this->db->rollback();
2280 return -1;
2281 }
2282 }
2283
2293 public function exclude($user)
2294 {
2295 $error = 0;
2296
2297 // Check parameters
2298 if ($this->status == self::STATUS_EXCLUDED) {
2299 dol_syslog(get_class($this)."::resiliate statut of member does not allow this", LOG_WARNING);
2300 return 0;
2301 }
2302
2303 $this->db->begin();
2304
2305 $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
2306 $sql .= " statut = ".((int) self::STATUS_EXCLUDED);
2307 $sql .= ", fk_user_valid = ".((int) $user->id);
2308 $sql .= " WHERE rowid = ".((int) $this->id);
2309
2310 $result = $this->db->query($sql);
2311 if ($result) {
2312 $this->statut = self::STATUS_EXCLUDED;
2314
2315 // Call trigger
2316 $result = $this->call_trigger('MEMBER_EXCLUDE', $user);
2317 if ($result < 0) {
2318 $error++;
2319 $this->db->rollback();
2320 return -1;
2321 }
2322 // End call triggers
2323
2324 $this->db->commit();
2325 return 1;
2326 } else {
2327 $this->error = $this->db->error();
2328 $this->db->rollback();
2329 return -1;
2330 }
2331 }
2332
2333 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2339 public function add_to_abo()
2340 {
2341 // phpcs:enable
2342 global $langs;
2343
2344 include_once DOL_DOCUMENT_ROOT.'/mailmanspip/class/mailmanspip.class.php';
2345 $mailmanspip = new MailmanSpip($this->db);
2346
2347 $err = 0;
2348
2349 // mailman
2350 if (getDolGlobalString('ADHERENT_USE_MAILMAN') && isModEnabled('mailmanspip')) {
2351 $result = $mailmanspip->add_to_mailman($this);
2352
2353 if ($result < 0) {
2354 if (!empty($mailmanspip->error)) {
2355 $this->errors[] = $mailmanspip->error;
2356 }
2357 $err += 1;
2358 }
2359 foreach ($mailmanspip->mladded_ko as $tmplist => $tmpemail) {
2360 $langs->load("errors");
2361 $this->errors[] = $langs->trans("ErrorFailedToAddToMailmanList", $tmpemail, $tmplist);
2362 }
2363 foreach ($mailmanspip->mladded_ok as $tmplist => $tmpemail) {
2364 $langs->load("mailmanspip");
2365 $this->mesgs[] = $langs->trans("SuccessToAddToMailmanList", $tmpemail, $tmplist);
2366 }
2367 }
2368
2369 // spip
2370 if (getDolGlobalString('ADHERENT_USE_SPIP') && isModEnabled('mailmanspip')) {
2371 $result = $mailmanspip->add_to_spip($this);
2372 if ($result < 0) {
2373 $this->errors[] = $mailmanspip->error;
2374 $err += 1;
2375 }
2376 }
2377 if ($err) {
2378 return -$err;
2379 } else {
2380 return 1;
2381 }
2382 }
2383
2384
2385 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2391 public function del_to_abo()
2392 {
2393 // phpcs:enable
2394 global $conf, $langs;
2395
2396 include_once DOL_DOCUMENT_ROOT.'/mailmanspip/class/mailmanspip.class.php';
2397 $mailmanspip = new MailmanSpip($this->db);
2398
2399 $err = 0;
2400
2401 // mailman
2402 if (getDolGlobalString('ADHERENT_USE_MAILMAN')) {
2403 $result = $mailmanspip->del_to_mailman($this);
2404 if ($result < 0) {
2405 if (!empty($mailmanspip->error)) {
2406 $this->errors[] = $mailmanspip->error;
2407 }
2408 $err += 1;
2409 }
2410
2411 foreach ($mailmanspip->mlremoved_ko as $tmplist => $tmpemail) {
2412 $langs->load("errors");
2413 $this->errors[] = $langs->trans("ErrorFailedToRemoveToMailmanList", $tmpemail, $tmplist);
2414 }
2415 foreach ($mailmanspip->mlremoved_ok as $tmplist => $tmpemail) {
2416 $langs->load("mailmanspip");
2417 $this->mesgs[] = $langs->trans("SuccessToRemoveToMailmanList", $tmpemail, $tmplist);
2418 }
2419 }
2420
2421 if (getDolGlobalString('ADHERENT_USE_SPIP') && isModEnabled('mailmanspip')) {
2422 $result = $mailmanspip->del_to_spip($this);
2423 if ($result < 0) {
2424 $this->errors[] = $mailmanspip->error;
2425 $err += 1;
2426 }
2427 }
2428 if ($err) {
2429 // error
2430 return -$err;
2431 } else {
2432 return 1;
2433 }
2434 }
2435
2436
2442 public function getCivilityLabel()
2443 {
2444 global $langs;
2445 $langs->load("dict");
2446
2447 $code = (empty($this->civility_id) ? '' : $this->civility_id);
2448 if (empty($code)) {
2449 return '';
2450 }
2451 return $langs->getLabelFromKey($this->db, "Civility".$code, "c_civility", "code", "label", $code);
2452 }
2453
2460 public function getTooltipContentArray($params)
2461 {
2462 global $langs;
2463
2464 $langs->loadLangs(['members', 'companies']);
2465 $nofetch = !empty($params['nofetch']);
2466
2467 $datas = array();
2468
2469 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
2470 $langs->load("users");
2471 return ['optimize' => $langs->trans("ShowUser")];
2472 }
2473 if (!empty($this->photo)) {
2474 $photo = '<div class="photointooltip floatright">';
2475 $photo .= Form::showphoto('memberphoto', $this, 80, 0, 0, 'photoref photowithmargin photologintooltip', 'small', 0, 1);
2476 $photo .= '</div>';
2477 $datas['photo'] = $photo;
2478 }
2479
2480 $datas['divopen'] = '<div class="centpercent">';
2481 $datas['picto'] = img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("Member").'</u> '.$this->getLibStatut(4);
2482 if (!empty($this->morphy)) {
2483 $datas['picto'] .= '&nbsp;' . $this->getmorphylib('', 1);
2484 }
2485 if (!empty($this->ref)) {
2486 $datas['ref'] = '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
2487 }
2488 if (!empty($this->login)) {
2489 $datas['login'] = '<br><b>'.$langs->trans('Login').':</b> '.$this->login;
2490 }
2491 if (!empty($this->firstname) || !empty($this->lastname)) {
2492 $datas['name'] = '<br><b>'.$langs->trans('Name').':</b> '.$this->getFullName($langs);
2493 }
2494 if (!empty($this->company)) {
2495 $datas['company'] = '<br><b>'.$langs->trans('Company').':</b> '.$this->company;
2496 }
2497 if (!empty($this->email)) {
2498 $datas['email'] = '<br><b>'.$langs->trans("EMail").':</b> '.$this->email;
2499 }
2500 $datas['address'] = '<br><b>'.$langs->trans("Address").':</b> '.dol_format_address($this, 1, ' ', $langs);
2501 // show categories for this record only in ajax to not overload lists
2502 if (isModEnabled('category') && !$nofetch) {
2503 require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
2504 $form = new Form($this->db);
2505 $datas['categories'] = '<br>' . $form->showCategories($this->id, Categorie::TYPE_MEMBER, 1);
2506 }
2507 $datas['divclose'] = '</div>';
2508
2509 return $datas;
2510 }
2511
2525 public function getNomUrl($withpictoimg = 0, $maxlen = 0, $option = 'card', $mode = '', $morecss = '', $save_lastsearch_value = -1, $notooltip = 0, $addlinktonotes = 0)
2526 {
2527 global $langs, $hookmanager;
2528
2529 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER') && $withpictoimg) {
2530 $withpictoimg = 0;
2531 }
2532
2533 $result = '';
2534 $linkstart = '';
2535 $linkend = '';
2536 $classfortooltip = 'classfortooltip';
2537 $dataparams = '';
2538 $params = [
2539 'id' => $this->id,
2540 'objecttype' => $this->element,
2541 'option' => $option,
2542 'nofetch' => 1,
2543 ];
2544 if (getDolGlobalInt('MAIN_ENABLE_AJAX_TOOLTIP')) {
2545 $classfortooltip = 'classforajaxtooltip';
2546 $dataparams = ' data-params="'.dol_escape_htmltag(json_encode($params)).'"';
2547 $label = '';
2548 } else {
2549 $label = implode($this->getTooltipContentArray($params));
2550 }
2551
2552 $baseurl = DOL_URL_ROOT . '/adherents/card.php';
2553 if ($option == 'subscription') {
2554 $baseurl = DOL_URL_ROOT . '/adherents/subscription.php';
2555 }
2556 $query = ['rowid' => $this->id];
2557
2558 if ($option != 'nolink') {
2559 // Add param to save lastsearch_values or not
2560 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
2561 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
2562 $add_save_lastsearch_values = 1;
2563 }
2564 if ($add_save_lastsearch_values) {
2565 $query = array_merge($query, ['save_lastsearch_values' => 1]);
2566 }
2567 }
2568 $url = dolBuildUrl($baseurl, $query);
2569
2570 $linkstart .= '<a href="'.$url.'"';
2571 $linkclose = "";
2572 if (empty($notooltip)) {
2573 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
2574 $langs->load("users");
2575 $label = $langs->trans("ShowUser");
2576 $linkclose .= ' alt="'.dolPrintHTMLForAttribute($label).'"';
2577 }
2578 $linkclose .= ($label ? ' title="'.dolPrintHTMLForAttribute($label).'"' : ' title="tocomplete"');
2579 $linkclose .= $dataparams.' class="'.$classfortooltip.($morecss ? ' '.$morecss : '').'"';
2580 }
2581
2582 $linkstart .= $linkclose.'>';
2583 $linkend = '</a>';
2584
2585 $result .= $linkstart;
2586
2587 if ($withpictoimg) {
2588 if (abs($withpictoimg) == 1 || abs($withpictoimg) == 4) {
2589 $morecss .= ' paddingrightonly';
2590 }
2591 // Only picto
2592 if ($withpictoimg > 0) {
2593 $picto = '<span class="nopadding'.($morecss ? ' userimg'.$morecss : '').'">'.img_object('', 'user', ' '.($notooltip ? '' : $dataparams), 0, 0, $notooltip ? 0 : 1).'</span>';
2594 } else {
2595 // Picto must be a photo
2596 $picto = '<span class="nopadding'.($morecss ? ' userimg'.$morecss : '').'">';
2597 $picto .= Form::showphoto('memberphoto', $this, 0, 0, 0, 'userphoto'.(($withpictoimg == -3 || $withpictoimg == -4) ? 'small' : ''), 'mini', 0, 1);
2598 $picto .= '</span>';
2599 }
2600 $result .= $picto;
2601 }
2602 if (($withpictoimg > -2 && $withpictoimg != 2) || $withpictoimg == -4) {
2603 if (!getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
2604 $result .= '<span class="nopadding valignmiddle'.((!isset($this->status) || $this->status) ? '' : ' strikefordisabled').
2605 ($morecss ? ' usertext'.$morecss : '').'">';
2606 }
2607 if ($mode == 'login') {
2608 $result .= dol_trunc(isset($this->login) ? $this->login : '', $maxlen);
2609 } elseif ($mode == 'ref') {
2610 $result .= $this->ref;
2611 } else {
2612 if (empty($this->lastname) && empty($this->firstname) && !empty($this->company)) {
2613 $result .= $this->company;
2614 } else {
2615 $result .= $this->getFullName($langs, 0, ($mode == 'firstname' ? 2 : ($mode == 'lastname' ? 4 : -1)), $maxlen);
2616 }
2617 }
2618 if (!getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
2619 $result .= '</span>';
2620 }
2621 }
2622
2623 $result .= $linkend;
2624
2625 if ($addlinktonotes) {
2626 if ($this->note_private) {
2627 $notetoshow = $langs->trans("ViewPrivateNote").':<br>'.dol_string_nohtmltag($this->note_private, 1);
2628 $result .= ' <span class="note inline-block">';
2629 $result .= '<a href="'.DOL_URL_ROOT.'/adherents/note.php?id='.$this->id.'" class="classfortooltip" title="'.dol_escape_htmltag($notetoshow).'">';
2630 $result .= img_picto('', 'note');
2631 $result .= '</a>';
2632 $result .= '</span>';
2633 }
2634 }
2635 global $action;
2636 $hookmanager->initHooks(array($this->element . 'dao'));
2637 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
2638 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
2639 if ($reshook > 0) {
2640 $result = $hookmanager->resPrint;
2641 } else {
2642 $result .= $hookmanager->resPrint;
2643 }
2644 return $result;
2645 }
2646
2653 public function getLibStatut($mode = 0)
2654 {
2655 return $this->LibStatut($this->status, $this->need_subscription, $this->datefin, $mode);
2656 }
2657
2658 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2668 public function LibStatut($status, $need_subscription, $date_end_subscription, $mode = 0)
2669 {
2670 // phpcs:enable
2671 global $langs;
2672 $langs->load("members");
2673
2674 $statusType = '';
2675 $labelStatus = '';
2676 $labelStatusShort = '';
2677
2678 if ($status == self::STATUS_DRAFT) {
2679 $statusType = 'status0';
2680 $labelStatus = $langs->trans("MemberStatusDraft");
2681 $labelStatusShort = $langs->trans("MemberStatusDraftShort");
2682 } elseif ($status >= self::STATUS_VALIDATED) {
2683 if ($need_subscription === 0) {
2684 $statusType = 'status4';
2685 $labelStatus = $langs->trans("Validated").' - '.$langs->trans("MemberStatusNoSubscription");
2686 $labelStatusShort = $langs->trans("MemberStatusNoSubscriptionShort");
2687 } elseif (!$date_end_subscription) {
2688 $statusType = 'status1';
2689 $labelStatus = $langs->trans("Validated").' - '.$langs->trans("WaitingSubscription");
2690 $labelStatusShort = $langs->trans("WaitingSubscriptionShort");
2691 } elseif ($date_end_subscription < dol_now()) { // expired
2692 $statusType = 'status2';
2693 $labelStatus = $langs->trans("Validated").' - '.$langs->trans("MemberStatusActiveLate");
2694 $labelStatusShort = $langs->trans("MemberStatusActiveLateShort");
2695 } else {
2696 $statusType = 'status4';
2697 $labelStatus = $langs->trans("Validated").' - '.$langs->trans("MemberStatusPaid");
2698 $labelStatusShort = $langs->trans("MemberStatusPaidShort");
2699 }
2700 } elseif ($status == self::STATUS_RESILIATED) {
2701 $statusType = 'status6';
2702 $labelStatus = $langs->transnoentitiesnoconv("MemberStatusResiliated");
2703 $labelStatusShort = $langs->transnoentitiesnoconv("MemberStatusResiliatedShort");
2704 } elseif ($status == self::STATUS_EXCLUDED) {
2705 $statusType = 'status10';
2706 $labelStatus = $langs->transnoentitiesnoconv("MemberStatusExcluded");
2707 $labelStatusShort = $langs->transnoentitiesnoconv("MemberStatusExcludedShort");
2708 }
2709
2710 return dolGetStatus($labelStatus, $labelStatusShort, '', $statusType, $mode);
2711 }
2712
2713
2719 public function loadStateBoard()
2720 {
2721 global $conf;
2722
2723 $this->nb = array();
2724
2725 $sql = "SELECT count(a.rowid) as nb";
2726 $sql .= " FROM ".MAIN_DB_PREFIX."adherent as a";
2727 $sql .= " WHERE a.statut > 0";
2728 $sql .= " AND a.entity IN (".getEntity('adherent').")";
2729
2730 $resql = $this->db->query($sql);
2731 if ($resql) {
2732 while ($obj = $this->db->fetch_object($resql)) {
2733 $this->nb["members"] = $obj->nb;
2734 }
2735 $this->db->free($resql);
2736 return 1;
2737 } else {
2738 dol_print_error($this->db);
2739 $this->error = $this->db->error();
2740 return -1;
2741 }
2742 }
2743
2744 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2752 public function load_board($user, $mode)
2753 {
2754 // phpcs:enable
2755 global $conf, $langs;
2756
2757 if ($user->socid) {
2758 return -1; // Protection to prevent calls by external users
2759 }
2760
2761 $now = dol_now();
2762
2763 $sql = "SELECT a.rowid, a.datefin, a.statut as status";
2764 $sql .= " FROM ".MAIN_DB_PREFIX."adherent as a";
2765 $sql .= ", ".MAIN_DB_PREFIX."adherent_type as t";
2766 $sql .= " WHERE a.fk_adherent_type = t.rowid";
2767 if ($mode == 'expired') {
2768 $sql .= " AND a.statut = ".self::STATUS_VALIDATED;
2769 $sql .= " AND a.entity IN (".getEntity('adherent').")";
2770 $sql .= " AND ((a.datefin IS NULL or a.datefin < '".$this->db->idate($now)."') AND t.subscription = '1')";
2771 } elseif ($mode == 'shift') {
2772 $sql .= " AND a.statut = ".self::STATUS_DRAFT;
2773 $sql .= " AND a.entity IN (".getEntity('adherent').")";
2774 }
2775
2776 $resql = $this->db->query($sql);
2777 if ($resql) {
2778 $langs->load("members");
2779
2780 $warning_delay = 0;
2781 $url = '';
2782 $label = '';
2783 $labelShort = '';
2784
2785 if ($mode == 'expired') {
2786 $warning_delay = getWarningDelay('member', 'subscription') / 60 / 60 / 24;
2787 $label = $langs->trans("MembersWithSubscriptionToReceive");
2788 $labelShort = $langs->trans("MembersWithSubscriptionToReceiveShort");
2789 $url = dolBuildUrl(DOL_URL_ROOT.'/adherents/list.php', ['mainmenu' => 'members', 'statut' => self::STATUS_VALIDATED, 'filter' => 'outofdate']);
2790 } elseif ($mode == 'shift') {
2791 $warning_delay = getWarningDelay('member', 'subscription') / 60 / 60 / 24;
2792 $url = dolBuildUrl(DOL_URL_ROOT.'/adherents/list.php', ['mainmenu' => 'members', 'statut' => self::STATUS_DRAFT]);
2793 $label = $langs->trans("MembersListToValid");
2794 $labelShort = $langs->trans("ToValidate");
2795 }
2796
2797 $response = new WorkboardResponse();
2798 $response->warning_delay = $warning_delay;
2799 $response->label = $label;
2800 $response->labelShort = $labelShort;
2801 $response->url = $url;
2802 $response->img = img_object('', "user");
2803
2804 $adherentstatic = new Adherent($this->db);
2805
2806 while ($obj = $this->db->fetch_object($resql)) {
2807 $response->nbtodo++;
2808
2809 $adherentstatic->datefin = $this->db->jdate($obj->datefin);
2810 $adherentstatic->statut = $obj->status;
2811 $adherentstatic->status = $obj->status;
2812
2813 if ($adherentstatic->hasDelay()) {
2814 $response->nbtodolate++;
2815 }
2816 }
2817
2818 return $response;
2819 } else {
2820 dol_print_error($this->db);
2821 $this->error = $this->db->error();
2822 return -1;
2823 }
2824 }
2825
2826
2838 public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
2839 {
2840 global $conf, $langs;
2841
2842 $langs->load("orders");
2843
2844 if (!dol_strlen($modele)) {
2845 $modele = 'standard';
2846
2847 if ($this->model_pdf) {
2848 $modele = $this->model_pdf;
2849 } elseif (getDolGlobalString('ADHERENT_ADDON_PDF')) {
2850 $modele = getDolGlobalString('ADHERENT_ADDON_PDF');
2851 }
2852 }
2853
2854 $modelpath = "core/modules/member/doc/";
2855
2856 return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
2857 }
2858
2859
2867 public function initAsSpecimen()
2868 {
2869 global $user, $langs;
2870 $now = dol_now();
2871
2872 // Initialise parameters
2873 $this->id = 0;
2874 $this->ref = 'ABC001';
2875 $this->entity = 1;
2876 $this->specimen = 1;
2877 $this->civility_id = 'MR';
2878 $this->lastname = 'DOLIBARR';
2879 $this->firstname = 'SPECIMEN';
2880 $this->gender = 'man';
2881 $this->login = 'dolibspec';
2882 $this->pass = 'dolibspec';
2883 $this->company = 'Societe ABC';
2884 $this->address = '61 jump street';
2885 $this->zip = '75000';
2886 $this->town = 'Paris';
2887 $this->country_id = 1;
2888 $this->country_code = 'FR';
2889 $this->country = 'France';
2890 $this->morphy = 'mor';
2891 $this->email = 'specimen@specimen.com';
2892 $this->socialnetworks = array(
2893 'skype' => 'skypepseudo',
2894 'twitter' => 'twitterpseudo',
2895 'facebook' => 'facebookpseudo',
2896 'linkedin' => 'linkedinpseudo',
2897 );
2898 $this->phone = '0999999999';
2899 $this->phone_perso = '0999999998';
2900 $this->phone_mobile = '0999999997';
2901 $this->note_public = 'This is a public note';
2902 $this->note_private = 'This is a private note';
2903 $this->birth = $now;
2904 $this->photo = '';
2905 $this->public = 1;
2906 $this->statut = self::STATUS_DRAFT;
2907 $this->status = self::STATUS_DRAFT;
2908
2909 $this->datefin = $now;
2910 $this->datevalid = $now;
2911 $this->default_lang = '';
2912
2913 $this->typeid = 1; // Id type adherent
2914 $this->type = 'Type adherent'; // Libelle type adherent
2915 $this->need_subscription = 0;
2916
2917 $this->first_subscription_date = $now;
2918 $this->first_subscription_date_start = $this->first_subscription_date;
2919 $this->first_subscription_date_end = dol_time_plus_duree($this->first_subscription_date_start, 1, 'y');
2920 $this->first_subscription_amount = 10;
2921
2922 $this->last_subscription_date = $this->first_subscription_date;
2923 $this->last_subscription_date_start = $this->first_subscription_date;
2924 $this->last_subscription_date_end = dol_time_plus_duree($this->last_subscription_date_start, 1, 'y');
2925 $this->last_subscription_amount = 10;
2926 return 1;
2927 }
2928
2929
2930 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2931 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
2941 public function _load_ldap_dn($info, $mode = 0)
2942 {
2943 // phpcs:enable
2944 global $conf;
2945 $dn = '';
2946 if ($mode == 0) {
2947 $dn = getDolGlobalString('LDAP_KEY_MEMBERS') . "=".$info[getDolGlobalString('LDAP_KEY_MEMBERS')]."," . getDolGlobalString('LDAP_MEMBER_DN');
2948 }
2949 if ($mode == 1) {
2950 $dn = getDolGlobalString('LDAP_MEMBER_DN');
2951 }
2952 if ($mode == 2) {
2953 $dn = getDolGlobalString('LDAP_KEY_MEMBERS') . "=".$info[getDolGlobalString('LDAP_KEY_MEMBERS')];
2954 }
2955 return $dn;
2956 }
2957
2958
2959 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2960 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
2966 public function _load_ldap_info()
2967 {
2968 // phpcs:enable
2969 global $conf, $langs;
2970
2971 $info = array();
2972 $socialnetworks = getArrayOfSocialNetworks();
2973 $keymodified = false;
2974
2975 // Object classes
2976 $info["objectclass"] = explode(',', getDolGlobalString('LDAP_MEMBER_OBJECT_CLASS'));
2977
2978 $this->fullname = $this->getFullName($langs);
2979
2980 // For avoid ldap error when firstname and lastname are empty
2981 if ($this->morphy == 'mor' && (empty($this->fullname) || $this->fullname == $this->company)) {
2982 $this->fullname = $this->company;
2983 $this->lastname = $this->company;
2984 }
2985
2986 // Possible LDAP KEY (constname => varname)
2987 $ldapkey = array(
2988 'LDAP_MEMBER_FIELD_FULLNAME' => 'fullname',
2989 'LDAP_MEMBER_FIELD_NAME' => 'lastname',
2990 'LDAP_MEMBER_FIELD_LOGIN' => 'login',
2991 'LDAP_MEMBER_FIELD_LOGIN_SAMBA' => 'login',
2992 'LDAP_MEMBER_FIELD_MAIL' => 'email'
2993 );
2994
2995 // Member
2996 foreach ($ldapkey as $constname => $varname) {
2997 if (!empty($this->$varname) && getDolGlobalString($constname)) {
2998 $info[getDolGlobalString($constname)] = $this->$varname;
2999
3000 // Check if it is the LDAP key and if its value has been changed
3001 if (getDolGlobalString('LDAP_KEY_MEMBERS') && getDolGlobalString('LDAP_KEY_MEMBERS') == getDolGlobalString($constname)) {
3002 if (!empty($this->oldcopy) && $this->$varname != $this->oldcopy->$varname) {
3003 $keymodified = true; // For check if LDAP key has been modified
3004 }
3005 }
3006 }
3007 }
3008 if ($this->firstname && getDolGlobalString('LDAP_MEMBER_FIELD_FIRSTNAME')) {
3009 $info[getDolGlobalString('LDAP_MEMBER_FIELD_FIRSTNAME')] = $this->firstname;
3010 }
3011 if ($this->poste && getDolGlobalString('LDAP_MEMBER_FIELD_TITLE')) {
3012 $info[getDolGlobalString('LDAP_MEMBER_FIELD_TITLE')] = $this->poste;
3013 }
3014 if ($this->company && getDolGlobalString('LDAP_MEMBER_FIELD_COMPANY')) {
3015 $info[getDolGlobalString('LDAP_MEMBER_FIELD_COMPANY')] = $this->company;
3016 }
3017 if ($this->address && getDolGlobalString('LDAP_MEMBER_FIELD_ADDRESS')) {
3018 $info[getDolGlobalString('LDAP_MEMBER_FIELD_ADDRESS')] = $this->address;
3019 }
3020 if ($this->zip && getDolGlobalString('LDAP_MEMBER_FIELD_ZIP')) {
3021 $info[getDolGlobalString('LDAP_MEMBER_FIELD_ZIP')] = $this->zip;
3022 }
3023 if ($this->town && getDolGlobalString('LDAP_MEMBER_FIELD_TOWN')) {
3024 $info[getDolGlobalString('LDAP_MEMBER_FIELD_TOWN')] = $this->town;
3025 }
3026 if ($this->country_code && getDolGlobalString('LDAP_MEMBER_FIELD_COUNTRY')) {
3027 $info[getDolGlobalString('LDAP_MEMBER_FIELD_COUNTRY')] = $this->country_code;
3028 }
3029 foreach ($socialnetworks as $key => $value) {
3030 if ($this->socialnetworks[$value['label']] && getDolGlobalString('LDAP_MEMBER_FIELD_'.strtoupper($value['label']))) {
3031 $info[getDolGlobalString('LDAP_MEMBER_FIELD_'.strtoupper($value['label']))] = $this->socialnetworks[$value['label']];
3032 }
3033 }
3034 if ($this->phone && getDolGlobalString('LDAP_MEMBER_FIELD_PHONE')) {
3035 $info[getDolGlobalString('LDAP_MEMBER_FIELD_PHONE')] = $this->phone;
3036 }
3037 if ($this->phone_perso && getDolGlobalString('LDAP_MEMBER_FIELD_PHONE_PERSO')) {
3038 $info[getDolGlobalString('LDAP_MEMBER_FIELD_PHONE_PERSO')] = $this->phone_perso;
3039 }
3040 if ($this->phone_mobile && getDolGlobalString('LDAP_MEMBER_FIELD_MOBILE')) {
3041 $info[getDolGlobalString('LDAP_MEMBER_FIELD_MOBILE')] = $this->phone_mobile;
3042 }
3043 if ($this->fax && getDolGlobalString('LDAP_MEMBER_FIELD_FAX')) {
3044 $info[getDolGlobalString('LDAP_MEMBER_FIELD_FAX')] = $this->fax;
3045 }
3046 if ($this->note_private && getDolGlobalString('LDAP_MEMBER_FIELD_DESCRIPTION')) {
3047 $info[getDolGlobalString('LDAP_MEMBER_FIELD_DESCRIPTION')] = dol_string_nohtmltag($this->note_private, 2);
3048 }
3049 if ($this->note_public && getDolGlobalString('LDAP_MEMBER_FIELD_NOTE_PUBLIC')) {
3050 $info[getDolGlobalString('LDAP_MEMBER_FIELD_NOTE_PUBLIC')] = dol_string_nohtmltag($this->note_public, 2);
3051 }
3052 if ($this->birth && getDolGlobalString('LDAP_MEMBER_FIELD_BIRTHDATE')) {
3053 $info[getDolGlobalString('LDAP_MEMBER_FIELD_BIRTHDATE')] = dol_print_date($this->birth, 'dayhourldap');
3054 }
3055 if (isset($this->statut) && getDolGlobalString('LDAP_FIELD_MEMBER_STATUS')) {
3056 $info[getDolGlobalString('LDAP_FIELD_MEMBER_STATUS')] = $this->statut;
3057 }
3058 if ($this->datefin && getDolGlobalString('LDAP_FIELD_MEMBER_END_LASTSUBSCRIPTION')) {
3059 $info[getDolGlobalString('LDAP_FIELD_MEMBER_END_LASTSUBSCRIPTION')] = dol_print_date($this->datefin, 'dayhourldap');
3060 }
3061
3062 // When password is modified
3063 if (!empty($this->pass)) {
3064 if (getDolGlobalString('LDAP_MEMBER_FIELD_PASSWORD')) {
3065 $info[getDolGlobalString('LDAP_MEMBER_FIELD_PASSWORD')] = $this->pass; // this->pass = Unencrypted password
3066 }
3067 if (getDolGlobalString('LDAP_MEMBER_FIELD_PASSWORD_CRYPTED')) {
3068 $info[getDolGlobalString('LDAP_MEMBER_FIELD_PASSWORD_CRYPTED')] = dol_hash($this->pass, 'openldap'); // Create OpenLDAP password (see LDAP_PASSWORD_HASH_TYPE)
3069 }
3070 } elseif (getDolGlobalString('LDAP_SERVER_PROTOCOLVERSION') !== '3') {
3071 // Set LDAP password if possible
3072 // If ldap key is modified and LDAPv3 we use ldap_rename function for avoid lose encrypt password
3073 if (getDolGlobalString('DATABASE_PWD_ENCRYPTED')) { // This should be on on default installation
3074 // Just for the case we use old md5 encryption (deprecated, no more used, kept for compatibility)
3075 if (!getDolGlobalString('MAIN_SECURITY_HASH_ALGO') || getDolGlobalString('MAIN_SECURITY_HASH_ALGO') == 'md5') {
3076 if ($this->pass_indatabase_crypted && getDolGlobalString('LDAP_MEMBER_FIELD_PASSWORD_CRYPTED')) {
3077 // Create OpenLDAP MD5 password from Dolibarr MD5 password
3078 // Note: This suppose that "pass_indatabase_crypted" is a md5 (this should not happen anymore)"
3079 $info[getDolGlobalString('LDAP_MEMBER_FIELD_PASSWORD_CRYPTED')] = dolGetLdapPasswordHash($this->pass_indatabase_crypted, 'md5frommd5');
3080 }
3081 }
3082 } elseif (!empty($this->pass_indatabase)) {
3083 // Use $this->pass_indatabase value if exists
3084 if (getDolGlobalString('LDAP_MEMBER_FIELD_PASSWORD')) {
3085 $info[getDolGlobalString('LDAP_MEMBER_FIELD_PASSWORD')] = $this->pass_indatabase; // $this->pass_indatabase = Unencrypted password
3086 }
3087 if (getDolGlobalString('LDAP_MEMBER_FIELD_PASSWORD_CRYPTED')) {
3088 $info[getDolGlobalString('LDAP_MEMBER_FIELD_PASSWORD_CRYPTED')] = dol_hash($this->pass_indatabase, 'openldap'); // Create OpenLDAP password (see LDAP_PASSWORD_HASH_TYPE)
3089 }
3090 }
3091 }
3092
3093 // Subscriptions
3094 if ($this->first_subscription_date && getDolGlobalString('LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_DATE')) {
3095 $info[getDolGlobalString('LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_DATE')] = dol_print_date($this->first_subscription_date, 'dayhourldap');
3096 }
3097 if (isset($this->first_subscription_amount) && getDolGlobalString('LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_AMOUNT')) {
3098 $info[getDolGlobalString('LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_AMOUNT')] = $this->first_subscription_amount;
3099 }
3100 if ($this->last_subscription_date && getDolGlobalString('LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_DATE')) {
3101 $info[getDolGlobalString('LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_DATE')] = dol_print_date($this->last_subscription_date, 'dayhourldap');
3102 }
3103 if (isset($this->last_subscription_amount) && getDolGlobalString('LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_AMOUNT')) {
3104 $info[getDolGlobalString('LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_AMOUNT')] = $this->last_subscription_amount;
3105 }
3106
3107 return $info;
3108 }
3109
3110
3117 public function info($id)
3118 {
3119 $sql = 'SELECT a.rowid, a.datec as datec,';
3120 $sql .= ' a.datevalid as datev,';
3121 $sql .= ' GREATEST(a.tms, aef.tms) as datem,';
3122 $sql .= ' a.fk_user_author, a.fk_user_valid, a.fk_user_mod';
3123 $sql .= ' FROM '.MAIN_DB_PREFIX.'adherent as a';
3124 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'adherent_extrafields as aef ON aef.fk_object = a.rowid';
3125 $sql .= ' WHERE a.rowid = '.((int) $id);
3126
3127 dol_syslog(get_class($this)."::info", LOG_DEBUG);
3128 $result = $this->db->query($sql);
3129 if ($result) {
3130 if ($this->db->num_rows($result)) {
3131 $obj = $this->db->fetch_object($result);
3132
3133 $this->id = $obj->rowid;
3134
3135 $this->user_creation_id = $obj->fk_user_author;
3136 $this->user_validation_id = $obj->fk_user_valid;
3137 $this->user_modification_id = $obj->fk_user_mod;
3138 $this->date_creation = $this->db->jdate($obj->datec);
3139 $this->date_validation = $this->db->jdate($obj->datev);
3140 $this->date_modification = $this->db->jdate($obj->datem);
3141 }
3142
3143 $this->db->free($result);
3144 } else {
3145 dol_print_error($this->db);
3146 }
3147 }
3148
3154 public function getNbOfEMailings()
3155 {
3156 $sql = "SELECT count(mc.email) as nb";
3157 $sql .= " FROM ".MAIN_DB_PREFIX."mailing_cibles as mc";
3158 $sql .= " WHERE mc.email = '".$this->db->escape($this->email)."'";
3159 $sql .= " AND mc.statut NOT IN (-1,0)"; // -1 error, 0 not sent, 1 sent with success
3160
3161 $resql = $this->db->query($sql);
3162 if ($resql) {
3163 $obj = $this->db->fetch_object($resql);
3164 $nb = (int) $obj->nb;
3165
3166 $this->db->free($resql);
3167 return $nb;
3168 } else {
3169 $this->error = $this->db->error();
3170 return -1;
3171 }
3172 }
3173
3184 public function setCategories($categories)
3185 {
3186 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
3187 return parent::setCategoriesCommon($categories, Categorie::TYPE_MEMBER);
3188 }
3189
3198 public static function replaceThirdparty($db, $origin_id, $dest_id)
3199 {
3200 $tables = array('adherent');
3201
3202 return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
3203 }
3204
3210 public function hasDelay()
3211 {
3212 global $conf;
3213
3214 //Only valid members
3215 if ($this->status != self::STATUS_VALIDATED) {
3216 return false;
3217 }
3218 if (!$this->datefin) {
3219 return false;
3220 }
3221
3222 $now = dol_now();
3223
3224 return $this->datefin < ($now - getWarningDelay('member', 'subscription'));
3225 }
3226
3227
3236 public function sendReminderForExpiredSubscription($daysbeforeendlist = '10', $fk_adherent_type = 0)
3237 {
3238 global $conf, $langs, $mysoc, $user;
3239
3240 $error = 0;
3241 $this->output = '';
3242 $this->error = '';
3243
3244 $blockingerrormsg = '';
3245
3246 if (!isModEnabled('member')) { // Should not happen. If module disabled, cron job should not be visible.
3247 $langs->load("agenda");
3248 $this->output = $langs->trans('ModuleNotEnabled', $langs->transnoentitiesnoconv("Adherent"));
3249 return 0;
3250 }
3251 if (!getDolGlobalString('MEMBER_REMINDER_EMAIL')) {
3252 $langs->load("agenda");
3253 $this->output = $langs->trans('EventRemindersByEmailNotEnabled', $langs->transnoentitiesnoconv("Adherent"));
3254 return 0;
3255 }
3256
3257 $now = dol_now();
3258 $nbok = 0;
3259 $nbko = 0;
3260
3261 $listofmembersok = array();
3262 $listofmembersko = array();
3263
3264 $arraydaysbeforeend = explode(';', $daysbeforeendlist);
3265 foreach ($arraydaysbeforeend as $daysbeforeend) { // Loop on each delay
3266 dol_syslog(__METHOD__.' - Process delta = '.$daysbeforeend, LOG_DEBUG);
3267
3268 if (!is_numeric($daysbeforeend)) {
3269 $blockingerrormsg = "Value for delta is not a numeric value";
3270 $nbko++;
3271 break;
3272 }
3273
3274 $tmp = dol_getdate($now);
3275 $datetosearchfor = dol_time_plus_duree(dol_mktime(0, 0, 0, $tmp['mon'], $tmp['mday'], $tmp['year'], 'tzserver'), (int) $daysbeforeend, 'd');
3276 $datetosearchforend = dol_time_plus_duree(dol_mktime(23, 59, 59, $tmp['mon'], $tmp['mday'], $tmp['year'], 'tzserver'), (int) $daysbeforeend, 'd');
3277
3278 $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'adherent';
3279 $sql .= " WHERE entity = ".((int) $conf->entity); // Do not use getEntity('adherent').")" here, we want the batch to be on its entity only;
3280 $sql .= " AND statut = 1";
3281 $sql .= " AND datefin >= '".$this->db->idate($datetosearchfor)."'";
3282 $sql .= " AND datefin <= '".$this->db->idate($datetosearchforend)."'";
3283 if ((int) $fk_adherent_type > 0) {
3284 $sql .= " AND fk_adherent_type = ".((int) $fk_adherent_type);
3285 }
3286 //$sql .= " LIMIT 10000";
3287
3288 $resql = $this->db->query($sql);
3289 if ($resql) {
3290 $num_rows = $this->db->num_rows($resql);
3291
3292 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
3293 $adherent = new Adherent($this->db);
3294 $formmail = new FormMail($this->db);
3295
3296 $i = 0;
3297 while ($i < $num_rows) {
3298 $obj = $this->db->fetch_object($resql);
3299
3300 $adherent->fetch($obj->rowid, '', 0, '', true, true);
3301
3302 if (empty($adherent->email)) {
3303 $nbko++;
3304 $listofmembersko[$adherent->id] = $adherent->id;
3305 } else {
3306 $thirdpartyres = $adherent->fetch_thirdparty();
3307 if ($thirdpartyres === -1) {
3308 $languagecodeformember = $mysoc->default_lang;
3309 } else {
3310 // 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.
3311 $languagefromcountrycode = getLanguageCodeFromCountryCode($adherent->country_code ? $adherent->country_code : $adherent->thirdparty->country_code);
3312 $languagecodeformember = (empty($adherent->thirdparty->default_lang) ? ($languagefromcountrycode ? $languagefromcountrycode : $mysoc->default_lang) : $adherent->thirdparty->default_lang);
3313 }
3314
3315 // Send reminder email
3316 $outputlangs = new Translate('', $conf);
3317 $outputlangs->setDefaultLang($languagecodeformember);
3318 $outputlangs->loadLangs(array("main", "members"));
3319 dol_syslog("sendReminderForExpiredSubscription Language for member id ".$adherent->id." set to ".$outputlangs->defaultlang." mysoc->default_lang=".$mysoc->default_lang);
3320
3321 $arraydefaultmessage = null;
3322 $labeltouse = getDolGlobalString('ADHERENT_EMAIL_TEMPLATE_REMIND_EXPIRATION');
3323
3324 if (!empty($labeltouse)) {
3325 $arraydefaultmessage = $formmail->getEMailTemplate($this->db, 'member', $user, $outputlangs, 0, 1, $labeltouse);
3326 }
3327
3328 if (!empty($labeltouse) && is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) {
3329 $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $adherent);
3330 //if (is_array($adherent->thirdparty)) $substitutionarraycomp = ...
3331 complete_substitutions_array($substitutionarray, $outputlangs, $adherent);
3332
3333 $subject = make_substitutions($arraydefaultmessage->topic, $substitutionarray, $outputlangs);
3334 $msg = make_substitutions($arraydefaultmessage->content, $substitutionarray, $outputlangs);
3335 $email_from = getDolGlobalString('ADHERENT_MAIL_FROM', $conf->email_from);
3336 $to = $adherent->email;
3337 $cc = getDolGlobalString('ADHERENT_CC_MAIL_FROM');
3338
3339 $trackid = 'mem'.$adherent->id;
3340 $moreinheader = 'X-Dolibarr-Info: sendReminderForExpiredSubscription'."\r\n";
3341
3342 include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
3343 $cmail = new CMailFile($subject, $to, $email_from, $msg, array(), array(), array(), $cc, '', 0, 1, '', '', $trackid, $moreinheader);
3344 $result = $cmail->sendfile();
3345 if (!$result) {
3346 $error++;
3347 $this->error .= $cmail->error.' ';
3348 if (!is_null($cmail->errors)) {
3349 $this->errors += $cmail->errors;
3350 }
3351 $nbko++;
3352 $listofmembersko[$adherent->id] = $adherent->id;
3353 } else {
3354 $nbok++;
3355 $listofmembersok[$adherent->id] = $adherent->id;
3356
3357 $message = $msg;
3358 $sendto = $to;
3359 $sendtocc = '';
3360 $sendtobcc = '';
3361 $actioncode = 'EMAIL';
3362 $extraparams = array();
3363
3364 $actionmsg = '';
3365 $actionmsg2 = $langs->transnoentities('MailSentByTo', CMailFile::getValidAddress($email_from, 4, 0, 1), CMailFile::getValidAddress($sendto, 4, 0, 1));
3366 if ($message) {
3367 $actionmsg = $langs->transnoentities('MailFrom').': '.dol_escape_htmltag($email_from);
3368 $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTo').': '.dol_escape_htmltag($sendto));
3369 // if ($sendtocc) {
3370 // $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('Bcc').": ".dol_escape_htmltag($sendtocc));
3371 // }
3372 $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTopic').": ".$subject);
3373 $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('TextUsedInTheMessageBody').":");
3374 $actionmsg = dol_concatdesc($actionmsg, $message);
3375 }
3376
3377 require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
3378
3379 // Insert record of emails sent
3380 $actioncomm = new ActionComm($this->db);
3381
3382 $actioncomm->type_code = 'AC_OTH_AUTO'; // Type of event ('AC_OTH', 'AC_OTH_AUTO', 'AC_XXX'...)
3383 $actioncomm->code = 'AC_'.$actioncode;
3384 $actioncomm->label = $actionmsg2;
3385 $actioncomm->note_private = $actionmsg;
3386 $actioncomm->fk_project = 0;
3387 $actioncomm->datep = $now;
3388 $actioncomm->datef = $now;
3389 $actioncomm->percentage = -1; // Not applicable
3390 $actioncomm->socid = $adherent->thirdparty->id;
3391 $actioncomm->contact_id = 0;
3392 $actioncomm->authorid = $user->id; // User saving action
3393 $actioncomm->userownerid = $user->id; // Owner of action
3394 // Fields when action is an email (content should be added into note)
3395 $actioncomm->email_msgid = $cmail->msgid;
3396 $actioncomm->email_from = $email_from;
3397 $actioncomm->email_sender = '';
3398 $actioncomm->email_to = $to;
3399 $actioncomm->email_tocc = $sendtocc;
3400 $actioncomm->email_tobcc = $sendtobcc;
3401 $actioncomm->email_subject = $subject;
3402 $actioncomm->errors_to = '';
3403
3404 $actioncomm->fk_element = $adherent->id;
3405 $actioncomm->elementid = $adherent->id;
3406 $actioncomm->elementtype = $adherent->element;
3407
3408 $actioncomm->extraparams = $extraparams;
3409
3410 $actioncomm->create($user);
3411 }
3412 } else {
3413 //$blockingerrormsg = "Can't find email template with label=".$labeltouse.", to use for the reminding email";
3414
3415 $error++;
3416 $this->error .= "Can't find email template with label=".$labeltouse.", to use for the reminding email ";
3417
3418 $nbko++;
3419 $listofmembersko[$adherent->id] = $adherent->id;
3420
3421 break;
3422 }
3423 }
3424
3425 $i++;
3426 }
3427 } else {
3428 $this->error = $this->db->lasterror();
3429 return 1;
3430 }
3431 }
3432
3433 if ($blockingerrormsg) {
3434 $this->error = $blockingerrormsg;
3435 return 1;
3436 } else {
3437 $this->output = 'Found '.($nbok + $nbko).' members to send reminder to.';
3438 $this->output .= ' Send email successfully to '.$nbok.' members';
3439 $listofids = '';
3440 $i = 0;
3441 foreach ($listofmembersok as $idmember) {
3442 if ($i > 100) {
3443 $listofids .= ', ...';
3444 break;
3445 }
3446 if (empty($listofids)) {
3447 $listofids .= ' [';
3448 } else {
3449 $listofids .= ', ';
3450 }
3451 $listofids .= $idmember;
3452 $i++;
3453 }
3454 if ($listofids) {
3455 $listofids .= ']';
3456 }
3457 $this->output .= ($listofids ? ' ids='.$listofids : '');
3458
3459 if ($nbko) {
3460 $this->output .= ' - Canceled for '.$nbko.' member (no email or email sending error)';
3461 $listofids = '';
3462 $i = 0;
3463 foreach ($listofmembersko as $idmember) {
3464 if ($i > 100) {
3465 $listofids .= ', ...';
3466 break;
3467 }
3468 if (empty($listofids)) {
3469 $listofids .= ' [';
3470 } else {
3471 $listofids .= ', ';
3472 }
3473 $listofids .= $idmember;
3474 $i++;
3475 }
3476 if ($listofids) {
3477 $listofids .= ']';
3478 }
3479 $this->output .= ($listofids ? ' ids='.$listofids : '');
3480 }
3481 }
3482
3483 return $nbko;
3484 }
3485
3493 public function getKanbanView($option = '', $arraydata = null)
3494 {
3495 $selected = (empty($arraydata['selected']) ? 0 : $arraydata['selected']);
3496
3497 $return = '<div class="box-flex-item box-flex-grow-zero">';
3498 $return .= '<div class="info-box info-box-sm">';
3499 $return .= '<span class="info-box-icon bg-infobox-action">';
3500 if (!empty($this->photo)) {
3501 $return .= Form::showphoto('memberphoto', $this, 0, 60, 0, 'photokanban photowithmargin photologintooltip', 'small', 0, 1);
3502 } else {
3503 $return .= img_picto('', 'user');
3504 }
3505 $return .= '</span>';
3506 $return .= '<div class="info-box-content">';
3507 $return .= '<span class="info-box-ref inline-block tdoverflowmax150 valignmiddle">' . $this->getNomUrl() . '</span>';
3508 if ($selected >= 0) {
3509 $return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
3510 }
3511 $return .= '<br><span class="info-box-label paddingright">'.$this->getmorphylib('', 2).'</span>';
3512 $return .= '<span class="info-box-label opacitymedium">'.$this->type.'</span>';
3513
3514 $return .= '<br><div class="info-box-status paddingtop">';
3515 $return .= $this->LibStatut($this->status, $this->need_subscription, $this->datefin, 5);
3516 $return .= '</div>';
3517 $return .= '</div>';
3518 $return .= '</div>';
3519 $return .= '</div>';
3520 return $return;
3521 }
3522}
$object ref
Definition info.php:90
Class to manage bank accounts.
Class to manage agenda events (actions)
Class to manage members of a foundation.
mergeMembers($member_origin_id)
Merge a member with current one, deleting the given company $member_origin_id.
setThirdPartyId($thirdpartyid)
Set link to a third party.
hasDelay()
Return if a member is late (subscription late) or not.
exclude($user)
Functiun to exclude (set adherent.status to -2) a member TODO A private note should be added to know ...
add_to_abo()
Function to add member into external tools mailing-list, spip, etc.
loadStateBoard()
Load indicators this->nb in state board.
_load_ldap_dn($info, $mode=0)
Returns the complete DN (Distinguished Name) string in the LDAP directory for the object.
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)
Function that terminates a member.
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.
$fields
'type' field format: 'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortf...
getKanbanView($option='', $arraydata=null)
Return clickable link of object (with eventually picto)
const STATUS_DRAFT
Draft status.
const STATUS_RESILIATED
Resiliated (membership end and was not renew)
sendReminderForExpiredSubscription($daysbeforeendlist='10', $fk_adherent_type=0)
Send reminders by emails before subscription end CAN BE A CRON TASK.
fetch_login($login)
Method to load member from its login.
_load_ldap_info()
Initialise tableau info (tableau des attributes 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.
subscription($date, $amount, $accountid=0, $operation='', $label='', $num_chq='', $emetteur_nom='', $emetteur_banque='', $datesubend=0, $fk_type=null, $ref_ext='')
Insert subscription into database and eventually add links to banks, mailman, etc....
__construct($db)
Constructor.
validate($user, $notrigger=0)
Function that validate a member.
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 clickable 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.
const STATUS_VALIDATED
Validated status.
fetch_subscriptions()
Function to get member subscriptions data: subscriptions, first_subscription_date,...
fetch($rowid, $ref='', $socid=0, $ref_ext='', $fetch_optionals=true, $fetch_subscriptions=true)
Load member from database.
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.
Class to manage categories.
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.
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, $usesharelinkifavailable=0)
Return HTML code to output a photo.
Class to manage a HTML form to send a unitary email Usage: $formail = new FormMail($db) $formmail->pr...
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.
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition index.php:169
getFullName($langs, $option=0, $nameorder=-1, $maxlen=0)
Return full name (civility+' '+name+' '+lastname)
setUpperOrLowerCase()
Set to upper or ucwords/lower if needed.
getCountry($searchkey, $withcode='', $dbtouse=null, $outputlangs=null, $entconv=1, $searchlabel='')
Return country label, code or id from an id, code or label.
global $mysoc
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition date.lib.php:126
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as p label as s rowid as s nom as s email
Sender: Who sends the email ("Sender" has sent emails on behalf of "From").
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
dol_move($srcfile, $destfile, $newmask='0', $overwriteifexists=1, $testvirus=0, $indexdatabase=1, $moreinfo=array(), $entity=null)
Move a file into another name.
dol_dir_list($utf8_path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition files.lib.php:65
dol_is_dir($folder)
Test if filename is a directory.
clean_url($url, $http=1)
Clean an url string.
dol_now($mode='gmt')
Return date for now.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='', $useCache=true)
Return an id or code from a code or id.
getLanguageCodeFromCountryCode($countrycode)
Return default language from country code.
setEntity($currentobject)
Set entity id to use when to create an object.
dol_format_address($object, $withcountry=0, $sep="\n", $outputlangs=null, $mode=0, $extralangcode='')
Return a formatted address (part address/zip/town/state) according to country rules.
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 '.
dolBuildUrl($url, $params=[], $addtoken=false, $anchor='')
Return path of url.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
GETPOSTISARRAY($paramname, $method=0)
Return true if the parameter $paramname is submit from a POST OR GET as an array.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
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...
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.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
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...
isValidEmail($address, $acceptsupervisorkey=0, $acceptuserkey=0)
Return true if email syntax is ok.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
getWarningDelay($module, $parmlevel1, $parmlevel2='')
Return a warning delay You can use it like this: if (getWarningDelay('module', 'paramlevel1')) It rep...
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.
div refaddress div address
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
yn($yesno, $format=1, $color=0)
Return yes or no in current language.
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
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...
Definition html.lib.php:172
if(preg_match('/(crypted|dolcrypt):/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...
Definition repair.php:130
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', $nosalt=0, $mode=0)
Returns a hash (non reversible encryption) of a string.