xref: /webtrees/app/Http/RequestHandlers/ReportSetupPage.php (revision 30e63383b10bafff54347985dcdbd10c40c33f62)
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\Contracts\UserInterface;
24use Fisharebest\Webtrees\Html;
25use Fisharebest\Webtrees\Http\ViewResponseTrait;
26use Fisharebest\Webtrees\I18N;
27use Fisharebest\Webtrees\Module\ModuleReportInterface;
28use Fisharebest\Webtrees\Registry;
29use Fisharebest\Webtrees\Report\ReportParserSetup;
30use Fisharebest\Webtrees\Services\LocalizationService;
31use Fisharebest\Webtrees\Services\ModuleService;
32use Fisharebest\Webtrees\Tree;
33use Psr\Http\Message\ResponseInterface;
34use Psr\Http\Message\ServerRequestInterface;
35use Psr\Http\Server\RequestHandlerInterface;
36
37use function assert;
38use function redirect;
39use function route;
40
41/**
42 * Get parameters for a report.
43 */
44class ReportSetupPage implements RequestHandlerInterface
45{
46    use ViewResponseTrait;
47
48    private LocalizationService $localization_service;
49
50    private ModuleService $module_service;
51
52    /**
53     * ReportEngineController constructor.
54     *
55     * @param LocalizationService $localization_service
56     * @param ModuleService       $module_service
57     */
58    public function __construct(LocalizationService $localization_service, ModuleService $module_service)
59    {
60        $this->localization_service = $localization_service;
61        $this->module_service = $module_service;
62    }
63
64    /**
65     * @param ServerRequestInterface $request
66     *
67     * @return ResponseInterface
68     */
69    public function handle(ServerRequestInterface $request): ResponseInterface
70    {
71        $tree = $request->getAttribute('tree');
72        assert($tree instanceof Tree);
73
74        $user = $request->getAttribute('user');
75        assert($user instanceof UserInterface);
76
77        $report = $request->getAttribute('report');
78        $module = $this->module_service->findByName($report);
79
80        if (!$module instanceof ModuleReportInterface) {
81            return redirect(route(ReportListPage::class, ['tree' => $tree->name()]));
82        }
83
84        Auth::checkComponentAccess($module, ModuleReportInterface::class, $tree, $user);
85
86        $xref = $request->getQueryParams()['xref'] ?? '';
87
88        $xml_filename = $module->resourcesFolder() . $module->xmlFilename();
89
90        $report_array = (new ReportParserSetup($xml_filename))->reportProperties();
91        $description  = $report_array['description'];
92        $title        = $report_array['title'];
93
94        $inputs = [];
95
96        foreach ($report_array['inputs'] ?? [] as $n => $input) {
97            $input += [
98                'type'    => 'text',
99                'default' => '',
100                'lookup'  => '',
101                'extra'   => '',
102            ];
103
104            $attributes = [
105                'id'    => 'input-' . $n,
106                'name'  => 'vars[' . $input['name'] . ']',
107                'class' => $input['type'] === 'checkbox' ? 'form-control-check' : 'form-control',
108            ];
109
110            switch ($input['lookup']) {
111                case 'INDI':
112                    $input['control'] = view('components/select-individual', [
113                        'id'         => 'input-' . $n,
114                        'name'       => 'vars[' . $input['name'] . ']',
115                        'individual' => Registry::individualFactory()->make($xref, $tree),
116                        'tree'       => $tree,
117                        'required'   => true,
118                    ]);
119                    break;
120
121                case 'FAM':
122                    $input['control'] = view('components/select-family', [
123                        'id'       => 'input-' . $n,
124                        'name'     => 'vars[' . $input['name'] . ']',
125                        'family'   => Registry::familyFactory()->make($xref, $tree),
126                        'tree'     => $tree,
127                        'required' => true,
128                    ]);
129                    break;
130
131                case 'SOUR':
132                    $input['control'] = view('components/select-source', [
133                        'id'       => 'input-' . $n,
134                        'name'     => 'vars[' . $input['name'] . ']',
135                        'family'   => Registry::sourceFactory()->make($xref, $tree),
136                        'tree'     => $tree,
137                        'required' => true,
138                    ]);
139                    break;
140
141                case 'DATE':
142                    // Need to know if the user prefers DMY/MDY/YMD so we can validate dates properly.
143                    $dmy = $this->localization_service->dateFormatToOrder(I18N::dateFormat());
144
145                    $attributes += [
146                        'type'     => 'text',
147                        'value'    => $input['default'],
148                        'dir'      => 'ltr',
149                        'onchange' => 'webtrees.reformatDate(this, "' . $dmy . '")'
150                    ];
151                    $input['control'] = '<input ' . Html::attributes($attributes) . '>';
152                    $input['extra'] = view('edit/input-addon-calendar', ['id' => 'input-' . $n]);
153                    break;
154
155                default:
156                    switch ($input['type']) {
157                        case 'text':
158                            $attributes += [
159                                'type'  => 'text',
160                                'value' => $input['default'],
161                            ];
162                            $input['control'] = '<input ' . Html::attributes($attributes) . '>';
163                            break;
164
165                        case 'checkbox':
166                            $attributes += [
167                                'type'    => 'checkbox',
168                                'checked' => (bool) $input['default'],
169                            ];
170                            $input['control'] = '<input ' . Html::attributes($attributes) . '>';
171                            break;
172
173                        case 'select':
174                            $options = [];
175                            foreach (explode('|', $input['options']) as $option) {
176                                [$key, $value] = explode('=>', $option);
177                                if (preg_match('/^I18N::number\((.+?)(,([\d+]))?\)$/', $value, $match)) {
178                                    $number        = (float) $match[1];
179                                    $precision     = (int) ($match[3] ?? 0);
180                                    $options[$key] = I18N::number($number, $precision);
181                                } elseif (preg_match('/^I18N::translate\(\'(.+)\'\)$/', $value, $match)) {
182                                    $options[$key] = I18N::translate($match[1]);
183                                } elseif (preg_match('/^I18N::translateContext\(\'(.+)\', *\'(.+)\'\)$/', $value, $match)) {
184                                    $options[$key] = I18N::translateContext($match[1], $match[2]);
185                                }
186                            }
187                            $input['control'] = view('components/select', ['name' => 'vars[' . $input['name'] . ']', 'id' => 'input-' . $n, 'selected' => $input['default'], 'options' => $options]);
188                            break;
189                    }
190            }
191
192            $inputs[] = $input;
193        }
194
195        $destination = $user->getPreference('default-report-destination', 'view');
196        $format      = $user->getPreference('default-report-format', 'PDF');
197
198        return $this->viewResponse('report-setup-page', [
199            'description' => $description,
200            'destination' => $destination,
201            'format'      => $format,
202            'inputs'      => $inputs,
203            'report'      => $report,
204            'title'       => $title,
205            'tree'        => $tree,
206        ]);
207    }
208}
209