3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
6 * Members related routes
10 * Copyright © 2014-2018 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/>.
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2014-2018 The Galette Team
32 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
34 * @link http://galette.tuxfamily.org
35 * @since 0.8.2dev 2014-11-27
39 use Galette\Entity\DynamicFieldsHandle
;
40 use Galette\Core\Password
;
41 use Galette\Core\PasswordImage
;
42 use Galette\Core\Mailing
;
43 use Galette\Core\GaletteMail
;
44 use Galette\Repository\Members
;
45 use Galette\Filters\MembersList
;
46 use Galette\Filters\SavedSearchesList
;
47 use Galette\Filters\AdvancedMembersList
;
48 use Galette\Entity\FieldsConfig
;
49 use Galette\Entity\Contribution
;
50 use Galette\Repository\Groups
;
51 use Galette\Repository\Reminders
;
52 use Galette\Entity\Adherent
;
53 use Galette\IO\PdfMembersCards
;
54 use Galette\IO\PdfMembersLabels
;
56 use Galette\IO\CsvOut
;
57 use Galette\Entity\Status
;
58 use Galette\Repository\Titles
;
59 use Galette\Entity\Texts
;
61 use Galette\Core\MailingHistory
;
62 use Galette\Entity\Group
;
64 use Galette\Core\Authentication
;
65 use Galette\Repository\PaymentTypes
;
66 use Galette\Repository\SavedSearches
;
71 function ($request, $response) {
72 if (!$this->preferences
->pref_bool_selfsubscribe ||
$this->login
->isLogged()) {
75 ->withHeader('Location', $this->router
->pathFor('slash'));
78 if ($this->session
->member
!== null) {
79 $member = $this->session
->member
;
80 $this->session
->member
= null;
85 $member = new Adherent($this->zdb
, null, $deps);
88 //mark as self membership
89 $member->setSelfMembership();
91 // flagging required fields
92 $fc = $this->fields_config
;
93 $form_elements = $fc->getFormElements($this->login
, true, true);
95 //image to defeat mass filling forms
96 $spam = new PasswordImage();
97 $spam_pass = $spam->newImage();
98 $spam_img = $spam->getImage();
103 $required_fields = array(
108 $list_members = $m->getList(false, $required_fields, true);
110 if (count($list_members) > 0) {
111 foreach ($list_members as $lmember) {
113 $sname = mb_strtoupper($lmember->nom_adh
, 'UTF-8') .
114 ' ' . ucwords(mb_strtolower($lmember->prenom_adh
, 'UTF-8')) .
115 ' (' . $lmember->id_adh
. ')';
116 $members[$lmember->$pk] = $sname;
120 $params['members'] = [
121 'filters' => $m->getFilters(),
122 'count' => $m->getCount()
125 //check if current attached member is part of the list
126 if ($member->hasParent()) {
127 if (!isset($members[$member->parent
->id
])) {
129 [$member->parent
->id
=> $member->parent
->getSName()] +
135 if (count($members)) {
136 $params['members']['list'] = $members;
144 'page_title' => _T("Subscription"),
145 'parent_tpl' => 'public_page.tpl',
148 'require_calendar' => true,
149 'autocomplete' => true,
152 'titles_list' => Titles
::getList($this->zdb
),
154 'spam_pass' => $spam_pass,
155 'spam_img' => $spam_img,
156 'fieldsets' => $form_elements['fieldsets'],
157 'hidden_elements' => $form_elements['hiddens']
162 )->setName('subscribe');
164 //members list CSV export
166 '/members/export/csv',
167 function ($request, $response) {
170 if (isset($this->session
->filter_members
)) {
171 //CAUTION: this one may be simple or advanced, display must change
172 $filters = $this->session
->filter_members
;
174 $filters = new MembersList();
177 $export_fields = null;
178 if (file_exists(GALETTE_CONFIG_PATH
. 'local_export_fields.inc.php')) {
179 include_once GALETTE_CONFIG_PATH
. 'local_export_fields.inc.php';
180 $export_fields = $fields;
184 $fc = $this->fields_config
;
185 $visibles = $fc->getVisibilities();
186 //hack for id_adh and parent_id
187 $hacks = ['id_adh', 'parent_id'];
188 foreach ($hacks as $hack) {
189 if ($visibles[$hack] == FieldsConfig
::NOBODY
) {
190 $visibles[$hack] = FieldsConfig
::MANAGER
;
193 $access_level = $this->login
->getAccessLevel();
196 foreach ($this->members_fields
as $k => $f) {
197 // skip fields blacklisted for export
198 if ($k === 'mdp_adh' ||
199 ($export_fields !== null &&
200 (is_array($export_fields) && !in_array($k, $export_fields)))
205 // skip fields according to access control
206 if ($visibles[$k] == FieldsConfig
::NOBODY ||
207 ($visibles[$k] == FieldsConfig
::ADMIN
&&
208 $access_level < Authentication
::ACCESS_ADMIN
) ||
209 ($visibles[$k] == FieldsConfig
::STAFF
&&
210 $access_level < Authentication
::ACCESS_STAFF
) ||
211 ($visibles[$k] == FieldsConfig
::MANAGER
&&
212 $access_level < Authentication
::ACCESS_MANAGER
)
218 $labels[] = $f['label'];
221 $members = new Members($filters);
222 $members_list = $members->getArrayList(
231 $s = new Status($this->zdb
);
232 $statuses = $s->getList();
235 $titles = $t->getList($this->zdb
);
237 foreach ($members_list as &$member) {
238 if (isset($member->id_statut
)) {
240 $member->id_statut
= $statuses[$member->id_statut
];
243 if (isset($member->titre_adh
)) {
245 $member->titre_adh
= $titles[$member->titre_adh
]->short
;
249 if (isset($member->date_crea_adh
)) {
250 if ($member->date_crea_adh
!= ''
251 && $member->date_crea_adh
!= '1901-01-01'
253 $dcrea = new DateTime($member->date_crea_adh
);
254 $member->date_crea_adh
= $dcrea->format(__("Y-m-d"));
256 $member->date_crea_adh
= '';
260 if (isset($member->date_modif_adh
)) {
261 if ($member->date_modif_adh
!= ''
262 && $member->date_modif_adh
!= '1901-01-01'
264 $dmodif = new DateTime($member->date_modif_adh
);
265 $member->date_modif_adh
= $dmodif->format(__("Y-m-d"));
267 $member->date_modif_adh
= '';
271 if (isset($member->date_echeance
)) {
272 if ($member->date_echeance
!= ''
273 && $member->date_echeance
!= '1901-01-01'
275 $dech = new DateTime($member->date_echeance
);
276 $member->date_echeance
= $dech->format(__("Y-m-d"));
278 $member->date_echeance
= '';
282 if (isset($member->ddn_adh
)) {
283 if ($member->ddn_adh
!= ''
284 && $member->ddn_adh
!= '1901-01-01'
286 $ddn = new DateTime($member->ddn_adh
);
287 $member->ddn_adh
= $ddn->format(__("Y-m-d"));
289 $member->ddn_adh
= '';
293 if (isset($member->sexe_adh
)) {
295 switch ($member->sexe_adh
) {
297 $member->sexe_adh
= _T("Man");
299 case Adherent
::WOMAN
:
300 $member->sexe_adh
= _T("Woman");
303 $member->sexe_adh
= _T("Unspecified");
309 if (isset($member->activite_adh
)) {
310 $member->activite_adh
311 = ($member->activite_adh
) ?
_T("Yes") : _T("No");
313 if (isset($member->bool_admin_adh
)) {
314 $member->bool_admin_adh
315 = ($member->bool_admin_adh
) ?
_T("Yes") : _T("No");
317 if (isset($member->bool_exempt_adh
)) {
318 $member->bool_exempt_adh
319 = ($member->bool_exempt_adh
) ?
_T("Yes") : _T("No");
321 if (isset($member->bool_display_info
)) {
322 $member->bool_display_info
323 = ($member->bool_display_info
) ?
_T("Yes") : _T("No");
326 $filename = 'filtered_memberslist.csv';
327 $filepath = CsvOut
::DEFAULT_DIRECTORY
. $filename;
328 $fp = fopen($filepath, 'w');
332 Csv
::DEFAULT_SEPARATOR
,
344 $filepath = CsvOut
::DEFAULT_DIRECTORY
. $filename;
345 if (file_exists($filepath)) {
346 $response = $this->response
->withHeader('Content-Description', 'File Transfer')
347 ->withHeader('Content-Type', 'text/csv')
348 ->withHeader('Content-Disposition', 'attachment;filename="' . $filename . '"')
349 ->withHeader('Pragma', 'no-cache')
350 ->withHeader('Content-Transfer-Encoding', 'binary')
351 ->withHeader('Expires', '0')
352 ->withHeader('Cache-Control', 'must-revalidate')
353 ->withHeader('Pragma', 'public')
354 ->withHeader('Content-Length', filesize($filepath));
356 $stream = fopen('php://memory', 'r+');
357 fwrite($stream, file_get_contents($filepath));
360 return $response->withBody(new \Slim\Http\
Stream($stream));
363 'A request has been made to get an exported file named `' .
364 $filename .'` that does not exists.',
367 $notFound = $this->notFoundHandler
;
368 return $notFound($request, $response);
372 )->setName('csv-memberslist')->add($authenticate);
376 '/members[/{option:page|order}/{value:\d+}]',
377 function ($request, $response, $args = []) {
379 if (isset($args['option'])) {
380 $option = $args['option'];
383 if (isset($args['value'])) {
384 $value = $args['value'];
387 if (isset($this->session
->filter_members
)) {
388 $filters = $this->session
->filter_members
;
390 $filters = new MembersList();
393 if ($option !== null) {
396 $filters->current_page
= (int)$value;
399 $filters->orderby
= $value;
404 $members = new Members($filters);
406 $members_list = array();
407 if ($this->login
->isAdmin() ||
$this->login
->isStaff()) {
408 $members_list = $members->getMembersList(true);
410 $members_list = $members->getManagedMembersList(true);
413 $groups = new Groups($this->zdb
, $this->login
);
414 $groups_list = $groups->getList();
416 //assign pagination variables to the template and add pagination links
417 $filters->setSmartyPagination($this->router
, $this->view
->getSmarty(), false);
418 $filters->setViewCommonsFilters($this->preferences
, $this->view
->getSmarty());
420 $this->session
->filter_members
= $filters;
425 'gestion_adherents.tpl',
427 'page_title' => _T("Members management"),
428 'require_dialog' => true,
429 'require_calendar' => true,
430 'require_mass' => true,
431 'members' => $members_list,
432 'filter_groups_options' => $groups_list,
433 'nb_members' => $members->getCount(),
434 'filters' => $filters,
435 'adv_filters' => $filters instanceof AdvancedMembersList
442 )->add($authenticate);
444 //members list filtering
447 function ($request, $response) {
448 $post = $request->getParsedBody();
449 if (isset($this->session
->filter_members
)) {
450 //CAUTION: this one may be simple or advanced, display must change
451 $filters = $this->session
->filter_members
;
453 $filters = new MembersList();
456 //reintialize filters
457 if (isset($post['clear_filter'])) {
458 $filters = new MembersList();
459 } elseif (isset($post['clear_adv_filter'])) {
460 $this->session
->filter_members
= null;
461 unset($this->session
->filter_members
);
465 ->withHeader('Location', $this->router
->pathFor('advanced-search'));
466 } elseif (isset($post['adv_criteria'])) {
469 ->withHeader('Location', $this->router
->pathFor('advanced-search'));
472 if (isset($post['filter_str'])) { //filter search string
473 $filters->filter_str
= stripslashes(
474 htmlspecialchars($post['filter_str'], ENT_QUOTES
)
478 if (isset($post['field_filter'])) {
479 if (is_numeric($post['field_filter'])) {
480 $filters->field_filter
= $post['field_filter'];
483 //membership to filter
484 if (isset($post['membership_filter'])) {
485 if (is_numeric($post['membership_filter'])) {
486 $filters->membership_filter
487 = $post['membership_filter'];
490 //account status to filter
491 if (isset($post['filter_account'])) {
492 if (is_numeric($post['filter_account'])) {
493 $filters->filter_account
= $post['filter_account'];
497 if (isset($post['email_filter'])) {
498 $filters->email_filter
= (int)$post['email_filter'];
501 if (isset($post['group_filter'])
502 && $post['group_filter'] > 0
504 $filters->group_filter
= (int)$post['group_filter'];
506 //number of rows to show
507 if (isset($post['nbshow'])) {
508 $filters->show
= $post['nbshow'];
511 if (isset($post['advanced_filtering'])) {
512 if (!$filters instanceof AdvancedMembersList
) {
513 $filters = new AdvancedMembersList($filters);
517 unset($post['advanced_filtering']);
519 foreach ($post as $k => $v) {
520 if (strpos($k, 'free_', 0) === 0) {
523 foreach ($post['free_field'] as $f) {
525 && trim($post['free_text'][$i]) !== ''
527 $fs_search = $post['free_text'][$i];
529 = (int)$post['free_logical_operator'][$i];
531 = (int)$post['free_query_operator'][$i];
532 $type = (int)$post['free_type'][$i];
537 'search' => $fs_search,
541 $filters->free_search
= $fs;
549 case 'contrib_min_amount':
550 case 'contrib_max_amount':
551 if (trim($v) !== '') {
564 if (isset($post['savesearch'])) {
569 $this->router
->pathFor(
576 $this->session
->filter_members
= $filters;
580 ->withHeader('Location', $this->router
->pathFor('members'));
582 )->setName('filter-memberslist')->add($authenticate);
587 function ($request, $response) {
588 if ($this->login
->isSuperAdmin()) {
591 ->withHeader('Location', $this->router
->pathFor('slash'));
602 $member = new Adherent($this->zdb
, $this->login
->login
, $deps);
605 $fc = $this->fields_config
;
606 $display_elements = $fc->getDisplayElements($this->login
);
613 'page_title' => _T("Member Profile"),
614 'require_dialog' => true,
616 'pref_lang' => $this->i18n
->getNameFromId($member->language
),
617 'pref_card_self' => $this->preferences
->pref_card_self
,
618 'groups' => Groups
::getSimpleList(),
620 'display_elements' => $display_elements
624 )->setName('me')->add($authenticate);
629 function ($request, $response, $args) {
640 $member = new Adherent($this->zdb
, (int)$id, $deps);
642 if ($this->login
->id
!= $id && !$this->login
->isAdmin() && !$this->login
->isStaff()) {
643 //check if requested member is part of managed groups
644 $groups = $member->groups
;
646 foreach ($groups as $g) {
647 if ($this->login
->isGroupManager($g->getId())) {
652 if ($is_managed !== true) {
653 //requested member is not part of managed groups,
654 //fall back to logged in member
656 'Trying to display member #' . $id . ' without appropriate ACLs',
664 $this->router
->pathFor(
666 ['id' => $this->login
->id
]
672 if ($member->id
== null) {
673 //member does not exists!
674 $this->flash
->addMessage(
676 str_replace('%id', $args['id'], _T("No member #%id."))
683 $this->router
->pathFor('slash')
687 // flagging fields visibility
688 $fc = $this->fields_config
;
689 $display_elements = $fc->getDisplayElements($this->login
);
696 'page_title' => _T("Member Profile"),
697 'require_dialog' => true,
699 'pref_lang' => $this->i18n
->getNameFromId($member->language
),
700 'pref_card_self' => $this->preferences
->pref_card_self
,
701 'groups' => Groups
::getSimpleList(),
703 'display_elements' => $display_elements
708 )->setName('member')->add($authenticate)->add($navMiddleware);
711 '/member/{action:edit|add}[/{id:\d+}]',
712 function ($request, $response, $args) {
713 $action = $args['action'];
715 if (isset($args['id'])) {
719 if ($action === 'edit' && $id === null) {
720 throw new \
RuntimeException(
721 _T("Member ID cannot ben null calling edit route!")
723 } elseif ($action === 'add' && $id !== null) {
726 ->withHeader('Location', $this->router
->pathFor('editmember', ['action' => 'add']));
738 if ($this->session
->member
!== null) {
739 $member = $this->session
->member
;
740 $this->session
->member
= null;
742 $member = new Adherent($this->zdb
, null, $deps);
745 if ($this->login
->isAdmin() ||
$this->login
->isStaff() ||
$this->login
->isGroupManager()) {
747 if ($member->id
!= $id) {
750 if (!$this->login
->isAdmin() && !$this->login
->isStaff() && $this->login
->isGroupManager()) {
751 //check if current logged in user can manage loaded member
752 $groups = $member->groups
;
754 foreach ($groups as $group) {
755 if ($this->login
->isGroupManager($group->getId())) {
760 if ($can_manage !== true) {
762 'Logged in member ' . $this->login
->login
.
763 ' has tried to load member #' . $member->id
.
764 ' but do not manage any groups he belongs to.',
767 $member->load($this->login
->id
);
772 if ($member->id
!= $id) {
773 $member->load($this->login
->id
);
777 // flagging required fields
778 $fc = $this->fields_config
;
780 // password required if we create a new member
781 if ($member->id
!= '') {
782 $fc->setNotRequired('mdp_adh');
785 //handle requirements for parent fields
786 $parent_fields = $member->getParentFields();
787 foreach ($parent_fields as $key => $field) {
788 if ($fc->isRequired($field) && $member->hasParent()) {
789 $fc->setNotRequired($field);
790 } elseif (!$fc->isRequired($field)) {
791 unset($parent_fields[$key]);
794 $route_params['parent_fields'] = $parent_fields;
796 // flagging required fields invisible to members
797 if ($this->login
->isAdmin() ||
$this->login
->isStaff()) {
798 $fc->setNotRequired('activite_adh');
799 $fc->setNotRequired('id_statut');
802 // template variable declaration
803 $title = _T("Member Profile");
804 if ($member->id
!= '') {
805 $title .= ' (' . _T("modification") . ')';
807 $title .= ' (' . _T("creation") . ')';
811 $statuts = new Status($this->zdb
);
814 $groups = new Groups($this->zdb
, $this->login
);
815 $groups_list = $groups->getSimpleList(true);
817 $form_elements = $fc->getFormElements(
825 $required_fields = array(
830 $list_members = $m->getList(false, $required_fields, true);
832 if (count($list_members) > 0) {
833 foreach ($list_members as $lmember) {
835 $sname = mb_strtoupper($lmember->nom_adh
, 'UTF-8') .
836 ' ' . ucwords(mb_strtolower($lmember->prenom_adh
, 'UTF-8')) .
837 ' (' . $lmember->id_adh
. ')';
838 $members[$lmember->$pk] = $sname;
842 $route_params['members'] = [
843 'filters' => $m->getFilters(),
844 'count' => $m->getCount()
847 //check if current attached member is part of the list
848 if ($member->hasParent()) {
849 if (!isset($members[$member->parent
->id
])) {
851 [$member->parent
->id
=> $member->parent
->getSName()] +
857 if (count($members)) {
858 $route_params['members']['list'] = $members;
868 'parent_tpl' => 'page.tpl',
869 'require_dialog' => true,
870 'autocomplete' => true,
871 'page_title' => $title,
874 'require_calendar' => true,
877 'titles_list' => Titles
::getList($this->zdb
),
878 'statuts' => $statuts->getList(),
879 'groups' => $groups_list,
880 'fieldsets' => $form_elements['fieldsets'],
881 'hidden_elements' => $form_elements['hiddens']
889 )->add($authenticate)->add($navMiddleware);
892 '/member/store[/{self:subscribe}]',
893 function ($request, $response, $args) {
894 if (!$this->preferences
->pref_bool_selfsubscribe
&& !$this->login
->isLogged()) {
897 ->withHeader('Location', $this->router
->pathFor('slash'));
900 $post = $request->getParsedBody();
909 $member = new Adherent($this->zdb
, null, $deps);
910 $member->setDependencies(
912 $this->members_fields
,
915 if (isset($args['self'])) {
916 //mark as self membership
917 $member->setSelfMembership();
920 $success_detected = [];
921 $warning_detected = [];
922 $error_detected = [];
925 $adherent['id_adh'] = get_numeric_form_value('id_adh', '');
927 if ($this->login
->isAdmin() ||
$this->login
->isStaff() ||
$this->login
->isGroupManager()) {
928 if ($adherent['id_adh']) {
929 $member->load($adherent['id_adh']);
930 if (!$this->login
->isAdmin() && !$this->login
->isStaff() && $this->login
->isGroupManager()) {
931 //check if current logged in user can manage loaded member
932 $groups = $member->groups
;
934 foreach ($groups as $group) {
935 if ($this->login
->isGroupManager($group->getId())) {
940 if ($can_manage !== true) {
942 'Logged in member ' . $this->login
->login
.
943 ' has tried to load member #' . $member->id
.
944 ' but do not manage any groups he belongs to.',
947 $member->load($this->login
->id
);
952 $member->load($this->login
->id
);
953 $adherent['id_adh'] = $this->login
->id
;
956 // flagging required fields
957 $fc = $this->fields_config
;
959 // password required if we create a new member
960 if ($member->id
!= '') {
961 $fc->setNotRequired('mdp_adh');
964 if ($member->hasParent() && !isset($post['detach_parent'])
965 ||
isset($post['parent_id']) && !empty($post['parent_id'])
967 $parent_fields = $member->getParentFields();
968 foreach ($parent_fields as $field) {
969 if ($fc->isRequired($field)) {
970 $fc->setNotRequired($field);
975 // flagging required fields invisible to members
976 if ($this->login
->isAdmin() ||
$this->login
->isStaff()) {
977 $fc->setNotRequired('activite_adh');
978 $fc->setNotRequired('id_statut');
981 $form_elements = $fc->getFormElements(
986 $fieldsets = $form_elements['fieldsets'];
990 foreach ($fieldsets as $category) {
991 foreach ($category->elements
as $field) {
992 if ($field->required
== true) {
993 $required[$field->field_id
] = true;
995 if ($field->disabled
== true) {
996 $disabled[$field->field_id
] = true;
997 } elseif (!isset($post[$field->field_id
])) {
998 switch ($field->field_id
) {
999 //unchecked booleans are not sent from form
1000 case 'bool_admin_adh':
1001 case 'bool_exempt_adh':
1002 case 'bool_display_info':
1003 $post[$field->field_id
] = 0;
1010 $real_requireds = array_diff(array_keys($required), array_keys($disabled));
1013 if (isset($post[array_shift($real_requireds)])) {
1015 $valid = $member->check($post, $required, $disabled);
1016 if ($valid !== true) {
1017 $error_detected = array_merge($error_detected, $valid);
1020 if (count($error_detected) == 0) {
1021 //all goes well, we can proceed
1024 if ($member->id
== '') {
1027 $store = $member->store();
1028 if ($store === true) {
1029 //member has been stored :)
1031 if (isset($args['self'])) {
1032 $success_detected[] = _T("Your account has been created!");
1033 if ($this->preferences
->pref_mail_method
> GaletteMail
::METHOD_DISABLED
1034 && $member->getEmail() != ''
1036 $success_detected[] = _T("An email has been sent to you, check your inbox.");
1039 $success_detected[] = _T("New member has been successfully added.");
1041 //Send email to admin if preference checked
1042 if ($this->preferences
->pref_mail_method
> GaletteMail
::METHOD_DISABLED
1043 && $this->preferences
->pref_bool_mailadh
1046 $this->texts_fields
,
1050 'name_adh' => custom_html_entity_decode(
1053 'firstname_adh' => custom_html_entity_decode(
1056 'lastname_adh' => custom_html_entity_decode(
1059 'mail_adh' => custom_html_entity_decode(
1062 'login_adh' => custom_html_entity_decode(
1067 $mtxt = $texts->getTexts(
1068 (isset($args['self']) ?
'newselfadh' : 'newadh'),
1069 $this->preferences
->pref_lang
1072 $mail = new GaletteMail($this->preferences
);
1073 $mail->setSubject($texts->getSubject());
1075 foreach ($this->preferences
->vpref_email
as $pref_email) {
1076 $recipients[$pref_email] = $this->preferences
->pref_email_nom
;
1078 $mail->setRecipients($recipients);
1079 $mail->setMessage($texts->getBody());
1080 $sent = $mail->send();
1082 if ($sent == GaletteMail
::MAIL_SENT
) {
1083 $this->history
->add(
1086 $member->sname
. ' (' . $member->email
. ')',
1087 _T("New account mail sent to admin for '%s'.")
1093 $member->sname
. ' (' . $member->email
. ')',
1094 _T("A problem happened while sending email to admin for account '%s'.")
1096 $this->history
->add($str);
1097 $warning_detected[] = $str;
1102 $success_detected[] = _T("Member account has been modified.");
1105 // send mail to member
1106 if (isset($args['self']) ||
isset($post['mail_confirm']) && $post['mail_confirm'] == '1') {
1107 if ($this->preferences
->pref_mail_method
> GaletteMail
::METHOD_DISABLED
) {
1108 if ($member->getEmail() == '' && !isset($args['self'])) {
1109 $error_detected[] = _T("- You can't send a confirmation by email if the member hasn't got an address!");
1112 'name_adh' => custom_html_entity_decode(
1115 'firstname_adh' => custom_html_entity_decode(
1118 'lastname_adh' => custom_html_entity_decode(
1121 'mail_adh' => custom_html_entity_decode(
1124 'login_adh' => custom_html_entity_decode(
1129 $password = new Password($this->zdb
);
1130 $res = $password->generateNewPassword($member->id
);
1132 $link_validity = new DateTime();
1133 $link_validity->add(new DateInterval('PT24H'));
1134 $mreplaces['change_pass_uri'] = $this->preferences
->getURL() .
1135 $this->router
->pathFor(
1136 'password-recovery',
1137 ['hash' => base64_encode($password->getHash())]
1139 $mreplaces['link_validity'] = $link_validity->format(_T("Y-m-d H:i:s"));
1144 _T("An error occurred storing temporary password for %s. Please inform an admin.")
1146 $this->history
->add($str);
1147 $this->flash
->addMessage(
1154 //send mail to member
1155 // Get email text in database
1157 $this->texts_fields
,
1162 $mlang = $this->preferences
->pref_lang
;
1163 if (isset($post['pref_lang'])) {
1164 $mlang = $post['pref_lang'];
1166 $mtxt = $texts->getTexts(
1167 (($new) ?
'sub' : 'accountedited'),
1171 $mail = new GaletteMail($this->preferences
);
1172 $mail->setSubject($texts->getSubject());
1173 $mail->setRecipients(
1175 $member->getEmail() => $member->sname
1178 $mail->setMessage($texts->getBody());
1179 $sent = $mail->send();
1181 if ($sent == GaletteMail
::MAIL_SENT
) {
1184 $member->sname
. ' (' . $member->getEmail() . ')',
1186 _T("New account mail sent to '%s'.") :
1187 _T("Account modification mail sent to '%s'.")
1189 $this->history
->add($msg);
1190 $success_detected[] = $msg;
1194 $member->sname
. ' (' . $member->getEmail() . ')',
1195 _T("A problem happened while sending account mail to '%s'")
1197 $this->history
->add($str);
1198 $error_detected[] = $str;
1201 } elseif ($this->preferences
->pref_mail_method
== GaletteMail
::METHOD_DISABLED
) {
1202 //if mail has been disabled in the preferences, we should not be here ;
1203 //we do not throw an error, just a simple warning that will be show later
1204 $msg = _T("You asked Galette to send a confirmation mail to the member, but mail has been disabled in the preferences.");
1205 $warning_detected[] = $msg;
1209 // send mail to admin
1210 if ($this->preferences
->pref_mail_method
> GaletteMail
::METHOD_DISABLED
1211 && $this->preferences
->pref_bool_mailadh
1213 && $member->id
== $this->login
->id
1216 'name_adh' => custom_html_entity_decode(
1219 'firstname_adh' => custom_html_entity_decode(
1222 'lastname_adh' => custom_html_entity_decode(
1225 'mail_adh' => custom_html_entity_decode(
1228 'login_adh' => custom_html_entity_decode(
1233 //send mail to member
1234 // Get email text in database
1236 $this->texts_fields
,
1241 $mlang = $this->preferences
->pref_lang
;
1243 $mtxt = $texts->getTexts(
1248 $mail = new GaletteMail($this->preferences
);
1249 $mail->setSubject($texts->getSubject());
1251 foreach ($this->preferences
->vpref_email_newadh
as $pref_email) {
1252 $recipients[$pref_email] = $this->preferences
->pref_email_nom
;
1254 $mail->setRecipients($recipients);
1256 $mail->setMessage($texts->getBody());
1257 $sent = $mail->send();
1259 if ($sent == GaletteMail
::MAIL_SENT
) {
1260 $msg = _T("Account modification mail sent to admin.");
1261 $this->history
->add($msg);
1262 $success_detected[] = $msg;
1264 $str = _T("A problem happened while sending account mail to admin");
1265 $this->history
->add($str);
1266 $error_detected[] = $str;
1270 //store requested groups
1273 $managed_groups_adh = null;
1275 //add/remove user from groups
1276 if (isset($post['groups_adh'])) {
1277 $groups_adh = $post['groups_adh'];
1279 $add_groups = Groups
::addMemberToGroups(
1284 if ($add_groups === false) {
1285 $error_detected[] = _T("An error occurred adding member to its groups.");
1288 //add/remove manager from groups
1289 if (isset($post['groups_managed_adh'])) {
1290 $managed_groups_adh = $post['groups_managed_adh'];
1292 $add_groups = Groups
::addMemberToGroups(
1294 $managed_groups_adh,
1297 $member->loadGroups();
1299 if ($add_groups === false) {
1300 $error_detected[] = _T("An error occurred adding member to its groups as manager.");
1303 //something went wrong :'(
1304 $error_detected[] = _T("An error occurred while storing the member.");
1308 if (count($error_detected) == 0) {
1309 $files_res = $member->handleFiles($_FILES);
1310 if (is_array($files_res)) {
1311 $error_detected = array_merge($error_detected, $files_res);
1314 if (isset($post['del_photo'])) {
1315 if (!$member->picture
->delete($member->id
)) {
1316 $error_detected[] = _T("Delete failed");
1317 $str_adh = $member->id
. ' (' . $member->sname
. ' ' . ')';
1319 'Unable to delete picture for member ' . $str_adh,
1326 if (count($error_detected) > 0) {
1327 foreach ($error_detected as $error) {
1328 if (strpos($error, '%member_url_') !== false) {
1329 preg_match('/%member_url_(\d+)/', $error, $matches);
1330 $url = $this->router
->pathFor('member', ['id' => $matches[1]]);
1331 $error = str_replace(
1332 '%member_url_' . $matches[1],
1337 $this->flash
->addMessage(
1344 if (count($warning_detected) > 0) {
1345 foreach ($warning_detected as $warning) {
1346 $this->flash
->addMessage(
1352 if (count($success_detected) > 0) {
1353 foreach ($success_detected as $success) {
1354 $this->flash
->addMessage(
1361 if (count($error_detected) == 0) {
1362 $redirect_url = null;
1363 if (isset($args['self'])) {
1364 $redirect_url = $this->router
->pathFor('login');
1365 } elseif (isset($post['redirect_on_create'])
1366 && $post['redirect_on_create'] > Adherent
::AFTER_ADD_DEFAULT
1368 switch ($post['redirect_on_create']) {
1369 case Adherent
::AFTER_ADD_TRANS
:
1370 $redirect_url = $this->router
->pathFor('transaction', ['action' => 'add']);
1372 case Adherent
::AFTER_ADD_NEW
:
1373 $redirect_url = $this->router
->pathFor('editmember', ['action' => 'add']);
1375 case Adherent
::AFTER_ADD_SHOW
:
1376 $redirect_url = $this->router
->pathFor('member', ['id' => $member->id
]);
1378 case Adherent
::AFTER_ADD_LIST
:
1379 $redirect_url = $this->router
->pathFor('members');
1381 case Adherent
::AFTER_ADD_HOME
:
1382 $redirect_url = $this->router
->pathFor('slash');
1385 } elseif (!isset($post['id_adh']) && !$member->isDueFree()) {
1386 $redirect_url = $this->router
->pathFor(
1392 ) . '?id_adh=' . $member->id
;
1394 $redirect_url = $this->router
->pathFor('member', ['id' => $member->id
]);
1399 ->withHeader('Location', $redirect_url);
1401 //store entity in session
1402 $this->session
->member
= $member;
1404 if (isset($args['self'])) {
1405 $redirect_url = $this->router
->pathFor('subscribe');
1409 'id' => $member->id
,
1413 $rparams = ['action' => 'add'];
1415 $redirect_url = $this->router
->pathFor(
1423 ->withHeader('Location', $redirect_url);
1427 )->setName('storemembers');
1430 '/member/remove/{id:\d+}',
1431 function ($request, $response, $args) {
1432 $adh = new Adherent($this->zdb
, (int)$args['id']);
1435 'id' => $args['id'],
1436 'redirect_uri' => $this->router
->pathFor('members')
1440 $this->view
->render(
1442 'confirm_removal.tpl',
1444 'type' => _T("Member"),
1445 'mode' => $request->isXhr() ?
'ajax' : '',
1446 'page_title' => sprintf(
1447 _T('Remove member %1$s'),
1450 'form_url' => $this->router
->pathFor('doRemoveMember', ['id' => $adh->id
]),
1451 'cancel_uri' => $this->router
->pathFor('members'),
1457 )->setName('removeMember')->add($authenticate);
1461 function ($request, $response) {
1462 $filters = $this->session
->filter_members
;
1465 'id' => $filters->selected
,
1466 'redirect_uri' => $this->router
->pathFor('members')
1470 $this->view
->render(
1472 'confirm_removal.tpl',
1474 'type' => _T("Member"),
1475 'mode' => $request->isXhr() ?
'ajax' : '',
1476 'page_title' => _T('Remove members'),
1477 'message' => str_replace(
1480 _T('You are about to remove %count members.')
1482 'form_url' => $this->router
->pathFor('doRemoveMember'),
1483 'cancel_uri' => $this->router
->pathFor('members'),
1489 )->setName('removeMembers')->add($authenticate);
1492 '/member/remove' . '[/{id:\d+}]',
1493 function ($request, $response) {
1494 $post = $request->getParsedBody();
1495 $ajax = isset($post['ajax']) && $post['ajax'] === 'true';
1498 $uri = isset($post['redirect_uri']) ?
1499 $post['redirect_uri'] :
1500 $this->router
->pathFor('slash');
1502 if (!isset($post['confirm'])) {
1503 $this->flash
->addMessage(
1505 _T("Removal has not been confirmed!")
1508 if (isset($this->session
->filter_members
)) {
1509 $filters = $this->session
->filter_members
;
1511 $filters = new MembersList();
1513 $members = new Members($filters);
1515 if (!is_array($post['id'])) {
1517 $adh = new Adherent($this->zdb
, (int)$post['id']);
1518 $ids = (array)$post['id'];
1523 $del = $members->removeMembers($ids);
1525 if ($del !== true) {
1526 if (count($ids) === 1) {
1527 $error_detected = str_replace(
1530 _T("An error occurred trying to remove member %name :/")
1533 $error_detected = _T("An error occurred trying to remove members :/");
1536 $this->flash
->addMessage(
1541 if (!is_array($post['id'])) {
1542 $success_detected = str_replace(
1545 _T("Member %name has been successfully deleted.")
1548 $success_detected = str_replace(
1551 _T("%count members have been successfully deleted.")
1555 $this->flash
->addMessage(
1567 ->withHeader('Location', $uri);
1569 return $response->withJson(
1571 'success' => $success
1576 )->setName('doRemoveMember')->add($authenticate);
1578 //advanced search page
1581 function ($request, $response) {
1582 if (isset($this->session
->filter_members
)) {
1583 $filters = $this->session
->filter_members
;
1584 if (!$filters instanceof AdvancedMembersList
) {
1585 $filters = new AdvancedMembersList($filters);
1588 $filters = new AdvancedMembersList();
1591 $groups = new Groups($this->zdb
, $this->login
);
1592 $groups_list = $groups->getList();
1594 //we want only visibles fields
1595 $fields = $this->members_fields
;
1596 $fc = $this->fields_config
;
1597 $visibles = $fc->getVisibilities();
1598 $access_level = $this->login
->getAccessLevel();
1600 //remove not searchable fields
1601 unset($fields['mdp_adh']);
1603 foreach ($fields as $k => $f) {
1604 if ($visibles[$k] == FieldsConfig
::NOBODY ||
1605 ($visibles[$k] == FieldsConfig
::ADMIN
&&
1606 $access_level < Authentication
::ACCESS_ADMIN
) ||
1607 ($visibles[$k] == FieldsConfig
::STAFF
&&
1608 $access_level < Authentication
::ACCESS_STAFF
) ||
1609 ($visibles[$k] == FieldsConfig
::MANAGER
&&
1610 $access_level < Authentication
::ACCESS_MANAGER
)
1616 //add status label search
1617 if ($pos = array_search(Status
::PK
, array_keys($fields))) {
1618 $fields = array_slice($fields, 0, $pos, true) +
1619 ['status_label' => ['label' => _T('Status label')]] +
1620 array_slice($fields, $pos, count($fields) -1, true);
1629 'children' => false,
1632 $member = new Adherent($this->zdb
, $this->login
->login
, $deps);
1633 $adh_dynamics = new DynamicFieldsHandle($this->zdb
, $this->login
, $member);
1635 $contrib = new Contribution($this->zdb
, $this->login
);
1636 $contrib_dynamics = new DynamicFieldsHandle($this->zdb
, $this->login
, $contrib);
1639 $statuts = new Status($this->zdb
);
1641 //Contributions types
1642 $ct = new Galette\Entity\
ContributionsTypes($this->zdb
);
1645 $ptypes = new PaymentTypes(
1650 $ptlist = $ptypes->getList();
1652 $filters->setViewCommonsFilters($this->preferences
, $this->view
->getSmarty());
1655 $this->view
->render(
1657 'advanced_search.tpl',
1659 'page_title' => _T("Advanced search"),
1660 'require_dialog' => true,
1661 'require_calendar' => true,
1662 'require_sorter' => true,
1663 'filter_groups_options' => $groups_list,
1664 'search_fields' => $fields,
1665 'adh_dynamics' => $adh_dynamics->getFields(),
1666 'contrib_dynamics' => $contrib_dynamics->getFields(),
1667 'statuts' => $statuts->getList(),
1668 'contributions_types' => $ct->getList(),
1669 'filters' => $filters,
1670 'payments_types' => $ptlist
1675 )->setName('advanced-search')->add($authenticate);
1677 //Batch actions on members list
1680 function ($request, $response) {
1681 $post = $request->getParsedBody();
1683 if (isset($post['member_sel'])) {
1684 if (isset($this->session
->filter_members
)) {
1685 $filters = $this->session
->filter_members
;
1687 $filters = new MembersList();
1690 $filters->selected
= $post['member_sel'];
1691 $this->session
->filter_members
= $filters;
1693 if (isset($post['cards'])) {
1696 ->withHeader('Location', $this->router
->pathFor('pdf-members-cards'));
1699 if (isset($post['labels'])) {
1702 ->withHeader('Location', $this->router
->pathFor('pdf-members-labels'));
1705 if (isset($post['mailing'])) {
1708 ->withHeader('Location', $this->router
->pathFor('mailing') . '?new=new');
1711 if (isset($post['attendance_sheet'])) {
1714 ->withHeader('Location', $this->router
->pathFor('attendance_sheet_details'));
1717 if (isset($post['csv'])) {
1720 ->withHeader('Location', $this->router
->pathFor('csv-memberslist'));
1723 if (isset($post['delete'])) {
1726 ->withHeader('Location', $this->router
->pathFor('removeMembers'));
1729 if (isset($post['masschange'])) {
1732 ->withHeader('Location', $this->router
->pathFor('masschangeMembers'));
1735 throw new \
RuntimeException('Does not know what to batch :(');
1737 $this->flash
->addMessage(
1739 _T("No member was selected, please check at least one name.")
1744 ->withHeader('Location', $this->router
->pathFor('members'));
1747 )->setName('batch-memberslist')->add($authenticate);
1751 '/members/cards[/{' . Adherent
::PK
. ':\d+}]',
1752 function ($request, $response, $args) {
1753 if ($this->session
->filter_members
) {
1754 $filters = $this->session
->filter_members
;
1756 $filters = new MembersList();
1759 if (isset($args[Adherent
::PK
])
1760 && $args[Adherent
::PK
] > 0
1762 $id_adh = $args[Adherent
::PK
];
1764 if ($this->login
->id
!= $id_adh
1765 && !$this->login
->isAdmin()
1766 && !$this->login
->isStaff()
1767 && !$this->login
->isGroupManager()
1772 if (!$this->login
->isAdmin() && !$this->login
->isStaff() && $this->login
->id
!= $id_adh) {
1773 if ($this->login
->isGroupManager()) {
1774 $adh = new Adherent($this->zdb
, $id_adh, ['dynamics' => true]);
1775 //check if current logged in user can manage loaded member
1776 $groups = $adh->groups
;
1777 $can_manage = false;
1778 foreach ($groups as $group) {
1779 if ($this->login
->isGroupManager($group->getId())) {
1784 if ($can_manage !== true) {
1786 'Logged in member ' . $this->login
->login
.
1787 ' has tried to load member #' . $adh->id
.
1788 ' but do not manage any groups he belongs to.',
1799 //requested member cannot be managed. Load logged in user
1800 $id_adh = (int)$this->login
->id
;
1803 //check if member is up to date
1804 if ($this->login
->id
== $id_adh) {
1805 $adh = new Adherent($this->zdb
, (int)$id_adh, ['dues' => true]);
1806 if (!$adh->isUp2Date()) {
1808 'Member ' . $id_adh . ' is not up to date; cannot get his PDF member card',
1813 ->withHeader('Location', $this->router
->pathFor('slash'));
1817 // If we are called from a member's card, get unique id value
1820 if (count($filters->selected
) == 0) {
1822 'No member selected to generate members cards',
1825 $this->flash
->addMessage(
1827 _T("No member was selected, please check at least one name.")
1832 ->withHeader('Location', $this->router
->pathFor('members'));
1836 // Fill array $selected with selected ids
1837 $selected = array();
1838 if (isset($unique) && $unique) {
1839 $selected[] = $unique;
1841 $selected = $filters->selected
;
1845 $members = $m->getArrayList(
1847 array('nom_adh', 'prenom_adh'),
1851 if (!is_array($members) ||
count($members) < 1) {
1853 'An error has occurred, unable to get members list.',
1857 $this->flash
->addMessage(
1859 _T("Unable to get members list.")
1864 ->withHeader('Location', $this->router
->pathFor('members'));
1867 $pdf = new PdfMembersCards($this->preferences
);
1868 $pdf->drawCards($members);
1870 $response = $this->response
->withHeader('Content-type', 'application/pdf')
1871 ->withHeader('Content-Disposition', 'attachment;filename="' . $pdf->getFileName() . '"');
1872 $response->write($pdf->download());
1875 )->setName('pdf-members-cards')->add($authenticate);
1877 //PDF members labels
1880 function ($request, $response) {
1881 $get = $request->getQueryParams();
1883 if ($this->session
->filter_reminders_labels
) {
1884 $filters = $this->session
->filter_reminders_labels
;
1885 unset($this->session
->filter_reminders_labels
);
1886 } elseif ($this->session
->filter_members
) {
1887 $filters = $this->session
->filter_members
;
1889 $filters = new MembersList();
1893 if (isset($get['from'])
1894 && $get['from'] === 'mailing'
1896 //if we're from mailing, we have to retrieve
1897 //its unreachables members for labels
1898 $mailing = $this->session
->mailing
;
1899 $members = $mailing->unreachables
;
1901 if (count($filters->selected
) == 0) {
1902 Analog
::log('No member selected to generate labels', Analog
::INFO
);
1903 $this->flash
->addMessage(
1905 _T("No member was selected, please check at least one name.")
1910 ->withHeader('Location', $this->router
->pathFor('members'));
1914 $members = $m->getArrayList(
1916 array('nom_adh', 'prenom_adh')
1920 if (!is_array($members) ||
count($members) < 1) {
1922 'An error has occurred, unable to get members list.',
1926 $this->flash
->addMessage(
1928 _T("Unable to get members list.")
1933 ->withHeader('Location', $this->router
->pathFor('members'));
1936 $pdf = new PdfMembersLabels($this->preferences
);
1937 $pdf->drawLabels($members);
1938 $response = $this->response
->withHeader('Content-type', 'application/pdf')
1939 ->withHeader('Content-Disposition', 'attachment;filename="' . $pdf->getFileName() . '"');
1940 $response->write($pdf->download());
1943 )->setName('pdf-members-labels')->add($authenticate);
1947 '/members/adhesion-form/{' . Adherent
::PK
. ':\d+}',
1948 function ($request, $response, $args) {
1949 $id_adh = (int)$args[Adherent
::PK
];
1952 if ($this->login
->id
!= $args['id']
1953 && !$this->login
->isAdmin()
1954 && !$this->login
->isStaff()
1955 && !$this->login
->isGroupManager()
1960 if (!$this->login
->isAdmin() && !$this->login
->isStaff() && $this->login
->id
!= $args['id']) {
1961 if ($this->login
->isGroupManager()) {
1962 $adh = new Adherent($this->zdb
, $id_adh, ['dynamics' => true]);
1963 //check if current logged in user can manage loaded member
1964 $groups = $adh->groups
;
1965 $can_manage = false;
1966 foreach ($groups as $group) {
1967 if ($this->login
->isGroupManager($group->getId())) {
1972 if ($can_manage !== true) {
1974 'Logged in member ' . $this->login
->login
.
1975 ' has tried to load member #' . $adh->id
.
1976 ' but do not manage any groups he belongs to.',
1987 //requested member cannot be managed. Load logged in user
1988 $id_adh = (int)$this->login
->id
;
1990 $adh = new Adherent($this->zdb
, $id_adh, ['dynamics' => true]);
1992 $form = $this->preferences
->pref_adhesion_form
;
1993 $pdf = new $form($adh, $this->zdb
, $this->preferences
);
1994 $response = $this->response
->withHeader('Content-type', 'application/pdf')
1995 ->withHeader('Content-Disposition', 'attachment; filename="' . $pdf->getFileName() . '"');
1996 $response->write($pdf->download());
1999 )->setName('adhesionForm')->add($authenticate);
2001 //Empty PDF adhesion form
2003 '/members/empty-adhesion-form',
2004 function ($request, $response) {
2005 $form = $this->preferences
->pref_adhesion_form
;
2006 $pdf = new $form(null, $this->zdb
, $this->preferences
);
2007 $response = $this->response
->withHeader('Content-type', 'application/pdf')
2008 ->withHeader('Content-Disposition', 'attachment; filename="' . $pdf->getFileName() . '"');
2009 $response->write($pdf->download());
2012 )->setName('emptyAdhesionForm');
2017 function ($request, $response) {
2018 $get = $request->getQueryParams();
2021 if (isset($get['mailing_new'])
2022 ||
isset($get['reminder'])
2024 if ($this->session
->mailing
!== null) {
2025 // check for temporary attachments to remove
2026 $m = $this->session
->mailing
;
2027 $m->removeAttachments(true);
2029 $this->session
->mailing
= null;
2034 if ($this->preferences
->pref_mail_method
== Mailing
::METHOD_DISABLED
2035 && !GALETTE_MODE
=== 'DEMO'
2037 $this->history
->add(
2038 _T("Trying to load mailing while mail is disabled in preferences.")
2040 $this->flash
->addMessage(
2042 _T("Trying to load mailing while mail is disabled in preferences.")
2046 ->withHeader('Location', $this->router
->pathFor('slash'));
2048 if (isset($this->session
->filter_mailing
)) {
2049 $filters = $this->session
->filter_mailing
;
2050 } elseif (isset($this->session
->filter_members
)) {
2051 $filters = $this->session
->filter_members
;
2053 $filters = new MembersList();
2056 if ($this->session
->mailing
!== null
2057 && !isset($get['from'])
2058 && !isset($get['reset'])
2060 $mailing = $this->session
->mailing
;
2061 } elseif (isset($get['from']) && is_numeric($get['from'])) {
2062 $mailing = new Mailing($this->preferences
, null, $get['from']);
2063 MailingHistory
::loadFrom($this->zdb
, (int)$get['from'], $mailing);
2064 } elseif (isset($get['reminder'])) {
2065 //FIXME: use a constant!
2067 $filters->membership_filter
= Members
::MEMBERSHIP_LATE
;
2068 $filters->filter_account
= Members
::ACTIVE_ACCOUNT
;
2069 $m = new Members($filters);
2070 $members = $m->getList(true);
2071 $mailing = new Mailing($this->preferences
, ($members !== false) ?
$members : null);
2073 if (count($filters->selected
) == 0
2074 && !isset($get['mailing_new'])
2075 && !isset($get['reminder'])
2078 '[Mailings] No member selected for mailing',
2082 $this->flash
->addMessage(
2084 _T('No member selected for mailing!')
2087 if (isset($profiler)) {
2091 $redirect_url = ($this->session
->redirect_mailing
!== null) ?
2092 $this->session
->redirect_mailing
:
2093 $this->router
->pathFor('members');
2097 ->withHeader('Location', $redirect_url);
2100 $members = $m->getArrayList($filters->selected
);
2101 $mailing = new Mailing($this->preferences
, ($members !== false) ?
$members : null);
2104 if (isset($get['remove_attachment'])) {
2105 $mailing->removeAttachment($get['remove_attachment']);
2108 if ($mailing->current_step
!== Mailing
::STEP_SENT
) {
2109 $this->session
->mailing
= $mailing;
2112 /** TODO: replace that... */
2113 $this->session
->labels
= $mailing->unreachables
;
2115 if (!$this->login
->isSuperAdmin()) {
2116 $member = new Adherent($this->zdb
, (int)$this->login
->id
, false);
2117 $params['sender_current'] = [
2118 'name' => $member->sname
,
2119 'email' => $member->getEmail()
2123 $params = array_merge(
2126 'mailing' => $mailing,
2127 'attachments' => $mailing->attachments
,
2128 'html_editor' => true,
2129 'html_editor_active'=> $this->preferences
->pref_editor_enabled
2135 $this->view
->render(
2137 'mailing_adherents.tpl',
2140 'page_title' => _T("Mailing"),
2141 'require_dialog' => true
2148 )->setName('mailing')->add($authenticate);
2152 function ($request, $response) {
2153 $post = $request->getParsedBody();
2154 $error_detected = [];
2155 $success_detected = [];
2157 $goto = $this->router
->pathFor('mailings');
2158 $redirect_url = ($this->session
->redirect_mailing
!== null) ?
2159 $this->session
->redirect_mailing
:
2160 $this->router
->pathFor('members');
2163 if (isset($post['mailing_done'])
2164 ||
isset($post['mailing_cancel'])
2166 if ($this->session
->mailing
!== null) {
2167 // check for temporary attachments to remove
2168 $m = $this->session
->mailing
;
2169 $m->removeAttachments(true);
2171 $this->session
->mailing
= null;
2172 if (isset($this->session
->filter_mailing
)) {
2173 $filters = $this->session
->filter_mailing
;
2174 $filters->selected
= [];
2175 $this->session
->filter_mailing
= $filters;
2180 ->withHeader('Location', $redirect_url);
2185 if ($this->preferences
->pref_mail_method
== Mailing
::METHOD_DISABLED
2186 && !GALETTE_MODE
=== 'DEMO'
2188 $this->history
->add(
2189 _T("Trying to load mailing while mail is disabled in preferences.")
2191 $error_detected[] = _T("Trying to load mailing while mail is disabled in preferences.");
2192 $goto = $this->router
->pathFor('slash');
2194 if (isset($this->session
->filter_members
)) {
2195 $filters = $this->session
->filter_members
;
2197 $filters = new MembersList();
2200 if ($this->session
->mailing
!== null
2201 && !isset($post['mailing_cancel'])
2203 $mailing = $this->session
->mailing
;
2205 if (count($filters->selected
) == 0) {
2207 '[Mailings] No member selected for mailing',
2211 $this->flash
->addMessage(
2213 _T('No member selected for mailing!')
2218 ->withHeader('Location', $redirect_url);
2221 $members = $m->getArrayList($filters->selected
);
2222 $mailing = new Mailing($this->preferences
, ($members !== false) ?
$members : null);
2225 if (isset($post['mailing_go'])
2226 ||
isset($post['mailing_reset'])
2227 ||
isset($post['mailing_confirm'])
2228 ||
isset($post['mailing_save'])
2230 if (trim($post['mailing_objet']) == '') {
2231 $error_detected[] = _T("Please type an object for the message.");
2233 $mailing->subject
= $post['mailing_objet'];
2236 if (trim($post['mailing_corps']) == '') {
2237 $error_detected[] = _T("Please enter a message.");
2239 $mailing->message
= $post['mailing_corps'];
2242 switch ($post['sender']) {
2243 case GaletteMail
::SENDER_CURRENT
:
2244 $member = new Adherent($this->zdb
, (int)$this->login
->id
, false);
2245 $mailing->setSender(
2250 case GaletteMail
::SENDER_OTHER
:
2251 $mailing->setSender(
2252 $post['sender_name'],
2253 $post['sender_address']
2256 case GaletteMail
::SENDER_PREFS
:
2258 //nothing to do; this is the default :)
2262 $mailing->html
= (isset($post['mailing_html'])) ?
true : false;
2264 //handle attachments
2265 if (isset($_FILES['files'])) {
2266 for ($i = 0; $i < count($_FILES['files']['name']); $i++
) {
2267 if ($_FILES['files']['error'][$i] === UPLOAD_ERR_OK
) {
2268 if ($_FILES['files']['tmp_name'][$i] != '') {
2269 if (is_uploaded_file($_FILES['files']['tmp_name'][$i])) {
2271 foreach (array_keys($_FILES['files']) as $key) {
2272 $da_file[$key] = $_FILES['files'][$key][$i];
2274 $res = $mailing->store($da_file);
2276 //what to do if one of attachments fail? should other be removed?
2277 $error_detected[] = $mailing->getAttachmentErrorMessage($res);
2281 } elseif ($_FILES['files']['error'][$i] !== UPLOAD_ERR_NO_FILE
) {
2283 $this->logo
->getPhpErrorMessage($_FILES['files']['error'][$i]),
2286 $error_detected[] = $this->logo
->getPhpErrorMessage(
2287 $_FILES['files']['error'][$i]
2293 if (count($error_detected) == 0
2294 && !isset($post['mailing_reset'])
2295 && !isset($post['mailing_save'])
2297 $mailing->current_step
= Mailing
::STEP_PREVIEW
;
2299 $mailing->current_step
= Mailing
::STEP_START
;
2303 if (isset($post['mailing_confirm']) && count($error_detected) == 0) {
2304 $mailing->current_step
= Mailing
::STEP_SEND
;
2305 //ok... let's go for fun
2306 $sent = $mailing->send();
2307 if ($sent == Mailing
::MAIL_ERROR
) {
2308 $mailing->current_step
= Mailing
::STEP_START
;
2310 '[Mailings] Message was not sent. Errors: ' .
2311 print_r($mailing->errors
, true),
2314 foreach ($mailing->errors
as $e) {
2315 $error_detected[] = $e;
2318 $mlh = new MailingHistory($this->zdb
, $this->login
, null, $mailing);
2319 $mlh->storeMailing(true);
2321 '[Mailings] Message has been sent.',
2324 $mailing->current_step
= Mailing
::STEP_SENT
;
2326 $filters->selected
= null;
2327 $this->session
->filter_members
= $filters;
2328 $this->session
->mailing
= null;
2329 $success_detected[] = _T("Mailing has been successfully sent!");
2330 $goto = $redirect_url;
2334 if ($mailing->current_step
!== Mailing
::STEP_SENT
) {
2335 $this->session
->mailing
= $mailing;
2338 /** TODO: replace that... */
2339 $this->session
->labels
= $mailing->unreachables
;
2341 if (!isset($post['html_editor_active'])
2342 ||
trim($post['html_editor_active']) == ''
2344 $post['html_editor_active'] = $this->preferences
->pref_editor_enabled
;
2347 if (isset($post['mailing_save'])) {
2348 //user requested to save the mailing
2349 $histo = new MailingHistory($this->zdb
, $this->login
, null, $mailing);
2350 if ($histo->storeMailing() !== false) {
2351 $success_detected[] = _T("Mailing has been successfully saved.");
2352 $this->session
->mailing
= null;
2357 //flash messages if any
2358 if (count($error_detected) > 0) {
2359 foreach ($error_detected as $error) {
2360 $this->flash
->addMessage('error_detected', $error);
2363 if (count($success_detected) > 0) {
2364 foreach ($success_detected as $success) {
2365 $this->flash
->addMessage('success_detected', $success);
2371 ->withHeader('Location', $goto);
2373 )->setName('doMailing')->add($authenticate);
2377 '/mailing/preview[/{id:\d+}]',
2378 function ($request, $response, $args) {
2379 $post = $request->getParsedBody();
2380 // check for ajax mode
2382 if ($request->isXhr()
2383 ||
isset($post['ajax'])
2384 && $post['ajax'] == 'true'
2390 if (isset($args['id'])) {
2391 $mailing = new Mailing($this->preferences
, null);
2392 MailingHistory
::loadFrom($this->zdb
, (int)$args['id'], $mailing, false);
2393 $attachments = $mailing->attachments
;
2395 $mailing = $this->session
->mailing
;
2397 switch ($post['sender']) {
2398 case GaletteMail
::SENDER_CURRENT
:
2399 $member = new Adherent($this->zdb
, (int)$this->login
->id
, false);
2400 $mailing->setSender(
2405 case GaletteMail
::SENDER_OTHER
:
2406 $mailing->setSender(
2407 $post['sender_name'],
2408 $post['sender_address']
2411 case GaletteMail
::SENDER_PREFS
:
2413 //nothing to do; this is the default :)
2417 $mailing->subject
= $post['subject'];
2418 $mailing->message
= $post['body'];
2419 $mailing->html
= ($post['html'] === 'true');
2420 $attachments = (isset($post['attachments']) ?
$post['attachments'] : []);
2424 $this->view
->render(
2426 'mailing_preview.tpl',
2428 'page_title' => _T("Mailing preview"),
2429 'mailing_id' => $args['id'],
2430 'mode' => ($ajax ?
'ajax' : ''),
2431 'mailing' => $mailing,
2432 'recipients' => $mailing->recipients
,
2433 'sender' => $mailing->getSenderName() . ' <' .
2434 $mailing->getSenderAddress() . '>',
2435 'attachments' => $attachments
2441 )->setName('mailingPreview')->add($authenticate);
2444 '/mailing/preview/{id:\d+}/attachment/{pos:\d+}',
2445 function ($request, $response, $args) {
2446 $mailing = new Mailing($this->preferences
, null);
2447 MailingHistory
::loadFrom($this->zdb
, (int)$args['id'], $mailing, false);
2448 $attachments = $mailing->attachments
;
2449 $attachment = $attachments[$args['pos']];
2450 $filepath = $attachment->getDestDir() . $attachment->getFileName();
2453 $ext = pathinfo($attachment->getFileName())['extension'];
2454 $response = $response->withHeader('Content-type', $attachment->getMimeType($filepath));
2456 $body = $response->getBody();
2457 $body->write(file_get_contents($filepath));
2460 )->setName('previewAttachment')->add($authenticate);
2463 '/ajax/mailing/set-recipients',
2464 function ($request, $response, $args) {
2465 $post = $request->getParsedBody();
2466 $mailing = $this->session
->mailing
;
2470 $members = $m->getArrayList(
2471 $post['recipients'],
2480 $mailing->setRecipients($members);
2482 $this->session
->mailing
= $mailing;
2485 $this->view
->render(
2487 'mailing_recipients.tpl',
2489 'mailing' => $mailing
2495 )->setName('mailingRecipients')->add($authenticate);
2500 function ($request, $response) {
2501 $texts = new Texts($this->texts_fields
, $this->preferences
, $this->router
);
2504 'impending' => $texts->getTexts('impendingduedate', $this->preferences
->pref_lang
),
2505 'late' => $texts->getTexts('lateduedate', $this->preferences
->pref_lang
)
2508 $members = new Members();
2509 $reminders = $members->getRemindersCount();
2512 $this->view
->render(
2516 'page_title' => _T("Reminders"),
2517 'previews' => $previews,
2518 'require_dialog' => true,
2519 'count_impending' => $reminders['impending'],
2520 'count_impending_nomail' => $reminders['nomail']['impending'],
2521 'count_late' => $reminders['late'],
2522 'count_late_nomail' => $reminders['nomail']['late']
2527 )->setName('reminders')->add($authenticate);
2531 function ($request, $response) {
2532 $error_detected = [];
2533 $warning_detected = [];
2534 $success_detected = [];
2536 $post = $request->getParsedBody();
2537 $texts = new Texts($this->texts_fields
, $this->preferences
, $this->router
);
2539 if (isset($post['reminders'])) {
2540 $selected = $post['reminders'];
2542 $reminders = new Reminders($selected);
2545 $labels_members = array();
2546 if (isset($post['reminder_wo_mail'])) {
2550 $list_reminders = $reminders->getList($this->zdb
, $labels);
2551 if (count($list_reminders) == 0) {
2552 $warning_detected[] = _T("No reminder to send for now.");
2554 foreach ($list_reminders as $reminder) {
2555 if ($labels === false) {
2556 //send reminders by mail
2557 $sent = $reminder->send($texts, $this->history
, $this->zdb
);
2559 if ($sent === true) {
2560 $success_detected[] = $reminder->getMessage();
2562 $error_detected[] = $reminder->getMessage();
2565 //generate labels for members without mail address
2566 $labels_members[] = $reminder->member_id
;
2570 if ($labels === true) {
2571 if (count($labels_members) > 0) {
2572 $labels_filters = new MembersList();
2573 $labels_filters->selected
= $labels_members;
2574 $this->session
->filters_reminders_labels
= $labels_filters;
2577 ->withHeader('Location', $this->router
->pathFor('pdf-member-labels'));
2579 $error_detected[] = _T("There are no member to proceed.");
2583 if (count($error_detected) > 0) {
2586 _T("Reminder has not been sent:")
2590 if (count($success_detected) > 0) {
2593 _T("Sent reminders:")
2598 //flash messages if any
2599 if (count($error_detected) > 0) {
2600 foreach ($error_detected as $error) {
2601 $this->flash
->addMessage('error_detected', $error);
2604 if (count($warning_detected) > 0) {
2605 foreach ($warning_detected as $warning) {
2606 $this->flash
->addMessage('warning_detected', $warning);
2609 if (count($success_detected) > 0) {
2610 foreach ($success_detected as $success) {
2611 $this->flash
->addMessage('success_detected', $success);
2617 ->withHeader('Location', $this->router
->pathFor('reminders'));
2619 )->setName('doReminders')->add($authenticate);
2622 '/members/reminder-filter/{membership:nearly|late}/{mail:withmail|withoutmail}',
2623 function ($request, $response, $args) {
2624 //always reset filters
2625 $filters = new MembersList();
2626 $filters->filter_account
= Members
::ACTIVE_ACCOUNT
;
2628 $membership = ($args['membership'] === 'nearly' ?
2629 Members
::MEMBERSHIP_NEARLY
:
2630 Members
::MEMBERSHIP_LATE
);
2631 $filters->membership_filter
= $membership;
2633 //TODO: filter on reminder may take care of parent email as well
2634 $mail = ($args['mail'] === 'withmail' ?
2635 Members
::FILTER_W_EMAIL
:
2636 Members
::FILTER_WO_EMAIL
);
2637 $filters->email_filter
= $mail;
2639 $this->session
->filter_members
= $filters;
2643 ->withHeader('Location', $this->router
->pathFor('members'));
2645 )->setName('reminders-filter')->add($authenticate);
2649 '/attendance-sheet/details',
2650 function ($request, $response) {
2651 $post = $request->getParsedBody();
2653 if ($this->session
->filter_members
!== null) {
2654 $filters = $this->session
->filter_members
;
2656 $filters = new MembersList();
2659 // check for ajax mode
2661 if ($request->isXhr()
2662 ||
isset($post['ajax'])
2663 && $post['ajax'] == 'true'
2667 //retrieve selected members
2668 $selection = (isset($post['selection']) ) ?
$post['selection'] : array();
2670 $filters->selected
= $selection;
2671 $this->session
->filter_members
= $filters;
2673 $selection = $filters->selected
;
2678 $this->view
->render(
2680 'attendance_sheet_details.tpl',
2682 'page_title' => _T("Attendance sheet configuration"),
2684 'selection' => $selection
2689 )->setName('attendance_sheet_details')->add($authenticate);
2692 '/attendance-sheet',
2693 function ($request, $response) {
2694 $post = $request->getParsedBody();
2696 if ($this->session
->filter_members
!== null) {
2697 $filters = $this->session
->filter_members
;
2699 $filters = new MembersList();
2702 //retrieve selected members
2703 $selection = (isset($post['selection']) ) ?
$post['selection'] : array();
2705 $filters->selected
= $selection;
2706 $this->session
->filter_members
= $filters;
2708 if (count($filters->selected
) == 0) {
2709 Analog
::log('No member selected to generate attendance sheet', Analog
::INFO
);
2710 $this->flash
->addMessage(
2712 _T("No member selected to generate attendance sheet")
2717 ->withHeader('Location', $this->router
->pathFor('members'));
2721 $members = $m->getArrayList(
2723 array('nom_adh', 'prenom_adh'),
2727 if (!is_array($members) ||
count($members) < 1) {
2728 Analog
::log('No member selected to generate attendance sheet', Analog
::INFO
);
2729 $this->flash
->addMessage(
2731 _T("No member selected to generate attendance sheet")
2736 ->withHeader('Location', $this->router
->pathFor('members'));
2739 $doc_title = _T("Attendance sheet");
2740 if (isset($post['sheet_type']) && trim($post['sheet_type']) != '') {
2741 $doc_title = $post['sheet_type'];
2744 $pdf = new Galette\IO\
PdfAttendanceSheet($this->preferences
);
2745 $pdf->doc_title
= $doc_title;
2746 // Set document information
2747 $pdf->SetTitle($doc_title);
2749 if (isset($post['sheet_title']) && trim($post['sheet_title']) != '') {
2750 $pdf->sheet_title
= $post['sheet_title'];
2752 if (isset($post['sheet_sub_title']) && trim($post['sheet_sub_title']) != '') {
2753 $pdf->sheet_sub_title
= $post['sheet_sub_title'];
2755 if (isset($post['sheet_date']) && trim($post['sheet_date']) != '') {
2756 $dformat = __("Y-m-d");
2757 $date = DateTime
::createFromFormat(
2761 $pdf->sheet_date
= $date;
2763 //with or without images?
2764 if (isset($post['sheet_photos']) && $post['sheet_photos'] === '1') {
2767 $pdf->drawSheet($members, $doc_title);
2768 $response = $this->response
->withHeader('Content-type', 'application/pdf');
2769 $response->write($pdf->Output(_T("attendance_sheet") . '.pdf', 'D'));
2772 )->setName('attendance_sheet')->add($authenticate);
2775 '/ajax/members[/{option:page|order}/{value:\d+}]',
2776 function ($request, $response, $args) {
2777 $post = $request->getParsedBody();
2779 if (isset($this->session
->ajax_members_filters
)) {
2780 $filters = $this->session
->ajax_members_filters
;
2782 $filters = new MembersList();
2785 if (isset($args['option']) && $args['option'] == 'page') {
2786 $filters->current_page
= (int)$args['value'];
2789 //numbers of rows to display
2790 if (isset($post['nbshow']) && is_numeric($post['nbshow'])) {
2791 $filters->show
= $post['nbshow'];
2794 $members = new Members($filters);
2795 if (!$this->login
->isAdmin() && !$this->login
->isStaff()) {
2796 if ($this->login
->isGroupManager()) {
2797 $members_list = $members->getManagedMembersList(true);
2802 [$this->login
->id
, $this->login
->login
],
2803 'Trying to list group members without access from #%id (%login)'
2807 throw new Exception('Access denied.');
2811 $members_list = $members->getMembersList(true);
2814 //assign pagination variables to the template and add pagination links
2815 $filters->setSmartyPagination($this->router
, $this->view
->getSmarty(), false);
2817 $this->session
->ajax_members_filters
= $filters;
2819 $selected_members = null;
2820 $unreachables_members = null;
2821 if (!isset($post['from'])) {
2822 $mailing = $this->session
->mailing
;
2823 if (!isset($post['members'])) {
2824 $selected_members = $mailing->recipients
;
2825 $unreachables_members = $mailing->unreachables
;
2828 $selected_members = $m->getArrayList($post['members']);
2829 if (isset($post['unreachables']) && is_array($post['unreachables'])) {
2830 $unreachables_members = $m->getArrayList($post['unreachables']);
2834 switch ($post['from']) {
2836 if (!isset($post['gid'])) {
2838 'Trying to list group members with no group id provided',
2841 throw new Exception('A group id is required.');
2844 if (!isset($post['members'])) {
2845 $group = new Group((int)$post['gid']);
2846 $selected_members = array();
2847 if (!isset($post['mode']) ||
$post['mode'] == 'members') {
2848 $selected_members = $group->getMembers();
2849 } elseif ($post['mode'] == 'managers') {
2850 $selected_members = $group->getManagers();
2853 'Trying to list group members with unknown mode',
2856 throw new Exception('Unknown mode.');
2861 $selected_members = $m->getArrayList($post['members']);
2862 if (isset($post['unreachables']) && is_array($post['unreachables'])) {
2863 $unreachables_members = $m->getArrayList($post['unreachables']);
2868 if (!isset($post['id_adh'])) {
2869 throw new \
RuntimeException(
2870 'Current selected member must be excluded while attaching!'
2879 'filters' => $filters,
2880 'members_list' => $members_list,
2881 'selected_members' => $selected_members,
2882 'unreachables_members' => $unreachables_members
2885 if (isset($post['multiple'])) {
2886 $params['multiple'] = true;
2889 if (isset($post['gid'])) {
2890 $params['the_id'] = $post['gid'];
2893 if (isset($post['id_adh'])) {
2894 $params['excluded'] = $post['id_adh'];
2898 $this->view
->render(
2905 )->setName('ajaxMembers')->add($authenticate);
2908 '/ajax/group/members',
2909 function ($request, $response) {
2910 $post = $request->getParsedBody();
2912 $ids = $post['persons'];
2913 $mode = $post['person_mode'];
2915 if (!$ids ||
!$mode) {
2917 'Missing persons and mode for ajaxGroupMembers',
2924 $persons = $m->getArrayList($ids);
2927 $this->view
->render(
2929 'group_persons.tpl',
2931 'persons' => $persons,
2932 'person_mode' => $mode
2937 )->setName('ajaxGroupMembers')->add($authenticate);
2940 '/member/{id:\d+}/file/{fid:\d+}/{pos:\d+}/{name}',
2941 function ($request, $response, $args) {
2943 $id = (int)$args['id'];
2944 if ($this->login
->id
!= $args['id']
2945 && !$this->login
->isAdmin()
2946 && !$this->login
->isStaff()
2947 && !$this->login
->isGroupManager()
2957 'children' => false,
2960 $member = new Adherent($this->zdb
, $id, $deps);
2962 if (!$denied && $this->login
->id
!= $args['id']
2963 && $this->login
->isGroupManager()
2964 && !$this->login
->isStaff()
2965 && !$this->login
->isAdmin()
2967 //check if current logged in user can manage loaded member
2968 $groups = $member->groups
;
2969 $can_manage = false;
2970 foreach ($groups as $group) {
2971 if ($this->login
->isGroupManager($group->getId())) {
2976 if ($can_manage !== true) {
2978 'Logged in member ' . $this->login
->login
.
2979 ' has tried to load member #' . $member->id
.
2980 ' but do not manage any groups he belongs to.',
2987 if ($denied === false) {
2988 $fields = $member->getDynamicFields()->getFields();
2989 if (!isset($fields[$args['fid']])) {
2990 //field does not exists or access is forbidden
2995 if ($denied === true) {
2996 $this->flash
->addMessage(
2998 _T("You do not have permission for requested URL.")
3005 $this->router
->pathFor(
3012 $filename = str_replace(
3023 'member_%mid_field_%fid_value_%pos'
3026 if (file_exists(GALETTE_FILES_PATH
. $filename)) {
3027 $type = File
::getMimeType(GALETTE_FILES_PATH
. $filename);
3028 $response = $this->response
3029 ->withHeader('Content-Type', $type)
3030 ->withHeader('Content-Disposition', 'attachment;filename="' . $args['name'] . '"')
3031 ->withHeader('Pragma', 'no-cache');
3032 $response->write(readfile(GALETTE_FILES_PATH
. $filename));
3036 'A request has been made to get an exported file named `' .
3037 $filename .'` that does not exists.',
3041 $this->flash
->addMessage(
3043 _T("The file does not exists or cannot be read :(")
3050 $this->router
->pathFor('member', ['id' => $args['id']])
3054 )->setName('getDynamicFile')->add($authenticate);
3057 '/members/mass-change',
3058 function ($request, $response) {
3059 $filters = $this->session
->filter_members
;
3062 'id' => $filters->selected
,
3063 'redirect_uri' => $this->router
->pathFor('members')
3066 $fc = $this->fields_config
;
3067 $form_elements = $fc->getMassiveFormElements($this->members_fields
, $this->login
);
3075 'children' => false,
3078 $member = new Adherent($this->zdb
, null, $deps);
3081 $statuts = new Status($this->zdb
);
3084 $this->view
->render(
3086 'mass_change_members.tpl',
3088 'mode' => $request->isXhr() ?
'ajax' : '',
3089 'page_title' => str_replace(
3092 _T('Mass change %count members')
3094 'form_url' => $this->router
->pathFor('masschangeMembersReview'),
3095 'cancel_uri' => $this->router
->pathFor('members'),
3097 'member' => $member,
3098 'fieldsets' => $form_elements['fieldsets'],
3099 'titles_list' => Titles
::getList($this->zdb
),
3100 'statuts' => $statuts->getList(),
3101 'require_mass' => true
3106 )->setName('masschangeMembers')->add($authenticate);
3109 '/members/mass-change/validate',
3110 function ($request, $response) {
3111 $post = $request->getParsedBody();
3113 if (!isset($post['confirm'])) {
3114 $this->flash
->addMessage(
3116 _T("Mass changes has not been confirmed!")
3119 //we want only visibles fields
3120 $fc = $this->fields_config
;
3121 $form_elements = $fc->getMassiveFormElements($this->members_fields
, $this->login
);
3124 foreach ($form_elements['fieldsets'] as $form_element) {
3125 foreach ($form_element->elements
as $field) {
3126 if (isset($post[$field->field_id
]) && isset($post['mass_' . $field->field_id
])) {
3127 $changes[$field->field_id
] = [
3128 'label' => $field->label
,
3129 'value' => $post[$field->field_id
]
3136 $filters = $this->session
->filter_members
;
3138 'id' => $filters->selected
,
3139 'redirect_uri' => $this->router
->pathFor('members')
3143 $statuts = new Status($this->zdb
);
3146 $this->view
->render(
3148 'mass_change_members.tpl',
3150 'mode' => $request->isXhr() ?
'ajax' : '',
3151 'page_title' => str_replace(
3154 _T('Review mass change %count members')
3156 'form_url' => $this->router
->pathFor('massstoremembers'),
3157 'cancel_uri' => $this->router
->pathFor('members'),
3159 'titles_list' => Titles
::getList($this->zdb
),
3160 'statuts' => $statuts->getList(),
3161 'changes' => $changes
3166 )->setName('masschangeMembersReview')->add($authenticate);
3169 '/members/mass-change',
3170 function ($request, $response, $args) {
3171 $post = $request->getParsedBody();
3172 $redirect_url = $post['redirect_uri'];
3173 $error_detected = [];
3176 unset($post['redirect_uri']);
3177 if (!isset($post['confirm'])) {
3178 $error_detected[] = _T("Mass changes has not been confirmed!");
3180 unset($post['confirm']);
3184 $fc = $this->fields_config
;
3185 $form_elements = $fc->getMassiveFormElements($this->members_fields
, $this->login
);
3186 $disabled = $this->members_fields
;
3187 foreach (array_keys($post) as $key) {
3189 foreach ($form_elements['fieldsets'] as $fieldset) {
3190 if (isset($fieldset->elements
[$key])) {
3197 'Permission issue mass editing field ' . $key,
3202 unset($disabled[$key]);
3206 if (!count($post)) {
3207 $error_detected[] = _T("Nothing to do!");
3209 $is_manager = !$this->login
->isAdmin() && !$this->login
->isStaff() && $this->login
->isGroupManager();
3210 foreach ($ids as $id) {
3213 'groups' => $is_manager,
3216 'children' => false,
3219 $member = new Adherent($this->zdb
, (int)$id, $deps);
3220 $member->setDependencies(
3222 $this->members_fields
,
3227 $groups = $member->groups
;
3228 $is_managed = false;
3229 foreach ($groups as $g) {
3230 if ($this->login
->isGroupManager($g->getId())) {
3237 'Trying to edit member #' . $id . ' without appropriate ACLs',
3240 $error_detected[] = _T('No permission to edit member');
3245 $valid = $member->check($post, [], $disabled);
3246 if ($valid === true) {
3247 $done = $member->store();
3249 $error_detected[] = _T("An error occurred while storing the member.");
3254 $error_detected = array_merge($error_detected, $valid);
3260 if ($mass == 0 && !count($error_detected)) {
3261 $error_detected[] = _T('Something went wront during mass edition!');
3263 $this->flash
->addMessage(
3268 _T('%count members has been changed successfully!')
3273 if (count($error_detected) > 0) {
3274 foreach ($error_detected as $error) {
3275 $this->flash
->addMessage(
3282 if (!$request->isXhr()) {
3285 ->withHeader('Location', $redirect_url);
3287 return $response->withJson(
3289 'success' => count($error_detected) === 0
3294 )->setName('massstoremembers')->add($authenticate);
3298 '/members/duplicate/{' . Adherent
::PK
. ':\d+}',
3299 function ($request, $response, $args) {
3300 $id_adh = (int)$args[Adherent
::PK
];
3301 $adh = new Adherent($this->zdb
, $id_adh, ['dynamics' => true]);
3302 $adh->setDuplicate();
3304 //store entity in session
3305 $this->session
->member
= $adh;
3309 ->withHeader('Location', $this->router
->pathFor('editmember', ['action' => 'add']));
3311 )->setName('duplicateMember')->add($authenticate);
3317 function ($request, $response) {
3318 if ($request->isPost()) {
3319 $post = $request->getParsedBody();
3321 $post = $request->getQueryParams();
3325 if (isset($post['search_title'])) {
3326 $name = $post['search_title'];
3327 unset($post['search_title']);
3330 //when using advanced search, no parameters are sent
3331 if (isset($post['advanced_search'])) {
3333 $filters = $this->session
->filter_members
;
3334 foreach ($filters->search_fields
as $field) {
3335 $post[$field] = $filters->$field;
3339 //reformat, add required infos
3341 'parameters' => $post,
3342 'form' => 'Adherent',
3346 $sco = new Galette\Entity\
SavedSearch($this->zdb
, $this->login
);
3347 if ($check = $sco->check($post)) {
3348 if (!$res = $sco->store()) {
3349 if ($res === false) {
3350 $this->flash
->addMessage(
3352 _T("An SQL error has occurred while storing search.")
3355 $this->flash
->addMessage(
3357 _T("This search is already saved.")
3361 $this->flash
->addMessage(
3363 _T("Search has been saved.")
3368 foreach ($sco->getErrors() as $error) {
3369 $this->flash
->addMessage(
3376 if ($request->isGet()) {
3379 ->withHeader('Location', $this->router
->pathFor('members'));
3382 )->setName('saveSearch');
3385 '/saved-searches[/{option:page|order}/{value:\d+}]',
3386 function ($request, $response, $args = []) {
3388 if (isset($args['option'])) {
3389 $option = $args['option'];
3392 if (isset($args['value'])) {
3393 $value = $args['value'];
3396 if (isset($this->session
->filter_savedsearch
)) {
3397 $filters = $this->session
->filter_savedsearch
;
3399 $filters = new SavedSearchesList();
3402 if ($option !== null) {
3405 $filters->current_page
= (int)$value;
3408 $filters->orderby
= $value;
3413 $searches = new SavedSearches($this->zdb
, $this->login
, $filters);
3414 $list = $searches->getList(true);
3416 //assign pagination variables to the template and add pagination links
3417 $filters->setSmartyPagination($this->router
, $this->view
->getSmarty(), false);
3419 $this->session
->filter_savedsearch
= $filters;
3422 $this->view
->render(
3424 'saved_searches.tpl',
3426 'page_title' => _T("Saved searches"),
3427 'require_dialog' => true,
3428 'searches' => $list,
3429 'nb' => $searches->getCount(),
3430 'filters' => $filters
3435 )->setName('searches')->add($authenticate);
3438 '/search/remove/{id:\d+}',
3439 function ($request, $response, $args) {
3441 'id' => $args['id'],
3442 'redirect_uri' => $this->router
->pathFor('searches')
3446 $this->view
->render(
3448 'confirm_removal.tpl',
3450 'type' => _T("Saved search"),
3451 'mode' => $request->isXhr() ?
'ajax' : '',
3452 'page_title' => _T('Remove saved search'),
3453 'form_url' => $this->router
->pathFor('doRemoveSearch', ['id' => $args['id']]),
3454 'cancel_uri' => $this->router
->pathFor('searches'),
3460 )->setName('removeSearch')->add($authenticate);
3464 function ($request, $response) {
3465 $filters = $this->session
->filter_savedsearch
;
3468 'id' => $filters->selected
,
3469 'redirect_uri' => $this->router
->pathFor('searches')
3473 $this->view
->render(
3475 'confirm_removal.tpl',
3477 'type' => _T("Saved search"),
3478 'mode' => $request->isXhr() ?
'ajax' : '',
3479 'page_title' => _T('Remove saved searches'),
3480 'message' => str_replace(
3483 _T('You are about to remove %count searches.')
3485 'form_url' => $this->router
->pathFor('doRemoveSearch'),
3486 'cancel_uri' => $this->router
->pathFor('searches'),
3492 )->setName('removeSearches')->add($authenticate);
3495 '/search/remove' . '[/{id:\d+}]',
3496 function ($request, $response) {
3497 $post = $request->getParsedBody();
3498 $ajax = isset($post['ajax']) && $post['ajax'] === 'true';
3501 $uri = isset($post['redirect_uri']) ?
3502 $post['redirect_uri'] :
3503 $this->router
->pathFor('slash');
3505 if (!isset($post['confirm'])) {
3506 $this->flash
->addMessage(
3508 _T("Removal has not been confirmed!")
3511 if (isset($this->session
->filter_savedsearch
)) {
3512 $filters = $this->session
->filter_savedsearch
;
3514 $filters = new SavedSearchesList();
3516 $searches = new SavedSearches($this->zdb
, $this->login
, $filters);
3518 if (!is_array($post['id'])) {
3519 $ids = (array)$post['id'];
3524 $del = $searches->remove($ids, $this->history
);
3526 if ($del !== true) {
3527 $error_detected = _T("An error occurred trying to remove searches :/");
3529 $this->flash
->addMessage(
3534 $success_detected = str_replace(
3537 _T("%count searches have been successfully deleted.")
3540 $this->flash
->addMessage(
3552 ->withHeader('Location', $uri);
3554 return $response->withJson(
3556 'success' => $success
3561 )->setName('doRemoveSearch')->add($authenticate);
3564 '/save-search/{id}',
3565 function ($request, $response, $args) {
3567 $sco = new Galette\Entity\
SavedSearch($this->zdb
, $this->login
, (int)$args['id']);
3568 $this->flash
->addMessage(
3570 _T("Saved search loaded")
3572 } catch (\Exception
$e) {
3573 $this->flash
->addMessage(
3575 _T("An SQL error has occurred while storing search.")
3578 $parameters = (array)$sco->parameters
;
3581 if (isset($parameters['free_search'])) {
3582 $filters = new AdvancedMembersList();
3584 $filters = new MembersList();
3587 foreach ($parameters as $key => $value) {
3588 $filters->$key = $value;
3590 $this->session
->filter_members
= $filters;
3594 ->withHeader('Location', $this->router
->pathFor('members'));
3596 )->setName('loadSearch');