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