xref: /webtrees/app/Http/RequestHandlers/ReportSetupPage.php (revision 94db7d2d27c3ad6a04fceebbdcb98e28e97649b3)
1<?php
2
3/**
4 * webtrees: online genealogy
5 * Copyright (C) 2021 webtrees development team
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18declare(strict_types=1);
19
20namespace Fisharebest\Webtrees\Http\RequestHandlers;
21
22use Fisharebest\Webtrees\Auth;
23use Fisharebest\Webtrees\Html;
24use Fisharebest\Webtrees\Http\ViewResponseTrait;
25use Fisharebest\Webtrees\I18N;
26use Fisharebest\Webtrees\Module\ModuleReportInterface;
27use Fisharebest\Webtrees\Registry;
28use Fisharebest\Webtrees\Report\ReportParserSetup;
29use Fisharebest\Webtrees\Services\LocalizationService;
30use Fisharebest\Webtrees\Services\ModuleService;
31use Fisharebest\Webtrees\Validator;
32use Psr\Http\Message\ResponseInterface;
33use Psr\Http\Message\ServerRequestInterface;
34use Psr\Http\Server\RequestHandlerInterface;
35
36use function redirect;
37use function route;
38
39/**
40 * Get parameters for a report.
41 */
42class ReportSetupPage implements RequestHandlerInterface
43{
44    use ViewResponseTrait;
45
46    private LocalizationService $localization_service;
47
48    private ModuleService $module_service;
49
50    /**
51     * ReportEngineController constructor.
52     *
53     * @param LocalizationService $localization_service
54     * @param ModuleService       $module_service
55     */
56    public function __construct(LocalizationService $localization_service, ModuleService $module_service)
57    {
58        $this->localization_service = $localization_service;
59        $this->module_service = $module_service;
60    }
61
62    /**
63     * @param ServerRequestInterface $request
64     *
65     * @return ResponseInterface
66     */
67    public function handle(ServerRequestInterface $request): ResponseInterface
68    {
69        $tree = Validator::attributes($request)->tree();
70        $user = Validator::attributes($request)->user();
71
72        $report = Validator::attributes($request)->string('report');
73        $module = $this->module_service->findByName($report);
74
75        if (!$module instanceof ModuleReportInterface) {
76            return redirect(route(ReportListPage::class, ['tree' => $tree->name()]));
77        }
78
79        Auth::checkComponentAccess($module, ModuleReportInterface::class, $tree, $user);
80
81        $xref = $request->getQueryParams()['xref'] ?? '';
82
83        $xml_filename = $module->resourcesFolder() . $module->xmlFilename();
84
85        $report_array = (new ReportParserSetup($xml_filename))->reportProperties();
86        $description  = $report_array['description'];
87        $title        = $report_array['title'];
88
89        $inputs = [];
90
91        foreach ($report_array['inputs'] ?? [] as $n => $input) {
92            $input += [
93                'type'    => 'text',
94                'default' => '',
95                'lookup'  => '',
96                'extra'   => '',
97            ];
98
99            $attributes = [
100                'id'    => 'input-' . $n,
101                'name'  => 'vars[' . $input['name'] . ']',
102                'class' => $input['type'] === 'checkbox' ? 'form-control-check' : 'form-control',
103            ];
104
105            switch ($input['lookup']) {
106                case 'INDI':
107                    $input['control'] = view('components/select-individual', [
108                        'id'         => 'input-' . $n,
109                        'name'       => 'vars[' . $input['name'] . ']',
110                        'individual' => Registry::individualFactory()->make($xref, $tree),
111                        'tree'       => $tree,
112                        'required'   => true,
113                    ]);
114                    break;
115
116                case 'FAM':
117                    $input['control'] = view('components/select-family', [
118                        'id'       => 'input-' . $n,
119                        'name'     => 'vars[' . $input['name'] . ']',
120                        'family'   => Registry::familyFactory()->make($xref, $tree),
121                        'tree'     => $tree,
122                        'required' => true,
123                    ]);
124                    break;
125
126                case 'SOUR':
127                    $input['control'] = view('components/select-source', [
128                        'id'       => 'input-' . $n,
129                        'name'     => 'vars[' . $input['name'] . ']',
130                        'family'   => Registry::sourceFactory()->make($xref, $tree),
131                        'tree'     => $tree,
132                        'required' => true,
133                    ]);
134                    break;
135
136                case 'DATE':
137                    // Need to know if the user prefers DMY/MDY/YMD so we can validate dates properly.
138                    $dmy = $this->localization_service->dateFormatToOrder(I18N::dateFormat());
139
140                    $attributes += [
141                        'type'     => 'text',
142                        'value'    => $input['default'],
143                        'dir'      => 'ltr',
144                        'onchange' => 'webtrees.reformatDate(this, "' . $dmy . '")'
145                    ];
146                    $input['control'] = '<input ' . Html::attributes($attributes) . '>';
147                    $input['extra'] = view('edit/input-addon-calendar', ['id' => 'input-' . $n]);
148                    break;
149
150                default:
151                    switch ($input['type']) {
152                        case 'text':
153                            $attributes += [
154                                'type'  => 'text',
155                                'value' => $input['default'],
156                            ];
157                            $input['control'] = '<input ' . Html::attributes($attributes) . '>';
158                            break;
159
160                        case 'checkbox':
161                            $attributes += [
162                                'type'    => 'checkbox',
163                                'checked' => (bool) $input['default'],
164                            ];
165                            $input['control'] = '<input ' . Html::attributes($attributes) . '>';
166                            break;
167
168                        case 'select':
169                            $options = [];
170                            foreach (explode('|', $input['options']) as $option) {
171                                [$key, $value] = explode('=>', $option);
172                                if (preg_match('/^I18N::number\((.+?)(,([\d+]))?\)$/', $value, $match)) {
173                                    $number        = (float) $match[1];
174                                    $precision     = (int) ($match[3] ?? 0);
175                                    $options[$key] = I18N::number($number, $precision);
176                                } elseif (preg_match('/^I18N::translate\(\'(.+)\'\)$/', $value, $match)) {
177                                    $options[$key] = I18N::translate($match[1]);
178                                } elseif (preg_match('/^I18N::translateContext\(\'(.+)\', *\'(.+)\'\)$/', $value, $match)) {
179                                    $options[$key] = I18N::translateContext($match[1], $match[2]);
180                                }
181                            }
182                            $input['control'] = view('components/select', ['name' => 'vars[' . $input['name'] . ']', 'id' => 'input-' . $n, 'selected' => $input['default'], 'options' => $options]);
183                            break;
184                    }
185            }
186
187            $inputs[] = $input;
188        }
189
190        $destination = $user->getPreference('default-report-destination', 'view');
191        $format      = $user->getPreference('default-report-format', 'PDF');
192
193        return $this->viewResponse('report-setup-page', [
194            'description' => $description,
195            'destination' => $destination,
196            'format'      => $format,
197            'inputs'      => $inputs,
198            'report'      => $report,
199            'title'       => $title,
200            'tree'        => $tree,
201        ]);
202    }
203}
204