]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Controllers/Crud/MembersController.php
Fix cs
[galette.git] / galette / lib / Galette / Controllers / Crud / MembersController.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * Galette members controller
7 *
8 * PHP version 5
9 *
10 * Copyright © 2019-2020 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 Controllers
28 * @package Galette
29 *
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2019-2020 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
33 * @version SVN: $Id$
34 * @link http://galette.tuxfamily.org
35 * @since Available since 0.9.4dev - 2019-12-02
36 */
37
38 namespace Galette\Controllers\Crud;
39
40 use Galette\Controllers\CrudController;
41
42 use Slim\Http\Request;
43 use Slim\Http\Response;
44 use Galette\Core\Authentication;
45 use Galette\Core\GaletteMail;
46 use Galette\Core\PasswordImage;
47 use Galette\Core\Picture;
48 use Galette\Entity\Adherent;
49 use Galette\Entity\Contribution;
50 use Galette\Entity\ContributionsTypes;
51 use Galette\Entity\DynamicFieldsHandle;
52 use Galette\Entity\Status;
53 use Galette\Entity\FieldsConfig;
54 use Galette\Filters\AdvancedMembersList;
55 use Galette\Filters\MembersList;
56 use Galette\IO\File;
57 use Galette\IO\MembersCsv;
58 use Galette\Repository\Groups;
59 use Galette\Repository\Members;
60 use Galette\Repository\PaymentTypes;
61 use Galette\Repository\Titles;
62 use Analog\Analog;
63
64 /**
65 * Galette members controller
66 *
67 * @category Controllers
68 * @name GaletteController
69 * @package Galette
70 * @author Johan Cwiklinski <johan@x-tnd.be>
71 * @copyright 2019-2020 The Galette Team
72 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
73 * @link http://galette.tuxfamily.org
74 * @since Available since 0.9.4dev - 2019-12-02
75 */
76
77 class MembersController extends CrudController
78 {
79 // CRUD - Create
80
81 /**
82 * Add page
83 *
84 * @param Request $request PSR Request
85 * @param Response $response PSR Response
86 * @param array $args Request arguments
87 *
88 * @return Response
89 */
90 public function add(Request $request, Response $response, array $args = []) :Response
91 {
92 return $this->edit($request, $response, $args);
93 }
94
95 /**
96 * Self subscription page
97 *
98 * @param Request $request PSR Request
99 * @param Response $response PSR Response
100 * @param array $args Request arguments
101 *
102 * @return Response
103 */
104 public function selfSubscribe(Request $request, Response $response, array $args = []) :Response
105 {
106 if (!$this->preferences->pref_bool_selfsubscribe || $this->login->isLogged()) {
107 return $response
108 ->withStatus(301)
109 ->withHeader('Location', $this->router->pathFor('slash'));
110 }
111
112 if ($this->session->member !== null) {
113 $member = $this->session->member;
114 $this->session->member = null;
115 } else {
116 $deps = [
117 'dynamics' => true
118 ];
119 $member = new Adherent($this->zdb, null, $deps);
120 }
121
122 //mark as self membership
123 $member->setSelfMembership();
124
125 // flagging required fields
126 $fc = $this->fields_config;
127 $form_elements = $fc->getFormElements($this->login, true, true);
128
129 //image to defeat mass filling forms
130 $spam = new PasswordImage();
131 $spam_pass = $spam->newImage();
132 $spam_img = $spam->getImage();
133
134 // members
135 $m = new Members();
136 $members = $m->getSelectizedMembers(
137 $this->zdb,
138 $member->hasParent() ? $member->parent->id : null
139 );
140
141 $params['members'] = [
142 'filters' => $m->getFilters(),
143 'count' => $m->getCount()
144 ];
145
146 if (count($members)) {
147 $params['members']['list'] = $members;
148 }
149
150 // display page
151 $this->view->render(
152 $response,
153 'member.tpl',
154 array(
155 'page_title' => _T("Subscription"),
156 'parent_tpl' => 'public_page.tpl',
157 'member' => $member,
158 'self_adh' => true,
159 'autocomplete' => true,
160 // pseudo random int
161 'time' => time(),
162 'titles_list' => Titles::getList($this->zdb),
163 //self_adh specific
164 'spam_pass' => $spam_pass,
165 'spam_img' => $spam_img,
166 'fieldsets' => $form_elements['fieldsets'],
167 'hidden_elements' => $form_elements['hiddens']
168 ) + $params
169 );
170 return $response;
171 }
172
173 /**
174 * Add action
175 *
176 * @param Request $request PSR Request
177 * @param Response $response PSR Response
178 * @param array $args Request arguments
179 *
180 * @return Response
181 */
182 public function doAdd(Request $request, Response $response, array $args = []) :Response
183 {
184 return $this->store($request, $response, $args);
185 }
186
187 /**
188 * Duplicate action
189 *
190 * @param Request $request PSR Request
191 * @param Response $response PSR Response
192 * @param array $args Request arguments
193 *
194 * @return Response
195 */
196 public function duplicate(Request $request, Response $response, array $args = []) :Response
197 {
198 $id_adh = (int)$args[Adherent::PK];
199 $adh = new Adherent($this->zdb, $id_adh, ['dynamics' => true]);
200 $adh->setDuplicate();
201
202 //store entity in session
203 $this->session->member = $adh;
204
205 return $response
206 ->withStatus(301)
207 ->withHeader('Location', $this->router->pathFor('editmember', ['action' => 'add']));
208 }
209
210 // /CRUD - Create
211 // CRUD - Read
212
213 /**
214 * Display member card
215 *
216 * @param Request $request PSR Request
217 * @param Response $response PSR Response
218 * @param array $args Request arguments
219 *
220 * @return Response
221 */
222 public function show(Request $request, Response $response, array $args) :Response
223 {
224 $id = (int)$args['id'];
225
226 $deps = array(
227 'picture' => true,
228 'groups' => true,
229 'dues' => true,
230 'parent' => true,
231 'children' => true,
232 'dynamics' => true
233 );
234 $member = new Adherent($this->zdb, $id, $deps);
235
236 if (!$member->canEdit($this->login)) {
237 $this->flash->addMessage(
238 'error_detected',
239 _T("You do not have permission for requested URL.")
240 );
241
242 return $response
243 ->withStatus(301)
244 ->withHeader(
245 'Location',
246 $this->router->pathFor('me')
247 );
248 }
249
250 if ($member->id == null) {
251 //member does not exists!
252 $this->flash->addMessage(
253 'error_detected',
254 str_replace('%id', $args['id'], _T("No member #%id."))
255 );
256
257 return $response
258 ->withStatus(404)
259 ->withHeader(
260 'Location',
261 $this->router->pathFor('slash')
262 );
263 }
264
265 // flagging fields visibility
266 $fc = $this->fields_config;
267 $display_elements = $fc->getDisplayElements($this->login);
268
269 // display page
270 $this->view->render(
271 $response,
272 'voir_adherent.tpl',
273 array(
274 'page_title' => _T("Member Profile"),
275 'member' => $member,
276 'pref_lang' => $this->i18n->getNameFromId($member->language),
277 'pref_card_self' => $this->preferences->pref_card_self,
278 'groups' => Groups::getSimpleList(),
279 'time' => time(),
280 'display_elements' => $display_elements
281 )
282 );
283 return $response;
284 }
285
286 /**
287 * Own card show
288 *
289 * @param Request $request PSR Request
290 * @param Response $response PSR Response
291 * @param array $args Request arguments
292 *
293 * @return Response
294 */
295 public function showMe(Request $request, Response $response, array $args = []) :Response
296 {
297 if ($this->login->isSuperAdmin()) {
298 return $response
299 ->withStatus(301)
300 ->withHeader('Location', $this->router->pathFor('slash'));
301 }
302 $args['show_me'] = true;
303 $args['id'] = $this->login->id;
304 return $this->show($request, $response, $args);
305 }
306
307 /**
308 * Get a dynamic file
309 *
310 * @param Request $request PSR Request
311 * @param Response $response PSR Response
312 * @param array $args Request arguments
313 *
314 * @return Response
315 */
316 public function getDynamicFile(Request $request, Response $response, array $args) :Response
317 {
318 $id = (int)$args['id'];
319 $deps = array(
320 'picture' => false,
321 'groups' => false,
322 'dues' => false,
323 'parent' => false,
324 'children' => false,
325 'dynamics' => true
326 );
327 $member = new Adherent($this->zdb, $id, $deps);
328
329 $denied = null;
330 if (!$member->canEdit($this->login)) {
331 $fields = $member->getDynamicFields()->getFields();
332 if (!isset($fields[$args['fid']])) {
333 //field does not exists or access is forbidden
334 $denied = true;
335 } else {
336 $denied = false;
337 }
338 }
339
340 if ($denied === true) {
341 $this->flash->addMessage(
342 'error_detected',
343 _T("You do not have permission for requested URL.")
344 );
345
346 return $response
347 ->withStatus(403)
348 ->withHeader(
349 'Location',
350 $this->router->pathFor(
351 'member',
352 ['id' => $id]
353 )
354 );
355 }
356
357 $filename = str_replace(
358 [
359 '%mid',
360 '%fid',
361 '%pos'
362 ],
363 [
364 $args['id'],
365 $args['fid'],
366 $args['pos']
367 ],
368 'member_%mid_field_%fid_value_%pos'
369 );
370
371 if (file_exists(GALETTE_FILES_PATH . $filename)) {
372 $type = File::getMimeType(GALETTE_FILES_PATH . $filename);
373 $response = $response
374 ->withHeader('Content-Type', $type)
375 ->withHeader('Content-Disposition', 'attachment;filename="' . $args['name'] . '"')
376 ->withHeader('Pragma', 'no-cache');
377 $response->write(readfile(GALETTE_FILES_PATH . $filename));
378 return $response;
379 } else {
380 Analog::log(
381 'A request has been made to get an exported file named `' .
382 $filename .'` that does not exists.',
383 Analog::WARNING
384 );
385
386 $this->flash->addMessage(
387 'error_detected',
388 _T("The file does not exists or cannot be read :(")
389 );
390
391 return $response
392 ->withStatus(404)
393 ->withHeader(
394 'Location',
395 $this->router->pathFor('member', ['id' => $args['id']])
396 );
397 }
398 }
399
400 /**
401 * Members list
402 *
403 * @param Request $request PSR Request
404 * @param Response $response PSR Response
405 * @param array $args Request arguments
406 *
407 * @return Response
408 */
409 public function list(Request $request, Response $response, array $args = []) :Response
410 {
411 $option = $args['option'] ?? null;
412 $value = $args['value'] ?? null;
413
414 if (isset($this->session->filter_members)) {
415 $filters = $this->session->filter_members;
416 } else {
417 $filters = new MembersList();
418 }
419
420 if ($option !== null) {
421 switch ($option) {
422 case 'page':
423 $filters->current_page = (int)$value;
424 break;
425 case 'order':
426 $filters->orderby = $value;
427 break;
428 }
429 }
430
431 $members = new Members($filters);
432
433 $members_list = array();
434 if ($this->login->isAdmin() || $this->login->isStaff()) {
435 $members_list = $members->getMembersList(true);
436 } else {
437 $members_list = $members->getManagedMembersList(true);
438 }
439
440 $groups = new Groups($this->zdb, $this->login);
441 $groups_list = $groups->getList();
442
443 //assign pagination variables to the template and add pagination links
444 $filters->setSmartyPagination($this->router, $this->view->getSmarty(), false);
445 $filters->setViewCommonsFilters($this->preferences, $this->view->getSmarty());
446
447 $this->session->filter_members = $filters;
448
449 // display page
450 $this->view->render(
451 $response,
452 'gestion_adherents.tpl',
453 array(
454 'page_title' => _T("Members management"),
455 'require_mass' => true,
456 'members' => $members_list,
457 'filter_groups_options' => $groups_list,
458 'nb_members' => $members->getCount(),
459 'filters' => $filters,
460 'adv_filters' => $filters instanceof AdvancedMembersList
461 )
462 );
463 return $response;
464 }
465
466 /**
467 * Members filtering
468 *
469 * @param Request $request PSR Request
470 * @param Response $response PSR Response
471 *
472 * @return Response
473 */
474 public function filter(Request $request, Response $response) :Response
475 {
476 $post = $request->getParsedBody();
477 if (isset($this->session->filter_members)) {
478 //CAUTION: this one may be simple or advanced, display must change
479 $filters = $this->session->filter_members;
480 } else {
481 $filters = new MembersList();
482 }
483
484 //reintialize filters
485 if (isset($post['clear_filter'])) {
486 $filters = new MembersList();
487 } elseif (isset($post['clear_adv_filter'])) {
488 $this->session->filter_members = null;
489 unset($this->session->filter_members);
490
491 return $response
492 ->withStatus(301)
493 ->withHeader('Location', $this->router->pathFor('advanced-search'));
494 } elseif (isset($post['adv_criteria'])) {
495 return $response
496 ->withStatus(301)
497 ->withHeader('Location', $this->router->pathFor('advanced-search'));
498 } else {
499 //string to filter
500 if (isset($post['filter_str'])) { //filter search string
501 $filters->filter_str = stripslashes(
502 htmlspecialchars($post['filter_str'], ENT_QUOTES)
503 );
504 }
505 //field to filter
506 if (isset($post['field_filter'])) {
507 if (is_numeric($post['field_filter'])) {
508 $filters->field_filter = $post['field_filter'];
509 }
510 }
511 //membership to filter
512 if (isset($post['membership_filter'])) {
513 if (is_numeric($post['membership_filter'])) {
514 $filters->membership_filter
515 = $post['membership_filter'];
516 }
517 }
518 //account status to filter
519 if (isset($post['filter_account'])) {
520 if (is_numeric($post['filter_account'])) {
521 $filters->filter_account = $post['filter_account'];
522 }
523 }
524 //email filter
525 if (isset($post['email_filter'])) {
526 $filters->email_filter = (int)$post['email_filter'];
527 }
528 //group filter
529 if (isset($post['group_filter'])
530 && $post['group_filter'] > 0
531 ) {
532 $filters->group_filter = (int)$post['group_filter'];
533 }
534 //number of rows to show
535 if (isset($post['nbshow'])) {
536 $filters->show = $post['nbshow'];
537 }
538
539 if (isset($post['advanced_filtering'])) {
540 if (!$filters instanceof AdvancedMembersList) {
541 $filters = new AdvancedMembersList($filters);
542 }
543 //Advanced filters
544 $filters->reinit();
545 unset($post['advanced_filtering']);
546 $freed = false;
547 foreach ($post as $k => $v) {
548 if (strpos($k, 'free_', 0) === 0) {
549 if (!$freed) {
550 $i = 0;
551 foreach ($post['free_field'] as $f) {
552 if (trim($f) !== ''
553 && trim($post['free_text'][$i]) !== ''
554 ) {
555 $fs_search = $post['free_text'][$i];
556 $log_op
557 = (int)$post['free_logical_operator'][$i];
558 $qry_op
559 = (int)$post['free_query_operator'][$i];
560 $type = (int)$post['free_type'][$i];
561 $fs = array(
562 'idx' => $i,
563 'field' => $f,
564 'type' => $type,
565 'search' => $fs_search,
566 'log_op' => $log_op,
567 'qry_op' => $qry_op
568 );
569 $filters->free_search = $fs;
570 }
571 $i++;
572 }
573 $freed = true;
574 }
575 } elseif ($k == 'groups_search') {
576 $i = 0;
577 $filters->groups_search_log_op = (int)$post['groups_logical_operator'];
578 foreach ($post['groups_search'] as $g) {
579 if (trim($g) !== '') {
580 $gs = array(
581 'idx' => $i,
582 'group' => $g
583 );
584 $filters->groups_search = $gs;
585 }
586 $i++;
587 }
588 } else {
589 switch ($k) {
590 case 'contrib_min_amount':
591 case 'contrib_max_amount':
592 if (trim($v) !== '') {
593 $v = (float)$v;
594 } else {
595 $v = null;
596 }
597 break;
598 }
599 $filters->$k = $v;
600 }
601 }
602 }
603 }
604
605 if (isset($post['savesearch'])) {
606 return $response
607 ->withStatus(301)
608 ->withHeader(
609 'Location',
610 $this->router->pathFor(
611 'saveSearch',
612 $post
613 )
614 );
615 }
616
617 $this->session->filter_members = $filters;
618
619 return $response
620 ->withStatus(301)
621 ->withHeader('Location', $this->router->pathFor('members'));
622 }
623
624 /**
625 * Advanced search page
626 *
627 * @param Request $request PSR Request
628 * @param Response $response PSR Response
629 *
630 * @return Response
631 */
632 public function advancedSearch(Request $request, Response $response) :Response
633 {
634 if (isset($this->session->filter_members)) {
635 $filters = $this->session->filter_members;
636 if (!$filters instanceof AdvancedMembersList) {
637 $filters = new AdvancedMembersList($filters);
638 }
639 } else {
640 $filters = new AdvancedMembersList();
641 }
642
643 $groups = new Groups($this->zdb, $this->login);
644 $groups_list = $groups->getList();
645
646 //we want only visibles fields
647 $fields = $this->members_fields;
648 $fc = $this->fields_config;
649 $visibles = $fc->getVisibilities();
650 $access_level = $this->login->getAccessLevel();
651
652 //remove not searchable fields
653 unset($fields['mdp_adh']);
654
655 foreach ($fields as $k => $f) {
656 if ($visibles[$k] == FieldsConfig::NOBODY ||
657 ($visibles[$k] == FieldsConfig::ADMIN &&
658 $access_level < Authentication::ACCESS_ADMIN) ||
659 ($visibles[$k] == FieldsConfig::STAFF &&
660 $access_level < Authentication::ACCESS_STAFF) ||
661 ($visibles[$k] == FieldsConfig::MANAGER &&
662 $access_level < Authentication::ACCESS_MANAGER)
663 ) {
664 unset($fields[$k]);
665 }
666 }
667
668 //add status label search
669 if ($pos = array_search(Status::PK, array_keys($fields))) {
670 $fields = array_slice($fields, 0, $pos, true) +
671 ['status_label' => ['label' => _T('Status label')]] +
672 array_slice($fields, $pos, count($fields) -1, true);
673 }
674
675 //dynamic fields
676 $deps = array(
677 'picture' => false,
678 'groups' => false,
679 'dues' => false,
680 'parent' => false,
681 'children' => false,
682 'dynamics' => false
683 );
684 $member = new Adherent($this->zdb, $this->login->login, $deps);
685 $adh_dynamics = new DynamicFieldsHandle($this->zdb, $this->login, $member);
686
687 $contrib = new Contribution($this->zdb, $this->login);
688 $contrib_dynamics = new DynamicFieldsHandle($this->zdb, $this->login, $contrib);
689
690 //Status
691 $statuts = new Status($this->zdb);
692
693 //Contributions types
694 $ct = new ContributionsTypes($this->zdb);
695
696 //Payments types
697 $ptypes = new PaymentTypes(
698 $this->zdb,
699 $this->preferences,
700 $this->login
701 );
702 $ptlist = $ptypes->getList();
703
704 $filters->setViewCommonsFilters($this->preferences, $this->view->getSmarty());
705
706 // display page
707 $this->view->render(
708 $response,
709 'advanced_search.tpl',
710 array(
711 'page_title' => _T("Advanced search"),
712 'filter_groups_options' => $groups_list,
713 'search_fields' => $fields,
714 'adh_dynamics' => $adh_dynamics->getFields(),
715 'contrib_dynamics' => $contrib_dynamics->getFields(),
716 'statuts' => $statuts->getList(),
717 'contributions_types' => $ct->getList(),
718 'filters' => $filters,
719 'payments_types' => $ptlist
720 )
721 );
722 return $response;
723 }
724
725 /**
726 * Batch actions handler
727 *
728 * @param Request $request PSR Request
729 * @param Response $response PSR Response
730 *
731 * @return Response
732 */
733 public function handleBatch(Request $request, Response $response) :Response
734 {
735 $post = $request->getParsedBody();
736
737 if (isset($post['member_sel'])) {
738 if (isset($this->session->filter_members)) {
739 $filters = $this->session->filter_members;
740 } else {
741 $filters = new MembersList();
742 }
743
744 $filters->selected = $post['member_sel'];
745 $this->session->filter_members = $filters;
746
747 if (isset($post['cards'])) {
748 return $response
749 ->withStatus(301)
750 ->withHeader('Location', $this->router->pathFor('pdf-members-cards'));
751 }
752
753 if (isset($post['labels'])) {
754 return $response
755 ->withStatus(301)
756 ->withHeader('Location', $this->router->pathFor('pdf-members-labels'));
757 }
758
759 if (isset($post['mailing'])) {
760 return $response
761 ->withStatus(301)
762 ->withHeader('Location', $this->router->pathFor('mailing') . '?mailing_new=new');
763 }
764
765 if (isset($post['attendance_sheet'])) {
766 return $response
767 ->withStatus(301)
768 ->withHeader('Location', $this->router->pathFor('attendance_sheet_details'));
769 }
770
771 if (isset($post['csv'])) {
772 return $response
773 ->withStatus(301)
774 ->withHeader('Location', $this->router->pathFor('csv-memberslist'));
775 }
776
777 if (isset($post['delete'])) {
778 return $response
779 ->withStatus(301)
780 ->withHeader('Location', $this->router->pathFor('removeMembers'));
781 }
782
783 if (isset($post['masschange'])) {
784 return $response
785 ->withStatus(301)
786 ->withHeader('Location', $this->router->pathFor('masschangeMembers'));
787 }
788
789 throw new \RuntimeException('Does not know what to batch :(');
790 } else {
791 $this->flash->addMessage(
792 'error_detected',
793 _T("No member was selected, please check at least one name.")
794 );
795
796 return $response
797 ->withStatus(301)
798 ->withHeader('Location', $this->router->pathFor('members'));
799 }
800 }
801
802 // /CRUD - Read
803 // CRUD - Update
804
805 /**
806 * Edit page
807 *
808 * @param Request $request PSR Request
809 * @param Response $response PSR Response
810 * @param array $args Request arguments
811 *
812 * @return Response
813 */
814 public function edit(Request $request, Response $response, array $args = []) :Response
815 {
816 $action = $args['action'];
817 $id = null;
818 if (isset($args['id'])) {
819 $id = (int)$args['id'];
820 }
821
822 if ($action === 'edit' && $id === null) {
823 throw new \RuntimeException(
824 _T("Member ID cannot ben null calling edit route!")
825 );
826 } elseif ($action === 'add' && $id !== null) {
827 return $response
828 ->withStatus(301)
829 ->withHeader('Location', $this->router->pathFor('editmember', ['action' => 'add']));
830 }
831 $deps = array(
832 'picture' => true,
833 'groups' => true,
834 'dues' => true,
835 'parent' => true,
836 'children' => true,
837 'dynamics' => true
838 );
839
840 if ($this->session->member !== null) {
841 $member = $this->session->member;
842 $this->session->member = null;
843 } else {
844 $member = new Adherent($this->zdb, $id, $deps);
845 }
846
847 if ($id !== null) {
848 if (!$member->canEdit($this->login)) {
849 $this->flash->addMessage(
850 'error_detected',
851 _T("You do not have permission for requested URL.")
852 );
853
854 return $response
855 ->withStatus(403)
856 ->withHeader(
857 'Location',
858 $this->router->pathFor('me')
859 );
860 }
861 } else {
862 if ($member->id != $id) {
863 $member->load($this->login->id);
864 }
865 }
866
867 // flagging required fields
868 $fc = $this->fields_config;
869
870 // password required if we create a new member
871 if ($member->id != '') {
872 $fc->setNotRequired('mdp_adh');
873 }
874
875 //handle requirements for parent fields
876 $parent_fields = $member->getParentFields();
877 $tpl_parent_fields = []; //for JS when detaching
878 foreach ($parent_fields as $field) {
879 if ($fc->isRequired($field)) {
880 $tpl_parent_fields[] = $field;
881 if ($member->hasParent()) {
882 $fc->setNotRequired($field);
883 }
884 }
885 }
886
887 // flagging required fields invisible to members
888 if ($this->login->isAdmin() || $this->login->isStaff()) {
889 $fc->setNotRequired('activite_adh');
890 $fc->setNotRequired('id_statut');
891 }
892
893 // template variable declaration
894 $title = _T("Member Profile");
895 if ($member->id != '') {
896 $title .= ' (' . _T("modification") . ')';
897 } else {
898 $title .= ' (' . _T("creation") . ')';
899 }
900
901 //Status
902 $statuts = new Status($this->zdb);
903
904 //Groups
905 $groups = new Groups($this->zdb, $this->login);
906 $groups_list = $groups->getSimpleList(true);
907
908 $form_elements = $fc->getFormElements(
909 $this->login,
910 $member->id == ''
911 );
912
913 // members
914 $m = new Members();
915 $id = null;
916 if ($member->hasParent()) {
917 $id = ($member->parent instanceof Adherent ? $member->parent->id : $member->parent);
918 }
919 $members = $m->getSelectizedMembers(
920 $this->zdb,
921 $id
922 );
923
924 $route_params['members'] = [
925 'filters' => $m->getFilters(),
926 'count' => $m->getCount()
927 ];
928
929 if (count($members)) {
930 $route_params['members']['list'] = $members;
931 }
932
933 // display page
934 $this->view->render(
935 $response,
936 'member.tpl',
937 array(
938 'parent_tpl' => 'page.tpl',
939 'autocomplete' => true,
940 'page_title' => $title,
941 'member' => $member,
942 'self_adh' => false,
943 // pseudo random int
944 'time' => time(),
945 'titles_list' => Titles::getList($this->zdb),
946 'statuts' => $statuts->getList(),
947 'groups' => $groups_list,
948 'fieldsets' => $form_elements['fieldsets'],
949 'hidden_elements' => $form_elements['hiddens'],
950 'parent_fields' => $tpl_parent_fields
951 )
952 );
953 return $response;
954 }
955
956 /**
957 * Edit action
958 *
959 * @param Request $request PSR Request
960 * @param Response $response PSR Response
961 * @param array $args Request arguments
962 *
963 * @return Response
964 */
965 public function doEdit(Request $request, Response $response, array $args = []) :Response
966 {
967 return $this->store($request, $response, $args);
968 }
969
970 /**
971 * Massive change page
972 *
973 * @param Request $request PSR Request
974 * @param Response $response PSR Response
975 * @param array $args Request arguments
976 *
977 * @return Response
978 */
979 public function massChange(Request $request, Response $response, array $args = []) :Response
980 {
981 $filters = $this->session->filter_members;
982
983 $data = [
984 'id' => $filters->selected,
985 'redirect_uri' => $this->router->pathFor('members')
986 ];
987
988 $fc = $this->fields_config;
989 $form_elements = $fc->getMassiveFormElements($this->members_fields, $this->login);
990
991 //dynamic fields
992 $deps = array(
993 'picture' => false,
994 'groups' => false,
995 'dues' => false,
996 'parent' => false,
997 'children' => false,
998 'dynamics' => false
999 );
1000 $member = new Adherent($this->zdb, null, $deps);
1001
1002 //Status
1003 $statuts = new Status($this->zdb);
1004
1005 // display page
1006 $this->view->render(
1007 $response,
1008 'mass_change_members.tpl',
1009 array(
1010 'mode' => $request->isXhr() ? 'ajax' : '',
1011 'page_title' => str_replace(
1012 '%count',
1013 count($data['id']),
1014 _T('Mass change %count members')
1015 ),
1016 'form_url' => $this->router->pathFor('masschangeMembersReview'),
1017 'cancel_uri' => $this->router->pathFor('members'),
1018 'data' => $data,
1019 'member' => $member,
1020 'fieldsets' => $form_elements['fieldsets'],
1021 'titles_list' => Titles::getList($this->zdb),
1022 'statuts' => $statuts->getList(),
1023 'require_mass' => true
1024 )
1025 );
1026 return $response;
1027 }
1028
1029 /**
1030 * Massive changes validation page
1031 *
1032 * @param Request $request PSR Request
1033 * @param Response $response PSR Response
1034 * @param array $args Request arguments
1035 *
1036 * @return Response
1037 */
1038 public function validateMassChange(Request $request, Response $response, array $args = []) :Response
1039 {
1040 $post = $request->getParsedBody();
1041
1042 if (!isset($post['confirm'])) {
1043 $this->flash->addMessage(
1044 'error_detected',
1045 _T("Mass changes has not been confirmed!")
1046 );
1047 } else {
1048 //we want only visibles fields
1049 $fc = $this->fields_config;
1050 $form_elements = $fc->getMassiveFormElements($this->members_fields, $this->login);
1051
1052 $changes = [];
1053 foreach ($form_elements['fieldsets'] as $form_element) {
1054 foreach ($form_element->elements as $field) {
1055 if (isset($post[$field->field_id]) && isset($post['mass_' . $field->field_id])) {
1056 $changes[$field->field_id] = [
1057 'label' => $field->label,
1058 'value' => $post[$field->field_id]
1059 ];
1060 }
1061 }
1062 }
1063 }
1064
1065 $filters = $this->session->filter_members;
1066 $data = [
1067 'id' => $filters->selected,
1068 'redirect_uri' => $this->router->pathFor('members')
1069 ];
1070
1071 //Status
1072 $statuts = new Status($this->zdb);
1073
1074 // display page
1075 $this->view->render(
1076 $response,
1077 'mass_change_members.tpl',
1078 array(
1079 'mode' => $request->isXhr() ? 'ajax' : '',
1080 'page_title' => str_replace(
1081 '%count',
1082 count($data['id']),
1083 _T('Review mass change %count members')
1084 ),
1085 'form_url' => $this->router->pathFor('massstoremembers'),
1086 'cancel_uri' => $this->router->pathFor('members'),
1087 'data' => $data,
1088 'titles_list' => Titles::getList($this->zdb),
1089 'statuts' => $statuts->getList(),
1090 'changes' => $changes
1091 )
1092 );
1093 return $response;
1094 }
1095
1096 /**
1097 * Do massive changes
1098 *
1099 * @param Request $request PSR Request
1100 * @param Response $response PSR Response
1101 * @param array $args Request arguments
1102 *
1103 * @return Response
1104 */
1105 public function doMassChange(Request $request, Response $response, array $args = []) :Response
1106 {
1107 $post = $request->getParsedBody();
1108 $redirect_url = $post['redirect_uri'];
1109 $error_detected = [];
1110 $mass = 0;
1111
1112 unset($post['redirect_uri']);
1113 if (!isset($post['confirm'])) {
1114 $error_detected[] = _T("Mass changes has not been confirmed!");
1115 } else {
1116 unset($post['confirm']);
1117 $ids = $post['id'];
1118 unset($post['id']);
1119
1120 $fc = $this->fields_config;
1121 $form_elements = $fc->getMassiveFormElements($this->members_fields, $this->login);
1122 $disabled = $this->members_fields;
1123 foreach (array_keys($post) as $key) {
1124 $found = false;
1125 foreach ($form_elements['fieldsets'] as $fieldset) {
1126 if (isset($fieldset->elements[$key])) {
1127 $found = true;
1128 continue;
1129 }
1130 }
1131 if (!$found) {
1132 Analog::log(
1133 'Permission issue mass editing field ' . $key,
1134 Analog::WARNING
1135 );
1136 unset($post[$key]);
1137 } else {
1138 unset($disabled[$key]);
1139 }
1140 }
1141
1142 if (!count($post)) {
1143 $error_detected[] = _T("Nothing to do!");
1144 } else {
1145 foreach ($ids as $id) {
1146 $is_manager = !$this->login->isAdmin()
1147 && !$this->login->isStaff()
1148 && $this->login->isGroupManager();
1149 $deps = array(
1150 'picture' => false,
1151 'groups' => $is_manager,
1152 'dues' => false,
1153 'parent' => false,
1154 'children' => false,
1155 'dynamics' => false
1156 );
1157 $member = new Adherent($this->zdb, (int)$id, $deps);
1158 $member->setDependencies(
1159 $this->preferences,
1160 $this->members_fields,
1161 $this->history
1162 );
1163 if (!$member->canEdit($this->login)) {
1164 continue;
1165 }
1166
1167 $valid = $member->check($post, [], $disabled);
1168 if ($valid === true) {
1169 $done = $member->store();
1170 if (!$done) {
1171 $error_detected[] = _T("An error occurred while storing the member.");
1172 } else {
1173 ++$mass;
1174 }
1175 } else {
1176 $error_detected = array_merge($error_detected, $valid);
1177 }
1178 }
1179 }
1180 }
1181
1182 if ($mass == 0 && !count($error_detected)) {
1183 $error_detected[] = _T('Something went wront during mass edition!');
1184 } else {
1185 $this->flash->addMessage(
1186 'success_detected',
1187 str_replace(
1188 '%count',
1189 $mass,
1190 _T('%count members has been changed successfully!')
1191 )
1192 );
1193 }
1194
1195 if (count($error_detected) > 0) {
1196 foreach ($error_detected as $error) {
1197 $this->flash->addMessage(
1198 'error_detected',
1199 $error
1200 );
1201 }
1202 }
1203
1204 if (!$request->isXhr()) {
1205 return $response
1206 ->withStatus(301)
1207 ->withHeader('Location', $redirect_url);
1208 } else {
1209 return $response->withJson(
1210 [
1211 'success' => count($error_detected) === 0
1212 ]
1213 );
1214 }
1215 }
1216
1217 /**
1218 * Store
1219 *
1220 * @param Request $request PSR Request
1221 * @param Response $response PSR Response
1222 * @param array $args Request arguments
1223 *
1224 * @return Response
1225 */
1226 public function store(Request $request, Response $response, array $args = []) :Response
1227 {
1228 if (!$this->preferences->pref_bool_selfsubscribe && !$this->login->isLogged()) {
1229 return $response
1230 ->withStatus(301)
1231 ->withHeader('Location', $this->router->pathFor('slash'));
1232 }
1233
1234 $post = $request->getParsedBody();
1235 $deps = array(
1236 'picture' => true,
1237 'groups' => true,
1238 'dues' => true,
1239 'parent' => true,
1240 'children' => true,
1241 'dynamics' => true
1242 );
1243 $member = new Adherent($this->zdb, null, $deps);
1244 $member->setDependencies(
1245 $this->preferences,
1246 $this->members_fields,
1247 $this->history
1248 );
1249 if (isset($args['self'])) {
1250 //mark as self membership
1251 $member->setSelfMembership();
1252 }
1253
1254 $success_detected = [];
1255 $warning_detected = [];
1256 $error_detected = [];
1257
1258 // new or edit
1259 $adherent['id_adh'] = get_numeric_form_value('id_adh', '');
1260 if ($adherent['id_adh']) {
1261 $member->load((int)$adherent['id_adh']);
1262 if (!$member->canEdit($this->login)) {
1263 //redirection should have been done before. Just throw an Exception.
1264 throw new \RuntimeException(
1265 str_replace(
1266 '%id',
1267 $member->id,
1268 'No right to store member #%id'
1269 )
1270 );
1271 }
1272 } else {
1273 $member->load($this->login->id);
1274 $adherent['id_adh'] = $this->login->id;
1275 }
1276
1277 // flagging required fields
1278 $fc = $this->fields_config;
1279
1280 // password required if we create a new member
1281 if ($member->id != '') {
1282 $fc->setNotRequired('mdp_adh');
1283 }
1284
1285 if ($member->hasParent() && !isset($post['detach_parent'])
1286 || isset($post['parent_id']) && !empty($post['parent_id'])
1287 ) {
1288 $parent_fields = $member->getParentFields();
1289 foreach ($parent_fields as $field) {
1290 if ($fc->isRequired($field)) {
1291 $fc->setNotRequired($field);
1292 }
1293 }
1294 }
1295
1296 // flagging required fields invisible to members
1297 if ($this->login->isAdmin() || $this->login->isStaff()) {
1298 $fc->setNotRequired('activite_adh');
1299 $fc->setNotRequired('id_statut');
1300 }
1301
1302 $form_elements = $fc->getFormElements(
1303 $this->login,
1304 $member->id == '',
1305 isset($args['self'])
1306 );
1307 $fieldsets = $form_elements['fieldsets'];
1308 $required = array();
1309 $disabled = array();
1310
1311 foreach ($fieldsets as $category) {
1312 foreach ($category->elements as $field) {
1313 if ($field->required == true) {
1314 $required[$field->field_id] = true;
1315 }
1316 if ($field->disabled == true) {
1317 $disabled[$field->field_id] = true;
1318 } elseif (!isset($post[$field->field_id])) {
1319 switch ($field->field_id) {
1320 //unchecked booleans are not sent from form
1321 case 'bool_admin_adh':
1322 case 'bool_exempt_adh':
1323 case 'bool_display_info':
1324 $post[$field->field_id] = 0;
1325 break;
1326 }
1327 }
1328 }
1329 }
1330
1331 $real_requireds = array_diff(array_keys($required), array_keys($disabled));
1332
1333 // Validation
1334 $redirect_url = $this->router->pathFor('member', ['id' => $member->id]);
1335 if (isset($post[array_shift($real_requireds)])) {
1336 // regular fields
1337 $valid = $member->check($post, $required, $disabled);
1338 if ($valid !== true) {
1339 $error_detected = array_merge($error_detected, $valid);
1340 }
1341
1342 if (count($error_detected) == 0) {
1343 //all goes well, we can proceed
1344
1345 $new = false;
1346 if ($member->id == '') {
1347 $new = true;
1348 }
1349 $store = $member->store();
1350 if ($store === true) {
1351 //member has been stored :)
1352 if ($new) {
1353 if (isset($args['self'])) {
1354 $success_detected[] = _T("Your account has been created!");
1355 if ($this->preferences->pref_mail_method > GaletteMail::METHOD_DISABLED
1356 && $member->getEmail() != ''
1357 ) {
1358 $success_detected[] = _T("An email has been sent to you, check your inbox.");
1359 }
1360 } else {
1361 $success_detected[] = _T("New member has been successfully added.");
1362 }
1363 //Send email to admin if preference checked
1364 if ($this->preferences->pref_mail_method > GaletteMail::METHOD_DISABLED
1365 && $this->preferences->pref_bool_mailadh
1366 ) {
1367 $texts = new Texts(
1368 $this->preferences,
1369 $this->router,
1370 array(
1371 'name_adh' => custom_html_entity_decode(
1372 $member->sname
1373 ),
1374 'firstname_adh' => custom_html_entity_decode(
1375 $member->surname
1376 ),
1377 'lastname_adh' => custom_html_entity_decode(
1378 $member->name
1379 ),
1380 'mail_adh' => custom_html_entity_decode(
1381 $member->email
1382 ),
1383 'login_adh' => custom_html_entity_decode(
1384 $member->login
1385 )
1386 )
1387 );
1388 $mtxt = $texts->getTexts(
1389 (isset($args['self']) ? 'newselfadh' : 'newadh'),
1390 $this->preferences->pref_lang
1391 );
1392
1393 $mail = new GaletteMail($this->preferences);
1394 $mail->setSubject($texts->getSubject());
1395 $recipients = [];
1396 foreach ($this->preferences->vpref_email_newadh as $pref_email) {
1397 $recipients[$pref_email] = $pref_email;
1398 }
1399 $mail->setRecipients($recipients);
1400 $mail->setMessage($texts->getBody());
1401 $sent = $mail->send();
1402
1403 if ($sent == GaletteMail::MAIL_SENT) {
1404 $this->history->add(
1405 str_replace(
1406 '%s',
1407 $member->sname . ' (' . $member->email . ')',
1408 _T("New account email sent to admin for '%s'.")
1409 )
1410 );
1411 } else {
1412 $str = str_replace(
1413 '%s',
1414 $member->sname . ' (' . $member->email . ')',
1415 _T("A problem happened while sending email to admin for account '%s'.")
1416 );
1417 $this->history->add($str);
1418 $warning_detected[] = $str;
1419 }
1420 unset($texts);
1421 }
1422 } else {
1423 $success_detected[] = _T("Member account has been modified.");
1424 }
1425
1426 // send email to member
1427 if (isset($args['self']) || isset($post['mail_confirm']) && $post['mail_confirm'] == '1') {
1428 if ($this->preferences->pref_mail_method > GaletteMail::METHOD_DISABLED) {
1429 if ($member->getEmail() == '' && !isset($args['self'])) {
1430 $error_detected[] = _T("- You can't send a confirmation by email if the member hasn't got an address!");
1431 } else {
1432 $mreplaces = [
1433 'name_adh' => custom_html_entity_decode(
1434 $member->sname
1435 ),
1436 'firstname_adh' => custom_html_entity_decode(
1437 $member->surname
1438 ),
1439 'lastname_adh' => custom_html_entity_decode(
1440 $member->name
1441 ),
1442 'mail_adh' => custom_html_entity_decode(
1443 $member->getEmail()
1444 ),
1445 'login_adh' => custom_html_entity_decode(
1446 $member->login
1447 )
1448 ];
1449 if ($new) {
1450 $password = new Password($this->zdb);
1451 $res = $password->generateNewPassword($member->id);
1452 if ($res == true) {
1453 $link_validity = new DateTime();
1454 $link_validity->add(new DateInterval('PT24H'));
1455 $mreplaces['change_pass_uri'] = $this->preferences->getURL() .
1456 $this->router->pathFor(
1457 'password-recovery',
1458 ['hash' => base64_encode($password->getHash())]
1459 );
1460 $mreplaces['link_validity'] = $link_validity->format(_T("Y-m-d H:i:s"));
1461 } else {
1462 $str = str_replace(
1463 '%s',
1464 $login_adh,
1465 _T("An error occurred storing temporary password for %s. Please inform an admin.")
1466 );
1467 $this->history->add($str);
1468 $this->flash->addMessage(
1469 'error_detected',
1470 $str
1471 );
1472 }
1473 }
1474
1475 //send email to member
1476 // Get email text in database
1477 $texts = new Texts(
1478 $this->preferences,
1479 $this->router,
1480 $mreplaces
1481 );
1482 $mlang = $this->preferences->pref_lang;
1483 if (isset($post['pref_lang'])) {
1484 $mlang = $post['pref_lang'];
1485 }
1486 $mtxt = $texts->getTexts(
1487 (($new) ? 'sub' : 'accountedited'),
1488 $mlang
1489 );
1490
1491 $mail = new GaletteMail($this->preferences);
1492 $mail->setSubject($texts->getSubject());
1493 $mail->setRecipients(
1494 array(
1495 $member->getEmail() => $member->sname
1496 )
1497 );
1498 $mail->setMessage($texts->getBody());
1499 $sent = $mail->send();
1500
1501 if ($sent == GaletteMail::MAIL_SENT) {
1502 $msg = str_replace(
1503 '%s',
1504 $member->sname . ' (' . $member->getEmail() . ')',
1505 ($new) ?
1506 _T("New account email sent to '%s'.") :
1507 _T("Account modification email sent to '%s'.")
1508 );
1509 $this->history->add($msg);
1510 $success_detected[] = $msg;
1511 } else {
1512 $str = str_replace(
1513 '%s',
1514 $member->sname . ' (' . $member->getEmail() . ')',
1515 _T("A problem happened while sending account email to '%s'")
1516 );
1517 $this->history->add($str);
1518 $error_detected[] = $str;
1519 }
1520 }
1521 } elseif ($this->preferences->pref_mail_method == GaletteMail::METHOD_DISABLED) {
1522 //if email has been disabled in the preferences, we should not be here ;
1523 //we do not throw an error, just a simple warning that will be show later
1524 $msg = _T("You asked Galette to send a confirmation email to the member, but email has been disabled in the preferences.");
1525 $warning_detected[] = $msg;
1526 }
1527 }
1528
1529 // send email to admin
1530 if ($this->preferences->pref_mail_method > GaletteMail::METHOD_DISABLED
1531 && $this->preferences->pref_bool_mailadh
1532 && !$new
1533 && $member->id == $this->login->id
1534 ) {
1535 $mreplaces = [
1536 'name_adh' => custom_html_entity_decode(
1537 $member->sname
1538 ),
1539 'firstname_adh' => custom_html_entity_decode(
1540 $member->surname
1541 ),
1542 'lastname_adh' => custom_html_entity_decode(
1543 $member->name
1544 ),
1545 'mail_adh' => custom_html_entity_decode(
1546 $member->getEmail()
1547 ),
1548 'login_adh' => custom_html_entity_decode(
1549 $member->login
1550 )
1551 ];
1552
1553 //send email to member
1554 // Get email text in database
1555 $texts = new Texts(
1556 $this->preferences,
1557 $this->router,
1558 $mreplaces
1559 );
1560 $mlang = $this->preferences->pref_lang;
1561
1562 $mtxt = $texts->getTexts(
1563 'admaccountedited',
1564 $mlang
1565 );
1566
1567 $mail = new GaletteMail($this->preferences);
1568 $mail->setSubject($texts->getSubject());
1569 $recipients = [];
1570 foreach ($this->preferences->vpref_email_newadh as $pref_email) {
1571 $recipients[$pref_email] = $pref_email;
1572 }
1573 $mail->setRecipients($recipients);
1574
1575 $mail->setMessage($texts->getBody());
1576 $sent = $mail->send();
1577
1578 if ($sent == GaletteMail::MAIL_SENT) {
1579 $msg = _T("Account modification email sent to admin.");
1580 $this->history->add($msg);
1581 $success_detected[] = $msg;
1582 } else {
1583 $str = _T("A problem happened while sending account email to admin");
1584 $this->history->add($str);
1585 $warning_detected[] = $str;
1586 }
1587 }
1588
1589 //store requested groups
1590 $add_groups = null;
1591 $groups_adh = null;
1592 $managed_groups_adh = null;
1593
1594 //add/remove user from groups
1595 if (isset($post['groups_adh'])) {
1596 $groups_adh = $post['groups_adh'];
1597 }
1598 $add_groups = Groups::addMemberToGroups(
1599 $member,
1600 $groups_adh
1601 );
1602
1603 if ($add_groups === false) {
1604 $error_detected[] = _T("An error occurred adding member to its groups.");
1605 }
1606
1607 //add/remove manager from groups
1608 if (isset($post['groups_managed_adh'])) {
1609 $managed_groups_adh = $post['groups_managed_adh'];
1610 }
1611 $add_groups = Groups::addMemberToGroups(
1612 $member,
1613 $managed_groups_adh,
1614 true
1615 );
1616 $member->loadGroups();
1617
1618 if ($add_groups === false) {
1619 $error_detected[] = _T("An error occurred adding member to its groups as manager.");
1620 }
1621 } else {
1622 //something went wrong :'(
1623 $error_detected[] = _T("An error occurred while storing the member.");
1624 }
1625 }
1626
1627 if (count($error_detected) == 0) {
1628 $files_res = $member->handleFiles($_FILES);
1629 if (is_array($files_res)) {
1630 $error_detected = array_merge($error_detected, $files_res);
1631 }
1632
1633 if (isset($post['del_photo'])) {
1634 if (!$member->picture->delete($member->id)) {
1635 $error_detected[] = _T("Delete failed");
1636 $str_adh = $member->id . ' (' . $member->sname . ' ' . ')';
1637 Analog::log(
1638 'Unable to delete picture for member ' . $str_adh,
1639 Analog::ERROR
1640 );
1641 }
1642 }
1643 }
1644
1645 if (count($error_detected) > 0) {
1646 foreach ($error_detected as $error) {
1647 if (strpos($error, '%member_url_') !== false) {
1648 preg_match('/%member_url_(\d+)/', $error, $matches);
1649 $url = $this->router->pathFor('member', ['id' => $matches[1]]);
1650 $error = str_replace(
1651 '%member_url_' . $matches[1],
1652 $url,
1653 $error
1654 );
1655 }
1656 $this->flash->addMessage(
1657 'error_detected',
1658 $error
1659 );
1660 }
1661 }
1662
1663 if (count($warning_detected) > 0) {
1664 foreach ($warning_detected as $warning) {
1665 $this->flash->addMessage(
1666 'warning_detected',
1667 $warning
1668 );
1669 }
1670 }
1671 if (count($success_detected) > 0) {
1672 foreach ($success_detected as $success) {
1673 $this->flash->addMessage(
1674 'success_detected',
1675 $success
1676 );
1677 }
1678 }
1679
1680 if (count($error_detected) == 0) {
1681 if (isset($args['self'])) {
1682 $redirect_url = $this->router->pathFor('login');
1683 } elseif (isset($post['redirect_on_create'])
1684 && $post['redirect_on_create'] > Adherent::AFTER_ADD_DEFAULT
1685 ) {
1686 switch ($post['redirect_on_create']) {
1687 case Adherent::AFTER_ADD_TRANS:
1688 $redirect_url = $this->router->pathFor('transaction', ['action' => 'add']);
1689 break;
1690 case Adherent::AFTER_ADD_NEW:
1691 $redirect_url = $this->router->pathFor('editmember', ['action' => 'add']);
1692 break;
1693 case Adherent::AFTER_ADD_SHOW:
1694 $redirect_url = $this->router->pathFor('member', ['id' => $member->id]);
1695 break;
1696 case Adherent::AFTER_ADD_LIST:
1697 $redirect_url = $this->router->pathFor('members');
1698 break;
1699 case Adherent::AFTER_ADD_HOME:
1700 $redirect_url = $this->router->pathFor('slash');
1701 break;
1702 }
1703 } elseif (!isset($post['id_adh']) && !$member->isDueFree()) {
1704 $redirect_url = $this->router->pathFor(
1705 'contribution',
1706 [
1707 'type' => 'fee',
1708 'action' => 'add',
1709 ]
1710 ) . '?id_adh=' . $member->id;
1711 } else {
1712 $redirect_url = $this->router->pathFor('member', ['id' => $member->id]);
1713 }
1714 } else {
1715 //store entity in session
1716 $this->session->member = $member;
1717
1718 if (isset($args['self'])) {
1719 $redirect_url = $this->router->pathFor('subscribe');
1720 } else {
1721 if ($member->id) {
1722 $rparams = [
1723 'id' => $member->id,
1724 'action' => 'edit'
1725 ];
1726 } else {
1727 $rparams = ['action' => 'add'];
1728 }
1729 $redirect_url = $this->router->pathFor(
1730 'editmember',
1731 $rparams
1732 );
1733 }
1734 }
1735 }
1736
1737 return $response
1738 ->withStatus(301)
1739 ->withHeader('Location', $redirect_url);
1740 }
1741
1742
1743 // /CRUD - Update
1744 // CRUD - Delete
1745
1746 /**
1747 * Get redirection URI
1748 *
1749 * @param array $args Route arguments
1750 *
1751 * @return string
1752 */
1753 public function redirectUri(array $args = [])
1754 {
1755 return $this->router->pathFor('members');
1756 }
1757
1758 /**
1759 * Get form URI
1760 *
1761 * @param array $args Route arguments
1762 *
1763 * @return string
1764 */
1765 public function formUri(array $args = [])
1766 {
1767 return $this->router->pathFor(
1768 'doRemoveMember',
1769 $args
1770 );
1771 }
1772
1773 /**
1774 * Get ID to remove
1775 *
1776 * In simple cases, we get the ID in the route arguments; but for
1777 * batchs, it should be found elsewhere.
1778 *
1779 * @param array $args Request arguments
1780 *
1781 * @return integer|null|array
1782 */
1783 protected function getIdsToRemove($args)
1784 {
1785 if (isset($args['id'])) {
1786 return $args['id'];
1787 } else {
1788 $filters = $this->session->filter_members;
1789 return $filters->selected;
1790 }
1791 }
1792
1793 /**
1794 * Get confirmation removal page title
1795 *
1796 * @param array $args Route arguments
1797 *
1798 * @return string
1799 */
1800 public function confirmRemoveTitle(array $args = [])
1801 {
1802 if (isset($args['id_adh'])) {
1803 //one member removal
1804 $adh = new Adherent($this->zdb, (int)$args['id']);
1805 return sprintf(
1806 _T('Remove member %1$s'),
1807 $adh->sfullname
1808 );
1809 } else {
1810 //batch members removal
1811 $filters = $this->session->filter_members;
1812 return str_replace(
1813 '%count',
1814 count($filters->selected),
1815 _T('You are about to remove %count members.')
1816 );
1817 }
1818 }
1819
1820 /**
1821 * Remove object
1822 *
1823 * @param array $args Route arguments
1824 * @param array $post POST values
1825 *
1826 * @return boolean
1827 */
1828 protected function doDelete(array $args, array $post)
1829 {
1830 if (isset($this->session->filter_members)) {
1831 $filters = $this->session->filter_members;
1832 } else {
1833 $filters = new MembersList();
1834 }
1835 $members = new Members($filters);
1836
1837 if (!is_array($post['id'])) {
1838 $ids = (array)$post['id'];
1839 } else {
1840 $ids = $post['id'];
1841 }
1842
1843 return $members->removeMembers($ids);
1844 }
1845
1846 // CRUD - Delete
1847 }