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

Adherent::sendEmail()   B

Complexity

Conditions 6
Paths 24

Size

Total Lines 36
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 21
c 0
b 0
f 0
nc 24
nop 11
dl 0
loc 36
rs 8.9617

How to fix   Many Parameters   

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php
2
/* Copyright (C) 2002-2003	Rodolphe Quiedeville	<[email protected]>
3
 * Copyright (C) 2002-2003	Jean-Louis Bergamo		<[email protected]>
4
 * Copyright (C) 2004-2012	Laurent Destailleur		<[email protected]>
5
 * Copyright (C) 2004		Sebastien Di Cintio		<[email protected]>
6
 * Copyright (C) 2004		Benoit Mortier			<[email protected]>
7
 * Copyright (C) 2009-2017	Regis Houssin			<[email protected]>
8
 * Copyright (C) 2014-2018	Alexandre Spangaro		<[email protected]>
9
 * Copyright (C) 2015		Marcos García			<[email protected]>
10
 * Copyright (C) 2015-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