3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
10 * Copyright © 2007-2021 The Galette Team
12 * This file is part of Galette (http://galette.tuxfamily.org).
14 * Galette is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
19 * Galette is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
29 * @author Johan Cwiklinski <johan@x-tnd.be>
30 * @copyright 2007-2021 The Galette Team
31 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
32 * @link http://galette.tuxfamily.org
33 * @since Available since 0.7dev - 2007-10-14
36 namespace Galette\Core
;
38 use Galette\Entity\PaymentType
;
39 use Galette\Entity\Social
;
40 use Galette\Features\Replacements
;
41 use Galette\Features\Socials
;
44 use Galette\Entity\Adherent
;
45 use Galette\Entity\Status
;
46 use Galette\IO\PdfMembersCards
;
47 use Galette\Repository\Members
;
50 * Preferences for galette
55 * @author Johan Cwiklinski <johan@x-tnd.be>
56 * @copyright 2007-2021 The Galette Team
57 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
58 * @link http://galette.tuxfamily.org
59 * @since Available since 0.7dev - 2007-10-14
61 * @property string $pref_admin_login Super admin login
62 * @property string $pref_admin_pass Super admin password
63 * @property string $pref_nom Association name
64 * @property string $pref_slogan Association slogan
65 * @property string $pref_adresse Address
66 * @property string $pref_adresse2 Address continuation
67 * @property string $pref_cp Association zipcode
68 * @property string $pref_ville Association town
69 * @property string $pref_pays Country
70 * @property integer $pref_postal_adress Postal adress to use, one of self::POSTAL_ADDRESS*
71 * @property integer $pref_postal_staff_member Staff member ID from which retrieve postal address
72 * @property string $pref_lang Default instance language
73 * @property integer $pref_numrows Default number of rows in lists
74 * @property integer $pref_log History, one of self::LOG_*
75 * @property integer $pref_statut Default status for new members
76 * @property string $pref_email_nom
77 * @property string $pref_email
78 * @property string $pref_email_newadh
79 * @property boolean $pref_bool_mailadh
80 * @property boolean $pref_bool_mailowner
81 * @property boolean $pref_editor_enabled
82 * @property integer $pref_mail_method Mail method, see GaletteMail::METHOD_*
83 * @property string $pref_mail_smtp
84 * @property string $pref_mail_smtp_host
85 * @property boolean $pref_mail_smtp_auth
86 * @property boolean $pref_mail_smtp_secure
87 * @property integer $pref_mail_smtp_port
88 * @property string $pref_mail_smtp_user
89 * @property string $pref_mail_smtp_password
90 * @property integer $pref_membership_ext
91 * @property string $pref_beg_membership
92 * @property integer $pref_membership_offermonths
93 * @property string $pref_email_reply_to
94 * @property string $pref_website
95 * @property integer $pref_etiq_marges_v
96 * @property string $pref_etiq_marges_h
97 * @property string $pref_etiq_hspace
98 * @property string $pref_etiq_vspace
99 * @property string $pref_etiq_hsize
100 * @property string $pref_etiq_vsize
101 * @property string $pref_etiq_cols
102 * @property string $pref_etiq_rows
103 * @property string $pref_etiq_corps
104 * @property string $pref_card_abrev
105 * @property string $pref_card_strip
106 * @property string $pref_card_tcol
107 * @property string $pref_card_scol
108 * @property string $pref_card_bcol
109 * @property string $pref_card_hcol
110 * @property string $pref_bool_display_title
111 * @property integer $pref_card_address
112 * @property string $pref_card_year
113 * @property integer $pref_card_marges_v
114 * @property integer $pref_card_marges_h
115 * @property integer $pref_card_vspace
116 * @property integer $pref_card_hspace
117 * @property string $pref_card_self
118 * @property string $pref_theme Prefered theme
119 * @property boolean $pref_bool_publicpages
120 * @property integer $pref_publicpages_visibility
121 * @property boolean $pref_bool_selfsubscribe
122 * @property string $pref_mail_sign
123 * @property string $pref_new_contrib_script
124 * @property boolean $pref_bool_wrap_mails
125 * @property string $pref_rss_url
126 * @property boolean $pref_show_id
127 * @property string $pref_adhesion_form
128 * @property boolean $pref_mail_allow_unsecure
129 * @property string $pref_instance_uuid
130 * @property string $pref_registration_uuid
131 * @property string $pref_telemetry_date
132 * @property string $pref_registration_date
133 * @property string $pref_footer
134 * @property integer $pref_filter_account
135 * @property string $pref_galette_url
136 * @property integer $pref_redirect_on_create
137 * @property integer $pref_password_length
138 * @property boolean $pref_password_blacklist
139 * @property integer $pref_password_strength
140 * @property integer $pref_default_paymenttype
141 * @property boolean $pref_bool_create_member
142 * @property boolean $pref_bool_groupsmanagers_create_member
143 * @property boolean $pref_bool_groupsmanagers_edit_member
144 * @property boolean $pref_bool_groupsmanagers_edit_groups
145 * @property boolean $pref_bool_groupsmanagers_mailings
146 * @property boolean $pref_bool_groupsmanagers_exports
147 * @property-read string $vpref_email_newadh Comma separated list of mail senders
154 protected $preferences; //redefined from Replacements feature - avoid circular dependency
156 private $errors = [];
158 public const TABLE
= 'preferences';
159 public const PK
= 'nom_pref';
161 /** Postal address will be the one given in the preferences */
162 public const POSTAL_ADDRESS_FROM_PREFS
= 0;
163 /** Postal address will be the one of the selected staff member */
164 public const POSTAL_ADDRESS_FROM_STAFF
= 1;
166 /** Public pages stuff */
167 /** Public pages are publically visibles */
168 public const PUBLIC_PAGES_VISIBILITY_PUBLIC
= 0;
169 /** Public pages are visibles for up to date members only */
170 public const PUBLIC_PAGES_VISIBILITY_RESTRICTED
= 1;
171 /** Public pages are visibles for admin and staff members only */
172 public const PUBLIC_PAGES_VISIBILITY_PRIVATE
= 2;
174 public const LOG_DISABLED
= 0;
175 public const LOG_ENABLED
= 1;
177 /** No password strength */
178 public const PWD_NONE
= 0;
179 /** Weak password strength */
180 public const PWD_WEAK
= 1;
181 /** Medium password strength */
182 public const PWD_MEDIUM
= 2;
183 /** Strong password strength */
184 public const PWD_STRONG
= 3;
185 /** Very strong password strength */
186 public const PWD_VERY_STRONG
= 4;
188 private static $fields = array(
193 private static $defaults = array(
194 'pref_admin_login' => 'admin',
195 'pref_admin_pass' => 'admin',
196 'pref_nom' => 'Galette',
198 'pref_adresse' => '-',
199 'pref_adresse2' => '',
203 'pref_postal_adress' => self
::POSTAL_ADDRESS_FROM_PREFS
,
204 'pref_postal_staff_member' => '',
205 'pref_lang' => I18n
::DEFAULT_LANG
,
206 'pref_numrows' => 30,
207 'pref_log' => self
::LOG_ENABLED
,
208 'pref_statut' => Status
::DEFAULT_STATUS
,
209 /* Preferences for emails */
210 'pref_email_nom' => 'Galette',
211 'pref_email' => 'mail@domain.com',
212 'pref_email_newadh' => 'mail@domain.com',
213 'pref_bool_mailadh' => false,
214 'pref_bool_mailowner' => false,
215 'pref_editor_enabled' => false,
216 'pref_mail_method' => GaletteMail
::METHOD_DISABLED
,
217 'pref_mail_smtp' => '',
218 'pref_mail_smtp_host' => '',
219 'pref_mail_smtp_auth' => false,
220 'pref_mail_smtp_secure' => false,
221 'pref_mail_smtp_port' => '',
222 'pref_mail_smtp_user' => '',
223 'pref_mail_smtp_password' => '',
224 'pref_membership_ext' => 12,
225 'pref_beg_membership' => '',
226 'pref_membership_offermonths' => 0,
227 'pref_email_reply_to' => '',
228 'pref_website' => '',
229 /* Preferences for labels */
230 'pref_etiq_marges_v' => 10,
231 'pref_etiq_marges_h' => 10,
232 'pref_etiq_hspace' => 10,
233 'pref_etiq_vspace' => 5,
234 'pref_etiq_hsize' => 90,
235 'pref_etiq_vsize' => 35,
236 'pref_etiq_cols' => 2,
237 'pref_etiq_rows' => 7,
238 'pref_etiq_corps' => 12,
239 /* Preferences for members cards */
240 'pref_card_abrev' => 'GALETTE',
241 'pref_card_strip' => 'Gestion d\'Adherents en Ligne Extrêmement Tarabiscotée',
242 'pref_card_tcol' => '#FFFFFF',
243 'pref_card_scol' => '#8C2453',
244 'pref_card_bcol' => '#53248C',
245 'pref_card_hcol' => '#248C53',
246 'pref_bool_display_title' => false,
247 'pref_card_address' => 1,
248 'pref_card_year' => '',
249 'pref_card_marges_v' => 15,
250 'pref_card_marges_h' => 20,
251 'pref_card_vspace' => 5,
252 'pref_card_hspace' => 10,
253 'pref_card_self' => 1,
254 'pref_theme' => 'default',
255 'pref_bool_publicpages' => true,
256 'pref_publicpages_visibility' => self
::PUBLIC_PAGES_VISIBILITY_RESTRICTED
,
257 'pref_bool_selfsubscribe' => true,
258 'pref_mail_sign' => "{ASSO_NAME}\r\n\r\n{ASSO_WEBSITE}",
259 /* New contribution script */
260 'pref_new_contrib_script' => '',
261 'pref_bool_wrap_mails' => true,
262 'pref_rss_url' => 'http://galette.eu/dc/index.php/feed/atom',
263 'pref_show_id' => false,
264 'pref_adhesion_form' => '\Galette\IO\PdfAdhesionForm',
265 'pref_mail_allow_unsecure' => false,
266 'pref_instance_uuid' => '',
267 'pref_registration_uuid' => '',
268 'pref_telemetry_date' => '',
269 'pref_registration_date' => '',
271 'pref_filter_account' => Members
::ALL_ACCOUNTS
,
272 'pref_galette_url' => '',
273 'pref_redirect_on_create' => Adherent
::AFTER_ADD_DEFAULT
,
274 /* Security related */
275 'pref_password_length' => 6,
276 'pref_password_blacklist' => false,
277 'pref_password_strength' => self
::PWD_NONE
,
278 'pref_default_paymenttype' => PaymentType
::CHECK
,
279 'pref_bool_create_member' => false,
280 'pref_bool_groupsmanagers_create_member' => false,
281 'pref_bool_groupsmanagers_edit_member' => false,
282 'pref_bool_groupsmanagers_edit_groups' => false,
283 'pref_bool_groupsmanagers_mailings' => false,
284 'pref_bool_groupsmanagers_exports' => true
290 // flagging required fields
291 private $required = array(
296 'pref_etiq_marges_v',
297 'pref_etiq_marges_h',
307 'pref_card_marges_v',
308 'pref_card_marges_h',
314 * Default constructor
316 * @param Db $zdb Db instance
317 * @param boolean $load Automatically load preferences on load
321 public function __construct(Db
$zdb, $load = true)
326 $this->checkUpdate();
331 * Check if all fields referenced in the default array does exists,
336 private function checkUpdate()
340 foreach (self
::$defaults as $k => $v) {
341 if (!isset($this->prefs
[$k])) {
342 if ($k == 'pref_admin_pass' && $v == 'admin') {
343 $v = password_hash($v, PASSWORD_BCRYPT
);
345 $this->prefs
[$k] = $v;
347 'The field `' . $k . '` does not exists, Galette will attempt to create it.',
357 if ($proceed !== false) {
359 $insert = $this->zdb
->insert(self
::TABLE
);
362 'nom_pref' => ':nom_pref',
363 'val_pref' => ':val_pref'
366 $stmt = $this->zdb
->sql
->prepareStatementForSqlObject($insert);
368 foreach ($params as $p) {
371 'nom_pref' => $p['nom_pref'],
372 'val_pref' => $p['val_pref']
376 } catch (Throwable
$e) {
378 'Unable to add missing preferences.' . $e->getMessage(),
385 'Missing preferences were successfully stored into database.',
392 * Load current preferences from database.
396 public function load()
398 $this->prefs
= array();
401 $result = $this->zdb
->selectAll(self
::TABLE
);
402 foreach ($result as $pref) {
403 $this->prefs
[$pref->nom_pref
] = $pref->val_pref
;
405 $this->socials
= Social
::getListForMember(null);
407 } catch (Throwable
$e) {
409 'Preferences cannot be loaded. Galette should not work without ' .
410 'preferences. Exiting.',
418 * Set default preferences at install time
420 * @param string $lang language selected at install screen
421 * @param string $adm_login admin login entered at install time
422 * @param string $adm_pass admin password entered at install time
424 * @return boolean|\Exception
426 public function installInit($lang, $adm_login, $adm_pass)
429 //first, we drop all values
430 $delete = $this->zdb
->delete(self
::TABLE
);
431 $this->zdb
->execute($delete);
433 //we then replace default values with the ones user has selected
434 $values = self
::$defaults;
435 $values['pref_lang'] = $lang;
436 $values['pref_admin_login'] = $adm_login;
437 $values['pref_admin_pass'] = $adm_pass;
438 $values['pref_card_year'] = date('Y');
440 $insert = $this->zdb
->insert(self
::TABLE
);
443 'nom_pref' => ':nom_pref',
444 'val_pref' => ':val_pref'
447 $stmt = $this->zdb
->sql
->prepareStatementForSqlObject($insert);
449 foreach ($values as $k => $v) {
459 'Default preferences were successfully stored into database.',
463 } catch (Throwable
$e) {
465 'Unable to initialize default preferences.' . $e->getMessage(),
473 * Returns all preferences keys
477 public function getFieldsNames()
479 return array_keys($this->prefs
);
485 * @param array $values Values
486 * @param Login $login Logged in user
490 public function check(array $values, Login
$login)
492 $insert_values = array();
493 if ($login->isSuperAdmin() && GALETTE_MODE
!== Galette
::MODE_DEMO
) {
494 $this->required
[] = 'pref_admin_login';
498 foreach ($this->getFieldsNames() as $fieldname) {
499 if (isset($values[$fieldname])) {
500 $value = trim($values[$fieldname]);
505 $insert_values[$fieldname] = $value;
508 //cleanup fields for demo
509 if (GALETTE_MODE
== Galette
::MODE_DEMO
) {
511 $insert_values['pref_admin_login'],
512 $insert_values['pref_admin_pass'],
513 $insert_values['pref_mail_method']
519 GALETTE_MODE
!== Galette
::MODE_DEMO
520 && isset($insert_values['pref_mail_method'])
522 if ($insert_values['pref_mail_method'] > GaletteMail
::METHOD_DISABLED
) {
524 !isset($insert_values['pref_email_nom'])
525 ||
$insert_values['pref_email_nom'] == ''
527 $this->errors
[] = _T("- You must indicate a sender name for emails!");
530 !isset($insert_values['pref_email'])
531 ||
$insert_values['pref_email'] == ''
533 $this->errors
[] = _T("- You must indicate an email address Galette should use to send emails!");
535 if ($insert_values['pref_mail_method'] == GaletteMail
::METHOD_SMTP
) {
537 !isset($insert_values['pref_mail_smtp_host'])
538 ||
$insert_values['pref_mail_smtp_host'] == ''
540 $this->errors
[] = _T("- You must indicate the SMTP server you want to use!");
544 $insert_values['pref_mail_method'] == GaletteMail
::METHOD_GMAIL
545 ||
($insert_values['pref_mail_method'] == GaletteMail
::METHOD_SMTP
546 && $insert_values['pref_mail_smtp_auth'])
549 !isset($insert_values['pref_mail_smtp_user'])
550 ||
trim($insert_values['pref_mail_smtp_user']) == ''
552 $this->errors
[] = _T("- You must provide a login for SMTP authentication.");
555 !isset($insert_values['pref_mail_smtp_password'])
556 ||
($insert_values['pref_mail_smtp_password']) == ''
558 $this->errors
[] = _T("- You must provide a password for SMTP authentication.");
565 isset($insert_values['pref_beg_membership'])
566 && $insert_values['pref_beg_membership'] != ''
567 && isset($insert_values['pref_membership_ext'])
568 && $insert_values['pref_membership_ext'] != ''
570 $this->errors
[] = _T("- Default membership extention and beginning of membership are mutually exclusive.");
574 isset($insert_values['pref_membership_offermonths'])
575 && (int)$insert_values['pref_membership_offermonths'] > 0
576 && isset($insert_values['pref_membership_ext'])
577 && $insert_values['pref_membership_ext'] != ''
579 $this->errors
[] = _T("- Offering months is only compatible with beginning of membership.");
582 // missing required fields?
583 foreach ($this->required
as $val) {
584 if (!isset($values[$val]) ||
isset($values[$val]) && trim($values[$val]) == '') {
585 $this->errors
[] = str_replace(
588 _T("- Mandatory field %field empty.")
593 if (GALETTE_MODE
!== Galette
::MODE_DEMO
&& isset($values['pref_admin_pass_check'])) {
594 // Check passwords. Hash will be done into the Preferences class
595 if (strcmp($insert_values['pref_admin_pass'], $values['pref_admin_pass_check']) != 0) {
596 $this->errors
[] = _T("Passwords mismatch");
601 if (isset($insert_values['pref_postal_adress'])) {
602 $value = $insert_values['pref_postal_adress'];
603 if ($value == Preferences
::POSTAL_ADDRESS_FROM_PREFS
) {
604 if (isset($insert_values['pref_postal_staff_member'])) {
605 unset($insert_values['pref_postal_staff_member']);
607 } elseif ($value == Preferences
::POSTAL_ADDRESS_FROM_STAFF
) {
608 if (!isset($value) ||
$value < 1) {
609 $this->errors
[] = _T("You have to select a staff member");
614 // update preferences
615 foreach ($insert_values as $champ => $valeur) {
617 $login->isSuperAdmin()
618 ||
(!$login->isSuperAdmin()
619 && ($champ != 'pref_admin_pass' && $champ != 'pref_admin_login'))
622 ($champ == "pref_admin_pass" && $_POST['pref_admin_pass'] != '')
623 ||
($champ != "pref_admin_pass")
625 $this->$champ = $valeur;
630 $this->checkSocials($values);
632 return 0 === count($this->errors
);
636 * Validate value of a field
638 * @param string $fieldname Field name
639 * @param mixed $value Value to be set
643 public function validateValue($fieldname, $value)
647 switch ($fieldname) {
649 case 'pref_email_newadh':
650 case 'pref_email_reply_to':
651 //check emails validity
652 //may be a comma separated list of valid emails identifiers:
653 //"The Name <mail@domain.com>,The Other <other@mail.com>" expect for reply_to.
655 if (trim($value) != '') {
656 if ($fieldname == 'pref_email_newadh') {
657 $addresses = explode(',', $value);
659 $addresses = [$value];
662 foreach ($addresses as $address) {
663 if (!GaletteMail
::isValidEmail($address)) {
664 $msg = str_replace('%s', $address, _T("Invalid E-Mail address: %s"));
665 Analog
::log($msg, Analog
::WARNING
);
666 $this->errors
[] = $msg;
670 case 'pref_admin_login':
671 if (GALETTE_MODE
=== Galette
::MODE_DEMO
) {
673 'Trying to set superadmin login while in DEMO.',
677 if (strlen($value) < 4) {
678 $this->errors
[] = _T("- The username must be composed of at least 4 characters!");
680 //check if login is already taken
681 if ($login->loginExists($value)) {
682 $this->errors
[] = _T("- This username is already used by another member !");
688 if (!is_numeric($value) ||
$value < 0) {
689 $this->errors
[] = _T("- The numbers and measures have to be integers!");
692 case 'pref_etiq_marges_h':
693 case 'pref_etiq_marges_v':
694 case 'pref_etiq_hspace':
695 case 'pref_etiq_vspace':
696 case 'pref_etiq_hsize':
697 case 'pref_etiq_vsize':
698 case 'pref_etiq_cols':
699 case 'pref_etiq_rows':
700 case 'pref_etiq_corps':
701 case 'pref_card_marges_v':
702 case 'pref_card_marges_h':
703 case 'pref_card_hspace':
704 case 'pref_card_vspace':
705 // prevent division by zero
706 if ($fieldname == 'pref_numrows' && $value == '0') {
709 if (!is_numeric($value) ||
$value < 0) {
710 $this->errors
[] = _T("- The numbers and measures have to be integers!");
713 case 'pref_card_tcol':
714 case 'pref_card_scol':
715 case 'pref_card_bcol':
716 case 'pref_card_hcol':
718 if (!preg_match("/^(#)?([0-9A-F]{6})$/i", $value, $matches)) {
719 // Set strip background colors to black or white (for tcol)
720 $value = ($fieldname == 'pref_card_tcol' ?
'#FFFFFF' : '#000000');
722 $value = '#' . $matches[2];
725 case 'pref_admin_pass':
726 if (GALETTE_MODE
== Galette
::MODE_DEMO
) {
728 'Trying to set superadmin pass while in DEMO.',
732 $pwcheck = new \Galette\Util\
Password($this);
733 $pwcheck->addPersonalInformation(['pref_admin_login' => $this->pref_admin_login
]);
734 if (!$pwcheck->isValid($value)) {
735 $this->errors
= array_merge(
737 $pwcheck->getErrors()
742 case 'pref_membership_ext':
743 if (!is_numeric($value) ||
$value < 0) {
744 $this->errors
[] = _T("- Invalid number of months of membership extension.");
747 case 'pref_beg_membership':
748 $beg_membership = explode("/", $value);
749 if (count($beg_membership) != 2) {
750 $this->errors
[] = _T("- Invalid format of beginning of membership.");
753 if (!checkdate($beg_membership[1], $beg_membership[0], $now['year'])) {
754 $this->errors
[] = _T("- Invalid date for beginning of membership.");
758 case 'pref_membership_offermonths':
759 if (!is_numeric($value) ||
$value < 0) {
760 $this->errors
[] = _T("- Invalid number of offered months.");
763 case 'pref_card_year':
764 if ($value !== 'DEADLINE' && !preg_match('/^(?:\d{4}|\d{2})(\D?)(?:\d{4}|\d{2})$/', $value)) {
765 $this->errors
[] = _T("- Invalid year for cards.");
769 $value = $this->cleanHtmlValue($value);
777 * Will store all preferences in the database
781 public function store()
784 $this->zdb
->connection
->beginTransaction();
785 $update = $this->zdb
->update(self
::TABLE
);
788 'val_pref' => ':val_pref'
790 )->where
->equalTo('nom_pref', ':nom_pref');
792 $stmt = $this->zdb
->sql
->prepareStatementForSqlObject($update);
794 foreach (self
::$defaults as $k => $v) {
796 GALETTE_MODE
== Galette
::MODE_DEMO
797 && in_array($k, ['pref_admin_pass', 'pref_admin_login', 'pref_mail_method'])
801 Analog
::log('Storing ' . $k, Analog
::DEBUG
);
803 $value = $this->prefs
[$k];
804 //do not store pdf_adhesion_form, it's designed to be overriden by plugin
805 if ($k === 'pref_adhesion_form') {
806 if (trim($v) == '') {
807 //Reset to default, should not be empty
808 $v = self
::$defaults['pref_adhesion_form'];
815 'val_pref' => $value,
820 $this->zdb
->connection
->commit();
822 'Preferences were successfully stored into database.',
826 $this->storeSocials(null);
829 } catch (Throwable
$e) {
830 $this->zdb
->connection
->rollBack();
834 $messages[] = $e->getMessage();
835 } while ($e = $e->getPrevious());
838 'Unable to store preferences | ' . print_r($messages, true),
846 * Returns postal address
848 * @return string postal address
850 public function getPostalAddress()
861 $replacements = null;
863 if ($this->prefs
['pref_postal_adress'] == self
::POSTAL_ADDRESS_FROM_PREFS
) {
864 $_address = $this->prefs
['pref_adresse'];
865 if ($this->prefs
['pref_adresse2'] && $this->prefs
['pref_adresse2'] != '') {
866 $_address .= "\n" . $this->prefs
['pref_adresse2'];
868 $replacements = array(
869 $this->prefs
['pref_nom'],
872 $this->prefs
['pref_cp'],
873 $this->prefs
['pref_ville'],
874 $this->prefs
['pref_pays']
877 //get selected staff member address
878 $adh = new Adherent($this->zdb
, (int)$this->prefs
['pref_postal_staff_member']);
879 $_complement = preg_replace(
880 array('/%name/', '/%status/'),
881 array($this->prefs
['pref_nom'], $adh->sstatus
),
882 _T("%name association's %status")
884 $_address = $adh->address
;
885 if ($adh->address_continuation
&& $adh->address_continuation
!= '') {
886 $_address .= "\n" . $adh->address_continuation
;
888 $replacements = array(
889 $adh->sfullname
. "\n",
898 /*FIXME: i18n fails :/ */
902 _T("%name\n%complement\n%address\n%zip %town - %country")
907 "%name%complement%address\n%zip %town - %country"
913 * Are public pages visibles?
915 * @param Authentication $login Authenticaqtion instance
919 public function showPublicPages(Authentication
$login)
921 if ($this->prefs
['pref_bool_publicpages']) {
922 //if public pages are actives, let's check if we
923 //display them for curent call
924 switch ($this->prefs
['pref_publicpages_visibility']) {
925 case self
::PUBLIC_PAGES_VISIBILITY_PUBLIC
:
926 //pages are publically visibles
929 case self
::PUBLIC_PAGES_VISIBILITY_RESTRICTED
:
930 //pages should be displayed only for up to date members
941 case self
::PUBLIC_PAGES_VISIBILITY_PRIVATE
:
942 //pages should be displayed only for staff and admins
943 if ($login->isAdmin() ||
$login->isStaff()) {
950 //should never be there
960 * Global getter method
962 * @param string $name name of the property we want to retrive
964 * @return false|object the called property
966 public function __get($name)
968 $forbidden = array('defaults');
969 $virtuals = array('vpref_email_newadh');
971 if (!in_array($name, $forbidden) && isset($this->prefs
[$name])) {
973 GALETTE_MODE
=== Galette
::MODE_DEMO
974 && $name == 'pref_mail_method'
976 return GaletteMail
::METHOD_DISABLED
;
977 } elseif ($name == 'pref_footer') {
978 return $this->cleanHtmlValue($this->prefs
[$name]);
980 if ($name == 'pref_adhesion_form' && $this->prefs
[$name] == '') {
981 $this->prefs
[$name] = self
::$defaults['pref_adhesion_form'];
983 $value = $this->prefs
[$name];
984 if (TYPE_DB
=== \Galette\Core\Db
::PGSQL
) {
985 if ($value === 'f') {
990 if (in_array($name, ['pref_email_newadh'])) {
991 $values = explode(',', $value);
992 $value = $values[0]; //take first as default
997 } elseif (in_array($name, $virtuals)) {
998 $virtual = str_replace('vpref_', 'pref_', $name);
999 return explode(',', $this->prefs
[$virtual]);
1000 } elseif ($name === 'socials') {
1001 return $this->socials
;
1004 'Preference `' . $name . '` is not set or is forbidden',
1012 * Get default preferences
1016 public function getDefaults()
1018 return self
::$defaults;
1022 * Global setter method
1024 * @param string $name name of the property we want to assign a value to
1025 * @param object $value a relevant value for the property
1029 public function __set($name, $value)
1031 //does this pref exists ?
1032 if (!array_key_exists($name, self
::$defaults)) {
1034 'Trying to set a preference value which does not seem to exist ('
1042 $name == 'pref_email'
1043 ||
$name == 'pref_email_newadh'
1044 ||
$name == 'pref_email_reply_to'
1046 if (GALETTE_MODE
=== Galette
::MODE_DEMO
) {
1048 'Trying to set pref_email while in DEMO.',
1055 // now, check validity
1057 $value = $this->validateValue($name, $value);
1060 //some values need to be changed (eg. passwords)
1061 if ($name == 'pref_admin_pass') {
1062 $value = password_hash($value, PASSWORD_BCRYPT
);
1065 //okay, let's update value
1066 $this->prefs
[$name] = $value;
1070 * Get instance URL from configuration (if set) or guessed if not
1074 public function getURL()
1077 if (isset($this->prefs
['pref_galette_url']) && !empty($this->prefs
['pref_galette_url'])) {
1078 $url = $this->prefs
['pref_galette_url'];
1080 $url = $this->getDefaultURL();
1086 * Get default URL (when not set by user in preferences)
1090 public function getDefaultURL()
1092 $scheme = (isset($_SERVER['HTTPS']) ?
'https' : 'http');
1093 $uri = $scheme . '://' . $_SERVER['HTTP_HOST'];
1098 * Get last telemetry date
1102 public function getTelemetryDate(): string
1104 $rawdate = $this->prefs
['pref_telemetry_date'];
1106 $date = new \
DateTime($rawdate);
1107 return $date->format(_T('Y-m-d H:i:s'));
1114 * Get last telemetry date
1116 * @return string|null
1118 public function getRegistrationDate()
1120 $rawdate = $this->prefs
['pref_registration_date'];
1122 $date = new \
DateTime($rawdate);
1123 return $date->format(_T('Y-m-d H:i:s'));
1130 * Check member cards sizes
1131 * Always a A4/portrait
1135 public function checkCardsSizes()
1137 $warning_detected = [];
1141 $size = $this->pref_card_marges_h
* 2;
1143 $size +
= PdfMembersCards
::getWidth() * PdfMembersCards
::getCols();
1145 $size +
= $this->pref_card_hspace
* (PdfMembersCards
::getCols() - 1);
1147 $warning_detected[] = _T('Current cards configuration may exceed page width!');
1152 $size = $this->pref_card_marges_v
* 2;
1154 $size +
= PdfMembersCards
::getHeight() * PdfMembersCards
::getRows();
1156 $size +
= $this->pref_card_vspace
* (PdfMembersCards
::getRows() - 1);
1158 $warning_detected[] = _T('Current cards configuration may exceed page height!');
1161 return $warning_detected;
1169 public function getErrors()
1171 return $this->errors
;
1175 * Build legend array
1179 public function getLegend(): array
1184 'title' => _T('Main information'),
1185 'patterns' => $this->getMainPatterns()
1188 $s_patterns = $this->getSignaturePatterns(false);
1189 if (count($s_patterns)) {
1190 $legend['socials'] = [
1191 'title' => _T('Social networks'),
1192 'patterns' => $this->getSignaturePatterns(false)
1200 * Get email signature
1204 public function getMailSignature(): string
1208 $signature = $this->pref_mail_sign
;
1210 if (trim($signature) == '') {
1214 $this->setPreferences($this)->setRouter($router);
1216 $this->getMainPatterns() +
$this->getSignaturePatterns()
1220 ->setSocialReplacements();
1222 $signature = $this->proceedReplacements($signature);
1224 return "\r\n-- \r\n" . $signature;
1228 * Get patterns for mail signature
1230 * @param boolean $legacy Whether to load legacy patterns
1234 protected function getSignaturePatterns($legacy = true): array
1237 $social = new Social($this->zdb
);
1239 $types = $this->getCoreRegisteredTypes() +
$social->getSystemTypes(false);
1241 foreach ($types as $type) {
1242 $s_patterns['asso_social_' . $type] = [
1243 'title' => $social->getSystemType($type),
1244 'pattern' => '/{ASSO_SOCIAL_' . strtoupper($type) . '}/'
1248 if ($legacy === true) {
1249 $main = $this->getMainPatterns();
1250 $s_patterns['_asso_name'] = [
1251 'title' => $main['asso_name']['title'],
1252 'pattern' => '/{NAME}/'
1255 $s_patterns['_asso_website'] = [
1256 'title' => $main['asso_website']['title'],
1257 'pattern' => '/{WEBSITE}/'
1260 foreach ([Social
::FACEBOOK
, Social
::TWITTER
, Social
::LINKEDIN
, Social
::VIADEO
] as $legacy_type) {
1261 $s_patterns['_asso_social_' . $legacy_type] = [
1262 'title' => $s_patterns['asso_social_' . $legacy_type]['title'],
1263 'pattern' => '/{' . strtoupper($legacy_type) . '}/'
1272 * Set emails replacements
1276 public function setSocialReplacements(): self
1280 $done_replacements = $this->getReplacements();
1281 $replacements['_asso_name'] = $done_replacements['asso_name'];
1282 $replacements['asso_website'] = $this->pref_website
;
1283 $replacements['_asso_website'] = $replacements['asso_website'];
1285 $social = new Social($this->zdb
);
1286 $types = $this->getCoreRegisteredTypes() +
$social->getSystemTypes(false);
1288 foreach ($types as $type) {
1289 $replace_value = null;
1290 $socials = Social
::getListForMember(null, $type);
1291 if (count($socials)) {
1292 $replace_value = '';
1293 foreach ($socials as $social) {
1294 if ($replace_value != '') {
1295 $replace_value .= ', ';
1297 $replace_value .= $social->url
;
1300 $replacements['asso_social_' . strtolower($type)] = $replace_value;
1304 foreach ([Social
::FACEBOOK
, Social
::TWITTER
, Social
::LINKEDIN
, Social
::VIADEO
] as $legacy_type) {
1305 $replacements['_asso_social_' . $legacy_type] = $replacements['asso_social_' . $legacy_type];
1308 $this->setReplacements($replacements);
1316 * @param string $value Value to clean
1320 public function cleanHtmlValue(string $value): string
1322 $config = \HTMLPurifier_Config
::createDefault();
1323 $config->set('Cache.SerializerPath', GALETTE_CACHE_DIR
);
1324 $purifier = new \
HTMLPurifier($config);
1325 return $purifier->purify($value);