adherent.class.php 85 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690
  1. <?php
  2. /* Copyright (C) 2002-2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (C) 2002-2003 Jean-Louis Bergamo <jlb@j1b.org>
  4. * Copyright (C) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net>
  5. * Copyright (C) 2004 Sebastien Di Cintio <sdicintio@ressource-toi.org>
  6. * Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
  7. * Copyright (C) 2009-2017 Regis Houssin <regis.houssin@capnetworks.com>
  8. * Copyright (C) 2014-2016 Alexandre Spangaro <aspangaro.dolibarr@gmail.com>
  9. * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
  10. * Copyright (C) 2015 Frederic France <frederic.france@free.fr>
  11. * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
  12. * Copyright (C) 2016 Juanjo Menent <jmenent@2byte.es>
  13. *
  14. * This program is free software; you can redistribute it and/or modify
  15. * it under the terms of the GNU General Public License as published by
  16. * the Free Software Foundation; either version 3 of the License, or
  17. * (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  26. */
  27. /**
  28. * \file htdocs/adherents/class/adherent.class.php
  29. * \ingroup member
  30. * \brief File of class to manage members of a foundation
  31. */
  32. require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
  33. require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
  34. require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
  35. /**
  36. * Class to manage members of a foundation
  37. */
  38. class Adherent extends CommonObject
  39. {
  40. /**
  41. * @var string ID to identify managed object
  42. */
  43. public $element='member';
  44. /**
  45. * @var string Name of table without prefix where object is stored
  46. */
  47. public $table_element='adherent';
  48. public $ismultientitymanaged = 1; // 0=No test on entity, 1=Test with field entity, 2=Test with link by societe
  49. public $mesgs;
  50. public $login;
  51. //! Clear password in memory
  52. public $pass;
  53. //! Clear password in database (defined if DATABASE_PWD_ENCRYPTED=0)
  54. public $pass_indatabase;
  55. //! Encrypted password in database (always defined)
  56. public $pass_indatabase_crypted;
  57. public $societe;
  58. public $company;
  59. public $address;
  60. public $zip;
  61. public $town;
  62. public $state_id; // Id of department
  63. public $state_code; // Code of department
  64. public $state; // Label of department
  65. public $email;
  66. public $skype;
  67. public $phone;
  68. public $phone_perso;
  69. public $phone_mobile;
  70. public $morphy;
  71. public $public;
  72. public $statut; // -1:brouillon, 0:resilie, >=1:valide,paye
  73. public $photo;
  74. public $datec;
  75. public $datem;
  76. public $datefin;
  77. public $datevalid;
  78. public $birth;
  79. public $note_public;
  80. public $note_private;
  81. public $typeid; // Id type adherent
  82. public $type; // Libelle type adherent
  83. public $need_subscription;
  84. public $user_id;
  85. public $user_login;
  86. /**
  87. * @var int Thirdparty ID
  88. */
  89. public $fk_soc;
  90. // Fields loaded by fetch_subscriptions()
  91. public $first_subscription_date;
  92. public $first_subscription_amount;
  93. public $last_subscription_date;
  94. public $last_subscription_date_start;
  95. public $last_subscription_date_end;
  96. public $last_subscription_amount;
  97. public $subscriptions=array();
  98. public $oldcopy; // To contains a clone of this when we need to save old properties of object
  99. /**
  100. * @var int Entity
  101. */
  102. public $entity;
  103. /**
  104. * Constructor
  105. *
  106. * @param DoliDB $db Database handler
  107. */
  108. function __construct($db)
  109. {
  110. $this->db = $db;
  111. $this->statut = -1;
  112. // l'adherent n'est pas public par defaut
  113. $this->public = 0;
  114. // les champs optionnels sont vides
  115. $this->array_options=array();
  116. }
  117. /**
  118. * Function sending an email has the adherent with the text supplied in parameter.
  119. *
  120. * @param string $text Content of message (not html entities encoded)
  121. * @param string $subject Subject of message
  122. * @param array $filename_list Array of attached files
  123. * @param array $mimetype_list Array of mime types of attached files
  124. * @param array $mimefilename_list Array of public names of attached files
  125. * @param string $addr_cc Email cc
  126. * @param string $addr_bcc Email bcc
  127. * @param int $deliveryreceipt Ask a delivery receipt
  128. * @param int $msgishtml 1=String IS already html, 0=String IS NOT html, -1=Unknown need autodetection
  129. * @param string $errors_to erros to
  130. * @return int <0 if KO, >0 if OK
  131. */
  132. // phpcs:ignore PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  133. 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='')
  134. {
  135. global $conf,$langs;
  136. // Detect if message is HTML
  137. if ($msgishtml == -1)
  138. {
  139. $msgishtml = 0;
  140. if (dol_textishtml($text,0)) $msgishtml = 1;
  141. }
  142. dol_syslog('send_an_email msgishtml='.$msgishtml);
  143. $texttosend=$this->makeSubstitution($text);
  144. $subjecttosend=$this->makeSubstitution($subject);
  145. if ($msgishtml) $texttosend=dol_htmlentitiesbr($texttosend);
  146. // Envoi mail confirmation
  147. $from=$conf->email_from;
  148. if (! empty($conf->global->ADHERENT_MAIL_FROM)) $from=$conf->global->ADHERENT_MAIL_FROM;
  149. // Send email (substitutionarray must be done just before this)
  150. include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
  151. $mailfile = new CMailFile($subjecttosend, $this->email, $from, $texttosend, $filename_list, $mimetype_list, $mimefilename_list, $addr_cc, $addr_bcc, $deliveryreceipt, $msgishtml);
  152. if ($mailfile->sendfile())
  153. {
  154. return 1;
  155. }
  156. else
  157. {
  158. $this->error=$langs->trans("ErrorFailedToSendMail",$from,$this->email).'. '.$mailfile->error;
  159. return -1;
  160. }
  161. }
  162. /**
  163. * Make substitution of tags into text with value of current object.
  164. *
  165. * @param string $text Text to make substitution to
  166. * @return string Value of input text string with substitutions done
  167. */
  168. function makeSubstitution($text)
  169. {
  170. global $conf,$langs;
  171. $birthday = dol_print_date($this->birth,'day');
  172. $msgishtml = 0;
  173. if (dol_textishtml($text,1)) $msgishtml = 1;
  174. $infos='';
  175. if ($this->civility_id) $infos.= $langs->transnoentities("UserTitle").": ".$this->getCivilityLabel()."\n";
  176. $infos.= $langs->transnoentities("id").": ".$this->id."\n";
  177. $infos.= $langs->transnoentities("Lastname").": ".$this->lastname."\n";
  178. $infos.= $langs->transnoentities("Firstname").": ".$this->firstname."\n";
  179. $infos.= $langs->transnoentities("Company").": ".$this->societe."\n";
  180. $infos.= $langs->transnoentities("Address").": ".$this->address."\n";
  181. $infos.= $langs->transnoentities("Zip").": ".$this->zip."\n";
  182. $infos.= $langs->transnoentities("Town").": ".$this->town."\n";
  183. $infos.= $langs->transnoentities("Country").": ".$this->country."\n";
  184. $infos.= $langs->transnoentities("EMail").": ".$this->email."\n";
  185. $infos.= $langs->transnoentities("PhonePro").": ".$this->phone."\n";
  186. $infos.= $langs->transnoentities("PhonePerso").": ".$this->phone_perso."\n";
  187. $infos.= $langs->transnoentities("PhoneMobile").": ".$this->phone_mobile."\n";
  188. if (empty($conf->global->ADHERENT_LOGIN_NOT_REQUIRED))
  189. {
  190. $infos.= $langs->transnoentities("Login").": ".$this->login."\n";
  191. $infos.= $langs->transnoentities("Password").": ".$this->pass."\n";
  192. }
  193. $infos.= $langs->transnoentities("Birthday").": ".$birthday."\n";
  194. $infos.= $langs->transnoentities("Photo").": ".$this->photo."\n";
  195. $infos.= $langs->transnoentities("Public").": ".yn($this->public);
  196. // Substitutions
  197. $substitutionarray=array(
  198. '__CIVILITY__'=>$this->getCivilityLabel(),
  199. '__FIRSTNAME__'=>$msgishtml?dol_htmlentitiesbr($this->firstname):$this->firstname,
  200. '__LASTNAME__'=>$msgishtml?dol_htmlentitiesbr($this->lastname):$this->lastname,
  201. '__FULLNAME__'=>$msgishtml?dol_htmlentitiesbr($this->getFullName($langs)):$this->getFullName($langs),
  202. '__COMPANY__'=>$msgishtml?dol_htmlentitiesbr($this->societe):$this->societe,
  203. '__ADDRESS__'=>$msgishtml?dol_htmlentitiesbr($this->address):$this->address,
  204. '__ZIP__'=>$msgishtml?dol_htmlentitiesbr($this->zip):$this->zip,
  205. '__TOWN__'=>$msgishtml?dol_htmlentitiesbr($this->town):$this->town,
  206. '__COUNTRY__'=>$msgishtml?dol_htmlentitiesbr($this->country):$this->country,
  207. '__EMAIL__'=>$msgishtml?dol_htmlentitiesbr($this->email):$this->email,
  208. '__BIRTH__'=>$msgishtml?dol_htmlentitiesbr($birthday):$birthday,
  209. '__PHOTO__'=>$msgishtml?dol_htmlentitiesbr($this->photo):$this->photo,
  210. '__LOGIN__'=>$msgishtml?dol_htmlentitiesbr($this->login):$this->login,
  211. '__PASSWORD__'=>$msgishtml?dol_htmlentitiesbr($this->pass):$this->pass,
  212. '__PHONE__'=>$msgishtml?dol_htmlentitiesbr($this->phone):$this->phone,
  213. '__PHONEPRO__'=>$msgishtml?dol_htmlentitiesbr($this->phone_perso):$this->phone_perso,
  214. '__PHONEMOBILE__'=>$msgishtml?dol_htmlentitiesbr($this->phone_mobile):$this->phone_mobile,
  215. );
  216. complete_substitutions_array($substitutionarray, $langs, $this);
  217. return make_substitutions($text, $substitutionarray, $langs);
  218. }
  219. /**
  220. * Return translated label by the nature of a adherent (physical or moral)
  221. *
  222. * @param string $morphy Nature of the adherent (physical or moral)
  223. * @return string Label
  224. */
  225. function getmorphylib($morphy='')
  226. {
  227. global $langs;
  228. if (! $morphy) { $morphy=$this->morphy; }
  229. if ($morphy == 'phy') { return $langs->trans("Physical"); }
  230. if ($morphy == 'mor') { return $langs->trans("Moral"); }
  231. return $morphy;
  232. }
  233. /**
  234. * Create a member into database
  235. *
  236. * @param User $user Objet user qui demande la creation
  237. * @param int $notrigger 1 ne declenche pas les triggers, 0 sinon
  238. * @return int <0 if KO, >0 if OK
  239. */
  240. function create($user,$notrigger=0)
  241. {
  242. global $conf,$langs;
  243. $error=0;
  244. $now=dol_now();
  245. // Clean parameters
  246. $this->import_key = trim($this->import_key);
  247. // Check parameters
  248. if (! empty($conf->global->ADHERENT_MAIL_REQUIRED) && ! isValidEMail($this->email))
  249. {
  250. $langs->load("errors");
  251. $this->error = $langs->trans("ErrorBadEMail",$this->email);
  252. return -1;
  253. }
  254. if (! $this->datec) $this->datec=$now;
  255. if (empty($conf->global->ADHERENT_LOGIN_NOT_REQUIRED))
  256. {
  257. if (empty($this->login))
  258. {
  259. $this->error = $langs->trans("ErrorWrongValueForParameterX","Login");
  260. return -1;
  261. }
  262. }
  263. $this->db->begin();
  264. // Insert member
  265. $sql = "INSERT INTO ".MAIN_DB_PREFIX."adherent";
  266. $sql.= " (datec,login,fk_user_author,fk_user_mod,fk_user_valid,morphy,fk_adherent_type,entity,import_key)";
  267. $sql.= " VALUES (";
  268. $sql.= " '".$this->db->idate($this->datec)."'";
  269. $sql.= ", ".($this->login?"'".$this->db->escape($this->login)."'":"null");
  270. $sql.= ", ".($user->id>0?$user->id:"null"); // Can be null because member can be created by a guest or a script
  271. $sql.= ", null, null, '".$this->db->escape($this->morphy)."'";
  272. $sql.= ", ".$this->typeid;
  273. $sql.= ", ".$conf->entity;
  274. $sql.= ", ".(! empty($this->import_key) ? "'".$this->db->escape($this->import_key)."'":"null");
  275. $sql.= ")";
  276. dol_syslog(get_class($this)."::create", LOG_DEBUG);
  277. $result = $this->db->query($sql);
  278. if ($result)
  279. {
  280. $id = $this->db->last_insert_id(MAIN_DB_PREFIX."adherent");
  281. if ($id > 0)
  282. {
  283. $this->id=$id;
  284. $this->ref=(string) $id;
  285. // Update minor fields
  286. $result=$this->update($user,1,1,0,0,'add'); // nosync is 1 to avoid update data of user
  287. if ($result < 0)
  288. {
  289. $this->db->rollback();
  290. return -1;
  291. }
  292. // Add link to user
  293. if ($this->user_id)
  294. {
  295. // Add link to user
  296. $sql = "UPDATE ".MAIN_DB_PREFIX."user SET";
  297. $sql.= " fk_member = ".$this->id;
  298. $sql.= " WHERE rowid = ".$this->user_id;
  299. dol_syslog(get_class($this)."::create", LOG_DEBUG);
  300. $resql = $this->db->query($sql);
  301. if (! $resql)
  302. {
  303. $this->error='Failed to update user to make link with member';
  304. $this->db->rollback();
  305. return -4;
  306. }
  307. }
  308. if (! $notrigger)
  309. {
  310. // Call trigger
  311. $result=$this->call_trigger('MEMBER_CREATE',$user);
  312. if ($result < 0) { $error++; }
  313. // End call triggers
  314. }
  315. if (count($this->errors))
  316. {
  317. dol_syslog(get_class($this)."::create ".implode(',',$this->errors), LOG_ERR);
  318. $this->db->rollback();
  319. return -3;
  320. }
  321. else
  322. {
  323. $this->db->commit();
  324. return $this->id;
  325. }
  326. }
  327. else
  328. {
  329. $this->error='Failed to get last insert id';
  330. dol_syslog(get_class($this)."::create ".$this->error, LOG_ERR);
  331. $this->db->rollback();
  332. return -2;
  333. }
  334. }
  335. else
  336. {
  337. $this->error=$this->db->error();
  338. $this->db->rollback();
  339. return -1;
  340. }
  341. }
  342. /**
  343. * Update a member in database (standard information and password)
  344. *
  345. * @param User $user User making update
  346. * @param int $notrigger 1=disable trigger UPDATE (when called by create)
  347. * @param int $nosyncuser 0=Synchronize linked user (standard info), 1=Do not synchronize linked user
  348. * @param int $nosyncuserpass 0=Synchronize linked user (password), 1=Do not synchronize linked user
  349. * @param int $nosyncthirdparty 0=Synchronize linked thirdparty (standard info), 1=Do not synchronize linked thirdparty
  350. * @param string $action Current action for hookmanager
  351. * @return int <0 if KO, >0 if OK
  352. */
  353. function update($user,$notrigger=0,$nosyncuser=0,$nosyncuserpass=0,$nosyncthirdparty=0,$action='update')
  354. {
  355. global $conf, $langs, $hookmanager;
  356. $nbrowsaffected=0;
  357. $error=0;
  358. dol_syslog(get_class($this)."::update notrigger=".$notrigger.", nosyncuser=".$nosyncuser.", nosyncuserpass=".$nosyncuserpass." nosyncthirdparty=".$nosyncthirdparty.", email=".$this->email);
  359. // Clean parameters
  360. $this->lastname=trim($this->lastname)?trim($this->lastname):trim($this->lastname);
  361. $this->firstname=trim($this->firstname)?trim($this->firstname):trim($this->firstname);
  362. $this->address=($this->address?$this->address:$this->address);
  363. $this->zip=($this->zip?$this->zip:$this->zip);
  364. $this->town=($this->town?$this->town:$this->town);
  365. $this->country_id=($this->country_id > 0?$this->country_id:$this->country_id);
  366. $this->state_id=($this->state_id > 0?$this->state_id:$this->state_id);
  367. if (! empty($conf->global->MAIN_FIRST_TO_UPPER)) $this->lastname=ucwords(trim($this->lastname));
  368. if (! empty($conf->global->MAIN_FIRST_TO_UPPER)) $this->firstname=ucwords(trim($this->firstname));
  369. $this->note_public=($this->note_public?$this->note_public:$this->note_public);
  370. $this->note_private=($this->note_private?$this->note_private:$this->note_private);
  371. // Check parameters
  372. if (! empty($conf->global->ADHERENT_MAIL_REQUIRED) && ! isValidEMail($this->email))
  373. {
  374. $langs->load("errors");
  375. $this->error = $langs->trans("ErrorBadEMail",$this->email);
  376. return -1;
  377. }
  378. $this->db->begin();
  379. $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
  380. $sql.= " civility = ".($this->civility_id?"'".$this->db->escape($this->civility_id)."'":"null");
  381. $sql.= ", firstname = ".($this->firstname?"'".$this->db->escape($this->firstname)."'":"null");
  382. $sql.= ", lastname = ".($this->lastname?"'".$this->db->escape($this->lastname)."'":"null");
  383. $sql.= ", login = ".($this->login?"'".$this->db->escape($this->login)."'":"null");
  384. $sql.= ", societe = ".($this->societe?"'".$this->db->escape($this->societe)."'":"null");
  385. $sql.= ", fk_soc = ".($this->fk_soc > 0?$this->db->escape($this->fk_soc):"null");
  386. $sql.= ", address = ".($this->address?"'".$this->db->escape($this->address)."'":"null");
  387. $sql.= ", zip = ".($this->zip?"'".$this->db->escape($this->zip)."'":"null");
  388. $sql.= ", town = ".($this->town?"'".$this->db->escape($this->town)."'":"null");
  389. $sql.= ", country = ".($this->country_id>0?$this->db->escape($this->country_id):"null");
  390. $sql.= ", state_id = ".($this->state_id>0?$this->db->escape($this->state_id):"null");
  391. $sql.= ", email = '".$this->db->escape($this->email)."'";
  392. $sql.= ", skype = '".$this->db->escape($this->skype)."'";
  393. $sql.= ", phone = ".($this->phone?"'".$this->db->escape($this->phone)."'":"null");
  394. $sql.= ", phone_perso = ".($this->phone_perso?"'".$this->db->escape($this->phone_perso)."'":"null");
  395. $sql.= ", phone_mobile = ".($this->phone_mobile?"'".$this->db->escape($this->phone_mobile)."'":"null");
  396. $sql.= ", note_private = ".($this->note_private?"'".$this->db->escape($this->note_private)."'":"null");
  397. $sql.= ", note_public = ".($this->note_public?"'".$this->db->escape($this->note_public)."'":"null");
  398. $sql.= ", photo = ".($this->photo?"'".$this->db->escape($this->photo)."'":"null");
  399. $sql.= ", public = '".$this->db->escape($this->public)."'";
  400. $sql.= ", statut = ".$this->db->escape($this->statut);
  401. $sql.= ", fk_adherent_type = ".$this->db->escape($this->typeid);
  402. $sql.= ", morphy = '".$this->db->escape($this->morphy)."'";
  403. $sql.= ", birth = ".($this->birth?"'".$this->db->idate($this->birth)."'":"null");
  404. if ($this->datefin) $sql.= ", datefin = '".$this->db->idate($this->datefin)."'"; // Must be modified only when deleting a subscription
  405. if ($this->datevalid) $sql.= ", datevalid = '".$this->db->idate($this->datevalid)."'"; // Must be modified only when validating a member
  406. $sql.= ", fk_user_mod = ".($user->id>0?$user->id:'null'); // Can be null because member can be create by a guest
  407. $sql.= " WHERE rowid = ".$this->id;
  408. dol_syslog(get_class($this)."::update update member", LOG_DEBUG);
  409. $resql = $this->db->query($sql);
  410. if ($resql)
  411. {
  412. unset($this->country_code);
  413. unset($this->country);
  414. unset($this->state_code);
  415. unset($this->state);
  416. $nbrowsaffected+=$this->db->affected_rows($resql);
  417. $action='update';
  418. // Actions on extra fields
  419. if (! $error && empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
  420. {
  421. $result=$this->insertExtraFields();
  422. if ($result < 0)
  423. {
  424. $error++;
  425. }
  426. }
  427. // Update password
  428. if (! $error && $this->pass)
  429. {
  430. dol_syslog(get_class($this)."::update update password");
  431. if ($this->pass != $this->pass_indatabase && $this->pass != $this->pass_indatabase_crypted)
  432. {
  433. $isencrypted = empty($conf->global->DATABASE_PWD_ENCRYPTED)?0:1;
  434. // If password to set differs from the one found into database
  435. $result=$this->setPassword($user,$this->pass,$isencrypted,$notrigger,$nosyncuserpass);
  436. if (! $nbrowsaffected) $nbrowsaffected++;
  437. }
  438. }
  439. // Remove links to user and replace with new one
  440. if (! $error)
  441. {
  442. dol_syslog(get_class($this)."::update update link to user");
  443. $sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = NULL WHERE fk_member = ".$this->id;
  444. dol_syslog(get_class($this)."::update", LOG_DEBUG);
  445. $resql = $this->db->query($sql);
  446. if (! $resql) { $this->error=$this->db->error(); $this->db->rollback(); return -5; }
  447. // If there is a user linked to this member
  448. if ($this->user_id > 0)
  449. {
  450. $sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = ".$this->id." WHERE rowid = ".$this->user_id;
  451. dol_syslog(get_class($this)."::update", LOG_DEBUG);
  452. $resql = $this->db->query($sql);
  453. if (! $resql) { $this->error=$this->db->error(); $this->db->rollback(); return -5; }
  454. }
  455. }
  456. if (! $error && $nbrowsaffected) // If something has change in main data
  457. {
  458. // Update information on linked user if it is an update
  459. if (! $error && $this->user_id > 0 && ! $nosyncuser)
  460. {
  461. require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
  462. dol_syslog(get_class($this)."::update update linked user");
  463. $luser=new User($this->db);
  464. $result=$luser->fetch($this->user_id);
  465. if ($result >= 0)
  466. {
  467. //var_dump($this->user_login);exit;
  468. //var_dump($this->login);exit;
  469. // 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.
  470. if (empty($conf->global->ADHERENT_LOGIN_NOT_REQUIRED)) $luser->login=$this->login;
  471. $luser->civility_id=$this->civility_id;
  472. $luser->firstname=$this->firstname;
  473. $luser->lastname=$this->lastname;
  474. $luser->pass=$this->pass;
  475. $luser->societe_id=$this->societe;
  476. $luser->birth=$this->birth;
  477. $luser->address=$this->address;
  478. $luser->zip=$this->zip;
  479. $luser->town=$this->town;
  480. $luser->country_id=$this->country_id;
  481. $luser->state_id=$this->state_id;
  482. $luser->email=$this->email;
  483. $luser->skype=$this->skype;
  484. $luser->office_phone=$this->phone;
  485. $luser->user_mobile=$this->phone_mobile;
  486. $luser->fk_member=$this->id;
  487. $result=$luser->update($user,0,1,1); // Use nosync to 1 to avoid cyclic updates
  488. if ($result < 0)
  489. {
  490. $this->error=$luser->error;
  491. dol_syslog(get_class($this)."::update ".$this->error,LOG_ERR);
  492. $error++;
  493. }
  494. }
  495. else
  496. {
  497. $this->error=$luser->error;
  498. $error++;
  499. }
  500. }
  501. // Update information on linked thirdparty if it is an update
  502. if (! $error && $this->fk_soc > 0 && ! $nosyncthirdparty)
  503. {
  504. require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
  505. dol_syslog(get_class($this)."::update update linked thirdparty");
  506. // This member is linked with a thirdparty, so we also update thirdparty informations
  507. // if this is an update.
  508. $lthirdparty=new Societe($this->db);
  509. $result=$lthirdparty->fetch($this->fk_soc);
  510. if ($result >= 0)
  511. {
  512. $lthirdparty->address=$this->address;
  513. $lthirdparty->zip=$this->zip;
  514. $lthirdparty->town=$this->town;
  515. $lthirdparty->email=$this->email;
  516. $lthirdparty->skype=$this->skype;
  517. $lthirdparty->phone=$this->phone;
  518. $lthirdparty->state_id=$this->state_id;
  519. $lthirdparty->country_id=$this->country_id;
  520. $lthirdparty->country_id=$this->country_id;
  521. //$lthirdparty->phone_mobile=$this->phone_mobile;
  522. $result=$lthirdparty->update($this->fk_soc,$user,0,1,1,'update'); // Use sync to 0 to avoid cyclic updates
  523. if ($result < 0)
  524. {
  525. $this->error=$lthirdparty->error;
  526. dol_syslog(get_class($this)."::update ".$this->error,LOG_ERR);
  527. $error++;
  528. }
  529. }
  530. else
  531. {
  532. $this->error=$lthirdparty->error;
  533. $error++;
  534. }
  535. }
  536. }
  537. if (! $error && ! $notrigger)
  538. {
  539. // Call trigger
  540. $result=$this->call_trigger('MEMBER_MODIFY',$user);
  541. if ($result < 0) { $error++; }
  542. // End call triggers
  543. }
  544. if (! $error)
  545. {
  546. $this->db->commit();
  547. return $nbrowsaffected;
  548. }
  549. else
  550. {
  551. $this->db->rollback();
  552. return -1;
  553. }
  554. }
  555. else
  556. {
  557. $this->db->rollback();
  558. $this->error=$this->db->lasterror();
  559. return -2;
  560. }
  561. }
  562. /**
  563. * Update denormalized last subscription date.
  564. * This function is called when we delete a subscription for example.
  565. *
  566. * @param User $user User making change
  567. * @return int <0 if KO, >0 if OK
  568. */
  569. // phpcs:ignore PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  570. function update_end_date($user)
  571. {
  572. $this->db->begin();
  573. // Search for last subscription id and end date
  574. $sql = "SELECT rowid, datec as dateop, dateadh as datedeb, datef as datefin";
  575. $sql.= " FROM ".MAIN_DB_PREFIX."subscription";
  576. $sql.= " WHERE fk_adherent=".$this->id;
  577. $sql.= " ORDER by dateadh DESC"; // Sort by start subscription date
  578. dol_syslog(get_class($this)."::update_end_date", LOG_DEBUG);
  579. $resql=$this->db->query($sql);
  580. if ($resql)
  581. {
  582. $obj=$this->db->fetch_object($resql);
  583. $dateop=$this->db->jdate($obj->dateop);
  584. $datedeb=$this->db->jdate($obj->datedeb);
  585. $datefin=$this->db->jdate($obj->datefin);
  586. $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
  587. $sql.= " datefin=".($datefin != '' ? "'".$this->db->idate($datefin)."'" : "null");
  588. $sql.= " WHERE rowid = ".$this->id;
  589. dol_syslog(get_class($this)."::update_end_date", LOG_DEBUG);
  590. $resql=$this->db->query($sql);
  591. if ($resql)
  592. {
  593. $this->last_subscription_date=$dateop;
  594. $this->last_subscription_date_start=$datedeb;
  595. $this->last_subscription_date_end=$datefin;
  596. $this->datefin=$datefin;
  597. $this->db->commit();
  598. return 1;
  599. }
  600. else
  601. {
  602. $this->db->rollback();
  603. return -1;
  604. }
  605. }
  606. else
  607. {
  608. $this->error=$this->db->lasterror();
  609. $this->db->rollback();
  610. return -1;
  611. }
  612. }
  613. /**
  614. * Fonction qui supprime l'adherent et les donnees associees
  615. *
  616. * @param int $rowid Id of member to delete
  617. * @param User $user User object
  618. * @param int $notrigger 1=Does not execute triggers, 0= execute triggers
  619. * @return int <0 if KO, 0=nothing to do, >0 if OK
  620. */
  621. function delete($rowid, $user, $notrigger=0)
  622. {
  623. global $conf, $langs;
  624. $result = 0;
  625. $error=0;
  626. $errorflag=0;
  627. // Check parameters
  628. if (empty($rowid)) $rowid=$this->id;
  629. $this->db->begin();
  630. if (! $error && ! $notrigger)
  631. {
  632. // Call trigger
  633. $result=$this->call_trigger('MEMBER_DELETE',$user);
  634. if ($result < 0) $error++;
  635. // End call triggers
  636. }
  637. // Remove category
  638. $sql = "DELETE FROM ".MAIN_DB_PREFIX."categorie_member WHERE fk_member = ".$rowid;
  639. dol_syslog(get_class($this)."::delete", LOG_DEBUG);
  640. $resql=$this->db->query($sql);
  641. if (! $resql)
  642. {
  643. $error++;
  644. $this->error .= $this->db->lasterror();
  645. $errorflag=-1;
  646. }
  647. // Remove subscription
  648. if (! $error)
  649. {
  650. $sql = "DELETE FROM ".MAIN_DB_PREFIX."subscription WHERE fk_adherent = ".$rowid;
  651. dol_syslog(get_class($this)."::delete", LOG_DEBUG);
  652. $resql=$this->db->query($sql);
  653. if (! $resql)
  654. {
  655. $error++;
  656. $this->error .= $this->db->lasterror();
  657. $errorflag=-2;
  658. }
  659. }
  660. // Remove linked user
  661. if (! $error)
  662. {
  663. $ret=$this->setUserId(0);
  664. if ($ret < 0)
  665. {
  666. $error++;
  667. $this->error .= $this->db->lasterror();
  668. $errorflag=-3;
  669. }
  670. }
  671. // Removed extrafields
  672. if (! $error)
  673. {
  674. if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED)) // For avoid conflicts if trigger used
  675. {
  676. $result=$this->deleteExtraFields();
  677. if ($result < 0)
  678. {
  679. $error++;
  680. $errorflag=-4;
  681. dol_syslog(get_class($this)."::delete erreur ".$errorflag." ".$this->error, LOG_ERR);
  682. }
  683. }
  684. }
  685. // Remove adherent
  686. if (! $error)
  687. {
  688. $sql = "DELETE FROM ".MAIN_DB_PREFIX."adherent WHERE rowid = ".$rowid;
  689. dol_syslog(get_class($this)."::delete", LOG_DEBUG);
  690. $resql=$this->db->query($sql);
  691. if (! $resql)
  692. {
  693. $error++;
  694. $this->error .= $this->db->lasterror();
  695. $errorflag=-5;
  696. }
  697. }
  698. if (! $error)
  699. {
  700. $this->db->commit();
  701. return 1;
  702. }
  703. else
  704. {
  705. $this->db->rollback();
  706. return $errorflag;
  707. }
  708. }
  709. /**
  710. * Change password of a user
  711. *
  712. * @param User $user Object user de l'utilisateur qui fait la modification
  713. * @param string $password New password (to generate if empty)
  714. * @param int $isencrypted 0 ou 1 si il faut crypter le mot de passe en base (0 par defaut)
  715. * @param int $notrigger 1=Ne declenche pas les triggers
  716. * @param int $nosyncuser Do not synchronize linked user
  717. * @return string If OK return clear password, 0 if no change, < 0 if error
  718. */
  719. function setPassword($user, $password='', $isencrypted=0, $notrigger=0, $nosyncuser=0)
  720. {
  721. global $conf, $langs;
  722. $error=0;
  723. dol_syslog(get_class($this)."::setPassword user=".$user->id." password=".preg_replace('/./i','*',$password)." isencrypted=".$isencrypted);
  724. // If new password not provided, we generate one
  725. if (! $password)
  726. {
  727. require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
  728. $password=getRandomPassword(false);
  729. }
  730. // Crypt password
  731. $password_crypted = dol_hash($password);
  732. $password_indatabase = '';
  733. if (! $isencrypted)
  734. {
  735. $password_indatabase = $password;
  736. }
  737. $this->db->begin();
  738. // Mise a jour
  739. $sql = "UPDATE ".MAIN_DB_PREFIX."adherent";
  740. $sql.= " SET pass_crypted = '".$this->db->escape($password_crypted)."'";
  741. //if (! empty($conf->global->DATABASE_PWD_ENCRYPTED))
  742. if ($isencrypted)
  743. {
  744. $sql.= ", pass = null";
  745. }
  746. else
  747. {
  748. $sql.= ", pass = '".$this->db->escape($password_indatabase)."'";
  749. }
  750. $sql.= " WHERE rowid = ".$this->id;
  751. //dol_syslog("Adherent::Password sql=hidden");
  752. dol_syslog(get_class($this)."::setPassword", LOG_DEBUG);
  753. $result = $this->db->query($sql);
  754. if ($result)
  755. {
  756. $nbaffectedrows=$this->db->affected_rows($result);
  757. if ($nbaffectedrows)
  758. {
  759. $this->pass=$password;
  760. $this->pass_indatabase=$password_indatabase;
  761. $this->pass_indatabase_crypted=$password_crypted;
  762. if ($this->user_id && ! $nosyncuser)
  763. {
  764. require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
  765. // This member is linked with a user, so we also update users informations
  766. // if this is an update.
  767. $luser=new User($this->db);
  768. $result=$luser->fetch($this->user_id);
  769. if ($result >= 0)
  770. {
  771. $result=$luser->setPassword($user,$this->pass,0,0,1);
  772. if ($result < 0)
  773. {
  774. $this->error=$luser->error;
  775. dol_syslog(get_class($this)."::setPassword ".$this->error,LOG_ERR);
  776. $error++;
  777. }
  778. }
  779. else
  780. {
  781. $this->error=$luser->error;
  782. $error++;
  783. }
  784. }
  785. if (! $error && ! $notrigger)
  786. {
  787. // Call trigger
  788. $result=$this->call_trigger('MEMBER_NEW_PASSWORD',$user);
  789. if ($result < 0) { $error++; $this->db->rollback(); return -1; }
  790. // End call triggers
  791. }
  792. $this->db->commit();
  793. return $this->pass;
  794. }
  795. else
  796. {
  797. $this->db->rollback();
  798. return 0;
  799. }
  800. }
  801. else
  802. {
  803. $this->db->rollback();
  804. dol_print_error($this->db);
  805. return -1;
  806. }
  807. }
  808. /**
  809. * Set link to a user
  810. *
  811. * @param int $userid Id of user to link to
  812. * @return int 1=OK, -1=KO
  813. */
  814. function setUserId($userid)
  815. {
  816. global $conf, $langs;
  817. $this->db->begin();
  818. // If user is linked to this member, remove old link to this member
  819. $sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = NULL WHERE fk_member = ".$this->id;
  820. dol_syslog(get_class($this)."::setUserId", LOG_DEBUG);
  821. $resql = $this->db->query($sql);
  822. if (! $resql) { $this->error=$this->db->error(); $this->db->rollback(); return -1; }
  823. // Set link to user
  824. if ($userid > 0)
  825. {
  826. $sql = "UPDATE ".MAIN_DB_PREFIX."user SET fk_member = ".$this->id;
  827. $sql.= " WHERE rowid = ".$userid;
  828. dol_syslog(get_class($this)."::setUserId", LOG_DEBUG);
  829. $resql = $this->db->query($sql);
  830. if (! $resql) { $this->error=$this->db->error(); $this->db->rollback(); return -2; }
  831. }
  832. $this->db->commit();
  833. return 1;
  834. }
  835. /**
  836. * Set link to a third party
  837. *
  838. * @param int $thirdpartyid Id of user to link to
  839. * @return int 1=OK, -1=KO
  840. */
  841. function setThirdPartyId($thirdpartyid)
  842. {
  843. global $conf, $langs;
  844. $this->db->begin();
  845. // Remove link to third party onto any other members
  846. if ($thirdpartyid > 0)
  847. {
  848. $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET fk_soc = null";
  849. $sql.= " WHERE fk_soc = '".$thirdpartyid."'";
  850. $sql.= " AND entity = ".$conf->entity;
  851. dol_syslog(get_class($this)."::setThirdPartyId", LOG_DEBUG);
  852. $resql = $this->db->query($sql);
  853. }
  854. // Add link to third party for current member
  855. $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET fk_soc = ".($thirdpartyid>0 ? $thirdpartyid : 'null');
  856. $sql.= " WHERE rowid = ".$this->id;
  857. dol_syslog(get_class($this)."::setThirdPartyId", LOG_DEBUG);
  858. $resql = $this->db->query($sql);
  859. if ($resql)
  860. {
  861. $this->db->commit();
  862. return 1;
  863. }
  864. else
  865. {
  866. $this->error=$this->db->error();
  867. $this->db->rollback();
  868. return -1;
  869. }
  870. }
  871. /**
  872. * Method to load member from its login
  873. *
  874. * @param string $login login of member
  875. * @return void
  876. */
  877. // phpcs:ignore PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  878. function fetch_login($login)
  879. {
  880. global $conf;
  881. $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."adherent";
  882. $sql.= " WHERE login='".$this->db->escape($login)."'";
  883. $sql.= " AND entity = ".$conf->entity;
  884. $resql=$this->db->query($sql);
  885. if ($resql)
  886. {
  887. if ($this->db->num_rows($resql))
  888. {
  889. $obj = $this->db->fetch_object($resql);
  890. $this->fetch($obj->rowid);
  891. }
  892. }
  893. else
  894. {
  895. dol_print_error($this->db);
  896. }
  897. }
  898. /**
  899. * Method to load member from its name
  900. *
  901. * @param string $firstname Firstname
  902. * @param string $lastname Lastname
  903. * @return void
  904. */
  905. // phpcs:ignore PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  906. function fetch_name($firstname,$lastname)
  907. {
  908. global $conf;
  909. $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."adherent";
  910. $sql.= " WHERE firstname='".$this->db->escape($firstname)."'";
  911. $sql.= " AND lastname='".$this->db->escape($lastname)."'";
  912. $sql.= " AND entity = ".$conf->entity;
  913. $resql=$this->db->query($sql);
  914. if ($resql)
  915. {
  916. if ($this->db->num_rows($resql))
  917. {
  918. $obj = $this->db->fetch_object($resql);
  919. $this->fetch($obj->rowid);
  920. }
  921. }
  922. else
  923. {
  924. dol_print_error($this->db);
  925. }
  926. }
  927. /**
  928. * Load member from database
  929. *
  930. * @param int $rowid Id of object to load
  931. * @param string $ref To load member from its ref
  932. * @param int $fk_soc To load member from its link to third party
  933. * @param string $ref_ext External reference
  934. * @param bool $fetch_optionals To load optionals (extrafields)
  935. * @param bool $fetch_subscriptions To load member subscriptions
  936. * @return int >0 if OK, 0 if not found, <0 if KO
  937. */
  938. function fetch($rowid,$ref='',$fk_soc='',$ref_ext='',$fetch_optionals=true,$fetch_subscriptions=true)
  939. {
  940. global $langs;
  941. $sql = "SELECT d.rowid, d.ref_ext, d.civility as civility_id, d.firstname, d.lastname, d.societe as company, d.fk_soc, d.statut, d.public, d.address, d.zip, d.town, d.note_private,";
  942. $sql.= " d.note_public,";
  943. $sql.= " d.email, d.skype, d.phone, d.phone_perso, d.phone_mobile, d.login, d.pass, d.pass_crypted,";
  944. $sql.= " d.photo, d.fk_adherent_type, d.morphy, d.entity,";
  945. $sql.= " d.datec as datec,";
  946. $sql.= " d.tms as datem,";
  947. $sql.= " d.datefin as datefin,";
  948. $sql.= " d.birth as birthday,";
  949. $sql.= " d.datevalid as datev,";
  950. $sql.= " d.country,";
  951. $sql.= " d.state_id,";
  952. $sql.= " d.model_pdf,";
  953. $sql.= " c.rowid as country_id, c.code as country_code, c.label as country,";
  954. $sql.= " dep.nom as state, dep.code_departement as state_code,";
  955. $sql.= " t.libelle as type, t.subscription as subscription,";
  956. $sql.= " u.rowid as user_id, u.login as user_login";
  957. $sql.= " FROM ".MAIN_DB_PREFIX."adherent_type as t, ".MAIN_DB_PREFIX."adherent as d";
  958. $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as c ON d.country = c.rowid";
  959. $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."c_departements as dep ON d.state_id = dep.rowid";
  960. $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."user as u ON d.rowid = u.fk_member";
  961. $sql.= " WHERE d.fk_adherent_type = t.rowid";
  962. if ($rowid) $sql.= " AND d.rowid=".$rowid;
  963. elseif ($ref || $fk_soc) {
  964. $sql.= " AND d.entity IN (".getEntity('adherent').")";
  965. if ($ref) $sql.= " AND d.rowid='".$this->db->escape($ref)."'";
  966. elseif ($fk_soc > 0) $sql.= " AND d.fk_soc=".$fk_soc;
  967. }
  968. elseif ($ref_ext)
  969. {
  970. $sql.= " AND d.ref_ext='".$this->db->escape($ref_ext)."'";
  971. }
  972. dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
  973. $resql=$this->db->query($sql);
  974. if ($resql)
  975. {
  976. if ($this->db->num_rows($resql))
  977. {
  978. $obj = $this->db->fetch_object($resql);
  979. $this->entity = $obj->entity;
  980. $this->ref = $obj->rowid;
  981. $this->id = $obj->rowid;
  982. $this->ref_ext = $obj->ref_ext;
  983. $this->civility_id = $obj->civility_id;
  984. $this->firstname = $obj->firstname;
  985. $this->lastname = $obj->lastname;
  986. $this->login = $obj->login;
  987. $this->societe = $obj->company;
  988. $this->company = $obj->company;
  989. $this->fk_soc = $obj->fk_soc;
  990. $this->address = $obj->address;
  991. $this->zip = $obj->zip;
  992. $this->town = $obj->town;
  993. $this->pass = $obj->pass;
  994. $this->pass_indatabase = $obj->pass;
  995. $this->pass_indatabase_crypted = $obj->pass_crypted;
  996. $this->state_id = $obj->state_id;
  997. $this->state_code = $obj->state_id?$obj->state_code:'';
  998. $this->state = $obj->state_id?$obj->state:'';
  999. $this->country_id = $obj->country_id;
  1000. $this->country_code = $obj->country_code;
  1001. if ($langs->trans("Country".$obj->country_code) != "Country".$obj->country_code)
  1002. $this->country = $langs->transnoentitiesnoconv("Country".$obj->country_code);
  1003. else
  1004. $this->country=$obj->country;
  1005. $this->phone = $obj->phone;
  1006. $this->phone_perso = $obj->phone_perso;
  1007. $this->phone_mobile = $obj->phone_mobile;
  1008. $this->email = $obj->email;
  1009. $this->skype = $obj->skype;
  1010. $this->photo = $obj->photo;
  1011. $this->statut = $obj->statut;
  1012. $this->public = $obj->public;
  1013. $this->datec = $this->db->jdate($obj->datec);
  1014. $this->datem = $this->db->jdate($obj->datem);
  1015. $this->datefin = $this->db->jdate($obj->datefin);
  1016. $this->datevalid = $this->db->jdate($obj->datev);
  1017. $this->birth = $this->db->jdate($obj->birthday);
  1018. $this->note_private = $obj->note_private;
  1019. $this->note_public = $obj->note_public;
  1020. $this->morphy = $obj->morphy;
  1021. $this->typeid = $obj->fk_adherent_type;
  1022. $this->type = $obj->type;
  1023. $this->need_subscription = $obj->subscription;
  1024. $this->user_id = $obj->user_id;
  1025. $this->user_login = $obj->user_login;
  1026. $this->model_pdf = $obj->model_pdf;
  1027. // Retreive all extrafield
  1028. // fetch optionals attributes and labels
  1029. if ($fetch_optionals) {
  1030. $this->fetch_optionals();
  1031. }
  1032. // Load other properties
  1033. if ($fetch_subscriptions) {
  1034. $result=$this->fetch_subscriptions();
  1035. }
  1036. return $this->id;
  1037. }
  1038. else
  1039. {
  1040. return 0;
  1041. }
  1042. }
  1043. else
  1044. {
  1045. $this->error=$this->db->lasterror();
  1046. return -1;
  1047. }
  1048. }
  1049. /**
  1050. * Fonction qui recupere pour un adherent les parametres
  1051. * first_subscription_date
  1052. * first_subscription_amount
  1053. * last_subscription_date
  1054. * last_subscription_amount
  1055. *
  1056. * @return int <0 si KO, >0 si OK
  1057. */
  1058. // phpcs:ignore PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  1059. function fetch_subscriptions()
  1060. {
  1061. global $langs;
  1062. require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
  1063. $sql = "SELECT c.rowid, c.fk_adherent, c.subscription, c.note, c.fk_bank,";
  1064. $sql.= " c.tms as datem,";
  1065. $sql.= " c.datec as datec,";
  1066. $sql.= " c.dateadh as dateh,";
  1067. $sql.= " c.datef as datef";
  1068. $sql.= " FROM ".MAIN_DB_PREFIX."subscription as c";
  1069. $sql.= " WHERE c.fk_adherent = ".$this->id;
  1070. $sql.= " ORDER BY c.dateadh";
  1071. dol_syslog(get_class($this)."::fetch_subscriptions", LOG_DEBUG);
  1072. $resql=$this->db->query($sql);
  1073. if ($resql)
  1074. {
  1075. $this->subscriptions=array();
  1076. $i=0;
  1077. while ($obj = $this->db->fetch_object($resql))
  1078. {
  1079. if ($i==0)
  1080. {
  1081. $this->first_subscription_date=$obj->dateh;
  1082. $this->first_subscription_amount=$obj->subscription;
  1083. }
  1084. $this->last_subscription_date=$obj->dateh;
  1085. $this->last_subscription_amount=$obj->subscription;
  1086. $subscription=new Subscription($this->db);
  1087. $subscription->id=$obj->rowid;
  1088. $subscription->fk_adherent=$obj->fk_adherent;
  1089. $subscription->amount=$obj->subscription;
  1090. $subscription->note=$obj->note;
  1091. $subscription->fk_bank=$obj->fk_bank;
  1092. $subscription->datem=$this->db->jdate($obj->datem);
  1093. $subscription->datec=$this->db->jdate($obj->datec);
  1094. $subscription->dateh=$this->db->jdate($obj->dateh);
  1095. $subscription->datef=$this->db->jdate($obj->datef);
  1096. $this->subscriptions[]=$subscription;
  1097. $i++;
  1098. }
  1099. return 1;
  1100. }
  1101. else
  1102. {
  1103. $this->error=$this->db->error().' sql='.$sql;
  1104. return -1;
  1105. }
  1106. }
  1107. /**
  1108. * Insert subscription into database and eventually add links to banks, mailman, etc...
  1109. *
  1110. * @param int $date Date of effect of subscription
  1111. * @param double $amount Amount of subscription (0 accepted for some members)
  1112. * @param int $accountid Id bank account
  1113. * @param string $operation Type of payment (if Id bank account provided). Example: 'CB', ...
  1114. * @param string $label Label operation (if Id bank account provided)
  1115. * @param string $num_chq Numero cheque (if Id bank account provided)
  1116. * @param string $emetteur_nom Name of cheque writer
  1117. * @param string $emetteur_banque Name of bank of cheque
  1118. * @param int $datesubend Date end subscription
  1119. * @return int rowid of record added, <0 if KO
  1120. */
  1121. function subscription($date, $amount, $accountid=0, $operation='', $label='', $num_chq='', $emetteur_nom='', $emetteur_banque='', $datesubend=0)
  1122. {
  1123. global $conf,$langs,$user;
  1124. require_once DOL_DOCUMENT_ROOT.'/adherents/class/subscription.class.php';
  1125. $error=0;
  1126. // Clean parameters
  1127. if (! $amount) $amount=0;
  1128. $this->db->begin();
  1129. if ($datesubend)
  1130. {
  1131. $datefin=$datesubend;
  1132. }
  1133. else
  1134. {
  1135. // If no end date, end date = date + 1 year - 1 day
  1136. $datefin = dol_time_plus_duree($date,1,'y');
  1137. $datefin = dol_time_plus_duree($datefin,-1,'d');
  1138. }
  1139. // Create subscription
  1140. $subscription=new Subscription($this->db);
  1141. $subscription->fk_adherent=$this->id;
  1142. $subscription->dateh=$date; // Date of new subscription
  1143. $subscription->datef=$datefin; // End data of new subscription
  1144. $subscription->amount=$amount;
  1145. $subscription->note=$label; // deprecated
  1146. $subscription->note_public=$label;
  1147. $rowid=$subscription->create($user);
  1148. if ($rowid > 0)
  1149. {
  1150. // Update denormalized subscription end date (read database subscription to find values)
  1151. // This will also update this->datefin
  1152. $result=$this->update_end_date($user);
  1153. if ($result > 0)
  1154. {
  1155. // Change properties of object (used by triggers)
  1156. $this->last_subscription_date=dol_now();
  1157. $this->last_subscription_amount=$amount;
  1158. $this->last_subscription_date_start=$date;
  1159. $this->last_subscription_date_end=$datefin;
  1160. }
  1161. if (! $error)
  1162. {
  1163. $this->db->commit();
  1164. return $rowid;
  1165. }
  1166. else
  1167. {
  1168. $this->db->rollback();
  1169. return -2;
  1170. }
  1171. }
  1172. else
  1173. {
  1174. $this->error=$subscription->error;
  1175. $this->errors=$subscription->errors;
  1176. $this->db->rollback();
  1177. return -1;
  1178. }
  1179. }
  1180. /**
  1181. * Do complementary actions after subscription recording.
  1182. *
  1183. * @param int $subscriptionid Id of created subscription
  1184. * @param string $option Which action ('bankdirect', 'bankviainvoice', 'invoiceonly', ...)
  1185. * @param int $accountid Id bank account
  1186. * @param int $datesubscription Date of subscription
  1187. * @param int $paymentdate Date of payment
  1188. * @param string $operation Code of type of operation (if Id bank account provided). Example 'CB', ...
  1189. * @param string $label Label operation (if Id bank account provided)
  1190. * @param double $amount Amount of subscription (0 accepted for some members)
  1191. * @param string $num_chq Numero cheque (if Id bank account provided)
  1192. * @param string $emetteur_nom Name of cheque writer
  1193. * @param string $emetteur_banque Name of bank of cheque
  1194. * @param string $autocreatethirdparty Auto create new thirdparty if member not yet linked to a thirdparty and we request an option that generate invoice.
  1195. * @return int <0 if KO, >0 if OK
  1196. */
  1197. function subscriptionComplementaryActions($subscriptionid, $option, $accountid, $datesubscription, $paymentdate, $operation, $label, $amount, $num_chq, $emetteur_nom='', $emetteur_banque='', $autocreatethirdparty=0)
  1198. {
  1199. global $conf, $langs, $user, $mysoc;
  1200. $error = 0;
  1201. $this->invoice = null; // This will contains invoice if an invoice is created
  1202. dol_syslog("subscriptionComplementaryActions subscriptionid=".$subscriptionid." option=".$option." accountid=".$accountid." datesubscription=".$datesubscription." paymentdate=".$paymentdate." label=".$label." amount=".$amount." num_chq=".$num_chq." autocreatethirdparty=".$autocreatethirdparty);
  1203. // Insert into bank account directlty (if option choosed for) + link to llx_subscription if option is 'bankdirect'
  1204. if ($option == 'bankdirect' && $accountid)
  1205. {
  1206. require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
  1207. $acct=new Account($this->db);
  1208. $result=$acct->fetch($accountid);
  1209. $dateop=$paymentdate;
  1210. $insertid=$acct->addline($dateop, $operation, $label, $amount, $num_chq, '', $user, $emetteur_nom, $emetteur_banque);
  1211. if ($insertid > 0)
  1212. {
  1213. $inserturlid=$acct->add_url_line($insertid, $this->id, DOL_URL_ROOT.'/adherents/card.php?rowid=', $this->getFullname($langs), 'member');
  1214. if ($inserturlid > 0)
  1215. {
  1216. // Update table subscription
  1217. $sql ="UPDATE ".MAIN_DB_PREFIX."subscription SET fk_bank=".$insertid;
  1218. $sql.=" WHERE rowid=".$subscriptionid;
  1219. dol_syslog("subscription::subscription", LOG_DEBUG);
  1220. $resql = $this->db->query($sql);
  1221. if (! $resql)
  1222. {
  1223. $error++;
  1224. $this->error=$this->db->lasterror();
  1225. $this->errors[]=$this->error;
  1226. }
  1227. }
  1228. else
  1229. {
  1230. $error++;
  1231. $this->error=$acct->error;
  1232. $this->errors=$acct->errors;
  1233. }
  1234. }
  1235. else
  1236. {
  1237. $error++;
  1238. $this->error=$acct->error;
  1239. $this->errors=$acct->errors;
  1240. }
  1241. }
  1242. // If option choosed, we create invoice
  1243. if (($option == 'bankviainvoice' && $accountid) || $option == 'invoiceonly')
  1244. {
  1245. require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
  1246. require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/paymentterm.class.php';
  1247. $invoice=new Facture($this->db);
  1248. $customer=new Societe($this->db);
  1249. if (! $error)
  1250. {
  1251. if (! ($this->fk_soc > 0)) // If not yet linked to a company
  1252. {
  1253. if ($autocreatethirdparty)
  1254. {
  1255. // Create a linked thirdparty to member
  1256. $companyalias='';
  1257. $fullname = $this->getFullName($langs);
  1258. if ($this->morphy == 'mor')
  1259. {
  1260. $companyname=$this->societe;
  1261. if (! empty($fullname)) $companyalias=$fullname;
  1262. }
  1263. else
  1264. {
  1265. $companyname=$fullname;
  1266. if (! empty($this->societe)) $companyalias=$this->societe;
  1267. }
  1268. $result=$customer->create_from_member($this, $companyname, $companyalias);
  1269. if ($result < 0)
  1270. {
  1271. $this->error = $customer->error;
  1272. $this->errors = $customer->errors;
  1273. $error++;
  1274. }
  1275. else
  1276. {
  1277. $this->fk_soc = $result;
  1278. }
  1279. }
  1280. else
  1281. {
  1282. $langs->load("errors");
  1283. $this->error=$langs->trans("ErrorMemberNotLinkedToAThirpartyLinkOrCreateFirst");
  1284. $this->errors[]=$this->error;
  1285. $error++;
  1286. }
  1287. }
  1288. }
  1289. if (! $error)
  1290. {
  1291. $result=$customer->fetch($this->fk_soc);
  1292. if ($result <= 0)
  1293. {
  1294. $this->error=$customer->error;
  1295. $this->errors=$customer->errors;
  1296. $error++;
  1297. }
  1298. }
  1299. if (! $error)
  1300. {
  1301. // Create draft invoice
  1302. $invoice->type=Facture::TYPE_STANDARD;
  1303. $invoice->cond_reglement_id=$customer->cond_reglement_id;
  1304. if (empty($invoice->cond_reglement_id))
  1305. {
  1306. $paymenttermstatic=new PaymentTerm($this->db);
  1307. $invoice->cond_reglement_id=$paymenttermstatic->getDefaultId();
  1308. if (empty($invoice->cond_reglement_id))
  1309. {
  1310. $error++;
  1311. $this->error='ErrorNoPaymentTermRECEPFound';
  1312. $this->errors[]=$this->error;
  1313. }
  1314. }
  1315. $invoice->socid=$this->fk_soc;
  1316. $invoice->date=$datesubscription;
  1317. // Possibility to add external linked objects with hooks
  1318. $invoice->linked_objects['subscription'] = $subscriptionid;
  1319. if (! empty($_POST['other_linked_objects']) && is_array($_POST['other_linked_objects']))
  1320. {
  1321. $invoice->linked_objects = array_merge($invoice->linked_objects, $_POST['other_linked_objects']);
  1322. }
  1323. $result=$invoice->create($user);
  1324. if ($result <= 0)
  1325. {
  1326. $this->error=$invoice->error;
  1327. $this->errors=$invoice->errors;
  1328. $error++;
  1329. }
  1330. else
  1331. {
  1332. $this->invoice = $invoice;
  1333. }
  1334. }
  1335. if (! $error)
  1336. {
  1337. // Add line to draft invoice
  1338. $idprodsubscription=0;
  1339. if (! empty($conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS) && (! empty($conf->product->enabled) || ! empty($conf->service->enabled))) $idprodsubscription = $conf->global->ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS;
  1340. $vattouse=0;
  1341. if (isset($conf->global->ADHERENT_VAT_FOR_SUBSCRIPTIONS) && $conf->global->ADHERENT_VAT_FOR_SUBSCRIPTIONS == 'defaultforfoundationcountry')
  1342. {
  1343. $vattouse=get_default_tva($mysoc, $mysoc, $idprodsubscription);
  1344. }
  1345. //print xx".$vattouse." - ".$mysoc." - ".$customer;exit;
  1346. $result=$invoice->addline($label,0,1,$vattouse,0,0,$idprodsubscription,0,$datesubscription,'',0,0,'','TTC',$amount,1);
  1347. if ($result <= 0)
  1348. {
  1349. $this->error=$invoice->error;
  1350. $this->errors=$invoice->errors;
  1351. $error++;
  1352. }
  1353. }
  1354. if (! $error)
  1355. {
  1356. // Validate invoice
  1357. $result=$invoice->validate($user);
  1358. if ($result <= 0)
  1359. {
  1360. $this->error=$invoice->error;
  1361. $this->errors=$invoice->errors;
  1362. $error++;
  1363. }
  1364. }
  1365. if (! $error)
  1366. {
  1367. // TODO Link invoice with subscription ?
  1368. }
  1369. // Add payment onto invoice
  1370. if (! $error && $option == 'bankviainvoice' && $accountid)
  1371. {
  1372. require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
  1373. require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
  1374. require_once DOL_DOCUMENT_ROOT.'/core/lib/functions.lib.php';
  1375. $amounts = array();
  1376. $amounts[$invoice->id] = price2num($amount);
  1377. $paiement = new Paiement($this->db);
  1378. $paiement->datepaye = $paymentdate;
  1379. $paiement->amounts = $amounts;
  1380. $paiement->paiementid = dol_getIdFromCode($this->db,$operation,'c_paiement','code','id',1);
  1381. $paiement->num_paiement = $num_chq;
  1382. $paiement->note = $label;
  1383. $paiement->note_public = $label;
  1384. if (! $error)
  1385. {
  1386. // Create payment line for invoice
  1387. $paiement_id = $paiement->create($user);
  1388. if (! $paiement_id > 0)
  1389. {
  1390. $this->error=$paiement->error;
  1391. $this->errors=$paiement->errors;
  1392. $error++;
  1393. }
  1394. }
  1395. if (! $error)
  1396. {
  1397. // Add transaction into bank account
  1398. $bank_line_id=$paiement->addPaymentToBank($user,'payment','(SubscriptionPayment)',$accountid,$emetteur_nom,$emetteur_banque);
  1399. if (! ($bank_line_id > 0))
  1400. {
  1401. $this->error=$paiement->error;
  1402. $this->errors=$paiement->errors;
  1403. $error++;
  1404. }
  1405. }
  1406. if (! $error && !empty($bank_line_id))
  1407. {
  1408. // Update fk_bank into subscription table
  1409. $sql = 'UPDATE '.MAIN_DB_PREFIX.'subscription SET fk_bank='.$bank_line_id;
  1410. $sql.= ' WHERE rowid='.$subscriptionid;
  1411. $result = $this->db->query($sql);
  1412. if (! $result)
  1413. {
  1414. $error++;
  1415. }
  1416. }
  1417. if (! $error)
  1418. {
  1419. // Set invoice as paid
  1420. $invoice->set_paid($user);
  1421. }
  1422. }
  1423. if (! $error)
  1424. {
  1425. // Define output language
  1426. $outputlangs = $langs;
  1427. $newlang = '';
  1428. $lang_id=GETPOST('lang_id');
  1429. if ($conf->global->MAIN_MULTILANGS && empty($newlang) && ! empty($lang_id))
  1430. $newlang = $lang_id;
  1431. if ($conf->global->MAIN_MULTILANGS && empty($newlang))
  1432. $newlang = $customer->default_lang;
  1433. if (! empty($newlang)) {
  1434. $outputlangs = new Translate("", $conf);
  1435. $outputlangs->setDefaultLang($newlang);
  1436. }
  1437. // Generate PDF (whatever is option MAIN_DISABLE_PDF_AUTOUPDATE) so we can include it into email
  1438. //if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
  1439. $invoice->generateDocument($invoice->modelpdf, $outputlangs);
  1440. }
  1441. }
  1442. if ($error)
  1443. {
  1444. return -1;
  1445. }
  1446. else
  1447. {
  1448. return 1;
  1449. }
  1450. }
  1451. /**
  1452. * Function that validate a member
  1453. *
  1454. * @param User $user user adherent qui valide
  1455. * @return int <0 if KO, 0 if nothing done, >0 if OK
  1456. */
  1457. function validate($user)
  1458. {
  1459. global $langs,$conf;
  1460. $error=0;
  1461. $now=dol_now();
  1462. // Check parameters
  1463. if ($this->statut == 1)
  1464. {
  1465. dol_syslog(get_class($this)."::validate statut of member does not allow this", LOG_WARNING);
  1466. return 0;
  1467. }
  1468. $this->db->begin();
  1469. $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
  1470. $sql.= " statut = 1";
  1471. $sql.= ", datevalid = '".$this->db->idate($now)."'";
  1472. $sql.= ", fk_user_valid=".$user->id;
  1473. $sql.= " WHERE rowid = ".$this->id;
  1474. dol_syslog(get_class($this)."::validate", LOG_DEBUG);
  1475. $result = $this->db->query($sql);
  1476. if ($result)
  1477. {
  1478. $this->statut=1;
  1479. // Call trigger
  1480. $result=$this->call_trigger('MEMBER_VALIDATE',$user);
  1481. if ($result < 0) { $error++; $this->db->rollback(); return -1; }
  1482. // End call triggers
  1483. $this->datevalid = $now;
  1484. $this->db->commit();
  1485. return 1;
  1486. }
  1487. else
  1488. {
  1489. $this->error=$this->db->error();
  1490. $this->db->rollback();
  1491. return -1;
  1492. }
  1493. }
  1494. /**
  1495. * Fonction qui resilie un adherent
  1496. *
  1497. * @param User $user User making change
  1498. * @return int <0 if KO, >0 if OK
  1499. */
  1500. function resiliate($user)
  1501. {
  1502. global $langs,$conf;
  1503. $error=0;
  1504. // Check paramaters
  1505. if ($this->statut == 0)
  1506. {
  1507. dol_syslog(get_class($this)."::resiliate statut of member does not allow this", LOG_WARNING);
  1508. return 0;
  1509. }
  1510. $this->db->begin();
  1511. $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET";
  1512. $sql.= " statut = 0";
  1513. $sql.= ", fk_user_valid=".$user->id;
  1514. $sql.= " WHERE rowid = ".$this->id;
  1515. $result = $this->db->query($sql);
  1516. if ($result)
  1517. {
  1518. $this->statut=0;
  1519. // Call trigger
  1520. $result=$this->call_trigger('MEMBER_RESILIATE',$user);
  1521. if ($result < 0) { $error++; $this->db->rollback(); return -1; }
  1522. // End call triggers
  1523. $this->db->commit();
  1524. return 1;
  1525. }
  1526. else
  1527. {
  1528. $this->error=$this->db->error();
  1529. $this->db->rollback();
  1530. return -1;
  1531. }
  1532. }
  1533. /**
  1534. * Function to add member into external tools mailing-list, spip, etc.
  1535. *
  1536. * @return int <0 if KO, >0 if OK
  1537. */
  1538. // phpcs:ignore PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  1539. function add_to_abo()
  1540. {
  1541. global $conf,$langs;
  1542. include_once DOL_DOCUMENT_ROOT.'/mailmanspip/class/mailmanspip.class.php';
  1543. $mailmanspip=new MailmanSpip($this->db);
  1544. $err=0;
  1545. // mailman
  1546. if (! empty($conf->global->ADHERENT_USE_MAILMAN) && ! empty($conf->mailmanspip->enabled))
  1547. {
  1548. $result=$mailmanspip->add_to_mailman($this);
  1549. if ($result < 0)
  1550. {
  1551. if (! empty($mailmanspip->error)) $this->errors[]=$mailmanspip->error;
  1552. $err+=1;
  1553. }
  1554. foreach ($mailmanspip->mladded_ko as $tmplist => $tmpemail)
  1555. {
  1556. $langs->load("errors");
  1557. $this->errors[]=$langs->trans("ErrorFailedToAddToMailmanList",$tmpemail,$tmplist);
  1558. }
  1559. foreach ($mailmanspip->mladded_ok as $tmplist => $tmpemail)
  1560. {
  1561. $langs->load("mailmanspip");
  1562. $this->mesgs[]=$langs->trans("SuccessToAddToMailmanList",$tmpemail,$tmplist);
  1563. }
  1564. }
  1565. // spip
  1566. if (! empty($conf->global->ADHERENT_USE_SPIP) && ! empty($conf->mailmanspip->enabled))
  1567. {
  1568. $result=$mailmanspip->add_to_spip($this);
  1569. if ($result < 0)
  1570. {
  1571. $this->errors[]=$mailmanspip->error;
  1572. $err+=1;
  1573. }
  1574. }
  1575. if ($err)
  1576. {
  1577. return -$err;
  1578. }
  1579. else
  1580. {
  1581. return 1;
  1582. }
  1583. }
  1584. /**
  1585. * Function to delete a member from external tools like mailing-list, spip, etc.
  1586. *
  1587. * @return int <0 if KO, >0 if OK
  1588. */
  1589. // phpcs:ignore PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  1590. function del_to_abo()
  1591. {
  1592. global $conf,$langs;
  1593. include_once DOL_DOCUMENT_ROOT.'/mailmanspip/class/mailmanspip.class.php';
  1594. $mailmanspip=new MailmanSpip($this->db);
  1595. $err=0;
  1596. // mailman
  1597. if (! empty($conf->global->ADHERENT_USE_MAILMAN))
  1598. {
  1599. $result=$mailmanspip->del_to_mailman($this);
  1600. if ($result < 0)
  1601. {
  1602. if (! empty($mailmanspip->error)) $this->errors[]=$mailmanspip->error;
  1603. $err+=1;
  1604. }
  1605. foreach ($mailmanspip->mlremoved_ko as $tmplist => $tmpemail)
  1606. {
  1607. $langs->load("errors");
  1608. $this->errors[]=$langs->trans("ErrorFailedToRemoveToMailmanList",$tmpemail,$tmplist);
  1609. }
  1610. foreach ($mailmanspip->mlremoved_ok as $tmplist => $tmpemail)
  1611. {
  1612. $langs->load("mailmanspip");
  1613. $this->mesgs[]=$langs->trans("SuccessToRemoveToMailmanList",$tmpemail,$tmplist);
  1614. }
  1615. }
  1616. if ($conf->global->ADHERENT_USE_SPIP && ! empty($conf->mailmanspip->enabled))
  1617. {
  1618. $result=$mailmanspip->del_to_spip($this);
  1619. if ($result < 0)
  1620. {
  1621. $this->errors[]=$mailmanspip->error;
  1622. $err+=1;
  1623. }
  1624. }
  1625. if ($err)
  1626. {
  1627. // error
  1628. return -$err;
  1629. }
  1630. else
  1631. {
  1632. return 1;
  1633. }
  1634. }
  1635. /**
  1636. * Return civility label of a member
  1637. *
  1638. * @return string Translated name of civility (translated with transnoentitiesnoconv)
  1639. */
  1640. function getCivilityLabel()
  1641. {
  1642. global $langs;
  1643. $langs->load("dict");
  1644. $code=(empty($this->civility_id)?'':$this->civility_id);
  1645. if (empty($code)) return '';
  1646. return $langs->getLabelFromKey($this->db, "Civility".$code, "c_civility", "code", "label", $code);
  1647. }
  1648. /**
  1649. * Return clicable name (with picto eventually)
  1650. *
  1651. * @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)
  1652. * @param int $maxlen length max label
  1653. * @param string $option Page for link ('card', 'category', 'subscription', ...)
  1654. * @param string $mode ''=Show firstname+lastname as label (using default order), 'firstname'=Show only firstname, 'login'=Show login, 'ref'=Show ref
  1655. * @param string $morecss Add more css on link
  1656. * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
  1657. * @return string Chaine avec URL
  1658. */
  1659. function getNomUrl($withpictoimg=0, $maxlen=0, $option='card', $mode='', $morecss='', $save_lastsearch_value=-1)
  1660. {
  1661. global $conf, $langs;
  1662. if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) && $withpictoimg) $withpictoimg=0;
  1663. $notooltip=0;
  1664. $result=''; $label='';
  1665. $link=''; $linkstart=''; $linkend='';
  1666. if (! empty($this->photo))
  1667. {
  1668. $label.= '<div class="photointooltip">';
  1669. $label.= Form::showphoto('memberphoto', $this, 80, 0, 0, 'photowithmargin photologintooltip', 'small', 0, 1);
  1670. $label.= '</div><div style="clear: both;"></div>';
  1671. }
  1672. $label.= '<div class="centpercent">';
  1673. $label.= '<u>' . $langs->trans("Member") . '</u>';
  1674. if (! empty($this->ref))
  1675. $label.= '<br><b>' . $langs->trans('Ref') . ':</b> ' . $this->ref;
  1676. if (! empty($this->firstname) || ! empty($this->lastname))
  1677. $label.= '<br><b>' . $langs->trans('Name') . ':</b> ' . $this->getFullName($langs);
  1678. if (! empty($this->societe))
  1679. $label.= '<br><b>' . $langs->trans('Company') . ':</b> ' . $this->societe;
  1680. $label.='</div>';
  1681. $url = DOL_URL_ROOT.'/adherents/card.php?rowid='.$this->id;
  1682. if ($option == 'subscription')
  1683. {
  1684. $url = DOL_URL_ROOT.'/adherents/subscription.php?rowid='.$this->id;
  1685. }
  1686. if ($option != 'nolink')
  1687. {
  1688. // Add param to save lastsearch_values or not
  1689. $add_save_lastsearch_values=($save_lastsearch_value == 1 ? 1 : 0);
  1690. if ($save_lastsearch_value == -1 && preg_match('/list\.php/',$_SERVER["PHP_SELF"])) $add_save_lastsearch_values=1;
  1691. if ($add_save_lastsearch_values) $url.='&save_lastsearch_values=1';
  1692. }
  1693. $link = '<a href="'.$url.'"';
  1694. $linkclose="";
  1695. if (empty($notooltip))
  1696. {
  1697. if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
  1698. {
  1699. $langs->load("users");
  1700. $label=$langs->trans("ShowUser");
  1701. $linkclose.=' alt="'.dol_escape_htmltag($label, 1).'"';
  1702. }
  1703. $linkclose.= ' title="'.dol_escape_htmltag($label, 1).'"';
  1704. $linkclose.= ' class="classfortooltip'.($morecss?' '.$morecss:'').'"';
  1705. }
  1706. $link.=$linkclose.'>';
  1707. $linkend='</a>';
  1708. //if ($withpictoimg == -1) $result.='<div class="nowrap">';
  1709. $result.=$link;
  1710. if ($withpictoimg)
  1711. {
  1712. $paddafterimage='';
  1713. if (abs($withpictoimg) == 1) $paddafterimage='style="margin-right: 3px;"';
  1714. // Only picto
  1715. if ($withpictoimg > 0) $picto='<div class="inline-block nopadding valignmiddle'.($morecss?' userimg'.$morecss:'').'">'.img_object('', 'user', $paddafterimage.' '.($notooltip?'':'class="classfortooltip"'), 0, 0, $notooltip?0:1).'</div>';
  1716. // Picto must be a photo
  1717. else $picto='<div class="inline-block nopadding valignmiddle'.($morecss?' userimg'.$morecss:'').'"'.($paddafterimage?' '.$paddafterimage:'').'>'.Form::showphoto('memberphoto', $this, 0, 0, 0, 'userphoto'.($withpictoimg==-3?'small':''), 'mini', 0, 1).'</div>';
  1718. $result.=$picto;
  1719. }
  1720. if ($withpictoimg > -2 && $withpictoimg != 2)
  1721. {
  1722. if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) $result.='<div class="inline-block nopadding valignmiddle'.((! isset($this->statut) || $this->statut)?'':' strikefordisabled').($morecss?' usertext'.$morecss:'').'">';
  1723. if ($mode == 'login') $result.=dol_trunc($this->login, $maxlen);
  1724. elseif ($mode == 'ref') $result.=$this->id;
  1725. else $result.=$this->getFullName($langs,'',($mode == 'firstname' ? 2 : -1),$maxlen);
  1726. if (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) $result.='</div>';
  1727. }
  1728. $result.=$linkend;
  1729. //if ($withpictoimg == -1) $result.='</div>';
  1730. return $result;
  1731. }
  1732. /**
  1733. * Retourne le libelle du statut d'un adherent (brouillon, valide, resilie)
  1734. *
  1735. * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
  1736. * @return string Label
  1737. */
  1738. function getLibStatut($mode=0)
  1739. {
  1740. return $this->LibStatut($this->statut,$this->need_subscription,$this->datefin,$mode);
  1741. }
  1742. /**
  1743. * Renvoi le libelle d'un statut donne
  1744. *
  1745. * @param int $statut Id statut
  1746. * @param int $need_subscription 1 if member type need subscription, 0 otherwise
  1747. * @param int $date_end_subscription Date fin adhesion
  1748. * @param int $mode 0=libelle long, 1=libelle court, 2=Picto + Libelle court, 3=Picto, 4=Picto + Libelle long, 5=Libelle court + Picto
  1749. * @return string Label
  1750. */
  1751. // phpcs:ignore PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  1752. function LibStatut($statut,$need_subscription,$date_end_subscription,$mode=0)
  1753. {
  1754. global $langs;
  1755. $langs->load("members");
  1756. if ($mode == 0)
  1757. {
  1758. if ($statut == -1) return $langs->trans("MemberStatusDraft");
  1759. if ($statut >= 1)
  1760. {
  1761. if (! $date_end_subscription) return $langs->trans("MemberStatusActive");
  1762. elseif ($date_end_subscription < time()) return $langs->trans("MemberStatusActiveLate");
  1763. else return $langs->trans("MemberStatusPaid");
  1764. }
  1765. if ($statut == 0) return $langs->trans("MemberStatusResiliated");
  1766. }
  1767. if ($mode == 1)
  1768. {
  1769. if ($statut == -1) return $langs->trans("MemberStatusDraftShort");
  1770. if ($statut >= 1)
  1771. {
  1772. if (! $date_end_subscription) return $langs->trans("MemberStatusActiveShort");
  1773. elseif ($date_end_subscription < time()) return $langs->trans("MemberStatusActiveLateShort");
  1774. else return $langs->trans("MemberStatusPaidShort");
  1775. }
  1776. if ($statut == 0) return $langs->trans("MemberStatusResiliatedShort");
  1777. }
  1778. if ($mode == 2)
  1779. {
  1780. if ($statut == -1) return img_picto($langs->trans('MemberStatusDraft'),'statut0').' '.$langs->trans("MemberStatusDraftShort");
  1781. if ($statut >= 1)
  1782. {
  1783. if (! $date_end_subscription) return img_picto($langs->trans('MemberStatusActive'),'statut1').' '.$langs->trans("MemberStatusActiveShort");
  1784. elseif ($date_end_subscription < time()) return img_picto($langs->trans('MemberStatusActiveLate'),'statut3').' '.$langs->trans("MemberStatusActiveLateShort");
  1785. else return img_picto($langs->trans('MemberStatusPaid'),'statut4').' '.$langs->trans("MemberStatusPaidShort");
  1786. }
  1787. if ($statut == 0) return img_picto($langs->trans('MemberStatusResiliated'),'statut5').' '.$langs->trans("MemberStatusResiliatedShort");
  1788. }
  1789. if ($mode == 3)
  1790. {
  1791. if ($statut == -1) return img_picto($langs->trans('MemberStatusDraft'),'statut0');
  1792. if ($statut >= 1)
  1793. {
  1794. if (! $date_end_subscription) return img_picto($langs->trans('MemberStatusActive'),'statut1');
  1795. elseif ($date_end_subscription < time()) return img_picto($langs->trans('MemberStatusActiveLate'),'statut3');
  1796. else return img_picto($langs->trans('MemberStatusPaid'),'statut4');
  1797. }
  1798. if ($statut == 0) return img_picto($langs->trans('MemberStatusResiliated'),'statut5');
  1799. }
  1800. if ($mode == 4)
  1801. {
  1802. if ($statut == -1) return img_picto($langs->trans('MemberStatusDraft'),'statut0').' '.$langs->trans("MemberStatusDraft");
  1803. if ($statut >= 1)
  1804. {
  1805. if (! $date_end_subscription) return img_picto($langs->trans('MemberStatusActive'),'statut1').' '.$langs->trans("MemberStatusActive");
  1806. elseif ($date_end_subscription < time()) return img_picto($langs->trans('MemberStatusActiveLate'),'statut3').' '.$langs->trans("MemberStatusActiveLate");
  1807. else return img_picto($langs->trans('MemberStatusPaid'),'statut4').' '.$langs->trans("MemberStatusPaid");
  1808. }
  1809. if ($statut == 0) return img_picto($langs->trans('MemberStatusResiliated'),'statut5').' '.$langs->trans("MemberStatusResiliated");
  1810. }
  1811. if ($mode == 5)
  1812. {
  1813. if ($statut == -1) return $langs->trans("MemberStatusDraft").' '.img_picto($langs->trans('MemberStatusDraft'),'statut0');
  1814. if ($statut >= 1)
  1815. {
  1816. if (! $date_end_subscription) return '<span class="hideonsmartphone">'.$langs->trans("MemberStatusActiveShort").' </span>'.img_picto($langs->trans('MemberStatusActive'),'statut1');
  1817. elseif ($date_end_subscription < time()) return '<span class="hideonsmartphone">'.$langs->trans("MemberStatusActiveLateShort").' </span>'.img_picto($langs->trans('MemberStatusActiveLate'),'statut3');
  1818. else return '<span class="hideonsmartphone">'.$langs->trans("MemberStatusPaidShort").' </span>'.img_picto($langs->trans('MemberStatusPaid'),'statut4');
  1819. }
  1820. if ($statut == 0) return '<span class="hideonsmartphone">'.$langs->trans("MemberStatusResiliated").' </span>'.img_picto($langs->trans('MemberStatusResiliated'),'statut5');
  1821. }
  1822. if ($mode == 6)
  1823. {
  1824. if ($statut == -1) return $langs->trans("MemberStatusDraft").' '.img_picto($langs->trans('MemberStatusDraft'),'statut0');
  1825. if ($statut >= 1)
  1826. {
  1827. if (! $date_end_subscription) return '<span class="hideonsmartphone">'.$langs->trans("MemberStatusActive").' </span>'.img_picto($langs->trans('MemberStatusActive'),'statut1');
  1828. elseif ($date_end_subscription < time()) return '<span class="hideonsmartphone">'.$langs->trans("MemberStatusActiveLate").' </span>'.img_picto($langs->trans('MemberStatusActiveLate'),'statut3');
  1829. else return '<span class="hideonsmartphone">'.$langs->trans("MemberStatusPaid").' </span>'.img_picto($langs->trans('MemberStatusPaid'),'statut4');
  1830. }
  1831. if ($statut == 0) return '<span class="hideonsmartphone">'.$langs->trans("MemberStatusResiliated").' </span>'.img_picto($langs->trans('MemberStatusResiliated'),'statut5');
  1832. }
  1833. }
  1834. /**
  1835. * Charge indicateurs this->nb de tableau de bord
  1836. *
  1837. * @return int <0 if KO, >0 if OK
  1838. */
  1839. // phpcs:ignore PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  1840. function load_state_board()
  1841. {
  1842. global $conf;
  1843. $this->nb=array();
  1844. $sql = "SELECT count(a.rowid) as nb";
  1845. $sql.= " FROM ".MAIN_DB_PREFIX."adherent as a";
  1846. $sql.= " WHERE a.statut > 0";
  1847. $sql.= " AND a.entity IN (".getEntity('adherent').")";
  1848. $resql=$this->db->query($sql);
  1849. if ($resql)
  1850. {
  1851. while ($obj=$this->db->fetch_object($resql))
  1852. {
  1853. $this->nb["members"]=$obj->nb;
  1854. }
  1855. $this->db->free($resql);
  1856. return 1;
  1857. }
  1858. else
  1859. {
  1860. dol_print_error($this->db);
  1861. $this->error=$this->db->error();
  1862. return -1;
  1863. }
  1864. }
  1865. /**
  1866. * Load indicators for dashboard (this->nbtodo and this->nbtodolate)
  1867. *
  1868. * @param User $user Objet user
  1869. * @return WorkboardResponse|int <0 if KO, WorkboardResponse if OK
  1870. */
  1871. // phpcs:ignore PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  1872. function load_board($user)
  1873. {
  1874. global $conf, $langs;
  1875. if ($user->societe_id) return -1; // protection pour eviter appel par utilisateur externe
  1876. $now=dol_now();
  1877. $sql = "SELECT a.rowid, a.datefin, a.statut";
  1878. $sql.= " FROM ".MAIN_DB_PREFIX."adherent as a";
  1879. $sql.= " WHERE a.statut = 1";
  1880. $sql.= " AND a.entity IN (".getEntity('adherent').")";
  1881. $sql.= " AND (a.datefin IS NULL or a.datefin < '".$this->db->idate($now)."')";
  1882. $resql=$this->db->query($sql);
  1883. if ($resql)
  1884. {
  1885. $langs->load("members");
  1886. $response = new WorkboardResponse();
  1887. $response->warning_delay=$conf->adherent->subscription->warning_delay/60/60/24;
  1888. $response->label=$langs->trans("MembersWithSubscriptionToReceive");
  1889. $response->url=DOL_URL_ROOT.'/adherents/list.php?mainmenu=members&amp;statut=1&amp;filter=outofdate';
  1890. $response->img=img_object('',"user");
  1891. $adherentstatic = new Adherent($this->db);
  1892. while ($obj=$this->db->fetch_object($resql))
  1893. {
  1894. $response->nbtodo++;
  1895. $adherentstatic->datefin = $this->db->jdate($obj->datefin);
  1896. $adherentstatic->statut = $obj->statut;
  1897. if ($adherentstatic->hasDelay()) {
  1898. $response->nbtodolate++;
  1899. }
  1900. }
  1901. return $response;
  1902. }
  1903. else
  1904. {
  1905. dol_print_error($this->db);
  1906. $this->error=$this->db->error();
  1907. return -1;
  1908. }
  1909. }
  1910. /**
  1911. * Create a document onto disk according to template module.
  1912. *
  1913. * @param string $modele Force template to use ('' to not force)
  1914. * @param Translate $outputlangs objet lang a utiliser pour traduction
  1915. * @param int $hidedetails Hide details of lines
  1916. * @param int $hidedesc Hide description
  1917. * @param int $hideref Hide ref
  1918. * @param null|array $moreparams Array to provide more information
  1919. * @return int 0 if KO, 1 if OK
  1920. */
  1921. public function generateDocument($modele, $outputlangs, $hidedetails=0, $hidedesc=0, $hideref=0, $moreparams=null)
  1922. {
  1923. global $conf,$langs;
  1924. $langs->load("orders");
  1925. if (! dol_strlen($modele)) {
  1926. $modele = 'standard';
  1927. if ($this->modelpdf) {
  1928. $modele = $this->modelpdf;
  1929. } elseif (! empty($conf->global->ADHERENT_ADDON_PDF)) {
  1930. $modele = $conf->global->ADHERENT_ADDON_PDF;
  1931. }
  1932. }
  1933. $modelpath = "core/modules/member/doc/";
  1934. return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
  1935. }
  1936. /**
  1937. * Initialise an instance with random values.
  1938. * Used to build previews or test instances.
  1939. * id must be 0 if object instance is a specimen.
  1940. *
  1941. * @return void
  1942. */
  1943. function initAsSpecimen()
  1944. {
  1945. global $user,$langs;
  1946. // Initialise parametres
  1947. $this->id=0;
  1948. $this->specimen=1;
  1949. $this->civility_id = 0;
  1950. $this->lastname = 'DOLIBARR';
  1951. $this->firstname = 'SPECIMEN';
  1952. $this->login='dolibspec';
  1953. $this->pass='dolibspec';
  1954. $this->societe = 'Societe ABC';
  1955. $this->address = '61 jump street';
  1956. $this->zip = '75000';
  1957. $this->town = 'Paris';
  1958. $this->country_id = 1;
  1959. $this->country_code = 'FR';
  1960. $this->country = 'France';
  1961. $this->morphy = 1;
  1962. $this->email = 'specimen@specimen.com';
  1963. $this->skype = 'tom.hanson';
  1964. $this->phone = '0999999999';
  1965. $this->phone_perso = '0999999998';
  1966. $this->phone_mobile = '0999999997';
  1967. $this->note_private='No comment';
  1968. $this->birth=time();
  1969. $this->photo='';
  1970. $this->public=1;
  1971. $this->statut=0;
  1972. $this->datefin=time();
  1973. $this->datevalid=time();
  1974. $this->typeid=1; // Id type adherent
  1975. $this->type='Type adherent'; // Libelle type adherent
  1976. $this->need_subscription=0;
  1977. $this->first_subscription_date=time();
  1978. $this->first_subscription_amount=10;
  1979. $this->last_subscription_date=time();
  1980. $this->last_subscription_amount=10;
  1981. }
  1982. /**
  1983. * Retourne chaine DN complete dans l'annuaire LDAP pour l'objet
  1984. *
  1985. * @param array $info Info array loaded by _load_ldap_info
  1986. * @param int $mode 0=Return full DN (uid=qqq,ou=xxx,dc=aaa,dc=bbb)
  1987. * 1=Return DN without key inside (ou=xxx,dc=aaa,dc=bbb)
  1988. * 2=Return key only (uid=qqq)
  1989. * @return string DN
  1990. */
  1991. // phpcs:ignore PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  1992. function _load_ldap_dn($info,$mode=0)
  1993. {
  1994. global $conf;
  1995. $dn='';
  1996. if ($mode==0) $dn=$conf->global->LDAP_KEY_MEMBERS."=".$info[$conf->global->LDAP_KEY_MEMBERS].",".$conf->global->LDAP_MEMBER_DN;
  1997. if ($mode==1) $dn=$conf->global->LDAP_MEMBER_DN;
  1998. if ($mode==2) $dn=$conf->global->LDAP_KEY_MEMBERS."=".$info[$conf->global->LDAP_KEY_MEMBERS];
  1999. return $dn;
  2000. }
  2001. /**
  2002. * Initialise tableau info (tableau des attributs LDAP)
  2003. *
  2004. * @return array Tableau info des attributs
  2005. */
  2006. // phpcs:ignore PEAR.NamingConventions.ValidFunctionName.NotCamelCaps
  2007. function _load_ldap_info()
  2008. {
  2009. global $conf,$langs;
  2010. $info=array();
  2011. $keymodified=false;
  2012. // Object classes
  2013. $info["objectclass"]=explode(',',$conf->global->LDAP_MEMBER_OBJECT_CLASS);
  2014. $this->fullname=$this->getFullName($langs);
  2015. // For avoid ldap error when firstname and lastname are empty
  2016. if ($this->morphy == 'mor' && (empty($this->fullname) || $this->fullname == $this->societe)) {
  2017. $this->fullname = $this->societe;
  2018. $this->lastname = $this->societe;
  2019. }
  2020. // Possible LDAP KEY (constname => varname)
  2021. $ldapkey = array(
  2022. 'LDAP_MEMBER_FIELD_FULLNAME' => 'fullname',
  2023. 'LDAP_MEMBER_FIELD_NAME' => 'lastname',
  2024. 'LDAP_MEMBER_FIELD_LOGIN' => 'login',
  2025. 'LDAP_MEMBER_FIELD_LOGIN_SAMBA' => 'login',
  2026. 'LDAP_MEMBER_FIELD_MAIL' => 'email'
  2027. );
  2028. // Member
  2029. foreach ($ldapkey as $constname => $varname)
  2030. {
  2031. if (! empty($this->$varname) && ! empty($conf->global->$constname))
  2032. {
  2033. $info[$conf->global->$constname] = $this->$varname;
  2034. // Check if it is the LDAP key and if its value has been changed
  2035. if (! empty($conf->global->LDAP_KEY_MEMBERS) && $conf->global->LDAP_KEY_MEMBERS == $conf->global->$constname)
  2036. {
  2037. if (! empty($this->oldcopy) && $this->$varname != $this->oldcopy->$varname) $keymodified=true; // For check if LDAP key has been modified
  2038. }
  2039. }
  2040. }
  2041. if ($this->firstname && ! empty($conf->global->LDAP_MEMBER_FIELD_FIRSTNAME)) $info[$conf->global->LDAP_MEMBER_FIELD_FIRSTNAME] = $this->firstname;
  2042. if ($this->poste && ! empty($conf->global->LDAP_MEMBER_FIELD_TITLE)) $info[$conf->global->LDAP_MEMBER_FIELD_TITLE] = $this->poste;
  2043. if ($this->societe && ! empty($conf->global->LDAP_MEMBER_FIELD_COMPANY)) $info[$conf->global->LDAP_MEMBER_FIELD_COMPANY] = $this->societe;
  2044. if ($this->address && ! empty($conf->global->LDAP_MEMBER_FIELD_ADDRESS)) $info[$conf->global->LDAP_MEMBER_FIELD_ADDRESS] = $this->address;
  2045. if ($this->zip && ! empty($conf->global->LDAP_MEMBER_FIELD_ZIP)) $info[$conf->global->LDAP_MEMBER_FIELD_ZIP] = $this->zip;
  2046. if ($this->town && ! empty($conf->global->LDAP_MEMBER_FIELD_TOWN)) $info[$conf->global->LDAP_MEMBER_FIELD_TOWN] = $this->town;
  2047. if ($this->country_code && ! empty($conf->global->LDAP_MEMBER_FIELD_COUNTRY)) $info[$conf->global->LDAP_MEMBER_FIELD_COUNTRY] = $this->country_code;
  2048. if ($this->skype && ! empty($conf->global->LDAP_MEMBER_FIELD_SKYPE)) $info[$conf->global->LDAP_MEMBER_FIELD_SKYPE] = $this->skype;
  2049. if ($this->phone && ! empty($conf->global->LDAP_MEMBER_FIELD_PHONE)) $info[$conf->global->LDAP_MEMBER_FIELD_PHONE] = $this->phone;
  2050. if ($this->phone_perso && ! empty($conf->global->LDAP_MEMBER_FIELD_PHONE_PERSO)) $info[$conf->global->LDAP_MEMBER_FIELD_PHONE_PERSO] = $this->phone_perso;
  2051. if ($this->phone_mobile && ! empty($conf->global->LDAP_MEMBER_FIELD_MOBILE)) $info[$conf->global->LDAP_MEMBER_FIELD_MOBILE] = $this->phone_mobile;
  2052. if ($this->fax && ! empty($conf->global->LDAP_MEMBER_FIELD_FAX)) $info[$conf->global->LDAP_MEMBER_FIELD_FAX] = $this->fax;
  2053. if ($this->note_private && ! empty($conf->global->LDAP_MEMBER_FIELD_DESCRIPTION)) $info[$conf->global->LDAP_MEMBER_FIELD_DESCRIPTION] = dol_string_nohtmltag($this->note_private, 2);
  2054. if ($this->note_public && ! empty($conf->global->LDAP_MEMBER_FIELD_NOTE_PUBLIC)) $info[$conf->global->LDAP_MEMBER_FIELD_NOTE_PUBLIC] = dol_string_nohtmltag($this->note_public, 2);
  2055. if ($this->birth && ! empty($conf->global->LDAP_MEMBER_FIELD_BIRTHDATE)) $info[$conf->global->LDAP_MEMBER_FIELD_BIRTHDATE] = dol_print_date($this->birth,'dayhourldap');
  2056. if (isset($this->statut) && ! empty($conf->global->LDAP_FIELD_MEMBER_STATUS)) $info[$conf->global->LDAP_FIELD_MEMBER_STATUS] = $this->statut;
  2057. if ($this->datefin && ! empty($conf->global->LDAP_FIELD_MEMBER_END_LASTSUBSCRIPTION)) $info[$conf->global->LDAP_FIELD_MEMBER_END_LASTSUBSCRIPTION] = dol_print_date($this->datefin,'dayhourldap');
  2058. // When password is modified
  2059. if (! empty($this->pass))
  2060. {
  2061. if (! empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD)) $info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD] = $this->pass; // this->pass = mot de passe non crypte
  2062. if (! empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED)) $info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED] = dol_hash($this->pass, 4); // Create OpenLDAP MD5 password (TODO add type of encryption)
  2063. }
  2064. // Set LDAP password if possible
  2065. else if ($conf->global->LDAP_SERVER_PROTOCOLVERSION !== '3') // If ldap key is modified and LDAPv3 we use ldap_rename function for avoid lose encrypt password
  2066. {
  2067. if (! empty($conf->global->DATABASE_PWD_ENCRYPTED))
  2068. {
  2069. // Just for the default MD5 !
  2070. if (empty($conf->global->MAIN_SECURITY_HASH_ALGO))
  2071. {
  2072. if ($this->pass_indatabase_crypted && ! empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED)) {
  2073. // Create OpenLDAP MD5 password from Dolibarr MD5 password
  2074. // Note: This suppose that "pass_indatabase_crypted" is a md5 (guaranted by the previous test if "(empty($conf->global->MAIN_SECURITY_HASH_ALGO))"
  2075. $info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED] = '{md5}'.base64_encode(hex2bin($this->pass_indatabase_crypted));
  2076. }
  2077. }
  2078. }
  2079. // Use $this->pass_indatabase value if exists
  2080. else if (! empty($this->pass_indatabase))
  2081. {
  2082. if (! empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD)) $info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD] = $this->pass_indatabase; // $this->pass_indatabase = mot de passe non crypte
  2083. if (! empty($conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED)) $info[$conf->global->LDAP_MEMBER_FIELD_PASSWORD_CRYPTED] = dol_hash($this->pass_indatabase, 4); // md5 for OpenLdap TODO add type of encryption
  2084. }
  2085. }
  2086. // Subscriptions
  2087. if ($this->first_subscription_date && ! empty($conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_DATE)) $info[$conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_DATE] = dol_print_date($this->first_subscription_date,'dayhourldap');
  2088. if (isset($this->first_subscription_amount) && ! empty($conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_AMOUNT)) $info[$conf->global->LDAP_FIELD_MEMBER_FIRSTSUBSCRIPTION_AMOUNT] = $this->first_subscription_amount;
  2089. if ($this->last_subscription_date && ! empty($conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_DATE)) $info[$conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_DATE] = dol_print_date($this->last_subscription_date,'dayhourldap');
  2090. if (isset($this->last_subscription_amount) && ! empty($conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_AMOUNT)) $info[$conf->global->LDAP_FIELD_MEMBER_LASTSUBSCRIPTION_AMOUNT] = $this->last_subscription_amount;
  2091. return $info;
  2092. }
  2093. /**
  2094. * Charge les informations d'ordre info dans l'objet adherent
  2095. *
  2096. * @param int $id Id of member to load
  2097. * @return void
  2098. */
  2099. function info($id)
  2100. {
  2101. $sql = 'SELECT a.rowid, a.datec as datec,';
  2102. $sql.= ' a.datevalid as datev,';
  2103. $sql.= ' a.tms as datem,';
  2104. $sql.= ' a.fk_user_author, a.fk_user_valid, a.fk_user_mod';
  2105. $sql.= ' FROM '.MAIN_DB_PREFIX.'adherent as a';
  2106. $sql.= ' WHERE a.rowid = '.$id;
  2107. dol_syslog(get_class($this)."::info", LOG_DEBUG);
  2108. $result=$this->db->query($sql);
  2109. if ($result)
  2110. {
  2111. if ($this->db->num_rows($result))
  2112. {
  2113. $obj = $this->db->fetch_object($result);
  2114. $this->id = $obj->rowid;
  2115. if ($obj->fk_user_author)
  2116. {
  2117. $cuser = new User($this->db);
  2118. $cuser->fetch($obj->fk_user_author);
  2119. $this->user_creation = $cuser;
  2120. }
  2121. if ($obj->fk_user_valid)
  2122. {
  2123. $vuser = new User($this->db);
  2124. $vuser->fetch($obj->fk_user_valid);
  2125. $this->user_validation = $vuser;
  2126. }
  2127. if ($obj->fk_user_mod)
  2128. {
  2129. $muser = new User($this->db);
  2130. $muser->fetch($obj->fk_user_mod);
  2131. $this->user_modification = $muser;
  2132. }
  2133. $this->date_creation = $this->db->jdate($obj->datec);
  2134. $this->date_validation = $this->db->jdate($obj->datev);
  2135. $this->date_modification = $this->db->jdate($obj->datem);
  2136. }
  2137. $this->db->free($result);
  2138. }
  2139. else
  2140. {
  2141. dol_print_error($this->db);
  2142. }
  2143. }
  2144. /**
  2145. * Return number of mass Emailing received by this member with its email
  2146. *
  2147. * @return int Number of EMailings
  2148. */
  2149. function getNbOfEMailings()
  2150. {
  2151. $sql = "SELECT count(mc.email) as nb";
  2152. $sql.= " FROM ".MAIN_DB_PREFIX."mailing_cibles as mc";
  2153. $sql.= " WHERE mc.email = '".$this->db->escape($this->email)."'";
  2154. $sql.= " AND mc.statut NOT IN (-1,0)"; // -1 erreur, 0 non envoye, 1 envoye avec succes
  2155. $resql=$this->db->query($sql);
  2156. if ($resql)
  2157. {
  2158. $obj = $this->db->fetch_object($resql);
  2159. $nb=$obj->nb;
  2160. $this->db->free($resql);
  2161. return $nb;
  2162. }
  2163. else
  2164. {
  2165. $this->error=$this->db->error();
  2166. return -1;
  2167. }
  2168. }
  2169. /**
  2170. * Sets object to supplied categories.
  2171. *
  2172. * Deletes object from existing categories not supplied.
  2173. * Adds it to non existing supplied categories.
  2174. * Existing categories are left untouch.
  2175. *
  2176. * @param int[]|int $categories Category or categories IDs
  2177. * @return void
  2178. */
  2179. public function setCategories($categories)
  2180. {
  2181. // Handle single category
  2182. if (!is_array($categories)) {
  2183. $categories = array($categories);
  2184. }
  2185. // Get current categories
  2186. require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php';
  2187. $c = new Categorie($this->db);
  2188. $existing = $c->containing($this->id, Categorie::TYPE_MEMBER, 'id');
  2189. // Diff
  2190. if (is_array($existing)) {
  2191. $to_del = array_diff($existing, $categories);
  2192. $to_add = array_diff($categories, $existing);
  2193. } else {
  2194. $to_del = array(); // Nothing to delete
  2195. $to_add = $categories;
  2196. }
  2197. // Process
  2198. foreach ($to_del as $del) {
  2199. if ($c->fetch($del) > 0) {
  2200. $c->del_type($this, 'member');
  2201. }
  2202. }
  2203. foreach ($to_add as $add) {
  2204. if ($c->fetch($add) > 0) {
  2205. $c->add_type($this, 'member');
  2206. }
  2207. }
  2208. return;
  2209. }
  2210. /**
  2211. * Function used to replace a thirdparty id with another one.
  2212. *
  2213. * @param DoliDB $db Database handler
  2214. * @param int $origin_id Old thirdparty id
  2215. * @param int $dest_id New thirdparty id
  2216. * @return bool
  2217. */
  2218. public static function replaceThirdparty($db, $origin_id, $dest_id)
  2219. {
  2220. $tables = array(
  2221. 'adherent'
  2222. );
  2223. return CommonObject::commonReplaceThirdparty($db, $origin_id, $dest_id, $tables);
  2224. }
  2225. /**
  2226. * Return if a member is late (subscription late) or not
  2227. *
  2228. * @return boolean True if late, False if not late
  2229. */
  2230. public function hasDelay()
  2231. {
  2232. global $conf;
  2233. //Only valid members
  2234. if ($this->statut <= 0) return false;
  2235. if (! $this->datefin) return false;
  2236. $now = dol_now();
  2237. return $this->datefin < ($now - $conf->adherent->subscription->warning_delay);
  2238. }
  2239. /**
  2240. * Send reminders by emails before subscription end
  2241. * CAN BE A CRON TASK
  2242. *
  2243. * @param int $daysbeforeend Nb of days before end of subscription (negative number = after subscription)
  2244. * @return int 0 if OK, <>0 if KO (this function is used also by cron so only 0 is OK)
  2245. */
  2246. public function sendReminderForExpiredSubscription($daysbeforeend=10)
  2247. {
  2248. global $conf, $langs, $mysoc, $user;
  2249. $error = 0;
  2250. $this->output = '';
  2251. $this->error='';
  2252. $blockingerrormsg = '';
  2253. /*if (empty($conf->global->MEMBER_REMINDER_EMAIL))
  2254. {
  2255. $langs->load("agenda");
  2256. $this->output = $langs->trans('EventRemindersByEmailNotEnabled', $langs->transnoentitiesnoconv("Adherent"));
  2257. return 0;
  2258. }*/
  2259. $now = dol_now();
  2260. dol_syslog(__METHOD__, LOG_DEBUG);
  2261. $tmp=dol_getdate($now);
  2262. $datetosearchfor = dol_time_plus_duree(dol_mktime(0, 0, 0, $tmp['mon'], $tmp['mday'], $tmp['year']), -1 * $daysbeforeend, 'd');
  2263. $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'adherent';
  2264. $sql.= " WHERE datefin = '".$this->db->idate($datetosearchfor)."'";
  2265. $resql = $this->db->query($sql);
  2266. if ($resql)
  2267. {
  2268. $num_rows = $this->db->num_rows($resql);
  2269. include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
  2270. $adherent = new Adherent($this->db);
  2271. $formmail = new FormMail($this->db);
  2272. $i=0;
  2273. $nbok = 0;
  2274. $nbko = 0;
  2275. while ($i < $num_rows)
  2276. {
  2277. $obj = $this->db->fetch_object($resql);
  2278. $adherent->fetch($obj->rowid);
  2279. if (empty($adherent->email))
  2280. {
  2281. $nbko++;
  2282. }
  2283. else
  2284. {
  2285. $adherent->fetch_thirdparty();
  2286. // Send reminder email
  2287. $outputlangs = new Translate('', $conf);
  2288. $outputlangs->setDefaultLang(empty($adherent->thirdparty->default_lang) ? $mysoc->default_lang : $adherent->thirdparty->default_lang);
  2289. $outputlangs->loadLangs(array("main", "members"));
  2290. $arraydefaultmessage=null;
  2291. $labeltouse = $conf->global->ADHERENT_EMAIL_TEMPLATE_REMIND_EXPIRATION;
  2292. if (! empty($labeltouse)) $arraydefaultmessage=$formmail->getEMailTemplate($this->db, 'member', $user, $outputlangs, 0, 1, $labeltouse);
  2293. if (! empty($labeltouse) && is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0)
  2294. {
  2295. $substitutionarray=getCommonSubstitutionArray($outputlangs, 0, null, $adherent);
  2296. //if (is_array($adherent->thirdparty)) $substitutionarraycomp = ...
  2297. complete_substitutions_array($substitutionarray, $outputlangs, $adherent);
  2298. $subject = make_substitutions($arraydefaultmessage->topic, $substitutionarray, $outputlangs);
  2299. $msg = make_substitutions($arraydefaultmessage->content, $substitutionarray, $outputlangs);
  2300. $from = $conf->global->ADHERENT_MAIL_FROM;
  2301. $to = $adherent->email;
  2302. include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
  2303. $cmail = new CMailFile($subject, $to, $from, $msg, array(), array(), array(), '', '', 0, 1);
  2304. $result = $cmail->sendfile();
  2305. if (! $result)
  2306. {
  2307. $error++;
  2308. $this->error = $cmail->error;
  2309. $this->errors += $cmail->errors;
  2310. $nbko++;
  2311. }
  2312. else
  2313. {
  2314. $nbok++;
  2315. }
  2316. }
  2317. else
  2318. {
  2319. $blockingerrormsg="Can't find email template, defined into member module setup, to use for reminding";
  2320. $nbko++;
  2321. break;
  2322. }
  2323. }
  2324. $i++;
  2325. }
  2326. }
  2327. else
  2328. {
  2329. $this->error = $this->db->lasterror();
  2330. return 1;
  2331. }
  2332. if ($blockingerrormsg)
  2333. {
  2334. $this->error = $blockingerrormsg;
  2335. return 1;
  2336. }
  2337. else
  2338. {
  2339. $this->output = 'Found '.($nbok + $nbko).' members to send reminder to.';
  2340. $this->output.= ' Send email successfuly to '.$nbok.' members';
  2341. if ($nbko) $this->output.= ' - Canceled for '.$nbko.' member (no email or email sending error)';
  2342. }
  2343. return 0;
  2344. }
  2345. }