Passed
Branch develop (07a336)
by
unknown
39:19
created

Adherent::send_an_email()   A

Complexity

Conditions 6
Paths 24

Size

Total Lines 31
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 18
c 0
b 0
f 0
nc 24
nop 11
dl 0
loc 31
rs 9.0444

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/* Copyright (C) 2002-2003	Rodolphe Quiedeville	<[email protected]>
3
 * Copyright (C) 2002-2003	Jean-Louis Bergamo		<[email protected]>
4
 * Copyright (C) 2004-2012	Laurent Destailleur		<[email protected]>
5
 * Copyright (C) 2004		Sebastien Di Cintio		<[email protected]>
6
 * Copyright (C) 2004		Benoit Mortier			<[email protected]>
7
 * Copyright (C) 2009-2017	Regis Houssin			<[email protected]>
8
 * Copyright (C) 2014-2018	Alexandre Spangaro		<[email protected]>
9
 * Copyright (C) 2015		Marcos García			<[email protected]>
10
 * Copyright (C) 2015-2020	Frédéric France			<[email protected]>
11
 * Copyright (C) 2015		Raphaël Doursenaud		<[email protected]>
12
 * Copyright (C) 2016		Juanjo Menent			<[email protected]>
13
 * Copyright (C) 2018-2019	Thibault FOUCART		<[email protected]>
14
 * Copyright (C) 2019		Nicolas ZABOURI 		<[email protected]>
15
 * Copyright (C) 2020		Josep Lluís Amador 		<[email protected]>
16
 *
17
 * This program is free software; you can redistribute it and/or modify
18
 * it under the terms of the GNU General Public License as published by
19
 * the Free Software Foundation; either version 3 of the License, or
20
 * (at your option) any later version.
21
 *
22
 * This program is distributed in the hope that it will be useful,
23
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25
 * GNU General Public License for more details.
26
 *
27
 * You should have received a copy of the GNU General Public License
28
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
29
 */
30
31
/**
32
 *	\file       htdocs/adherents/class/adherent.class.php
33
 *	\ingroup    member
34
 *	\brief      File of class to manage members of a foundation
35
 */
36
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
37
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
38
require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
39
40
41
/**
42
 *		Class to manage members of a foundation
43
 */
44
class Adherent extends CommonObject
45
{
46
47
	/**
48
	 * @var string ID to identify managed object
49
	 */
50
	public $element = 'member';
51
52
	/**
53
	 * @var string Name of table without prefix where object is stored
54
	 */
55
	public $table_element = 'adherent';
56
57
	/**
58
	 * 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
59
	 * @var int
60
	 */
61
	public $ismultientitymanaged = 1;
62
63
	/**
64
	 * @var string picto
65
	 */
66
	public $picto = 'member';
67
68
69
	public $mesgs;
70
71
	/**
72
	 * @var string login of member
73
	 */
74
	public $login;
75
76
	/**
77
	 * @var string Clear password in memory
78
	 */
79
	public $pass;
80
81
	/**
82
	 * @var string Clear password in database (defined if DATABASE_PWD_ENCRYPTED=0)
83
	 */
84
	public $pass_indatabase;
85
86
	/**
87
	 * @var string Encrypted password in database (always defined)
88
	 */
89
	public $pass_indatabase_crypted;
90
91
	/**
92
	 * @var string company name
93
	 * @deprecated
94
	 */
95
	public $societe;
96
97
	/**
98
	 * @var string company name
99
	 */
100
	public $company;
101
102
	/**
103
	 * @var int Thirdparty ID
104
	 */
105
	public $fk_soc;
106
	public $socid;
107
108
	/**
109
	 * @var string Address
110
	 */
111
	public $address;
112
113
	/**
114
	 * @var string zipcode
115
	 */
116
	public $zip;
117
118
	/**
119
	 * @var string town
120
	 */
121
	public $town;
122
123
	/**
124
	 * @var int Id of state
125
	 */
126
	public $state_id;
127
128
	/**
129
	 * @var string Code of state
130
	 */
131
	public $state_code;
132
133
	/**
134
	 * @var string Label of state
135
	 */
136
	public $state;
137
138
	/**
139
	 * @var string email
140
	 */
141
	public $email;
142
143
	/**
144
	 * @var array array of socialnetworks
145
	 */
146
	public $socialnetworks;
147
148
	/**
149
	 * @var string skype account
150
	 * @deprecated
151
	 */
152
	public $skype;
153
154
	/**
155
	 * @var string twitter account
156
	 * @deprecated
157
	 */
158
	public $twitter;
159
160
	/**
161
	 * @var string facebook account
162
	 * @deprecated
163
	 */
164
	public $facebook;
165
166
	/**
167
	 * @var string linkedin account
168
	 * @deprecated
169
	 */
170
	public $linkedin;
171
172
	/**
173
	 * @var string Phone number
174
	 */
175
	public $phone;
176
177
	/**
178
	 * @var string Private Phone number
179
	 */
180
	public $phone_perso;
181
182
	/**
183
	 * @var string Professional Phone number
184
	 */
185
	public $phone_pro;
186
187
	/**
188
	 * @var string Mobile phone number
189
	 */
190
	public $phone_mobile;
191
192
	/**
193
	 * @var string Fax number
194
	 */
195
	public $fax;
196
197
	/**
198
	 * @var string Function
199
	 */
200
	public $poste;
201
202
	/**
203
	 * @var string mor or phy
204
	 */
205
	public $morphy;
206
207
	public $public;
208
209
	// -1:brouillon, 0:resilie, >=1:valide,paye
210
	// def in common object
211
	//public $status;
212
213
	/**
214
	 * @var string photo of member
215
	 */
216
	public $photo;
217
218
	/**
219
	 * Date creation record (datec)
220
	 *
221
	 * @var integer
222
	 */
223
	public $datec;
224
225
	/**
226
	 * Date modification record (tms)
227
	 *
228
	 * @var integer
229
	 */
230
	public $datem;
231
232
	public $datevalid;
233
234
	/**
235
	 * @var string gender
236
	 */
237
	public $gender;
238
239
	public $birth;
240
241
	/**
242
	 * @var int id type member
243
	 */
244
	public $typeid;
245
246
	/**
247
	 * @var string label type member
248
	 */
249
	public $type;
250
251
	public $need_subscription;
252
253
	public $user_id;
254
255
	public $user_login;
256
257
	public $datefin;
258
259
	// From member table
260
261
	// Fields loaded by fetch_subscriptions()
262
	public $first_subscription_date;
263
264
	public $first_subscription_amount;
265
266
	public $last_subscription_date;
267
268
	public $last_subscription_date_start;
269
270
	public $last_subscription_date_end;
271
272
	public $last_subscription_amount;
273
274
	public $subscriptions = array();
275
276
	/**
277
	 * @var Adherent To contains a clone of this when we need to save old properties of object
278
	 */
279
	public $oldcopy;
280
281
	/**
282
	 * @var int Entity
283
	 */
284
	public $entity;
285
286
	/**
287
	 * @var array fields
288
	 */
289
	public $fields = array(
290
		'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 10),
291
		'ref' => array('type' => 'varchar(30)', 'label' => 'Ref', 'default' => 1, 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 12, 'index' => 1),
292
		'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => 1, 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 15, 'index' => 1),
293
		'ref_ext' => array('type' => 'varchar(128)', 'label' => 'Ref ext', 'enabled' => 1, 'visible' => 0, 'position' => 20),
294
		'civility' => array('type' => 'varchar(6)', 'label' => 'Civility', 'enabled' => 1, 'visible' => -1, 'position' => 25),
295
		'lastname' => array('type' => 'varchar(50)', 'label' => 'Lastname', 'enabled' => 1, 'visible' => -1, 'position' => 30),
296
		'firstname' => array('type' => 'varchar(50)', 'label' => 'Firstname', 'enabled' => 1, 'visible' => -1, 'position' => 35),
297
		'login' => array('type' => 'varchar(50)', 'label' => 'Login', 'enabled' => 1, 'visible' => -1, 'position' => 40),
298
		'gender' => array('type' => 'varchar(10)', 'label' => 'Gender', 'enabled' => 1, 'visible' => -1, 'position' => 250),
299
		'pass' => array('type' => 'varchar(50)', 'label' => 'Pass', 'enabled' => 1, 'visible' => -1, 'position' => 45),
300
		'pass_crypted' => array('type' => 'varchar(128)', 'label' => 'Pass crypted', 'enabled' => 1, 'visible' => -1, 'position' => 50),
301
		'fk_adherent_type' => array('type' => 'integer', 'label' => 'Fk adherent type', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 55),
302
		'morphy' => array('type' => 'varchar(3)', 'label' => 'MorPhy', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 60),
303
		'societe' => array('type' => 'varchar(128)', 'label' => 'Societe', 'enabled' => 1, 'visible' => -1, 'position' => 65),
304
		'fk_soc' => array('type' => 'integer:Societe:societe/class/societe.class.php', 'label' => 'ThirdParty', 'enabled' => 1, 'visible' => -1, 'position' => 70),
305
		'address' => array('type' => 'text', 'label' => 'Address', 'enabled' => 1, 'visible' => -1, 'position' => 75),
306
		'zip' => array('type' => 'varchar(10)', 'label' => 'Zip', 'enabled' => 1, 'visible' => -1, 'position' => 80),
307
		'town' => array('type' => 'varchar(50)', 'label' => 'Town', 'enabled' => 1, 'visible' => -1, 'position' => 85),
308
		'state_id' => array('type' => 'integer', 'label' => 'State id', 'enabled' => 1, 'visible' => -1, 'position' => 90),
309
		'country' => array('type' => 'integer:Ccountry:core/class/ccountry.class.php', 'label' => 'Country', 'enabled' => 1, 'visible' => -1, 'position' => 95),
310
		'email' => array('type' => 'varchar(255)', 'label' => 'Email', 'enabled' => 1, 'visible' => -1, 'position' => 100),
311
		'socialnetworks' => array('type' => 'text', 'label' => 'Socialnetworks', 'enabled' => 1, 'visible' => -1, 'position' => 105),
312
		'phone' => array('type' => 'varchar(30)', 'label' => 'Phone', 'enabled' => 1, 'visible' => -1, 'position' => 115),
313
		'phone_perso' => array('type' => 'varchar(30)', 'label' => 'Phone perso', 'enabled' => 1, 'visible' => -1, 'position' => 120),
314
		'phone_mobile' => array('type' => 'varchar(30)', 'label' => 'Phone mobile', 'enabled' => 1, 'visible' => -1, 'position' => 125),
315
		'birth' => array('type' => 'date', 'label' => 'DateOfBirth', 'enabled' => 1, 'visible' => -1, 'position' => 130),
316
		'photo' => array('type' => 'varchar(255)', 'label' => 'Photo', 'enabled' => 1, 'visible' => -1, 'position' => 135),
317
		'public' => array('type' => 'smallint(6)', 'label' => 'Public', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 145),
318
		'datefin' => array('type' => 'datetime', 'label' => 'DateEnd', 'enabled' => 1, 'visible' => -1, 'position' => 150),
319
		'note_private' => array('type' => 'text', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 155),
320
		'note_public' => array('type' => 'text', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 160),
321
		'datevalid' => array('type' => 'datetime', 'label' => 'DateValidation', 'enabled' => 1, 'visible' => -1, 'position' => 165),
322
		'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -1, 'position' => 170),
323
		'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 175),
324
		'fk_user_author' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'Fk user author', 'enabled' => 1, 'visible' => -1, 'position' => 180),
325
		'fk_user_mod' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'Fk user mod', 'enabled' => 1, 'visible' => -1, 'position' => 185),
326
		'fk_user_valid' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserValidation', 'enabled' => 1, 'visible' => -1, 'position' => 190),
327
		'canvas' => array('type' => 'varchar(32)', 'label' => 'Canvas', 'enabled' => 1, 'visible' => -1, 'position' => 195),
328
		'statut' => array('type' => 'smallint(6)', 'label' => 'Statut', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 500,
329
		'arrayofkeyval' => array(0 => 'Draft', 1 => 'Validated', -1 => 'MemberStatusResiliatedShort')),
330
		'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'visible' => 0, 'position' => 800),
331
		'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -2, 'position' => 805)
332
	);
333
334
335
	/**
336
	 *	Constructor
337
	 *
338
	 *	@param 		DoliDB		$db		Database handler
339
	 */
340
	public function __construct($db)
341
	{
342
		$this->db = $db;
343
		$this->statut = -1;
344
		// l'adherent n'est pas public par defaut
345
		$this->public = 0;
346
		// les champs optionnels sont vides
347
		$this->array_options = array();
348
	}
349
350
351
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
352
	/**
353
	 *  Function sending an email to the current member with the text supplied in parameter.
354
	 *
355
	 *  @param	string	$text				Content of message (not html entities encoded)
356
	 *  @param	string	$subject			Subject of message
357
	 *  @param 	array	$filename_list      Array of attached files
358
	 *  @param 	array	$mimetype_list      Array of mime types of attached files
359
	 *  @param 	array	$mimefilename_list  Array of public names of attached files
360
	 *  @param 	string	$addr_cc            Email cc
361
	 *  @param 	string	$addr_bcc           Email bcc
362
	 *  @param 	int		$deliveryreceipt	Ask a delivery receipt
363
	 *  @param	int		$msgishtml			1=String IS already html, 0=String IS NOT html, -1=Unknown need autodetection
364
	 *  @param	string	$errors_to			erros to
365
	 *  @param	string	$moreinheader		Add more html headers
366
	 *  @return	int							<0 if KO, >0 if OK
367
	 */
368
	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 = '')
369
	{
370
		// phpcs:enable
371
		global $conf, $langs;
372
373
		// Detect if message is HTML
374
		if ($msgishtml == -1) {
375
			$msgishtml = 0;
376
			if (dol_textishtml($text, 0)) $msgishtml = 1;
377
		}
378
379
		dol_syslog('send_an_email msgishtml='.$msgishtml);
380
381
		$texttosend = $this->makeSubstitution($text);
382
		$subjecttosend = $this->makeSubstitution($subject);
383
		if ($msgishtml) $texttosend = dol_htmlentitiesbr($texttosend);
384
385
		// Envoi mail confirmation
386
		$from = $conf->email_from;
387
		if (!empty($conf->global->ADHERENT_MAIL_FROM)) $from = $conf->global->ADHERENT_MAIL_FROM;
388
389
		$trackid = 'mem'.$this->id;
390
391
		// Send email (substitutionarray must be done just before this)
392
		include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
393
		$mailfile = new CMailFile($subjecttosend, $this->email, $from, $texttosend, $filename_list, $mimetype_list, $mimefilename_list, $addr_cc, $addr_bcc, $deliveryreceipt, $msgishtml, '', '', $trackid, $moreinheader);
394
		if ($mailfile->sendfile()) {
395
			return 1;
396
		} else {
397
			$this->error = $langs->trans("ErrorFailedToSendMail", $from, $this->email).'. '.$mailfile->error;
398
			return -1;
399
		}
400
	}
401
402
403
	/**
404
	 * Make substitution of tags into text with value of current object.
405
	 *
406
	 * @param	string	$text       Text to make substitution to
407
	 * @return  string      		Value of input text string with substitutions done
408
	 */
409
	public function makeSubstitution($text)
410
	{
411
		global $conf, $langs;
412
413
		$birthday = dol_print_date($this->birth, 'day');
414
415
		$msgishtml = 0;
416
		if (dol_textishtml($text, 1)) $msgishtml = 1;
417
418
		$infos = '';
419
		if ($this->civility_id) $infos .= $langs->transnoentities("UserTitle").": ".$this->getCivilityLabel()."\n";
420
		$infos .= $langs->transnoentities("id").": ".$this->id."\n";
421
		$infos .= $langs->transnoentities("ref").": ".$this->ref."\n";
422
		$infos .= $langs->transnoentities("Lastname").": ".$this->lastname."\n";
423
		$infos .= $langs->transnoentities("Firstname").": ".$this->firstname."\n";
424
		$infos .= $langs->transnoentities("Company").": ".$this->company."\n";
425
		$infos .= $langs->transnoentities("Address").": ".$this->address."\n";
426
		$infos .= $langs->transnoentities("Zip").": ".$this->zip."\n";
427
		$infos .= $langs->transnoentities("Town").": ".$this->town."\n";
428
		$infos .= $langs->transnoentities("Country").": ".$this->country."\n";
429
		$infos .= $langs->transnoentities("EMail").": ".$this->email."\n";
430
		$infos .= $langs->transnoentities("PhonePro").": ".$this->phone."\n";
431
		$infos .= $langs->transnoentities("PhonePerso").": ".$this->phone_perso."\n";
432
		$infos .= $langs->transnoentities("PhoneMobile").": ".$this->phone_mobile."\n";
433
		if (empty($conf->global->ADHERENT_LOGIN_NOT_REQUIRED)) {
434
			$infos .= $langs->transnoentities("Login").": ".$this->login."\n";
435
			$infos .= $langs->transnoentities("Password").": ".$this->pass."\n";
436
		}
437
		$infos .= $langs->transnoentities("Birthday").": ".$birthday."\n";
438
		$infos .= $langs->transnoentities("Photo").": ".$this->photo."\n";
439
		$infos .= $langs->transnoentities("Public").": ".yn($this->public);
440
441
		// Substitutions
442
		$substitutionarray = array(
443
			'__ID__' => $this->id,
444
			'__REF__' => $this->ref,
445
			'__MEMBER_ID__' => $this->id,
446
			'__CIVILITY__' => $this->getCivilityLabel(),
447
			'__FIRSTNAME__' => $msgishtml ? dol_htmlentitiesbr($this->firstname) : ($this->firstname ? $this->firstname : ''),
448
			'__LASTNAME__' => $msgishtml ? dol_htmlentitiesbr($this->lastname) : ($this->lastname ? $this->lastname : ''),
449
			'__FULLNAME__' => $msgishtml ? dol_htmlentitiesbr($this->getFullName($langs)) : $this->getFullName($langs),
450
			'__COMPANY__' => $msgishtml ? dol_htmlentitiesbr($this->company) : ($this->company ? $this->company : ''),
451
			'__ADDRESS__' => $msgishtml ? dol_htmlentitiesbr($this->address) : ($this->address ? $this->address : ''),
452
			'__ZIP__' => $msgishtml ? dol_htmlentitiesbr($this->zip) : ($this->zip ? $this->zip : ''),
453
			'__TOWN__' => $msgishtml ? dol_htmlentitiesbr($this->town) : ($this->town ? $this->town : ''),
454
			'__COUNTRY__' => $msgishtml ? dol_htmlentitiesbr($this->country) : ($this->country ? $this->country : ''),
455
			'__EMAIL__' => $msgishtml ? dol_htmlentitiesbr($this->email) : ($this->email ? $this->email : ''),
456
			'__BIRTH__' => $msgishtml ? dol_htmlentitiesbr($birthday) : ($birthday ? $birthday : ''),
457
			'__PHOTO__' => $msgishtml ? dol_htmlentitiesbr($this->photo) : ($this->photo ? $this->photo : ''),
458
			'__LOGIN__' => $msgishtml ? dol_htmlentitiesbr($this->login) : ($this->login ? $this->login : ''),
459
			'__PASSWORD__' => $msgishtml ? dol_htmlentitiesbr($this->pass) : ($this->pass ? $this->pass : ''),
460
			'__PHONE__' => $msgishtml ? dol_htmlentitiesbr($this->phone) : ($this->phone ? $this->phone : ''),
461
			'__PHONEPRO__' => $msgishtml ? dol_htmlentitiesbr($this->phone_perso) : ($this->phone_perso ? $this->phone_perso : ''),
462
			'__PHONEMOBILE__' => $msgishtml ? dol_htmlentitiesbr($this->phone_mobile) : ($this->phone_mobile ? $this->phone_mobile : ''),
463
			'__TYPE__' => $msgishtml ? dol_htmlentitiesbr($this->type) : ($this->type ? $this->type : '')
464
		);
465
466
		complete_substitutions_array($substitutionarray, $langs, $this);
467
468
		return make_substitutions($text, $substitutionarray, $langs);
469
	}
470
471
472
	/**
473
	 *	Return translated label by the nature of a adherent (physical or moral)
474
	 *
475
	 *	@param	string		$morphy		Nature of the adherent (physical or moral)
476
	 *	@return	string					Label
477
	 */
478
	public function getmorphylib($morphy = '')
479
	{
480
		global $langs;
481
		if (!$morphy) {
482
			$morphy = $this->morphy;
483
		}
484
		if ($morphy == 'phy') {
485
			return $langs->trans("Physical");
486
		}
487
		if ($morphy == 'mor') {
488
			return $langs->trans("Moral");
489
		}
490
		return $morphy;
491
	}
492
493
	/**
494
	 *	Create a member into database
495
	 *
496
	 *	@param	User	$user        	Objet user qui demande la creation
497
	 *	@param  int		$notrigger		1 ne declenche pas les triggers, 0 sinon
498
	 *	@return	int						<0 if KO, >0 if OK
499
	 */
500
	public function create($user, $notrigger = 0)
501
	{
502
		global $conf, $langs;
503
504
		$error = 0;
505
506
		$now = dol_now();
507
508
		// Clean parameters
509
		$this->import_key = trim($this->import_key);
510
511
		// Check parameters
512
		if (!empty($conf->global->ADHERENT_MAIL_REQUIRED) && !isValidEMail($this->email)) {
513
			$langs->load("errors");
514
			$this->error = $langs->trans("ErrorBadEMail", $this->email);
515
			return -1;
516
		}
517
		if (!$this->datec) $this->datec = $now;
518
		if (empty($conf->global->ADHERENT_LOGIN_NOT_REQUIRED)) {
519
			if (empty($this->login)) {
520
				$this->error = $langs->trans("ErrorWrongValueForParameterX", "Login");
521
				return -1;
522
			}
523
		}
524
525
		$this->db->begin();
526
527
		// Insert member
528
		$sql = "INSERT INTO ".MAIN_DB_PREFIX."adherent";
529
		$sql .= " (ref, datec,login,fk_user_author,fk_user_mod,fk_user_valid,morphy,fk_adherent_type,entity,import_key)";
530
		$sql .= " VALUES (";
531
		$sql .= " '(PROV)'";
532
		$sql .= ", '".$this->db->idate($this->datec)."'";
533
		$sql .= ", ".($this->login ? "'".$this->db->escape($this->login)."'" : "null");
534
		$sql .= ", ".($user->id > 0 ? $user->id : "null"); // Can be null because member can be created by a guest or a script
535
		$sql .= ", null, null, '".$this->db->escape($this->morphy)."'";
536
		$sql .= ", ".$this->typeid;
537
		$sql .= ", ".$conf->entity;
538
		$sql .= ", ".(!empty($this->import_key) ? "'".$this->db->escape($this->import_key)."'" : "null");
539
		$sql .= ")";
540
541
		dol_syslog(get_class($this)."::create", LOG_DEBUG);
542
		$result = $this->db->query($sql);
543
		if ($result) {
544
			$id = $this->db->last_insert_id(MAIN_DB_PREFIX."adherent");
545
			if ($id > 0) {
546
				$this->id = $id;
547
				$this->ref = (string) $id;
548
549
				// Update minor fields
550
				$result = $this->update($user, 1, 1, 0, 0, 'add'); // nosync is 1 to avoid update data of user
551
				if ($result < 0) {
552
					$this->db->rollback();
553
					return -1;
554
				}
555
556
				// Add link to user
557
				if ($this->user_id) {
558
					// Add link to user
559
					$sql = "UPDATE ".MAIN_DB_PREFIX."user SET";
560
					$sql .= " fk_member = ".$this->id;
561
					$sql .= " WHERE rowid = ".$this->user_id;
562
					dol_syslog(get_class($this)."::create", LOG_DEBUG);
563
					$resql = $this->db->query($sql);
564
					if (!$resql) {
565
						$this->error = 'Failed to update user to make link with member';
566
						$this->db->rollback();
567
						return -4;
568
					}
569
				}
570
571
				if (!$notrigger) {
572
					// Call trigger
573
					$result = $this->call_trigger('MEMBER_CREATE', $user);
574
					if ($result < 0) {
575
						$error++;
576
					}
577
					// End call triggers
578
				}
579
580
				if (count($this->errors)) {
581
					dol_syslog(get_class($this)."::create ".implode(',', $this->errors), LOG_ERR);
582
					$this->db->rollback();
583
					return -3;
584
				} else {
585
					$this->db->commit();
586
					return $this->id;
587
				}
588
			} else {
589
				$this->error = 'Failed to get last insert id';
590
				dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
591
				$this->db->rollback();
592
				return -2;
593
			}
594
		} else {
595
			$this->error = $this->db->error();
596
			$this->db->rollback();
597
			return -1;
598
		}
599
	}
600
601
602
	/**
603
	 *	Update a member in database (standard information and password)
604
	 *
605
	 *	@param	User	$user				User making update
606
	 *	@param	int		$notrigger			1=disable trigger UPDATE (when called by create)
607
	 *	@param	int		$nosyncuser			0=Synchronize linked user (standard info), 1=Do not synchronize linked user
608
	 *	@param	int		$nosyncuserpass		0=Synchronize linked user (password), 1=Do not synchronize linked user
609
	 *	@param	int		$nosyncthirdparty	0=Synchronize linked thirdparty (standard info), 1=Do not synchronize linked thirdparty
610
	 * 	@param	string	$action				Current action for hookmanager
611
	 * 	@return	int							<0 if KO, >0 if OK
612
	 */
613
	public function update($user, $notrigger = 0, $nosyncuser = 0, $nosyncuserpass = 0, $nosyncthirdparty = 0, $action = 'update')
614
	{
615
		global $conf, $langs, $hookmanager;
616
617
		$nbrowsaffected = 0;
618
		$error = 0;
619
620
		dol_syslog(get_class($this)."::update notrigger=".$notrigger.", nosyncuser=".$nosyncuser.", nosyncuserpass=".$nosyncuserpass." nosyncthirdparty=".$nosyncthirdparty.", email=".
621
			$this->email);
622
623
		// Clean parameters
624
		$this->lastname = trim($this->lastname) ? trim($this->lastname) : trim($this->lastname);
625
		$this->firstname = trim($this->firstname) ? trim($this->firstname) : trim($this->firstname);
626
		$this->gender = trim($this->gender);
627
		$this->address = ($this->address ? $this->address : $this->address);
628
		$this->zip = ($this->zip ? $this->zip : $this->zip);
629
		$this->town = ($this->town ? $this->town : $this->town);
630
		$this->country_id = ($this->country_id > 0 ? $this->country_id : $this->country_id);
631
		$this->state_id = ($this->state_id > 0 ? $this->state_id : $this->state_id);
632
		$this->setUpperOrLowerCase();
633
		$this->note_public = ($this->note_public ? $this->note_public : $this->note_public);
634
		$this->note_private = ($this->note_private ? $this->note_private : $this->note_private);
635
636
		// Check parameters
637
		if (!empty($conf->global->ADHERENT_MAIL_REQUIRED) && !isValidEMail($this->email)) {
638
			$langs->load("errors");
639
			$this->error = $langs->trans("ErrorBadEMail", $this->email);
640
			return -1;
641
		}
642
643
		$this->db->begin();
644
645
		$sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
646
		$sql .= " ref = '".$this->db->escape($this->ref)."'";
647
		$sql .= ", civility = ".($this->civility_id ? "'".$this->db->escape($this->civility_id)."'" : "null");
648
		$sql .= ", firstname = ".($this->firstname ? "'".$this->db->escape($this->firstname)."'" : "null");
649
		$sql .= ", lastname = ".($this->lastname ? "'".$this->db->escape($this->lastname)."'" : "null");
650
		$sql .= ", gender = ".($this->gender != -1 ? "'".$this->db->escape($this->gender)."'" : "null"); // 'man' or 'woman'
651
		$sql .= ", login = ".($this->login ? "'".$this->db->escape($this->login)."'" : "null");
652
		$sql .= ", societe = ".($this->company ? "'".$this->db->escape($this->company)."'" : ($this->societe ? "'".$this->db->escape($this->societe)."'" : "null"));
1 ignored issue
show
Deprecated Code introduced by
The property Adherent::$societe has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

652
		$sql .= ", societe = ".($this->company ? "'".$this->db->escape($this->company)."'" : (/** @scrutinizer ignore-deprecated */ $this->societe ? "'".$this->db->escape($this->societe)."'" : "null"));
Loading history...
653
		$sql .= ", fk_soc = ".($this->socid > 0 ? $this->db->escape($this->socid) : "null");
654
		$sql .= ", address = ".($this->address ? "'".$this->db->escape($this->address)."'" : "null");
655
		$sql .= ", zip = ".($this->zip ? "'".$this->db->escape($this->zip)."'" : "null");
656
		$sql .= ", town = ".($this->town ? "'".$this->db->escape($this->town)."'" : "null");
657
		$sql .= ", country = ".($this->country_id > 0 ? $this->db->escape($this->country_id) : "null");
658
		$sql .= ", state_id = ".($this->state_id > 0 ? $this->db->escape($this->state_id) : "null");
659
		$sql .= ", email = '".$this->db->escape($this->email)."'";
660
		$sql .= ", socialnetworks = '".$this->db->escape(json_encode($this->socialnetworks))."'";
661
		$sql .= ", phone = ".($this->phone ? "'".$this->db->escape($this->phone)."'" : "null");
662
		$sql .= ", phone_perso = ".($this->phone_perso ? "'".$this->db->escape($this->phone_perso)."'" : "null");
663
		$sql .= ", phone_mobile = ".($this->phone_mobile ? "'".$this->db->escape($this->phone_mobile)."'" : "null");
664
		$sql .= ", note_private = ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "null");
665
		$sql .= ", note_public = ".($this->note_public ? "'".$this->db->escape($this->note_public)."'" : "null");
666
		$sql .= ", photo = ".($this->photo ? "'".$this->db->escape($this->photo)."'" : "null");
667
		$sql .= ", public = '".$this->db->escape($this->public)."'";
668
		$sql .= ", statut = ".$this->db->escape($this->statut);
669
		$sql .= ", fk_adherent_type = ".$this->db->escape($this->typeid);
670
		$sql .= ", morphy = '".$this->db->escape($this->morphy)."'";
671
		$sql .= ", birth = ".($this->birth ? "'".$this->db->idate($this->birth)."'" : "null");
672
		if ($this->socid) $sql .= ", fk_soc = '".$this->db->escape($this->socid)."'"; // Must be modified only when creating from a third-party
673
		if ($this->datefin) $sql .= ", datefin = '".$this->db->idate($this->datefin)."'"; // Must be modified only when deleting a subscription
674
		if ($this->datevalid) $sql .= ", datevalid = '".$this->db->idate($this->datevalid)."'"; // Must be modified only when validating a member
675
		$sql .= ", fk_user_mod = ".($user->id > 0 ? $user->id : 'null'); // Can be null because member can be create by a guest
676
		$sql .= " WHERE rowid = ".$this->id;
677
678
		// If we change the type of membership, we set also label of new type
679
		if (!empty($this->oldcopy) && $this->typeid != $this->oldcopy->typeid) {
680
			$sql2 = "SELECT libelle as label";
681
			$sql2 .= " FROM ".MAIN_DB_PREFIX."adherent_type";
682
			$sql2 .= " WHERE rowid = ".$this->typeid;
683
			$resql2 = $this->db->query($sql2);
684
			if ($resql2) {
685
				while ($obj = $this->db->fetch_object($resql2)) {
686
					$this->type = $obj->label;
687
				}
688
			}
689
		}
690
691
		dol_syslog(get_class($this)."::update update member", LOG_DEBUG);
692
		$resql = $this->db->query($sql);
693
		if ($resql) {
694
			unset($this->country_code);
695
			unset($this->country);
696
			unset($this->state_code);
697
			unset($this->state);
698
699
			$nbrowsaffected += $this->db->affected_rows($resql);
700
701
			$action = 'update';
702
703
			// Actions on extra fields
704
			if (!$error) {
705
				$result = $this->insertExtraFields();
706
				if ($result < 0) {
707
					$error++;
708
				}
709
			}
710
711
			// Update password
712
			if (!$error && $this->pass) {
713
				dol_syslog(get_class($this)."::update update password");
714
				if ($this->pass != $this->pass_indatabase && $this->pass != $this->pass_indatabase_crypted) {
715
					$isencrypted = empty($conf->global->DATABASE_PWD_ENCRYPTED) ? 0 : 1;
716
717
					// If password to set differs from the one found into database
718
					$result = $this->setPassword($user, $this->pass, $isencrypted, $notrigger, $nosyncuserpass);
719
					if (!$nbrowsaffected) $nbrowsaffected++;
720
				}
721
			}
722
723
			// Remove links to user and replace with new one
724
			if (!$error) {
725
				dol_syslog(get_class($this)."::update update link to user");
726
				$sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = NULL WHERE fk_member = ".$this->id;
727
				dol_syslog(get_class($this)."::update", LOG_DEBUG);
728
				$resql = $this->db->query($sql);
729
				if (!$resql) {
730
					$this->error = $this->db->error();
731
					$this->db->rollback();
732
					return -5;
733
				}
734
				// If there is a user linked to this member
735
				if ($this->user_id > 0) {
736
					$sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = ".$this->id." WHERE rowid = ".$this->user_id;
737
					dol_syslog(get_class($this)."::update", LOG_DEBUG);
738
					$resql = $this->db->query($sql);
739
					if (!$resql) {
740
						$this->error = $this->db->error();
741
						$this->db->rollback();
742
						return -5;
743
					}
744
				}
745
			}
746
747
			if (!$error && $nbrowsaffected) { // If something has change in main data
748
				// Update information on linked user if it is an update
749
				if (!$error && $this->user_id > 0 && !$nosyncuser) {
750
					require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
751
752
					dol_syslog(get_class($this)."::update update linked user");
753
754
					$luser = new User($this->db);
755
					$result = $luser->fetch($this->user_id);
756
757
					if ($result >= 0) {
758
						//var_dump($this->user_login);exit;
759
						//var_dump($this->login);exit;
760
761
						// 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.
762
						if (empty($conf->global->ADHERENT_LOGIN_NOT_REQUIRED)) $luser->login = $this->login;
763
764
						$luser->ref = $this->ref;
765
						$luser->civility_id = $this->civility_id;
766
						$luser->firstname = $this->firstname;
767
						$luser->lastname = $this->lastname;
768
						$luser->gender = $this->gender;
769
						$luser->pass = $this->pass;
770
						//$luser->socid=$this->fk_soc;		// We do not enable this. This may transform a user into an external user.
771
772
						$luser->birth = $this->birth;
773
774
						$luser->address = $this->address;
775
						$luser->zip = $this->zip;
776
						$luser->town = $this->town;
777
						$luser->country_id = $this->country_id;
778
						$luser->state_id = $this->state_id;
779
780
						$luser->email = $this->email;
781
						$luser->socialnetworks = $this->socialnetworks;
782
						$luser->office_phone = $this->phone;
783
						$luser->user_mobile = $this->phone_mobile;
784
785
						$luser->fk_member = $this->id;
786
787
						$result = $luser->update($user, 0, 1, 1); // Use nosync to 1 to avoid cyclic updates
788
						if ($result < 0) {
789
							$this->error = $luser->error;
790
							dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
791
							$error++;
792
						}
793
					} else {
794
						$this->error = $luser->error;
795
						$error++;
796
					}
797
				}
798
799
				// Update information on linked thirdparty if it is an update
800
				if (!$error && $this->fk_soc > 0 && !$nosyncthirdparty) {
801
					require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
802
803
					dol_syslog(get_class($this)."::update update linked thirdparty");
804
805
					// This member is linked with a thirdparty, so we also update thirdparty informations
806
					// if this is an update.
807
					$lthirdparty = new Societe($this->db);
808
					$result = $lthirdparty->fetch($this->fk_soc);
809
810
					if ($result > 0) {
811
						$lthirdparty->address = $this->address;
812
						$lthirdparty->zip = $this->zip;
813
						$lthirdparty->town = $this->town;
814
						$lthirdparty->email = $this->email;
815
						$lthirdparty->socialnetworks = $this->socialnetworks;
816
						$lthirdparty->phone = $this->phone;
817
						$lthirdparty->state_id = $this->state_id;
818
						$lthirdparty->country_id = $this->country_id;
819
						//$lthirdparty->phone_mobile=$this->phone_mobile;
820
821
						$result = $lthirdparty->update($this->fk_soc, $user, 0, 1, 1, 'update'); // Use sync to 0 to avoid cyclic updates
822
823
						if ($result < 0) {
824
							$this->error = $lthirdparty->error;
825
							$this->errors = $lthirdparty->errors;
826
							dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
827
							$error++;
828
						}
829
					} elseif ($result < 0) {
830
						$this->error = $lthirdparty->error;
831
						$error++;
832
					}
833
				}
834
			}
835
836
			if (!$error && !$notrigger) {
837
				// Call trigger
838
				$result = $this->call_trigger('MEMBER_MODIFY', $user);
839
				if ($result < 0) {
840
					$error++;
841
				}
842
				// End call triggers
843
			}
844
845
			if (!$error) {
846
				$this->db->commit();
847
				return $nbrowsaffected;
848
			} else {
849
				$this->db->rollback();
850
				return -1;
851
			}
852
		} else {
853
			$this->db->rollback();
854
			$this->error = $this->db->lasterror();
855
			return -2;
856
		}
857
	}
858
859
860
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
861
	/**
862
	 *	Update denormalized last subscription date.
863
	 * 	This function is called when we delete a subscription for example.
864
	 *
865
	 *	@param	User	$user			User making change
866
	 *	@return	int						<0 if KO, >0 if OK
867
	 */
868
	public function update_end_date($user)
869
	{
870
		// phpcs:enable
871
		$this->db->begin();
872
873
		// Search for last subscription id and end date
874
		$sql = "SELECT rowid, datec as dateop, dateadh as datedeb, datef as datefin";
875
		$sql .= " FROM ".MAIN_DB_PREFIX."subscription";
876
		$sql .= " WHERE fk_adherent=".$this->id;
877
		$sql .= " ORDER by dateadh DESC"; // Sort by start subscription date
878
879
		dol_syslog(get_class($this)."::update_end_date", LOG_DEBUG);
880
		$resql = $this->db->query($sql);
881
		if ($resql) {
882
			$obj = $this->db->fetch_object($resql);
883
			$dateop = $this->db->jdate($obj->dateop);
884
			$datedeb = $this->db->jdate($obj->datedeb);
885
			$datefin = $this->db->jdate($obj->datefin);
886
887
			$sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
888
			$sql .= " datefin=".($datefin != '' ? "'".$this->db->idate($datefin)."'" : "null");
889
			$sql .= " WHERE rowid = ".$this->id;
890
891
			dol_syslog(get_class($this)."::update_end_date", LOG_DEBUG);
892
			$resql = $this->db->query($sql);
893
			if ($resql) {
894
				$this->last_subscription_date = $dateop;
895
				$this->last_subscription_date_start = $datedeb;
896
				$this->last_subscription_date_end = $datefin;
897
				$this->datefin = $datefin;
898
				$this->db->commit();
899
				return 1;
900
			} else {
901
				$this->db->rollback();
902
				return -1;
903
			}
904
		} else {
905
			$this->error = $this->db->lasterror();
906
			$this->db->rollback();
907
			return -1;
908
		}
909
	}
910
911
	/**
912
	 *  Fonction qui supprime l'adherent et les donnees associees
913
	 *
914
	 *  @param	int		$rowid		Id of member to delete
915
	 *	@param	User		$user		User object
916
	 *	@param	int		$notrigger	1=Does not execute triggers, 0= execute triggers
917
	 *  @return	int					<0 if KO, 0=nothing to do, >0 if OK
918
	 */
919
	public function delete($rowid, $user, $notrigger = 0)
920
	{
921
		global $conf, $langs;
922
923
		$result = 0;
924
		$error = 0;
925
		$errorflag = 0;
926
927
		// Check parameters
928
		if (empty($rowid)) $rowid = $this->id;
929
930
		$this->db->begin();
931
932
		if (!$error && !$notrigger) {
933
			// Call trigger
934
			$result = $this->call_trigger('MEMBER_DELETE', $user);
935
			if ($result < 0) $error++;
936
			// End call triggers
937
		}
938
939
		// Remove category
940
		$sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_member WHERE fk_member = ".$rowid;
941
		dol_syslog(get_class($this)."::delete", LOG_DEBUG);
942
		$resql = $this->db->query($sql);
943
		if (!$resql) {
944
			$error++;
945
			$this->error .= $this->db->lasterror();
946
			$errorflag = -1;
947
		}
948
949
		// Remove subscription
950
		if (!$error) {
951
			$sql = "DELETE FROM ".MAIN_DB_PREFIX."subscription WHERE fk_adherent = ".$rowid;
952
			dol_syslog(get_class($this)."::delete", LOG_DEBUG);
953
			$resql = $this->db->query($sql);
954
			if (!$resql) {
955
				$error++;
956
				$this->error .= $this->db->lasterror();
957
				$errorflag = -2;
958
			}
959
		}
960
961
		// Remove linked user
962
		if (!$error) {
963
			$ret = $this->setUserId(0);
964
			if ($ret < 0) {
965
				$error++;
966
				$this->error .= $this->db->lasterror();
967
				$errorflag = -3;
968
			}
969
		}
970
971
		// Removed extrafields
972
		if (!$error) {
973
			$result = $this->deleteExtraFields();
974
			if ($result < 0) {
975
				$error++;
976
				$errorflag = -4;
977
				dol_syslog(get_class($this)."::delete erreur ".$errorflag." ".$this->error, LOG_ERR);
978
			}
979
		}
980
981
		// Remove adherent
982
		if (!$error) {
983
			$sql = "DELETE FROM ".MAIN_DB_PREFIX."adherent WHERE rowid = ".$rowid;
984
			dol_syslog(get_class($this)."::delete", LOG_DEBUG);
985
			$resql = $this->db->query($sql);
986
			if (!$resql) {
987
				$error++;
988
				$this->error .= $this->db->lasterror();
989
				$errorflag = -5;
990
			}
991
		}
992
993
		if (!$error) {
994
			$this->db->commit();
995
			return 1;
996
		} else {
997
			$this->db->rollback();
998
			return $errorflag;
999
		}
1000
	}
1001
1002
1003
	/**
1004
	 *    Change password of a user
1005
	 *
1006
	 *    @param	User	$user           Object user de l'utilisateur qui fait la modification
1007
	 *    @param 	string	$password       New password (to generate if empty)
1008
	 *    @param    int		$isencrypted    0 ou 1 si il faut crypter le mot de passe en base (0 par defaut)
1009
	 *	  @param	int		$notrigger		1=Ne declenche pas les triggers
1010
	 *    @param	int		$nosyncuser		Do not synchronize linked user
1011
	 *    @return   string           		If OK return clear password, 0 if no change, < 0 if error
1012
	 */
1013
	public function setPassword($user, $password = '', $isencrypted = 0, $notrigger = 0, $nosyncuser = 0)
1014
	{
1015
		global $conf, $langs;
1016
1017
		$error = 0;
1018
1019
		dol_syslog(get_class($this)."::setPassword user=".$user->id." password=".preg_replace('/./i', '*', $password)." isencrypted=".$isencrypted);
1020
1021
		// If new password not provided, we generate one
1022
		if (!$password) {
1023
			require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
1024
			$password = getRandomPassword(false);
1025
		}
1026
1027
		// Crypt password
1028
		$password_crypted = dol_hash($password);
1029
1030
		$password_indatabase = '';
1031
		if (!$isencrypted) {
1032
			$password_indatabase = $password;
1033
		}
1034
1035
		$this->db->begin();
1036
1037
		// Mise a jour
1038
		$sql = "UPDATE ".MAIN_DB_PREFIX."adherent";
1039
		$sql .= " SET pass_crypted = '".$this->db->escape($password_crypted)."'";
1040
		//if (! empty($conf->global->DATABASE_PWD_ENCRYPTED))
1041
		if ($isencrypted) {
1042
			$sql .= ", pass = null";
1043
		} else {
1044
			$sql .= ", pass = '".$this->db->escape($password_indatabase)."'";
1045
		}
1046
		$sql .= " WHERE rowid = ".$this->id;
1047
1048
		//dol_syslog("Adherent::Password sql=hidden");
1049
		dol_syslog(get_class($this)."::setPassword", LOG_DEBUG);
1050
		$result = $this->db->query($sql);
1051
		if ($result) {
1052
			$nbaffectedrows = $this->db->affected_rows($result);
1053
1054
			if ($nbaffectedrows) {
1055
				$this->pass = $password;
1056
				$this->pass_indatabase = $password_indatabase;
1057
				$this->pass_indatabase_crypted = $password_crypted;
1058
1059
				if ($this->user_id && !$nosyncuser) {
1060
					require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
1061
1062
					// This member is linked with a user, so we also update users informations
1063
					// if this is an update.
1064
					$luser = new User($this->db);
1065
					$result = $luser->fetch($this->user_id);
1066
1067
					if ($result >= 0) {
1068
						$result = $luser->setPassword($user, $this->pass, 0, 0, 1);
1069
						if ($result < 0) {
1070
							$this->error = $luser->error;
1071
							dol_syslog(get_class($this)."::setPassword ".$this->error, LOG_ERR);
1072
							$error++;
1073
						}
1074
					} else {
1075
						$this->error = $luser->error;
1076
						$error++;
1077
					}
1078
				}
1079
1080
				if (!$error && !$notrigger) {
1081
					// Call trigger
1082
					$result = $this->call_trigger('MEMBER_NEW_PASSWORD', $user);
1083
					if ($result < 0) {
1084
						$error++;
1085
						$this->db->rollback();
1086
						return -1;
1087
					}
1088
					// End call triggers
1089
				}
1090
1091
				$this->db->commit();
1092
				return $this->pass;
1093
			} else {
1094
				$this->db->rollback();
1095
				return 0;
1096
			}
1097
		} else {
1098
			$this->db->rollback();
1099
			dol_print_error($this->db);
1100
			return -1;
1101
		}
1102
	}
1103
1104
1105
	/**
1106
	 *    Set link to a user
1107
	 *
1108
	 *    @param     int	$userid        	Id of user to link to
1109
	 *    @return    int					1=OK, -1=KO
1110
	 */
1111
	public function setUserId($userid)
1112
	{
1113
		global $conf, $langs;
1114
1115
		$this->db->begin();
1116
1117
		// If user is linked to this member, remove old link to this member
1118
		$sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = NULL WHERE fk_member = ".$this->id;
1119
		dol_syslog(get_class($this)."::setUserId", LOG_DEBUG);
1120
		$resql = $this->db->query($sql);
1121
		if (!$resql) {
1122
			$this->error = $this->db->error();
1123
			$this->db->rollback();
1124
			return -1;
1125
		}
1126
1127
		// Set link to user
1128
		if ($userid > 0) {
1129
			$sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = ".$this->id;
1130
			$sql .= " WHERE rowid = ".$userid;
1131
			dol_syslog(get_class($this)."::setUserId", LOG_DEBUG);
1132
			$resql = $this->db->query($sql);
1133
			if (!$resql) {
1134
				$this->error = $this->db->error();
1135
				$this->db->rollback();
1136
				return -2;
1137
			}
1138
		}
1139
1140
		$this->db->commit();
1141
1142
		return 1;
1143
	}
1144
1145
1146
	/**
1147
	 *    Set link to a third party
1148
	 *
1149
	 *    @param     int	$thirdpartyid		Id of user to link to
1150
	 *    @return    int						1=OK, -1=KO
1151
	 */
1152
	public function setThirdPartyId($thirdpartyid)
1153
	{
1154
		global $conf, $langs;
1155
1156
		$this->db->begin();
1157
1158
		// Remove link to third party onto any other members
1159
		if ($thirdpartyid > 0) {
1160
			$sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET fk_soc = null";
1161
			$sql .= " WHERE fk_soc = ".((int) $thirdpartyid);
1162
			$sql .= " AND entity = ".$conf->entity;
1163
			dol_syslog(get_class($this)."::setThirdPartyId", LOG_DEBUG);
1164
			$resql = $this->db->query($sql);
1165
		}
1166
1167
		// Add link to third party for current member
1168
		$sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET fk_soc = ".($thirdpartyid > 0 ? $thirdpartyid : 'null');
1169
		$sql .= " WHERE rowid = ".$this->id;
1170
1171
		dol_syslog(get_class($this)."::setThirdPartyId", LOG_DEBUG);
1172
		$resql = $this->db->query($sql);
1173
		if ($resql) {
1174
			$this->db->commit();
1175
			return 1;
1176
		} else {
1177
			$this->error = $this->db->error();
1178
			$this->db->rollback();
1179
			return -1;
1180
		}
1181
	}
1182
1183
1184
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1185
	/**
1186
	 *	Method to load member from its login
1187
	 *
1188
	 *	@param	string	$login		login of member
1189
	 *	@return	void
1190
	 */
1191
	public function fetch_login($login)
1192
	{
1193
		// phpcs:enable
1194
		global $conf;
1195
1196
		$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."adherent";
1197
		$sql .= " WHERE login='".$this->db->escape($login)."'";
1198
		$sql .= " AND entity = ".$conf->entity;
1199
1200
		$resql = $this->db->query($sql);
1201
		if ($resql) {
1202
			if ($this->db->num_rows($resql)) {
1203
				$obj = $this->db->fetch_object($resql);
1204
				$this->fetch($obj->rowid);
1205
			}
1206
		} else {
1207
			dol_print_error($this->db);
1208
		}
1209
	}
1210
1211
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1212
	/**
1213
	 *	Method to load member from its name
1214
	 *
1215
	 *	@param	string	$firstname	Firstname
1216
	 *	@param	string	$lastname	Lastname
1217
	 *	@return	void
1218
	 */
1219
	public function fetch_name($firstname, $lastname)
1220
	{
1221
		// phpcs:enable
1222
		global $conf;
1223
1224
		$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."adherent";
1225
		$sql .= " WHERE firstname='".$this->db->escape($firstname)."'";
1226
		$sql .= " AND lastname='".$this->db->escape($lastname)."'";
1227
		$sql .= " AND entity = ".$conf->entity;
1228
1229
		$resql = $this->db->query($sql);
1230
		if ($resql) {
1231
			if ($this->db->num_rows($resql)) {
1232
				$obj = $this->db->fetch_object($resql);
1233
				$this->fetch($obj->rowid);
1234
			}
1235
		} else {
1236
			dol_print_error($this->db);
1237
		}
1238
	}
1239
1240
	/**
1241
	 *	Load member from database
1242
	 *
1243
	 *	@param	int		$rowid      			Id of object to load
1244
	 * 	@param	string	$ref					To load member from its ref
1245
	 * 	@param	int		$fk_soc					To load member from its link to third party
1246
	 * 	@param	string	$ref_ext				External reference
1247
	 *  @param	bool	$fetch_optionals		To load optionals (extrafields)
1248
	 *  @param	bool	$fetch_subscriptions	To load member subscriptions
1249
	 *	@return int								>0 if OK, 0 if not found, <0 if KO
1250
	 */
1251
	public function fetch($rowid, $ref = '', $fk_soc = '', $ref_ext = '', $fetch_optionals = true, $fetch_subscriptions = true)
1252
	{
1253
		global $langs;
1254
1255
		$sql = "SELECT d.rowid, d.ref, d.ref_ext, d.civility as civility_code, d.gender, d.firstname, d.lastname,";
1256
		$sql .= " d.societe as company, d.fk_soc, d.statut, d.public, d.address, d.zip, d.town, d.note_private,";
1257
		$sql .= " d.note_public,";
1258
		$sql .= " d.email, d.socialnetworks, d.phone, d.phone_perso, d.phone_mobile, d.login, d.pass, d.pass_crypted,";
1259
		$sql .= " d.photo, d.fk_adherent_type, d.morphy, d.entity,";
1260
		$sql .= " d.datec as datec,";
1261
		$sql .= " d.tms as datem,";
1262
		$sql .= " d.datefin as datefin,";
1263
		$sql .= " d.birth as birthday,";
1264
		$sql .= " d.datevalid as datev,";
1265
		$sql .= " d.country,";
1266
		$sql .= " d.state_id,";
1267
		$sql .= " d.model_pdf,";
1268
		$sql .= " c.rowid as country_id, c.code as country_code, c.label as country,";
1269
		$sql .= " dep.nom as state, dep.code_departement as state_code,";
1270
		$sql .= " t.libelle as type, t.subscription as subscription,";
1271
		$sql .= " u.rowid as user_id, u.login as user_login";
1272
		$sql .= " FROM ".MAIN_DB_PREFIX."adherent_type as t, ".MAIN_DB_PREFIX."adherent as d";
1273
		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as c ON d.country = c.rowid";
1274
		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as dep ON d.state_id = dep.rowid";
1275
		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u ON d.rowid = u.fk_member";
1276
		$sql .= " WHERE d.fk_adherent_type = t.rowid";
1277
		if ($rowid) {
1278
			$sql .= " AND d.rowid=".((int) $rowid);
1279
		} elseif ($ref || $fk_soc) {
1280
			$sql .= " AND d.entity IN (".getEntity('adherent').")";
1281
			if ($ref) {
1282
				$sql .= " AND d.ref='".$this->db->escape($ref)."'";
1283
			} elseif ($fk_soc > 0) {
1284
				$sql .= " AND d.fk_soc=".((int) $fk_soc);
1285
			}
1286
		} elseif ($ref_ext) {
1287
			$sql .= " AND d.ref_ext='".$this->db->escape($ref_ext)."'";
1288
		}
1289
1290
		dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
1291
		$resql = $this->db->query($sql);
1292
		if ($resql) {
1293
			if ($this->db->num_rows($resql)) {
1294
				$obj = $this->db->fetch_object($resql);
1295
1296
				$this->entity = $obj->entity;
1297
				$this->id = $obj->rowid;
1298
				$this->ref = $obj->ref;
1299
				$this->ref_ext = $obj->ref_ext;
1300
1301
				$this->civility_id = $obj->civility_code; // Bad. Kept for backard compatibility
1302
				$this->civility_code = $obj->civility_code;
1303
				$this->civility = $obj->civility_code ? ($langs->trans("Civility".$obj->civility_code) != ("Civility".$obj->civility_code) ? $langs->trans("Civility".$obj->civility_code) : $obj->civility_code) : '';
1304
1305
				$this->firstname = $obj->firstname;
1306
				$this->lastname = $obj->lastname;
1307
				$this->gender = $obj->gender;
1308
				$this->login = $obj->login;
1309
				$this->societe = $obj->company;
1310
				$this->company = $obj->company;
1311
				$this->socid = $obj->fk_soc;
1312
				$this->fk_soc = $obj->fk_soc; // For backward compatibility
1313
				$this->address = $obj->address;
1314
				$this->zip = $obj->zip;
1315
				$this->town = $obj->town;
1316
1317
				$this->pass = $obj->pass;
1318
				$this->pass_indatabase = $obj->pass;
1319
				$this->pass_indatabase_crypted = $obj->pass_crypted;
1320
1321
				$this->state_id = $obj->state_id;
1322
				$this->state_code = $obj->state_id ? $obj->state_code : '';
1323
				$this->state = $obj->state_id ? $obj->state : '';
1324
1325
				$this->country_id = $obj->country_id;
1326
				$this->country_code = $obj->country_code;
1327
				if ($langs->trans("Country".$obj->country_code) != "Country".$obj->country_code) {
1328
					$this->country = $langs->transnoentitiesnoconv("Country".$obj->country_code);
1329
				} else {
1330
					$this->country = $obj->country;
1331
				}
1332
1333
				$this->phone = $obj->phone;
1334
				$this->phone_perso = $obj->phone_perso;
1335
				$this->phone_mobile = $obj->phone_mobile;
1336
				$this->email = $obj->email;
1337
1338
				$this->socialnetworks = (array) json_decode($obj->socialnetworks, true);
1339
1340
				$this->photo = $obj->photo;
1341
				$this->statut = $obj->statut;
1342
				$this->public = $obj->public;
1343
1344
				$this->datec = $this->db->jdate($obj->datec);
1345
				$this->date_creation = $this->db->jdate($obj->datec);
1346
				$this->datem = $this->db->jdate($obj->datem);
1347
				$this->date_modification = $this->db->jdate($obj->datem);
1348
				$this->datefin = $this->db->jdate($obj->datefin);
1349
				$this->datevalid = $this->db->jdate($obj->datev);
1350
				$this->date_validation = $this->db->jdate($obj->datev);
1351
				$this->birth = $this->db->jdate($obj->birthday);
1352
1353
				$this->note_private = $obj->note_private;
1354
				$this->note_public = $obj->note_public;
1355
				$this->morphy = $obj->morphy;
1356
1357
				$this->typeid = $obj->fk_adherent_type;
1358
				$this->type = $obj->type;
1359
				$this->need_subscription = $obj->subscription;
1360
1361
				$this->user_id = $obj->user_id;
1362
				$this->user_login = $obj->user_login;
1363
1364
				$this->model_pdf = $obj->model_pdf;
1365
1366
				// Retrieve all extrafield
1367
				// fetch optionals attributes and labels
1368
				if ($fetch_optionals) {
1369
					$this->fetch_optionals();
1370
				}
1371
1372
				// Load other properties
1373
				if ($fetch_subscriptions) {
1374
					$result = $this->fetch_subscriptions();
1375
				}
1376
1377
				return $this->id;
1378
			} else {
1379
				return 0;
1380
			}
1381
		} else {
1382
			$this->error = $this->db->lasterror();
1383
			return -1;
1384
		}
1385
	}
1386
1387
1388
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1389
	/**
1390
	 *	Function to get member subscriptions data
1391
	 *				first_subscription_date, first_subscription_date_start, first_subscription_date_end, first_subscription_amount
1392
	 *				last_subscription_date, last_subscription_date_start, last_subscription_date_end, last_subscription_amount
1393
	 *
1394
	 *	@return		int			<0 si KO, >0 si OK
1395
	 */
1396
	public function fetch_subscriptions()
1397
	{
1398
		// phpcs:enable
1399
		global $langs;
1400
1401
		require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
1402
1403
		$sql = "SELECT c.rowid, c.fk_adherent, c.fk_type, c.subscription, c.note, c.fk_bank,";
1404
		$sql .= " c.tms as datem,";
1405
		$sql .= " c.datec as datec,";
1406
		$sql .= " c.dateadh as dateh,";
1407
		$sql .= " c.datef as datef";
1408
		$sql .= " FROM ".MAIN_DB_PREFIX."subscription as c";
1409
		$sql .= " WHERE c.fk_adherent = ".$this->id;
1410
		$sql .= " ORDER BY c.dateadh";
1411
		dol_syslog(get_class($this)."::fetch_subscriptions", LOG_DEBUG);
1412
1413
		$resql = $this->db->query($sql);
1414
		if ($resql) {
1415
			$this->subscriptions = array();
1416
1417
			$i = 0;
1418
			while ($obj = $this->db->fetch_object($resql)) {
1419
				if ($i == 0) {
1420
					$this->first_subscription_date = $this->db->jdate($obj->datec);
1421
					$this->first_subscription_date_start = $this->db->jdate($obj->dateh);
1422
					$this->first_subscription_date_end = $this->db->jdate($obj->datef);
1423
					$this->first_subscription_amount = $obj->subscription;
1424
				}
1425
				$this->last_subscription_date = $this->db->jdate($obj->datec);
1426
				$this->last_subscription_date_start = $this->db->jdate($obj->datef);
1427
				$this->last_subscription_date_end = $this->db->jdate($obj->datef);
1428
				$this->last_subscription_amount = $obj->subscription;
1429
1430
				$subscription = new Subscription($this->db);
1431
				$subscription->id = $obj->rowid;
1432
				$subscription->fk_adherent = $obj->fk_adherent;
1433
				$subscription->fk_type = $obj->fk_type;
1434
				$subscription->amount = $obj->subscription;
1435
				$subscription->note = $obj->note;
1436
				$subscription->fk_bank = $obj->fk_bank;
1437
				$subscription->datem = $this->db->jdate($obj->datem);
1438
				$subscription->datec = $this->db->jdate($obj->datec);
1439
				$subscription->dateh = $this->db->jdate($obj->dateh);
1440
				$subscription->datef = $this->db->jdate($obj->datef);
1441
1442
				$this->subscriptions[] = $subscription;
1443
1444
				$i++;
1445
			}
1446
			return 1;
1447
		} else {
1448
			$this->error = $this->db->error().' sql='.$sql;
1449
			return -1;
1450
		}
1451
	}
1452
1453
1454
	/**
1455
	 *	Insert subscription into database and eventually add links to banks, mailman, etc...
1456
	 *
1457
	 *	@param	int	        $date        		Date of effect of subscription
1458
	 *	@param	double		$amount     		Amount of subscription (0 accepted for some members)
1459
	 *	@param	int			$accountid			Id bank account
1460
	 *	@param	string		$operation			Type of payment (if Id bank account provided). Example: 'CB', ...
1461
	 *	@param	string		$label				Label operation (if Id bank account provided)
1462
	 *	@param	string		$num_chq			Numero cheque (if Id bank account provided)
1463
	 *	@param	string		$emetteur_nom		Name of cheque writer
1464
	 *	@param	string		$emetteur_banque	Name of bank of cheque
1465
	 *	@param	int     	$datesubend			Date end subscription
1466
	 *	@return int         					rowid of record added, <0 if KO
1467
	 */
1468
	public function subscription($date, $amount, $accountid = 0, $operation = '', $label = '', $num_chq = '', $emetteur_nom = '', $emetteur_banque = '', $datesubend = 0)
1469
	{
1470
		global $conf, $langs, $user;
1471
1472
		require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
1473
1474
		$error = 0;
1475
1476
		// Clean parameters
1477
		if (!$amount) $amount = 0;
1478
1479
		$this->db->begin();
1480
1481
		if ($datesubend) {
1482
			$datefin = $datesubend;
1483
		} else {
1484
			// If no end date, end date = date + 1 year - 1 day
1485
			$datefin = dol_time_plus_duree($date, 1, 'y');
1486
			$datefin = dol_time_plus_duree($datefin, -1, 'd');
1487
		}
1488
1489
		// Create subscription
1490
		$subscription = new Subscription($this->db);
1491
		$subscription->fk_adherent = $this->id;
1492
		$subscription->dateh = $date; // Date of new subscription
1493
		$subscription->datef = $datefin; // End data of new subscription
1494
		$subscription->amount = $amount;
1495
		$subscription->note = $label; // deprecated
1496
		$subscription->note_public = $label;
1497
1498
		$rowid = $subscription->create($user);
1499
		if ($rowid > 0) {
1500
			// Update denormalized subscription end date (read database subscription to find values)
1501
			// This will also update this->datefin
1502
			$result = $this->update_end_date($user);
1503
			if ($result > 0) {
1504
				// Change properties of object (used by triggers)
1505
				$this->last_subscription_date = dol_now();
1506
				$this->last_subscription_date_start = $date;
1507
				$this->last_subscription_date_end = $datefin;
1508
				$this->last_subscription_amount = $amount;
1509
			}
1510
1511
			if (!$error) {
1512
				$this->db->commit();
1513
				return $rowid;
1514
			} else {
1515
				$this->db->rollback();
1516
				return -2;
1517
			}
1518
		} else {
1519
			$this->error = $subscription->error;
1520
			$this->errors = $subscription->errors;
1521
			$this->db->rollback();
1522
			return -1;
1523
		}
1524
	}
1525
1526
1527
	/**
1528
	 *	Do complementary actions after subscription recording.
1529
	 *
1530
	 *	@param	int			$subscriptionid			Id of created subscription
1531
	 *  @param	string		$option					Which action ('bankdirect', 'bankviainvoice', 'invoiceonly', ...)
1532
	 *	@param	int			$accountid				Id bank account
1533
	 *	@param	int			$datesubscription		Date of subscription
1534
	 *	@param	int			$paymentdate			Date of payment
1535
	 *	@param	string		$operation				Code of type of operation (if Id bank account provided). Example 'CB', ...
1536
	 *	@param	string		$label					Label operation (if Id bank account provided)
1537
	 *	@param	double		$amount     			Amount of subscription (0 accepted for some members)
1538
	 *	@param	string		$num_chq				Numero cheque (if Id bank account provided)
1539
	 *	@param	string		$emetteur_nom			Name of cheque writer
1540
	 *	@param	string		$emetteur_banque		Name of bank of cheque
1541
	 *  @param	string		$autocreatethirdparty	Auto create new thirdparty if member not yet linked to a thirdparty and we request an option that generate invoice.
1542
	 *	@return int									<0 if KO, >0 if OK
1543
	 */
1544
	public function subscriptionComplementaryActions($subscriptionid, $option, $accountid, $datesubscription, $paymentdate, $operation, $label, $amount, $num_chq, $emetteur_nom = '', $emetteur_banque = '', $autocreatethirdparty = 0)
1545
	{
1546
		global $conf, $langs, $user, $mysoc;
1547
1548
		$error = 0;
1549
1550
		$this->invoice = null; // This will contains invoice if an invoice is created
1551
1552
		dol_syslog("subscriptionComplementaryActions subscriptionid=".$subscriptionid." option=".$option." accountid=".$accountid." datesubscription=".$datesubscription." paymentdate=".
1553
			$paymentdate." label=".$label." amount=".$amount." num_chq=".$num_chq." autocreatethirdparty=".$autocreatethirdparty);
1554
1555
		// Insert into bank account directlty (if option choosed for) + link to llx_subscription if option is 'bankdirect'
1556
		if ($option == 'bankdirect' && $accountid) {
1557
			require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
1558
1559
			$acct = new Account($this->db);
1560
			$result = $acct->fetch($accountid);
1561
1562
			$dateop = $paymentdate;
1563
1564
			$insertid = $acct->addline($dateop, $operation, $label, $amount, $num_chq, '', $user, $emetteur_nom, $emetteur_banque);
1565
			if ($insertid > 0) {
1566
				$inserturlid = $acct->add_url_line($insertid, $this->id, DOL_URL_ROOT.'/adherents/card.php?rowid=', $this->getFullname($langs), 'member');
1567
				if ($inserturlid > 0) {
1568
					// Update table subscription
1569
					$sql = "UPDATE ".MAIN_DB_PREFIX."subscription SET fk_bank=".$insertid;
1570
					$sql .= " WHERE rowid=".$subscriptionid;
1571
1572
					dol_syslog("subscription::subscription", LOG_DEBUG);
1573
					$resql = $this->db->query($sql);
1574
					if (!$resql) {
1575
						$error++;
1576
						$this->error = $this->db->lasterror();
1577
						$this->errors[] = $this->error;
1578
					}
1579
				} else {
1580
					$error++;
1581
					$this->error = $acct->error;
1582
					$this->errors = $acct->errors;
1583
				}
1584
			} else {
1585
				$error++;
1586
				$this->error = $acct->error;
1587
				$this->errors = $acct->errors;
1588
			}
1589
		}
1590
1591
		// If option choosed, we create invoice
1592
		if (($option == 'bankviainvoice' && $accountid) || $option == 'invoiceonly') {
1593
			require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
1594
			require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/paymentterm.class.php';
1595
1596
			$invoice = new Facture($this->db);
1597
			$customer = new Societe($this->db);
1598
1599
			if (!$error) {
1600
				if (!($this->fk_soc > 0)) { // If not yet linked to a company
1601
					if ($autocreatethirdparty) {
1602
						// Create a linked thirdparty to member
1603
						$companyalias = '';
1604
						$fullname = $this->getFullName($langs);
1605
1606
						if ($this->morphy == 'mor') {
1607
							$companyname = $this->company;
1608
							if (!empty($fullname)) $companyalias = $fullname;
1609
						} else {
1610
							$companyname = $fullname;
1611
							if (!empty($this->company)) $companyalias = $this->company;
1612
						}
1613
1614
						$result = $customer->create_from_member($this, $companyname, $companyalias);
1615
						if ($result < 0) {
1616
							$this->error = $customer->error;
1617
							$this->errors = $customer->errors;
1618
							$error++;
1619
						} else {
1620
							$this->fk_soc = $result;
1621
						}
1622
					} else {
1623
						$langs->load("errors");
1624
						$this->error = $langs->trans("ErrorMemberNotLinkedToAThirpartyLinkOrCreateFirst");
1625
						$this->errors[] = $this->error;
1626
						$error++;
1627
					}
1628
				}
1629
			}
1630
			if (!$error) {
1631
				$result = $customer->fetch($this->fk_soc);
1632
				if ($result <= 0) {
1633
					$this->error = $customer->error;
1634
					$this->errors = $customer->errors;
1635
					$error++;
1636
				}
1637
			}
1638
1639
			if (!$error) {
1640
				// Create draft invoice
1641
				$invoice->type = Facture::TYPE_STANDARD;
1642
				$invoice->cond_reglement_id = $customer->cond_reglement_id;
1643
				if (empty($invoice->cond_reglement_id)) {
1644
					$paymenttermstatic = new PaymentTerm($this->db);
1645
					$invoice->cond_reglement_id = $paymenttermstatic->getDefaultId();
1646
					if (empty($invoice->cond_reglement_id)) {
1647
						$error++;
1648
						$this->error = 'ErrorNoPaymentTermRECEPFound';
1649
						$this->errors[] = $this->error;
1650
					}
1651
				}
1652
				$invoice->socid = $this->fk_soc;
1653
				$invoice->date = $datesubscription;
1654
1655
				// Possibility to add external linked objects with hooks
1656
				$invoice->linked_objects['subscription'] = $subscriptionid;
1657
				if (!empty($_POST['other_linked_objects']) && is_array($_POST['other_linked_objects'])) {
1658
					$invoice->linked_objects = array_merge($invoice->linked_objects, $_POST['other_linked_objects']);
1659
				}
1660
1661
				$result = $invoice->create($user);
1662
				if ($result <= 0) {
1663
					$this->error = $invoice->error;
1664
					$this->errors = $invoice->errors;
1665
					$error++;
1666
				} else {
1667
					$this->invoice = $invoice;
1668
				}
1669
			}
1670
1671
			if (!$error) {
1672
				// Add line to draft invoice
1673
				$idprodsubscription = 0;
1674
				if (!empty($conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS) && (!empty($conf->product->enabled) || !empty($conf->service->enabled))) $idprodsubscription = $conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS;
1675
1676
				$vattouse = 0;
1677
				if (isset($conf->global->ADHERENT_VAT_FOR_SUBSCRIPTIONS) && $conf->global->ADHERENT_VAT_FOR_SUBSCRIPTIONS == 'defaultforfoundationcountry') {
1678
					$vattouse = get_default_tva($mysoc, $mysoc, $idprodsubscription);
1679
				}
1680
				//print xx".$vattouse." - ".$mysoc." - ".$customer;exit;
1681
				$result = $invoice->addline($label, 0, 1, $vattouse, 0, 0, $idprodsubscription, 0, $datesubscription, '', 0, 0, '', 'TTC', $amount, 1);
1682
				if ($result <= 0) {
1683
					$this->error = $invoice->error;
1684
					$this->errors = $invoice->errors;
1685
					$error++;
1686
				}
1687
			}
1688
1689
			if (!$error) {
1690
				// Validate invoice
1691
				$result = $invoice->validate($user);
1692
				if ($result <= 0) {
1693
					$this->error = $invoice->error;
1694
					$this->errors = $invoice->errors;
1695
					$error++;
1696
				}
1697
			}
1698
1699
			if (!$error) {
1700
				// TODO Link invoice with subscription ?
1701
			}
1702
1703
			// Add payment onto invoice
1704
			if (!$error && $option == 'bankviainvoice' && $accountid) {
1705
				require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
1706
				require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
1707
				require_once DOL_DOCUMENT_ROOT.'/core/lib/functions.lib.php';
1708
1709
				$amounts = array();
1710
				$amounts[$invoice->id] = price2num($amount);
1711
1712
				$paiement = new Paiement($this->db);
1713
				$paiement->datepaye = $paymentdate;
1714
				$paiement->amounts = $amounts;
1715
				$paiement->paiementid = dol_getIdFromCode($this->db, $operation, 'c_paiement', 'code', 'id', 1);
1716
				$paiement->num_payment = $num_chq;
1717
				$paiement->note_public = $label;
1718
1719
				if (!$error) {
1720
					// Create payment line for invoice
1721
					$paiement_id = $paiement->create($user);
1722
					if (!$paiement_id > 0) {
1723
						$this->error = $paiement->error;
1724
						$this->errors = $paiement->errors;
1725
						$error++;
1726
					}
1727
				}
1728
1729
				if (!$error) {
1730
					// Add transaction into bank account
1731
					$bank_line_id = $paiement->addPaymentToBank($user, 'payment', '(SubscriptionPayment)', $accountid, $emetteur_nom, $emetteur_banque);
1732
					if (!($bank_line_id > 0)) {
1733
						$this->error = $paiement->error;
1734
						$this->errors = $paiement->errors;
1735
						$error++;
1736
					}
1737
				}
1738
1739
				if (!$error && !empty($bank_line_id)) {
1740
					// Update fk_bank into subscription table
1741
					$sql = 'UPDATE '.MAIN_DB_PREFIX.'subscription SET fk_bank='.$bank_line_id;
1742
					$sql .= ' WHERE rowid='.$subscriptionid;
1743
1744
					$result = $this->db->query($sql);
1745
					if (!$result) {
1746
						$error++;
1747
					}
1748
				}
1749
1750
				if (!$error) {
1751
					// Set invoice as paid
1752
					$invoice->set_paid($user);
1753
				}
1754
			}
1755
1756
			if (!$error) {
1757
				// Define output language
1758
				$outputlangs = $langs;
1759
				$newlang = '';
1760
				$lang_id = GETPOST('lang_id');
1761
				if ($conf->global->MAIN_MULTILANGS && empty($newlang) && !empty($lang_id)) $newlang = $lang_id;
1762
				if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $customer->default_lang;
1763
				if (!empty($newlang)) {
1764
					$outputlangs = new Translate("", $conf);
1765
					$outputlangs->setDefaultLang($newlang);
1766
				}
1767
				// Generate PDF (whatever is option MAIN_DISABLE_PDF_AUTOUPDATE) so we can include it into email
1768
				//if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
1769
1770
				$invoice->generateDocument($invoice->model_pdf, $outputlangs);
1771
			}
1772
		}
1773
1774
		if ($error) {
1775
			return -1;
1776
		} else {
1777
			return 1;
1778
		}
1779
	}
1780
1781
1782
	/**
1783
	 *		Function that validate a member
1784
	 *
1785
	 *		@param	User	$user		user adherent qui valide
1786
	 *		@return	int					<0 if KO, 0 if nothing done, >0 if OK
1787
	 */
1788
	public function validate($user)
1789
	{
1790
		global $langs, $conf;
1791
1792
		$error = 0;
1793
		$now = dol_now();
1794
1795
		// Check parameters
1796
		if ($this->statut == 1) {
1797
			dol_syslog(get_class($this)."::validate statut of member does not allow this", LOG_WARNING);
1798
			return 0;
1799
		}
1800
1801
		$this->db->begin();
1802
1803
		$sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
1804
		$sql .= " statut = 1";
1805
		$sql .= ", datevalid = '".$this->db->idate($now)."'";
1806
		$sql .= ", fk_user_valid=".$user->id;
1807
		$sql .= " WHERE rowid = ".$this->id;
1808
1809
		dol_syslog(get_class($this)."::validate", LOG_DEBUG);
1810
		$result = $this->db->query($sql);
1811
		if ($result) {
1812
			$this->statut = 1;
1813
1814
			// Call trigger
1815
			$result = $this->call_trigger('MEMBER_VALIDATE', $user);
1816
			if ($result < 0) {
1817
				$error++;
1818
				$this->db->rollback();
1819
				return -1;
1820
			}
1821
			// End call triggers
1822
1823
			$this->datevalid = $now;
1824
1825
			$this->db->commit();
1826
			return 1;
1827
		} else {
1828
			$this->error = $this->db->error();
1829
			$this->db->rollback();
1830
			return -1;
1831
		}
1832
	}
1833
1834
1835
	/**
1836
	 *		Fonction qui resilie un adherent
1837
	 *
1838
	 *		@param	User	$user		User making change
1839
	 *		@return	int					<0 if KO, >0 if OK
1840
	 */
1841
	public function resiliate($user)
1842
	{
1843
		global $langs, $conf;
1844
1845
		$error = 0;
1846
1847
		// Check parameters
1848
		if ($this->statut == 0) {
1849
			dol_syslog(get_class($this)."::resiliate statut of member does not allow this", LOG_WARNING);
1850
			return 0;
1851
		}
1852
1853
		$this->db->begin();
1854
1855
		$sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
1856
		$sql .= " statut = 0";
1857
		$sql .= ", fk_user_valid=".$user->id;
1858
		$sql .= " WHERE rowid = ".$this->id;
1859
1860
		$result = $this->db->query($sql);
1861
		if ($result) {
1862
			$this->statut = 0;
1863
1864
			// Call trigger
1865
			$result = $this->call_trigger('MEMBER_RESILIATE', $user);
1866
			if ($result < 0) {
1867
				$error++;
1868
				$this->db->rollback();
1869
				return -1;
1870
			}
1871
			// End call triggers
1872
1873
			$this->db->commit();
1874
			return 1;
1875
		} else {
1876
			$this->error = $this->db->error();
1877
			$this->db->rollback();
1878
			return -1;
1879
		}
1880
	}
1881
1882
1883
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1884
	/**
1885
	 *  Function to add member into external tools mailing-list, spip, etc.
1886
	 *
1887
	 *  @return		int		<0 if KO, >0 if OK
1888
	 */
1889
	public function add_to_abo()
1890
	{
1891
		// phpcs:enable
1892
		global $conf, $langs;
1893
1894
		include_once DOL_DOCUMENT_ROOT.'/mailmanspip/class/mailmanspip.class.php';
1895
		$mailmanspip = new MailmanSpip($this->db);
1896
1897
		$err = 0;
1898
1899
		// mailman
1900
		if (!empty($conf->global->ADHERENT_USE_MAILMAN) && !empty($conf->mailmanspip->enabled)) {
1901
			$result = $mailmanspip->add_to_mailman($this);
1902
1903
			if ($result < 0) {
1904
				if (!empty($mailmanspip->error)) $this->errors[] = $mailmanspip->error;
1905
				$err += 1;
1906
			}
1907
			foreach ($mailmanspip->mladded_ko as $tmplist => $tmpemail) {
1908
				$langs->load("errors");
1909
				$this->errors[] = $langs->trans("ErrorFailedToAddToMailmanList", $tmpemail, $tmplist);
1910
			}
1911
			foreach ($mailmanspip->mladded_ok as $tmplist => $tmpemail) {
1912
				$langs->load("mailmanspip");
1913
				$this->mesgs[] = $langs->trans("SuccessToAddToMailmanList", $tmpemail, $tmplist);
1914
			}
1915
		}
1916
1917
		// spip
1918
		if (!empty($conf->global->ADHERENT_USE_SPIP) && !empty($conf->mailmanspip->enabled)) {
1919
			$result = $mailmanspip->add_to_spip($this);
1920
			if ($result < 0) {
1921
				$this->errors[] = $mailmanspip->error;
1922
				$err += 1;
1923
			}
1924
		}
1925
		if ($err) {
1926
			return -$err;
1927
		} else {
1928
			return 1;
1929
		}
1930
	}
1931
1932
1933
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1934
	/**
1935
	 *  Function to delete a member from external tools like mailing-list, spip, etc.
1936
	 *
1937
	 *  @return     int     <0 if KO, >0 if OK
1938
	 */
1939
	public function del_to_abo()
1940
	{
1941
		// phpcs:enable
1942
		global $conf, $langs;
1943
1944
		include_once DOL_DOCUMENT_ROOT.'/mailmanspip/class/mailmanspip.class.php';
1945
		$mailmanspip = new MailmanSpip($this->db);
1946
1947
		$err = 0;
1948
1949
		// mailman
1950
		if (!empty($conf->global->ADHERENT_USE_MAILMAN)) {
1951
			$result = $mailmanspip->del_to_mailman($this);
1952
			if ($result < 0) {
1953
				if (!empty($mailmanspip->error)) $this->errors[] = $mailmanspip->error;
1954
				$err += 1;
1955
			}
1956
1957
			foreach ($mailmanspip->mlremoved_ko as $tmplist => $tmpemail) {
1958
				$langs->load("errors");
1959
				$this->errors[] = $langs->trans("ErrorFailedToRemoveToMailmanList", $tmpemail, $tmplist);
1960
			}
1961
			foreach ($mailmanspip->mlremoved_ok as $tmplist => $tmpemail) {
1962
				$langs->load("mailmanspip");
1963
				$this->mesgs[] = $langs->trans("SuccessToRemoveToMailmanList", $tmpemail, $tmplist);
1964
			}
1965
		}
1966
1967
		if ($conf->global->ADHERENT_USE_SPIP && !empty($conf->mailmanspip->enabled)) {
1968
			$result = $mailmanspip->del_to_spip($this);
1969
			if ($result < 0) {
1970
				$this->errors[] = $mailmanspip->error;
1971
				$err += 1;
1972
			}
1973
		}
1974
		if ($err) {
1975
			// error
1976
			return -$err;
1977
		} else {
1978
			return 1;
1979
		}
1980
	}
1981
1982
1983
	/**
1984
	 *    Return civility label of a member
1985
	 *
1986
	 *    @return   string              	Translated name of civility (translated with transnoentitiesnoconv)
1987
	 */
1988
	public function getCivilityLabel()
1989
	{
1990
		global $langs;
1991
		$langs->load("dict");
1992
1993
		$code = (empty($this->civility_id) ? '' : $this->civility_id);
1994
		if (empty($code)) return '';
1995
		return $langs->getLabelFromKey($this->db, "Civility".$code, "c_civility", "code", "label", $code);
1996
	}
1997
1998
	/**
1999
	 *  Return clicable name (with picto eventually)
2000
	 *
2001
	 *	@param	int		$withpictoimg				0=No picto, 1=Include picto into link, 2=Only picto, -1=Include photo into link, -2=Only picto photo, -3=Only photo very small)
2002
	 *	@param	int		$maxlen						length max label
2003
	 *	@param	string	$option						Page for link ('card', 'category', 'subscription', ...)
2004
	 *	@param  string  $mode           			''=Show firstname+lastname as label (using default order), 'firstname'=Show only firstname, 'lastname'=Show only lastname, 'login'=Show login, 'ref'=Show ref
2005
	 *	@param  string  $morecss        			Add more css on link
2006
	 *	@param  int		$save_lastsearch_value    	-1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
2007
	 *	@param	int		$notooltip					1=Disable tooltip
2008
	 *	@param  int		$addlinktonotes				1=Add link to notes
2009
	 *	@return	string								Chaine avec URL
2010
	 */
2011
	public function getNomUrl($withpictoimg = 0, $maxlen = 0, $option = 'card', $mode = '', $morecss = '', $save_lastsearch_value = -1, $notooltip = 0, $addlinktonotes = 0)
2012
	{
2013
		global $conf, $langs;
2014
2015
		if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) && $withpictoimg) $withpictoimg = 0;
2016
2017
		$result = '';
2018
		$label = '';
2019
		$linkstart = '';
2020
		$linkend = '';
2021
2022
		if (!empty($this->photo)) {
2023
			$label .= '<div class="photointooltip">';
2024
			$label .= Form::showphoto('memberphoto', $this, 80, 0, 0, 'photowithmargin photologintooltip', 'small', 0, 1);
2025
			$label .= '</div><div style="clear: both;"></div>';
2026
		}
2027
2028
		$label .= '<div class="centpercent">';
2029
		$label .= img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("Member").'</u>';
2030
		$label .= ' '.$this->getLibStatut(4);
2031
		if (!empty($this->ref)) $label .= '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
2032
		if (!empty($this->firstname) || !empty($this->lastname)) $label .= '<br><b>'.$langs->trans('Name').':</b> '.$this->getFullName($langs);
2033
		if (!empty($this->company)) $label .= '<br><b>'.$langs->trans('Company').':</b> '.$this->company;
2034
		$label .= '</div>';
2035
2036
		$url = DOL_URL_ROOT.'/adherents/card.php?rowid='.$this->id;
2037
		if ($option == 'subscription') {
2038
			$url = DOL_URL_ROOT.'/adherents/subscription.php?rowid='.$this->id;
2039
		}
2040
2041
		if ($option != 'nolink') {
2042
			// Add param to save lastsearch_values or not
2043
			$add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
2044
			if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) $add_save_lastsearch_values = 1;
2045
			if ($add_save_lastsearch_values) $url .= '&save_lastsearch_values=1';
2046
		}
2047
2048
		$linkstart .= '<a href="'.$url.'"';
2049
		$linkclose = "";
2050
		if (empty($notooltip)) {
2051
			if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
2052
				$langs->load("users");
2053
				$label = $langs->trans("ShowUser");
2054
				$linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
2055
			}
2056
			$linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
2057
			$linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
2058
		}
2059
2060
		$linkstart .= $linkclose.'>';
2061
		$linkend = '</a>';
2062
2063
		$result .= $linkstart;
2064
		if ($withpictoimg) $result .= '<div class="inline-block nopadding valignmiddle">';
2065
		if ($withpictoimg) {
2066
			$paddafterimage = '';
2067
			if (abs($withpictoimg) == 1) $paddafterimage = 'style="margin-right: 3px;"';
2068
			// Only picto
2069
			if ($withpictoimg > 0)
2070
				$picto = '<span class="nopadding'.($morecss ? ' userimg'.$morecss : '').'">'.
2071
					img_object('', 'user', $paddafterimage.' '.($notooltip ? '' : 'class="classfortooltip"'), 0, 0, $notooltip ? 0 : 1).'</span>';
2072
			// Picto must be a photo
2073
			else {
2074
				$picto = '<span class="nopadding'.($morecss ? ' userimg'.$morecss : '').'"'.($paddafterimage ? ' '.$paddafterimage : '').'>';
2075
				$picto .= Form::showphoto('memberphoto', $this, 0, 0, 0, 'userphoto'.($withpictoimg == -3 ? 'small' : ''), 'mini', 0, 1);
2076
				$picto .= '</span>';
2077
			}
2078
			$result .= $picto;
2079
		}
2080
		if ($withpictoimg > -2 && $withpictoimg != 2) {
2081
			if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) $result .= '<span class="nopadding valignmiddle'.((!isset($this->statut) || $this->statut) ? '' : ' strikefordisabled').
2082
				($morecss ? ' usertext'.$morecss : '').'">';
2083
			if ($mode == 'login') {
2084
				$result .= dol_trunc($this->login, $maxlen);
2085
			} elseif ($mode == 'ref') {
2086
				$result .= $this->ref;
2087
			} else {
2088
				$result .= $this->getFullName($langs, '', ($mode == 'firstname' ? 2 : ($mode == 'lastname' ? 4 : -1)), $maxlen);
2089
			}
2090
			if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) $result .= '</span>';
2091
		}
2092
		if ($withpictoimg) $result .= '</div>';
2093
		$result .= $linkend;
2094
2095
		if ($addlinktonotes) {
2096
			if ($this->note_private) {
2097
				$notetoshow = $langs->trans("ViewPrivateNote").':<br>'.dol_string_nohtmltag($this->note_private, 1);
2098
				$result .= ' <span class="note inline-block">';
2099
				$result .= '<a href="'.DOL_URL_ROOT.'/adherents/note.php?id='.$this->id.'" class="classfortooltip" title="'.dol_escape_htmltag($notetoshow).'">';
2100
				$result .= img_picto('', 'note');
2101
				$result .= '</a>';
2102
				$result .= '</span>';
2103
			}
2104
		}
2105
2106
		return $result;
2107
	}
2108
2109
	/**
2110
	 *  Retourne le libelle du statut d'un adherent (brouillon, valide, resilie)
2111
	 *
2112
	 *  @param	int		$mode       0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
2113
	 *  @return string				Label
2114
	 */
2115
	public function getLibStatut($mode = 0)
2116
	{
2117
		return $this->LibStatut($this->statut, $this->need_subscription, $this->datefin, $mode);
2118
	}
2119
2120
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2121
	/**
2122
	 *  Renvoi le libelle d'un statut donne
2123
	 *
2124
	 *  @param	int			$status      			Id status
2125
	 *	@param	int			$need_subscription		1 if member type need subscription, 0 otherwise
2126
	 *	@param	int     	$date_end_subscription	Date fin adhesion
2127
	 *  @param  int		    $mode                   0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto
2128
	 *  @return string      						Label
2129
	 */
2130
	public function LibStatut($status, $need_subscription, $date_end_subscription, $mode = 0)
2131
	{
2132
		// phpcs:enable
2133
		global $langs;
2134
		$langs->load("members");
2135
2136
		$statusType = '';
2137
		$labelStatus = '';
2138
		$labelStatusShort = '';
2139
2140
		if ($status == -1) {
2141
			$statusType = 'status0';
2142
			$labelStatus = $langs->trans("MemberStatusDraft");
2143
			$labelStatusShort = $langs->trans("MemberStatusDraftShort");
2144
		} elseif ($status >= 1) {
2145
			if ($need_subscription == 0) {
2146
				$statusType = 'status4';
2147
				$labelStatus = $langs->trans("MemberStatusNoSubscription");
2148
				$labelStatusShort = $langs->trans("MemberStatusNoSubscriptionShort");
2149
			} elseif (!$date_end_subscription) {
2150
				$statusType = 'status1';
2151
				$labelStatus = $langs->trans("MemberStatusActive");
2152
				$labelStatusShort = $langs->trans("MemberStatusActiveShort");
2153
			} elseif ($date_end_subscription < time()) {
2154
				$statusType = 'status3';
2155
				$labelStatus = $langs->trans("MemberStatusActiveLate");
2156
				$labelStatusShort = $langs->trans("MemberStatusActiveLateShort");
2157
			} else {
2158
				$statusType = 'status4';
2159
				$labelStatus = $langs->trans("MemberStatusPaid");
2160
				$labelStatusShort = $langs->trans("MemberStatusPaidShort");
2161
			}
2162
		} elseif ($status == 0) {
2163
			$statusType = 'status6';
2164
			$labelStatus = $langs->trans("MemberStatusResiliated");
2165
			$labelStatusShort = $langs->trans("MemberStatusResiliatedShort");
2166
		}
2167
2168
		return dolGetStatus($labelStatus, $labelStatusShort, '', $statusType, $mode);
2169
	}
2170
2171
2172
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2173
	/**
2174
	 *      Charge indicateurs this->nb de tableau de bord
2175
	 *
2176
	 *      @return     int         <0 if KO, >0 if OK
2177
	 */
2178
	public function load_state_board()
2179
	{
2180
		// phpcs:enable
2181
		global $conf;
2182
2183
		$this->nb = array();
2184
2185
		$sql = "SELECT count(a.rowid) as nb";
2186
		$sql .= " FROM ".MAIN_DB_PREFIX."adherent as a";
2187
		$sql .= " WHERE a.statut > 0";
2188
		$sql .= " AND a.entity IN (".getEntity('adherent').")";
2189
2190
		$resql = $this->db->query($sql);
2191
		if ($resql) {
2192
			while ($obj = $this->db->fetch_object($resql)) {
2193
				$this->nb["members"] = $obj->nb;
2194
			}
2195
			$this->db->free($resql);
2196
			return 1;
2197
		} else {
2198
			dol_print_error($this->db);
2199
			$this->error = $this->db->error();
2200
			return -1;
2201
		}
2202
	}
2203
2204
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2205
	/**
2206
	 *      Load indicators for dashboard (this->nbtodo and this->nbtodolate)
2207
	 *
2208
	 *      @param	User	$user   		Objet user
2209
	 *      @param  string	$mode           "expired" for membership to renew, "shift" for member to validate
2210
	 *      @return WorkboardResponse|int 	<0 if KO, WorkboardResponse if OK
2211
	 */
2212
	public function load_board($user, $mode)
2213
	{
2214
		// phpcs:enable
2215
		global $conf, $langs;
2216
2217
		if ($user->socid) return -1; // protection pour eviter appel par utilisateur externe
2218
2219
		$now = dol_now();
2220
2221
		$sql = "SELECT a.rowid, a.datefin, a.statut";
2222
		$sql .= " FROM ".MAIN_DB_PREFIX."adherent as a";
2223
		$sql .= ", ".MAIN_DB_PREFIX."adherent_type as t";
2224
		$sql .= " WHERE a.fk_adherent_type = t.rowid";
2225
		if ($mode == 'expired') {
2226
			$sql .= " AND a.statut = 1";
2227
			$sql .= " AND a.entity IN (".getEntity('adherent').")";
2228
			$sql .= " AND ((a.datefin IS NULL or a.datefin < '".$this->db->idate($now)."') AND t.subscription = '1')";
2229
		} elseif ($mode == 'shift') {
2230
			$sql .= " AND a.statut = -1";
2231
			$sql .= " AND a.entity IN (".getEntity('adherent').")";
2232
		}
2233
2234
		$resql = $this->db->query($sql);
2235
		if ($resql) {
2236
			$langs->load("members");
2237
2238
			$warning_delay = 0;
2239
			$url = '';
2240
			$label = '';
2241
			$labelShort = '';
2242
2243
			if ($mode == 'expired') {
2244
				$warning_delay = $conf->adherent->subscription->warning_delay / 60 / 60 / 24;
2245
				$label = $langs->trans("MembersWithSubscriptionToReceive");
2246
				$labelShort = $langs->trans("MembersWithSubscriptionToReceiveShort");
2247
				$url = DOL_URL_ROOT.'/adherents/list.php?mainmenu=members&amp;statut=1&amp;filter=outofdate';
2248
			} elseif ($mode == 'shift') {
2249
				$warning_delay = $conf->adherent->subscription->warning_delay / 60 / 60 / 24;
2250
				$url = DOL_URL_ROOT.'/adherents/list.php?mainmenu=members&amp;statut=-1';
2251
				$label = $langs->trans("MembersListToValid");
2252
				$labelShort = $langs->trans("ToValidate");
2253
			}
2254
2255
			$response = new WorkboardResponse();
2256
			$response->warning_delay = $warning_delay;
2257
			$response->label = $label;
2258
			$response->labelShort = $labelShort;
2259
			$response->url = $url;
2260
			$response->img = img_object('', "user");
2261
2262
			$adherentstatic = new Adherent($this->db);
2263
2264
			while ($obj = $this->db->fetch_object($resql)) {
2265
				$response->nbtodo++;
2266
2267
				$adherentstatic->datefin = $this->db->jdate($obj->datefin);
2268
				$adherentstatic->statut = $obj->statut;
2269
2270
				if ($adherentstatic->hasDelay()) {
2271
					$response->nbtodolate++;
2272
				}
2273
			}
2274
2275
			return $response;
2276
		} else {
2277
			dol_print_error($this->db);
2278
			$this->error = $this->db->error();
2279
			return -1;
2280
		}
2281
	}
2282
2283
2284
	/**
2285
	 *  Create a document onto disk according to template module.
2286
	 *
2287
	 *  @param	    string		$modele			Force template to use ('' to not force)
2288
	 *  @param		Translate	$outputlangs	objet lang a utiliser pour traduction
2289
	 *  @param      int			$hidedetails    Hide details of lines
2290
	 *  @param      int			$hidedesc       Hide description
2291
	 *  @param      int			$hideref        Hide ref
2292
	 *  @param   null|array  $moreparams     Array to provide more information
2293
	 *  @return     int         				0 if KO, 1 if OK
2294
	 */
2295
	public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
2296
	{
2297
		global $conf, $langs;
2298
2299
		$langs->load("orders");
2300
2301
		if (!dol_strlen($modele)) {
2302
			$modele = 'standard';
2303
2304
			if ($this->model_pdf) {
2305
				$modele = $this->model_pdf;
2306
			} elseif (!empty($conf->global->ADHERENT_ADDON_PDF)) {
2307
				$modele = $conf->global->ADHERENT_ADDON_PDF;
2308
			}
2309
		}
2310
2311
		$modelpath = "core/modules/member/doc/";
2312
2313
		return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
2314
	}
2315
2316
2317
	/**
2318
	 *  Initialise an instance with random values.
2319
	 *  Used to build previews or test instances.
2320
	 *	id must be 0 if object instance is a specimen.
2321
	 *
2322
	 *  @return	int
2323
	 */
2324
	public function initAsSpecimen()
2325
	{
2326
		global $user, $langs;
2327
		$now = dol_now();
2328
2329
		// Initialise parametres
2330
		$this->id = 0;
2331
		$this->ref = 'ABC001';
2332
		$this->entity = 1;
2333
		$this->specimen = 1;
2334
		$this->civility_id = 0;
2335
		$this->lastname = 'DOLIBARR';
2336
		$this->firstname = 'SPECIMEN';
2337
		$this->gender = 'man';
2338
		$this->login = 'dolibspec';
2339
		$this->pass = 'dolibspec';
2340
		$this->company = 'Societe ABC';
2341
		$this->address = '61 jump street';
2342
		$this->zip = '75000';
2343
		$this->town = 'Paris';
2344
		$this->country_id = 1;
2345
		$this->country_code = 'FR';
2346
		$this->country = 'France';
2347
		$this->morphy = 'mor';
2348
		$this->email = '[email protected]';
2349
		$this->socialnetworks = array(
2350
			'skype' => 'skypepseudo',
2351
			'twitter' => 'twitterpseudo',
2352
			'facebook' => 'facebookpseudo',
2353
			'linkedin' => 'linkedinpseudo',
2354
		);
2355
		$this->phone = '0999999999';
2356
		$this->phone_perso = '0999999998';
2357
		$this->phone_mobile = '0999999997';
2358
		$this->note_public = 'This is a public note';
2359
		$this->note_private = 'This is a private note';
2360
		$this->birth = $now;
2361
		$this->photo = '';
2362
		$this->public = 1;
2363
		$this->statut = 0;
2364
2365
		$this->datefin = $now;
2366
		$this->datevalid = $now;
2367
2368
		$this->typeid = 1; // Id type adherent
2369
		$this->type = 'Type adherent'; // Libelle type adherent
2370
		$this->need_subscription = 0;
2371
2372
		$this->first_subscription_date = $now;
2373
		$this->first_subscription_date_start = $this->first_subscription_date;
2374
		$this->first_subscription_date_end = dol_time_plus_duree($this->first_subscription_date_start, 1, 'y');
2375
		$this->first_subscription_amount = 10;
2376
2377
		$this->last_subscription_date = $this->first_subscription_date;
2378
		$this->last_subscription_date_start = $this->first_subscription_date;
2379
		$this->last_subscription_date_end = dol_time_plus_duree($this->last_subscription_date_start, 1, 'y');
2380
		$this->last_subscription_amount = 10;
2381
		return 1;
2382
	}
2383
2384
2385
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2386
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
2387
	/**
2388
	 *	Retourne chaine DN complete dans l'annuaire LDAP pour l'objet
2389
	 *
2390
	 *	@param	array	$info		Info array loaded by _load_ldap_info
2391
	 *	@param	int		$mode		0=Return full DN (uid=qqq,ou=xxx,dc=aaa,dc=bbb)
2392
	 *								1=Return DN without key inside (ou=xxx,dc=aaa,dc=bbb)
2393
	 *								2=Return key only (uid=qqq)
2394
	 *	@return	string				DN
2395
	 */
2396
	public function _load_ldap_dn($info, $mode = 0)
2397
	{
2398
		// phpcs:enable
2399
		global $conf;
2400
		$dn = '';
2401
		if ($mode == 0) $dn = $conf->global->LDAP_KEY_MEMBERS."=".$info[$conf->global->LDAP_KEY_MEMBERS].",".$conf->global->LDAP_MEMBER_DN;
2402
		if ($mode == 1) $dn = $conf->global->LDAP_MEMBER_DN;
2403
		if ($mode == 2) $dn = $conf->global->LDAP_KEY_MEMBERS."=".$info[$conf->global->LDAP_KEY_MEMBERS];
2404
		return $dn;
2405
	}
2406
2407
2408
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2409
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
2410
	/**
2411
	 *	Initialise tableau info (tableau des attributs LDAP)
2412
	 *
2413
	 *	@return		array		Tableau info des attributs
2414
	 */
2415
	public function _load_ldap_info()
2416
	{
2417
		// phpcs:enable
2418
		global $conf, $langs;
2419
2420
		$info = array();
2421
		$socialnetworks = getArrayOfSocialNetworks();
2422
		$keymodified = false;
2423
2424
		// Object classes
2425
		$info["objectclass"] = explode(',', $conf->global->LDAP_MEMBER_OBJECT_CLASS);
2426
2427
		$this->fullname = $this->getFullName($langs);
2428
2429
		// For avoid ldap error when firstname and lastname are empty
2430
		if ($this->morphy == 'mor' && (empty($this->fullname) || $this->fullname == $this->company)) {
2431
			$this->fullname = $this->company;
2432
			$this->lastname = $this->company;
2433
		}
2434
2435
		// Possible LDAP KEY (constname => varname)
2436
		$ldapkey = array(
2437
			'LDAP_MEMBER_FIELD_FULLNAME' => 'fullname',
2438
			'LDAP_MEMBER_FIELD_NAME' => 'lastname',
2439
			'LDAP_MEMBER_FIELD_LOGIN' => 'login',
2440
			'LDAP_MEMBER_FIELD_LOGIN_SAMBA' => 'login',
2441
			'LDAP_MEMBER_FIELD_MAIL' => 'email'
2442
		);
2443
2444
		// Member
2445
		foreach ($ldapkey as $constname => $varname) {
2446
			if (!empty($this->$varname) && !empty($conf->global->$constname)) {
2447
				$info[$conf->global->$constname] = $this->$varname;
2448
2449
				// Check if it is the LDAP key and if its value has been changed
2450
				if (!empty($conf->global->LDAP_KEY_MEMBERS) && $conf->global->LDAP_KEY_MEMBERS == $conf->global->$constname) {
2451
					if (!empty($this->oldcopy) && $this->$varname != $this->oldcopy->$varname) $keymodified = true; // For check if LDAP key has been modified
2452
				}
2453
			}
2454
		}
2455
		if ($this->firstname && !empty($conf->global->LDAP_MEMBER_FIELD_FIRSTNAME)) $info[$conf->global->LDAP_MEMBER_FIELD_FIRSTNAME] = $this->firstname;
2456
		if ($this->poste && !empty($conf->global->LDAP_MEMBER_FIELD_TITLE)) $info[$conf->global->LDAP_MEMBER_FIELD_TITLE] = $this->poste;
2457
		if ($this->company && !empty($conf->global->LDAP_MEMBER_FIELD_COMPANY)) $info[$conf->global->LDAP_MEMBER_FIELD_COMPANY] = $this->company;
2458
		if ($this->address && !empty($conf->global->LDAP_MEMBER_FIELD_ADDRESS)) $info[$conf->global->LDAP_MEMBER_FIELD_ADDRESS] = $this->address;
2459
		if ($this->zip && !empty($conf->global->LDAP_MEMBER_FIELD_ZIP)) $info[$conf->global->LDAP_MEMBER_FIELD_ZIP] = $this->zip;
2460
		if ($this->town && !empty($conf->global->LDAP_MEMBER_FIELD_TOWN)) $info[$conf->global->LDAP_MEMBER_FIELD_TOWN] = $this->town;
2461
		if ($this->country_code && !empty($conf->global->LDAP_MEMBER_FIELD_COUNTRY)) $info[$conf->global->LDAP_MEMBER_FIELD_COUNTRY] = $this->country_code;
2462
		foreach ($socialnetworks as $key => $value) {
2463
			if ($this->socialnetworks[$value['label']] && !empty($conf->global->{'LDAP_MEMBER_FIELD_'.strtoupper($value['label'])})) {
2464
				$info[$conf->global->{'LDAP_MEMBER_FIELD_'.strtoupper($value['label'])}] = $this->socialnetworks[$value['label']];
2465
			}
2466
		}
2467
		if ($this->phone && !empty($conf->global->LDAP_MEMBER_FIELD_PHONE)) $info[$conf->global->LDAP_MEMBER_FIELD_PHONE] = $this->phone;
2468
		if ($this->phone_perso && !empty($conf->global->LDAP_MEMBER_FIELD_PHONE_PERSO)) $info[$conf->global->LDAP_MEMBER_FIELD_PHONE_PERSO] = $this->phone_perso;
2469
		if ($this->phone_mobile && !empty($conf->global->LDAP_MEMBER_FIELD_MOBILE)) $info[$conf->global->LDAP_MEMBER_FIELD_MOBILE] = $this->phone_mobile;
2470
		if ($this->fax && !empty($conf->global->LDAP_MEMBER_FIELD_FAX)) $info[$conf->global->LDAP_MEMBER_FIELD_FAX] = $this->fax;
2471
		if ($this->note_private && !empty($conf->global->LDAP_MEMBER_FIELD_DESCRIPTION)) $info[$conf->global->LDAP_MEMBER_FIELD_DESCRIPTION] = dol_string_nohtmltag($this->note_private, 2);
2472
		if ($this->note_public && !empty($conf->global->LDAP_MEMBER_FIELD_NOTE_PUBLIC)) $info[$conf->global->LDAP_MEMBER_FIELD_NOTE_PUBLIC] = dol_string_nohtmltag($this->note_public, 2);
2473
		if ($this->birth && !empty($conf->global->LDAP_MEMBER_FIELD_BIRTHDATE)) $info[$conf->global->LDAP_MEMBER_FIELD_BIRTHDATE] = dol_print_date($this->birth, 'dayhourldap');
2474
		if (isset($this->statut) && !empty($conf->global->LDAP_FIELD_MEMBER_STATUS)) $info[$conf->global->LDAP_FIELD_MEMBER_STATUS] = $this->statut;
2475
		if ($this->datefin && !empty($conf->global->LDAP_FIELD_MEMBER_END_LASTSUBSCRIPTION)) $info[$conf->global->LDAP_FIELD_MEMBER_END_LASTSUBSCRIPTION] = dol_print_date($this->datefin, 'dayhourldap');
2476
2477
		// When password is modified
2478
		if (!empty($this->pass)) {
2479
			if (!empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD)) {
2480
				$info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD] = $this->pass; // this->pass = mot de passe non crypte
2481
			}
2482
			if (!empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED)) {
2483
				$info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED] = dol_hash($this->pass, 4); // Create OpenLDAP MD5 password (TODO add type of encryption)
2484
			}
2485
		} // Set LDAP password if possible
2486
		elseif ($conf->global->LDAP_SERVER_PROTOCOLVERSION !== '3') { // If ldap key is modified and LDAPv3 we use ldap_rename function for avoid lose encrypt password
2487
			if (!empty($conf->global->DATABASE_PWD_ENCRYPTED)) {
2488
				// Just for the default MD5 !
2489
				if (empty($conf->global->MAIN_SECURITY_HASH_ALGO)) {
2490
					if ($this->pass_indatabase_crypted && !empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED)) {
2491
						// Create OpenLDAP MD5 password from Dolibarr MD5 password
2492
						// Note: This suppose that "pass_indatabase_crypted" is a md5 (guaranted by the previous test if "(empty($conf->global->MAIN_SECURITY_HASH_ALGO))"
2493
						$info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED] = '{md5}'.base64_encode(hex2bin($this->pass_indatabase_crypted));
2494
					}
2495
				}
2496
			} // Use $this->pass_indatabase value if exists
2497
			elseif (!empty($this->pass_indatabase)) {
2498
				if (!empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD)) $info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD] = $this->pass_indatabase; // $this->pass_indatabase = mot de passe non crypte
2499
				if (!empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED)) $info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED] = dol_hash($this->pass_indatabase, 4); // md5 for OpenLdap TODO add type of encryption
2500
			}
2501
		}
2502
2503
		// Subscriptions
2504
		if ($this->first_subscription_date && !empty($conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_DATE)) $info[$conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_DATE] = dol_print_date($this->first_subscription_date, 'dayhourldap');
2505
		if (isset($this->first_subscription_amount) && !empty($conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_AMOUNT)) $info[$conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_AMOUNT] = $this->first_subscription_amount;
2506
		if ($this->last_subscription_date && !empty($conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_DATE)) $info[$conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_DATE] = dol_print_date($this->last_subscription_date, 'dayhourldap');
2507
		if (isset($this->last_subscription_amount) && !empty($conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_AMOUNT)) $info[$conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_AMOUNT] = $this->last_subscription_amount;
2508
2509
		return $info;
2510
	}
2511
2512
2513
	/**
2514
	 *      Load type info information in the member object
2515
	 *
2516
	 *      @param  int		$id       Id of member to load
2517
	 *      @return	void
2518
	 */
2519
	public function info($id)
2520
	{
2521
		$sql = 'SELECT a.rowid, a.datec as datec,';
2522
		$sql .= ' a.datevalid as datev,';
2523
		$sql .= ' a.tms as datem,';
2524
		$sql .= ' a.fk_user_author, a.fk_user_valid, a.fk_user_mod';
2525
		$sql .= ' FROM '.MAIN_DB_PREFIX.'adherent as a';
2526
		$sql .= ' WHERE a.rowid = '.$id;
2527
2528
		dol_syslog(get_class($this)."::info", LOG_DEBUG);
2529
		$result = $this->db->query($sql);
2530
		if ($result) {
2531
			if ($this->db->num_rows($result)) {
2532
				$obj = $this->db->fetch_object($result);
2533
				$this->id = $obj->rowid;
2534
				if ($obj->fk_user_author) {
2535
					$cuser = new User($this->db);
2536
					$cuser->fetch($obj->fk_user_author);
2537
					$this->user_creation = $cuser;
2538
				}
2539
2540
				if ($obj->fk_user_valid) {
2541
					$vuser = new User($this->db);
2542
					$vuser->fetch($obj->fk_user_valid);
2543
					$this->user_validation = $vuser;
2544
				}
2545
2546
				if ($obj->fk_user_mod) {
2547
					$muser = new User($this->db);
2548
					$muser->fetch($obj->fk_user_mod);
2549
					$this->user_modification = $muser;
2550
				}
2551
2552
				$this->date_creation = $this->db->jdate($obj->datec);
2553
				$this->date_validation = $this->db->jdate($obj->datev);
2554
				$this->date_modification = $this->db->jdate($obj->datem);
2555
			}
2556
2557
			$this->db->free($result);
2558
		} else {
2559
			dol_print_error($this->db);
2560
		}
2561
	}
2562
2563
	/**
2564
	 *  Return number of mass Emailing received by this member with its email
2565
	 *
2566
	 *  @return       int     Number of EMailings
2567
	 */
2568
	public function getNbOfEMailings()
2569
	{
2570
		$sql = "SELECT count(mc.email) as nb";
2571
		$sql .= " FROM ".MAIN_DB_PREFIX."mailing_cibles as mc";
2572
		$sql .= " WHERE mc.email = '".$this->db->escape($this->email)."'";
2573
		$sql .= " AND mc.statut NOT IN (-1,0)"; // -1 erreur, 0 non envoye, 1 envoye avec succes
2574
2575
		$resql = $this->db->query($sql);
2576
		if ($resql) {
2577
			$obj = $this->db->fetch_object($resql);
2578
			$nb = $obj->nb;
2579
2580
			$this->db->free($resql);
2581
			return $nb;
2582
		} else {
2583
			$this->error = $this->db->error();
2584
			return -1;
2585
		}
2586
	}
2587
2588
	/**
2589
	 * Sets object to supplied categories.
2590
	 *
2591
	 * Deletes object from existing categories not supplied.
2592
	 * Adds it to non existing supplied categories.
2593
	 * Existing categories are left untouch.
2594
	 *
2595
	 * @param int[]|int $categories Category or categories IDs
2596
	 * @return void
2597
	 */
2598
	public function setCategories($categories)
2599
	{
2600
		require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
2601
		return parent::setCategoriesCommon($categories, Categorie::TYPE_MEMBER);
2602
	}
2603
2604
	/**
2605
	 * Function used to replace a thirdparty id with another one.
2606
	 *
2607
	 * @param DoliDB 	$db 			Database handler
2608
	 * @param int 		$origin_id 		Old thirdparty id
2609
	 * @param int 		$dest_id 		New thirdparty id
2610
	 * @return bool
2611
	 */
2612
	public static function replaceThirdparty($db, $origin_id, $dest_id)
2613
	{
2614
		$tables = array('adherent');
2615
2616
		return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
2617
	}
2618
2619
	/**
2620
	 * Return if a member is late (subscription late) or not
2621
	 *
2622
	 * @return boolean     True if late, False if not late
2623
	 */
2624
	public function hasDelay()
2625
	{
2626
		global $conf;
2627
2628
		//Only valid members
2629
		if ($this->statut <= 0) return false;
2630
		if (!$this->datefin) return false;
2631
2632
		$now = dol_now();
2633
2634
		return $this->datefin < ($now - $conf->adherent->subscription->warning_delay);
2635
	}
2636
2637
2638
	/**
2639
	 * Send reminders by emails before subscription end
2640
	 * CAN BE A CRON TASK
2641
	 *
2642
	 * @param	string		$daysbeforeendlist		Nb of days before end of subscription (negative number = after subscription). Can be a list of delay, separated by a semicolon, for example '10;5;0;-5'
2643
	 * @return	int									0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK)
2644
	 */
2645
	public function sendReminderForExpiredSubscription($daysbeforeendlist = '10')
2646
	{
2647
		global $conf, $langs, $mysoc, $user;
2648
2649
		$error = 0;
2650
		$this->output = '';
2651
		$this->error = '';
2652
2653
		$blockingerrormsg = '';
2654
2655
		if (empty($conf->adherent->enabled)) { // Should not happen. If module disabled, cron job should not be visible.
2656
			$langs->load("agenda");
2657
			$this->output = $langs->trans('ModuleNotEnabled', $langs->transnoentitiesnoconv("Adherent"));
2658
			return 0;
2659
		}
2660
		if (empty($conf->global->MEMBER_REMINDER_EMAIL)) {
2661
			$langs->load("agenda");
2662
			$this->output = $langs->trans('EventRemindersByEmailNotEnabled', $langs->transnoentitiesnoconv("Adherent"));
2663
			return 0;
2664
		}
2665
2666
		$now = dol_now();
2667
		$nbok = 0;
2668
		$nbko = 0;
2669
2670
		$listofmembersok = array();
2671
		$listofmembersko = array();
2672
2673
		$arraydaysbeforeend = explode(';', $daysbeforeendlist);
2674
		foreach ($arraydaysbeforeend as $daysbeforeend) { // Loop on each delay
2675
			dol_syslog(__METHOD__.' - Process delta = '.$daysbeforeend, LOG_DEBUG);
2676
2677
			if (!is_numeric($daysbeforeend)) {
2678
				$blockingerrormsg = "Value for delta is not a positive or negative numeric";
2679
				$nbko++;
2680
				break;
2681
			}
2682
2683
			$tmp = dol_getdate($now);
2684
			$datetosearchfor = dol_time_plus_duree(dol_mktime(0, 0, 0, $tmp['mon'], $tmp['mday'], $tmp['year']), $daysbeforeend, 'd');
2685
2686
			$sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'adherent';
2687
			$sql .= " WHERE entity = ".$conf->entity; // Do not use getEntity('adherent').")" here, we want the batch to be on its entity only;
2688
			$sql .= " AND datefin = '".$this->db->idate($datetosearchfor)."'";
2689
2690
			$resql = $this->db->query($sql);
2691
			if ($resql) {
2692
				$num_rows = $this->db->num_rows($resql);
2693
2694
				include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
2695
				$adherent = new Adherent($this->db);
2696
				$formmail = new FormMail($this->db);
2697
2698
				$i = 0;
2699
				while ($i < $num_rows) {
2700
					$obj = $this->db->fetch_object($resql);
2701
2702
					$adherent->fetch($obj->rowid, '', '', '', true, true);
2703
2704
					if (empty($adherent->email)) {
2705
						$nbko++;
2706
						$listofmembersko[$adherent->id] = $adherent->id;
2707
					} else {
2708
						$adherent->fetch_thirdparty();
2709
2710
						// 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.
2711
						$languagefromcountrycode = getLanguageCodeFromCountryCode($adherent->country_code ? $adherent->country_code : $adherent->thirdparty->country_code);
2712
						$languagecodeformember = (empty($adherent->thirdparty->default_lang) ? ($languagefromcountrycode ? $languagefromcountrycode : $mysoc->default_lang) : $adherent->thirdparty->default_lang);
2713
2714
						// Send reminder email
2715
						$outputlangs = new Translate('', $conf);
2716
						$outputlangs->setDefaultLang($languagecodeformember);
2717
						$outputlangs->loadLangs(array("main", "members"));
2718
						dol_syslog("sendReminderForExpiredSubscription Language for member id ".$adherent->id." set to ".$outputlangs->defaultlang." mysoc->default_lang=".$mysoc->default_lang);
2719
2720
						$arraydefaultmessage = null;
2721
						$labeltouse = $conf->global->ADHERENT_EMAIL_TEMPLATE_REMIND_EXPIRATION;
2722
2723
						if (!empty($labeltouse)) $arraydefaultmessage = $formmail->getEMailTemplate($this->db, 'member', $user, $outputlangs, 0, 1, $labeltouse);
2724
2725
						if (!empty($labeltouse) && is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) {
2726
							$substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $adherent);
2727
							//if (is_array($adherent->thirdparty)) $substitutionarraycomp = ...
2728
							complete_substitutions_array($substitutionarray, $outputlangs, $adherent);
2729
2730
							$subject = make_substitutions($arraydefaultmessage->topic, $substitutionarray, $outputlangs);
2731
							$msg = make_substitutions($arraydefaultmessage->content, $substitutionarray, $outputlangs);
2732
							$from = $conf->global->ADHERENT_MAIL_FROM;
2733
							$to = $adherent->email;
2734
2735
							$trackid = 'mem'.$adherent->id;
2736
							$moreinheader = 'X-Dolibarr-Info: sendReminderForExpiredSubscription'."\r\n";
2737
2738
							include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
2739
							$cmail = new CMailFile($subject, $to, $from, $msg, array(), array(), array(), '', '', 0, 1, '', '', $trackid, $moreinheader);
2740
							$result = $cmail->sendfile();
2741
							if (!$result) {
2742
								$error++;
2743
								$this->error = $cmail->error;
2744
								if (!is_null($cmail->errors)) {
2745
									$this->errors += $cmail->errors;
2746
								}
2747
								$nbko++;
2748
								$listofmembersko[$adherent->id] = $adherent->id;
2749
							} else {
2750
								$nbok++;
2751
								$listofmembersok[$adherent->id] = $adherent->id;
2752
2753
								$message = $msg;
2754
								$sendto = $to;
2755
								$sendtocc = '';
2756
								$sendtobcc = '';
2757
								$actioncode = 'EMAIL';
2758
								$extraparams = '';
2759
2760
								$actionmsg = '';
2761
								$actionmsg2 = $langs->transnoentities('MailSentBy').' '.CMailFile::getValidAddress($from, 4, 0, 1).' '.$langs->transnoentities('To').' '.
2762
									CMailFile::getValidAddress($sendto, 4, 0, 1);
2763
								if ($message) {
2764
									$actionmsg = $langs->transnoentities('MailFrom').': '.dol_escape_htmltag($from);
2765
									$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTo').': '.dol_escape_htmltag($sendto));
2766
									if ($sendtocc) $actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('Bcc').": ".dol_escape_htmltag($sendtocc));
2767
									$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTopic').": ".$subject);
2768
									$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('TextUsedInTheMessageBody').":");
2769
									$actionmsg = dol_concatdesc($actionmsg, $message);
2770
								}
2771
2772
								require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
2773
2774
								// Insert record of emails sent
2775
								$actioncomm = new ActionComm($this->db);
2776
2777
								$actioncomm->type_code = 'AC_OTH_AUTO'; // Type of event ('AC_OTH', 'AC_OTH_AUTO', 'AC_XXX'...)
2778
								$actioncomm->code = 'AC_'.$actioncode;
2779
								$actioncomm->label = $actionmsg2;
2780
								$actioncomm->note_private = $actionmsg;
2781
								$actioncomm->fk_project = 0;
2782
								$actioncomm->datep = $now;
2783
								$actioncomm->datef = $now;
2784
								$actioncomm->percentage = -1; // Not applicable
2785
								$actioncomm->socid = $adherent->thirdparty->id;
2786
								$actioncomm->contact_id = 0;
2787
								$actioncomm->authorid = $user->id; // User saving action
2788
								$actioncomm->userownerid = $user->id; // Owner of action
2789
								// Fields when action is en email (content should be added into note)
2790
								$actioncomm->email_msgid = $cmail->msgid;
2791
								$actioncomm->email_from = $from;
2792
								$actioncomm->email_sender = '';
2793
								$actioncomm->email_to = $to;
2794
								$actioncomm->email_tocc = $sendtocc;
2795
								$actioncomm->email_tobcc = $sendtobcc;
2796
								$actioncomm->email_subject = $subject;
2797
								$actioncomm->errors_to = '';
2798
2799
								$actioncomm->fk_element = $adherent->id;
2800
								$actioncomm->elementtype = $adherent->element;
2801
2802
								$actioncomm->extraparams = $extraparams;
2803
2804
								$actioncomm->create($user);
2805
							}
2806
						} else {
2807
							$blockingerrormsg = "Can't find email template, defined into member module setup, to use for reminding";
2808
2809
							$nbko++;
2810
							$listofmembersko[$adherent->id] = $adherent->id;
2811
2812
							break;
2813
						}
2814
					}
2815
2816
					$i++;
2817
				}
2818
			} else {
2819
				$this->error = $this->db->lasterror();
2820
				return 1;
2821
			}
2822
		}
2823
2824
		if ($blockingerrormsg) {
2825
			$this->error = $blockingerrormsg;
2826
			return 1;
2827
		} else {
2828
			$this->output = 'Found '.($nbok + $nbko).' members to send reminder to.';
2829
			$this->output .= ' Send email successfuly to '.$nbok.' members';
2830
			if (is_array($listofmembersok)) {
2831
				$listofids = '';
2832
				$i = 0;
2833
				foreach ($listofmembersok as $idmember) {
2834
					if ($i > 100) {
2835
						$listofids .= ', ...';
2836
						break;
2837
					}
2838
					if (empty($listofids)) {
2839
						$listofids .= ' [';
2840
					} else {
2841
						$listofids .= ', ';
2842
					}
2843
					$listofids .= $idmember;
2844
					$i++;
2845
				}
2846
				if ($listofids) $listofids .= ']';
2847
				$this->output .= $listofids;
2848
			}
2849
			if ($nbko) {
2850
				$this->output .= ' - Canceled for '.$nbko.' member (no email or email sending error)';
2851
				if (is_array($listofmembersko)) {
2852
					$listofids = '';
2853
					$i = 0;
2854
					foreach ($listofmembersko as $idmember) {
2855
						if ($i > 100) {
2856
							$listofids .= ', ...';
2857
							break;
2858
						}
2859
						if (empty($listofids)) {
2860
							$listofids .= ' [';
2861
						} else {
2862
							$listofids .= ', ';
2863
						}
2864
						$listofids .= $idmember;
2865
						$i++;
2866
					}
2867
					if ($listofids) $listofids .= ']';
2868
					$this->output .= $listofids;
2869
				}
2870
			}
2871
		}
2872
2873
		return 0;
2874
	}
2875
}
2876