dolibarr 23.0.3
new.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2001-2002 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2001-2002 Jean-Louis Bergamo <jlb@j1b.org>
4 * Copyright (C) 2006-2013 Laurent Destailleur <eldy@users.sourceforge.net>
5 * Copyright (C) 2012 Regis Houssin <regis.houssin@inodbox.com>
6 * Copyright (C) 2012 J. Fernando Lagrange <fernando@demo-tic.org>
7 * Copyright (C) 2018-2025 Frédéric France <frederic.france@free.fr>
8 * Copyright (C) 2018 Alexandre Spangaro <aspangaro@open-dsi.fr>
9 * Copyright (C) 2021 Waël Almoman <info@almoman.com>
10 * Copyright (C) 2022 Udo Tamm <dev@dolibit.de>
11 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program. If not, see <https://www.gnu.org/licenses/>.
25 */
26
43if (!defined('NOLOGIN')) {
44 define("NOLOGIN", 1); // This means this output page does not require to be logged.
45}
46if (!defined('NOCSRFCHECK')) {
47 define("NOCSRFCHECK", 1); // We accept to go on this page from external web site.
48}
49if (!defined('NOBROWSERNOTIF')) {
50 define('NOBROWSERNOTIF', '1');
51}
52
53
54// For MultiCompany module.
55// Do not use GETPOST here, function is not defined and define must be done before including main.inc.php
56// Because 2 entities can have the same ref.
57$entity = (!empty($_GET['entity']) ? (int) $_GET['entity'] : (!empty($_POST['entity']) ? (int) $_POST['entity'] : 1));
58define("DOLENTITY", $entity);
59
60
61// Load Dolibarr environment
62require '../../main.inc.php';
71require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
72require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
73require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
74require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent_type.class.php';
75require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
76require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
77require_once DOL_DOCUMENT_ROOT.'/core/class/cunits.class.php';
78require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
79
80// Init vars
81$backtopage = GETPOST('backtopage', 'alpha');
82$action = GETPOST('action', 'aZ09');
83
84$errmsg = '';
85$num = 0;
86$error = 0;
87
88// Load translation files
89$langs->loadLangs(array("main", "members", "companies", "install", "other", "errors"));
90
91if (isModEnabled('multicompany')) {
92 force_switch_entity($entity);
93}
94
95// Security check
96if (!isModEnabled('member')) {
97 httponly_accessforbidden('Module Membership not enabled');
98}
99
100if (!getDolGlobalString('MEMBER_ENABLE_PUBLIC')) {
101 httponly_accessforbidden("Auto subscription form for public visitors has not been enabled");
102}
103
104// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
105$hookmanager->initHooks(array('publicnewmembercard', 'globalcard'));
106
107$extrafields = new ExtraFields($db);
108
109$object = new Adherent($db);
110
111$user->loadDefaultValues();
112
113$captchaobj = null;
114if (getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA_MEMBER')) {
115 require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
116 $captcha = getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA_HANDLER', 'standard');
117 // List of directories where we can find captcha handlers
118 $dirModCaptcha = array_merge(
119 array(
120 'main' => '/core/modules/security/captcha/'
121 ),
122 is_array($conf->modules_parts['captcha']) ? $conf->modules_parts['captcha'] : array()
123 );
124 $fullpathclassfile = '';
125 foreach ($dirModCaptcha as $dir) {
126 $fullpathclassfile = dol_buildpath($dir."modCaptcha".ucfirst($captcha).'.class.php', 0, 2);
127 if ($fullpathclassfile) {
128 break;
129 }
130 }
131 if ($fullpathclassfile) {
132 include_once $fullpathclassfile;
133 // Charging the numbering class
134 $classname = "modCaptcha".ucfirst($captcha);
135 if (class_exists($classname)) {
136 $captchaobj = new $classname($db, $conf, $langs, $user);
137 '@phan-var-force ModeleCaptcha $captchaobj';
139 } else {
140 print 'Error, the captcha handler class '.$classname.' was not found after the include';
141 }
142 } else {
143 print 'Error, the captcha handler '.$captcha.' has no class file found modCaptcha'.ucfirst($captcha);
144 }
145}
146
154function force_switch_entity($newEntity)
155{
156 global $db, $conf;
157
158 if ($newEntity != $conf->entity) {
159 $conf->entity = $newEntity;
160 $conf->setValues($db);
161 }
162}
163
177function llxHeaderVierge($title, $head = "", $disablejs = 0, $disablehead = 0, $arrayofjs = [], $arrayofcss = []) // @phan-suppress-current-line PhanRedefineFunction
178{
179 global $conf, $langs, $mysoc;
180
181 top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss); // Show html headers
182
183 print '<body id="mainbody" class="publicnewmemberform">';
184
185 include_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
186 htmlPrintOnlineHeader($mysoc, $langs, 1, getDolGlobalString('MEMBER_PUBLIC_INTERFACE'), 'MEMBER_IMAGE_PUBLIC_REGISTRATION');
187
188 print '<div class="divmainbodylarge">';
189}
190
198function llxFooterVierge() // @phan-suppress-current-line PhanRedefineFunction
199{
200 global $conf, $langs;
201
202 print '</div>';
203
204 printCommonFooter('public');
205
206 if (!empty($conf->use_javascript_ajax)) {
207 print "\n".'<!-- Includes JS Footer of Dolibarr -->'."\n";
208 print '<script src="'.DOL_URL_ROOT.'/core/js/lib_foot.js.php?lang='.$langs->defaultlang.'"></script>'."\n";
209 }
210
211 print "</body>\n";
212 print "</html>\n";
213}
214
215
216
217/*
218 * Actions
219 */
220
221$parameters = array();
222// Note that $action and $object may have been modified by some hooks
223$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action);
224if ($reshook < 0) {
225 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
226}
227
228// Verify if we can find member
229
230if (empty($reshook) && getDolGlobalInt("MEMBER_SEARCH_MEMBER_PUBLIC_FORM_CREATE") && $action == 'add' && !GETPOSTISSET("nofetchmember")) { // Test on permission not required here
231 $memberfound = false;
232
233 if (!getDolGlobalString('ADHERENT_LOGIN_NOT_REQUIRED') && GETPOSTISSET('login')) {
234 // Note that this allow to guess anonymous ID already used. But this is not a problem as it is an anonymous pseudonym.
235 // If we try to new account and option MEMBER_SEARCH_MEMBER_PUBLIC_FORM_CREATE was off, we also get the same error.
236 $sql = "SELECT rowid as id";
237 $sql .= " FROM ".MAIN_DB_PREFIX."adherent as a";
238 $sql .= " WHERE a.login = '".$db->escape(GETPOST('login'))."'";
239 $sql .= " AND statut = 1";
240 $sql .= " AND entity IN (".getEntity($object->element).")";
241 $resql = $db->query($sql);
242 if ($resql) {
243 if ($db->num_rows($resql) == 1) {
244 $obj = $db->fetch_object($resql);
245 $object->fetch($obj->id);
246 $memberfound = true;
247 }
248 } else {
249 dol_print_error($db);
250 }
251 }
252
253 if (!$memberfound && GETPOST("morphy") == 'mor' && GETPOSTISSET("societe") ) {
254 $sql = "SELECT a.rowid as id";
255 $sql .= " FROM ".MAIN_DB_PREFIX."adherent as a";
256 $sql .= " JOIN ".MAIN_DB_PREFIX."societe as s";
257 $sql .= " ON a.fk_soc = s.rowid";
258 $sql .= " WHERE s.nom = '".$db->escape(GETPOST("societe", 'alphanohtml'))."'";
259 $sql .= " AND a.email = '".$db->escape(preg_replace('/\s+/', '', GETPOST("member_email", 'aZ09arobase')))."'";
260 $sql .= " AND a.statut = 1";
261 $sql .= " AND a.entity IN (".getEntity($object->element).")";
262 $resql = $db->query($sql);
263 if ($resql) {
264 if ($db->num_rows($resql) == 1) {
265 $obj = $db->fetch_object($resql);
266 $object->fetch($obj->id);
267 $memberfound = true;
268 }
269 } else {
270 dol_print_error($db);
271 }
272 }
273
274 if (!$memberfound && GETPOST("morphy") == 'phy' && GETPOSTISSET("lastname") && GETPOSTISSET("firstname") && !empty(GETPOST("member_email", 'aZ09arobase'))) {
275 $sql = "SELECT rowid as id";
276 $sql .= " FROM ".MAIN_DB_PREFIX."adherent";
277 $sql .= " WHERE firstname = '".$db->escape(GETPOST("firstname", 'alphanohtml'))."'";
278 $sql .= " AND lastname = '".$db->escape(GETPOST("lastname", 'alphanohtml'))."'";
279 $sql .= " AND email = '".$db->escape(preg_replace('/\s+/', '', GETPOST("member_email", 'aZ09arobase')))."'";
280 $sql .= " AND statut = 1";
281 $sql .= " AND entity IN (".getEntity($object->element).")";
282 $resql = $db->query($sql);
283 if ($resql) {
284 if ($db->num_rows($resql) == 1) {
285 $obj = $db->fetch_object($resql);
286 $object->fetch($obj->id);
287 $memberfound = true;
288 }
289 } else {
290 dol_print_error($db);
291 }
292 }
293
294 if ($memberfound) {
295 $action = 'subscription';
296 }
297}
298
299// Action called when page is submitted
300if (empty($reshook) && $action == 'add') { // Test on permission not required here. This is an anonymous form. Check is done on constant to enable and mitigation.
301 $error = 0;
302 $urlback = '';
303
304 $db->begin();
305
306 $morphy = GETPOST("morphy", 'alphanohtml');
307 $lastname = GETPOST("lastname", 'alphanohtml');
308 $firstname = GETPOST("firstname", 'alphanohtml');
309 $societe = GETPOST("societe", 'alphanohtml');
310 $email = preg_replace('/\s+/', '', GETPOST("member_email", 'aZ09arobase'));
311 $country_id = getDolGlobalInt("MEMBER_NEWFORM_FORCECOUNTRYCODE", GETPOSTINT('country_id'));
312
313 if (!in_array($morphy, array('mor', 'phy'))) {
314 $error++;
315 $errmsg .= $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv('MemberNature'))."<br>\n";
316 }
317
318 // test if login already exists
319 if (!getDolGlobalString('ADHERENT_LOGIN_NOT_REQUIRED')) {
320 if (!GETPOST('member_email')) {
321 $error++;
322 $errmsg .= $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("EMail"))."<br>\n";
323 }
324 if (!GETPOST('login')) {
325 $error++;
326 $errmsg .= $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Login"))."<br>\n";
327 }
328 $sql = "SELECT login FROM ".MAIN_DB_PREFIX."adherent WHERE login = '".$db->escape(GETPOST('login'))."'";
329 $result = $db->query($sql);
330 if ($result) {
331 $num = $db->num_rows($result);
332 }
333 if ($num != 0) {
334 $error++;
335 $langs->load("errors");
336 $errmsg .= $langs->trans("ErrorLoginAlreadyExists")."<br>\n";
337 }
338 if (!GETPOSTISSET("pass1") || !GETPOSTISSET("pass2") || GETPOST("pass1", 'none') == '' || GETPOST("pass2", 'none') == '' || GETPOST("pass1", 'none') != GETPOST("pass2", 'none')) {
339 $error++;
340 $langs->load("errors");
341 $errmsg .= $langs->trans("ErrorPasswordsMustMatch")."<br>\n";
342 }
343 }
344 if (GETPOST('typeid') <= 0) {
345 $error++;
346 $errmsg .= $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type"))."<br>\n";
347 }
348
349 if ($morphy && $morphy != 'mor' && empty($lastname)) {
350 $error++;
351 $langs->load("errors");
352 $errmsg .= $langs->trans("ErrorFieldRequired", $langs->transnoentities("Lastname"));
353 }
354 if ($morphy && $morphy != 'mor' && (!isset($firstname) || $firstname == '')) {
355 $error++;
356 $langs->load("errors");
357 $errmsg .= $langs->trans("ErrorFieldRequired", $langs->transnoentities("Firstname"));
358 }
359 if ($morphy == 'mor' && empty($societe)) {
360 $error++;
361 $langs->load("errors");
362 $errmsg .= $langs->trans("ErrorFieldRequired", $langs->transnoentities("Company"));
363 }
364 if (empty($country_id)) {
365 $error++;
366 $langs->load("errors");
367 $errmsg .= $langs->trans("ErrorFieldRequired", $langs->transnoentities("Country"));
368 }
369 if (getDolGlobalString('ADHERENT_MAIL_REQUIRED') && $email && !isValidEmail($email)) {
370 $error++;
371 $langs->load("errors");
372 $errmsg .= $langs->trans("ErrorBadEMail", $email);
373 }
374 $birthday = dol_mktime(GETPOSTINT("birthhour"), GETPOSTINT("birthmin"), GETPOSTINT("birthsec"), GETPOSTINT("birthmonth"), GETPOSTINT("birthday"), GETPOSTINT("birthyear"));
375 if (GETPOST("birthmonth") && empty($birthday)) {
376 $error++;
377 $langs->load("errors");
378 $errmsg .= $langs->trans("ErrorBadDateFormat")."<br>\n";
379 }
380
381 // TODO Add this in a hook
382 if (getDolGlobalString('MEMBER_NEWFORM_DOLIBARRTURNOVER')) {
383 if (GETPOST("morphy") == 'mor' && GETPOSTFLOAT('budget') <= 0) {
384 $error++;
385 $errmsg .= $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("TurnoverOrBudget"))."<br>\n";
386 }
387 }
388
389 // Check Captcha code if is enabled
390 $ok = false;
391 if (getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA_MEMBER') && is_object($captchaobj)) {
392 if (method_exists($captchaobj, 'validateCodeAfterLoginSubmit')) {
393 $ok = $captchaobj->validateCodeAfterLoginSubmit(); // @phan-suppress-current-line PhanUndeclaredMethod
394 } else {
395 print 'Error, the captcha handler '.get_class($captchaobj).' does not have any method validateCodeAfterLoginSubmit()';
396 }
397 if (!$ok) {
398 $error++;
399 $langs->load("errors");
400 $errmsg .= $langs->trans("ErrorBadValueForCode")."<br>\n";
401 $action = '';
402 }
403 }
404
405 $public = GETPOSTISSET('public') ? 1 : 0;
406
407 if (!$error) {
408 // E-mail looks OK and login does not exist
409 $adh = new Adherent($db);
410 $adh->statut = -1;
411 $adh->status = -1;
412 $adh->public = $public;
413 $adh->firstname = GETPOST('firstname');
414 $adh->lastname = GETPOST('lastname');
415 $adh->gender = GETPOST('gender');
416 $adh->civility_id = GETPOST('civility_id');
417 $adh->company = GETPOST('societe');
418 $adh->societe = $adh->company;
419 $adh->address = GETPOST('address');
420 $adh->zip = GETPOST('zipcode');
421 $adh->town = GETPOST('town');
422 $adh->email = GETPOST('member_email', 'aZ09arobase');
423 if (!getDolGlobalString('ADHERENT_LOGIN_NOT_REQUIRED')) {
424 $adh->login = GETPOST('login');
425 $adh->pass = GETPOST('pass1', 'password');
426 }
427 $adh->photo = GETPOST('photo');
428 $adh->country_id = getDolGlobalInt("MEMBER_NEWFORM_FORCECOUNTRYCODE", GETPOSTINT('country_id'));
429 $adh->state_id = GETPOSTINT('state_id');
430 $adh->typeid = getDolGlobalInt("MEMBER_NEWFORM_FORCETYPE", GETPOSTINT('typeid'));
431 $adh->note_private = GETPOST('note_private');
432 $adh->morphy = getDolGlobalString("MEMBER_NEWFORM_FORCEMORPHY", GETPOST('morphy'));
433 $adh->birth = $birthday;
434 $adh->phone = GETPOST('phone');
435 $adh->phone_perso = GETPOST('phone_perso');
436 $adh->phone_mobile= GETPOST('phone_mobile');
437
438 $adh->ip = getUserRemoteIP();
439
440 $nb_post_max = getDolGlobalInt("MAIN_SECURITY_MAX_POST_ON_PUBLIC_PAGES_BY_IP_ADDRESS", 200);
441 $now = dol_now();
442 $minmonthpost = dol_time_plus_duree($now, -1, "m");
443 // Calculate nb of post for IP
444 $nb_post_ip = 0;
445 if ($nb_post_max > 0) { // Calculate only if there is a limit to check
446 $sql = "SELECT COUNT(ref) as nb_adh";
447 $sql .= " FROM ".MAIN_DB_PREFIX."adherent";
448 $sql .= " WHERE ip = '".$db->escape($adh->ip)."'";
449 $sql .= " AND datec > '".$db->idate($minmonthpost)."'";
450 $resql = $db->query($sql);
451 if ($resql) {
452 $num = $db->num_rows($resql);
453 $i = 0;
454 while ($i < $num) {
455 $i++;
456 $obj = $db->fetch_object($resql);
457 $nb_post_ip = $obj->nb_adh;
458 }
459 }
460 }
461
462
463 // Fill array 'array_options' with data from add form
464 $extrafields->fetch_name_optionals_label($adh->table_element);
465 $ret = $extrafields->setOptionalsFromPost(null, $adh);
466 if ($ret < 0) {
467 $error++;
468 $errmsg .= $adh->error;
469 }
470
471 if ($nb_post_max > 0 && $nb_post_ip >= $nb_post_max) {
472 $error++;
473 $errmsg .= $langs->trans("AlreadyTooMuchPostOnThisIPAdress");
474 array_push($adh->errors, $langs->trans("AlreadyTooMuchPostOnThisIPAdress"));
475 }
476
477 if (!$error) {
478 $result = $adh->create($user);
479 if ($result > 0) {
480 require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
481 $object = $adh;
482
483 $adht = new AdherentType($db);
484 $adht->fetch($object->typeid);
485
486 if ($object->email) {
487 $subject = '';
488 $msg = '';
489
490 // Send subscription email
491 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
492 $formmail = new FormMail($db);
493 // Set output language
494 $outputlangs = new Translate('', $conf);
495 $outputlangs->setDefaultLang(empty($object->thirdparty->default_lang) ? $mysoc->default_lang : $object->thirdparty->default_lang);
496 // Load traductions files required by page
497 $outputlangs->loadLangs(array("main", "members"));
498 // Get email content from template
499 $arraydefaultmessage = null;
500 $labeltouse = getDolGlobalString('ADHERENT_EMAIL_TEMPLATE_AUTOREGISTER');
501
502 if (!empty($labeltouse)) {
503 $arraydefaultmessage = $formmail->getEMailTemplate($db, 'member', $user, $outputlangs, 0, 1, $labeltouse);
504 }
505
506 if (!empty($labeltouse) && is_object($arraydefaultmessage) && $arraydefaultmessage->id > 0) {
507 $subject = $arraydefaultmessage->topic;
508 $msg = $arraydefaultmessage->content;
509 }
510
511 $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $object);
512 complete_substitutions_array($substitutionarray, $outputlangs, $object);
513 $subjecttosend = make_substitutions($subject, $substitutionarray, $outputlangs);
514 $texttosend = make_substitutions(dol_concatdesc($msg, $adht->getMailOnValid()), $substitutionarray, $outputlangs);
515
516 if ($subjecttosend && $texttosend) {
517 $moreinheader = 'X-Dolibarr-Info: send_an_email by public/members/new.php'."\r\n";
518
519 $result = $object->sendEmail($texttosend, $subjecttosend, array(), array(), array(), "", "", 0, -1, '', $moreinheader);
520 }
521 /*if ($result < 0) {
522 $error++;
523 setEventMessages($object->error, $object->errors, 'errors');
524 }*/
525 }
526
527 // Send email to the foundation to say a new member subscribed with autosubscribe form
528 if (getDolGlobalString('MAIN_INFO_SOCIETE_MAIL') && getDolGlobalString('ADHERENT_AUTOREGISTER_NOTIF_MAIL_SUBJECT') &&
529 getDolGlobalString('ADHERENT_AUTOREGISTER_NOTIF_MAIL')) {
530 // Define link to login card
531 $appli = constant('DOL_APPLICATION_TITLE');
532 if (getDolGlobalString('MAIN_APPLICATION_TITLE')) {
533 $appli = getDolGlobalString('MAIN_APPLICATION_TITLE');
534 if (preg_match('/\d\.\d/', $appli)) {
535 if (!preg_match('/'.preg_quote(DOL_VERSION, '/').'/', $appli)) {
536 $appli .= " (".DOL_VERSION.")"; // If new title contains a version that is different than core
537 }
538 } else {
539 $appli .= " ".DOL_VERSION;
540 }
541 } else {
542 $appli .= " ".DOL_VERSION;
543 }
544
545 $to = $adh->makeSubstitution(getDolGlobalString('MAIN_INFO_SOCIETE_MAIL'));
546 $from = getDolGlobalString('ADHERENT_MAIL_FROM', $conf->email_from);
547 $mailfile = new CMailFile(
548 '['.$appli.'] ' . getDolGlobalString('ADHERENT_AUTOREGISTER_NOTIF_MAIL_SUBJECT'),
549 $to,
550 $from,
551 $adh->makeSubstitution(getDolGlobalString('ADHERENT_AUTOREGISTER_NOTIF_MAIL')),
552 array(),
553 array(),
554 array(),
555 "",
556 "",
557 0,
558 -1
559 );
560
561 if (!$mailfile->sendfile()) {
562 dol_syslog($langs->trans("ErrorFailedToSendMail", $from, $to), LOG_ERR);
563 }
564 }
565
566 // Auto-create thirdparty on member creation
567 if (getDolGlobalString('ADHERENT_DEFAULT_CREATE_THIRDPARTY')) {
568 $company = new Societe($db);
569 $result = $company->create_from_member($adh);
570 if ($result < 0) {
571 $error++;
572 $errmsg .= implode('<br>', $company->errors);
573 }
574 }
575
576 if (!empty($backtopage)) {
577 $urlback = $backtopage;
578 } elseif (getDolGlobalString('MEMBER_URL_REDIRECT_SUBSCRIPTION')) {
579 $urlback = getDolGlobalString('MEMBER_URL_REDIRECT_SUBSCRIPTION');
580 // TODO Make replacement of __AMOUNT__, etc...
581 } else {
582 $urlback = $_SERVER["PHP_SELF"]."?action=added&token=".newToken();
583 }
584
585 if (getDolGlobalString('MEMBER_NEWFORM_PAYONLINE') && getDolGlobalString('MEMBER_NEWFORM_PAYONLINE') != '-1') {
586 if (empty($adht->caneditamount)) { // If edition of amount not allowed
587 // TODO Check amount is same than the amount required for the type of member or if not defined as the default amount into $conf->global->MEMBER_NEWFORM_AMOUNT
588 // It is not so important because a test is done on return of payment validation.
589 }
590
591 $urlback = getOnlinePaymentUrl(0, 'member', $adh->ref, (float) price2num(GETPOST('amount', 'alpha'), 'MT'), '', 0);
592
593 if (GETPOST('member_email')) {
594 $urlback .= '&email='.urlencode(GETPOST('member_email'));
595 }
596 if (getDolGlobalString('MEMBER_NEWFORM_PAYONLINE') != '-1' && getDolGlobalString('MEMBER_NEWFORM_PAYONLINE') != 'all') {
597 $urlback .= '&paymentmethod='.urlencode(getDolGlobalString('MEMBER_NEWFORM_PAYONLINE'));
598 }
599 } else {
600 if (!empty($entity)) {
601 $urlback .= '&entity='.((int) $entity);
602 }
603 }
604 } else {
605 $error++;
606 $errmsg .= implode('<br>', $adh->errors);
607 }
608 }
609 }
610
611 if (!$error) {
612 $db->commit();
613
614 header("Location: ".$urlback);
615 exit;
616 } else {
617 $db->rollback();
618 $action = "create";
619 }
620}
621
622// Action called after a submitted was send and member created successfully
623// If MEMBER_URL_REDIRECT_SUBSCRIPTION is set to an url, we never go here because a redirect was done to this url. Same if we ask to redirect to the payment page.
624// backtopage parameter with an url was set on member submit page, we never go here because a redirect was done to this url.
625
626if (empty($reshook) && $action == 'added') { // Test on permission not required here
627 llxHeaderVierge($langs->trans("NewMemberForm"));
628
629 // If we have not been redirected
630 print '<br><br>';
631 print '<div class="center">';
632 print $langs->trans("NewMemberbyWeb");
633 print '</div>';
634
636 exit;
637}
638
639
640/*
641 * View
642 */
643
644$form = new Form($db);
645$formcompany = new FormCompany($db);
646$adht = new AdherentType($db);
647$extrafields->fetch_name_optionals_label($object->table_element); // fetch optionals attributes and labels
648
649
650llxHeaderVierge($langs->trans("NewSubscription"));
651
652print '<br>';
653print load_fiche_titre(img_picto('', 'member_nocolor', 'class="pictofixedwidth"').' &nbsp; '.$langs->trans("NewSubscription"), '', '', 0, '', 'center');
654
655
656print '<div align="center">';
657print '<div id="divsubscribe">';
658
659print '<div class="center subscriptionformhelptext opacitymedium justify">';
660if (getDolGlobalString('MEMBER_NEWFORM_TEXT')) {
661 print $langs->trans(getDolGlobalString('MEMBER_NEWFORM_TEXT'))."<br>\n";
662} else {
663 print $langs->trans("NewSubscriptionDesc", getDolGlobalString("MAIN_INFO_SOCIETE_MAIL"))."<br>\n";
664}
665print '</div>';
666
667dol_htmloutput_errors($errmsg);
669
670if ($action == "subscription") {
671 $urltocall = DOL_URL_ROOT.'/public/payment/newpayment.php?source=member&ref='.$object->id;
672 print $form->formconfirm($urltocall, $langs->trans("CorrespondingMemberFound"), $langs->trans("CorrespondingMemberFoundQuestion"), "confirm_subscription", '', 'no', 1);
673}
674
675// Print form
676print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="newmember" id="newmember">'."\n";
677print '<input type="hidden" name="token" value="'.newToken().'" />';
678print '<input type="hidden" name="entity" value="'.$entity.'" />';
679print '<input type="hidden" name="page_y" value="" />';
680
681if (getDolGlobalString('MEMBER_SKIP_TABLE') || getDolGlobalString('MEMBER_NEWFORM_FORCETYPE') || in_array($action, array('create', 'subscription'))) {
682 if ($action == 'subscription') {
683 print '<input type="hidden" name="nofetchmember" value="nofetchmember" />';
684 }
685 print '<input type="hidden" name="action" value="add" />';
686 print '<br>';
687
688 //$messagemandatory = '<span class="">'.$langs->trans("FieldsWithAreMandatory", '*').'</span>';
689 //print '<br>'.$messagemandatory.'<br>';
690 //print $langs->trans("FieldsWithIsForPublic",'**').'<br>';
691
692 print dol_get_fiche_head();
693
694 if ($conf->use_javascript_ajax) {
695 print "\n".'<script type="text/javascript">'."\n";
696 print 'jQuery(document).ready(function () {
697 jQuery("#selectcountry_id").change(function() {
698 console.log("We change country, so we reload page");
699 document.newmember.action.value="create";
700 jQuery("#newmember").submit();
701 });
702 function initfieldrequired() {
703 console.log("initfieldrequired");
704 jQuery("#tdcompany").removeClass("fieldrequired");
705 jQuery("#tdlastname").removeClass("fieldrequired");
706 jQuery("#tdfirstname").removeClass("fieldrequired");
707 if (jQuery(\'input[name="morphy"]:checked\').val() == \'mor\') {
708 jQuery("#tdcompany").addClass("fieldrequired");
709 }
710 if (jQuery(\'input[name="morphy"]:checked\').val() == \'phy\') {
711 jQuery("#tdlastname").addClass("fieldrequired");
712 jQuery("#tdfirstname").addClass("fieldrequired");
713 }
714 }
715 jQuery(\'input[name="morphy"]\').change(function() {
716 initfieldrequired();
717 });
718 initfieldrequired();
719 })';
720 print '</script>'."\n";
721 }
722
723 print '<table class="border" summary="form to subscribe" id="tablesubscribe">'."\n";
724
725 // Type
726 if (!getDolGlobalString('MEMBER_NEWFORM_FORCETYPE')) {
727 $typeid = GETPOSTINT("typeid");
728 print '<tr><td class="fieldrequired titlefieldmiddle">'.$langs->trans("MemberType").'</td><td>';
729 $listetype = $adht->liste_array(1);
730 print img_picto('', $adht->picto, 'class="pictofixedwidth"');
731 if (count($listetype)) {
732 print $form->selectarray("typeid", $listetype, (GETPOSTINT('typeid') ? GETPOSTINT('typeid') : $typeid), (count($listetype) > 1 ? 1 : 0), 0, 0, '', 0, 0, 0, '', 'minwidth150 maxwidth300 widthcentpercentminusx', 1);
733 } else {
734 print '<span class="error">'.$langs->trans("NoTypeDefinedGoToSetup").'</span>';
735 }
736 print '</td></tr>'."\n";
737 } else {
738 $adht->fetch(getDolGlobalInt('MEMBER_NEWFORM_FORCETYPE'));
739 print '<input type="hidden" id="typeid" name="typeid" value="' . getDolGlobalString('MEMBER_NEWFORM_FORCETYPE').'">';
740 }
741
742 // Moral/Physic attribute
743 $morphys = [
744 "phy" => $langs->trans("Physical"),
745 "mor" => $langs->trans("Moral"),
746 ];
747 $checkednature = GETPOST("morphy", 'alpha');
748 $listetype_natures = $adht->morphyByType(1); // Load the array of morphy per typeof membership
749 $listetype_natures_json = json_encode($listetype_natures);
750
751 if (!getDolGlobalString('MEMBER_NEWFORM_FORCEMORPHY')) {
752 if (empty($checkednature) && !empty($listetype_natures[GETPOSTINT('typeid')])) {
753 $checkednature = $listetype_natures[GETPOSTINT('typeid')];
754 }
755
756 print '<tr><td class="fieldrequired titlefieldmiddle">'.$langs->trans("MemberNature")."</td><td>\n";
757
758 $disabledphy = '';
759 $disabledmor = '';
760 //$disabledphy = ($checkednature == "mor" ? ' disabled="disabled"' : '');
761 //$disabledmor = ($checkednature == "phy" ? ' disabled="disabled"' : '');
762 print '<span id="spannature1" class="nonature-back spannature paddinglarge marginrightonly"><label for="phisicalinput" class="valignmiddle">'.$morphys["phy"].'<input id="phisicalinput" class="flat checkforselect marginleftonly valignmiddle" type="radio" name="morphy" value="phy"'.($checkednature == "phy" ? ' checked="checked"' : '').$disabledphy.'></label></span>';
763 print '<span id="spannature2" class="nonature-back spannature paddinglarge marginrightonly"><label for="moralinput" class="valignmiddle">'.$morphys["mor"].'<input id="moralinput" class="flat checkforselect marginleftonly valignmiddle" type="radio" name="morphy" value="mor"'.($checkednature == "mor" ? ' checked="checked"' : '').$disabledmor.'></label></span>';
764
765 // Add JS to manage the background of nature
766 if ($conf->use_javascript_ajax) {
767 print '<script>
768 var listetype_natures = '.$listetype_natures_json.';
769
770 jQuery(function($) {
771 function refreshNatureCss() {
772 $(".spannature").each(function(index) {
773 let $span = $("#spannature" + (index + 1));
774 let checked = $span.find(".checkforselect").is(":checked");
775
776 if (checked) {
777 if (index === 0) {
778 $span.addClass("member-individual-back").removeClass("nonature-back member-company-back");
779 } else if (index === 1) {
780 $span.addClass("member-company-back").removeClass("nonature-back member-individual-back");
781 }
782 } else {
783 $span.removeClass("member-individual-back member-company-back")
784 .addClass("nonature-back");
785 }
786 });
787 }
788
789 $(".spannature").on("click", function() {
790 console.log("Nature clicked");
791 refreshNatureCss();
792 });
793
794 $("#typeid").on("change", function() {
795 console.log("Type of membership is modified");
796 let morphy = listetype_natures[$(this).val()];
797 console.log("morphy="+morphy);
798
799 let $phyInput = $("#phisicalinput");
800 let $morInput = $("#moralinput");
801 let $tdLast = $("#tdlastname");
802 let $tdFirst = $("#tdfirstname");
803 let $tdCompany = $("#tdcompany");
804 let $span1 = $("#spannature1");
805 let $span2 = $("#spannature2");
806
807 switch (morphy) {
808 case "phy":
809 /* $phyInput.prop({disabled: false, checked: true});
810 $morInput.prop({disabled: true, checked: false}); */
811 $span1.addClass("member-individual-back").removeClass("nonature-back");
812 $span2.removeClass("member-company-back").addClass("nonature-back");
813 $("#phisicalinput").prop("checked", true);
814 $tdLast.addClass("fieldrequired");
815 $tdFirst.addClass("fieldrequired");
816 $tdCompany.removeClass("fieldrequired");
817 break;
818
819 case "mor":
820 /* $phyInput.prop({disabled: true, checked: false});
821 $morInput.prop({disabled: false, checked: true}); */
822 $span2.addClass("member-company-back").removeClass("nonature-back");
823 $span1.removeClass("member-individual-back").addClass("nonature-back");
824 $("#moralinput").prop("checked", true);
825 $tdCompany.addClass("fieldrequired");
826 $tdLast.removeClass("fieldrequired");
827 $tdFirst.removeClass("fieldrequired");
828 break;
829
830 default:';
831 if ($action != "subscription" && !GETPOST('morphy')) {
832 print '
833 $phyInput.prop({disabled: false, checked: false});
834 $morInput.prop({disabled: false, checked: false});
835 $span1.removeClass("member-individual-back").addClass("nonature-back");
836 $span2.removeClass("member-company-back").addClass("nonature-back");';
837 }
838 print'}
839 });
840
841 // Initial state
842 refreshNatureCss();
843 });
844 </script>';
845 }
846 print '</td></tr>'."\n";
847 } else {
848 //print $morphys[$conf->global->MEMBER_NEWFORM_FORCEMORPHY];
849 print '<input type="hidden" id="morphy" name="morphy" value="' . getDolGlobalString('MEMBER_NEWFORM_FORCEMORPHY').'">';
850 }
851
852 // Company // TODO : optional hide
853 print '<tr id="trcompany" class="trcompany"><td id="tdcompany" class="titlefieldmiddle paddingrightonly'.($checkednature == "mor" ? ' fieldrequired"' : '').'">'.$langs->trans("Company").'</td><td>';
854 print img_picto('', 'company', 'class="pictofixedwidth paddingright"');
855 print '<input type="text" name="societe" class="minwidth150 widthcentpercentminusx" value="'.dol_escape_htmltag(GETPOST('societe')).'"></td></tr>'."\n";
856
857 // Title
858 if (getDolGlobalString('MEMBER_NEWFORM_ASK_TITLE')) {
859 print '<tr><td>'.$langs->trans('UserTitle').'</td><td>';
860 print $formcompany->select_civility(GETPOST('civility_id'), 'civility_id').'</td></tr>'."\n";
861 }
862
863 // Firstname
864 print '<tr><td id="tdfirstname" class="classfortooltip'.($checkednature == "phy" ? ' fieldrequired"' : '').'">'.$langs->trans("Firstname").'</td><td><input type="text" name="firstname" class="minwidth150" value="'.dol_escape_htmltag(GETPOST('firstname')).'" spellcheck="false"></td></tr>'."\n";
865
866 // Lastname
867 print '<tr><td id="tdlastname" class="classfortooltip'.($checkednature == "phy" ? ' fieldrequired"' : '').'">'.$langs->trans("Lastname").'</td><td><input type="text" name="lastname" class="minwidth150" value="'.dol_escape_htmltag(GETPOST('lastname')).'" spellcheck="false"></td></tr>'."\n";
868
869 // EMail
870 print '<tr><td>'.(getDolGlobalString('ADHERENT_MAIL_REQUIRED') ? '<span class="fieldrequired">' : '').$langs->trans("EMail").(getDolGlobalString('ADHERENT_MAIL_REQUIRED') ? '</span>' : '').'</td>';
871 print '<td>'.img_picto('', 'object_email').' <input type="text" name="member_email" class="minwidth150 maxwidth300 widthcentpercentminusx" maxlength="255" value="'.dol_escape_htmltag(GETPOST('member_email', "aZ09arobase")).'" spellcheck="false"></td></tr>'."\n";
872
873 // Login
874 if (!getDolGlobalString('ADHERENT_LOGIN_NOT_REQUIRED')) {
875 print '<tr><td><span class="fieldrequired">'.$langs->trans("Login").' / '.$langs->trans("Id").'</span></td><td><input type="text" name="login" maxlength="50" class="minwidth100" value="'.(GETPOSTISSET("login") ? GETPOST("login", 'alphanohtml', 2) : $object->login).'"></td></tr>'."\n";
876 print '<tr><td><span class="fieldrequired">'.$langs->trans("Password").'</span></td><td><input type="password" maxlength="128" name="pass1" class="minwidth100" value="'.dol_escape_htmltag(GETPOST("pass1", "none", 2)).'"></td></tr>'."\n";
877 print '<tr><td><span class="fieldrequired">'.$langs->trans("PasswordRetype").'</span></td><td><input type="password" maxlength="128" name="pass2" class="minwidth100" value="'.dol_escape_htmltag(GETPOST("pass2", "none", 2)).'"></td></tr>'."\n";
878 }
879
880 // Gender
881 print '<tr><td>'.$langs->trans("Gender").'</td>';
882 print '<td>';
883 $arraygender = array('man' => $langs->trans("Genderman"), 'woman' => $langs->trans("Genderwoman"), 'other' => $langs->trans("Genderother"));
884 print $form->selectarray('gender', $arraygender, GETPOST('gender', 'alphanohtml'), 1, 0, 0, '', 0, 0, 0, '', 'minwidth150 maxwidth300 widthcentpercentminusx', 1);
885 print '</td></tr>';
886
887 // Address
888 print '<tr><td>'.$langs->trans("Address").'</td><td>'."\n";
889 print '<textarea name="address" id="address" wrap="soft" class="quatrevingtpercent" rows="'.ROWS_3.'">'.dol_escape_htmltag(GETPOST('address', 'restricthtml'), 0, 1).'</textarea></td></tr>'."\n";
890
891 // Zip / Town
892 print '<tr><td>'.$langs->trans('Zip').' / '.$langs->trans('Town').'</td><td>';
893 print $formcompany->select_ziptown(GETPOST('zipcode'), 'zipcode', array('town', 'selectcountry_id', 'state_id'), 0, 1, '', 'width75');
894 print ' / ';
895 print $formcompany->select_ziptown(GETPOST('town'), 'town', array('zipcode', 'selectcountry_id', 'state_id'), 0, 1);
896 print '</td></tr>';
897
898 $country_id = GETPOSTINT('country_id');
899
900 // Country
901 print '<tr><td class="fieldrequired">'.$langs->trans('Country').'</td><td>';
902 print img_picto('', 'country', 'class="pictofixedwidth paddingright"');
903 if (!$country_id && getDolGlobalString('MEMBER_NEWFORM_FORCECOUNTRYCODE')) {
904 $country_id = getCountry(getDolGlobalString('MEMBER_NEWFORM_FORCECOUNTRYCODE'), '2', $db, $langs);
905 }
906 if (!$country_id && !empty($conf->geoipmaxmind->enabled)) {
907 $country_code = dol_user_country();
908 //print $country_code;
909 if ($country_code) {
910 $new_country_id = getCountry($country_code, '3', $db, $langs);
911 //print 'xxx'.$country_code.' - '.$new_country_id;
912 if ($new_country_id) {
913 $country_id = $new_country_id;
914 }
915 }
916 }
917 $country_code = getCountry($country_id, '2', $db, $langs);
918 print $form->select_country($country_id, 'country_id', '', 0, 'minwidth150 maxwidth300 widthcentpercentminusx reposition');
919 print '</td></tr>';
920
921 // State
922 if (!getDolGlobalString('SOCIETE_DISABLE_STATE')) {
923 print '<tr><td>'.$langs->trans('State').'</td><td>';
924 if ($country_code) {
925 print img_picto('', 'state', 'class="pictofixedwidth paddingright"');
926 print $formcompany->select_state(GETPOSTINT("state_id"), $country_code, 'state_id', 'minwidth150 maxwidth300 widthcentpercentminusx');
927 }
928 print '</td></tr>';
929 }
930
931 // Pro phone
932 print '<tr><td>'.$langs->trans("PhonePro").'</td>';
933 print '<td>'.img_picto('', 'object_phoning', 'class="pictofixedwidth"').'<input type="text" name="phone" class="maxwidth300 widthcentpercentminusx" value="'.dol_escape_htmltag(GETPOST('phone')).'"></td></tr>';
934
935 // Personal phone
936 print '<tr><td>'.$langs->trans("PhonePerso").'</td>';
937 print '<td>'.img_picto('', 'object_phoning', 'class="pictofixedwidth"').'<input type="text" name="phone_perso" class="maxwidth300 widthcentpercentminusx" value="'.dol_escape_htmltag(GETPOST('phone_perso')).'"></td></tr>';
938
939 // Mobile phone
940 print '<tr><td>'.$langs->trans("PhoneMobile").'</td>';
941 print '<td>'.img_picto('', 'object_phoning_mobile', 'class="pictofixedwidth"').'<input type="text" name="phone_mobile" class="maxwidth300 widthcentpercentminusx" value="'.dol_escape_htmltag(GETPOST('phone_mobile')).'"></td></tr>';
942
943 // Birthday
944 print '<tr id="trbirth" class="trbirth"><td>'.$langs->trans("DateOfBirth").'</td><td>';
945 print $form->selectDate(!empty($birthday) ? $birthday : "", 'birth', 0, 0, 1, "newmember", 1, 0);
946 print '</td></tr>'."\n";
947
948 // Photo
949 print '<tr><td>'.$langs->trans("URLPhoto").'</td><td><input type="text" name="photo" class="minwidth150" value="'.dol_escape_htmltag(GETPOST('photo')).'"></td></tr>'."\n";
950
951 // Public
952 if (getDolGlobalString('MEMBER_PUBLIC_ENABLED')) {
953 $linkofpubliclist = DOL_MAIN_URL_ROOT.'/public/members/public_list.php'.((isModEnabled('multicompany')) ? '?entity='.$conf->entity : '');
954 $publiclabel = $langs->trans("Public", getDolGlobalString('MAIN_INFO_SOCIETE_NOM'), $linkofpubliclist);
955 print '<tr><td>'.$form->textwithpicto($langs->trans("MembershipPublic"), $publiclabel).'</td><td><input type="checkbox" name="public"></td></tr>'."\n";
956 }
957
958 // Other attributes
959 $parameters['tpl_context'] = 'public'; // define template context to public
960 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php';
961
962 // Comments
963 print '<tr>';
964 print '<td class="tdtop"></td>';
965 print '<td class="tdtop"><textarea placeholder="'.dolPrintHTML($langs->trans("Comments")).'" name="note_private" id="note_private" wrap="soft" class="quatrevingtpercent" rows="'.ROWS_3.'">'.dol_escape_htmltag(GETPOST('note_private', 'restricthtml'), 0, 1).'</textarea></td>';
966 print '</tr>'."\n";
967
968
969 // Define amount by default to suggest
970 $typeid = getDolGlobalInt('MEMBER_NEWFORM_FORCETYPE', GETPOSTINT('typeid'));
971 $adht = new AdherentType($db);
972 $adht->fetch($typeid);
973 $caneditamount = $adht->caneditamount;
974 $amountbytype = $adht->amountByType(1); // Load the array of amount per type
975 foreach ($amountbytype as $k => $v) {
976 $amount = max(0, (float) $v, (float) getDolGlobalInt("MEMBER_NEWFORM_AMOUNT"));
977 $amountbytype[$k] = $amount;
978 }
979
980 $amountbytype_json = json_encode($amountbytype);
981 $caneditamountbytype = $adht->caneditamountByType(1); // Load the array of caneditamount per type
982 $caneditamountbytype_json = json_encode($caneditamountbytype);
983
984
985 // Set amount for the subscription from the the type and options:
986 // - First check the amount of the member type.
987 $amount = empty($amountbytype[$typeid]) ? 0 : $amountbytype[$typeid];
988 // - If not found, take the default amount only if the user is authorized to edit it
989 if (empty($amount) && getDolGlobalString('MEMBER_NEWFORM_AMOUNT')) {
990 $amount = getDolGlobalString('MEMBER_NEWFORM_AMOUNT');
991 }
992 // - If not set, we accept to have amount defined as parameter (for backward compatibility).
993 if (empty($amount)) {
994 $amount = (GETPOST('amount') ? price2num(GETPOST('amount', 'alpha'), 'MT', 2) : '');
995 }
996 // - If a min is set, we take it into account
997 $amount = max(0, (float) $amount, (float) getDolGlobalInt("MEMBER_MIN_AMOUNT"));
998
999 // Clean the amount
1000 $amount = price2num($amount);
1001
1002
1003
1004 // Add hook to complete the form
1005 $parameters = array('country_id' => $country_id, 'mode' => 'new');
1006 $reshook = $hookmanager->executeHooks('membershipNewSubscriptionPublicForm', $parameters, $object, $action);
1007 if ($reshook < 0) {
1008 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1009 $error++;
1010 }
1011 // TODO Move this into previous hook
1012 if (getDolGlobalString('MEMBER_NEWFORM_DOLIBARRTURNOVER')) {
1013 // Do not set a default amount MEMBER_NEWFORM_AMOUNT if you use MEMBER_NEWFORM_DOLIBARRTURNOVER
1014 $s = $langs->trans("AreYouAPreferredPartner", '<a href="https://partners.dolibarr.org" target="_blank">{s1}</a>');
1015 $s = str_replace('{s1}', 'Preferred Partner', $s);
1016 print '<tr id="trbudget" class="trcompany"><td class="paddingrightonly"><label for="pp" class="small">'.$s.'</label></td><td>';
1017 print '<input type="checkbox" name="pp" id="pp" value="1"'.(GETPOST('pp') ? ' checked="checked"' : '').' class="reposition">';
1018 print '</td></tr>';
1019
1020 print '<tr id="trbudget" class="trcompany"><td class="fieldrequired paddingrightonly"><span class="small">'.$langs->trans("TurnoverOrBudget").'</span></td><td>';
1021
1022 $country_code = dol_getIdFromCode($db, $country_id, 'c_country', 'rowid', 'code');
1023 if ($country_code === 'FR' && $checkednature === 'mor' && GETPOST('pp')) {
1024 print '<input type="text" name="budget" id="budget" class="flat turnover right width100" value="'.GETPOST('budget').'" required>';
1025 } else {
1026 $arraybudget = array('50' => '<= 100 000', '100' => '<= 200 000', '200' => '<= 500 000', '300' => '<= 1 500 000', '600' => '<= 3 000 000', '1000' => '<= 5 000 000', '2000' => '5 000 000+');
1027 print $form->selectarray('budget', $arraybudget, GETPOSTINT('budget'), 1, 0, '', 0, 0, 0, '');
1028 }
1029 print ' € or $';
1030
1031 print '<script type="text/javascript">
1032 jQuery(document).ready(function() {
1033 firstload = true;
1034
1035 newamount = initturnover();
1036 jQuery("#amount").val(newamount);
1037
1038 firstload = false;
1039
1040 jQuery("#selectcountry_id").change(function() {
1041 console.log("We change country (code added for association, replace common code), so we reload page");
1042 jQuery("#budget").val(\'\');
1043 jQuery("#amount").val(\'\');
1044 jQuery("#amounthidden").val(\'\');
1045 });
1046 jQuery("#phisicalinput,#moralinput").click(function() {
1047 console.log("We change the nature of membership");
1048 newamount = initturnover();
1049 jQuery("#amount").val(newamount);
1050 });
1051 jQuery("#pp").change(function() {
1052 console.log("We change the preferred partner status");
1053 selectcountry_id = jQuery("#selectcountry_id").val();
1054 morphy = jQuery("#moralinput").is(\':checked\') ? \'mor\' : \'phy\';
1055 jQuery("#budget").val(\'\');
1056 jQuery("#amount").val(\'\');
1057 jQuery("#amounthidden").val(\'\');
1058 document.newmember.action.value="create";
1059 jQuery("#newmember").submit();
1060 });
1061 jQuery("#budget").change(function() {
1062 console.log("Turnover amount has been modified on change");
1063 newamount = initturnover();
1064 jQuery("#amount").val(newamount);
1065 jQuery("#amounthidden").val(newamount);
1066 });
1067 jQuery("#budget").keyup(function() {
1068 console.log("Turnover amount has been modified on keyup");
1069 newamount = initturnover();
1070 jQuery("#amount").val(newamount);
1071 jQuery("#amounthidden").val(newamount);
1072 });
1073
1074 function initturnover() {
1075 newamount = 0;
1076
1077 morphy = jQuery("#moralinput").is(\':checked\') ? \'mor\' : \'phy\';
1078 selectcountry_id = jQuery("#selectcountry_id").val();
1079 pp = jQuery("#pp").is(\':checked\') ? true : false;
1080 console.log("Set fields according to nature and other properties");
1081 console.log("morphy="+morphy);
1082 console.log("selectcountry_id="+selectcountry_id);
1083 console.log("pp="+pp);
1084
1085 if (morphy == \'phy\') {
1086 jQuery(".amount").val('.((float) $amount).');
1087 jQuery("#trbirth").show();
1088 jQuery(".trcompany").hide();
1089 jQuery(".trbudget").hide();
1090 newamount = '.((float) $amount).';
1091 } else {
1092 jQuery(".amount").val(\'\');
1093 jQuery("#trbirth").hide();
1094 jQuery(".trcompany").show();
1095 jQuery(".trbudget").show();
1096 jQuery(".hideifautoturnover").hide();
1097 if (firstload) {
1098 jQuery("#budget").val(\'\');
1099 }
1100
1101 if (selectcountry_id == 1) {
1102 if (pp) {
1103 console.log("value selected in input text field is "+jQuery("#budget").val());
1104 newamount = Math.max(Math.round(price2numjs(jQuery("#budget").val()) * 0.005), 50);
1105 console.log("newamount = "+newamount);
1106 } else {
1107 console.log("not a pp");
1108 if (jQuery("#budget").val() > 0) {
1109 console.log("value found in budget is "+jQuery("#budget").val());
1110 newamount = jQuery("#budget").val();
1111 } else {
1112 jQuery("#budget").val(\'\');
1113 newamount = \'\';
1114 }
1115 }
1116 } else {
1117 if (jQuery("#budget").val() > 0) {
1118 newamount = jQuery("#budget").val();
1119 } else {
1120 jQuery("#budget").val(\'\');
1121 newamount = \'\';
1122 }
1123 console.log("newamount="+newamount);
1124 }
1125 }
1126
1127 return newamount;
1128 }
1129 });
1130 </script>';
1131 print '</td></tr>'."\n";
1132 }
1133
1134 if (getDolGlobalString('MEMBER_NEWFORM_PAYONLINE')) { // Can be 'all', 'paypal', 'paybox', 'stripe'...
1135 print '<tr><td>'.$langs->trans("Subscription");
1136 if (getDolGlobalString('MEMBER_EXT_URL_SUBSCRIPTION_INFO')) {
1137 print '<br>';
1138 print '<a href="' . getDolGlobalString('MEMBER_EXT_URL_SUBSCRIPTION_INFO').'" rel="external" target="_blank" rel="noopener noreferrer">';
1139 print img_picto('', 'url', 'class="pictofixedwidth"').$langs->trans("SeeHere");
1140 print '</a>';
1141 }
1142 print '</td><td class="nowrap">';
1143
1144 if (empty($amount) && getDolGlobalString('MEMBER_NEWFORM_AMOUNT')) {
1145 $amount = getDolGlobalString('MEMBER_NEWFORM_AMOUNT');
1146 }
1147
1148 $showedamount = $amount > 0 ? $amount : 0;
1149 if ($caneditamount === "1") {
1150 print '<input type="text" name="amount" id="amount" class="flat amount right width75" value="'.$showedamount.'">';
1151 print '<input type="text" name="amount" id="amounthidden" class="flat amount width75 hidden" disabled value="'.$showedamount.'">';
1152 print ' '.$langs->getCurrencySymbol($conf->currency).'<span class="opacitymedium hideifautoturnover small">';
1153 if (!getDolGlobalString('MEMBER_NEWFORM_DOLIBARRTURNOVER')) {
1154 print ' - ';
1155 print $amount > 0 ? $langs->trans("AnyAmountWithAdvisedAmount", price($amount, 0, $langs, 1, -1, -1, $conf->currency)) : $langs->trans("AnyAmountWithoutAdvisedAmount");
1156 }
1157 print '</span>';
1158 } else {
1159 print '<input type="text" name="amount" id="amount" class="flat amount width75 right hidden" value="'.$showedamount.'">';
1160 print '<input type="text" name="amount" id="amounthidden" class="flat amount width75" disabled value="'.$showedamount.'">';
1161 print ' '.$langs->getCurrencySymbol($conf->currency).'<span class="opacitymedium hideifautoturnover hidden small">';
1162 if (!getDolGlobalString('MEMBER_NEWFORM_DOLIBARRTURNOVER')) {
1163 print ' - ';
1164 print $amount > 0 ? $langs->trans("AnyAmountWithAdvisedAmount", price($amount, 0, $langs, 1, -1, -1, $conf->currency)) : $langs->trans("AnyAmountWithoutAdvisedAmount");
1165 }
1166 print '</span>';
1167 }
1168 print '</td></tr>';
1169
1170 // Add JS to manage the background of amount depending on type
1171 if ($conf->use_javascript_ajax) {
1172 print "<script>
1173 var amountbytype = $amountbytype_json;
1174 var canEditAmount = $caneditamountbytype_json;
1175 </script>";
1176
1177 print '<script>
1178 jQuery(function($) {
1179 $("#typeid").on("change", function() {
1180 console.log("Type of membership changed, we force amount update");
1181 let typeId = $(this).val();
1182 let amountVal = amountbytype[typeId] || 0;
1183 let formattedAmount = parseFloat(amountVal);
1184
1185 if (canEditAmount[typeId] === "1") {
1186 // Editable mode
1187 $("#amount").val(formattedAmount).prop("disabled", false).removeClass("hidden");
1188 $("#amounthidden").addClass("hidden");
1189 $(".hideifautoturnover").removeClass("hidden");
1190 } else {
1191 // Read-only mode
1192 $("#amounthidden").val(formattedAmount).prop("disabled", true).removeClass("hidden");
1193 $("#amount").addClass("hidden");
1194 $(".hideifautoturnover").addClass("hidden");
1195 }
1196 });
1197
1198 // Trigger it once so the amount matches the initial selection
1199 $("#typeid").trigger("change");
1200 });
1201 </script>';
1202 }
1203 }
1204
1205 // Display Captcha code if is enabled
1206 if (getDolGlobalString('MAIN_SECURITY_ENABLECAPTCHA_MEMBER') && is_object($captchaobj)) {
1207 print '<tr><td><label><span class="fieldrequired">'.$langs->trans("SecurityCode").'</span></label></td><td><br>';
1208 if (method_exists($captchaobj, 'getCaptchaCodeForForm')) {
1209 print $captchaobj->getCaptchaCodeForForm(''); // @phan-suppress-current-line PhanUndeclaredMethod
1210 } else {
1211 print 'Error, the captcha handler '.get_class($captchaobj).' does not have any method getCaptchaCodeForForm()';
1212 }
1213 print '<br></td></tr>';
1214 }
1215
1216 print "</table>\n";
1217
1218 print dol_get_fiche_end();
1219
1220 // Save / Submit
1221 print '<div class="center">';
1222 print '<input type="submit" value="'.$langs->trans("GetMembershipButtonLabel").'" id="submitsave" class="button">';
1223 if (!empty($backtopage)) {
1224 print ' &nbsp; &nbsp; <input type="submit" value="'.$langs->trans("Cancel").'" id="submitcancel" class="button button-cancel">';
1225 }
1226 print '</div>';
1227
1228
1229 print "</form>\n";
1230 print "<br>";
1231 print '</div></div>';
1232} else { // Show the table of membership types
1233 // Get units
1234 $measuringUnits = new CUnits($db);
1235 $result = $measuringUnits->fetchAll('', '', 0, 0, array('t.active' => 1));
1236 $units = array();
1237 foreach ($measuringUnits->records as $lines) {
1238 $units[$lines->short_label] = $langs->trans(ucfirst((string) $lines->label));
1239 }
1240
1241 $publiccounters = getDolGlobalString("MEMBER_COUNTERS_ARE_PUBLIC");
1242 $hidevoteallowed = getDolGlobalString("MEMBER_HIDE_VOTE_ALLOWED");
1243
1244 $sql = "SELECT d.rowid, d.libelle as label, d.subscription, d.amount, d.caneditamount, d.vote, d.note, d.duration, d.statut as status, d.morphy,";
1245 $sql .= " COUNT(a.rowid) AS membercount";
1246 $sql .= " FROM ".MAIN_DB_PREFIX."adherent_type as d";
1247 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."adherent as a";
1248 $sql .= " ON d.rowid = a.fk_adherent_type AND a.statut > 0";
1249 $sql .= " WHERE d.entity IN (".getEntity('member_type').")";
1250 $sql .= " AND d.statut=1";
1251 $sql .= " GROUP BY d.rowid, d.libelle, d.subscription, d.amount, d.caneditamount, d.vote, d.note, d.duration, d.statut, d.morphy";
1252
1253 $result = $db->query($sql);
1254 if ($result) {
1255 $num = $db->num_rows($result);
1256
1257 print '<br><div class="div-table-responsive">';
1258 print '<table class="tagtable liste">'."\n";
1259 print '<input type="hidden" name="action" value="create">';
1260
1261 print '<tr class="liste_titre">';
1262 print '<th>'.$langs->trans("Label").'</th>';
1263 print '<th class="center">'.$langs->trans("MembershipDuration").'</th>';
1264 print '<th class="center">'.$langs->trans("Amount").'</th>';
1265 print '<th class="center">'.$langs->trans("MembersNature").'</th>';
1266 if (empty($hidevoteallowed)) {
1267 print '<th class="center">'.$langs->trans("VoteAllowed").'</th>';
1268 }
1269 if ($publiccounters) {
1270 print '<th class="center">'.$langs->trans("Members").'</th>';
1271 }
1272 print '<th class="center">'.$langs->trans("NewSubscription").'</th>';
1273 print "</tr>\n";
1274
1275 $i = 0;
1276 while ($i < $num) {
1277 $objp = $db->fetch_object($result); // Load the member type and information on it
1278
1279 $caneditamount = $objp->caneditamount;
1280 $amountbytype = $adht->amountByType(1); // Load the array of amount per type
1281
1282 print '<tr class="oddeven">';
1283 // Label
1284 print '<td>'.dolPrintHTML($objp->label).'</td>';
1285 // Duration
1286 print '<td class="center">';
1287 $unit = preg_replace("/[^a-zA-Z]+/", "", $objp->duration);
1288 print max(1, intval($objp->duration)).' '.$units[$unit];
1289 print '</td>';
1290 // Amount
1291 print '<td class="center"><span class="amount nowrap">';
1292
1293 // Set amount for the subscription from the the type and options:
1294 // - First check the amount of the member type.
1295 $amount = empty($amountbytype[$objp->rowid]) ? 0 : $amountbytype[$objp->rowid];
1296 // - If not found, take the default amount only if the user is authorized to edit it
1297 if (empty($amount) && getDolGlobalString('MEMBER_NEWFORM_AMOUNT')) {
1298 $amount = getDolGlobalString('MEMBER_NEWFORM_AMOUNT');
1299 }
1300 // - If not set, we accept to have amount defined as parameter (for backward compatibility).
1301 if (empty($amount)) {
1302 $amount = (GETPOST('amount') ? price2num(GETPOST('amount', 'alpha'), 'MT', 2) : '');
1303 }
1304 // - If a min is set, we take it into account
1305 $amount = max(0, (float) $amount, (float) getDolGlobalInt("MEMBER_MIN_AMOUNT"));
1306
1307 $displayedamount = $amount;
1308
1309 if ($objp->subscription) {
1310 if ($displayedamount > 0 || !$caneditamount) {
1311 print price($displayedamount, 1, $langs, 1, 0, -1, $conf->currency);
1312 }
1313 if ($caneditamount && $displayedamount > 0) {
1314 print $form->textwithpicto('', $langs->transnoentities("CanEditAmountShortForValues"), 1, 'help', '', 0, 3);
1315 } elseif ($caneditamount) {
1316 print $langs->transnoentities("CanEditAmountShort");
1317 }
1318 } else {
1319 print "–"; // No subscription required
1320 }
1321 print '</span></td>';
1322 print '<td class="center">';
1323 if ($objp->morphy == 'phy') {
1324 print $langs->trans("Physical");
1325 } elseif ($objp->morphy == 'mor') {
1326 print $langs->trans("Moral");
1327 } else {
1328 print $langs->trans("MorAndPhy");
1329 }
1330 print '</td>';
1331 if (empty($hidevoteallowed)) {
1332 print '<td class="center">'.yn($objp->vote).'</td>';
1333 }
1334 $membercount = $objp->membercount > 0 ? $objp->membercount : "–";
1335 if ($publiccounters) {
1336 print '<td class="center">'.$membercount.'</td>';
1337 }
1338 print '<td class="center"><button class="button button-save reposition" name="typeid" type="submit" name="submit" value="'.$objp->rowid.'">'.$langs->trans("GetMembershipButtonLabel").'</button></td>';
1339 print "</tr>";
1340 $i++;
1341 }
1342
1343 // If no record found
1344 if ($num == 0) {
1345 $colspan = 8;
1346 print '<tr><td colspan="'.$colspan.'" class="opacitymedium">'.$langs->trans("NoRecordFound").'</td></tr>';
1347 }
1348
1349 print "</table>";
1350 print '</div>';
1351
1352 print '</form>';
1353 } else {
1354 dol_print_error($db);
1355 }
1356}
1357
1358//htmlPrintOnlineFooter($mysoc, $langs);
1360
1361$db->close();
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
Class to manage members of a foundation.
Class to manage members type.
Class to send emails (with attachments or not) Usage: $mailfile = new CMailFile($subject,...
Class of dictionary type of thirdparty (used by imports)
Class to manage standard extra fields.
Class to build HTML component for third parties management Only common components are here.
Class to manage generation of HTML components Only common components must be here.
Class permettant la generation du formulaire html d'envoi de mail unitaire Usage: $formail = new Form...
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
llxHeaderVierge($title, $head="", $disablejs=0, $disablehead=0, $arrayofjs=[], $arrayofcss=[])
Show header for new prospect.
Definition new.php:122
llxFooterVierge()
Show footer for new societe.
Definition new.php:143
htmlPrintOnlineHeader($mysoc, $langs, $showlogo=1, $alttext='', $subimageconst='', $altlogo1='', $altlogo2='')
Show the header of a company in HTML public pages.
getCountry($searchkey, $withcode='', $dbtouse=null, $outputlangs=null, $entconv=1, $searchlabel='')
Return country label, code or id from an id, code or label.
global $mysoc
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition date.lib.php:125
dol_now($mode='gmt')
Return date for now.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='', $useCache=true)
Return an id or code from a code or id.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_user_country()
Return country code for current user.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
printCommonFooter($zone='private')
Print common footer : conf->global->MAIN_HTML_FOOTER js for switch of menu hider js for conf->global-...
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
GETPOSTFLOAT($paramname, $rounding='', $option=2)
Return the value of a $_GET or $_POST supervariable, converted into float.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
dol_htmloutput_events($disabledoutputofmessages=0)
Print formatted messages to output (Used to show messages on html output).
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the "subst...
make_substitutions($text, $substitutionarray, $outputlangs=null, $converttextinhtmlifnecessary=0)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=>newva...
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
getUserRemoteIP($trusted=0)
Return the real IP of remote user.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
isValidEmail($address, $acceptsupervisorkey=0, $acceptuserkey=0)
Return true if email syntax is ok.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_htmloutput_errors($mesgstring='', $mesgarray=array(), $keepembedded=0)
Print formatted error messages to output (Used to show messages on html output).
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
top_htmlhead($head, $title='', $disablejs=0, $disablehead=0, $arrayofjs=array(), $arrayofcss=array(), $disableforlogin=0, $disablenofollow=0, $disablenoindex=0)
Output html header of a page.
if(getDolGlobalString( 'MAIN_SECURITY_ENABLECAPTCHA_MEMBER')) force_switch_entity($newEntity)
Force switching conf of entity, even if user is connected Fox example when trying to go on public for...
Definition new.php:154
httponly_accessforbidden($message='1', $http_response_code=403, $stringalreadysanitized=0)
Show a message to say access is forbidden and stop program.