adherent.class.php 95 KB

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