Passed
Branch develop (b13600)
by
unknown
108:30
created

Adherent::_load_ldap_info()   D

Complexity

Conditions 65

Size

Total Lines 142
Code Lines 80

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 65
eloc 80
nop 0
dl 0
loc 142
rs 4.1666
c 0
b 0
f 0

How to fix   Long Method    Complexity   

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:

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