Passed
Branch develop (2765c7)
by
unknown
99:11
created

Adherent::send_an_email()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 11
dl 0
loc 6
rs 10

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
	 *  Return clicable name (with picto eventually)
2281
	 *
2282
	 *	@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)
2283
	 *	@param	int		$maxlen						length max label
2284
	 *	@param	string	$option						Page for link ('card', 'category', 'subscription', ...)
2285
	 *	@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
2286
	 *	@param  string  $morecss        			Add more css on link
2287
	 *	@param  int		$save_lastsearch_value    	-1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
2288
	 *	@param	int		$notooltip					1=Disable tooltip
2289
	 *	@param  int		$addlinktonotes				1=Add link to notes
2290
	 *	@return	string								Chaine avec URL
2291
	 */
2292
	public function getNomUrl($withpictoimg = 0, $maxlen = 0, $option = 'card', $mode = '', $morecss = '', $save_lastsearch_value = -1, $notooltip = 0, $addlinktonotes = 0)
2293
	{
2294
		global $conf, $langs, $hookmanager;
2295
2296
		if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) && $withpictoimg) {
2297
			$withpictoimg = 0;
2298
		}
2299
2300
		$result = '';
2301
		$label = '';
2302
		$linkstart = '';
2303
		$linkend = '';
2304
2305
		if (!empty($this->photo)) {
2306
			$label .= '<div class="photointooltip floatright">';
2307
			$label .= Form::showphoto('memberphoto', $this, 80, 0, 0, 'photoref photowithmargin photologintooltip', 'small', 0, 1);
2308
			$label .= '</div>';
2309
			//$label .= '<div style="clear: both;"></div>';
2310
		}
2311
2312
		$label .= '<div class="centpercent">';
2313
		$label .= img_picto('', $this->picto).' <u class="paddingrightonly">'.$langs->trans("Member").'</u>';
2314
		$label .= ' '.$this->getLibStatut(4);
2315
		if (!empty($this->ref)) {
2316
			$label .= '<br><b>'.$langs->trans('Ref').':</b> '.$this->ref;
2317
		}
2318
		if (!empty($this->login)) {
2319
			$label .= '<br><b>'.$langs->trans('Login').':</b> '.$this->login;
2320
		}
2321
		if (!empty($this->firstname) || !empty($this->lastname)) {
2322
			$label .= '<br><b>'.$langs->trans('Name').':</b> '.$this->getFullName($langs);
2323
		}
2324
		if (!empty($this->company)) {
2325
			$label .= '<br><b>'.$langs->trans('Company').':</b> '.$this->company;
2326
		}
2327
		$label .= '</div>';
2328
2329
		$url = DOL_URL_ROOT.'/adherents/card.php?rowid='.((int) $this->id);
2330
		if ($option == 'subscription') {
2331
			$url = DOL_URL_ROOT.'/adherents/subscription.php?rowid='.((int) $this->id);
2332
		}
2333
2334
		if ($option != 'nolink') {
2335
			// Add param to save lastsearch_values or not
2336
			$add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
2337
			if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
2338
				$add_save_lastsearch_values = 1;
2339
			}
2340
			if ($add_save_lastsearch_values) {
2341
				$url .= '&save_lastsearch_values=1';
2342
			}
2343
		}
2344
2345
		$linkstart .= '<a href="'.$url.'"';
2346
		$linkclose = "";
2347
		if (empty($notooltip)) {
2348
			if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
2349
				$langs->load("users");
2350
				$label = $langs->trans("ShowUser");
2351
				$linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
2352
			}
2353
			$linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
2354
			$linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
2355
		}
2356
2357
		$linkstart .= $linkclose.'>';
2358
		$linkend = '</a>';
2359
2360
		$result .= $linkstart;
2361
		if ($withpictoimg) {
2362
			$result .= '<div class="inline-block nopadding valignmiddle">';
2363
		}
2364
		if ($withpictoimg) {
2365
			$paddafterimage = '';
2366
			if (abs($withpictoimg) == 1) {
2367
				$paddafterimage = 'style="margin-right: 3px;"';
2368
			}
2369
			// Only picto
2370
			if ($withpictoimg > 0) {
2371
				$picto = '<span class="nopadding'.($morecss ? ' userimg'.$morecss : '').'">'.
2372
					img_object('', 'user', $paddafterimage.' '.($notooltip ? '' : 'class="classfortooltip"'), 0, 0, $notooltip ? 0 : 1).'</span>';
2373
			} else {
2374
				// Picto must be a photo
2375
				$picto = '<span class="nopadding'.($morecss ? ' userimg'.$morecss : '').'"'.($paddafterimage ? ' '.$paddafterimage : '').'>';
2376
				$picto .= Form::showphoto('memberphoto', $this, 0, 0, 0, 'userphoto'.($withpictoimg == -3 ? 'small' : ''), 'mini', 0, 1);
2377
				$picto .= '</span>';
2378
			}
2379
			$result .= $picto;
2380
		}
2381
		if ($withpictoimg > -2 && $withpictoimg != 2) {
2382
			if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
2383
				$result .= '<span class="nopadding valignmiddle'.((!isset($this->statut) || $this->statut) ? '' : ' strikefordisabled').
2384
				($morecss ? ' usertext'.$morecss : '').'">';
2385
			}
2386
			if ($mode == 'login') {
2387
				$result .= dol_trunc($this->login, $maxlen);
2388
			} elseif ($mode == 'ref') {
2389
				$result .= $this->ref;
2390
			} else {
2391
				$result .= $this->getFullName($langs, '', ($mode == 'firstname' ? 2 : ($mode == 'lastname' ? 4 : -1)), $maxlen);
2392
			}
2393
			if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
2394
				$result .= '</span>';
2395
			}
2396
		}
2397
		if ($withpictoimg) {
2398
			$result .= '</div>';
2399
		}
2400
		$result .= $linkend;
2401
2402
		if ($addlinktonotes) {
2403
			if ($this->note_private) {
2404
				$notetoshow = $langs->trans("ViewPrivateNote").':<br>'.dol_string_nohtmltag($this->note_private, 1);
2405
				$result .= ' <span class="note inline-block">';
2406
				$result .= '<a href="'.DOL_URL_ROOT.'/adherents/note.php?id='.$this->id.'" class="classfortooltip" title="'.dol_escape_htmltag($notetoshow).'">';
2407
				$result .= img_picto('', 'note');
2408
				$result .= '</a>';
2409
				$result .= '</span>';
2410
			}
2411
		}
2412
		global $action;
2413
		$hookmanager->initHooks(array($this->element . 'dao'));
2414
		$parameters = array('id'=>$this->id, 'getnomurl' => &$result);
2415
		$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
2416
		if ($reshook > 0) {
2417
			$result = $hookmanager->resPrint;
2418
		} else {
2419
			$result .= $hookmanager->resPrint;
2420
		}
2421
		return $result;
2422
	}
2423
2424
	/**
2425
	 *  Retourne le libelle du statut d'un adherent (brouillon, valide, resilie, exclu)
2426
	 *
2427
	 *  @param	int		$mode       0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
2428
	 *  @return string				Label
2429
	 */
2430
	public function getLibStatut($mode = 0)
2431
	{
2432
		return $this->LibStatut($this->statut, $this->need_subscription, $this->datefin, $mode);
2433
	}
2434
2435
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2436
	/**
2437
	 *  Renvoi le libelle d'un statut donne
2438
	 *
2439
	 *  @param	int			$status      			Id status
2440
	 *	@param	int			$need_subscription		1 if member type need subscription, 0 otherwise
2441
	 *	@param	int     	$date_end_subscription	Date fin adhesion
2442
	 *  @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
2443
	 *  @return string      						Label
2444
	 */
2445
	public function LibStatut($status, $need_subscription, $date_end_subscription, $mode = 0)
2446
	{
2447
		// phpcs:enable
2448
		global $langs;
2449
		$langs->load("members");
2450
2451
		$statusType = '';
2452
		$labelStatus = '';
2453
		$labelStatusShort = '';
2454
2455
		if ($status == self::STATUS_DRAFT) {
2456
			$statusType = 'status0';
2457
			$labelStatus = $langs->trans("MemberStatusDraft");
2458
			$labelStatusShort = $langs->trans("MemberStatusDraftShort");
2459
		} elseif ($status >= self::STATUS_VALIDATED) {
2460
			if ($need_subscription === 0) {
2461
				$statusType = 'status4';
2462
				$labelStatus = $langs->trans("MemberStatusNoSubscription");
2463
				$labelStatusShort = $langs->trans("MemberStatusNoSubscriptionShort");
2464
			} elseif (!$date_end_subscription) {
2465
				$statusType = 'status1';
2466
				$labelStatus = $langs->trans("MemberStatusActive");
2467
				$labelStatusShort = $langs->trans("MemberStatusActiveShort");
2468
			} elseif ($date_end_subscription < dol_now()) {	// expired
2469
				$statusType = 'status8';
2470
				$labelStatus = $langs->trans("MemberStatusActiveLate");
2471
				$labelStatusShort = $langs->trans("MemberStatusActiveLateShort");
2472
			} else {
2473
				$statusType = 'status4';
2474
				$labelStatus = $langs->trans("MemberStatusPaid");
2475
				$labelStatusShort = $langs->trans("MemberStatusPaidShort");
2476
			}
2477
		} elseif ($status == self::STATUS_RESILIATED) {
2478
			$statusType = 'status6';
2479
			$labelStatus = $langs->transnoentitiesnoconv("MemberStatusResiliated");
2480
			$labelStatusShort = $langs->transnoentitiesnoconv("MemberStatusResiliatedShort");
2481
		} elseif ($status == self::STATUS_EXCLUDED) {
2482
			$statusType = 'status10';
2483
			$labelStatus = $langs->transnoentitiesnoconv("MemberStatusExcluded");
2484
			$labelStatusShort = $langs->transnoentitiesnoconv("MemberStatusExcludedShort");
2485
		}
2486
2487
		return dolGetStatus($labelStatus, $labelStatusShort, '', $statusType, $mode);
2488
	}
2489
2490
2491
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2492
	/**
2493
	 *      Charge indicateurs this->nb de tableau de bord
2494
	 *
2495
	 *      @return     int         <0 if KO, >0 if OK
2496
	 */
2497
	public function load_state_board()
2498
	{
2499
		// phpcs:enable
2500
		global $conf;
2501
2502
		$this->nb = array();
2503
2504
		$sql = "SELECT count(a.rowid) as nb";
2505
		$sql .= " FROM ".MAIN_DB_PREFIX."adherent as a";
2506
		$sql .= " WHERE a.statut > 0";
2507
		$sql .= " AND a.entity IN (".getEntity('adherent').")";
2508
2509
		$resql = $this->db->query($sql);
2510
		if ($resql) {
2511
			while ($obj = $this->db->fetch_object($resql)) {
2512
				$this->nb["members"] = $obj->nb;
2513
			}
2514
			$this->db->free($resql);
2515
			return 1;
2516
		} else {
2517
			dol_print_error($this->db);
2518
			$this->error = $this->db->error();
2519
			return -1;
2520
		}
2521
	}
2522
2523
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2524
	/**
2525
	 *      Load indicators for dashboard (this->nbtodo and this->nbtodolate)
2526
	 *
2527
	 *      @param	User	$user   		Objet user
2528
	 *      @param  string	$mode           "expired" for membership to renew, "shift" for member to validate
2529
	 *      @return WorkboardResponse|int 	<0 if KO, WorkboardResponse if OK
2530
	 */
2531
	public function load_board($user, $mode)
2532
	{
2533
		// phpcs:enable
2534
		global $conf, $langs;
2535
2536
		if ($user->socid) {
2537
			return -1; // protection pour eviter appel par utilisateur externe
2538
		}
2539
2540
		$now = dol_now();
2541
2542
		$sql = "SELECT a.rowid, a.datefin, a.statut";
2543
		$sql .= " FROM ".MAIN_DB_PREFIX."adherent as a";
2544
		$sql .= ", ".MAIN_DB_PREFIX."adherent_type as t";
2545
		$sql .= " WHERE a.fk_adherent_type = t.rowid";
2546
		if ($mode == 'expired') {
2547
			$sql .= " AND a.statut = ".self::STATUS_VALIDATED;
2548
			$sql .= " AND a.entity IN (".getEntity('adherent').")";
2549
			$sql .= " AND ((a.datefin IS NULL or a.datefin < '".$this->db->idate($now)."') AND t.subscription = '1')";
2550
		} elseif ($mode == 'shift') {
2551
			$sql .= " AND a.statut = ".self::STATUS_DRAFT;
2552
			$sql .= " AND a.entity IN (".getEntity('adherent').")";
2553
		}
2554
2555
		$resql = $this->db->query($sql);
2556
		if ($resql) {
2557
			$langs->load("members");
2558
2559
			$warning_delay = 0;
2560
			$url = '';
2561
			$label = '';
2562
			$labelShort = '';
2563
2564
			if ($mode == 'expired') {
2565
				$warning_delay = $conf->adherent->subscription->warning_delay / 60 / 60 / 24;
2566
				$label = $langs->trans("MembersWithSubscriptionToReceive");
2567
				$labelShort = $langs->trans("MembersWithSubscriptionToReceiveShort");
2568
				$url = DOL_URL_ROOT.'/adherents/list.php?mainmenu=members&amp;statut='.self::STATUS_VALIDATED.'&amp;filter=outofdate';
2569
			} elseif ($mode == 'shift') {
2570
				$warning_delay = $conf->adherent->subscription->warning_delay / 60 / 60 / 24;
2571
				$url = DOL_URL_ROOT.'/adherents/list.php?mainmenu=members&amp;statut='.self::STATUS_DRAFT;
2572
				$label = $langs->trans("MembersListToValid");
2573
				$labelShort = $langs->trans("ToValidate");
2574
			}
2575
2576
			$response = new WorkboardResponse();
2577
			$response->warning_delay = $warning_delay;
2578
			$response->label = $label;
2579
			$response->labelShort = $labelShort;
2580
			$response->url = $url;
2581
			$response->img = img_object('', "user");
2582
2583
			$adherentstatic = new Adherent($this->db);
2584
2585
			while ($obj = $this->db->fetch_object($resql)) {
2586
				$response->nbtodo++;
2587
2588
				$adherentstatic->datefin = $this->db->jdate($obj->datefin);
2589
				$adherentstatic->statut = $obj->statut;
2590
2591
				if ($adherentstatic->hasDelay()) {
2592
					$response->nbtodolate++;
2593
				}
2594
			}
2595
2596
			return $response;
2597
		} else {
2598
			dol_print_error($this->db);
2599
			$this->error = $this->db->error();
2600
			return -1;
2601
		}
2602
	}
2603
2604
2605
	/**
2606
	 *  Create a document onto disk according to template module.
2607
	 *
2608
	 *  @param	    string		$modele			Force template to use ('' to not force)
2609
	 *  @param		Translate	$outputlangs	objet lang a utiliser pour traduction
2610
	 *  @param      int			$hidedetails    Hide details of lines
2611
	 *  @param      int			$hidedesc       Hide description
2612
	 *  @param      int			$hideref        Hide ref
2613
	 *  @param   null|array  $moreparams     Array to provide more information
2614
	 *  @return     int         				0 if KO, 1 if OK
2615
	 */
2616
	public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
2617
	{
2618
		global $conf, $langs;
2619
2620
		$langs->load("orders");
2621
2622
		if (!dol_strlen($modele)) {
2623
			$modele = 'standard';
2624
2625
			if ($this->model_pdf) {
2626
				$modele = $this->model_pdf;
2627
			} elseif (!empty($conf->global->ADHERENT_ADDON_PDF)) {
2628
				$modele = $conf->global->ADHERENT_ADDON_PDF;
2629
			}
2630
		}
2631
2632
		$modelpath = "core/modules/member/doc/";
2633
2634
		return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
2635
	}
2636
2637
2638
	/**
2639
	 *  Initialise an instance with random values.
2640
	 *  Used to build previews or test instances.
2641
	 *	id must be 0 if object instance is a specimen.
2642
	 *
2643
	 *  @return	int
2644
	 */
2645
	public function initAsSpecimen()
2646
	{
2647
		global $user, $langs;
2648
		$now = dol_now();
2649
2650
		// Initialise parametres
2651
		$this->id = 0;
2652
		$this->ref = 'ABC001';
2653
		$this->entity = 1;
2654
		$this->specimen = 1;
2655
		$this->civility_id = 0;
2656
		$this->lastname = 'DOLIBARR';
2657
		$this->firstname = 'SPECIMEN';
2658
		$this->gender = 'man';
2659
		$this->login = 'dolibspec';
2660
		$this->pass = 'dolibspec';
2661
		$this->company = 'Societe ABC';
2662
		$this->address = '61 jump street';
2663
		$this->zip = '75000';
2664
		$this->town = 'Paris';
2665
		$this->country_id = 1;
2666
		$this->country_code = 'FR';
2667
		$this->country = 'France';
2668
		$this->morphy = 'mor';
2669
		$this->email = '[email protected]';
2670
		$this->socialnetworks = array(
2671
			'skype' => 'skypepseudo',
2672
			'twitter' => 'twitterpseudo',
2673
			'facebook' => 'facebookpseudo',
2674
			'linkedin' => 'linkedinpseudo',
2675
		);
2676
		$this->phone = '0999999999';
2677
		$this->phone_perso = '0999999998';
2678
		$this->phone_mobile = '0999999997';
2679
		$this->note_public = 'This is a public note';
2680
		$this->note_private = 'This is a private note';
2681
		$this->birth = $now;
2682
		$this->photo = '';
2683
		$this->public = 1;
2684
		$this->statut = self::STATUS_DRAFT;
2685
2686
		$this->datefin = $now;
2687
		$this->datevalid = $now;
2688
		$this->default_lang = '';
2689
2690
		$this->typeid = 1; // Id type adherent
2691
		$this->type = 'Type adherent'; // Libelle type adherent
2692
		$this->need_subscription = 0;
2693
2694
		$this->first_subscription_date = $now;
2695
		$this->first_subscription_date_start = $this->first_subscription_date;
2696
		$this->first_subscription_date_end = dol_time_plus_duree($this->first_subscription_date_start, 1, 'y');
2697
		$this->first_subscription_amount = 10;
2698
2699
		$this->last_subscription_date = $this->first_subscription_date;
2700
		$this->last_subscription_date_start = $this->first_subscription_date;
2701
		$this->last_subscription_date_end = dol_time_plus_duree($this->last_subscription_date_start, 1, 'y');
2702
		$this->last_subscription_amount = 10;
2703
		return 1;
2704
	}
2705
2706
2707
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2708
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
2709
	/**
2710
	 *	Retourne chaine DN complete dans l'annuaire LDAP pour l'objet
2711
	 *
2712
	 *	@param	array	$info		Info array loaded by _load_ldap_info
2713
	 *	@param	int		$mode		0=Return full DN (uid=qqq,ou=xxx,dc=aaa,dc=bbb)
2714
	 *								1=Return DN without key inside (ou=xxx,dc=aaa,dc=bbb)
2715
	 *								2=Return key only (uid=qqq)
2716
	 *	@return	string				DN
2717
	 */
2718
	public function _load_ldap_dn($info, $mode = 0)
2719
	{
2720
		// phpcs:enable
2721
		global $conf;
2722
		$dn = '';
2723
		if ($mode == 0) {
2724
			$dn = $conf->global->LDAP_KEY_MEMBERS."=".$info[$conf->global->LDAP_KEY_MEMBERS].",".$conf->global->LDAP_MEMBER_DN;
2725
		}
2726
		if ($mode == 1) {
2727
			$dn = $conf->global->LDAP_MEMBER_DN;
2728
		}
2729
		if ($mode == 2) {
2730
			$dn = $conf->global->LDAP_KEY_MEMBERS."=".$info[$conf->global->LDAP_KEY_MEMBERS];
2731
		}
2732
		return $dn;
2733
	}
2734
2735
2736
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2737
	// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
2738
	/**
2739
	 *	Initialise tableau info (tableau des attributs LDAP)
2740
	 *
2741
	 *	@return		array		Tableau info des attributs
2742
	 */
2743
	public function _load_ldap_info()
2744
	{
2745
		// phpcs:enable
2746
		global $conf, $langs;
2747
2748
		$info = array();
2749
		$socialnetworks = getArrayOfSocialNetworks();
2750
		$keymodified = false;
2751
2752
		// Object classes
2753
		$info["objectclass"] = explode(',', $conf->global->LDAP_MEMBER_OBJECT_CLASS);
2754
2755
		$this->fullname = $this->getFullName($langs);
2756
2757
		// For avoid ldap error when firstname and lastname are empty
2758
		if ($this->morphy == 'mor' && (empty($this->fullname) || $this->fullname == $this->company)) {
2759
			$this->fullname = $this->company;
2760
			$this->lastname = $this->company;
2761
		}
2762
2763
		// Possible LDAP KEY (constname => varname)
2764
		$ldapkey = array(
2765
			'LDAP_MEMBER_FIELD_FULLNAME' => 'fullname',
2766
			'LDAP_MEMBER_FIELD_NAME' => 'lastname',
2767
			'LDAP_MEMBER_FIELD_LOGIN' => 'login',
2768
			'LDAP_MEMBER_FIELD_LOGIN_SAMBA' => 'login',
2769
			'LDAP_MEMBER_FIELD_MAIL' => 'email'
2770
		);
2771
2772
		// Member
2773
		foreach ($ldapkey as $constname => $varname) {
2774
			if (!empty($this->$varname) && !empty($conf->global->$constname)) {
2775
				$info[$conf->global->$constname] = $this->$varname;
2776
2777
				// Check if it is the LDAP key and if its value has been changed
2778
				if (!empty($conf->global->LDAP_KEY_MEMBERS) && $conf->global->LDAP_KEY_MEMBERS == $conf->global->$constname) {
2779
					if (!empty($this->oldcopy) && $this->$varname != $this->oldcopy->$varname) {
2780
						$keymodified = true; // For check if LDAP key has been modified
2781
					}
2782
				}
2783
			}
2784
		}
2785
		if ($this->firstname && !empty($conf->global->LDAP_MEMBER_FIELD_FIRSTNAME)) {
2786
			$info[$conf->global->LDAP_MEMBER_FIELD_FIRSTNAME] = $this->firstname;
2787
		}
2788
		if ($this->poste && !empty($conf->global->LDAP_MEMBER_FIELD_TITLE)) {
2789
			$info[$conf->global->LDAP_MEMBER_FIELD_TITLE] = $this->poste;
2790
		}
2791
		if ($this->company && !empty($conf->global->LDAP_MEMBER_FIELD_COMPANY)) {
2792
			$info[$conf->global->LDAP_MEMBER_FIELD_COMPANY] = $this->company;
2793
		}
2794
		if ($this->address && !empty($conf->global->LDAP_MEMBER_FIELD_ADDRESS)) {
2795
			$info[$conf->global->LDAP_MEMBER_FIELD_ADDRESS] = $this->address;
2796
		}
2797
		if ($this->zip && !empty($conf->global->LDAP_MEMBER_FIELD_ZIP)) {
2798
			$info[$conf->global->LDAP_MEMBER_FIELD_ZIP] = $this->zip;
2799
		}
2800
		if ($this->town && !empty($conf->global->LDAP_MEMBER_FIELD_TOWN)) {
2801
			$info[$conf->global->LDAP_MEMBER_FIELD_TOWN] = $this->town;
2802
		}
2803
		if ($this->country_code && !empty($conf->global->LDAP_MEMBER_FIELD_COUNTRY)) {
2804
			$info[$conf->global->LDAP_MEMBER_FIELD_COUNTRY] = $this->country_code;
2805
		}
2806
		foreach ($socialnetworks as $key => $value) {
2807
			if ($this->socialnetworks[$value['label']] && !empty($conf->global->{'LDAP_MEMBER_FIELD_'.strtoupper($value['label'])})) {
2808
				$info[$conf->global->{'LDAP_MEMBER_FIELD_'.strtoupper($value['label'])}] = $this->socialnetworks[$value['label']];
2809
			}
2810
		}
2811
		if ($this->phone && !empty($conf->global->LDAP_MEMBER_FIELD_PHONE)) {
2812
			$info[$conf->global->LDAP_MEMBER_FIELD_PHONE] = $this->phone;
2813
		}
2814
		if ($this->phone_perso && !empty($conf->global->LDAP_MEMBER_FIELD_PHONE_PERSO)) {
2815
			$info[$conf->global->LDAP_MEMBER_FIELD_PHONE_PERSO] = $this->phone_perso;
2816
		}
2817
		if ($this->phone_mobile && !empty($conf->global->LDAP_MEMBER_FIELD_MOBILE)) {
2818
			$info[$conf->global->LDAP_MEMBER_FIELD_MOBILE] = $this->phone_mobile;
2819
		}
2820
		if ($this->fax && !empty($conf->global->LDAP_MEMBER_FIELD_FAX)) {
2821
			$info[$conf->global->LDAP_MEMBER_FIELD_FAX] = $this->fax;
2822
		}
2823
		if ($this->note_private && !empty($conf->global->LDAP_MEMBER_FIELD_DESCRIPTION)) {
2824
			$info[$conf->global->LDAP_MEMBER_FIELD_DESCRIPTION] = dol_string_nohtmltag($this->note_private, 2);
2825
		}
2826
		if ($this->note_public && !empty($conf->global->LDAP_MEMBER_FIELD_NOTE_PUBLIC)) {
2827
			$info[$conf->global->LDAP_MEMBER_FIELD_NOTE_PUBLIC] = dol_string_nohtmltag($this->note_public, 2);
2828
		}
2829
		if ($this->birth && !empty($conf->global->LDAP_MEMBER_FIELD_BIRTHDATE)) {
2830
			$info[$conf->global->LDAP_MEMBER_FIELD_BIRTHDATE] = dol_print_date($this->birth, 'dayhourldap');
2831
		}
2832
		if (isset($this->statut) && !empty($conf->global->LDAP_FIELD_MEMBER_STATUS)) {
2833
			$info[$conf->global->LDAP_FIELD_MEMBER_STATUS] = $this->statut;
2834
		}
2835
		if ($this->datefin && !empty($conf->global->LDAP_FIELD_MEMBER_END_LASTSUBSCRIPTION)) {
2836
			$info[$conf->global->LDAP_FIELD_MEMBER_END_LASTSUBSCRIPTION] = dol_print_date($this->datefin, 'dayhourldap');
2837
		}
2838
2839
		// When password is modified
2840
		if (!empty($this->pass)) {
2841
			if (!empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD)) {
2842
				$info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD] = $this->pass; // this->pass = mot de passe non crypte
2843
			}
2844
			if (!empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED)) {
2845
				$info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED] = dol_hash($this->pass, 'openldap'); // Create OpenLDAP password (see LDAP_PASSWORD_HASH_TYPE)
2846
			}
2847
		} elseif ($conf->global->LDAP_SERVER_PROTOCOLVERSION !== '3') {
2848
			// Set LDAP password if possible
2849
			// If ldap key is modified and LDAPv3 we use ldap_rename function for avoid lose encrypt password
2850
			if (!empty($conf->global->DATABASE_PWD_ENCRYPTED)) {
2851
				// Just for the default MD5 !
2852
				if (empty($conf->global->MAIN_SECURITY_HASH_ALGO)) {
2853
					if ($this->pass_indatabase_crypted && !empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED)) {
2854
						// Create OpenLDAP MD5 password from Dolibarr MD5 password
2855
						// Note: This suppose that "pass_indatabase_crypted" is a md5 (guaranted by the previous test if "(empty($conf->global->MAIN_SECURITY_HASH_ALGO))"
2856
						$info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED] = dolGetLdapPasswordHash($this->pass_indatabase_crypted, 'md5frommd5');
2857
					}
2858
				}
2859
			} elseif (!empty($this->pass_indatabase)) {
2860
				// Use $this->pass_indatabase value if exists
2861
				if (!empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD)) {
2862
					$info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD] = $this->pass_indatabase; // $this->pass_indatabase = mot de passe non crypte
2863
				}
2864
				if (!empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED)) {
2865
					$info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED] = dol_hash($this->pass_indatabase, 'openldap'); // Create OpenLDAP password (see LDAP_PASSWORD_HASH_TYPE)
2866
				}
2867
			}
2868
		}
2869
2870
		// Subscriptions
2871
		if ($this->first_subscription_date && !empty($conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_DATE)) {
2872
			$info[$conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_DATE] = dol_print_date($this->first_subscription_date, 'dayhourldap');
2873
		}
2874
		if (isset($this->first_subscription_amount) && !empty($conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_AMOUNT)) {
2875
			$info[$conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_AMOUNT] = $this->first_subscription_amount;
2876
		}
2877
		if ($this->last_subscription_date && !empty($conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_DATE)) {
2878
			$info[$conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_DATE] = dol_print_date($this->last_subscription_date, 'dayhourldap');
2879
		}
2880
		if (isset($this->last_subscription_amount) && !empty($conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_AMOUNT)) {
2881
			$info[$conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_AMOUNT] = $this->last_subscription_amount;
2882
		}
2883
2884
		return $info;
2885
	}
2886
2887
2888
	/**
2889
	 *      Load type info information in the member object
2890
	 *
2891
	 *      @param  int		$id       Id of member to load
2892
	 *      @return	void
2893
	 */
2894
	public function info($id)
2895
	{
2896
		$sql = 'SELECT a.rowid, a.datec as datec,';
2897
		$sql .= ' a.datevalid as datev,';
2898
		$sql .= ' a.tms as datem,';
2899
		$sql .= ' a.fk_user_author, a.fk_user_valid, a.fk_user_mod';
2900
		$sql .= ' FROM '.MAIN_DB_PREFIX.'adherent as a';
2901
		$sql .= ' WHERE a.rowid = '.((int) $id);
2902
2903
		dol_syslog(get_class($this)."::info", LOG_DEBUG);
2904
		$result = $this->db->query($sql);
2905
		if ($result) {
2906
			if ($this->db->num_rows($result)) {
2907
				$obj = $this->db->fetch_object($result);
2908
				$this->id = $obj->rowid;
2909
2910
				$this->user_creation_id = $obj->fk_user_author;
2911
				$this->user_validation_id = $obj->fk_user_valid;
2912
				$this->user_modification_id = $obj->fk_user_mod;
2913
				$this->date_creation = $this->db->jdate($obj->datec);
2914
				$this->date_validation = $this->db->jdate($obj->datev);
2915
				$this->date_modification = $this->db->jdate($obj->datem);
2916
			}
2917
2918
			$this->db->free($result);
2919
		} else {
2920
			dol_print_error($this->db);
2921
		}
2922
	}
2923
2924
	/**
2925
	 *  Return number of mass Emailing received by this member with its email
2926
	 *
2927
	 *  @return       int     Number of EMailings
2928
	 */
2929
	public function getNbOfEMailings()
2930
	{
2931
		$sql = "SELECT count(mc.email) as nb";
2932
		$sql .= " FROM ".MAIN_DB_PREFIX."mailing_cibles as mc";
2933
		$sql .= " WHERE mc.email = '".$this->db->escape($this->email)."'";
2934
		$sql .= " AND mc.statut NOT IN (-1,0)"; // -1 erreur, 0 non envoye, 1 envoye avec succes
2935
2936
		$resql = $this->db->query($sql);
2937
		if ($resql) {
2938
			$obj = $this->db->fetch_object($resql);
2939
			$nb = $obj->nb;
2940
2941
			$this->db->free($resql);
2942
			return $nb;
2943
		} else {
2944
			$this->error = $this->db->error();
2945
			return -1;
2946
		}
2947
	}
2948
2949
	/**
2950
	 * Sets object to supplied categories.
2951
	 *
2952
	 * Deletes object from existing categories not supplied.
2953
	 * Adds it to non existing supplied categories.
2954
	 * Existing categories are left untouch.
2955
	 *
2956
	 * @param 	int[]|int 	$categories 	Category or categories IDs
2957
	 * @return 	int							<0 if KO, >0 if OK
2958
	 */
2959
	public function setCategories($categories)
2960
	{
2961
		require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
2962
		return parent::setCategoriesCommon($categories, Categorie::TYPE_MEMBER);
2963
	}
2964
2965
	/**
2966
	 * Function used to replace a thirdparty id with another one.
2967
	 *
2968
	 * @param DoliDB 	$db 			Database handler
2969
	 * @param int 		$origin_id 		Old thirdparty id
2970
	 * @param int 		$dest_id 		New thirdparty id
2971
	 * @return bool
2972
	 */
2973
	public static function replaceThirdparty($db, $origin_id, $dest_id)
2974
	{
2975
		$tables = array('adherent');
2976
2977
		return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
2978
	}
2979
2980
	/**
2981
	 * Return if a member is late (subscription late) or not
2982
	 *
2983
	 * @return boolean     True if late, False if not late
2984
	 */
2985
	public function hasDelay()
2986
	{
2987
		global $conf;
2988
2989
		//Only valid members
2990
		if ($this->statut != self::STATUS_VALIDATED) {
2991
			return false;
2992
		}
2993
		if (!$this->datefin) {
2994
			return false;
2995
		}
2996
2997
		$now = dol_now();
2998
2999
		return $this->datefin < ($now - $conf->adherent->subscription->warning_delay);
3000
	}
3001
3002
3003
	/**
3004
	 * Send reminders by emails before subscription end
3005
	 * CAN BE A CRON TASK
3006
	 *
3007
	 * @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'
3008
	 * @return	int									0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK)
3009
	 */
3010
	public function sendReminderForExpiredSubscription($daysbeforeendlist = '10')
3011
	{
3012
		global $conf, $langs, $mysoc, $user;
3013
3014
		$error = 0;
3015
		$this->output = '';
3016
		$this->error = '';
3017
3018
		$blockingerrormsg = '';
3019
3020
		if (empty($conf->adherent->enabled)) { // Should not happen. If module disabled, cron job should not be visible.
3021
			$langs->load("agenda");
3022
			$this->output = $langs->trans('ModuleNotEnabled', $langs->transnoentitiesnoconv("Adherent"));
3023
			return 0;
3024
		}
3025
		if (empty($conf->global->MEMBER_REMINDER_EMAIL)) {
3026
			$langs->load("agenda");
3027
			$this->output = $langs->trans('EventRemindersByEmailNotEnabled', $langs->transnoentitiesnoconv("Adherent"));
3028
			return 0;
3029
		}
3030
3031
		$now = dol_now();
3032
		$nbok = 0;
3033
		$nbko = 0;
3034
3035
		$listofmembersok = array();
3036
		$listofmembersko = array();
3037
3038
		$arraydaysbeforeend = explode(';', $daysbeforeendlist);
3039
		foreach ($arraydaysbeforeend as $daysbeforeend) { // Loop on each delay
3040
			dol_syslog(__METHOD__.' - Process delta = '.$daysbeforeend, LOG_DEBUG);
3041
3042
			if (!is_numeric($daysbeforeend)) {
3043
				$blockingerrormsg = "Value for delta is not a numeric value";
3044
				$nbko++;
3045
				break;
3046
			}
3047
3048
			$tmp = dol_getdate($now);
3049
			$datetosearchfor = dol_time_plus_duree(dol_mktime(0, 0, 0, $tmp['mon'], $tmp['mday'], $tmp['year'], 'tzserver'), $daysbeforeend, 'd');
3050
3051
			$sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'adherent';
3052
			$sql .= " WHERE entity = ".((int) $conf->entity); // Do not use getEntity('adherent').")" here, we want the batch to be on its entity only;
3053
			$sql .= " AND datefin = '".$this->db->idate($datetosearchfor)."'";
3054
			//$sql .= " LIMIT 10000";
3055
3056
			$resql = $this->db->query($sql);
3057
			if ($resql) {
3058
				$num_rows = $this->db->num_rows($resql);
3059
3060
				include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
3061
				$adherent = new Adherent($this->db);
3062
				$formmail = new FormMail($this->db);
3063
3064
				$i = 0;
3065
				while ($i < $num_rows) {
3066
					$obj = $this->db->fetch_object($resql);
3067
3068
					$adherent->fetch($obj->rowid, '', '', '', true, true);
3069
3070
					if (empty($adherent->email)) {
3071
						$nbko++;
3072
						$listofmembersko[$adherent->id] = $adherent->id;
3073
					} else {
3074
						$adherent->fetch_thirdparty();
3075
3076
						// 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.
3077
						$languagefromcountrycode = getLanguageCodeFromCountryCode($adherent->country_code ? $adherent->country_code : $adherent->thirdparty->country_code);
3078
						$languagecodeformember = (empty($adherent->thirdparty->default_lang) ? ($languagefromcountrycode ? $languagefromcountrycode : $mysoc->default_lang) : $adherent->thirdparty->default_lang);
3079
3080
						// Send reminder email
3081
						$outputlangs = new Translate('', $conf);
3082
						$outputlangs->setDefaultLang($languagecodeformember);
3083
						$outputlangs->loadLangs(array("main", "members"));
3084
						dol_syslog("sendReminderForExpiredSubscription Language for member id ".$adherent->id." set to ".$outputlangs->defaultlang." mysoc->default_lang=".$mysoc->default_lang);
3085
3086
						$arraydefaultmessage = null;
3087
						$labeltouse = getDolGlobalString('ADHERENT_EMAIL_TEMPLATE_REMIND_EXPIRATION');
3088
3089
						if (!empty($labeltouse)) {
3090
							$arraydefaultmessage = $formmail->getEMailTemplate($this->db, 'member', $user, $outputlangs, 0, 1, $labeltouse);
3091
						}
3092
3093
						if (!empty($labeltouse) && is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) {
3094
							$substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $adherent);
3095
							//if (is_array($adherent->thirdparty)) $substitutionarraycomp = ...
3096
							complete_substitutions_array($substitutionarray, $outputlangs, $adherent);
3097
3098
							$subject = make_substitutions($arraydefaultmessage->topic, $substitutionarray, $outputlangs);
3099
							$msg = make_substitutions($arraydefaultmessage->content, $substitutionarray, $outputlangs);
3100
							$from = getDolGlobalString('ADHERENT_MAIL_FROM');
3101
							$to = $adherent->email;
3102
3103
							$trackid = 'mem'.$adherent->id;
3104
							$moreinheader = 'X-Dolibarr-Info: sendReminderForExpiredSubscription'."\r\n";
3105
3106
							include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
3107
							$cmail = new CMailFile($subject, $to, $from, $msg, array(), array(), array(), '', '', 0, 1, '', '', $trackid, $moreinheader);
3108
							$result = $cmail->sendfile();
3109
							if (!$result) {
3110
								$error++;
3111
								$this->error .= $cmail->error.' ';
3112
								if (!is_null($cmail->errors)) {
3113
									$this->errors += $cmail->errors;
3114
								}
3115
								$nbko++;
3116
								$listofmembersko[$adherent->id] = $adherent->id;
3117
							} else {
3118
								$nbok++;
3119
								$listofmembersok[$adherent->id] = $adherent->id;
3120
3121
								$message = $msg;
3122
								$sendto = $to;
3123
								$sendtocc = '';
3124
								$sendtobcc = '';
3125
								$actioncode = 'EMAIL';
3126
								$extraparams = '';
3127
3128
								$actionmsg = '';
3129
								$actionmsg2 = $langs->transnoentities('MailSentBy').' '.CMailFile::getValidAddress($from, 4, 0, 1).' '.$langs->transnoentities('To').' '.CMailFile::getValidAddress($sendto, 4, 0, 1);
3130
								if ($message) {
3131
									$actionmsg = $langs->transnoentities('MailFrom').': '.dol_escape_htmltag($from);
3132
									$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTo').': '.dol_escape_htmltag($sendto));
3133
									if ($sendtocc) {
3134
										$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('Bcc').": ".dol_escape_htmltag($sendtocc));
3135
									}
3136
									$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('MailTopic').": ".$subject);
3137
									$actionmsg = dol_concatdesc($actionmsg, $langs->transnoentities('TextUsedInTheMessageBody').":");
3138
									$actionmsg = dol_concatdesc($actionmsg, $message);
3139
								}
3140
3141
								require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
3142
3143
								// Insert record of emails sent
3144
								$actioncomm = new ActionComm($this->db);
3145
3146
								$actioncomm->type_code = 'AC_OTH_AUTO'; // Type of event ('AC_OTH', 'AC_OTH_AUTO', 'AC_XXX'...)
3147
								$actioncomm->code = 'AC_'.$actioncode;
3148
								$actioncomm->label = $actionmsg2;
3149
								$actioncomm->note_private = $actionmsg;
3150
								$actioncomm->fk_project = 0;
3151
								$actioncomm->datep = $now;
3152
								$actioncomm->datef = $now;
3153
								$actioncomm->percentage = -1; // Not applicable
3154
								$actioncomm->socid = $adherent->thirdparty->id;
3155
								$actioncomm->contact_id = 0;
3156
								$actioncomm->authorid = $user->id; // User saving action
3157
								$actioncomm->userownerid = $user->id; // Owner of action
3158
								// Fields when action is en email (content should be added into note)
3159
								$actioncomm->email_msgid = $cmail->msgid;
3160
								$actioncomm->email_from = $from;
3161
								$actioncomm->email_sender = '';
3162
								$actioncomm->email_to = $to;
3163
								$actioncomm->email_tocc = $sendtocc;
3164
								$actioncomm->email_tobcc = $sendtobcc;
3165
								$actioncomm->email_subject = $subject;
3166
								$actioncomm->errors_to = '';
3167
3168
								$actioncomm->fk_element = $adherent->id;
3169
								$actioncomm->elementtype = $adherent->element;
3170
3171
								$actioncomm->extraparams = $extraparams;
3172
3173
								$actioncomm->create($user);
3174
							}
3175
						} else {
3176
							//$blockingerrormsg = "Can't find email template with label=".$labeltouse.", to use for the reminding email";
3177
3178
							$error++;
3179
							$this->error .= "Can't find email template with label=".$labeltouse.", to use for the reminding email ";
3180
3181
							$nbko++;
3182
							$listofmembersko[$adherent->id] = $adherent->id;
3183
3184
							break;
3185
						}
3186
					}
3187
3188
					$i++;
3189
				}
3190
			} else {
3191
				$this->error = $this->db->lasterror();
3192
				return 1;
3193
			}
3194
		}
3195
3196
		if ($blockingerrormsg) {
3197
			$this->error = $blockingerrormsg;
3198
			return 1;
3199
		} else {
3200
			$this->output = 'Found '.($nbok + $nbko).' members to send reminder to.';
3201
			$this->output .= ' Send email successfuly to '.$nbok.' members';
3202
			if (is_array($listofmembersok)) {
3203
				$listofids = '';
3204
				$i = 0;
3205
				foreach ($listofmembersok as $idmember) {
3206
					if ($i > 100) {
3207
						$listofids .= ', ...';
3208
						break;
3209
					}
3210
					if (empty($listofids)) {
3211
						$listofids .= ' [';
3212
					} else {
3213
						$listofids .= ', ';
3214
					}
3215
					$listofids .= $idmember;
3216
					$i++;
3217
				}
3218
				if ($listofids) {
3219
					$listofids .= ']';
3220
				}
3221
3222
				$this->output .= ($listofids ? ' ids='.$listofids : '');
3223
			}
3224
			if ($nbko) {
3225
				$this->output .= ' - Canceled for '.$nbko.' member (no email or email sending error)';
3226
				if (is_array($listofmembersko)) {
3227
					$listofids = '';
3228
					$i = 0;
3229
					foreach ($listofmembersko as $idmember) {
3230
						if ($i > 100) {
3231
							$listofids .= ', ...';
3232
							break;
3233
						}
3234
						if (empty($listofids)) {
3235
							$listofids .= ' [';
3236
						} else {
3237
							$listofids .= ', ';
3238
						}
3239
						$listofids .= $idmember;
3240
						$i++;
3241
					}
3242
					if ($listofids) {
3243
						$listofids .= ']';
3244
					}
3245
					$this->output .= ($listofids ? ' ids='.$listofids : '');
3246
				}
3247
			}
3248
		}
3249
3250
		return $nbko;
3251
	}
3252
3253
		/**
3254
	 *	Return clicable link of object (with eventually picto)
3255
	 *
3256
	 *	@param      string	    $option                 Where point the link (0=> main card, 1,2 => shipment, 'nolink'=>No link)
3257
	 *  @param		array		$arraydata				Array of data
3258
	 *  @return		string								HTML Code for Kanban thumb.
3259
	 */
3260
	public function getKanbanView($option = '', $arraydata = null)
3261
	{
3262
3263
		$return = '<div class="box-flex-item box-flex-grow-zero">';
3264
		$return .= '<div class="info-box info-box-sm">';
3265
		$return .= '<span class="info-box-icon bg-infobox-action">';
3266
3267
		if (property_exists($this, 'photo') || !empty($this->photo)) {
3268
			$return.= Form::showphoto('memberphoto', $this, 0, 60, 0, 'photokanban photoref photowithmargin photologintooltip', 'small', 0, 1);
3269
		} else {
3270
			$return .= img_picto('', 'user');
3271
		}
3272
		$return .= '</span>';
3273
		$return .= '<div class="info-box-content">';
3274
		$return .= '<span class="info-box-ref">'.(method_exists($this, 'getNomUrl') ? $this->getNomUrl() : $this->ref).'</span>';
3275
		if (property_exists($this, 'type')) {
3276
			$return .= '<br><span class="info-box-label opacitymedium">'.$this->type.'</span>';
3277
		}
3278
		if (method_exists($this, 'getmorphylib')) {
3279
			$return .= '<br><span class="info-box-label">'.$this->getmorphylib('', 2).'</span>';
3280
		}
3281
		if (method_exists($this, 'getLibStatut')) {
3282
			$return .= '<br><div class="info-box-status margintoponly">'.$this->getLibStatut(5).'</div>';
3283
		}
3284
		$return .= '</div>';
3285
		$return .= '</div>';
3286
		$return .= '</div>';
3287
		return $return;
3288
	}
3289
}
3290