]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Core/Preferences.php
Few fixes
[galette.git] / galette / lib / Galette / Core / Preferences.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * Preferences handling
7 *
8 * PHP version 5
9 *
10 * Copyright © 2007-2014 The Galette Team
11 *
12 * This file is part of Galette (http://galette.tuxfamily.org).
13 *
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.
18 *
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.
23 *
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/>.
26 *
27 * @category Core
28 * @package Galette
29 * @author Johan Cwiklinski <johan@x-tnd.be>
30 * @copyright 2007-2014 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
34 */
35
36 namespace Galette\Core;
37
38 use Analog\Analog;
39 use Galette\Entity\Adherent;
40 use Galette\Entity\Status;
41 use Galette\Core\Db;
42 use Galette\IO\PdfMembersCards;
43 use Galette\Repository\Members;
44
45 /**
46 * Preferences for galette
47 *
48 * @category Core
49 * @name Preferences
50 * @package Galette
51 * @author Johan Cwiklinski <johan@x-tnd.be>
52 * @copyright 2007-2014 The Galette Team
53 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
54 * @link http://galette.tuxfamily.org
55 * @since Available since 0.7dev - 2007-10-14
56 *
57 * @property string $pref_admin_login Super admin login
58 * @property string $pref_admin_pass Super admin password
59 * @property string $pref_nom Association name
60 * @property string $pref_slogan Association slogan
61 * @property string $pref_adresse Address
62 * @property string $pref_adresse2 Address continuation
63 * @property string $pref_cp Association zipcode
64 * @property string $pref_ville Association town
65 * @property string $pref_pays Country
66 * @property integer $pref_postal_adress Postal adress to use, one of self::POSTAL_ADDRESS*
67 * @property integer $pref_postal_staff_member Staff member ID from which retrieve postal address
68 * @property string $pref_lang Default instance language
69 * @property integer $pref_numrows Default number of rows in lists
70 * @property integer $pref_log History, one of self::LOG_*
71 * @property interger $pref_statut Default status for new members
72 * @property string $pref_email_nom
73 * @property string $pref_email
74 * @property string $pref_email_newadh
75 * @property boolean $pref_bool_mailadh
76 * @property boolean $pref_editor_enabled
77 * @property integer $pref_mail_method Mail method, see GaletteMail::METHOD_*
78 * @property string $pref_mail_smtp
79 * @property string $pref_mail_smtp_host
80 * @property boolean $pref_mail_smtp_auth
81 * @property boolean $pref_mail_smtp_secure
82 * @property integer $pref_mail_smtp_port
83 * @property string $pref_mail_smtp_user
84 * @property string $pref_mail_smtp_password
85 * @property integer $pref_membership_ext
86 * @property string $pref_beg_membership
87 * @property integer $pref_membership_offermonths
88 * @property string $pref_email_reply_to
89 * @property string $pref_website
90 * @property integer $pref_etiq_marges_v
91 * @property string $pref_etiq_marges_h
92 * @property string $pref_etiq_hspace
93 * @property string $pref_etiq_vspace
94 * @property string $pref_etiq_hsize
95 * @property string $pref_etiq_vsize
96 * @property string $pref_etiq_cols
97 * @property string $pref_etiq_rows
98 * @property string $pref_etiq_corps
99 * @property string $pref_card_abrev
100 * @property string $pref_card_strip
101 * @property string $pref_card_tcol
102 * @property string $pref_card_scol
103 * @property string $pref_card_bcol
104 * @property string $pref_card_hcol
105 * @property string $pref_bool_display_title
106 * @property integer $pref_card_address
107 * @property string $pref_card_year
108 * @property integer $pref_card_marges_v
109 * @property integer $pref_card_marges_h
110 * @property integer $pref_card_vspace
111 * @property integer $pref_card_hspace
112 * @property string $pref_card_self
113 * @property string $pref_theme Prefered theme
114 * @property boolean $pref_bool_publicpages
115 * @property integer $pref_publicpages_visibility
116 * @property boolean $pref_bool_selfsubscribe
117 * @property string $pref_googleplus
118 * @property string $pref_facebook
119 * @property string $pref_twitter
120 * @property string $pref_viadeo
121 * @property string $pref_linkedin
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-read string $vpref_email_newadh Comma separated list of mail senders
141 */
142 class Preferences
143 {
144 private $zdb;
145 private $prefs;
146 private $errors = [];
147
148 public const TABLE = 'preferences';
149 public const PK = 'nom_pref';
150
151 /** Postal address will be the one given in the preferences */
152 public const POSTAL_ADDRESS_FROM_PREFS = 0;
153 /** Postal address will be the one of the selected staff member */
154 public const POSTAL_ADDRESS_FROM_STAFF = 1;
155
156 /** Public pages stuff */
157 /** Public pages are publically visibles */
158 public const PUBLIC_PAGES_VISIBILITY_PUBLIC = 0;
159 /** Public pages are visibles for up to date members only */
160 public const PUBLIC_PAGES_VISIBILITY_RESTRICTED = 1;
161 /** Public pages are visibles for admin and staff members only */
162 public const PUBLIC_PAGES_VISIBILITY_PRIVATE = 2;
163
164 public const LOG_DISABLED = 0;
165 public const LOG_ENABLED = 1;
166
167 /** No password strength */
168 public const PWD_NONE = 0;
169 /** Weak password strength */
170 public const PWD_WEAK = 1;
171 /** Medium password strength */
172 public const PWD_MEDIUM = 2;
173 /** Strong password strength */
174 public const PWD_STRONG = 3;
175 /** Very strong password strength */
176 public const PWD_VERY_STRONG = 4;
177
178 private static $fields = array(
179 'nom_pref',
180 'val_pref'
181 );
182
183 private static $defaults = array(
184 'pref_admin_login' => 'admin',
185 'pref_admin_pass' => 'admin',
186 'pref_nom' => 'Galette',
187 'pref_slogan' => '',
188 'pref_adresse' => '-',
189 'pref_adresse2' => '',
190 'pref_cp' => '',
191 'pref_ville' => '',
192 'pref_pays' => '',
193 'pref_postal_adress' => self::POSTAL_ADDRESS_FROM_PREFS,
194 'pref_postal_staff_member' => '',
195 'pref_lang' => I18n::DEFAULT_LANG,
196 'pref_numrows' => 30,
197 'pref_log' => self::LOG_ENABLED,
198 'pref_statut' => Status::DEFAULT_STATUS,
199 /* Preferences for emails */
200 'pref_email_nom' => 'Galette',
201 'pref_email' => 'mail@domain.com',
202 'pref_email_newadh' => 'mail@domain.com',
203 'pref_bool_mailadh' => false,
204 'pref_editor_enabled' => false,
205 'pref_mail_method' => GaletteMail::METHOD_DISABLED,
206 'pref_mail_smtp' => '',
207 'pref_mail_smtp_host' => '',
208 'pref_mail_smtp_auth' => false,
209 'pref_mail_smtp_secure' => false,
210 'pref_mail_smtp_port' => '',
211 'pref_mail_smtp_user' => '',
212 'pref_mail_smtp_password' => '',
213 'pref_membership_ext' => 12,
214 'pref_beg_membership' => '',
215 'pref_membership_offermonths' => 0,
216 'pref_email_reply_to' => '',
217 'pref_website' => '',
218 /* Preferences for labels */
219 'pref_etiq_marges_v' => 10,
220 'pref_etiq_marges_h' => 10,
221 'pref_etiq_hspace' => 10,
222 'pref_etiq_vspace' => 5,
223 'pref_etiq_hsize' => 90,
224 'pref_etiq_vsize' => 35,
225 'pref_etiq_cols' => 2,
226 'pref_etiq_rows' => 7,
227 'pref_etiq_corps' => 12,
228 /* Preferences for members cards */
229 'pref_card_abrev' => 'GALETTE',
230 'pref_card_strip' => 'Gestion d\'Adherents en Ligne Extrêmement Tarabiscotée',
231 'pref_card_tcol' => '#FFFFFF',
232 'pref_card_scol' => '#8C2453',
233 'pref_card_bcol' => '#53248C',
234 'pref_card_hcol' => '#248C53',
235 'pref_bool_display_title' => false,
236 'pref_card_address' => 1,
237 'pref_card_year' => '',
238 'pref_card_marges_v' => 15,
239 'pref_card_marges_h' => 20,
240 'pref_card_vspace' => 5,
241 'pref_card_hspace' => 10,
242 'pref_card_self' => 1,
243 'pref_theme' => 'default',
244 'pref_bool_publicpages' => true,
245 'pref_publicpages_visibility' => self::PUBLIC_PAGES_VISIBILITY_RESTRICTED,
246 'pref_bool_selfsubscribe' => true,
247 'pref_googleplus' => '',
248 'pref_facebook' => '',
249 'pref_twitter' => '',
250 'pref_viadeo' => '',
251 'pref_linkedin' => '',
252 'pref_mail_sign' => "{NAME}\r\n\r\n{WEBSITE}\r\n{GOOGLEPLUS}\r\n{FACEBOOK}\r\n{TWITTER}\r\n{LINKEDIN}\r\n{VIADEO}",
253 /* New contribution script */
254 'pref_new_contrib_script' => '',
255 'pref_bool_wrap_mails' => true,
256 'pref_rss_url' => 'http://galette.eu/dc/index.php/feed/atom',
257 'pref_show_id' => false,
258 'pref_adhesion_form' => '\Galette\IO\PdfAdhesionForm',
259 'pref_mail_allow_unsecure' => false,
260 'pref_instance_uuid' => '',
261 'pref_registration_uuid' => '',
262 'pref_telemetry_date' => '',
263 'pref_registration_date' => '',
264 'pref_footer' => '',
265 'pref_filter_account' => Members::ALL_ACCOUNTS,
266 'pref_galette_url' => '',
267 'pref_redirect_on_create' => Adherent::AFTER_ADD_DEFAULT,
268 /* Security related */
269 'pref_password_length' => 6,
270 'pref_password_blacklist' => false,
271 'pref_password_strength' => self::PWD_NONE
272 );
273
274 // flagging required fields
275 private $required = array(
276 'pref_nom',
277 'pref_lang',
278 'pref_numrows',
279 'pref_log',
280 'pref_etiq_marges_v',
281 'pref_etiq_marges_h',
282 'pref_etiq_hspace',
283 'pref_etiq_vspace',
284 'pref_etiq_hsize',
285 'pref_etiq_vsize',
286 'pref_etiq_cols',
287 'pref_etiq_rows',
288 'pref_etiq_corps',
289 'pref_card_abrev',
290 'pref_card_strip',
291 'pref_card_marges_v',
292 'pref_card_marges_h',
293 'pref_card_hspace',
294 'pref_card_vspace'
295 );
296
297 /**
298 * Default constructor
299 *
300 * @param Db $zdb Db instance
301 * @param boolean $load Automatically load preferences on load
302 *
303 * @return void
304 */
305 public function __construct(Db $zdb, $load = true)
306 {
307 $this->zdb = $zdb;
308 if ($load) {
309 $this->load();
310 $this->checkUpdate();
311 }
312 }
313
314 /**
315 * Check if all fields referenced in the default array does exists,
316 * create them if not
317 *
318 * @return void
319 */
320 private function checkUpdate()
321 {
322 $proceed = false;
323 $params = array();
324 foreach (self::$defaults as $k => $v) {
325 if (!isset($this->prefs[$k])) {
326 $this->prefs[$k] = $v;
327 Analog::log(
328 'The field `' . $k . '` does not exists, Galette will attempt to create it.',
329 Analog::INFO
330 );
331 $proceed = true;
332 $params[] = array(
333 'nom_pref' => $k,
334 'val_pref' => $v
335 );
336 }
337 }
338 if ($proceed !== false) {
339 try {
340 $insert = $this->zdb->insert(self::TABLE);
341 $insert->values(
342 array(
343 'nom_pref' => ':nom_pref',
344 'val_pref' => ':val_pref'
345 )
346 );
347 $stmt = $this->zdb->sql->prepareStatementForSqlObject($insert);
348
349 foreach ($params as $p) {
350 $stmt->execute(
351 array(
352 'nom_pref' => $p['nom_pref'],
353 'val_pref' => $p['val_pref']
354 )
355 );
356 }
357 } catch (\Exception $e) {
358 Analog::log(
359 'Unable to add missing preferences.' . $e->getMessage(),
360 Analog::WARNING
361 );
362 return false;
363 }
364
365 Analog::log(
366 'Missing preferences were successfully stored into database.',
367 Analog::INFO
368 );
369 }
370 }
371
372 /**
373 * Load current preferences from database.
374 *
375 * @return boolean
376 */
377 public function load()
378 {
379 $this->prefs = array();
380
381 try {
382 $result = $this->zdb->selectAll(self::TABLE);
383 foreach ($result as $pref) {
384 $this->prefs[$pref->nom_pref] = $pref->val_pref;
385 }
386 return true;
387 } catch (\Exception $e) {
388 Analog::log(
389 'Preferences cannot be loaded. Galette should not work without ' .
390 'preferences. Exiting.',
391 Analog::URGENT
392 );
393 return false;
394 }
395 }
396
397 /**
398 * Set default preferences at install time
399 *
400 * @param string $lang language selected at install screen
401 * @param string $adm_login admin login entered at install time
402 * @param string $adm_pass admin password entered at install time
403 *
404 * @return boolean|\Exception
405 */
406 public function installInit($lang, $adm_login, $adm_pass)
407 {
408 try {
409 //first, we drop all values
410 $delete = $this->zdb->delete(self::TABLE);
411 $this->zdb->execute($delete);
412
413 //we then replace default values with the ones user has selected
414 $values = self::$defaults;
415 $values['pref_lang'] = $lang;
416 $values['pref_admin_login'] = $adm_login;
417 $values['pref_admin_pass'] = $adm_pass;
418 $values['pref_card_year'] = date('Y');
419
420 $insert = $this->zdb->insert(self::TABLE);
421 $insert->values(
422 array(
423 'nom_pref' => ':nom_pref',
424 'val_pref' => ':val_pref'
425 )
426 );
427 $stmt = $this->zdb->sql->prepareStatementForSqlObject($insert);
428
429 foreach ($values as $k => $v) {
430 $stmt->execute(
431 array(
432 'nom_pref' => $k,
433 'val_pref' => $v
434 )
435 );
436 }
437
438 Analog::log(
439 'Default preferences were successfully stored into database.',
440 Analog::INFO
441 );
442 return true;
443 } catch (\Exception $e) {
444 Analog::log(
445 'Unable to initialize default preferences.' . $e->getMessage(),
446 Analog::WARNING
447 );
448 return $e;
449 }
450 }
451
452 /**
453 * Returns all preferences keys
454 *
455 * @return array
456 */
457 public function getFieldsNames()
458 {
459 return array_keys($this->prefs);
460 }
461
462 /**
463 * Check values
464 *
465 * @param array $values Values
466 * @param Login $login Logged in user
467 *
468 * @return boolean
469 */
470 public function check(array $values, Login $login)
471 {
472 $insert_values = array();
473 if ($login->isSuperAdmin() && GALETTE_MODE !== 'DEMO') {
474 $this->required[] = 'pref_admin_login';
475 }
476
477 // obtain fields
478 foreach ($this->getFieldsNames() as $fieldname) {
479 if (isset($values[$fieldname])) {
480 $value = trim($values[$fieldname]);
481 } else {
482 $value = "";
483 }
484
485 $insert_values[$fieldname] = $value;
486 }
487
488 // missing relations
489 if (
490 GALETTE_MODE !== 'DEMO'
491 && isset($insert_values['pref_mail_method'])
492 ) {
493 if ($insert_values['pref_mail_method'] > GaletteMail::METHOD_DISABLED) {
494 if (
495 !isset($insert_values['pref_email_nom'])
496 || $insert_values['pref_email_nom'] == ''
497 ) {
498 $this->errors[] = _T("- You must indicate a sender name for emails!");
499 }
500 if (
501 !isset($insert_values['pref_email'])
502 || $insert_values['pref_email'] == ''
503 ) {
504 $this->errors[] = _T("- You must indicate an email address Galette should use to send emails!");
505 }
506 if ($insert_values['pref_mail_method'] == GaletteMail::METHOD_SMTP) {
507 if (
508 !isset($insert_values['pref_mail_smtp_host'])
509 || $insert_values['pref_mail_smtp_host'] == ''
510 ) {
511 $this->errors[] = _T("- You must indicate the SMTP server you want to use!");
512 }
513 }
514 if (
515 $insert_values['pref_mail_method'] == GaletteMail::METHOD_GMAIL
516 || ($insert_values['pref_mail_method'] == GaletteMail::METHOD_SMTP
517 && $insert_values['pref_mail_smtp_auth'])
518 ) {
519 if (
520 !isset($insert_values['pref_mail_smtp_user'])
521 || trim($insert_values['pref_mail_smtp_user']) == ''
522 ) {
523 $this->errors[] = _T("- You must provide a login for SMTP authentication.");
524 }
525 if (
526 !isset($insert_values['pref_mail_smtp_password'])
527 || ($insert_values['pref_mail_smtp_password']) == ''
528 ) {
529 $this->errors[] = _T("- You must provide a password for SMTP authentication.");
530 }
531 }
532 }
533 }
534
535 if (
536 isset($insert_values['pref_beg_membership'])
537 && $insert_values['pref_beg_membership'] != ''
538 && isset($insert_values['pref_membership_ext'])
539 && $insert_values['pref_membership_ext'] != ''
540 ) {
541 $this->errors[] = _T("- Default membership extention and beginning of membership are mutually exclusive.");
542 }
543
544 if (
545 isset($insert_values['pref_membership_offermonths'])
546 && (int)$insert_values['pref_membership_offermonths'] > 0
547 && isset($insert_values['pref_membership_ext'])
548 && $insert_values['pref_membership_ext'] != ''
549 ) {
550 $this->errors[] = _T("- Offering months is only compatible with beginning of membership.");
551 }
552
553 // missing required fields?
554 foreach ($this->required as $val) {
555 if (!isset($values[$val]) || isset($values[$val]) && trim($values[$val]) == '') {
556 $this->errors[] = str_replace(
557 '%field',
558 $val,
559 _T("- Mandatory field %field empty.")
560 );
561 }
562 }
563
564 if (GALETTE_MODE !== 'DEMO' && isset($values['pref_admin_pass_check'])) {
565 // Check passwords. Hash will be done into the Preferences class
566 if (strcmp($insert_values['pref_admin_pass'], $values['pref_admin_pass_check']) != 0) {
567 $this->errors[] = _T("Passwords mismatch");
568 }
569 }
570
571 //postal address
572 if (isset($insert_values['pref_postal_adress'])) {
573 $value = $insert_values['pref_postal_adress'];
574 if ($value == Preferences::POSTAL_ADDRESS_FROM_PREFS) {
575 if (isset($insert_values['pref_postal_staff_member'])) {
576 unset($insert_values['pref_postal_staff_member']);
577 }
578 } elseif ($value == Preferences::POSTAL_ADDRESS_FROM_STAFF) {
579 if (!isset($value) || $value < 1) {
580 $this->errors[] = _T("You have to select a staff member");
581 }
582 }
583 }
584
585 // update preferences
586 foreach ($insert_values as $champ => $valeur) {
587 if (
588 $login->isSuperAdmin()
589 || (!$login->isSuperAdmin()
590 && ($champ != 'pref_admin_pass' && $champ != 'pref_admin_login'))
591 ) {
592 if (
593 ($champ == "pref_admin_pass" && $_POST['pref_admin_pass'] != '')
594 || ($champ != "pref_admin_pass")
595 ) {
596 $this->$champ = $valeur;
597 }
598 }
599 }
600
601 return 0 === count($this->errors);
602 }
603
604 /**
605 * Validate value of a field
606 *
607 * @param string $fieldname Field name
608 * @param mixed $value Value to be set
609 *
610 * @return mixed
611 */
612 public function validateValue($fieldname, $value)
613 {
614 global $login;
615
616 switch ($fieldname) {
617 case 'pref_email':
618 case 'pref_email_newadh':
619 case 'pref_email_reply_to':
620 //check emails validity
621 //may be a comma separated list of valid emails identifiers:
622 //"The Name <mail@domain.com>,The Other <other@mail.com>" expect for reply_to.
623 $addresses = [];
624 if (trim($value) != '') {
625 if ($fieldname == 'pref_email_newadh') {
626 $addresses = explode(',', $value);
627 } else {
628 $addresses = [$value];
629 }
630 }
631 foreach ($addresses as $address) {
632 if (!GaletteMail::isValidEmail($address)) {
633 $msg = str_replace('%s', $address, _T("Invalid E-Mail address: %s"));
634 Analog::log($msg, Analog::WARNING);
635 $this->errors[] = $msg;
636 }
637 }
638 break;
639 case 'pref_admin_login':
640 if (GALETTE_MODE === 'DEMO') {
641 Analog::log(
642 'Trying to set superadmin login while in DEMO.',
643 Analog::WARNING
644 );
645 } else {
646 if (strlen($value) < 4) {
647 $this->errors[] = _T("- The username must be composed of at least 4 characters!");
648 } else {
649 //check if login is already taken
650 if ($login->loginExists($value)) {
651 $this->errors[] = _T("- This username is already used by another member !");
652 }
653 }
654 }
655 break;
656 case 'pref_numrows':
657 if (!is_numeric($value) || $value < 0) {
658 $this->errors[] = _T("- The numbers and measures have to be integers!");
659 }
660 break;
661 case 'pref_etiq_marges_h':
662 case 'pref_etiq_marges_v':
663 case 'pref_etiq_hspace':
664 case 'pref_etiq_vspace':
665 case 'pref_etiq_hsize':
666 case 'pref_etiq_vsize':
667 case 'pref_etiq_cols':
668 case 'pref_etiq_rows':
669 case 'pref_etiq_corps':
670 case 'pref_card_marges_v':
671 case 'pref_card_marges_h':
672 case 'pref_card_hspace':
673 case 'pref_card_vspace':
674 // prevent division by zero
675 if ($fieldname == 'pref_numrows' && $value == '0') {
676 $value = '10';
677 }
678 if (!is_numeric($value) || $value < 0) {
679 $this->errors[] = _T("- The numbers and measures have to be integers!");
680 }
681 break;
682 case 'pref_card_tcol':
683 case 'pref_card_scol':
684 case 'pref_card_bcol':
685 case 'pref_card_hcol':
686 $matches = [];
687 if (!preg_match("/^(#)?([0-9A-F]{6})$/i", $value, $matches)) {
688 // Set strip background colors to black or white (for tcol)
689 $value = ($fieldname == 'pref_card_tcol' ? '#FFFFFF' : '#000000');
690 } else {
691 $value = '#' . $matches[2];
692 }
693 break;
694 case 'pref_admin_pass':
695 if (GALETTE_MODE == 'DEMO') {
696 Analog::log(
697 'Trying to set superadmin pass while in DEMO.',
698 Analog::WARNING
699 );
700 } else {
701 $pwcheck = new \Galette\Util\Password($this);
702 $pwcheck->addPersonalInformation(['pref_admin_login' => $this->pref_admin_login]);
703 if (!$pwcheck->isValid($value)) {
704 $this->errors = array_merge(
705 $this->errors,
706 $pwcheck->getErrors()
707 );
708 }
709 }
710 break;
711 case 'pref_membership_ext':
712 if (!is_numeric($value) || $value < 0) {
713 $this->errors[] = _T("- Invalid number of months of membership extension.");
714 }
715 break;
716 case 'pref_beg_membership':
717 $beg_membership = explode("/", $value);
718 if (count($beg_membership) != 2) {
719 $this->errors[] = _T("- Invalid format of beginning of membership.");
720 } else {
721 $now = getdate();
722 if (!checkdate($beg_membership[1], $beg_membership[0], $now['year'])) {
723 $this->errors[] = _T("- Invalid date for beginning of membership.");
724 }
725 }
726 break;
727 case 'pref_membership_offermonths':
728 if (!is_numeric($value) || $value < 0) {
729 $this->errors[] = _T("- Invalid number of offered months.");
730 }
731 break;
732 case 'pref_card_year':
733 if ($value !== 'DEADLINE' && !preg_match('/^(?:\d{4}|\d{2})(\D?)(?:\d{4}|\d{2})$/', $value)) {
734 $this->errors[] = _T("- Invalid year for cards.");
735 }
736 break;
737 }
738
739 return $value;
740 }
741
742 /**
743 * Will store all preferences in the database
744 *
745 * @return boolean
746 */
747 public function store()
748 {
749 try {
750 $this->zdb->connection->beginTransaction();
751 $update = $this->zdb->update(self::TABLE);
752 $update->set(
753 array(
754 'val_pref' => ':val_pref'
755 )
756 )->where->equalTo('nom_pref', ':nom_pref');
757
758 $stmt = $this->zdb->sql->prepareStatementForSqlObject($update);
759
760 foreach (self::$defaults as $k => $v) {
761 if (
762 GALETTE_MODE == 'DEMO'
763 && in_array($k, ['pref_admin_pass', 'pref_admin_login', 'pref_mail_method'])
764 ) {
765 continue;
766 }
767 Analog::log('Storing ' . $k, Analog::DEBUG);
768
769 $value = $this->prefs[$k];
770 //do not store pdf_adhesion_form, it's designed to be overriden by plugin
771 if ($k === 'pref_adhesion_form') {
772 if (trim($v) == '') {
773 //Reset to default, should not be empty
774 $v = self::$defaults['pref_adhesion_form'];
775 }
776 $value = $v;
777 }
778
779 $stmt->execute(
780 array(
781 'val_pref' => $value,
782 'where1' => $k
783 )
784 );
785 }
786 $this->zdb->connection->commit();
787 Analog::log(
788 'Preferences were successfully stored into database.',
789 Analog::INFO
790 );
791 return true;
792 } catch (\Exception $e) {
793 $this->zdb->connection->rollBack();
794
795 $messages = array();
796 do {
797 $messages[] = $e->getMessage();
798 } while ($e = $e->getPrevious());
799
800 Analog::log(
801 'Unable to store preferences | ' . print_r($messages, true),
802 Analog::WARNING
803 );
804 return false;
805 }
806 }
807
808 /**
809 * Returns postal address
810 *
811 * @return string postal address
812 */
813 public function getPostalAddress()
814 {
815 $regs = array(
816 '/%name/',
817 '/%complement/',
818 '/%address/',
819 '/%zip/',
820 '/%town/',
821 '/%country/',
822 );
823
824 $replacements = null;
825
826 if ($this->prefs['pref_postal_adress'] == self::POSTAL_ADDRESS_FROM_PREFS) {
827 $_address = $this->prefs['pref_adresse'];
828 if ($this->prefs['pref_adresse2'] && $this->prefs['pref_adresse2'] != '') {
829 $_address .= "\n" . $this->prefs['pref_adresse2'];
830 }
831 $replacements = array(
832 $this->prefs['pref_nom'],
833 "\n",
834 $_address,
835 $this->prefs['pref_cp'],
836 $this->prefs['pref_ville'],
837 $this->prefs['pref_pays']
838 );
839 } else {
840 //get selected staff member address
841 $adh = new Adherent($this->zdb, (int)$this->prefs['pref_postal_staff_member']);
842 $_complement = preg_replace(
843 array('/%name/', '/%status/'),
844 array($this->prefs['pref_nom'], $adh->sstatus),
845 _T("%name association's %status")
846 ) . "\n";
847 $_address = $adh->address;
848 if ($adh->address_continuation && $adh->address_continuation != '') {
849 $_address .= "\n" . $adh->address_continuation;
850 }
851 $replacements = array(
852 $adh->sfullname . "\n",
853 $_complement,
854 $_address,
855 $adh->zipcode,
856 $adh->town,
857 $adh->country
858 );
859 }
860
861 /*FIXME: i18n fails :/ */
862 /*$r = preg_replace(
863 $regs,
864 $replacements,
865 _T("%name\n%complement\n%address\n%zip %town - %country")
866 );*/
867 $r = preg_replace(
868 $regs,
869 $replacements,
870 "%name%complement%address\n%zip %town - %country"
871 );
872 return $r;
873 }
874
875 /**
876 * Are public pages visibles?
877 *
878 * @param Authentication $login Authenticaqtion instance
879 *
880 * @return boolean
881 */
882 public function showPublicPages(Authentication $login)
883 {
884 if ($this->prefs['pref_bool_publicpages']) {
885 //if public pages are actives, let's check if we
886 //display them for curent call
887 switch ($this->prefs['pref_publicpages_visibility']) {
888 case self::PUBLIC_PAGES_VISIBILITY_PUBLIC:
889 //pages are publically visibles
890 return true;
891 break;
892 case self::PUBLIC_PAGES_VISIBILITY_RESTRICTED:
893 //pages should be displayed only for up to date members
894 if (
895 $login->isUp2Date()
896 || $login->isAdmin()
897 || $login->isStaff()
898 ) {
899 return true;
900 } else {
901 return false;
902 }
903 break;
904 case self::PUBLIC_PAGES_VISIBILITY_PRIVATE:
905 //pages should be displayed only for staff and admins
906 if ($login->isAdmin() || $login->isStaff()) {
907 return true;
908 } else {
909 return false;
910 }
911 break;
912 default:
913 //should never be there
914 return false;
915 break;
916 }
917 } else {
918 return false;
919 }
920 }
921
922 /**
923 * Global getter method
924 *
925 * @param string $name name of the property we want to retrive
926 *
927 * @return false|object the called property
928 */
929 public function __get($name)
930 {
931 $forbidden = array('defaults');
932 $virtuals = array('vpref_email_newadh');
933
934 if (!in_array($name, $forbidden) && isset($this->prefs[$name])) {
935 if (
936 GALETTE_MODE === 'DEMO'
937 && $name == 'pref_mail_method'
938 ) {
939 return GaletteMail::METHOD_DISABLED;
940 } else {
941 if ($name == 'pref_adhesion_form' && $this->prefs[$name] == '') {
942 $this->prefs[$name] = self::$defaults['pref_adhesion_form'];
943 }
944 $value = $this->prefs[$name];
945 if (TYPE_DB === \Galette\Core\Db::PGSQL) {
946 if ($value === 'f') {
947 $value = false;
948 }
949 }
950
951 if (in_array($name, ['pref_email_newadh'])) {
952 $values = explode(',', $value);
953 $value = $values[0]; //take first as default
954 }
955
956 return $value;
957 }
958 } elseif (in_array($name, $virtuals)) {
959 $virtual = str_replace('vpref_', 'pref_', $name);
960 return explode(',', $this->prefs[$virtual]);
961 } else {
962 Analog::log(
963 'Preference `' . $name . '` is not set or is forbidden',
964 Analog::INFO
965 );
966 return false;
967 }
968 }
969
970 /**
971 * Get default preferences
972 *
973 * @return array
974 */
975 public function getDefaults()
976 {
977 return self::$defaults;
978 }
979
980 /**
981 * Global setter method
982 *
983 * @param string $name name of the property we want to assign a value to
984 * @param object $value a relevant value for the property
985 *
986 * @return void
987 */
988 public function __set($name, $value)
989 {
990 //does this pref exists ?
991 if (!array_key_exists($name, self::$defaults)) {
992 Analog::log(
993 'Trying to set a preference value which does not seem to exist ('
994 . $name . ')',
995 Analog::WARNING
996 );
997 return false;
998 }
999
1000 if (
1001 $name == 'pref_email'
1002 || $name == 'pref_email_newadh'
1003 || $name == 'pref_email_reply_to'
1004 ) {
1005 if (GALETTE_MODE === 'DEMO') {
1006 Analog::log(
1007 'Trying to set pref_email while in DEMO.',
1008 Analog::WARNING
1009 );
1010 return;
1011 }
1012 }
1013
1014 // now, check validity
1015 if ($value != '') {
1016 $value = $this->validateValue($name, $value);
1017 }
1018
1019 //some values need to be changed (eg. passwords)
1020 if ($name == 'pref_admin_pass') {
1021 $value = password_hash($value, PASSWORD_BCRYPT);
1022 }
1023
1024 //okay, let's update value
1025 $this->prefs[$name] = $value;
1026 }
1027
1028 /**
1029 * Get instance URL from configuration (if set) or guessed if not
1030 *
1031 * @return string
1032 */
1033 public function getURL()
1034 {
1035 $url = null;
1036 if (isset($this->prefs['pref_galette_url']) && !empty($this->prefs['pref_galette_url'])) {
1037 $url = $this->prefs['pref_galette_url'];
1038 } else {
1039 $url = $this->getDefaultURL();
1040 }
1041 return $url;
1042 }
1043
1044 /**
1045 * Get default URL (when not setted by user in preferences)
1046 *
1047 * @return string
1048 */
1049 public function getDefaultURL()
1050 {
1051 $scheme = (isset($_SERVER['HTTPS']) ? 'https' : 'http');
1052 $uri = $scheme . '://' . $_SERVER['HTTP_HOST'];
1053 return $uri;
1054 }
1055
1056 /**
1057 * Check member cards sizes
1058 * Always a A4/portrait
1059 *
1060 * @return array
1061 */
1062 public function checkCardsSizes()
1063 {
1064 $warning_detected = [];
1065 //check page width
1066 $max = 210;
1067 //margins
1068 $size = $this->pref_card_marges_h * 2;
1069 //cards
1070 $size += PdfMembersCards::getWidth() * PdfMembersCards::getCols();
1071 //spacing
1072 $size += $this->pref_card_hspace * (PdfMembersCards::getCols() - 1);
1073 if ($size > $max) {
1074 $warning_detected[] = _T('Current cards configuration may exceed page width!');
1075 }
1076
1077 $max = 297;
1078 //margins
1079 $size = $this->pref_card_marges_v * 2;
1080 //cards
1081 $size += PdfMembersCards::getHeight() * PdfMembersCards::getRows();
1082 //spacing
1083 $size += $this->pref_card_vspace * (PdfMembersCards::getRows() - 1);
1084 if ($size > $max) {
1085 $warning_detected[] = _T('Current cards configuration may exceed page height!');
1086 }
1087
1088 return $warning_detected;
1089 }
1090
1091 /**
1092 * Get errors
1093 *
1094 * @return array
1095 */
1096 public function getErrors()
1097 {
1098 return $this->errors;
1099 }
1100 }