Passed
Branch develop (cac63d)
by
unknown
42:43
created

Adherent::getNomUrl()   D

Complexity

Conditions 41

Size

Total Lines 118
Code Lines 80

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 41
eloc 80
nop 8
dl 0
loc 118
rs 4.1666
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
 * Copyright (C) 2021		Waël Almoman            <[email protected]>
17
 *
18
 * This program is free software; you can redistribute it and/or modify
19
 * it under the terms of the GNU General Public License as published by
20
 * the Free Software Foundation; either version 3 of the License, or
21
 * (at your option) any later version.
22
 *
23
 * This program is distributed in the hope that it will be useful,
24
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26
 * GNU General Public License for more details.
27
 *
28
 * You should have received a copy of the GNU General Public License
29
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
30
 */
31
32
/**
33
 *	\file       htdocs/adherents/class/adherent.class.php
34
 *	\ingroup    member
35
 *	\brief      File of class to manage members of a foundation
36
 */
37
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
38
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
39
require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
40
41
42
/**
43
 *		Class to manage members of a foundation
44
 */
45
class Adherent extends CommonObject
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 string url
145
	 */
146
	public $url;
147
148
	/**
149
	 * @var array array of socialnetworks
150
	 */
151
	public $socialnetworks;
152
153
	/**
154
	 * @var string skype account
155
	 * @deprecated
156
	 */
157
	public $skype;
158
159
	/**
160
	 * @var string twitter account
161
	 * @deprecated
162
	 */
163
	public $twitter;
164
165
	/**
166
	 * @var string facebook account
167
	 * @deprecated
168
	 */
169
	public $facebook;
170
171
	/**
172
	 * @var string linkedin account
173
	 * @deprecated
174
	 */
175
	public $linkedin;
176
177
	/**
178
	 * @var string Phone number
179
	 */
180
	public $phone;
181
182
	/**
183
	 * @var string Private Phone number
184
	 */
185
	public $phone_perso;
186
187
	/**
188
	 * @var string Professional Phone number
189
	 */
190
	public $phone_pro;
191
192
	/**
193
	 * @var string Mobile phone number
194
	 */
195
	public $phone_mobile;
196
197
	/**
198
	 * @var string Fax number
199
	 */
200
	public $fax;
201
202
	/**
203
	 * @var string Function
204
	 */
205
	public $poste;
206
207
	/**
208
	 * @var string mor or phy
209
	 */
210
	public $morphy;
211
212
	/**
213
	 * @var int Info can be public
214
	 */
215
	public $public;
216
217
	/**
218
	 * @var string photo of member
219
	 */
220
	public $photo;
221
222
	/**
223
	 * Date creation record (datec)
224
	 *
225
	 * @var integer
226
	 */
227
	public $datec;
228
229
	/**
230
	 * Date modification record (tms)
231
	 *
232
	 * @var integer
233
	 */
234
	public $datem;
235
236
	public $datevalid;
237
238
	/**
239
	 * @var string gender
240
	 */
241
	public $gender;
242
243
	public $birth;
244
245
	/**
246
	 * @var int id type member
247
	 */
248
	public $typeid;
249
250
	/**
251
	 * @var string label type member
252
	 */
253
	public $type;
254
255
	public $need_subscription;
256
257
	public $user_id;
258
259
	public $user_login;
260
261
	public $datefin;
262
263
264
	// Fields loaded by fetch_subscriptions() from member table
265
266
	public $first_subscription_date;
267
268
	public $first_subscription_amount;
269
270
	public $last_subscription_date;
271
272
	public $last_subscription_date_start;
273
274
	public $last_subscription_date_end;
275
276
	public $last_subscription_amount;
277
278
	public $subscriptions = array();
279
280
281
	// Fields loaded by fetchPartnerships() from partnership table
282
283
	public $partnerships = array();
284
285
286
	/**
287
	 * @var Adherent To contains a clone of this when we need to save old properties of object
288
	 */
289
	public $oldcopy;
290
291
	/**
292
	 * @var int Entity
293
	 */
294
	public $entity;
295
296
	/**
297
	 * @var array fields
298
	 */
299
	public $fields = array(
300
		'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 10),
301
		'ref' => array('type' => 'varchar(30)', 'label' => 'Ref', 'default' => 1, 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 12, 'index' => 1),
302
		'entity' => array('type' => 'integer', 'label' => 'Entity', 'default' => 1, 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 15, 'index' => 1),
303
		'ref_ext' => array('type' => 'varchar(128)', 'label' => 'Ref ext', 'enabled' => 1, 'visible' => 0, 'position' => 20),
304
		'civility' => array('type' => 'varchar(6)', 'label' => 'Civility', 'enabled' => 1, 'visible' => -1, 'position' => 25),
305
		'lastname' => array('type' => 'varchar(50)', 'label' => 'Lastname', 'enabled' => 1, 'visible' => -1, 'position' => 30, 'showoncombobox'=>1),
306
		'firstname' => array('type' => 'varchar(50)', 'label' => 'Firstname', 'enabled' => 1, 'visible' => -1, 'position' => 35, 'showoncombobox'=>1),
307
		'login' => array('type' => 'varchar(50)', 'label' => 'Login', 'enabled' => 1, 'visible' => -1, 'position' => 40),
308
		'gender' => array('type' => 'varchar(10)', 'label' => 'Gender', 'enabled' => 1, 'visible' => -1, 'position' => 250),
309
		'pass' => array('type' => 'varchar(50)', 'label' => 'Pass', 'enabled' => 1, 'visible' => -1, 'position' => 45),
310
		'pass_crypted' => array('type' => 'varchar(128)', 'label' => 'Pass crypted', 'enabled' => 1, 'visible' => -1, 'position' => 50),
311
		'fk_adherent_type' => array('type' => 'integer', 'label' => 'Fk adherent type', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 55),
312
		'morphy' => array('type' => 'varchar(3)', 'label' => 'MorPhy', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 60),
313
		'societe' => array('type' => 'varchar(128)', 'label' => 'Societe', 'enabled' => 1, 'visible' => -1, 'position' => 65, 'showoncombobox'=>2),
314
		'fk_soc' => array('type' => 'integer:Societe:societe/class/societe.class.php', 'label' => 'ThirdParty', 'enabled' => 1, 'visible' => -1, 'position' => 70),
315
		'address' => array('type' => 'text', 'label' => 'Address', 'enabled' => 1, 'visible' => -1, 'position' => 75),
316
		'zip' => array('type' => 'varchar(10)', 'label' => 'Zip', 'enabled' => 1, 'visible' => -1, 'position' => 80),
317
		'town' => array('type' => 'varchar(50)', 'label' => 'Town', 'enabled' => 1, 'visible' => -1, 'position' => 85),
318
		'state_id' => array('type' => 'integer', 'label' => 'State id', 'enabled' => 1, 'visible' => -1, 'position' => 90),
319
		'country' => array('type' => 'integer:Ccountry:core/class/ccountry.class.php', 'label' => 'Country', 'enabled' => 1, 'visible' => -1, 'position' => 95),
320
		'email' => array('type' => 'varchar(255)', 'label' => 'Email', 'enabled' => 1, 'visible' => -1, 'position' => 100),
321
		'url' =>array('type'=>'varchar(255)', 'label'=>'Url', 'enabled'=>1, 'visible'=>-1, 'position'=>110),
322
		'socialnetworks' => array('type' => 'text', 'label' => 'Socialnetworks', 'enabled' => 1, 'visible' => -1, 'position' => 105),
323
		'phone' => array('type' => 'varchar(30)', 'label' => 'Phone', 'enabled' => 1, 'visible' => -1, 'position' => 115),
324
		'phone_perso' => array('type' => 'varchar(30)', 'label' => 'Phone perso', 'enabled' => 1, 'visible' => -1, 'position' => 120),
325
		'phone_mobile' => array('type' => 'varchar(30)', 'label' => 'Phone mobile', 'enabled' => 1, 'visible' => -1, 'position' => 125),
326
		'birth' => array('type' => 'date', 'label' => 'DateOfBirth', 'enabled' => 1, 'visible' => -1, 'position' => 130),
327
		'photo' => array('type' => 'varchar(255)', 'label' => 'Photo', 'enabled' => 1, 'visible' => -1, 'position' => 135),
328
		'public' => array('type' => 'smallint(6)', 'label' => 'Public', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 145),
329
		'datefin' => array('type' => 'datetime', 'label' => 'DateEnd', 'enabled' => 1, 'visible' => -1, 'position' => 150),
330
		'note_private' => array('type' => 'text', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 155),
331
		'note_public' => array('type' => 'text', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 160),
332
		'datevalid' => array('type' => 'datetime', 'label' => 'DateValidation', 'enabled' => 1, 'visible' => -1, 'position' => 165),
333
		'datec' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -1, 'position' => 170),
334
		'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 175),
335
		'fk_user_author' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'Fk user author', 'enabled' => 1, 'visible' => -1, 'position' => 180),
336
		'fk_user_mod' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'Fk user mod', 'enabled' => 1, 'visible' => -1, 'position' => 185),
337
		'fk_user_valid' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserValidation', 'enabled' => 1, 'visible' => -1, 'position' => 190),
338
		'canvas' => array('type' => 'varchar(32)', 'label' => 'Canvas', 'enabled' => 1, 'visible' => -1, 'position' => 195),
339
		'statut' => array('type' => 'smallint(6)', 'label' => 'Statut', 'enabled' => 1, 'visible' => -1, 'notnull' => 1, 'position' => 500,
340
		'arrayofkeyval' => array(-1 => 'Draft', 1 => 'Validated', 0 => 'MemberStatusResiliatedShort', -2 => 'MemberStatusExcludedShort')),
341
		'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'visible' => 0, 'position' => 800),
342
		'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -2, 'position' => 805)
343
	);
344
345
	/**
346
	 * Draft status
347
	 */
348
	const STATUS_DRAFT = -1;
349
	/**
350
	 * Validated status
351
	 */
352
	const STATUS_VALIDATED = 1;
353
	/**
354
	 * Resiliated
355
	 */
356
	const STATUS_RESILIATED = 0;
357
	/**
358
	 * Excluded
359
	 */
360
	const STATUS_EXCLUDED = -2;
361
362
363
	/**
364
	 *	Constructor
365
	 *
366
	 *	@param 		DoliDB		$db		Database handler
367
	 */
368
	public function __construct($db)
369
	{
370
		$this->db = $db;
371
		$this->statut = self::STATUS_DRAFT;
372
		$this->status = $this->statut;
373
		// l'adherent n'est pas public par defaut
374
		$this->public = 0;
375
		// les champs optionnels sont vides
376
		$this->array_options = array();
377
	}
378
379
380
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
381
	/**
382
	 *  Function sending an email to the current member with the text supplied in parameter.
383
	 *
384
	 *  @param	string	$text				Content of message (not html entities encoded)
385
	 *  @param	string	$subject			Subject of message
386
	 *  @param 	array	$filename_list      Array of attached files
387
	 *  @param 	array	$mimetype_list      Array of mime types of attached files
388
	 *  @param 	array	$mimefilename_list  Array of public names of attached files
389
	 *  @param 	string	$addr_cc            Email cc
390
	 *  @param 	string	$addr_bcc           Email bcc
391
	 *  @param 	int		$deliveryreceipt	Ask a delivery receipt
392
	 *  @param	int		$msgishtml			1=String IS already html, 0=String IS NOT html, -1=Unknown need autodetection
393
	 *  @param	string	$errors_to			erros to
394
	 *  @param	string	$moreinheader		Add more html headers
395
	 *  @return	int							<0 if KO, >0 if OK
396
	 */
397
	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 = '')
398
	{
399
		// phpcs:enable
400
		global $conf, $langs;
401
402
		// Detect if message is HTML
403
		if ($msgishtml == -1) {
404
			$msgishtml = 0;
405
			if (dol_textishtml($text, 0)) {
406
				$msgishtml = 1;
407
			}
408
		}
409
410
		dol_syslog('send_an_email msgishtml='.$msgishtml);
411
412
		$texttosend = $this->makeSubstitution($text);
413
		$subjecttosend = $this->makeSubstitution($subject);
414
		if ($msgishtml) {
415
			$texttosend = dol_htmlentitiesbr($texttosend);
416
		}
417
418
		// Envoi mail confirmation
419
		$from = $conf->email_from;
420
		if (!empty($conf->global->ADHERENT_MAIL_FROM)) {
421
			$from = $conf->global->ADHERENT_MAIL_FROM;
422
		}
423
424
		$trackid = 'mem'.$this->id;
425
426
		// Send email (substitutionarray must be done just before this)
427
		include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
428
		$mailfile = new CMailFile($subjecttosend, $this->email, $from, $texttosend, $filename_list, $mimetype_list, $mimefilename_list, $addr_cc, $addr_bcc, $deliveryreceipt, $msgishtml, '', '', $trackid, $moreinheader);
429
		if ($mailfile->sendfile()) {
430
			return 1;
431
		} else {
432
			$this->error = $langs->trans("ErrorFailedToSendMail", $from, $this->email).'. '.$mailfile->error;
433
			return -1;
434
		}
435
	}
436
437
438
	/**
439
	 * Make substitution of tags into text with value of current object.
440
	 *
441
	 * @param	string	$text       Text to make substitution to
442
	 * @return  string      		Value of input text string with substitutions done
443
	 */
444
	public function makeSubstitution($text)
445
	{
446
		global $conf, $langs;
447
448
		$birthday = dol_print_date($this->birth, 'day');
449
450
		$msgishtml = 0;
451
		if (dol_textishtml($text, 1)) {
452
			$msgishtml = 1;
453
		}
454
455
		$infos = '';
456
		if ($this->civility_id) {
457
			$infos .= $langs->transnoentities("UserTitle").": ".$this->getCivilityLabel()."\n";
458
		}
459
		$infos .= $langs->transnoentities("id").": ".$this->id."\n";
460
		$infos .= $langs->transnoentities("ref").": ".$this->ref."\n";
461
		$infos .= $langs->transnoentities("Lastname").": ".$this->lastname."\n";
462
		$infos .= $langs->transnoentities("Firstname").": ".$this->firstname."\n";
463
		$infos .= $langs->transnoentities("Company").": ".$this->company."\n";
464
		$infos .= $langs->transnoentities("Address").": ".$this->address."\n";
465
		$infos .= $langs->transnoentities("Zip").": ".$this->zip."\n";
466
		$infos .= $langs->transnoentities("Town").": ".$this->town."\n";
467
		$infos .= $langs->transnoentities("Country").": ".$this->country."\n";
468
		$infos .= $langs->transnoentities("EMail").": ".$this->email."\n";
469
		$infos .= $langs->transnoentities("PhonePro").": ".$this->phone."\n";
470
		$infos .= $langs->transnoentities("PhonePerso").": ".$this->phone_perso."\n";
471
		$infos .= $langs->transnoentities("PhoneMobile").": ".$this->phone_mobile."\n";
472
		if (empty($conf->global->ADHERENT_LOGIN_NOT_REQUIRED)) {
473
			$infos .= $langs->transnoentities("Login").": ".$this->login."\n";
474
			$infos .= $langs->transnoentities("Password").": ".$this->pass."\n";
475
		}
476
		$infos .= $langs->transnoentities("Birthday").": ".$birthday."\n";
477
		$infos .= $langs->transnoentities("Photo").": ".$this->photo."\n";
478
		$infos .= $langs->transnoentities("Public").": ".yn($this->public);
479
480
		// Substitutions
481
		$substitutionarray = array(
482
			'__ID__' => $this->id,
483
			'__REF__' => $this->ref,
484
			'__MEMBER_ID__' => $this->id,
485
			'__CIVILITY__' => $this->getCivilityLabel(),
486
			'__FIRSTNAME__' => $msgishtml ? dol_htmlentitiesbr($this->firstname) : ($this->firstname ? $this->firstname : ''),
487
			'__LASTNAME__' => $msgishtml ? dol_htmlentitiesbr($this->lastname) : ($this->lastname ? $this->lastname : ''),
488
			'__FULLNAME__' => $msgishtml ? dol_htmlentitiesbr($this->getFullName($langs)) : $this->getFullName($langs),
489
			'__COMPANY__' => $msgishtml ? dol_htmlentitiesbr($this->company) : ($this->company ? $this->company : ''),
490
			'__ADDRESS__' => $msgishtml ? dol_htmlentitiesbr($this->address) : ($this->address ? $this->address : ''),
491
			'__ZIP__' => $msgishtml ? dol_htmlentitiesbr($this->zip) : ($this->zip ? $this->zip : ''),
492
			'__TOWN__' => $msgishtml ? dol_htmlentitiesbr($this->town) : ($this->town ? $this->town : ''),
493
			'__COUNTRY__' => $msgishtml ? dol_htmlentitiesbr($this->country) : ($this->country ? $this->country : ''),
494
			'__EMAIL__' => $msgishtml ? dol_htmlentitiesbr($this->email) : ($this->email ? $this->email : ''),
495
			'__BIRTH__' => $msgishtml ? dol_htmlentitiesbr($birthday) : ($birthday ? $birthday : ''),
496
			'__PHOTO__' => $msgishtml ? dol_htmlentitiesbr($this->photo) : ($this->photo ? $this->photo : ''),
497
			'__LOGIN__' => $msgishtml ? dol_htmlentitiesbr($this->login) : ($this->login ? $this->login : ''),
498
			'__PASSWORD__' => $msgishtml ? dol_htmlentitiesbr($this->pass) : ($this->pass ? $this->pass : ''),
499
			'__PHONE__' => $msgishtml ? dol_htmlentitiesbr($this->phone) : ($this->phone ? $this->phone : ''),
500
			'__PHONEPRO__' => $msgishtml ? dol_htmlentitiesbr($this->phone_perso) : ($this->phone_perso ? $this->phone_perso : ''),
501
			'__PHONEMOBILE__' => $msgishtml ? dol_htmlentitiesbr($this->phone_mobile) : ($this->phone_mobile ? $this->phone_mobile : ''),
502
			'__TYPE__' => $msgishtml ? dol_htmlentitiesbr($this->type) : ($this->type ? $this->type : '')
503
		);
504
505
		complete_substitutions_array($substitutionarray, $langs, $this);
506
507
		return make_substitutions($text, $substitutionarray, $langs);
508
	}
509
510
511
	/**
512
	 *	Return translated label by the nature of a adherent (physical or moral)
513
	 *
514
	 *	@param	string		$morphy		Nature of the adherent (physical or moral)
515
	 *	@return	string					Label
516
	 */
517
	public function getmorphylib($morphy = '')
518
	{
519
		global $langs;
520
		if (!$morphy) {
521
			$morphy = $this->morphy;
522
		}
523
		if ($morphy == 'phy') {
524
			return $langs->trans("Physical");
525
		}
526
		if ($morphy == 'mor') {
527
			return $langs->trans("Moral");
528
		}
529
		return $morphy;
530
	}
531
532
	/**
533
	 *	Create a member into database
534
	 *
535
	 *	@param	User	$user        	Objet user qui demande la creation
536
	 *	@param  int		$notrigger		1 ne declenche pas les triggers, 0 sinon
537
	 *	@return	int						<0 if KO, >0 if OK
538
	 */
539
	public function create($user, $notrigger = 0)
540
	{
541
		global $conf, $langs;
542
543
		$error = 0;
544
545
		$now = dol_now();
546
547
		// Clean parameters
548
		$this->import_key = trim($this->import_key);
549
550
		// Check parameters
551
		if (!empty($conf->global->ADHERENT_MAIL_REQUIRED) && !isValidEMail($this->email)) {
552
			$langs->load("errors");
553
			$this->error = $langs->trans("ErrorBadEMail", $this->email);
554
			return -1;
555
		}
556
		if (!$this->datec) {
557
			$this->datec = $now;
558
		}
559
		if (empty($conf->global->ADHERENT_LOGIN_NOT_REQUIRED)) {
560
			if (empty($this->login)) {
561
				$this->error = $langs->trans("ErrorWrongValueForParameterX", "Login");
562
				return -1;
563
			}
564
		}
565
566
		$this->db->begin();
567
568
		// Insert member
569
		$sql = "INSERT INTO ".MAIN_DB_PREFIX."adherent";
570
		$sql .= " (ref, datec,login,fk_user_author,fk_user_mod,fk_user_valid,morphy,fk_adherent_type,entity,import_key)";
571
		$sql .= " VALUES (";
572
		$sql .= " '(PROV)'";
573
		$sql .= ", '".$this->db->idate($this->datec)."'";
574
		$sql .= ", ".($this->login ? "'".$this->db->escape($this->login)."'" : "null");
575
		$sql .= ", ".($user->id > 0 ? $user->id : "null"); // Can be null because member can be created by a guest or a script
576
		$sql .= ", null, null, '".$this->db->escape($this->morphy)."'";
577
		$sql .= ", ".$this->typeid;
578
		$sql .= ", ".$conf->entity;
579
		$sql .= ", ".(!empty($this->import_key) ? "'".$this->db->escape($this->import_key)."'" : "null");
580
		$sql .= ")";
581
582
		dol_syslog(get_class($this)."::create", LOG_DEBUG);
583
		$result = $this->db->query($sql);
584
		if ($result) {
585
			$id = $this->db->last_insert_id(MAIN_DB_PREFIX."adherent");
586
			if ($id > 0) {
587
				$this->id = $id;
588
				$this->ref = (string) $id;
589
590
				// Update minor fields
591
				$result = $this->update($user, 1, 1, 0, 0, 'add'); // nosync is 1 to avoid update data of user
592
				if ($result < 0) {
593
					$this->db->rollback();
594
					return -1;
595
				}
596
597
				// Add link to user
598
				if ($this->user_id) {
599
					// Add link to user
600
					$sql = "UPDATE ".MAIN_DB_PREFIX."user SET";
601
					$sql .= " fk_member = ".$this->id;
602
					$sql .= " WHERE rowid = ".$this->user_id;
603
					dol_syslog(get_class($this)."::create", LOG_DEBUG);
604
					$resql = $this->db->query($sql);
605
					if (!$resql) {
606
						$this->error = 'Failed to update user to make link with member';
607
						$this->db->rollback();
608
						return -4;
609
					}
610
				}
611
612
				if (!$notrigger) {
613
					// Call trigger
614
					$result = $this->call_trigger('MEMBER_CREATE', $user);
615
					if ($result < 0) {
616
						$error++;
617
					}
618
					// End call triggers
619
				}
620
621
				if (count($this->errors)) {
622
					dol_syslog(get_class($this)."::create ".implode(',', $this->errors), LOG_ERR);
623
					$this->db->rollback();
624
					return -3;
625
				} else {
626
					$this->db->commit();
627
					return $this->id;
628
				}
629
			} else {
630
				$this->error = 'Failed to get last insert id';
631
				dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
632
				$this->db->rollback();
633
				return -2;
634
			}
635
		} else {
636
			$this->error = $this->db->error();
637
			$this->db->rollback();
638
			return -1;
639
		}
640
	}
641
642
643
	/**
644
	 *	Update a member in database (standard information and password)
645
	 *
646
	 *	@param	User	$user				User making update
647
	 *	@param	int		$notrigger			1=disable trigger UPDATE (when called by create)
648
	 *	@param	int		$nosyncuser			0=Synchronize linked user (standard info), 1=Do not synchronize linked user
649
	 *	@param	int		$nosyncuserpass		0=Synchronize linked user (password), 1=Do not synchronize linked user
650
	 *	@param	int		$nosyncthirdparty	0=Synchronize linked thirdparty (standard info), 1=Do not synchronize linked thirdparty
651
	 * 	@param	string	$action				Current action for hookmanager
652
	 * 	@return	int							<0 if KO, >0 if OK
653
	 */
654
	public function update($user, $notrigger = 0, $nosyncuser = 0, $nosyncuserpass = 0, $nosyncthirdparty = 0, $action = 'update')
655
	{
656
		global $conf, $langs, $hookmanager;
657
658
		$nbrowsaffected = 0;
659
		$error = 0;
660
661
		dol_syslog(get_class($this)."::update notrigger=".$notrigger.", nosyncuser=".$nosyncuser.", nosyncuserpass=".$nosyncuserpass." nosyncthirdparty=".$nosyncthirdparty.", email=".
662
			$this->email);
663
664
		// Clean parameters
665
		$this->lastname = trim($this->lastname) ? trim($this->lastname) : trim($this->lastname);
666
		$this->firstname = trim($this->firstname) ? trim($this->firstname) : trim($this->firstname);
667
		$this->gender = trim($this->gender);
668
		$this->address = ($this->address ? $this->address : $this->address);
669
		$this->zip = ($this->zip ? $this->zip : $this->zip);
670
		$this->town = ($this->town ? $this->town : $this->town);
671
		$this->country_id = ($this->country_id > 0 ? $this->country_id : $this->country_id);
672
		$this->state_id = ($this->state_id > 0 ? $this->state_id : $this->state_id);
673
		$this->setUpperOrLowerCase();
674
		$this->note_public = ($this->note_public ? $this->note_public : $this->note_public);
675
		$this->note_private = ($this->note_private ? $this->note_private : $this->note_private);
676
		$this->url = $this->url ?clean_url($this->url, 0) : '';
677
678
		// Check parameters
679
		if (!empty($conf->global->ADHERENT_MAIL_REQUIRED) && !isValidEMail($this->email)) {
680
			$langs->load("errors");
681
			$this->error = $langs->trans("ErrorBadEMail", $this->email);
682
			return -1;
683
		}
684
685
		$this->db->begin();
686
687
		$sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
688
		$sql .= " ref = '".$this->db->escape($this->ref)."'";
689
		$sql .= ", civility = ".($this->civility_id ? "'".$this->db->escape($this->civility_id)."'" : "null");
690
		$sql .= ", firstname = ".($this->firstname ? "'".$this->db->escape($this->firstname)."'" : "null");
691
		$sql .= ", lastname = ".($this->lastname ? "'".$this->db->escape($this->lastname)."'" : "null");
692
		$sql .= ", gender = ".($this->gender != -1 ? "'".$this->db->escape($this->gender)."'" : "null"); // 'man' or 'woman'
693
		$sql .= ", login = ".($this->login ? "'".$this->db->escape($this->login)."'" : "null");
694
		$sql .= ", societe = ".($this->company ? "'".$this->db->escape($this->company)."'" : ($this->societe ? "'".$this->db->escape($this->societe)."'" : "null"));
695
		$sql .= ", fk_soc = ".($this->socid > 0 ? $this->db->escape($this->socid) : "null");
696
		$sql .= ", address = ".($this->address ? "'".$this->db->escape($this->address)."'" : "null");
697
		$sql .= ", zip = ".($this->zip ? "'".$this->db->escape($this->zip)."'" : "null");
698
		$sql .= ", town = ".($this->town ? "'".$this->db->escape($this->town)."'" : "null");
699
		$sql .= ", country = ".($this->country_id > 0 ? $this->db->escape($this->country_id) : "null");
700
		$sql .= ", state_id = ".($this->state_id > 0 ? $this->db->escape($this->state_id) : "null");
701
		$sql .= ", email = '".$this->db->escape($this->email)."'";
702
		$sql .= ", url = ".(!empty($this->url) ? "'".$this->db->escape($this->url)."'" : "null");
703
		$sql .= ", socialnetworks = '".$this->db->escape(json_encode($this->socialnetworks))."'";
704
		$sql .= ", phone = ".($this->phone ? "'".$this->db->escape($this->phone)."'" : "null");
705
		$sql .= ", phone_perso = ".($this->phone_perso ? "'".$this->db->escape($this->phone_perso)."'" : "null");
706
		$sql .= ", phone_mobile = ".($this->phone_mobile ? "'".$this->db->escape($this->phone_mobile)."'" : "null");
707
		$sql .= ", note_private = ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "null");
708
		$sql .= ", note_public = ".($this->note_public ? "'".$this->db->escape($this->note_public)."'" : "null");
709
		$sql .= ", photo = ".($this->photo ? "'".$this->db->escape($this->photo)."'" : "null");
710
		$sql .= ", public = '".$this->db->escape($this->public)."'";
711
		$sql .= ", statut = ".$this->db->escape($this->statut);
712
		$sql .= ", fk_adherent_type = ".$this->db->escape($this->typeid);
713
		$sql .= ", morphy = '".$this->db->escape($this->morphy)."'";
714
		$sql .= ", birth = ".($this->birth ? "'".$this->db->idate($this->birth)."'" : "null");
715
		if ($this->socid) {
716
			$sql .= ", fk_soc = '".$this->db->escape($this->socid)."'"; // Must be modified only when creating from a third-party
717
		}
718
		if ($this->datefin) {
719
			$sql .= ", datefin = '".$this->db->idate($this->datefin)."'"; // Must be modified only when deleting a subscription
720
		}
721
		if ($this->datevalid) {
722
			$sql .= ", datevalid = '".$this->db->idate($this->datevalid)."'"; // Must be modified only when validating a member
723
		}
724
		$sql .= ", fk_user_mod = ".($user->id > 0 ? $user->id : 'null'); // Can be null because member can be create by a guest
725
		$sql .= " WHERE rowid = ".((int) $this->id);
726
727
		// If we change the type of membership, we set also label of new type
728
		if (!empty($this->oldcopy) && $this->typeid != $this->oldcopy->typeid) {
729
			$sql2 = "SELECT libelle as label";
730
			$sql2 .= " FROM ".MAIN_DB_PREFIX."adherent_type";
731
			$sql2 .= " WHERE rowid = ".$this->typeid;
732
			$resql2 = $this->db->query($sql2);
733
			if ($resql2) {
734
				while ($obj = $this->db->fetch_object($resql2)) {
735
					$this->type = $obj->label;
736
				}
737
			}
738
		}
739
740
		dol_syslog(get_class($this)."::update update member", LOG_DEBUG);
741
		$resql = $this->db->query($sql);
742
		if ($resql) {
743
			unset($this->country_code);
744
			unset($this->country);
745
			unset($this->state_code);
746
			unset($this->state);
747
748
			$nbrowsaffected += $this->db->affected_rows($resql);
749
750
			$action = 'update';
751
752
			// Actions on extra fields
753
			if (!$error) {
754
				$result = $this->insertExtraFields();
755
				if ($result < 0) {
756
					$error++;
757
				}
758
			}
759
760
			// Update password
761
			if (!$error && $this->pass) {
762
				dol_syslog(get_class($this)."::update update password");
763
				if ($this->pass != $this->pass_indatabase && $this->pass != $this->pass_indatabase_crypted) {
764
					$isencrypted = empty($conf->global->DATABASE_PWD_ENCRYPTED) ? 0 : 1;
765
766
					// If password to set differs from the one found into database
767
					$result = $this->setPassword($user, $this->pass, $isencrypted, $notrigger, $nosyncuserpass);
768
					if (!$nbrowsaffected) {
769
						$nbrowsaffected++;
770
					}
771
				}
772
			}
773
774
			// Remove links to user and replace with new one
775
			if (!$error) {
776
				dol_syslog(get_class($this)."::update update link to user");
777
				$sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = NULL WHERE fk_member = ".$this->id;
778
				dol_syslog(get_class($this)."::update", LOG_DEBUG);
779
				$resql = $this->db->query($sql);
780
				if (!$resql) {
781
					$this->error = $this->db->error();
782
					$this->db->rollback();
783
					return -5;
784
				}
785
				// If there is a user linked to this member
786
				if ($this->user_id > 0) {
787
					$sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = ".$this->id." WHERE rowid = ".$this->user_id;
788
					dol_syslog(get_class($this)."::update", LOG_DEBUG);
789
					$resql = $this->db->query($sql);
790
					if (!$resql) {
791
						$this->error = $this->db->error();
792
						$this->db->rollback();
793
						return -5;
794
					}
795
				}
796
			}
797
798
			if (!$error && $nbrowsaffected) { // If something has change in main data
799
				// Update information on linked user if it is an update
800
				if (!$error && $this->user_id > 0 && !$nosyncuser) {
801
					require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
802
803
					dol_syslog(get_class($this)."::update update linked user");
804
805
					$luser = new User($this->db);
806
					$result = $luser->fetch($this->user_id);
807
808
					if ($result >= 0) {
809
						//var_dump($this->user_login);exit;
810
						//var_dump($this->login);exit;
811
812
						// 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.
813
						if (empty($conf->global->ADHERENT_LOGIN_NOT_REQUIRED)) {
814
							$luser->login = $this->login;
815
						}
816
817
						$luser->ref = $this->ref;
818
						$luser->civility_id = $this->civility_id;
819
						$luser->firstname = $this->firstname;
820
						$luser->lastname = $this->lastname;
821
						$luser->gender = $this->gender;
822
						$luser->pass = $this->pass;
823
						//$luser->socid=$this->fk_soc;		// We do not enable this. This may transform a user into an external user.
824
825
						$luser->birth = $this->birth;
826
827
						$luser->address = $this->address;
828
						$luser->zip = $this->zip;
829
						$luser->town = $this->town;
830
						$luser->country_id = $this->country_id;
831
						$luser->state_id = $this->state_id;
832
833
						$luser->email = $this->email;
834
						$luser->socialnetworks = $this->socialnetworks;
835
						$luser->office_phone = $this->phone;
836
						$luser->user_mobile = $this->phone_mobile;
837
838
						$luser->fk_member = $this->id;
839
840
						$result = $luser->update($user, 0, 1, 1); // Use nosync to 1 to avoid cyclic updates
841
						if ($result < 0) {
842
							$this->error = $luser->error;
843
							dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
844
							$error++;
845
						}
846
					} else {
847
						$this->error = $luser->error;
848
						$error++;
849
					}
850
				}
851
852
				// Update information on linked thirdparty if it is an update
853
				if (!$error && $this->fk_soc > 0 && !$nosyncthirdparty) {
854
					require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
855
856
					dol_syslog(get_class($this)."::update update linked thirdparty");
857
858
					// This member is linked with a thirdparty, so we also update thirdparty informations
859
					// if this is an update.
860
					$lthirdparty = new Societe($this->db);
861
					$result = $lthirdparty->fetch($this->fk_soc);
862
863
					if ($result > 0) {
864
						$lthirdparty->address = $this->address;
865
						$lthirdparty->zip = $this->zip;
866
						$lthirdparty->town = $this->town;
867
						$lthirdparty->email = $this->email;
868
						$lthirdparty->socialnetworks = $this->socialnetworks;
869
						$lthirdparty->phone = $this->phone;
870
						$lthirdparty->state_id = $this->state_id;
871
						$lthirdparty->country_id = $this->country_id;
872
						//$lthirdparty->phone_mobile=$this->phone_mobile;
873
874
						$result = $lthirdparty->update($this->fk_soc, $user, 0, 1, 1, 'update'); // Use sync to 0 to avoid cyclic updates
875
876
						if ($result < 0) {
877
							$this->error = $lthirdparty->error;
878
							$this->errors = $lthirdparty->errors;
879
							dol_syslog(get_class($this)."::update ".$this->error, LOG_ERR);
880
							$error++;
881
						}
882
					} elseif ($result < 0) {
883
						$this->error = $lthirdparty->error;
884
						$error++;
885
					}
886
				}
887
			}
888
889
			if (!$error && !$notrigger) {
890
				// Call trigger
891
				$result = $this->call_trigger('MEMBER_MODIFY', $user);
892
				if ($result < 0) {
893
					$error++;
894
				}
895
				// End call triggers
896
			}
897
898
			if (!$error) {
899
				$this->db->commit();
900
				return $nbrowsaffected;
901
			} else {
902
				$this->db->rollback();
903
				return -1;
904
			}
905
		} else {
906
			$this->db->rollback();
907
			$this->error = $this->db->lasterror();
908
			return -2;
909
		}
910
	}
911
912
913
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
914
	/**
915
	 *	Update denormalized last subscription date.
916
	 * 	This function is called when we delete a subscription for example.
917
	 *
918
	 *	@param	User	$user			User making change
919
	 *	@return	int						<0 if KO, >0 if OK
920
	 */
921
	public function update_end_date($user)
922
	{
923
		// phpcs:enable
924
		$this->db->begin();
925
926
		// Search for last subscription id and end date
927
		$sql = "SELECT rowid, datec as dateop, dateadh as datedeb, datef as datefin";
928
		$sql .= " FROM ".MAIN_DB_PREFIX."subscription";
929
		$sql .= " WHERE fk_adherent=".$this->id;
930
		$sql .= " ORDER by dateadh DESC"; // Sort by start subscription date
931
932
		dol_syslog(get_class($this)."::update_end_date", LOG_DEBUG);
933
		$resql = $this->db->query($sql);
934
		if ($resql) {
935
			$obj = $this->db->fetch_object($resql);
936
			$dateop = $this->db->jdate($obj->dateop);
937
			$datedeb = $this->db->jdate($obj->datedeb);
938
			$datefin = $this->db->jdate($obj->datefin);
939
940
			$sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
941
			$sql .= " datefin=".($datefin != '' ? "'".$this->db->idate($datefin)."'" : "null");
942
			$sql .= " WHERE rowid = ".$this->id;
943
944
			dol_syslog(get_class($this)."::update_end_date", LOG_DEBUG);
945
			$resql = $this->db->query($sql);
946
			if ($resql) {
947
				$this->last_subscription_date = $dateop;
948
				$this->last_subscription_date_start = $datedeb;
949
				$this->last_subscription_date_end = $datefin;
950
				$this->datefin = $datefin;
951
				$this->db->commit();
952
				return 1;
953
			} else {
954
				$this->db->rollback();
955
				return -1;
956
			}
957
		} else {
958
			$this->error = $this->db->lasterror();
959
			$this->db->rollback();
960
			return -1;
961
		}
962
	}
963
964
	/**
965
	 *  Fonction qui supprime l'adherent et les donnees associees
966
	 *
967
	 *  @param	int		$rowid		Id of member to delete
968
	 *	@param	User		$user		User object
969
	 *	@param	int		$notrigger	1=Does not execute triggers, 0= execute triggers
970
	 *  @return	int					<0 if KO, 0=nothing to do, >0 if OK
971
	 */
972
	public function delete($rowid, $user, $notrigger = 0)
973
	{
974
		global $conf, $langs;
975
976
		$result = 0;
977
		$error = 0;
978
		$errorflag = 0;
979
980
		// Check parameters
981
		if (empty($rowid)) {
982
			$rowid = $this->id;
983
		}
984
985
		$this->db->begin();
986
987
		if (!$error && !$notrigger) {
988
			// Call trigger
989
			$result = $this->call_trigger('MEMBER_DELETE', $user);
990
			if ($result < 0) {
991
				$error++;
992
			}
993
			// End call triggers
994
		}
995
996
		// Remove category
997
		$sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_member WHERE fk_member = ".((int) $rowid);
998
		dol_syslog(get_class($this)."::delete", LOG_DEBUG);
999
		$resql = $this->db->query($sql);
1000
		if (!$resql) {
1001
			$error++;
1002
			$this->error .= $this->db->lasterror();
1003
			$errorflag = -1;
1004
		}
1005
1006
		// Remove subscription
1007
		if (!$error) {
1008
			$sql = "DELETE FROM ".MAIN_DB_PREFIX."subscription WHERE fk_adherent = ".((int) $rowid);
1009
			dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1010
			$resql = $this->db->query($sql);
1011
			if (!$resql) {
1012
				$error++;
1013
				$this->error .= $this->db->lasterror();
1014
				$errorflag = -2;
1015
			}
1016
		}
1017
1018
		// Remove linked user
1019
		if (!$error) {
1020
			$ret = $this->setUserId(0);
1021
			if ($ret < 0) {
1022
				$error++;
1023
				$this->error .= $this->db->lasterror();
1024
				$errorflag = -3;
1025
			}
1026
		}
1027
1028
		// Removed extrafields
1029
		if (!$error) {
1030
			$result = $this->deleteExtraFields();
1031
			if ($result < 0) {
1032
				$error++;
1033
				$errorflag = -4;
1034
				dol_syslog(get_class($this)."::delete erreur ".$errorflag." ".$this->error, LOG_ERR);
1035
			}
1036
		}
1037
1038
		// Remove adherent
1039
		if (!$error) {
1040
			$sql = "DELETE FROM ".MAIN_DB_PREFIX."adherent WHERE rowid = ".((int) $rowid);
1041
			dol_syslog(get_class($this)."::delete", LOG_DEBUG);
1042
			$resql = $this->db->query($sql);
1043
			if (!$resql) {
1044
				$error++;
1045
				$this->error .= $this->db->lasterror();
1046
				$errorflag = -5;
1047
			}
1048
		}
1049
1050
		if (!$error) {
1051
			$this->db->commit();
1052
			return 1;
1053
		} else {
1054
			$this->db->rollback();
1055
			return $errorflag;
1056
		}
1057
	}
1058
1059
1060
	/**
1061
	 *    Change password of a user
1062
	 *
1063
	 *    @param	User	$user           Object user de l'utilisateur qui fait la modification
1064
	 *    @param 	string	$password       New password (to generate if empty)
1065
	 *    @param    int		$isencrypted    0 ou 1 si il faut crypter le mot de passe en base (0 par defaut)
1066
	 *	  @param	int		$notrigger		1=Ne declenche pas les triggers
1067
	 *    @param	int		$nosyncuser		Do not synchronize linked user
1068
	 *    @return   string           		If OK return clear password, 0 if no change, < 0 if error
1069
	 */
1070
	public function setPassword($user, $password = '', $isencrypted = 0, $notrigger = 0, $nosyncuser = 0)
1071
	{
1072
		global $conf, $langs;
1073
1074
		$error = 0;
1075
1076
		dol_syslog(get_class($this)."::setPassword user=".$user->id." password=".preg_replace('/./i', '*', $password)." isencrypted=".$isencrypted);
1077
1078
		// If new password not provided, we generate one
1079
		if (!$password) {
1080
			require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
1081
			$password = getRandomPassword(false);
1082
		}
1083
1084
		// Crypt password
1085
		$password_crypted = dol_hash($password);
1086
1087
		$password_indatabase = '';
1088
		if (!$isencrypted) {
1089
			$password_indatabase = $password;
1090
		}
1091
1092
		$this->db->begin();
1093
1094
		// Mise a jour
1095
		$sql = "UPDATE ".MAIN_DB_PREFIX."adherent";
1096
		$sql .= " SET pass_crypted = '".$this->db->escape($password_crypted)."'";
1097
		//if (! empty($conf->global->DATABASE_PWD_ENCRYPTED))
1098
		if ($isencrypted) {
1099
			$sql .= ", pass = null";
1100
		} else {
1101
			$sql .= ", pass = '".$this->db->escape($password_indatabase)."'";
1102
		}
1103
		$sql .= " WHERE rowid = ".$this->id;
1104
1105
		//dol_syslog("Adherent::Password sql=hidden");
1106
		dol_syslog(get_class($this)."::setPassword", LOG_DEBUG);
1107
		$result = $this->db->query($sql);
1108
		if ($result) {
1109
			$nbaffectedrows = $this->db->affected_rows($result);
1110
1111
			if ($nbaffectedrows) {
1112
				$this->pass = $password;
1113
				$this->pass_indatabase = $password_indatabase;
1114
				$this->pass_indatabase_crypted = $password_crypted;
1115
1116
				if ($this->user_id && !$nosyncuser) {
1117
					require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
1118
1119
					// This member is linked with a user, so we also update users informations
1120
					// if this is an update.
1121
					$luser = new User($this->db);
1122
					$result = $luser->fetch($this->user_id);
1123
1124
					if ($result >= 0) {
1125
						$result = $luser->setPassword($user, $this->pass, 0, 0, 1);
1126
						if ($result < 0) {
1127
							$this->error = $luser->error;
1128
							dol_syslog(get_class($this)."::setPassword ".$this->error, LOG_ERR);
1129
							$error++;
1130
						}
1131
					} else {
1132
						$this->error = $luser->error;
1133
						$error++;
1134
					}
1135
				}
1136
1137
				if (!$error && !$notrigger) {
1138
					// Call trigger
1139
					$result = $this->call_trigger('MEMBER_NEW_PASSWORD', $user);
1140
					if ($result < 0) {
1141
						$error++;
1142
						$this->db->rollback();
1143
						return -1;
1144
					}
1145
					// End call triggers
1146
				}
1147
1148
				$this->db->commit();
1149
				return $this->pass;
1150
			} else {
1151
				$this->db->rollback();
1152
				return 0;
1153
			}
1154
		} else {
1155
			$this->db->rollback();
1156
			dol_print_error($this->db);
1157
			return -1;
1158
		}
1159
	}
1160
1161
1162
	/**
1163
	 *    Set link to a user
1164
	 *
1165
	 *    @param     int	$userid        	Id of user to link to
1166
	 *    @return    int					1=OK, -1=KO
1167
	 */
1168
	public function setUserId($userid)
1169
	{
1170
		global $conf, $langs;
1171
1172
		$this->db->begin();
1173
1174
		// If user is linked to this member, remove old link to this member
1175
		$sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = NULL WHERE fk_member = ".((int) $this->id);
1176
		dol_syslog(get_class($this)."::setUserId", LOG_DEBUG);
1177
		$resql = $this->db->query($sql);
1178
		if (!$resql) {
1179
			$this->error = $this->db->error();
1180
			$this->db->rollback();
1181
			return -1;
1182
		}
1183
1184
		// Set link to user
1185
		if ($userid > 0) {
1186
			$sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = ".((int) $this->id);
1187
			$sql .= " WHERE rowid = ".((int) $userid);
1188
			dol_syslog(get_class($this)."::setUserId", LOG_DEBUG);
1189
			$resql = $this->db->query($sql);
1190
			if (!$resql) {
1191
				$this->error = $this->db->error();
1192
				$this->db->rollback();
1193
				return -2;
1194
			}
1195
		}
1196
1197
		$this->db->commit();
1198
1199
		return 1;
1200
	}
1201
1202
1203
	/**
1204
	 *    Set link to a third party
1205
	 *
1206
	 *    @param     int	$thirdpartyid		Id of user to link to
1207
	 *    @return    int						1=OK, -1=KO
1208
	 */
1209
	public function setThirdPartyId($thirdpartyid)
1210
	{
1211
		global $conf, $langs;
1212
1213
		$this->db->begin();
1214
1215
		// Remove link to third party onto any other members
1216
		if ($thirdpartyid > 0) {
1217
			$sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET fk_soc = null";
1218
			$sql .= " WHERE fk_soc = ".((int) $thirdpartyid);
1219
			$sql .= " AND entity = ".$conf->entity;
1220
			dol_syslog(get_class($this)."::setThirdPartyId", LOG_DEBUG);
1221
			$resql = $this->db->query($sql);
1222
		}
1223
1224
		// Add link to third party for current member
1225
		$sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET fk_soc = ".($thirdpartyid > 0 ? $thirdpartyid : 'null');
1226
		$sql .= " WHERE rowid = ".$this->id;
1227
1228
		dol_syslog(get_class($this)."::setThirdPartyId", LOG_DEBUG);
1229
		$resql = $this->db->query($sql);
1230
		if ($resql) {
1231
			$this->db->commit();
1232
			return 1;
1233
		} else {
1234
			$this->error = $this->db->error();
1235
			$this->db->rollback();
1236
			return -1;
1237
		}
1238
	}
1239
1240
1241
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1242
	/**
1243
	 *	Method to load member from its login
1244
	 *
1245
	 *	@param	string	$login		login of member
1246
	 *	@return	void
1247
	 */
1248
	public function fetch_login($login)
1249
	{
1250
		// phpcs:enable
1251
		global $conf;
1252
1253
		$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."adherent";
1254
		$sql .= " WHERE login='".$this->db->escape($login)."'";
1255
		$sql .= " AND entity = ".$conf->entity;
1256
1257
		$resql = $this->db->query($sql);
1258
		if ($resql) {
1259
			if ($this->db->num_rows($resql)) {
1260
				$obj = $this->db->fetch_object($resql);
1261
				$this->fetch($obj->rowid);
1262
			}
1263
		} else {
1264
			dol_print_error($this->db);
1265
		}
1266
	}
1267
1268
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1269
	/**
1270
	 *	Method to load member from its name
1271
	 *
1272
	 *	@param	string	$firstname	Firstname
1273
	 *	@param	string	$lastname	Lastname
1274
	 *	@return	void
1275
	 */
1276
	public function fetch_name($firstname, $lastname)
1277
	{
1278
		// phpcs:enable
1279
		global $conf;
1280
1281
		$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."adherent";
1282
		$sql .= " WHERE firstname='".$this->db->escape($firstname)."'";
1283
		$sql .= " AND lastname='".$this->db->escape($lastname)."'";
1284
		$sql .= " AND entity = ".$conf->entity;
1285
1286
		$resql = $this->db->query($sql);
1287
		if ($resql) {
1288
			if ($this->db->num_rows($resql)) {
1289
				$obj = $this->db->fetch_object($resql);
1290
				$this->fetch($obj->rowid);
1291
			}
1292
		} else {
1293
			dol_print_error($this->db);
1294
		}
1295
	}
1296
1297
	/**
1298
	 *	Load member from database
1299
	 *
1300
	 *	@param	int		$rowid      			Id of object to load
1301
	 * 	@param	string	$ref					To load member from its ref
1302
	 * 	@param	int		$fk_soc					To load member from its link to third party
1303
	 * 	@param	string	$ref_ext				External reference
1304
	 *  @param	bool	$fetch_optionals		To load optionals (extrafields)
1305
	 *  @param	bool	$fetch_subscriptions	To load member subscriptions
1306
	 *	@return int								>0 if OK, 0 if not found, <0 if KO
1307
	 */
1308
	public function fetch($rowid, $ref = '', $fk_soc = '', $ref_ext = '', $fetch_optionals = true, $fetch_subscriptions = true)
1309
	{
1310
		global $langs;
1311
1312
		$sql = "SELECT d.rowid, d.ref, d.ref_ext, d.civility as civility_code, d.gender, d.firstname, d.lastname,";
1313
		$sql .= " d.societe as company, d.fk_soc, d.statut, d.public, d.address, d.zip, d.town, d.note_private,";
1314
		$sql .= " d.note_public,";
1315
		$sql .= " d.email, d.url, d.socialnetworks, d.phone, d.phone_perso, d.phone_mobile, d.login, d.pass, d.pass_crypted,";
1316
		$sql .= " d.photo, d.fk_adherent_type, d.morphy, d.entity,";
1317
		$sql .= " d.datec as datec,";
1318
		$sql .= " d.tms as datem,";
1319
		$sql .= " d.datefin as datefin,";
1320
		$sql .= " d.birth as birthday,";
1321
		$sql .= " d.datevalid as datev,";
1322
		$sql .= " d.country,";
1323
		$sql .= " d.state_id,";
1324
		$sql .= " d.model_pdf,";
1325
		$sql .= " c.rowid as country_id, c.code as country_code, c.label as country,";
1326
		$sql .= " dep.nom as state, dep.code_departement as state_code,";
1327
		$sql .= " t.libelle as type, t.subscription as subscription,";
1328
		$sql .= " u.rowid as user_id, u.login as user_login";
1329
		$sql .= " FROM ".MAIN_DB_PREFIX."adherent_type as t, ".MAIN_DB_PREFIX."adherent as d";
1330
		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as c ON d.country = c.rowid";
1331
		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as dep ON d.state_id = dep.rowid";
1332
		$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u ON d.rowid = u.fk_member";
1333
		$sql .= " WHERE d.fk_adherent_type = t.rowid";
1334
		if ($rowid) {
1335
			$sql .= " AND d.rowid=".((int) $rowid);
1336
		} elseif ($ref || $fk_soc) {
1337
			$sql .= " AND d.entity IN (".getEntity('adherent').")";
1338
			if ($ref) {
1339
				$sql .= " AND d.ref='".$this->db->escape($ref)."'";
1340
			} elseif ($fk_soc > 0) {
1341
				$sql .= " AND d.fk_soc=".((int) $fk_soc);
1342
			}
1343
		} elseif ($ref_ext) {
1344
			$sql .= " AND d.ref_ext='".$this->db->escape($ref_ext)."'";
1345
		}
1346
1347
		dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
1348
		$resql = $this->db->query($sql);
1349
		if ($resql) {
1350
			if ($this->db->num_rows($resql)) {
1351
				$obj = $this->db->fetch_object($resql);
1352
1353
				$this->entity = $obj->entity;
1354
				$this->id = $obj->rowid;
1355
				$this->ref = $obj->ref;
1356
				$this->ref_ext = $obj->ref_ext;
1357
1358
				$this->civility_id = $obj->civility_code; // Bad. Kept for backard compatibility
1359
				$this->civility_code = $obj->civility_code;
1360
				$this->civility = $obj->civility_code ? ($langs->trans("Civility".$obj->civility_code) != ("Civility".$obj->civility_code) ? $langs->trans("Civility".$obj->civility_code) : $obj->civility_code) : '';
1361
1362
				$this->firstname = $obj->firstname;
1363
				$this->lastname = $obj->lastname;
1364
				$this->gender = $obj->gender;
1365
				$this->login = $obj->login;
1366
				$this->societe = $obj->company;
1367
				$this->company = $obj->company;
1368
				$this->socid = $obj->fk_soc;
1369
				$this->fk_soc = $obj->fk_soc; // For backward compatibility
1370
				$this->address = $obj->address;
1371
				$this->zip = $obj->zip;
1372
				$this->town = $obj->town;
1373
1374
				$this->pass = $obj->pass;
1375
				$this->pass_indatabase = $obj->pass;
1376
				$this->pass_indatabase_crypted = $obj->pass_crypted;
1377
1378
				$this->state_id = $obj->state_id;
1379
				$this->state_code = $obj->state_id ? $obj->state_code : '';
1380
				$this->state = $obj->state_id ? $obj->state : '';
1381
1382
				$this->country_id = $obj->country_id;
1383
				$this->country_code = $obj->country_code;
1384
				if ($langs->trans("Country".$obj->country_code) != "Country".$obj->country_code) {
1385
					$this->country = $langs->transnoentitiesnoconv("Country".$obj->country_code);
1386
				} else {
1387
					$this->country = $obj->country;
1388
				}
1389
1390
				$this->phone = $obj->phone;
1391
				$this->phone_perso = $obj->phone_perso;
1392
				$this->phone_mobile = $obj->phone_mobile;
1393
				$this->email = $obj->email;
1394
				$this->url = $obj->url;
1395
1396
				$this->socialnetworks = (array) json_decode($obj->socialnetworks, true);
1397
1398
				$this->photo = $obj->photo;
1399
				$this->statut = $obj->statut;
1400
				$this->public = $obj->public;
1401
1402
				$this->datec = $this->db->jdate($obj->datec);
1403
				$this->date_creation = $this->db->jdate($obj->datec);
1404
				$this->datem = $this->db->jdate($obj->datem);
1405
				$this->date_modification = $this->db->jdate($obj->datem);
1406
				$this->datefin = $this->db->jdate($obj->datefin);
1407
				$this->datevalid = $this->db->jdate($obj->datev);
1408
				$this->date_validation = $this->db->jdate($obj->datev);
1409
				$this->birth = $this->db->jdate($obj->birthday);
1410
1411
				$this->note_private = $obj->note_private;
1412
				$this->note_public = $obj->note_public;
1413
				$this->morphy = $obj->morphy;
1414
1415
				$this->typeid = $obj->fk_adherent_type;
1416
				$this->type = $obj->type;
1417
				$this->need_subscription = $obj->subscription;
1418
1419
				$this->user_id = $obj->user_id;
1420
				$this->user_login = $obj->user_login;
1421
1422
				$this->model_pdf = $obj->model_pdf;
1423
1424
				// Retrieve all extrafield
1425
				// fetch optionals attributes and labels
1426
				if ($fetch_optionals) {
1427
					$this->fetch_optionals();
1428
				}
1429
1430
				// Load other properties
1431
				if ($fetch_subscriptions) {
1432
					$result = $this->fetch_subscriptions();
1433
				}
1434
1435
				return $this->id;
1436
			} else {
1437
				return 0;
1438
			}
1439
		} else {
1440
			$this->error = $this->db->lasterror();
1441
			return -1;
1442
		}
1443
	}
1444
1445
1446
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1447
	/**
1448
	 *	Function to get member subscriptions data:
1449
	 *  subscriptions,
1450
	 *	first_subscription_date, first_subscription_date_start, first_subscription_date_end, first_subscription_amount
1451
	 *	last_subscription_date, last_subscription_date_start, last_subscription_date_end, last_subscription_amount
1452
	 *
1453
	 *	@return		int			<0 if KO, >0 if OK
1454
	 */
1455
	public function fetch_subscriptions()
1456
	{
1457
		// phpcs:enable
1458
		global $langs;
1459
1460
		require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
1461
1462
		$sql = "SELECT c.rowid, c.fk_adherent, c.fk_type, c.subscription, c.note, c.fk_bank,";
1463
		$sql .= " c.tms as datem,";
1464
		$sql .= " c.datec as datec,";
1465
		$sql .= " c.dateadh as dateh,";
1466
		$sql .= " c.datef as datef";
1467
		$sql .= " FROM ".MAIN_DB_PREFIX."subscription as c";
1468
		$sql .= " WHERE c.fk_adherent = ".$this->id;
1469
		$sql .= " ORDER BY c.dateadh";
1470
		dol_syslog(get_class($this)."::fetch_subscriptions", LOG_DEBUG);
1471
1472
		$resql = $this->db->query($sql);
1473
		if ($resql) {
1474
			$this->subscriptions = array();
1475
1476
			$i = 0;
1477
			while ($obj = $this->db->fetch_object($resql)) {
1478
				if ($i == 0) {
1479
					$this->first_subscription_date = $this->db->jdate($obj->datec);
1480
					$this->first_subscription_date_start = $this->db->jdate($obj->dateh);
1481
					$this->first_subscription_date_end = $this->db->jdate($obj->datef);
1482
					$this->first_subscription_amount = $obj->subscription;
1483
				}
1484
				$this->last_subscription_date = $this->db->jdate($obj->datec);
1485
				$this->last_subscription_date_start = $this->db->jdate($obj->datef);
1486
				$this->last_subscription_date_end = $this->db->jdate($obj->datef);
1487
				$this->last_subscription_amount = $obj->subscription;
1488
1489
				$subscription = new Subscription($this->db);
1490
				$subscription->id = $obj->rowid;
1491
				$subscription->fk_adherent = $obj->fk_adherent;
1492
				$subscription->fk_type = $obj->fk_type;
1493
				$subscription->amount = $obj->subscription;
1494
				$subscription->note = $obj->note;
1495
				$subscription->fk_bank = $obj->fk_bank;
1496
				$subscription->datem = $this->db->jdate($obj->datem);
1497
				$subscription->datec = $this->db->jdate($obj->datec);
1498
				$subscription->dateh = $this->db->jdate($obj->dateh);
1499
				$subscription->datef = $this->db->jdate($obj->datef);
1500
1501
				$this->subscriptions[] = $subscription;
1502
1503
				$i++;
1504
			}
1505
			return 1;
1506
		} else {
1507
			$this->error = $this->db->error().' sql='.$sql;
1508
			return -1;
1509
		}
1510
	}
1511
1512
1513
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1514
	/**
1515
	 *	Function to get partnerships array
1516
	 *
1517
	 *  @param		string		$mode		'member' or 'thirdparty'
1518
	 *	@return		int						<0 if KO, >0 if OK
1519
	 */
1520
	public function fetchPartnerships($mode)
1521
	{
1522
		// phpcs:enable
1523
		global $langs;
1524
1525
		require_once DOL_DOCUMENT_ROOT.'/parntership/class/partnership.class.php';
1526
1527
1528
		$this->partnerships[] = array();
1529
1530
		return 1;
1531
	}
1532
1533
1534
	/**
1535
	 *	Insert subscription into database and eventually add links to banks, mailman, etc...
1536
	 *
1537
	 *	@param	int	        $date        		Date of effect of subscription
1538
	 *	@param	double		$amount     		Amount of subscription (0 accepted for some members)
1539
	 *	@param	int			$accountid			Id bank account
1540
	 *	@param	string		$operation			Type of payment (if Id bank account provided). Example: 'CB', ...
1541
	 *	@param	string		$label				Label operation (if Id bank account provided)
1542
	 *	@param	string		$num_chq			Numero cheque (if Id bank account provided)
1543
	 *	@param	string		$emetteur_nom		Name of cheque writer
1544
	 *	@param	string		$emetteur_banque	Name of bank of cheque
1545
	 *	@param	int     	$datesubend			Date end subscription
1546
	 *	@param	int     	$fk_type 			Member type id
1547
	 *	@return int         					rowid of record added, <0 if KO
1548
	 */
1549
	public function subscription($date, $amount, $accountid = 0, $operation = '', $label = '', $num_chq = '', $emetteur_nom = '', $emetteur_banque = '', $datesubend = 0, $fk_type = null)
1550
	{
1551
		global $conf, $langs, $user;
1552
1553
		require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
1554
1555
		$error = 0;
1556
1557
		// Clean parameters
1558
		if (!$amount) {
1559
			$amount = 0;
1560
		}
1561
1562
		$this->db->begin();
1563
1564
		if ($datesubend) {
1565
			$datefin = $datesubend;
1566
		} else {
1567
			// If no end date, end date = date + 1 year - 1 day
1568
			$datefin = dol_time_plus_duree($date, 1, 'y');
1569
			$datefin = dol_time_plus_duree($datefin, -1, 'd');
1570
		}
1571
1572
		// Create subscription
1573
		$subscription = new Subscription($this->db);
1574
		$subscription->fk_adherent = $this->id;
1575
		$subscription->dateh = $date; // Date of new subscription
1576
		$subscription->datef = $datefin; // End data of new subscription
1577
		$subscription->amount = $amount;
1578
		$subscription->note = $label; // deprecated
1579
		$subscription->note_public = $label;
1580
		$subscription->fk_type = $fk_type;
1581
1582
		$rowid = $subscription->create($user);
1583
		if ($rowid > 0) {
1584
			// Update denormalized subscription end date (read database subscription to find values)
1585
			// This will also update this->datefin
1586
			$result = $this->update_end_date($user);
1587
			if ($result > 0) {
1588
				// Change properties of object (used by triggers)
1589
				$this->last_subscription_date = dol_now();
1590
				$this->last_subscription_date_start = $date;
1591
				$this->last_subscription_date_end = $datefin;
1592
				$this->last_subscription_amount = $amount;
1593
			}
1594
1595
			if (!$error) {
1596
				$this->db->commit();
1597
				return $rowid;
1598
			} else {
1599
				$this->db->rollback();
1600
				return -2;
1601
			}
1602
		} else {
1603
			$this->error = $subscription->error;
1604
			$this->errors = $subscription->errors;
1605
			$this->db->rollback();
1606
			return -1;
1607
		}
1608
	}
1609
1610
1611
	/**
1612
	 *	Do complementary actions after subscription recording.
1613
	 *
1614
	 *	@param	int			$subscriptionid			Id of created subscription
1615
	 *  @param	string		$option					Which action ('bankdirect', 'bankviainvoice', 'invoiceonly', ...)
1616
	 *	@param	int			$accountid				Id bank account
1617
	 *	@param	int			$datesubscription		Date of subscription
1618
	 *	@param	int			$paymentdate			Date of payment
1619
	 *	@param	string		$operation				Code of type of operation (if Id bank account provided). Example 'CB', ...
1620
	 *	@param	string		$label					Label operation (if Id bank account provided)
1621
	 *	@param	double		$amount     			Amount of subscription (0 accepted for some members)
1622
	 *	@param	string		$num_chq				Numero cheque (if Id bank account provided)
1623
	 *	@param	string		$emetteur_nom			Name of cheque writer
1624
	 *	@param	string		$emetteur_banque		Name of bank of cheque
1625
	 *  @param	string		$autocreatethirdparty	Auto create new thirdparty if member not yet linked to a thirdparty and we request an option that generate invoice.
1626
	 *  @param  string      $ext_payment_id         External id of payment (for example Stripe charge id)
1627
	 *  @param  string      $ext_payment_site       Name of external paymentmode (for example 'stripe')
1628
	 *	@return int									<0 if KO, >0 if OK
1629
	 */
1630
	public function subscriptionComplementaryActions($subscriptionid, $option, $accountid, $datesubscription, $paymentdate, $operation, $label, $amount, $num_chq, $emetteur_nom = '', $emetteur_banque = '', $autocreatethirdparty = 0, $ext_payment_id = '', $ext_payment_site = '')
1631
	{
1632
		global $conf, $langs, $user, $mysoc;
1633
1634
		$error = 0;
1635
1636
		$this->invoice = null; // This will contains invoice if an invoice is created
1637
1638
		dol_syslog("subscriptionComplementaryActions subscriptionid=".$subscriptionid." option=".$option." accountid=".$accountid." datesubscription=".$datesubscription." paymentdate=".
1639
			$paymentdate." label=".$label." amount=".$amount." num_chq=".$num_chq." autocreatethirdparty=".$autocreatethirdparty);
1640
1641
		// Insert into bank account directlty (if option choosed for) + link to llx_subscription if option is 'bankdirect'
1642
		if ($option == 'bankdirect' && $accountid) {
1643
			require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
1644
1645
			$acct = new Account($this->db);
1646
			$result = $acct->fetch($accountid);
1647
1648
			$dateop = $paymentdate;
1649
1650
			$insertid = $acct->addline($dateop, $operation, $label, $amount, $num_chq, '', $user, $emetteur_nom, $emetteur_banque);
1651
			if ($insertid > 0) {
1652
				$inserturlid = $acct->add_url_line($insertid, $this->id, DOL_URL_ROOT.'/adherents/card.php?rowid=', $this->getFullname($langs), 'member');
1653
				if ($inserturlid > 0) {
1654
					// Update table subscription
1655
					$sql = "UPDATE ".MAIN_DB_PREFIX."subscription SET fk_bank=".((int) $insertid);
1656
					$sql .= " WHERE rowid=".((int) $subscriptionid);
1657
1658
					dol_syslog("subscription::subscription", LOG_DEBUG);
1659
					$resql = $this->db->query($sql);
1660
					if (!$resql) {
1661
						$error++;
1662
						$this->error = $this->db->lasterror();
1663
						$this->errors[] = $this->error;
1664
					}
1665
				} else {
1666
					$error++;
1667
					$this->error = $acct->error;
1668
					$this->errors = $acct->errors;
1669
				}
1670
			} else {
1671
				$error++;
1672
				$this->error = $acct->error;
1673
				$this->errors = $acct->errors;
1674
			}
1675
		}
1676
1677
		// If option choosed, we create invoice
1678
		if (($option == 'bankviainvoice' && $accountid) || $option == 'invoiceonly') {
1679
			require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
1680
			require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/paymentterm.class.php';
1681
1682
			$invoice = new Facture($this->db);
1683
			$customer = new Societe($this->db);
1684
1685
			if (!$error) {
1686
				if (!($this->fk_soc > 0)) { // If not yet linked to a company
1687
					if ($autocreatethirdparty) {
1688
						// Create a linked thirdparty to member
1689
						$companyalias = '';
1690
						$fullname = $this->getFullName($langs);
1691
1692
						if ($this->morphy == 'mor') {
1693
							$companyname = $this->company;
1694
							if (!empty($fullname)) {
1695
								$companyalias = $fullname;
1696
							}
1697
						} else {
1698
							$companyname = $fullname;
1699
							if (!empty($this->company)) {
1700
								$companyalias = $this->company;
1701
							}
1702
						}
1703
1704
						$result = $customer->create_from_member($this, $companyname, $companyalias);
1705
						if ($result < 0) {
1706
							$this->error = $customer->error;
1707
							$this->errors = $customer->errors;
1708
							$error++;
1709
						} else {
1710
							$this->fk_soc = $result;
1711
						}
1712
					} else {
1713
						$langs->load("errors");
1714
						$this->error = $langs->trans("ErrorMemberNotLinkedToAThirpartyLinkOrCreateFirst");
1715
						$this->errors[] = $this->error;
1716
						$error++;
1717
					}
1718
				}
1719
			}
1720
			if (!$error) {
1721
				$result = $customer->fetch($this->fk_soc);
1722
				if ($result <= 0) {
1723
					$this->error = $customer->error;
1724
					$this->errors = $customer->errors;
1725
					$error++;
1726
				}
1727
			}
1728
1729
			if (!$error) {
1730
				// Create draft invoice
1731
				$invoice->type = Facture::TYPE_STANDARD;
1732
				$invoice->cond_reglement_id = $customer->cond_reglement_id;
1733
				if (empty($invoice->cond_reglement_id)) {
1734
					$paymenttermstatic = new PaymentTerm($this->db);
1735
					$invoice->cond_reglement_id = $paymenttermstatic->getDefaultId();
1736
					if (empty($invoice->cond_reglement_id)) {
1737
						$error++;
1738
						$this->error = 'ErrorNoPaymentTermRECEPFound';
1739
						$this->errors[] = $this->error;
1740
					}
1741
				}
1742
				$invoice->socid = $this->fk_soc;
1743
				$invoice->date = $datesubscription;
1744
1745
				// Possibility to add external linked objects with hooks
1746
				$invoice->linked_objects['subscription'] = $subscriptionid;
1747
				if (!empty($_POST['other_linked_objects']) && is_array($_POST['other_linked_objects'])) {
1748
					$invoice->linked_objects = array_merge($invoice->linked_objects, $_POST['other_linked_objects']);
1749
				}
1750
1751
				$result = $invoice->create($user);
1752
				if ($result <= 0) {
1753
					$this->error = $invoice->error;
1754
					$this->errors = $invoice->errors;
1755
					$error++;
1756
				} else {
1757
					$this->invoice = $invoice;
1758
				}
1759
			}
1760
1761
			if (!$error) {
1762
				// Add line to draft invoice
1763
				$idprodsubscription = 0;
1764
				if (!empty($conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS) && (!empty($conf->product->enabled) || !empty($conf->service->enabled))) {
1765
					$idprodsubscription = $conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS;
1766
				}
1767
1768
				$vattouse = 0;
1769
				if (isset($conf->global->ADHERENT_VAT_FOR_SUBSCRIPTIONS) && $conf->global->ADHERENT_VAT_FOR_SUBSCRIPTIONS == 'defaultforfoundationcountry') {
1770
					$vattouse = get_default_tva($mysoc, $mysoc, $idprodsubscription);
1771
				}
1772
				//print xx".$vattouse." - ".$mysoc." - ".$customer;exit;
1773
				$result = $invoice->addline($label, 0, 1, $vattouse, 0, 0, $idprodsubscription, 0, $datesubscription, '', 0, 0, '', 'TTC', $amount, 1);
1774
				if ($result <= 0) {
1775
					$this->error = $invoice->error;
1776
					$this->errors = $invoice->errors;
1777
					$error++;
1778
				}
1779
			}
1780
1781
			if (!$error) {
1782
				// Validate invoice
1783
				$result = $invoice->validate($user);
1784
				if ($result <= 0) {
1785
					$this->error = $invoice->error;
1786
					$this->errors = $invoice->errors;
1787
					$error++;
1788
				}
1789
			}
1790
1791
			if (!$error) {
1792
				// TODO Link invoice with subscription ?
1793
			}
1794
1795
			// Add payment onto invoice
1796
			if (!$error && $option == 'bankviainvoice' && $accountid) {
1797
				require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
1798
				require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
1799
				require_once DOL_DOCUMENT_ROOT.'/core/lib/functions.lib.php';
1800
1801
				$amounts = array();
1802
				$amounts[$invoice->id] = price2num($amount);
1803
1804
				$paiement = new Paiement($this->db);
1805
				$paiement->datepaye = $paymentdate;
1806
				$paiement->amounts = $amounts;
1807
				$paiement->paiementid = dol_getIdFromCode($this->db, $operation, 'c_paiement', 'code', 'id', 1);
1808
				$paiement->num_payment = $num_chq;
1809
				$paiement->note_public = $label;
1810
				$paiement->ext_payment_id = $ext_payment_id;
1811
				$paiement->ext_payment_site = $ext_payment_site;
1812
1813
				if (!$error) {
1814
					// Create payment line for invoice
1815
					$paiement_id = $paiement->create($user);
1816
					if (!$paiement_id > 0) {
1817
						$this->error = $paiement->error;
1818
						$this->errors = $paiement->errors;
1819
						$error++;
1820
					}
1821
				}
1822
1823
				if (!$error) {
1824
					// Add transaction into bank account
1825
					$bank_line_id = $paiement->addPaymentToBank($user, 'payment', '(SubscriptionPayment)', $accountid, $emetteur_nom, $emetteur_banque);
1826
					if (!($bank_line_id > 0)) {
1827
						$this->error = $paiement->error;
1828
						$this->errors = $paiement->errors;
1829
						$error++;
1830
					}
1831
				}
1832
1833
				if (!$error && !empty($bank_line_id)) {
1834
					// Update fk_bank into subscription table
1835
					$sql = 'UPDATE '.MAIN_DB_PREFIX.'subscription SET fk_bank='.$bank_line_id;
1836
					$sql .= ' WHERE rowid='.$subscriptionid;
1837
1838
					$result = $this->db->query($sql);
1839
					if (!$result) {
1840
						$error++;
1841
					}
1842
				}
1843
1844
				if (!$error) {
1845
					// Set invoice as paid
1846
					$invoice->setPaid($user);
1847
				}
1848
			}
1849
1850
			if (!$error) {
1851
				// Define output language
1852
				$outputlangs = $langs;
1853
				$newlang = '';
1854
				$lang_id = GETPOST('lang_id');
1855
				if ($conf->global->MAIN_MULTILANGS && empty($newlang) && !empty($lang_id)) {
1856
					$newlang = $lang_id;
1857
				}
1858
				if ($conf->global->MAIN_MULTILANGS && empty($newlang)) {
1859
					$newlang = $customer->default_lang;
1860
				}
1861
				if (!empty($newlang)) {
1862
					$outputlangs = new Translate("", $conf);
1863
					$outputlangs->setDefaultLang($newlang);
1864
				}
1865
				// Generate PDF (whatever is option MAIN_DISABLE_PDF_AUTOUPDATE) so we can include it into email
1866
				//if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
1867
1868
				$invoice->generateDocument($invoice->model_pdf, $outputlangs);
1869
			}
1870
		}
1871
1872
		if ($error) {
1873
			return -1;
1874
		} else {
1875
			return 1;
1876
		}
1877
	}
1878
1879
1880
	/**
1881
	 *		Function that validate a member
1882
	 *
1883
	 *		@param	User	$user		user adherent qui valide
1884
	 *		@return	int					<0 if KO, 0 if nothing done, >0 if OK
1885
	 */
1886
	public function validate($user)
1887
	{
1888
		global $langs, $conf;
1889
1890
		$error = 0;
1891
		$now = dol_now();
1892
1893
		// Check parameters
1894
		if ($this->statut == self::STATUS_VALIDATED) {
1895
			dol_syslog(get_class($this)."::validate statut of member does not allow this", LOG_WARNING);
1896
			return 0;
1897
		}
1898
1899
		$this->db->begin();
1900
1901
		$sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
1902
		$sql .= " statut = ".self::STATUS_VALIDATED;
1903
		$sql .= ", datevalid = '".$this->db->idate($now)."'";
1904
		$sql .= ", fk_user_valid=".$user->id;
1905
		$sql .= " WHERE rowid = ".$this->id;
1906
1907
		dol_syslog(get_class($this)."::validate", LOG_DEBUG);
1908
		$result = $this->db->query($sql);
1909
		if ($result) {
1910
			$this->statut = self::STATUS_VALIDATED;
1911
1912
			// Call trigger
1913
			$result = $this->call_trigger('MEMBER_VALIDATE', $user);
1914
			if ($result < 0) {
1915
				$error++;
1916
				$this->db->rollback();
1917
				return -1;
1918
			}
1919
			// End call triggers
1920
1921
			$this->datevalid = $now;
1922
1923
			$this->db->commit();
1924
			return 1;
1925
		} else {
1926
			$this->error = $this->db->error();
1927
			$this->db->rollback();
1928
			return -1;
1929
		}
1930
	}
1931
1932
1933
	/**
1934
	 *		Fonction qui resilie un adherent
1935
	 *
1936
	 *		@param	User	$user		User making change
1937
	 *		@return	int					<0 if KO, >0 if OK
1938
	 */
1939
	public function resiliate($user)
1940
	{
1941
		global $langs, $conf;
1942
1943
		$error = 0;
1944
1945
		// Check parameters
1946
		if ($this->statut == self::STATUS_RESILIATED) {
1947
			dol_syslog(get_class($this)."::resiliate statut of member does not allow this", LOG_WARNING);
1948
			return 0;
1949
		}
1950
1951
		$this->db->begin();
1952
1953
		$sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
1954
		$sql .= " statut = ".self::STATUS_RESILIATED;
1955
		$sql .= ", fk_user_valid=".$user->id;
1956
		$sql .= " WHERE rowid = ".$this->id;
1957
1958
		$result = $this->db->query($sql);
1959
		if ($result) {
1960
			$this->statut = self::STATUS_RESILIATED;
1961
1962
			// Call trigger
1963
			$result = $this->call_trigger('MEMBER_RESILIATE', $user);
1964
			if ($result < 0) {
1965
				$error++;
1966
				$this->db->rollback();
1967
				return -1;
1968
			}
1969
			// End call triggers
1970
1971
			$this->db->commit();
1972
			return 1;
1973
		} else {
1974
			$this->error = $this->db->error();
1975
			$this->db->rollback();
1976
			return -1;
1977
		}
1978
	}
1979
1980
	/**
1981
	 *		Functiun to exlude (set adherent.status to -2) a member
1982
	 *		TODO
1983
	 *		A private note should be added to know why the member has been excluded
1984
	 *		For historical purpose it add an "extra-subscription" type excluded
1985
	 *
1986
	 *		@param	User	$user		User making change
1987
	 *		@return	int					<0 if KO, >0 if OK
1988
	 */
1989
	public function exclude($user)
1990
	{
1991
		global $langs, $conf;
1992
1993
		$error = 0;
1994
1995
		// Check parameters
1996
		if ($this->statut == self::STATUS_EXCLUDED) {
1997
			dol_syslog(get_class($this)."::resiliate statut of member does not allow this", LOG_WARNING);
1998
			return 0;
1999
		}
2000
2001
		$this->db->begin();
2002
2003
		$sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
2004
		$sql .= " statut = ".self::STATUS_EXCLUDED;
2005
		$sql .= ", fk_user_valid=".$user->id;
2006
		$sql .= " WHERE rowid = ".$this->id;
2007
2008
		$result = $this->db->query($sql);
2009
		if ($result) {
2010
			$this->statut = self::STATUS_EXCLUDED;
2011
2012
			// Call trigger
2013
			$result = $this->call_trigger('MEMBER_EXCLUDE', $user);
2014
			if ($result < 0) {
2015
				$error++;
2016
				$this->db->rollback();
2017
				return -1;
2018
			}
2019
			// End call triggers
2020
2021
			$this->db->commit();
2022
			return 1;
2023
		} else {
2024
			$this->error = $this->db->error();
2025
			$this->db->rollback();
2026
			return -1;
2027
		}
2028
	}
2029
2030
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2031
	/**
2032
	 *  Function to add member into external tools mailing-list, spip, etc.
2033
	 *
2034
	 *  @return		int		<0 if KO, >0 if OK
2035
	 */
2036
	public function add_to_abo()
2037
	{
2038
		// phpcs:enable
2039
		global $conf, $langs;
2040
2041
		include_once DOL_DOCUMENT_ROOT.'/mailmanspip/class/mailmanspip.class.php';
2042
		$mailmanspip = new MailmanSpip($this->db);
2043
2044
		$err = 0;
2045
2046
		// mailman
2047
		if (!empty($conf->global->ADHERENT_USE_MAILMAN) && !empty($conf->mailmanspip->enabled)) {
2048
			$result = $mailmanspip->add_to_mailman($this);
2049
2050
			if ($result < 0) {
2051
				if (!empty($mailmanspip->error)) {
2052
					$this->errors[] = $mailmanspip->error;
2053
				}
2054
				$err += 1;
2055
			}
2056
			foreach ($mailmanspip->mladded_ko as $tmplist => $tmpemail) {
2057
				$langs->load("errors");
2058
				$this->errors[] = $langs->trans("ErrorFailedToAddToMailmanList", $tmpemail, $tmplist);
2059
			}
2060
			foreach ($mailmanspip->mladded_ok as $tmplist => $tmpemail) {
2061
				$langs->load("mailmanspip");
2062
				$this->mesgs[] = $langs->trans("SuccessToAddToMailmanList", $tmpemail, $tmplist);
2063
			}
2064
		}
2065
2066
		// spip
2067
		if (!empty($conf->global->ADHERENT_USE_SPIP) && !empty($conf->mailmanspip->enabled)) {
2068
			$result = $mailmanspip->add_to_spip($this);
2069
			if ($result < 0) {
2070
				$this->errors[] = $mailmanspip->error;
2071
				$err += 1;
2072
			}
2073
		}
2074
		if ($err) {
2075
			return -$err;
2076
		} else {
2077
			return 1;
2078
		}
2079
	}
2080
2081
2082
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2083
	/**
2084
	 *  Function to delete a member from external tools like mailing-list, spip, etc.
2085
	 *
2086
	 *  @return     int     <0 if KO, >0 if OK
2087
	 */
2088
	public function del_to_abo()
2089
	{
2090
		// phpcs:enable
2091
		global $conf, $langs;
2092
2093
		include_once DOL_DOCUMENT_ROOT.'/mailmanspip/class/mailmanspip.class.php';
2094
		$mailmanspip = new MailmanSpip($this->db);
2095
2096
		$err = 0;
2097
2098
		// mailman
2099
		if (!empty($conf->global->ADHERENT_USE_MAILMAN)) {
2100
			$result = $mailmanspip->del_to_mailman($this);
2101
			if ($result < 0) {
2102
				if (!empty($mailmanspip->error)) {
2103
					$this->errors[] = $mailmanspip->error;
2104
				}
2105
				$err += 1;
2106
			}
2107
2108
			foreach ($mailmanspip->mlremoved_ko as $tmplist => $tmpemail) {
2109
				$langs->load("errors");
2110
				$this->errors[] = $langs->trans("ErrorFailedToRemoveToMailmanList", $tmpemail, $tmplist);
2111
			}
2112
			foreach ($mailmanspip->mlremoved_ok as $tmplist => $tmpemail) {
2113
				$langs->load("mailmanspip");
2114
				$this->mesgs[] = $langs->trans("SuccessToRemoveToMailmanList", $tmpemail, $tmplist);
2115
			}
2116
		}
2117
2118
		if ($conf->global->ADHERENT_USE_SPIP && !empty($conf->mailmanspip->enabled)) {
2119
			$result = $mailmanspip->del_to_spip($this);
2120
			if ($result < 0) {
2121
				$this->errors[] = $mailmanspip->error;
2122
				$err += 1;
2123
			}
2124
		}
2125
		if ($err) {
2126
			// error
2127
			return -$err;
2128
		} else {
2129
			return 1;
2130
		}
2131
	}
2132
2133
2134
	/**
2135
	 *    Return civility label of a member
2136
	 *
2137
	 *    @return   string              	Translated name of civility (translated with transnoentitiesnoconv)
2138
	 */
2139
	public function getCivilityLabel()
2140
	{
2141
		global $langs;
2142
		$langs->load("dict");
2143
2144
		$code = (empty($this->civility_id) ? '' : $this->civility_id);
2145
		if (empty($code)) {
2146
			return '';
2147
		}
2148
		return $langs->getLabelFromKey($this->db, "Civility".$code, "c_civility", "code", "label", $code);
2149
	}
2150
2151
	/**
2152
	 *  Return clicable name (with picto eventually)
2153
	 *
2154
	 *	@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)
2155
	 *	@param	int		$maxlen						length max label
2156
	 *	@param	string	$option						Page for link ('card', 'category', 'subscription', ...)
2157
	 *	@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
2158
	 *	@param  string  $morecss        			Add more css on link
2159
	 *	@param  int		$save_lastsearch_value    	-1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
2160
	 *	@param	int		$notooltip					1=Disable tooltip
2161
	 *	@param  int		$addlinktonotes				1=Add link to notes
2162
	 *	@return	string								Chaine avec URL
2163
	 */
2164
	public function getNomUrl($withpictoimg = 0, $maxlen = 0, $option = 'card', $mode = '', $morecss = '', $save_lastsearch_value = -1, $notooltip = 0, $addlinktonotes = 0)
2165
	{
2166
		global $conf, $langs;
2167
2168
		if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) && $withpictoimg) {
2169
			$withpictoimg = 0;
2170
		}
2171
2172
		$result = '';
2173
		$label = '';
2174
		$linkstart = '';
2175
		$linkend = '';
2176
2177
		if (!empty($this->photo)) {
2178
			$label .= '<div class="photointooltip">';
2179
			$label .= Form::showphoto('memberphoto', $this, 80, 0, 0, 'photowithmargin photologintooltip', 'small', 0, 1);
2180
			$label .= '</div><div style="clear: both;"></div>';
2181
		}
2182
2183
		$label .= '<div class="centpercent">';
2184
		$label .= img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("Member").'</u>';
2185
		$label .= ' '.$this->getLibStatut(4);
2186
		if (!empty($this->ref)) {
2187
			$label .= '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
2188
		}
2189
		if (!empty($this->firstname) || !empty($this->lastname)) {
2190
			$label .= '<br><b>'.$langs->trans('Name').':</b> '.$this->getFullName($langs);
2191
		}
2192
		if (!empty($this->company)) {
2193
			$label .= '<br><b>'.$langs->trans('Company').':</b> '.$this->company;
2194
		}
2195
		$label .= '</div>';
2196
2197
		$url = DOL_URL_ROOT.'/adherents/card.php?rowid='.((int) $this->id);
2198
		if ($option == 'subscription') {
2199
			$url = DOL_URL_ROOT.'/adherents/subscription.php?rowid='.((int) $this->id);
2200
		}
2201
2202
		if ($option != 'nolink') {
2203
			// Add param to save lastsearch_values or not
2204
			$add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
2205
			if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
2206
				$add_save_lastsearch_values = 1;
2207
			}
2208
			if ($add_save_lastsearch_values) {
2209
				$url .= '&save_lastsearch_values=1';
2210
			}
2211
		}
2212
2213
		$linkstart .= '<a href="'.$url.'"';
2214
		$linkclose = "";
2215
		if (empty($notooltip)) {
2216
			if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
2217
				$langs->load("users");
2218
				$label = $langs->trans("ShowUser");
2219
				$linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
2220
			}
2221
			$linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
2222
			$linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
2223
		}
2224
2225
		$linkstart .= $linkclose.'>';
2226
		$linkend = '</a>';
2227
2228
		$result .= $linkstart;
2229
		if ($withpictoimg) {
2230
			$result .= '<div class="inline-block nopadding valignmiddle">';
2231
		}
2232
		if ($withpictoimg) {
2233
			$paddafterimage = '';
2234
			if (abs($withpictoimg) == 1) {
2235
				$paddafterimage = 'style="margin-right: 3px;"';
2236
			}
2237
			// Only picto
2238
			if ($withpictoimg > 0) {
2239
				$picto = '<span class="nopadding'.($morecss ? ' userimg'.$morecss : '').'">'.
2240
					img_object('', 'user', $paddafterimage.' '.($notooltip ? '' : 'class="classfortooltip"'), 0, 0, $notooltip ? 0 : 1).'</span>';
2241
			} else {
2242
				// Picto must be a photo
2243
				$picto = '<span class="nopadding'.($morecss ? ' userimg'.$morecss : '').'"'.($paddafterimage ? ' '.$paddafterimage : '').'>';
2244
				$picto .= Form::showphoto('memberphoto', $this, 0, 0, 0, 'userphoto'.($withpictoimg == -3 ? 'small' : ''), 'mini', 0, 1);
2245
				$picto .= '</span>';
2246
			}
2247
			$result .= $picto;
2248
		}
2249
		if ($withpictoimg > -2 && $withpictoimg != 2) {
2250
			if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
2251
				$result .= '<span class="nopadding valignmiddle'.((!isset($this->statut) || $this->statut) ? '' : ' strikefordisabled').
2252
				($morecss ? ' usertext'.$morecss : '').'">';
2253
			}
2254
			if ($mode == 'login') {
2255
				$result .= dol_trunc($this->login, $maxlen);
2256
			} elseif ($mode == 'ref') {
2257
				$result .= $this->ref;
2258
			} else {
2259
				$result .= $this->getFullName($langs, '', ($mode == 'firstname' ? 2 : ($mode == 'lastname' ? 4 : -1)), $maxlen);
2260
			}
2261
			if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
2262
				$result .= '</span>';
2263
			}
2264
		}
2265
		if ($withpictoimg) {
2266
			$result .= '</div>';
2267
		}
2268
		$result .= $linkend;
2269
2270
		if ($addlinktonotes) {
2271
			if ($this->note_private) {
2272
				$notetoshow = $langs->trans("ViewPrivateNote").':<br>'.dol_string_nohtmltag($this->note_private, 1);
2273
				$result .= ' <span class="note inline-block">';
2274
				$result .= '<a href="'.DOL_URL_ROOT.'/adherents/note.php?id='.$this->id.'" class="classfortooltip" title="'.dol_escape_htmltag($notetoshow).'">';
2275
				$result .= img_picto('', 'note');
2276
				$result .= '</a>';
2277
				$result .= '</span>';
2278
			}
2279
		}
2280
2281
		return $result;
2282
	}
2283
2284
	/**
2285
	 *  Retourne le libelle du statut d'un adherent (brouillon, valide, resilie, exclu)
2286
	 *
2287
	 *  @param	int		$mode       0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
2288
	 *  @return string				Label
2289
	 */
2290
	public function getLibStatut($mode = 0)
2291
	{
2292
		return $this->LibStatut($this->statut, $this->need_subscription, $this->datefin, $mode);
2293
	}
2294
2295
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2296
	/**
2297
	 *  Renvoi le libelle d'un statut donne
2298
	 *
2299
	 *  @param	int			$status      			Id status
2300
	 *	@param	int			$need_subscription		1 if member type need subscription, 0 otherwise
2301
	 *	@param	int     	$date_end_subscription	Date fin adhesion
2302
	 *  @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
2303
	 *  @return string      						Label
2304
	 */
2305
	public function LibStatut($status, $need_subscription, $date_end_subscription, $mode = 0)
2306
	{
2307
		// phpcs:enable
2308
		global $langs;
2309
		$langs->load("members");
2310
2311
		$statusType = '';
2312
		$labelStatus = '';
2313
		$labelStatusShort = '';
2314
2315
		if ($status == self::STATUS_DRAFT) {
2316
			$statusType = 'status0';
2317
			$labelStatus = $langs->trans("MemberStatusDraft");
2318
			$labelStatusShort = $langs->trans("MemberStatusDraftShort");
2319
		} elseif ($status >= self::STATUS_VALIDATED) {
2320
			if ($need_subscription == 0) {
2321
				$statusType = 'status4';
2322
				$labelStatus = $langs->trans("MemberStatusNoSubscription");
2323
				$labelStatusShort = $langs->trans("MemberStatusNoSubscriptionShort");
2324
			} elseif (!$date_end_subscription) {
2325
				$statusType = 'status1';
2326
				$labelStatus = $langs->trans("MemberStatusActive");
2327
				$labelStatusShort = $langs->trans("MemberStatusActiveShort");
2328
			} elseif ($date_end_subscription < dol_now()) {
2329
				$statusType = 'status3';
2330
				$labelStatus = $langs->trans("MemberStatusActiveLate");
2331
				$labelStatusShort = $langs->trans("MemberStatusActiveLateShort");
2332
			} else {
2333
				$statusType = 'status4';
2334
				$labelStatus = $langs->trans("MemberStatusPaid");
2335
				$labelStatusShort = $langs->trans("MemberStatusPaidShort");
2336
			}
2337
		} elseif ($status == self::STATUS_RESILIATED) {
2338
			$statusType = 'status6';
2339
			$labelStatus = $langs->trans("MemberStatusResiliated");
2340
			$labelStatusShort = $langs->trans("MemberStatusResiliatedShort");
2341
		} elseif ($status == self::STATUS_EXCLUDED) {
2342
			$statusType = 'status10';
2343
			$labelStatus = $langs->trans("MemberStatusExcluded");
2344
			$labelStatusShort = $langs->trans("MemberStatusExcludedShort");
2345
		}
2346
2347
		return dolGetStatus($labelStatus, $labelStatusShort, '', $statusType, $mode);
2348
	}
2349
2350
2351
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2352
	/**
2353
	 *      Charge indicateurs this->nb de tableau de bord
2354
	 *
2355
	 *      @return     int         <0 if KO, >0 if OK
2356
	 */
2357
	public function load_state_board()
2358
	{
2359
		// phpcs:enable
2360
		global $conf;
2361
2362
		$this->nb = array();
2363
2364
		$sql = "SELECT count(a.rowid) as nb";
2365
		$sql .= " FROM ".MAIN_DB_PREFIX."adherent as a";
2366
		$sql .= " WHERE a.statut > 0";
2367
		$sql .= " AND a.entity IN (".getEntity('adherent').")";
2368
2369
		$resql = $this->db->query($sql);
2370
		if ($resql) {
2371
			while ($obj = $this->db->fetch_object($resql)) {
2372
				$this->nb["members"] = $obj->nb;
2373
			}
2374
			$this->db->free($resql);
2375
			return 1;
2376
		} else {
2377
			dol_print_error($this->db);
2378
			$this->error = $this->db->error();
2379
			return -1;
2380
		}
2381
	}
2382
2383
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2384
	/**
2385
	 *      Load indicators for dashboard (this->nbtodo and this->nbtodolate)
2386
	 *
2387
	 *      @param	User	$user   		Objet user
2388
	 *      @param  string	$mode           "expired" for membership to renew, "shift" for member to validate
2389
	 *      @return WorkboardResponse|int 	<0 if KO, WorkboardResponse if OK
2390
	 */
2391
	public function load_board($user, $mode)
2392
	{
2393
		// phpcs:enable
2394
		global $conf, $langs;
2395
2396
		if ($user->socid) {
2397
			return -1; // protection pour eviter appel par utilisateur externe
2398
		}
2399
2400
		$now = dol_now();
2401
2402
		$sql = "SELECT a.rowid, a.datefin, a.statut";
2403
		$sql .= " FROM ".MAIN_DB_PREFIX."adherent as a";
2404
		$sql .= ", ".MAIN_DB_PREFIX."adherent_type as t";
2405
		$sql .= " WHERE a.fk_adherent_type = t.rowid";
2406
		if ($mode == 'expired') {
2407
			$sql .= " AND a.statut = ".self::STATUS_VALIDATED;
2408
			$sql .= " AND a.entity IN (".getEntity('adherent').")";
2409
			$sql .= " AND ((a.datefin IS NULL or a.datefin < '".$this->db->idate($now)."') AND t.subscription = '1')";
2410
		} elseif ($mode == 'shift') {
2411
			$sql .= " AND a.statut = ".self::STATUS_DRAFT;
2412
			$sql .= " AND a.entity IN (".getEntity('adherent').")";
2413
		}
2414
2415
		$resql = $this->db->query($sql);
2416
		if ($resql) {
2417
			$langs->load("members");
2418
2419
			$warning_delay = 0;
2420
			$url = '';
2421
			$label = '';
2422
			$labelShort = '';
2423
2424
			if ($mode == 'expired') {
2425
				$warning_delay = $conf->adherent->subscription->warning_delay / 60 / 60 / 24;
2426
				$label = $langs->trans("MembersWithSubscriptionToReceive");
2427
				$labelShort = $langs->trans("MembersWithSubscriptionToReceiveShort");
2428
				$url = DOL_URL_ROOT.'/adherents/list.php?mainmenu=members&amp;statut='.self::STATUS_VALIDATED.'&amp;filter=outofdate';
2429
			} elseif ($mode == 'shift') {
2430
				$warning_delay = $conf->adherent->subscription->warning_delay / 60 / 60 / 24;
2431
				$url = DOL_URL_ROOT.'/adherents/list.php?mainmenu=members&amp;statut='.self::STATUS_DRAFT;
2432
				$label = $langs->trans("MembersListToValid");
2433
				$labelShort = $langs->trans("ToValidate");
2434
			}
2435
2436
			$response = new WorkboardResponse();
2437
			$response->warning_delay = $warning_delay;
2438
			$response->label = $label;
2439
			$response->labelShort = $labelShort;
2440
			$response->url = $url;
2441
			$response->img = img_object('', "user");
2442
2443
			$adherentstatic = new Adherent($this->db);
2444
2445
			while ($obj = $this->db->fetch_object($resql)) {
2446
				$response->nbtodo++;
2447
2448
				$adherentstatic->datefin = $this->db->jdate($obj->datefin);
2449
				$adherentstatic->statut = $obj->statut;
2450
2451
				if ($adherentstatic->hasDelay()) {
2452
					$response->nbtodolate++;
2453
				}
2454
			}
2455
2456
			return $response;
2457
		} else {
2458
			dol_print_error($this->db);
2459
			$this->error = $this->db->error();
2460
			return -1;
2461
		}
2462
	}
2463
2464
2465
	/**
2466
	 *  Create a document onto disk according to template module.
2467
	 *
2468
	 *  @param	    string		$modele			Force template to use ('' to not force)
2469
	 *  @param		Translate	$outputlangs	objet lang a utiliser pour traduction
2470
	 *  @param      int			$hidedetails    Hide details of lines
2471
	 *  @param      int			$hidedesc       Hide description
2472
	 *  @param      int			$hideref        Hide ref
2473
	 *  @param   null|array  $moreparams     Array to provide more information
2474
	 *  @return     int         				0 if KO, 1 if OK
2475
	 */
2476
	public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
2477
	{
2478
		global $conf, $langs;
2479
2480
		$langs->load("orders");
2481
2482
		if (!dol_strlen($modele)) {
2483
			$modele = 'standard';
2484
2485
			if ($this->model_pdf) {
2486
				$modele = $this->model_pdf;
2487
			} elseif (!empty($conf->global->ADHERENT_ADDON_PDF)) {
2488
				$modele = $conf->global->ADHERENT_ADDON_PDF;
2489
			}
2490
		}
2491
2492
		$modelpath = "core/modules/member/doc/";
2493
2494
		return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
2495
	}
2496
2497
2498
	/**
2499
	 *  Initialise an instance with random values.
2500
	 *  Used to build previews or test instances.
2501
	 *	id must be 0 if object instance is a specimen.
2502
	 *
2503
	 *  @return	int
2504
	 */
2505
	public function initAsSpecimen()
2506
	{
2507
		global $user, $langs;
2508
		$now = dol_now();
2509
2510
		// Initialise parametres
2511
		$this->id = 0;
2512
		$this->ref = 'ABC001';
2513
		$this->entity = 1;
2514
		$this->specimen = 1;
2515
		$this->civility_id = 0;
2516
		$this->lastname = 'DOLIBARR';
2517
		$this->firstname = 'SPECIMEN';
2518
		$this->gender = 'man';
2519
		$this->login = 'dolibspec';
2520
		$this->pass = 'dolibspec';
2521
		$this->company = 'Societe ABC';
2522
		$this->address = '61 jump street';
2523
		$this->zip = '75000';
2524
		$this->town = 'Paris';
2525
		$this->country_id = 1;
2526
		$this->country_code = 'FR';
2527
		$this->country = 'France';
2528
		$this->morphy = 'mor';
2529
		$this->email = '[email protected]';
2530
		$this->socialnetworks = array(
2531
			'skype' => 'skypepseudo',
2532
			'twitter' => 'twitterpseudo',
2533
			'facebook' => 'facebookpseudo',
2534
			'linkedin' => 'linkedinpseudo',
2535
		);
2536
		$this->phone = '0999999999';
2537
		$this->phone_perso = '0999999998';
2538
		$this->phone_mobile = '0999999997';
2539
		$this->note_public = 'This is a public note';
2540
		$this->note_private = 'This is a private note';
2541
		$this->birth = $now;
2542
		$this->photo = '';
2543
		$this->public = 1;
2544
		$this->statut = self::STATUS_DRAFT;
2545
2546
		$this->datefin = $now;
2547
		$this->datevalid = $now;
2548
2549
		$this->typeid = 1; // Id type adherent
2550
		$this->type = 'Type adherent'; // Libelle type adherent
2551
		$this->need_subscription = 0;
2552
2553
		$this->first_subscription_date = $now;
2554
		$this->first_subscription_date_start = $this->first_subscription_date;
2555
		$this->first_subscription_date_end = dol_time_plus_duree($this->first_subscription_date_start, 1, 'y');
2556
		$this->first_subscription_amount = 10;
2557
2558
		$this->last_subscription_date = $this->first_subscription_date;
2559
		$this->last_subscription_date_start = $this->first_subscription_date;
2560
		$this->last_subscription_date_end = dol_time_plus_duree($this->last_subscription_date_start, 1, 'y');
2561
		$this->last_subscription_amount = 10;
2562
		return 1;
2563
	}
2564
2565
2566
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2567
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
2568
	/**
2569
	 *	Retourne chaine DN complete dans l'annuaire LDAP pour l'objet
2570
	 *
2571
	 *	@param	array	$info		Info array loaded by _load_ldap_info
2572
	 *	@param	int		$mode		0=Return full DN (uid=qqq,ou=xxx,dc=aaa,dc=bbb)
2573
	 *								1=Return DN without key inside (ou=xxx,dc=aaa,dc=bbb)
2574
	 *								2=Return key only (uid=qqq)
2575
	 *	@return	string				DN
2576
	 */
2577
	public function _load_ldap_dn($info, $mode = 0)
2578
	{
2579
		// phpcs:enable
2580
		global $conf;
2581
		$dn = '';
2582
		if ($mode == 0) {
2583
			$dn = $conf->global->LDAP_KEY_MEMBERS."=".$info[$conf->global->LDAP_KEY_MEMBERS].",".$conf->global->LDAP_MEMBER_DN;
2584
		}
2585
		if ($mode == 1) {
2586
			$dn = $conf->global->LDAP_MEMBER_DN;
2587
		}
2588
		if ($mode == 2) {
2589
			$dn = $conf->global->LDAP_KEY_MEMBERS."=".$info[$conf->global->LDAP_KEY_MEMBERS];
2590
		}
2591
		return $dn;
2592
	}
2593
2594
2595
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2596
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
2597
	/**
2598
	 *	Initialise tableau info (tableau des attributs LDAP)
2599
	 *
2600
	 *	@return		array		Tableau info des attributs
2601
	 */
2602
	public function _load_ldap_info()
2603
	{
2604
		// phpcs:enable
2605
		global $conf, $langs;
2606
2607
		$info = array();
2608
		$socialnetworks = getArrayOfSocialNetworks();
2609
		$keymodified = false;
2610
2611
		// Object classes
2612
		$info["objectclass"] = explode(',', $conf->global->LDAP_MEMBER_OBJECT_CLASS);
2613
2614
		$this->fullname = $this->getFullName($langs);
2615
2616
		// For avoid ldap error when firstname and lastname are empty
2617
		if ($this->morphy == 'mor' && (empty($this->fullname) || $this->fullname == $this->company)) {
2618
			$this->fullname = $this->company;
2619
			$this->lastname = $this->company;
2620
		}
2621
2622
		// Possible LDAP KEY (constname => varname)
2623
		$ldapkey = array(
2624
			'LDAP_MEMBER_FIELD_FULLNAME' => 'fullname',
2625
			'LDAP_MEMBER_FIELD_NAME' => 'lastname',
2626
			'LDAP_MEMBER_FIELD_LOGIN' => 'login',
2627
			'LDAP_MEMBER_FIELD_LOGIN_SAMBA' => 'login',
2628
			'LDAP_MEMBER_FIELD_MAIL' => 'email'
2629
		);
2630
2631
		// Member
2632
		foreach ($ldapkey as $constname => $varname) {
2633
			if (!empty($this->$varname) && !empty($conf->global->$constname)) {
2634
				$info[$conf->global->$constname] = $this->$varname;
2635
2636
				// Check if it is the LDAP key and if its value has been changed
2637
				if (!empty($conf->global->LDAP_KEY_MEMBERS) && $conf->global->LDAP_KEY_MEMBERS == $conf->global->$constname) {
2638
					if (!empty($this->oldcopy) && $this->$varname != $this->oldcopy->$varname) {
2639
						$keymodified = true; // For check if LDAP key has been modified
2640
					}
2641
				}
2642
			}
2643
		}
2644
		if ($this->firstname && !empty($conf->global->LDAP_MEMBER_FIELD_FIRSTNAME)) {
2645
			$info[$conf->global->LDAP_MEMBER_FIELD_FIRSTNAME] = $this->firstname;
2646
		}
2647
		if ($this->poste && !empty($conf->global->LDAP_MEMBER_FIELD_TITLE)) {
2648
			$info[$conf->global->LDAP_MEMBER_FIELD_TITLE] = $this->poste;
2649
		}
2650
		if ($this->company && !empty($conf->global->LDAP_MEMBER_FIELD_COMPANY)) {
2651
			$info[$conf->global->LDAP_MEMBER_FIELD_COMPANY] = $this->company;
2652
		}
2653
		if ($this->address && !empty($conf->global->LDAP_MEMBER_FIELD_ADDRESS)) {
2654
			$info[$conf->global->LDAP_MEMBER_FIELD_ADDRESS] = $this->address;
2655
		}
2656
		if ($this->zip && !empty($conf->global->LDAP_MEMBER_FIELD_ZIP)) {
2657
			$info[$conf->global->LDAP_MEMBER_FIELD_ZIP] = $this->zip;
2658
		}
2659
		if ($this->town && !empty($conf->global->LDAP_MEMBER_FIELD_TOWN)) {
2660
			$info[$conf->global->LDAP_MEMBER_FIELD_TOWN] = $this->town;
2661
		}
2662
		if ($this->country_code && !empty($conf->global->LDAP_MEMBER_FIELD_COUNTRY)) {
2663
			$info[$conf->global->LDAP_MEMBER_FIELD_COUNTRY] = $this->country_code;
2664
		}
2665
		foreach ($socialnetworks as $key => $value) {
2666
			if ($this->socialnetworks[$value['label']] && !empty($conf->global->{'LDAP_MEMBER_FIELD_'.strtoupper($value['label'])})) {
2667
				$info[$conf->global->{'LDAP_MEMBER_FIELD_'.strtoupper($value['label'])}] = $this->socialnetworks[$value['label']];
2668
			}
2669
		}
2670
		if ($this->phone && !empty($conf->global->LDAP_MEMBER_FIELD_PHONE)) {
2671
			$info[$conf->global->LDAP_MEMBER_FIELD_PHONE] = $this->phone;
2672
		}
2673
		if ($this->phone_perso && !empty($conf->global->LDAP_MEMBER_FIELD_PHONE_PERSO)) {
2674
			$info[$conf->global->LDAP_MEMBER_FIELD_PHONE_PERSO] = $this->phone_perso;
2675
		}
2676
		if ($this->phone_mobile && !empty($conf->global->LDAP_MEMBER_FIELD_MOBILE)) {
2677
			$info[$conf->global->LDAP_MEMBER_FIELD_MOBILE] = $this->phone_mobile;
2678
		}
2679
		if ($this->fax && !empty($conf->global->LDAP_MEMBER_FIELD_FAX)) {
2680
			$info[$conf->global->LDAP_MEMBER_FIELD_FAX] = $this->fax;
2681
		}
2682
		if ($this->note_private && !empty($conf->global->LDAP_MEMBER_FIELD_DESCRIPTION)) {
2683
			$info[$conf->global->LDAP_MEMBER_FIELD_DESCRIPTION] = dol_string_nohtmltag($this->note_private, 2);
2684
		}
2685
		if ($this->note_public && !empty($conf->global->LDAP_MEMBER_FIELD_NOTE_PUBLIC)) {
2686
			$info[$conf->global->LDAP_MEMBER_FIELD_NOTE_PUBLIC] = dol_string_nohtmltag($this->note_public, 2);
2687
		}
2688
		if ($this->birth && !empty($conf->global->LDAP_MEMBER_FIELD_BIRTHDATE)) {
2689
			$info[$conf->global->LDAP_MEMBER_FIELD_BIRTHDATE] = dol_print_date($this->birth, 'dayhourldap');
2690
		}
2691
		if (isset($this->statut) && !empty($conf->global->LDAP_FIELD_MEMBER_STATUS)) {
2692
			$info[$conf->global->LDAP_FIELD_MEMBER_STATUS] = $this->statut;
2693
		}
2694
		if ($this->datefin && !empty($conf->global->LDAP_FIELD_MEMBER_END_LASTSUBSCRIPTION)) {
2695
			$info[$conf->global->LDAP_FIELD_MEMBER_END_LASTSUBSCRIPTION] = dol_print_date($this->datefin, 'dayhourldap');
2696
		}
2697
2698
		// When password is modified
2699
		if (!empty($this->pass)) {
2700
			if (!empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD)) {
2701
				$info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD] = $this->pass; // this->pass = mot de passe non crypte
2702
			}
2703
			if (!empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED)) {
2704
				$info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED] = dol_hash($this->pass, 4); // Create OpenLDAP MD5 password (TODO add type of encryption)
2705
			}
2706
		} elseif ($conf->global->LDAP_SERVER_PROTOCOLVERSION !== '3') {
2707
			// Set LDAP password if possible
2708
			// If ldap key is modified and LDAPv3 we use ldap_rename function for avoid lose encrypt password
2709
			if (!empty($conf->global->DATABASE_PWD_ENCRYPTED)) {
2710
				// Just for the default MD5 !
2711
				if (empty($conf->global->MAIN_SECURITY_HASH_ALGO)) {
2712
					if ($this->pass_indatabase_crypted && !empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED)) {
2713
						// Create OpenLDAP MD5 password from Dolibarr MD5 password
2714
						// Note: This suppose that "pass_indatabase_crypted" is a md5 (guaranted by the previous test if "(empty($conf->global->MAIN_SECURITY_HASH_ALGO))"
2715
						$info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED] = '{md5}'.base64_encode(hex2bin($this->pass_indatabase_crypted));
2716
					}
2717
				}
2718
			} elseif (!empty($this->pass_indatabase)) {
2719
				// Use $this->pass_indatabase value if exists
2720
				if (!empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD)) {
2721
					$info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD] = $this->pass_indatabase; // $this->pass_indatabase = mot de passe non crypte
2722
				}
2723
				if (!empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED)) {
2724
					$info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED] = dol_hash($this->pass_indatabase, 4); // md5 for OpenLdap TODO add type of encryption
2725
				}
2726
			}
2727
		}
2728
2729
		// Subscriptions
2730
		if ($this->first_subscription_date && !empty($conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_DATE)) {
2731
			$info[$conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_DATE] = dol_print_date($this->first_subscription_date, 'dayhourldap');
2732
		}
2733
		if (isset($this->first_subscription_amount) && !empty($conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_AMOUNT)) {
2734
			$info[$conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_AMOUNT] = $this->first_subscription_amount;
2735
		}
2736
		if ($this->last_subscription_date && !empty($conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_DATE)) {
2737
			$info[$conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_DATE] = dol_print_date($this->last_subscription_date, 'dayhourldap');
2738
		}
2739
		if (isset($this->last_subscription_amount) && !empty($conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_AMOUNT)) {
2740
			$info[$conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_AMOUNT] = $this->last_subscription_amount;
2741
		}
2742
2743
		return $info;
2744
	}
2745
2746
2747
	/**
2748
	 *      Load type info information in the member object
2749
	 *
2750
	 *      @param  int		$id       Id of member to load
2751
	 *      @return	void
2752
	 */
2753
	public function info($id)
2754
	{
2755
		$sql = 'SELECT a.rowid, a.datec as datec,';
2756
		$sql .= ' a.datevalid as datev,';
2757
		$sql .= ' a.tms as datem,';
2758
		$sql .= ' a.fk_user_author, a.fk_user_valid, a.fk_user_mod';
2759
		$sql .= ' FROM '.MAIN_DB_PREFIX.'adherent as a';
2760
		$sql .= ' WHERE a.rowid = '.((int) $id);
2761
2762
		dol_syslog(get_class($this)."::info", LOG_DEBUG);
2763
		$result = $this->db->query($sql);
2764
		if ($result) {
2765
			if ($this->db->num_rows($result)) {
2766
				$obj = $this->db->fetch_object($result);
2767
				$this->id = $obj->rowid;
2768
				if ($obj->fk_user_author) {
2769
					$cuser = new User($this->db);
2770
					$cuser->fetch($obj->fk_user_author);
2771
					$this->user_creation = $cuser;
2772
				}
2773
2774
				if ($obj->fk_user_valid) {
2775
					$vuser = new User($this->db);
2776
					$vuser->fetch($obj->fk_user_valid);
2777
					$this->user_validation = $vuser;
2778
				}
2779
2780
				if ($obj->fk_user_mod) {
2781
					$muser = new User($this->db);
2782
					$muser->fetch($obj->fk_user_mod);
2783
					$this->user_modification = $muser;
2784
				}
2785
2786
				$this->date_creation = $this->db->jdate($obj->datec);
2787
				$this->date_validation = $this->db->jdate($obj->datev);
2788
				$this->date_modification = $this->db->jdate($obj->datem);
2789
			}
2790
2791
			$this->db->free($result);
2792
		} else {
2793
			dol_print_error($this->db);
2794
		}
2795
	}
2796
2797
	/**
2798
	 *  Return number of mass Emailing received by this member with its email
2799
	 *
2800
	 *  @return       int     Number of EMailings
2801
	 */
2802
	public function getNbOfEMailings()
2803
	{
2804
		$sql = "SELECT count(mc.email) as nb";
2805
		$sql .= " FROM ".MAIN_DB_PREFIX."mailing_cibles as mc";
2806
		$sql .= " WHERE mc.email = '".$this->db->escape($this->email)."'";
2807
		$sql .= " AND mc.statut NOT IN (-1,0)"; // -1 erreur, 0 non envoye, 1 envoye avec succes
2808
2809
		$resql = $this->db->query($sql);
2810
		if ($resql) {
2811
			$obj = $this->db->fetch_object($resql);
2812
			$nb = $obj->nb;
2813
2814
			$this->db->free($resql);
2815
			return $nb;
2816
		} else {
2817
			$this->error = $this->db->error();
2818
			return -1;
2819
		}
2820
	}
2821
2822
	/**
2823
	 * Sets object to supplied categories.
2824
	 *
2825
	 * Deletes object from existing categories not supplied.
2826
	 * Adds it to non existing supplied categories.
2827
	 * Existing categories are left untouch.
2828
	 *
2829
	 * @param int[]|int $categories Category or categories IDs
2830
	 * @return void
2831
	 */
2832
	public function setCategories($categories)
2833
	{
2834
		require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
2835
		return parent::setCategoriesCommon($categories, Categorie::TYPE_MEMBER);
2836
	}
2837
2838
	/**
2839
	 * Function used to replace a thirdparty id with another one.
2840
	 *
2841
	 * @param DoliDB 	$db 			Database handler
2842
	 * @param int 		$origin_id 		Old thirdparty id
2843
	 * @param int 		$dest_id 		New thirdparty id
2844
	 * @return bool
2845
	 */
2846
	public static function replaceThirdparty($db, $origin_id, $dest_id)
2847
	{
2848
		$tables = array('adherent');
2849
2850
		return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
2851
	}
2852
2853
	/**
2854
	 * Return if a member is late (subscription late) or not
2855
	 *
2856
	 * @return boolean     True if late, False if not late
2857
	 */
2858
	public function hasDelay()
2859
	{
2860
		global $conf;
2861
2862
		//Only valid members
2863
		if ($this->statut != self::STATUS_VALIDATED) {
2864
			return false;
2865
		}
2866
		if (!$this->datefin) {
2867
			return false;
2868
		}
2869
2870
		$now = dol_now();
2871
2872
		return $this->datefin < ($now - $conf->adherent->subscription->warning_delay);
2873
	}
2874
2875
2876
	/**
2877
	 * Send reminders by emails before subscription end
2878
	 * CAN BE A CRON TASK
2879
	 *
2880
	 * @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'
2881
	 * @return	int									0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK)
2882
	 */
2883
	public function sendReminderForExpiredSubscription($daysbeforeendlist = '10')
2884
	{
2885
		global $conf, $langs, $mysoc, $user;
2886
2887
		$error = 0;
2888
		$this->output = '';
2889
		$this->error = '';
2890
2891
		$blockingerrormsg = '';
2892
2893
		if (empty($conf->adherent->enabled)) { // Should not happen. If module disabled, cron job should not be visible.
2894
			$langs->load("agenda");
2895
			$this->output = $langs->trans('ModuleNotEnabled', $langs->transnoentitiesnoconv("Adherent"));
2896
			return 0;
2897
		}
2898
		if (empty($conf->global->MEMBER_REMINDER_EMAIL)) {
2899
			$langs->load("agenda");
2900
			$this->output = $langs->trans('EventRemindersByEmailNotEnabled', $langs->transnoentitiesnoconv("Adherent"));
2901
			return 0;
2902
		}
2903
2904
		$now = dol_now();
2905
		$nbok = 0;
2906
		$nbko = 0;
2907
2908
		$listofmembersok = array();
2909
		$listofmembersko = array();
2910
2911
		$arraydaysbeforeend = explode(';', $daysbeforeendlist);
2912
		foreach ($arraydaysbeforeend as $daysbeforeend) { // Loop on each delay
2913
			dol_syslog(__METHOD__.' - Process delta = '.$daysbeforeend, LOG_DEBUG);
2914
2915
			if (!is_numeric($daysbeforeend)) {
2916
				$blockingerrormsg = "Value for delta is not a positive or negative numeric";
2917
				$nbko++;
2918
				break;
2919
			}
2920
2921
			$tmp = dol_getdate($now);
2922
			$datetosearchfor = dol_time_plus_duree(dol_mktime(0, 0, 0, $tmp['mon'], $tmp['mday'], $tmp['year']), $daysbeforeend, 'd');
2923
2924
			$sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'adherent';
2925
			$sql .= " WHERE entity = ".$conf->entity; // Do not use getEntity('adherent').")" here, we want the batch to be on its entity only;
2926
			$sql .= " AND datefin = '".$this->db->idate($datetosearchfor)."'";
2927
2928
			$resql = $this->db->query($sql);
2929
			if ($resql) {
2930
				$num_rows = $this->db->num_rows($resql);
2931
2932
				include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
2933
				$adherent = new Adherent($this->db);
2934
				$formmail = new FormMail($this->db);
2935
2936
				$i = 0;
2937
				while ($i < $num_rows) {
2938
					$obj = $this->db->fetch_object($resql);
2939
2940
					$adherent->fetch($obj->rowid, '', '', '', true, true);
2941
2942
					if (empty($adherent->email)) {
2943
						$nbko++;
2944
						$listofmembersko[$adherent->id] = $adherent->id;
2945
					} else {
2946
						$adherent->fetch_thirdparty();
2947
2948
						// 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.
2949
						$languagefromcountrycode = getLanguageCodeFromCountryCode($adherent->country_code ? $adherent->country_code : $adherent->thirdparty->country_code);
2950
						$languagecodeformember = (empty($adherent->thirdparty->default_lang) ? ($languagefromcountrycode ? $languagefromcountrycode : $mysoc->default_lang) : $adherent->thirdparty->default_lang);
2951
2952
						// Send reminder email
2953
						$outputlangs = new Translate('', $conf);
2954
						$outputlangs->setDefaultLang($languagecodeformember);
2955
						$outputlangs->loadLangs(array("main", "members"));
2956
						dol_syslog("sendReminderForExpiredSubscription Language for member id ".$adherent->id." set to ".$outputlangs->defaultlang." mysoc->default_lang=".$mysoc->default_lang);
2957
2958
						$arraydefaultmessage = null;
2959
						$labeltouse = $conf->global->ADHERENT_EMAIL_TEMPLATE_REMIND_EXPIRATION;
2960
2961
						if (!empty($labeltouse)) {
2962
							$arraydefaultmessage = $formmail->getEMailTemplate($this->db, 'member', $user, $outputlangs, 0, 1, $labeltouse);
2963
						}
2964
2965
						if (!empty($labeltouse) && is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) {
2966
							$substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $adherent);
2967
							//if (is_array($adherent->thirdparty)) $substitutionarraycomp = ...
2968
							complete_substitutions_array($substitutionarray, $outputlangs, $adherent);
2969
2970
							$subject = make_substitutions($arraydefaultmessage->topic, $substitutionarray, $outputlangs);
2971
							$msg = make_substitutions($arraydefaultmessage->content, $substitutionarray, $outputlangs);
2972
							$from = $conf->global->ADHERENT_MAIL_FROM;
2973
							$to = $adherent->email;
2974
2975
							$trackid = 'mem'.$adherent->id;
2976
							$moreinheader = 'X-Dolibarr-Info: sendReminderForExpiredSubscription'."\r\n";
2977
2978
							include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
2979
							$cmail = new CMailFile($subject, $to, $from, $msg, array(), array(), array(), '', '', 0, 1, '', '', $trackid, $moreinheader);
2980
							$result = $cmail->sendfile();
2981
							if (!$result) {
2982
								$error++;
2983
								$this->error = $cmail->error;
2984
								if (!is_null($cmail->errors)) {
2985
									$this->errors += $cmail->errors;
2986
								}
2987
								$nbko++;
2988
								$listofmembersko[$adherent->id] = $adherent->id;
2989
							} else {
2990
								$nbok++;
2991
								$listofmembersok[$adherent->id] = $adherent->id;
2992
2993
								$message = $msg;
2994
								$sendto = $to;
2995
								$sendtocc = '';
2996
								$sendtobcc = '';
2997
								$actioncode = 'EMAIL';
2998
								$extraparams = '';
2999
3000
								$actionmsg = '';
3001
								$actionmsg2 = $langs->transnoentities('MailSentBy').' '.CMailFile::getValidAddress($from, 4, 0, 1).' '.$langs->transnoentities('To').' '.
3002
									CMailFile::getValidAddress($sendto, 4, 0, 1);
3003
								if ($message) {
3004
									$actionmsg = $langs->transnoentities('MailFrom').': '.dol_escape_htmltag($from);
3005
									$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTo').': '.dol_escape_htmltag($sendto));
3006
									if ($sendtocc) {
3007
										$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('Bcc').": ".dol_escape_htmltag($sendtocc));
3008
									}
3009
									$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTopic').": ".$subject);
3010
									$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('TextUsedInTheMessageBody').":");
3011
									$actionmsg = dol_concatdesc($actionmsg, $message);
3012
								}
3013
3014
								require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
3015
3016
								// Insert record of emails sent
3017
								$actioncomm = new ActionComm($this->db);
3018
3019
								$actioncomm->type_code = 'AC_OTH_AUTO'; // Type of event ('AC_OTH', 'AC_OTH_AUTO', 'AC_XXX'...)
3020
								$actioncomm->code = 'AC_'.$actioncode;
3021
								$actioncomm->label = $actionmsg2;
3022
								$actioncomm->note_private = $actionmsg;
3023
								$actioncomm->fk_project = 0;
3024
								$actioncomm->datep = $now;
3025
								$actioncomm->datef = $now;
3026
								$actioncomm->percentage = -1; // Not applicable
3027
								$actioncomm->socid = $adherent->thirdparty->id;
3028
								$actioncomm->contact_id = 0;
3029
								$actioncomm->authorid = $user->id; // User saving action
3030
								$actioncomm->userownerid = $user->id; // Owner of action
3031
								// Fields when action is en email (content should be added into note)
3032
								$actioncomm->email_msgid = $cmail->msgid;
3033
								$actioncomm->email_from = $from;
3034
								$actioncomm->email_sender = '';
3035
								$actioncomm->email_to = $to;
3036
								$actioncomm->email_tocc = $sendtocc;
3037
								$actioncomm->email_tobcc = $sendtobcc;
3038
								$actioncomm->email_subject = $subject;
3039
								$actioncomm->errors_to = '';
3040
3041
								$actioncomm->fk_element = $adherent->id;
3042
								$actioncomm->elementtype = $adherent->element;
3043
3044
								$actioncomm->extraparams = $extraparams;
3045
3046
								$actioncomm->create($user);
3047
							}
3048
						} else {
3049
							$blockingerrormsg = "Can't find email template, defined into member module setup, to use for reminding";
3050
3051
							$nbko++;
3052
							$listofmembersko[$adherent->id] = $adherent->id;
3053
3054
							break;
3055
						}
3056
					}
3057
3058
					$i++;
3059
				}
3060
			} else {
3061
				$this->error = $this->db->lasterror();
3062
				return 1;
3063
			}
3064
		}
3065
3066
		if ($blockingerrormsg) {
3067
			$this->error = $blockingerrormsg;
3068
			return 1;
3069
		} else {
3070
			$this->output = 'Found '.($nbok + $nbko).' members to send reminder to.';
3071
			$this->output .= ' Send email successfuly to '.$nbok.' members';
3072
			if (is_array($listofmembersok)) {
3073
				$listofids = '';
3074
				$i = 0;
3075
				foreach ($listofmembersok as $idmember) {
3076
					if ($i > 100) {
3077
						$listofids .= ', ...';
3078
						break;
3079
					}
3080
					if (empty($listofids)) {
3081
						$listofids .= ' [';
3082
					} else {
3083
						$listofids .= ', ';
3084
					}
3085
					$listofids .= $idmember;
3086
					$i++;
3087
				}
3088
				if ($listofids) {
3089
					$listofids .= ']';
3090
				}
3091
				$this->output .= $listofids;
3092
			}
3093
			if ($nbko) {
3094
				$this->output .= ' - Canceled for '.$nbko.' member (no email or email sending error)';
3095
				if (is_array($listofmembersko)) {
3096
					$listofids = '';
3097
					$i = 0;
3098
					foreach ($listofmembersko as $idmember) {
3099
						if ($i > 100) {
3100
							$listofids .= ', ...';
3101
							break;
3102
						}
3103
						if (empty($listofids)) {
3104
							$listofids .= ' [';
3105
						} else {
3106
							$listofids .= ', ';
3107
						}
3108
						$listofids .= $idmember;
3109
						$i++;
3110
					}
3111
					if ($listofids) {
3112
						$listofids .= ']';
3113
					}
3114
					$this->output .= $listofids;
3115
				}
3116
			}
3117
		}
3118
3119
		return 0;
3120
	}
3121
}
3122