]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Controllers/Crud/ContributionsController.php
e130be8646c29377d983359d4a4208013e18fc28
[galette.git] / galette / lib / Galette / Controllers / Crud / ContributionsController.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * Galette contributions controller
7 *
8 * PHP version 5
9 *
10 * Copyright © 2020-2023 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 2020-2023 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 * @link http://galette.tuxfamily.org
34 * @since Available since 0.9.4dev - 2020-05-08
35 */
36
37 namespace Galette\Controllers\Crud;
38
39 use Galette\Features\BatchList;
40 use Galette\Filters\ContributionsList;
41 use Throwable;
42 use Analog\Analog;
43 use Galette\Controllers\CrudController;
44 use Slim\Psr7\Request;
45 use Slim\Psr7\Response;
46 use Galette\Entity\Adherent;
47 use Galette\Entity\Contribution;
48 use Galette\Entity\Transaction;
49 use Galette\Repository\Members;
50 use Galette\Entity\ContributionsTypes;
51 use Galette\Repository\PaymentTypes;
52
53 /**
54 * Galette contributions controller
55 *
56 * @category Controllers
57 * @name ContributionsController
58 * @package Galette
59 * @author Johan Cwiklinski <johan@x-tnd.be>
60 * @copyright 2020-2023 The Galette Team
61 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
62 * @link http://galette.tuxfamily.org
63 * @since Available since 0.9.4dev - 2020-05-02
64 */
65
66 class ContributionsController extends CrudController
67 {
68 use BatchList;
69
70 // CRUD - Create
71
72 /**
73 * Add/Edit page
74 *
75 * Only a few things changes in add and edit pages,
76 * boths methods will use this common one.
77 *
78 * @param Request $request PSR Request
79 * @param Response $response PSR Response
80 * @param string $type Contribution type
81 * @param Contribution $contrib Contribution instance
82 *
83 * @return Response
84 */
85 public function addEditPage(
86 Request $request,
87 Response $response,
88 string $type,
89 Contribution $contrib
90 ): Response {
91 $post = $request->getParsedBody();
92
93 // check for ajax mode
94 $ajax = false;
95 if (
96 ($request->getHeaderLine('X-Requested-With') === 'XMLHttpRequest')
97 || isset($post['ajax'])
98 && $post['ajax'] == 'true'
99 ) {
100 $ajax = true;
101 }
102
103 // contribution types
104 $ct = new ContributionsTypes($this->zdb);
105 $contributions_types = $ct->getList($type === Contribution::TYPE_FEE);
106
107 // template variable declaration
108 $title = null;
109 if ($type === Contribution::TYPE_FEE) {
110 $title = _T("Membership fee");
111 } else {
112 $title = _T("Donation");
113 }
114
115 if ($contrib->id != '') {
116 $title .= ' (' . _T("modification") . ')';
117 } else {
118 $title .= ' (' . _T("creation") . ')';
119 }
120
121 $params = [
122 'page_title' => $title,
123 'required' => $contrib->getRequired(),
124 'contribution' => $contrib,
125 'adh_selected' => $contrib->member,
126 'type' => $type
127 ];
128
129 // contribution types
130 $params['type_cotis_options'] = $contributions_types;
131
132 // members
133 $m = new Members();
134 $members = $m->getDropdownMembers(
135 $this->zdb,
136 $this->login,
137 $contrib->member > 0 ? $contrib->member : null
138 );
139
140 $params['members'] = [
141 'filters' => $m->getFilters(),
142 'count' => $m->getCount()
143 ];
144
145 if (count($members)) {
146 $params['members']['list'] = $members;
147 }
148
149 $ext_membership = '';
150 if ($contrib->isFee() || $type === Contribution::TYPE_FEE) {
151 $ext_membership = $this->preferences->pref_membership_ext;
152 }
153 $params['pref_membership_ext'] = $ext_membership;
154 $params['autocomplete'] = true;
155 $params['mode'] = ($ajax ? 'ajax' : '');
156
157 // display page
158 $this->view->render(
159 $response,
160 'pages/contribution_form.html.twig',
161 $params
162 );
163 return $response;
164 }
165
166 /**
167 * Add page
168 *
169 * @param Request $request PSR Request
170 * @param Response $response PSR Response
171 * @param string|null $type Contribution type
172 *
173 * @return Response
174 */
175 public function add(Request $request, Response $response, string $type = null): Response
176 {
177 if ($this->session->contribution !== null) {
178 $contrib = $this->session->contribution;
179 $this->session->contribution = null;
180 } else {
181 $get = $request->getQueryParams();
182
183 $ct = new ContributionsTypes($this->zdb);
184 $contributions_types = $ct->getList($type === Contribution::TYPE_FEE);
185
186 $cparams = ['type' => array_keys($contributions_types)[0]];
187
188 //member id
189 if (isset($get[Adherent::PK]) && $get[Adherent::PK] > 0) {
190 $cparams['adh'] = (int)$get[Adherent::PK];
191 }
192
193 //transaction id
194 if (isset($get[Transaction::PK]) && $get[Transaction::PK] > 0) {
195 $cparams['trans'] = $get[Transaction::PK];
196 }
197
198 $contrib = new Contribution(
199 $this->zdb,
200 $this->login,
201 $cparams
202 );
203
204 if (isset($cparams['adh'])) {
205 $contrib->member = $cparams['adh'];
206 }
207
208 if (isset($get['montant_cotis']) && $get['montant_cotis'] > 0) {
209 $contrib->amount = $get['montant_cotis'];
210 }
211 }
212
213 return $this->addEditPage($request, $response, $type, $contrib);
214 }
215
216 /**
217 * Add action
218 *
219 * @param Request $request PSR Request
220 * @param Response $response PSR Response
221 * @param string|null $type Contribution type
222 *
223 * @return Response
224 */
225 public function doAdd(Request $request, Response $response, string $type = null): Response
226 {
227 return $this->store($request, $response, 'add', $type);
228 }
229
230 /**
231 * Choose contribution type to mass add contribution
232 *
233 * @param Request $request PSR Request
234 * @param Response $response PSR Response
235 *
236 * @return Response
237 */
238 public function massAddChooseType(Request $request, Response $response): Response
239 {
240 $filters = $this->session->filter_members;
241 $data = [
242 'id' => $filters->selected,
243 'redirect_uri' => $this->routeparser->urlFor('members')
244 ];
245
246 // display page
247 $this->view->render(
248 $response,
249 'modals/mass_choose_contributions_type.html.twig',
250 array(
251 'mode' => ($request->getHeaderLine('X-Requested-With') === 'XMLHttpRequest') ? 'ajax' : '',
252 'page_title' => str_replace(
253 '%count',
254 count($data['id']),
255 _T('Mass add contribution on %count members')
256 ),
257 'data' => $data,
258 'form_url' => $this->routeparser->urlFor('massAddContributions'),
259 'cancel_uri' => $this->routeparser->urlFor('members')
260 )
261 );
262 return $response;
263 }
264
265 /**
266 * Massive change page
267 *
268 * @param Request $request PSR Request
269 * @param Response $response PSR Response
270 *
271 * @return Response
272 */
273 public function massAddContributions(Request $request, Response $response): Response
274 {
275 $post = $request->getParsedBody();
276 $filters = $this->session->filter_members;
277 $type = $post['type'];
278
279 $ct = new ContributionsTypes($this->zdb);
280 $contributions_types = $ct->getList($type === Contribution::TYPE_FEE);
281
282 $contribution = new Contribution(
283 $this->zdb,
284 $this->login,
285 ['type' => array_keys($contributions_types)[0]]
286 );
287
288 $data = [
289 'id' => $filters->selected,
290 'redirect_uri' => $this->routeparser->urlFor('members'),
291 'type' => $type
292 ];
293
294 // display page
295 $this->view->render(
296 $response,
297 'modals/mass_add_contributions.html.twig',
298 array(
299 'mode' => ($request->getHeaderLine('X-Requested-With') === 'XMLHttpRequest') ? 'ajax' : '',
300 'page_title' => str_replace(
301 '%count',
302 count($data['id']),
303 _T('Mass add contribution on %count members')
304 ),
305 'form_url' => $this->routeparser->urlFor('doMassAddContributions'),
306 'cancel_uri' => $this->routeparser->urlFor('members'),
307 'data' => $data,
308 'contribution' => $contribution,
309 'type' => $type,
310 'require_mass' => true,
311 'required' => $contribution->getRequired(),
312 'type_cotis_options' => $contributions_types
313 )
314 );
315 return $response;
316 }
317
318 /**
319 * Do massive contribution add
320 *
321 * @param Request $request PSR Request
322 * @param Response $response PSR Response
323 *
324 * @return Response
325 */
326 public function doMassAddContributions(Request $request, Response $response): Response
327 {
328 $post = $request->getParsedBody();
329 $members_ids = $post['id'];
330 unset($post['id']);
331
332 $error_detected = [];
333
334 // flagging required fields for first step only
335 $disabled = [];
336 $success = 0;
337 $errors = 0;
338
339 foreach ($members_ids as $member_id) {
340 $post[Adherent::PK] = (int)$member_id;
341 $contrib = new Contribution($this->zdb, $this->login);
342
343 // regular fields
344 $valid = $contrib->check($post, $contrib->getRequired(), $disabled);
345 if ($valid !== true) {
346 $error_detected = array_merge($error_detected, $valid);
347 }
348
349 //all goes well, we can proceed
350 if (count($error_detected) == 0) {
351 $store = $contrib->store();
352 if ($store === true) {
353 ++$success;
354 $files_res = $contrib->handleFiles($_FILES);
355 if (is_array($files_res)) {
356 $error_detected = array_merge($error_detected, $files_res);
357 }
358 } else {
359 ++$errors;
360 }
361 }
362 }
363
364 if (count($error_detected) == 0) {
365 $redirect_url = $this->routeparser->urlFor('members');
366 } else {
367 //something went wrong.
368 //store entity in session
369 $redirect_url = $this->routeparser->urlFor('massAddContributions');
370 //report errors
371 foreach ($error_detected as $error) {
372 $this->flash->addMessage(
373 'error_detected',
374 $error
375 );
376 }
377 }
378
379 //redirect to calling action
380 return $response
381 ->withStatus(301)
382 ->withHeader('Location', $redirect_url);
383 }
384
385 // /CRUD - Create
386 // CRUD - Read
387
388 /**
389 * List page
390 *
391 * @param Request $request PSR Request
392 * @param Response $response PSR Response
393 * @param string $option One of 'page' or 'order'
394 * @param string|integer $value Value of the option
395 * @param string $type One of 'transactions' or 'contributions'
396 *
397 * @return Response
398 */
399 public function list(Request $request, Response $response, $option = null, $value = null, $type = null): Response
400 {
401 $ajax = false;
402 $get = $request->getQueryParams();
403
404 switch ($type) {
405 case 'transactions':
406 $raw_type = 'transactions';
407 break;
408 case 'contributions':
409 $raw_type = 'contributions';
410 break;
411 default:
412 Analog::log(
413 'Trying to load unknown contribution type ' . $type,
414 Analog::WARNING
415 );
416 return $response
417 ->withStatus(301)
418 ->withHeader(
419 'Location',
420 $this->routeparser->urlFor('me')
421 );
422 }
423
424 $filter_name = 'filter_' . $raw_type;
425 if (
426 ($request->getHeaderLine('X-Requested-With') === 'XMLHttpRequest')
427 || isset($get['ajax'])
428 && $get['ajax'] == 'true'
429 ) {
430 $ajax = true;
431 $filter_name .= '_ajax';
432 }
433
434 if (isset($this->session->$filter_name)) {
435 $filters = $this->session->$filter_name;
436 } else {
437 $filter_class = '\\Galette\\Filters\\' . ucwords($raw_type . 'List');
438 $filters = new $filter_class();
439 }
440
441 //member id
442 if (isset($get[Adherent::PK]) && $get[Adherent::PK] > 0) {
443 $filters->filtre_cotis_adh = (int)$get[Adherent::PK];
444 }
445
446 if ($type === 'contributions') {
447 if (isset($request->getQueryParams()['max_amount'])) {
448 $filters->filtre_transactions = true;
449 $filters->max_amount = (int)$request->getQueryParams()['max_amount'];
450 }
451 }
452
453 if ($option !== null) {
454 switch ($option) {
455 case 'page':
456 $filters->current_page = (int)$value;
457 break;
458 case 'order':
459 $filters->orderby = $value;
460 break;
461 case 'member':
462 $filters->filtre_cotis_adh = ($value === 'all' ? null : $value);
463 break;
464 }
465 }
466
467 if (!$this->login->isAdmin() && !$this->login->isStaff() && $value != $this->login->id) {
468 if ($value === 'all' || empty($value)) {
469 $value = $this->login->id;
470 } else {
471 $member = new Adherent(
472 $this->zdb,
473 (int)$value,
474 [
475 'picture' => false,
476 'groups' => false,
477 'dues' => false,
478 'parent' => true
479 ]
480 );
481 if (
482 !$member->hasParent() ||
483 $member->hasParent() && $member->parent->id != $this->login->id
484 ) {
485 $value = $this->login->id;
486 Analog::log(
487 'Trying to display contributions for member #' . $value .
488 ' without appropriate ACLs',
489 Analog::WARNING
490 );
491 }
492 }
493 $filters->filtre_cotis_children = $value;
494 }
495
496 $class = '\\Galette\\Entity\\' . ucwords(trim($raw_type, 's'));
497 $contrib = new $class($this->zdb, $this->login);
498
499 if (!$contrib->canShow($this->login)) {
500 Analog::log(
501 'Trying to display contributions without appropriate ACLs',
502 Analog::WARNING
503 );
504 return $response
505 ->withStatus(301)
506 ->withHeader(
507 'Location',
508 $this->routeparser->urlFor('me')
509 );
510 }
511
512 $class = '\\Galette\\Repository\\' . ucwords($raw_type);
513 $contrib = new $class($this->zdb, $this->login, $filters);
514 $contribs_list = $contrib->getList(true);
515
516 //store filters into session
517 if ($ajax === false) {
518 $this->session->$filter_name = $filters;
519 }
520
521 //assign pagination variables to the template and add pagination links
522 $filters->setSmartyPagination($this->routeparser, $this->view);
523
524 $tpl_vars = [
525 'page_title' => $raw_type === 'contributions' ?
526 _T("Contributions management") : _T("Transactions management"),
527 'contribs' => $contrib,
528 'list' => $contribs_list,
529 'nb' => $contrib->getCount(),
530 'filters' => $filters,
531 'mode' => ($ajax === true ? 'ajax' : 'std')
532 ];
533
534 if ($filters->filtre_cotis_adh != null) {
535 $member = new Adherent($this->zdb);
536 $member->enableDep('children');
537 $member->load($filters->filtre_cotis_adh);
538 $tpl_vars['member'] = $member;
539 }
540
541 if ($filters->filtre_cotis_children != false) {
542 $member = new Adherent(
543 $this->zdb,
544 $filters->filtre_cotis_children,
545 [
546 'picture' => false,
547 'groups' => false,
548 'dues' => false,
549 'parent' => true
550 ]
551 );
552 $tpl_vars['pmember'] = $member;
553 }
554
555 // hide column action in ajax mode
556 if ($ajax === true) {
557 $tpl_vars['no_action'] = true;
558 }
559
560 // display page
561 $this->view->render(
562 $response,
563 'pages/' . $raw_type . '_list.html.twig',
564 $tpl_vars
565 );
566 return $response;
567 }
568
569 /**
570 * List page for logged-in member
571 *
572 * @param Request $request PSR Request
573 * @param Response $response PSR Response
574 * @param string $type One of 'transactions' or 'contributions'
575 *
576 * @return Response
577 */
578 public function myList(Request $request, Response $response, string $type = null): Response
579 {
580 return $this->list(
581 $request->withQueryParams(
582 $request->getQueryParams() + [
583 Adherent::PK => $this->login->id
584 ]
585 ),
586 $response,
587 null,
588 null,
589 $type
590 );
591 }
592
593 /**
594 * Filtering
595 *
596 * @param Request $request PSR Request
597 * @param Response $response PSR Response
598 * @param string|null $type One of 'transactions' or 'contributions'
599 *
600 * @return Response
601 */
602 public function filter(Request $request, Response $response, string $type = null): Response
603 {
604 $ajax = false;
605 $filter_name = 'filter_' . $type;
606 if ($request->getHeaderLine('X-Requested-With') === 'XMLHttpRequest') {
607 $ajax = true;
608 $filter_name .= '_ajax';
609 }
610
611 $post = $request->getParsedBody();
612 $error_detected = [];
613
614 if ($this->session->$filter_name !== null) {
615 $filters = $this->session->$filter_name;
616 } else {
617 $filter_class = '\\Galette\\Filters\\' . ucwords($type) . 'List';
618 $filters = new $filter_class();
619 }
620
621 if (isset($post['clear_filter'])) {
622 $filters->reinit($ajax);
623 } else {
624 if (!isset($post['max_amount'])) {
625 $filters->max_amount = null;
626 }
627
628 if (
629 (isset($post['nbshow']) && is_numeric($post['nbshow']))
630 ) {
631 $filters->show = $post['nbshow'];
632 }
633
634 if (isset($post['date_field'])) {
635 $filters->date_field = $post['date_field'];
636 }
637
638 if (isset($post['end_date_filter']) || isset($post['start_date_filter'])) {
639 try {
640 if (isset($post['start_date_filter'])) {
641 $filters->start_date_filter = $post['start_date_filter'];
642 }
643 if (isset($post['end_date_filter'])) {
644 $filters->end_date_filter = $post['end_date_filter'];
645 }
646 } catch (Throwable $e) {
647 $error_detected[] = $e->getMessage();
648 }
649 }
650
651 if (isset($post['payment_type_filter'])) {
652 $ptf = (int)$post['payment_type_filter'];
653 $ptypes = new PaymentTypes(
654 $this->zdb,
655 $this->preferences,
656 $this->login
657 );
658 $ptlist = $ptypes->getList();
659 if (isset($ptlist[$ptf])) {
660 $filters->payment_type_filter = $ptf;
661 } elseif ($ptf == -1) {
662 $filters->payment_type_filter = null;
663 } else {
664 $error_detected[] = _T("- Unknown payment type!");
665 }
666 }
667 }
668
669 $this->session->$filter_name = $filters;
670
671 if (count($error_detected) > 0) {
672 //report errors
673 foreach ($error_detected as $error) {
674 $this->flash->addMessage(
675 'error_detected',
676 $error
677 );
678 }
679 }
680
681 return $response
682 ->withStatus(301)
683 ->withHeader('Location', $this->routeparser->urlFor('contributions', ['type' => $type]));
684 }
685
686 /**
687 * Batch actions handler
688 *
689 * @param Request $request PSR Request
690 * @param Response $response PSR Response
691 * @param string $type One of 'transactions' or 'contributions'
692 *
693 * @return Response
694 */
695 public function handleBatch(Request $request, Response $response, string $type): Response
696 {
697 $filter_name = 'filter_' . $type;
698 $post = $request->getParsedBody();
699
700 if (isset($post['entries_sel'])) {
701 $filters = $this->session->$filter_name ?? new ContributionsList();
702 $filters->selected = $post['entries_sel'];
703 $this->session->$filter_name = $filters;
704
705 if (isset($post['csv'])) {
706 return $response
707 ->withStatus(301)
708 ->withHeader('Location', $this->routeparser->urlFor('csv-contributionslist', ['type' => $type]));
709 }
710
711 if (isset($post['delete'])) {
712 return $response
713 ->withStatus(301)
714 ->withHeader('Location', $this->routeparser->urlFor('removeContributions', ['type' => $type]));
715 }
716
717 throw new \RuntimeException('Does not know what to batch :(');
718 } else {
719 $this->flash->addMessage(
720 'error_detected',
721 _T("No contribution was selected, please check at least one.")
722 );
723
724 return $response
725 ->withStatus(301)
726 ->withHeader('Location', $this->routeparser->urlFor('contributions', ['type' => $type]));
727 }
728 }
729
730 // /CRUD - Read
731 // CRUD - Update
732
733 /**
734 * Edit page
735 *
736 * @param Request $request PSR Request
737 * @param Response $response PSR Response
738 * @param int $id Contribution id
739 * @param string|null $type Contribution type
740 *
741 * @return Response
742 */
743 public function edit(Request $request, Response $response, int $id, string $type = null): Response
744 {
745 if ($this->session->contribution !== null) {
746 $contrib = $this->session->contribution;
747 $this->session->contribution = null;
748 } else {
749 $contrib = new Contribution($this->zdb, $this->login, $id);
750 if ($contrib->id == '') {
751 //not possible to load contribution, exit
752 $this->flash->addMessage(
753 'error_detected',
754 str_replace(
755 '%id',
756 $id,
757 _T("Unable to load contribution #%id!")
758 )
759 );
760 return $response
761 ->withStatus(301)
762 ->withHeader('Location', $this->routeparser->urlFor(
763 'contributions',
764 ['type' => 'contributions']
765 ));
766 }
767 }
768
769 return $this->addEditPage($request, $response, $type, $contrib);
770 }
771
772 /**
773 * Edit action
774 *
775 * @param Request $request PSR Request
776 * @param Response $response PSR Response
777 * @param integer $id Contribution id
778 * @param string|null $type Contribution type
779 *
780 * @return Response
781 */
782 public function doEdit(Request $request, Response $response, int $id, string $type = null): Response
783 {
784 return $this->store($request, $response, 'edit', $type, $id);
785 }
786
787 /**
788 * Store contribution (new or existing)
789 *
790 * @param Request $request PSR Request
791 * @param Response $response PSR Response
792 * @param string $action Action ('edit' or 'add')
793 * @param string $type Contribution type
794 * @param integer $id Contribution id
795 *
796 * @return Response
797 */
798 public function store(Request $request, Response $response, $action, string $type, $id = null): Response
799 {
800 $post = $request->getParsedBody();
801 $args = [
802 'action' => $action,
803 'type' => $type
804 ];
805 if ($id !== null) {
806 $args['id'] = $id;
807 }
808
809 if ($action == 'edit' && isset($post['btnreload'])) {
810 $redirect_url = $this->routeparser->urlFor($action . 'Contribution', $args);
811 $redirect_url .= '?' . Adherent::PK . '=' . $post[Adherent::PK] . '&' .
812 ContributionsTypes::PK . '=' . $post[ContributionsTypes::PK] . '&' .
813 'montant_cotis=' . $post['montant_cotis'];
814 return $response
815 ->withStatus(301)
816 ->withHeader('Location', $redirect_url);
817 }
818
819 $error_detected = [];
820
821 if ($this->session->contribution !== null) {
822 $contrib = $this->session->contribution;
823 $this->session->contribution = null;
824 } else {
825 if ($id === null) {
826 $contrib = new Contribution($this->zdb, $this->login);
827 } else {
828 $contrib = new Contribution($this->zdb, $this->login, $id);
829 }
830 }
831
832 $disabled = [];
833
834 // regular fields
835 $valid = $contrib->check($post, $contrib->getRequired(), $disabled);
836 if ($valid !== true) {
837 $error_detected = array_merge($error_detected, $valid);
838 }
839
840 // send email to member
841 if (isset($post['mail_confirm']) && $post['mail_confirm'] == '1') {
842 $contrib->setSendmail(); //flag to send creation email
843 }
844
845 //all goes well, we can proceed
846 if (count($error_detected) == 0) {
847 $store = $contrib->store();
848 if ($store === true) {
849 $this->flash->addMessage(
850 'success_detected',
851 _T('Contribution has been successfully stored')
852 );
853 } else {
854 //something went wrong :'(
855 $error_detected[] = _T("An error occurred while storing the contribution.");
856 }
857 }
858
859 if (count($error_detected) === 0) {
860 $files_res = $contrib->handleFiles($_FILES);
861 if (is_array($files_res)) {
862 $error_detected = array_merge($error_detected, $files_res);
863 }
864 }
865
866 if (count($error_detected) == 0) {
867 $this->session->contribution = null;
868 if ($contrib->isTransactionPart() && $contrib->transaction->getMissingAmount() > 0) {
869 //new contribution
870 $redirect_url = $this->routeparser->urlFor(
871 'addContribution',
872 [
873 'type' => $post['contrib_type'] ?? $type
874 ]
875 ) . '?' . Transaction::PK . '=' . $contrib->transaction->id .
876 '&' . Adherent::PK . '=' . $contrib->member;
877 } else {
878 //contributions list for member
879 $redirect_url = $this->routeparser->urlFor(
880 'contributions',
881 [
882 'type' => 'contributions'
883 ]
884 ) . '?' . Adherent::PK . '=' . $contrib->member;
885 }
886 } else {
887 //something went wrong.
888 //store entity in session
889 $this->session->contribution = $contrib;
890 $redirect_url = $this->routeparser->urlFor($action . 'Contribution', $args);
891
892 //report errors
893 foreach ($error_detected as $error) {
894 $this->flash->addMessage(
895 'error_detected',
896 $error
897 );
898 }
899 }
900
901 //redirect to calling action
902 return $response
903 ->withStatus(301)
904 ->withHeader('Location', $redirect_url);
905 }
906
907 // /CRUD - Update
908 // CRUD - Delete
909
910 /**
911 * Get redirection URI
912 *
913 * @param array $args Route arguments
914 *
915 * @return string
916 */
917 public function redirectUri(array $args)
918 {
919 return $this->routeparser->urlFor('contributions', ['type' => $args['type']]);
920 }
921
922 /**
923 * Get form URI
924 *
925 * @param array $args Route arguments
926 *
927 * @return string
928 */
929 public function formUri(array $args)
930 {
931 return $this->routeparser->urlFor(
932 'doRemoveContribution',
933 $args
934 );
935 }
936
937 /**
938 * Get confirmation removal page title
939 *
940 * @param array $args Route arguments
941 *
942 * @return string
943 */
944 public function confirmRemoveTitle(array $args)
945 {
946 $raw_type = null;
947
948 switch ($args['type']) {
949 case 'transactions':
950 $raw_type = 'transactions';
951 break;
952 case 'contributions':
953 $raw_type = 'contributions';
954 break;
955 }
956
957 if (isset($args['ids'])) {
958 return sprintf(
959 _T('Remove %1$s %2$s'),
960 count($args['ids']),
961 ($raw_type === 'contributions') ? _T('contributions') : _T('transactions')
962 );
963 } else {
964 return sprintf(
965 _T('Remove %1$s #%2$s'),
966 ($raw_type === 'contributions') ? _T('contribution') : _T('transaction'),
967 $args['id']
968 );
969 }
970 }
971
972 /**
973 * Remove object
974 *
975 * @param array $args Route arguments
976 * @param array $post POST values
977 *
978 * @return boolean
979 */
980 protected function doDelete(array $args, array $post)
981 {
982 $raw_type = null;
983 switch ($args['type']) {
984 case 'transactions':
985 $raw_type = 'transactions';
986 break;
987 case 'contributions':
988 $raw_type = 'contributions';
989 break;
990 }
991
992 $class = '\\Galette\Repository\\' . ucwords($raw_type);
993 $contribs = new $class($this->zdb, $this->login);
994 $rm = $contribs->remove($args['ids'] ?? $args['id'], $this->history);
995 return $rm;
996 }
997
998 // /CRUD - Delete
999 // /CRUD
1000
1001 /**
1002 * Get filter name in session
1003 *
1004 * @param array|null $args Route arguments
1005 *
1006 * @return string
1007 */
1008 public function getFilterName(array $args = null): string
1009 {
1010 return 'filter_' . $args['type'];
1011 }
1012 }