xref: /webtrees/app/Http/RequestHandlers/SearchAdvancedPage.php (revision a91af26a243351ccb974da73fcc6ad5c8e1d6eba)
1f5402f3dSGreg Roach<?php
2f5402f3dSGreg Roach
3f5402f3dSGreg Roach/**
4f5402f3dSGreg Roach * webtrees: online genealogy
5f5402f3dSGreg Roach * Copyright (C) 2019 webtrees development team
6f5402f3dSGreg Roach * This program is free software: you can redistribute it and/or modify
7f5402f3dSGreg Roach * it under the terms of the GNU General Public License as published by
8f5402f3dSGreg Roach * the Free Software Foundation, either version 3 of the License, or
9f5402f3dSGreg Roach * (at your option) any later version.
10f5402f3dSGreg Roach * This program is distributed in the hope that it will be useful,
11f5402f3dSGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
12f5402f3dSGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13f5402f3dSGreg Roach * GNU General Public License for more details.
14f5402f3dSGreg Roach * You should have received a copy of the GNU General Public License
15f5402f3dSGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>.
16f5402f3dSGreg Roach */
17f5402f3dSGreg Roach
18f5402f3dSGreg Roachdeclare(strict_types=1);
19f5402f3dSGreg Roach
20f5402f3dSGreg Roachnamespace Fisharebest\Webtrees\Http\RequestHandlers;
21f5402f3dSGreg Roach
22f5402f3dSGreg Roachuse Fisharebest\Webtrees\GedcomTag;
23f5402f3dSGreg Roachuse Fisharebest\Webtrees\Http\ViewResponseTrait;
24f5402f3dSGreg Roachuse Fisharebest\Webtrees\I18N;
25f5402f3dSGreg Roachuse Fisharebest\Webtrees\Services\SearchService;
26f5402f3dSGreg Roachuse Fisharebest\Webtrees\Tree;
27f5402f3dSGreg Roachuse InvalidArgumentException;
28f5402f3dSGreg Roachuse Psr\Http\Message\ResponseInterface;
29f5402f3dSGreg Roachuse Psr\Http\Message\ServerRequestInterface;
30f5402f3dSGreg Roachuse Psr\Http\Server\RequestHandlerInterface;
31f5402f3dSGreg Roach
32f5402f3dSGreg Roach/**
33f5402f3dSGreg Roach * Search for genealogy data
34f5402f3dSGreg Roach */
35f5402f3dSGreg Roachclass SearchAdvancedPage implements RequestHandlerInterface
36f5402f3dSGreg Roach{
37f5402f3dSGreg Roach    use ViewResponseTrait;
38f5402f3dSGreg Roach
39f5402f3dSGreg Roach    private const DEFAULT_ADVANCED_FIELDS = [
40f5402f3dSGreg Roach        'NAME:GIVN',
41f5402f3dSGreg Roach        'NAME:SURN',
42f5402f3dSGreg Roach        'BIRT:DATE',
43f5402f3dSGreg Roach        'BIRT:PLAC',
44f5402f3dSGreg Roach        'FAMS:MARR:DATE',
45f5402f3dSGreg Roach        'FAMS:MARR:PLAC',
46f5402f3dSGreg Roach        'DEAT:DATE',
47f5402f3dSGreg Roach        'DEAT:PLAC',
48f5402f3dSGreg Roach        'FAMC:HUSB:NAME:GIVN',
49f5402f3dSGreg Roach        'FAMC:HUSB:NAME:SURN',
50f5402f3dSGreg Roach        'FAMC:WIFE:NAME:GIVN',
51f5402f3dSGreg Roach        'FAMC:WIFE:NAME:SURN',
52f5402f3dSGreg Roach    ];
53f5402f3dSGreg Roach
54f5402f3dSGreg Roach    private const OTHER_ADVANCED_FIELDS = [
55f5402f3dSGreg Roach        'ADOP:DATE',
56f5402f3dSGreg Roach        'ADOP:PLAC',
57f5402f3dSGreg Roach        'AFN',
58f5402f3dSGreg Roach        'BAPL:DATE',
59f5402f3dSGreg Roach        'BAPL:PLAC',
60f5402f3dSGreg Roach        'BAPM:DATE',
61f5402f3dSGreg Roach        'BAPM:PLAC',
62f5402f3dSGreg Roach        'BARM:DATE',
63f5402f3dSGreg Roach        'BARM:PLAC',
64f5402f3dSGreg Roach        'BASM:DATE',
65f5402f3dSGreg Roach        'BASM:PLAC',
66f5402f3dSGreg Roach        'BLES:DATE',
67f5402f3dSGreg Roach        'BLES:PLAC',
68f5402f3dSGreg Roach        'BURI:DATE',
69f5402f3dSGreg Roach        'BURI:PLAC',
70f5402f3dSGreg Roach        'CAST',
71f5402f3dSGreg Roach        'CENS:DATE',
72f5402f3dSGreg Roach        'CENS:PLAC',
73f5402f3dSGreg Roach        'CHAN:DATE',
74f5402f3dSGreg Roach        'CHAN:_WT_USER',
75f5402f3dSGreg Roach        'CHR:DATE',
76f5402f3dSGreg Roach        'CHR:PLAC',
77f5402f3dSGreg Roach        'CREM:DATE',
78f5402f3dSGreg Roach        'CREM:PLAC',
79f5402f3dSGreg Roach        'DSCR',
80f5402f3dSGreg Roach        'EMAIL',
81f5402f3dSGreg Roach        'EMIG:DATE',
82f5402f3dSGreg Roach        'EMIG:PLAC',
83f5402f3dSGreg Roach        'ENDL:DATE',
84f5402f3dSGreg Roach        'ENDL:PLAC',
85f5402f3dSGreg Roach        'EVEN',
86f5402f3dSGreg Roach        'EVEN:TYPE',
87f5402f3dSGreg Roach        'EVEN:DATE',
88f5402f3dSGreg Roach        'EVEN:PLAC',
89f5402f3dSGreg Roach        'FACT',
90f5402f3dSGreg Roach        'FACT:TYPE',
91f5402f3dSGreg Roach        'FAMS:CENS:DATE',
92f5402f3dSGreg Roach        'FAMS:CENS:PLAC',
93f5402f3dSGreg Roach        'FAMS:DIV:DATE',
94f5402f3dSGreg Roach        'FAMS:NOTE',
95f5402f3dSGreg Roach        'FAMS:SLGS:DATE',
96f5402f3dSGreg Roach        'FAMS:SLGS:PLAC',
97f5402f3dSGreg Roach        'FAX',
98f5402f3dSGreg Roach        'FCOM:DATE',
99f5402f3dSGreg Roach        'FCOM:PLAC',
100f5402f3dSGreg Roach        'IMMI:DATE',
101f5402f3dSGreg Roach        'IMMI:PLAC',
102f5402f3dSGreg Roach        'NAME:NICK',
103f5402f3dSGreg Roach        'NAME:_MARNM',
104f5402f3dSGreg Roach        'NAME:_HEB',
105f5402f3dSGreg Roach        'NAME:ROMN',
106f5402f3dSGreg Roach        'NATI',
107f5402f3dSGreg Roach        'NATU:DATE',
108f5402f3dSGreg Roach        'NATU:PLAC',
109f5402f3dSGreg Roach        'NOTE',
110f5402f3dSGreg Roach        'OCCU',
111f5402f3dSGreg Roach        'ORDN:DATE',
112f5402f3dSGreg Roach        'ORDN:PLAC',
113f5402f3dSGreg Roach        'REFN',
114f5402f3dSGreg Roach        'RELI',
115f5402f3dSGreg Roach        'RESI',
116f5402f3dSGreg Roach        'RESI:DATE',
117f5402f3dSGreg Roach        'RESI:PLAC',
118f5402f3dSGreg Roach        'SLGC:DATE',
119f5402f3dSGreg Roach        'SLGC:PLAC',
120f5402f3dSGreg Roach        'TITL',
121f5402f3dSGreg Roach        '_BRTM:DATE',
122f5402f3dSGreg Roach        '_BRTM:PLAC',
123f5402f3dSGreg Roach        '_MILI',
124f5402f3dSGreg Roach    ];
125f5402f3dSGreg Roach
126f5402f3dSGreg Roach    /** @var SearchService */
127f5402f3dSGreg Roach    private $search_service;
128f5402f3dSGreg Roach
129f5402f3dSGreg Roach    /**
130f5402f3dSGreg Roach     * SearchController constructor.
131f5402f3dSGreg Roach     *
132f5402f3dSGreg Roach     * @param SearchService $search_service
133f5402f3dSGreg Roach     */
134f5402f3dSGreg Roach    public function __construct(SearchService $search_service)
135f5402f3dSGreg Roach    {
136f5402f3dSGreg Roach        $this->search_service = $search_service;
137f5402f3dSGreg Roach    }
138f5402f3dSGreg Roach
139f5402f3dSGreg Roach    /**
140f5402f3dSGreg Roach     * A structured search.
141f5402f3dSGreg Roach     *
142f5402f3dSGreg Roach     * @param ServerRequestInterface $request
143f5402f3dSGreg Roach     *
144f5402f3dSGreg Roach     * @return ResponseInterface
145f5402f3dSGreg Roach     */
146f5402f3dSGreg Roach    public function handle(ServerRequestInterface $request): ResponseInterface
147f5402f3dSGreg Roach    {
148f5402f3dSGreg Roach        $tree = $request->getAttribute('tree');
149f5402f3dSGreg Roach        assert($tree instanceof Tree, new InvalidArgumentException());
150f5402f3dSGreg Roach
151f5402f3dSGreg Roach        $default_fields = array_fill_keys(self::DEFAULT_ADVANCED_FIELDS, '');
152f5402f3dSGreg Roach
153f5402f3dSGreg Roach        $params = $request->getQueryParams();
154f5402f3dSGreg Roach
155f5402f3dSGreg Roach        $fields      = $params['fields'] ?? $default_fields;
156f5402f3dSGreg Roach        $modifiers   = $params['modifiers'] ?? [];
157f5402f3dSGreg Roach
158f5402f3dSGreg Roach        $other_fields = $this->otherFields($fields);
159f5402f3dSGreg Roach        $date_options = $this->dateOptions();
160f5402f3dSGreg Roach        $name_options = $this->nameOptions();
161f5402f3dSGreg Roach
162*a91af26aSGreg Roach        if (array_filter($fields) !== []) {
163f5402f3dSGreg Roach            $individuals = $this->search_service->searchIndividualsAdvanced([$tree], $fields, $modifiers);
164f5402f3dSGreg Roach        } else {
165f5402f3dSGreg Roach            $individuals = [];
166f5402f3dSGreg Roach        }
167f5402f3dSGreg Roach
168f5402f3dSGreg Roach        $title = I18N::translate('Advanced search');
169f5402f3dSGreg Roach
170f5402f3dSGreg Roach        return $this->viewResponse('search-advanced-page', [
171f5402f3dSGreg Roach            'date_options' => $date_options,
172f5402f3dSGreg Roach            'fields'       => $fields,
173f5402f3dSGreg Roach            'individuals'  => $individuals,
174f5402f3dSGreg Roach            'modifiers'    => $modifiers,
175f5402f3dSGreg Roach            'name_options' => $name_options,
176f5402f3dSGreg Roach            'other_fields' => $other_fields,
177f5402f3dSGreg Roach            'title'        => $title,
178f5402f3dSGreg Roach        ]);
179f5402f3dSGreg Roach    }
180f5402f3dSGreg Roach
181f5402f3dSGreg Roach    /**
182f5402f3dSGreg Roach     * Extra search fields to add to the advanced search
183f5402f3dSGreg Roach     *
184f5402f3dSGreg Roach     * @param string[] $fields
185f5402f3dSGreg Roach     *
186f5402f3dSGreg Roach     * @return string[]
187f5402f3dSGreg Roach     */
188f5402f3dSGreg Roach    private function otherFields(array $fields): array
189f5402f3dSGreg Roach    {
190f5402f3dSGreg Roach        $unused = array_diff(self::OTHER_ADVANCED_FIELDS, array_keys($fields));
191f5402f3dSGreg Roach
192f5402f3dSGreg Roach        $other_fields = [];
193f5402f3dSGreg Roach
194f5402f3dSGreg Roach        foreach ($unused as $tag) {
195f5402f3dSGreg Roach            $other_fields[$tag] = GedcomTag::getLabel($tag);
196f5402f3dSGreg Roach        }
197f5402f3dSGreg Roach
198f5402f3dSGreg Roach        return $other_fields;
199f5402f3dSGreg Roach    }
200f5402f3dSGreg Roach
201f5402f3dSGreg Roach    /**
202f5402f3dSGreg Roach     * For the advanced search
203f5402f3dSGreg Roach     *
204f5402f3dSGreg Roach     * @return string[]
205f5402f3dSGreg Roach     */
206f5402f3dSGreg Roach    private function dateOptions(): array
207f5402f3dSGreg Roach    {
208f5402f3dSGreg Roach        return [
209f5402f3dSGreg Roach            0  => I18N::translate('Exact date'),
210f5402f3dSGreg Roach            2  => I18N::plural('±%s year', '±%s years', 2, I18N::number(2)),
211f5402f3dSGreg Roach            5  => I18N::plural('±%s year', '±%s years', 5, I18N::number(5)),
212f5402f3dSGreg Roach            10 => I18N::plural('±%s year', '±%s years', 10, I18N::number(10)),
213f5402f3dSGreg Roach        ];
214f5402f3dSGreg Roach    }
215f5402f3dSGreg Roach
216f5402f3dSGreg Roach    /**
217f5402f3dSGreg Roach     * For the advanced search
218f5402f3dSGreg Roach     *
219f5402f3dSGreg Roach     * @return string[]
220f5402f3dSGreg Roach     */
221f5402f3dSGreg Roach    private function nameOptions(): array
222f5402f3dSGreg Roach    {
223f5402f3dSGreg Roach        return [
224f5402f3dSGreg Roach            'EXACT'    => I18N::translate('Exact'),
225f5402f3dSGreg Roach            'BEGINS'   => I18N::translate('Begins with'),
226f5402f3dSGreg Roach            'CONTAINS' => I18N::translate('Contains'),
227f5402f3dSGreg Roach            'SDX'      => I18N::translate('Sounds like'),
228f5402f3dSGreg Roach        ];
229f5402f3dSGreg Roach    }
230f5402f3dSGreg Roach}
231