]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Controllers/PdfController.php
Switch to PSR12, phpcbf fix
[galette.git] / galette / lib / Galette / Controllers / PdfController.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * Galette PDF controller
7 *
8 * PHP version 5
9 *
10 * Copyright © 2019 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 Entity
28 * @package Galette
29 *
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2019 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-05
36 */
37
38 namespace Galette\Controllers;
39
40 use Slim\Http\Request;
41 use Slim\Http\Response;
42 use Analog\Analog;
43 use Galette\Core\Links;
44 use Galette\Entity\Adherent;
45 use Galette\Entity\Contribution;
46 use Galette\Entity\PdfModel;
47 use Galette\Filters\MembersList;
48 use Galette\IO\Pdf;
49 use Galette\IO\PdfAttendanceSheet;
50 use Galette\IO\PdfContribution;
51 use Galette\IO\PdfGroups;
52 use Galette\IO\PdfMembersCards;
53 use Galette\IO\PdfMembersLabels;
54 use Galette\Repository\Members;
55 use Galette\Repository\Groups;
56 use Galette\Repository\PdfModels;
57
58 /**
59 * Galette PDF controller
60 *
61 * @category Controllers
62 * @name GaletteController
63 * @package Galette
64 * @author Johan Cwiklinski <johan@x-tnd.be>
65 * @copyright 2019 The Galette Team
66 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
67 * @link http://galette.tuxfamily.org
68 * @since Available since 0.9.4dev - 2019-12-05
69 */
70
71 class PdfController extends AbstractController
72 {
73 /**
74 * Send response
75 *
76 * @param Response $response PSR Response
77 * @param Pdf $pdf PDF to output
78 *
79 * @return Response
80 */
81 protected function sendResponse(Response $response, Pdf $pdf): Response
82 {
83 return $response
84 ->withHeader('Content-type', 'application/pdf')
85 ->withHeader('Content-Disposition', 'attachment;filename="' . $pdf->getFileName() . '"')
86 ->write($pdf->download());
87 return $response;
88 }
89
90 /**
91 * Members PDF card
92 *
93 * @param Request $request PSR Request
94 * @param Response $response PSR Response
95 * @param array $args Request arguments
96 *
97 * @return Response
98 */
99 public function membersCards(Request $request, Response $response, array $args = []): Response
100 {
101 if ($this->session->filter_members) {
102 $filters = $this->session->filter_members;
103 } else {
104 $filters = new MembersList();
105 }
106
107 if (
108 isset($args[Adherent::PK])
109 && $args[Adherent::PK] > 0
110 ) {
111 $id_adh = $args[Adherent::PK];
112 $deps = ['dynamics' => true];
113 if ($this->login->id == $id_adh) {
114 $deps['dues'] = true;
115 }
116 $adh = new Adherent(
117 $this->zdb,
118 $id_adh,
119 $deps
120 );
121 if (!$adh->canEdit($this->login)) {
122 $this->flash->addMessage(
123 'error_detected',
124 _T("You do not have permission for requested URL.")
125 );
126
127 return $response
128 ->withStatus(403)
129 ->withHeader(
130 'Location',
131 $this->router->pathFor('me')
132 );
133 }
134
135 //check if member is up to date
136 if ($this->login->id == $id_adh) {
137 if (!$adh->isUp2Date()) {
138 Analog::log(
139 'Member ' . $id_adh . ' is not up to date; cannot get his PDF member card',
140 Analog::WARNING
141 );
142 return $response
143 ->withStatus(301)
144 ->withHeader('Location', $this->router->pathFor('slash'));
145 }
146 }
147
148 // If we are called from a member's card, get unique id value
149 $unique = $id_adh;
150 } else {
151 if (count($filters->selected) == 0) {
152 Analog::log(
153 'No member selected to generate members cards',
154 Analog::INFO
155 );
156 $this->flash->addMessage(
157 'error_detected',
158 _T("No member was selected, please check at least one name.")
159 );
160
161 return $response
162 ->withStatus(301)
163 ->withHeader('Location', $this->router->pathFor('members'));
164 }
165 }
166
167 // Fill array $selected with selected ids
168 $selected = array();
169 if (isset($unique) && $unique) {
170 $selected[] = $unique;
171 } else {
172 $selected = $filters->selected;
173 }
174
175 $m = new Members();
176 $members = $m->getArrayList(
177 $selected,
178 array('nom_adh', 'prenom_adh'),
179 true
180 );
181
182 if (!is_array($members) || count($members) < 1) {
183 Analog::log(
184 'An error has occurred, unable to get members list.',
185 Analog::ERROR
186 );
187
188 $this->flash->addMessage(
189 'error_detected',
190 _T("Unable to get members list.")
191 );
192
193 return $response
194 ->withStatus(301)
195 ->withHeader('Location', $this->router->pathFor('members'));
196 }
197
198 $pdf = new PdfMembersCards($this->preferences);
199 $pdf->drawCards($members);
200
201 return $this->sendResponse($response, $pdf);
202 }
203
204 /**
205 * Members PDF label
206 *
207 * @param Request $request PSR Request
208 * @param Response $response PSR Response
209 *
210 * @return Response
211 */
212 public function membersLabels(Request $request, Response $response): Response
213 {
214 $post = $request->getParsedBody();
215 $get = $request->getQueryParams();
216
217 $session_var = $post['session_var'] ?? $get['session_var'] ?? 'filter_members';
218
219 if (isset($this->session->$session_var)) {
220 $filters = $this->session->$session_var;
221 } else {
222 $filters = new MembersList();
223 }
224
225 $members = null;
226 if (
227 isset($get['from'])
228 && $get['from'] === 'mailing'
229 ) {
230 //if we're from mailing, we have to retrieve
231 //its unreachables members for labels
232 $mailing = $this->session->mailing;
233 $members = $mailing->unreachables;
234 } else {
235 if (count($filters->selected) == 0) {
236 Analog::log('No member selected to generate labels', Analog::INFO);
237 $this->flash->addMessage(
238 'error_detected',
239 _T("No member was selected, please check at least one name.")
240 );
241
242 return $response
243 ->withStatus(301)
244 ->withHeader('Location', $this->router->pathFor('members'));
245 }
246
247 $m = new Members();
248 $members = $m->getArrayList(
249 $filters->selected,
250 array('nom_adh', 'prenom_adh')
251 );
252 }
253
254 if (!is_array($members) || count($members) < 1) {
255 Analog::log(
256 'An error has occurred, unable to get members list.',
257 Analog::ERROR
258 );
259
260 $this->flash->addMessage(
261 'error_detected',
262 _T("Unable to get members list.")
263 );
264
265 return $response
266 ->withStatus(301)
267 ->withHeader('Location', $this->router->pathFor('members'));
268 }
269
270 $pdf = new PdfMembersLabels($this->preferences);
271 $pdf->drawLabels($members);
272
273 return $this->sendResponse($response, $pdf);
274 }
275
276 /**
277 * PDF adhesion form
278 *
279 * @param Request $request PSR Request
280 * @param Response $response PSR Response
281 * @param array $args Request arguments
282 *
283 * @return Response
284 */
285 public function adhesionForm(Request $request, Response $response, array $args = []): Response
286 {
287 $id_adh = isset($args[Adherent::PK]) ? (int)$args[Adherent::PK] : null;
288 $adh = new Adherent($this->zdb, $id_adh, ['dynamics' => true]);
289
290 if ($id_adh !== null && !$adh->canEdit($this->login)) {
291 $this->flash->addMessage(
292 'error_detected',
293 _T("You do not have permission for requested URL.")
294 );
295
296 return $response
297 ->withStatus(403)
298 ->withHeader(
299 'Location',
300 $this->router->pathFor('me')
301 );
302 }
303
304 $form = $this->preferences->pref_adhesion_form;
305 $pdf = new $form($adh, $this->zdb, $this->preferences);
306
307 return $this->sendResponse($response, $pdf);
308 }
309
310 /**
311 * PDF attendance sheet configuration page
312 *
313 * @param Request $request PSR Request
314 * @param Response $response PSR Response
315 * @param array $args Request arguments
316 *
317 * @return Response
318 */
319 public function attendanceSheetConfig(Request $request, Response $response, array $args = []): Response
320 {
321 $post = $request->getParsedBody();
322
323 if ($this->session->filter_members !== null) {
324 $filters = $this->session->filter_members;
325 } else {
326 $filters = new MembersList();
327 }
328
329 // check for ajax mode
330 $ajax = false;
331 if (
332 $request->isXhr()
333 || isset($post['ajax'])
334 && $post['ajax'] == 'true'
335 ) {
336 $ajax = true;
337
338 //retrieve selected members
339 $selection = (isset($post['selection'])) ? $post['selection'] : array();
340
341 $filters->selected = $selection;
342 $this->session->filter_members = $filters;
343 } else {
344 $selection = $filters->selected;
345 }
346
347 // display page
348 $this->view->render(
349 $response,
350 'attendance_sheet_details.tpl',
351 [
352 'page_title' => _T("Attendance sheet configuration"),
353 'ajax' => $ajax,
354 'selection' => $selection
355 ]
356 );
357 return $response;
358 }
359
360 /**
361 * PDF attendance sheet
362 *
363 * @param Request $request PSR Request
364 * @param Response $response PSR Response
365 *
366 * @return Response
367 */
368 public function attendanceSheet(Request $request, Response $response): Response
369 {
370 $post = $request->getParsedBody();
371
372 if ($this->session->filter_members !== null) {
373 $filters = $this->session->filter_members;
374 } else {
375 $filters = new MembersList();
376 }
377
378 //retrieve selected members
379 $selection = (isset($post['selection'])) ? $post['selection'] : array();
380
381 $filters->selected = $selection;
382 $this->session->filter_members = $filters;
383
384 if (count($filters->selected) == 0) {
385 Analog::log('No member selected to generate attendance sheet', Analog::INFO);
386 $this->flash->addMessage(
387 'error_detected',
388 _T("No member selected to generate attendance sheet")
389 );
390
391 return $response
392 ->withStatus(301)
393 ->withHeader('Location', $this->router->pathFor('members'));
394 }
395
396 $m = new Members();
397 $members = $m->getArrayList(
398 $filters->selected,
399 array('nom_adh', 'prenom_adh'),
400 true
401 );
402
403 if (!is_array($members) || count($members) < 1) {
404 Analog::log('No member selected to generate attendance sheet', Analog::INFO);
405 $this->flash->addMessage(
406 'error_detected',
407 _T("No member selected to generate attendance sheet")
408 );
409
410 return $response
411 ->withStatus(301)
412 ->withHeader('Location', $this->router->pathFor('members'));
413 }
414
415 $doc_title = _T("Attendance sheet");
416 if (isset($post['sheet_type']) && trim($post['sheet_type']) != '') {
417 $doc_title = $post['sheet_type'];
418 }
419
420 $data = [
421 'doc_title' => $doc_title,
422 'title' => $post['sheet_title'] ?? null,
423 'subtitle' => $post['sheet_sub_title'] ?? null,
424 'sheet_date' => $post['sheet_date'] ?? null
425 ];
426 $pdf = new PdfAttendanceSheet($this->zdb, $this->preferences, $data);
427 //with or without images?
428 if (isset($post['sheet_photos']) && $post['sheet_photos'] === '1') {
429 $pdf->withImages();
430 }
431 $pdf->drawSheet($members);
432
433 return $this->sendResponse($response, $pdf);
434 }
435
436 /**
437 * Contribution PDF
438 *
439 * @param Request $request PSR Request
440 * @param Response $response PSR Response
441 * @param array $args Request arguments
442 *
443 * @return Response
444 */
445 public function contribution(Request $request, Response $response, array $args = []): Response
446 {
447 $contribution = new Contribution($this->zdb, $this->login, (int)$args['id']);
448 if ($contribution->id == '') {
449 //not possible to load contribution, exit
450 $this->flash->addMessage(
451 'error_detected',
452 str_replace(
453 '%id',
454 $args['id'],
455 _T("Unable to load contribution #%id!")
456 )
457 );
458 return $response
459 ->withStatus(301)
460 ->withHeader('Location', $this->router->pathFor(
461 'contributions',
462 ['type' => 'contributions']
463 ));
464 } else {
465 $pdf = new PdfContribution($contribution, $this->zdb, $this->preferences);
466 return $this->sendResponse($response, $pdf);
467 }
468 }
469
470 /**
471 * Groups PDF
472 *
473 * @param Request $request PSR Request
474 * @param Response $response PSR Response
475 * @param array $args Request arguments
476 *
477 * @return Response
478 */
479 public function group(Request $request, Response $response, array $args = []): Response
480 {
481 $groups = new Groups($this->zdb, $this->login);
482
483 $groups_list = null;
484 if (isset($args['id'])) {
485 $groups_list = $groups->getList(true, $args['id']);
486 } else {
487 $groups_list = $groups->getList();
488 }
489
490 if (!is_array($groups_list) || count($groups_list) < 1) {
491 Analog::log(
492 'An error has occurred, unable to get groups list.',
493 Analog::ERROR
494 );
495
496 $this->flash->addMessage(
497 'error_detected',
498 _T("Unable to get groups list.")
499 );
500
501 return $response
502 ->withStatus(301)
503 ->withHeader('Location', $this->router->pathFor('groups'));
504 }
505
506 $pdf = new PdfGroups($this->preferences);
507 $pdf->draw($groups_list, $this->login);
508
509 return $this->sendResponse($response, $pdf);
510 }
511
512 /**
513 * PDF models list
514 *
515 * @param Request $request PSR Request
516 * @param Response $response PSR Response
517 * @param array $args Request arguments
518 *
519 * @return Response
520 */
521 public function models(Request $request, Response $response, array $args = []): Response
522 {
523 $id = 1;
524 if (isset($_POST[PdfModel::PK])) {
525 $id = (int)$_POST[PdfModel::PK];
526 } elseif (isset($args['id'])) {
527 $id = (int)$args['id'];
528 }
529
530
531 $ms = new PdfModels($this->zdb, $this->preferences, $this->login);
532 $models = $ms->getList();
533
534 $model = null;
535 foreach ($models as $m) {
536 if ($m->id === $id) {
537 $model = $m;
538 break;
539 }
540 }
541
542 $tpl = null;
543 $params = [];
544
545 //Render directly template if we called from ajax,
546 //render in a full page otherwise
547 if (
548 $request->isXhr()
549 || isset($request->getQueryParams()['ajax'])
550 && $request->getQueryParams()['ajax'] == 'true'
551 ) {
552 $tpl = 'gestion_pdf_content.tpl';
553 $params['model'] = $model;
554 } else {
555 $tpl = 'gestion_pdf.tpl';
556 $params = [
557 'page_title' => _T("PDF models"),
558 'models' => $models,
559 'model' => $model
560 ];
561 }
562
563 // display page
564 $this->view->render(
565 $response,
566 $tpl,
567 $params
568 );
569 return $response;
570 }
571
572 /**
573 * Store PDF models
574 *
575 * @param Request $request PSR Request
576 * @param Response $response PSR Response
577 * @param array $args Request arguments
578 *
579 * @return Response
580 */
581 public function storeModels(Request $request, Response $response, array $args = []): Response
582 {
583 $post = $request->getParsedBody();
584 $type = null;
585 if (isset($post['model_type'])) {
586 $type = (int)$post['model_type'];
587 }
588
589 if ($type === null) {
590 $this->flash->addMessage(
591 'error_detected',
592 _T("Missing PDF model type!")
593 );
594 } else {
595 $class = PdfModel::getTypeClass($type);
596 if (isset($post[PdfModel::PK])) {
597 $model = new $class($this->zdb, $this->preferences, (int)$_POST[PdfModel::PK]);
598 } else {
599 $model = new $class($this->zdb, $this->preferences);
600 }
601
602 try {
603 $model->header = $post['model_header'];
604 $model->footer = $post['model_footer'];
605 $model->type = $type;
606 if (isset($post['model_body'])) {
607 $model->body = $post['model_body'];
608 }
609 if (isset($post['model_title'])) {
610 $model->title = $post['model_title'];
611 }
612 if (isset($post['model_body'])) {
613 $model->subtitle = $post['model_subtitle'];
614 }
615 if (isset($post['model_styles'])) {
616 $model->styles = $post['model_styles'];
617 }
618 $res = $model->store();
619 if ($res === true) {
620 $this->flash->addMessage(
621 'success_detected',
622 _T("Model has been successfully stored!")
623 );
624 } else {
625 $this->flash->addMessage(
626 'error_detected',
627 _T("Model has not been stored :(")
628 );
629 }
630 } catch (\Exception $e) {
631 $error_detected[] = $e->getMessage();
632 }
633 }
634
635 return $response
636 ->withStatus(301)
637 ->withHeader('Location', $this->router->pathFor('pdfModels', ['id' => $model->id]));
638 }
639
640
641 /**
642 * Get direct document
643 *
644 * @param Request $request PSR Request
645 * @param Response $response PSR Response
646 * @param array $args Request arguments
647 *
648 * @return Response
649 */
650 public function directlinkDocument(Request $request, Response $response, array $args = []): Response
651 {
652 $hash = $args['hash'];
653 $post = $request->getParsedBody();
654 $email = $post['email'];
655
656 $links = new Links($this->zdb);
657 $valid = $links->isHashValid($hash, $email);
658
659 if ($valid === false) {
660 $this->flash->addMessage(
661 'error_detected',
662 _T("Invalid link!")
663 );
664
665 return $response->withStatus(301)
666 ->withHeader('Location', $this->router->pathFor('directlink', ['hash' => $hash]));
667 }
668
669 $target = $valid[0];
670 $id = $valid[1];
671
672 if ($target === Links::TARGET_MEMBERCARD) {
673 $m = new Members();
674 $members = $m->getArrayList(
675 [$id],
676 array('nom_adh', 'prenom_adh'),
677 true
678 );
679
680 if (!is_array($members) || count($members) < 1) {
681 Analog::log(
682 'An error has occurred, unable to get members list.',
683 Analog::ERROR
684 );
685
686 $this->flash->addMessage(
687 'error_detected',
688 _T("Unable to get members list.")
689 );
690
691 return $response
692 ->withStatus(301)
693 ->withHeader('Location', $this->router->pathFor('directlink', ['hash' => $hash]));
694 }
695
696 $pdf = new PdfMembersCards($this->preferences);
697 $pdf->drawCards($members);
698 } else {
699 $contribution = new Contribution($this->zdb, $this->login, $id);
700 if ($contribution->id == '') {
701 //not possible to load contribution, exit
702 $this->flash->addMessage(
703 'error_detected',
704 str_replace(
705 '%id',
706 $args['id'],
707 _T("Unable to load contribution #%id!")
708 )
709 );
710 return $response
711 ->withStatus(301)
712 ->withHeader('Location', $this->router->pathFor(
713 'directlink',
714 ['hash' => $hash]
715 ));
716 } else {
717 $pdf = new PdfContribution($contribution, $this->zdb, $this->preferences);
718 }
719 }
720
721 return $this->sendResponse($response, $pdf);
722 }
723 }