Issues (2560)

app/Http/RequestHandlers/MergeTreesAction.php (14 issues)

1
<?php
2
3
/**
4
 * webtrees: online genealogy
5
 * Copyright (C) 2025 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
18
declare(strict_types=1);
19
20
namespace Fisharebest\Webtrees\Http\RequestHandlers;
21
22
use Fisharebest\Webtrees\DB;
0 ignored issues
show
The type Fisharebest\Webtrees\DB was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
23
use Fisharebest\Webtrees\FlashMessages;
0 ignored issues
show
The type Fisharebest\Webtrees\FlashMessages was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
24
use Fisharebest\Webtrees\Header;
0 ignored issues
show
The type Fisharebest\Webtrees\Header was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
25
use Fisharebest\Webtrees\I18N;
0 ignored issues
show
The type Fisharebest\Webtrees\I18N was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
26
use Fisharebest\Webtrees\Services\AdminService;
27
use Fisharebest\Webtrees\Services\TreeService;
0 ignored issues
show
The type Fisharebest\Webtrees\Services\TreeService was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
28
use Fisharebest\Webtrees\Tree;
29
use Fisharebest\Webtrees\Validator;
30
use Illuminate\Database\Query\Builder;
31
use Illuminate\Database\Query\Expression;
32
use Psr\Http\Message\ResponseInterface;
33
use Psr\Http\Message\ServerRequestInterface;
34
use Psr\Http\Server\RequestHandlerInterface;
35
36
use function redirect;
37
use function route;
38
39
/**
40
 * Merge two family trees.
41
 */
42
class MergeTreesAction implements RequestHandlerInterface
43
{
44
    private AdminService $admin_service;
45
46
    private TreeService $tree_service;
47
48
    /**
49
     * @param AdminService $admin_service
50
     * @param TreeService  $tree_service
51
     */
52
    public function __construct(AdminService $admin_service, TreeService $tree_service)
53
    {
54
        $this->admin_service = $admin_service;
55
        $this->tree_service  = $tree_service;
56
    }
57
58
    /**
59
     * @param ServerRequestInterface $request
60
     *
61
     * @return ResponseInterface
62
     */
63
    public function handle(ServerRequestInterface $request): ResponseInterface
64
    {
65
        $tree1_name = Validator::parsedBody($request)->string('tree1_name');
66
        $tree2_name = Validator::parsedBody($request)->string('tree2_name');
67
68
        $tree1 = $this->tree_service->all()->get($tree1_name);
69
        $tree2 = $this->tree_service->all()->get($tree2_name);
70
71
        if ($tree1 instanceof Tree && $tree2 instanceof Tree && $tree1 !== $tree2 && $this->admin_service->countCommonXrefs($tree1, $tree2) === 0) {
72
            DB::query()->from('individuals')->insertUsing([
73
                'i_file',
74
                'i_id',
75
                'i_rin',
76
                'i_sex',
77
                'i_gedcom',
78
            ], static function (Builder $query) use ($tree1, $tree2): void {
79
                $query->select([
80
                    new Expression($tree2->id()),
81
                    'i_id',
82
                    'i_rin',
83
                    'i_sex',
84
                    'i_gedcom',
85
                ])->from('individuals')
0 ignored issues
show
'individuals' of type string is incompatible with the type Closure|Illuminate\Datab...\Database\Query\Builder expected by parameter $table of Illuminate\Database\Query\Builder::from(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

85
                ])->from(/** @scrutinizer ignore-type */ 'individuals')
Loading history...
86
                    ->where('i_file', '=', $tree1->id());
87
            });
88
89
            DB::query()->from('families')->insertUsing([
90
                'f_file',
91
                'f_id',
92
                'f_husb',
93
                'f_wife',
94
                'f_gedcom',
95
                'f_numchil',
96
            ], static function (Builder $query) use ($tree1, $tree2): void {
97
                $query->select([
98
                    new Expression($tree2->id()),
99
                    'f_id',
100
                    'f_husb',
101
                    'f_wife',
102
                    'f_gedcom',
103
                    'f_numchil',
104
                ])->from('families')
0 ignored issues
show
'families' of type string is incompatible with the type Closure|Illuminate\Datab...\Database\Query\Builder expected by parameter $table of Illuminate\Database\Query\Builder::from(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

104
                ])->from(/** @scrutinizer ignore-type */ 'families')
Loading history...
105
                    ->where('f_file', '=', $tree1->id());
106
            });
107
108
            DB::query()->from('sources')->insertUsing([
109
                's_file',
110
                's_id',
111
                's_name',
112
                's_gedcom',
113
            ], static function (Builder $query) use ($tree1, $tree2): void {
114
                $query->select([
115
                    new Expression($tree2->id()),
116
                    's_id',
117
                    's_name',
118
                    's_gedcom',
119
                ])->from('sources')
0 ignored issues
show
'sources' of type string is incompatible with the type Closure|Illuminate\Datab...\Database\Query\Builder expected by parameter $table of Illuminate\Database\Query\Builder::from(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

119
                ])->from(/** @scrutinizer ignore-type */ 'sources')
Loading history...
120
                    ->where('s_file', '=', $tree1->id());
121
            });
122
123
            DB::query()->from('media')->insertUsing([
124
                'm_file',
125
                'm_id',
126
                'm_gedcom',
127
            ], static function (Builder $query) use ($tree1, $tree2): void {
128
                $query->select([
129
                    new Expression($tree2->id()),
130
                    'm_id',
131
                    'm_gedcom',
132
                ])->from('media')
0 ignored issues
show
'media' of type string is incompatible with the type Closure|Illuminate\Datab...\Database\Query\Builder expected by parameter $table of Illuminate\Database\Query\Builder::from(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

132
                ])->from(/** @scrutinizer ignore-type */ 'media')
Loading history...
133
                    ->where('m_file', '=', $tree1->id());
134
            });
135
136
            DB::query()->from('media_file')->insertUsing([
137
                'm_file',
138
                'm_id',
139
                'multimedia_file_refn',
140
                'multimedia_format',
141
                'source_media_type',
142
                'descriptive_title',
143
            ], static function (Builder $query) use ($tree1, $tree2): void {
144
                $query->select([
145
                    new Expression($tree2->id()),
146
                    'm_id',
147
                    'multimedia_file_refn',
148
                    'multimedia_format',
149
                    'source_media_type',
150
                    'descriptive_title',
151
                ])->from('media_file')
0 ignored issues
show
'media_file' of type string is incompatible with the type Closure|Illuminate\Datab...\Database\Query\Builder expected by parameter $table of Illuminate\Database\Query\Builder::from(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

151
                ])->from(/** @scrutinizer ignore-type */ 'media_file')
Loading history...
152
                    ->where('m_file', '=', $tree1->id());
153
            });
154
155
            DB::query()->from('other')->insertUsing([
156
                'o_file',
157
                'o_id',
158
                'o_type',
159
                'o_gedcom',
160
            ], static function (Builder $query) use ($tree1, $tree2): void {
161
                $query->select([
162
                    new Expression($tree2->id()),
163
                    'o_id',
164
                    'o_type',
165
                    'o_gedcom',
166
                ])->from('other')
0 ignored issues
show
'other' of type string is incompatible with the type Closure|Illuminate\Datab...\Database\Query\Builder expected by parameter $table of Illuminate\Database\Query\Builder::from(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

166
                ])->from(/** @scrutinizer ignore-type */ 'other')
Loading history...
167
                    ->whereNotIn('o_type', [Header::RECORD_TYPE, 'TRLR'])
168
                    ->where('o_file', '=', $tree1->id());
169
            });
170
171
            DB::query()->from('name')->insertUsing([
172
                'n_file',
173
                'n_id',
174
                'n_num',
175
                'n_type',
176
                'n_sort',
177
                'n_full',
178
                'n_surname',
179
                'n_surn',
180
                'n_givn',
181
                'n_soundex_givn_std',
182
                'n_soundex_surn_std',
183
                'n_soundex_givn_dm',
184
                'n_soundex_surn_dm',
185
            ], static function (Builder $query) use ($tree1, $tree2): void {
186
                $query->select([
187
                    new Expression($tree2->id()),
188
                    'n_id',
189
                    'n_num',
190
                    'n_type',
191
                    'n_sort',
192
                    'n_full',
193
                    'n_surname',
194
                    'n_surn',
195
                    'n_givn',
196
                    'n_soundex_givn_std',
197
                    'n_soundex_surn_std',
198
                    'n_soundex_givn_dm',
199
                    'n_soundex_surn_dm',
200
                ])->from('name')
0 ignored issues
show
'name' of type string is incompatible with the type Closure|Illuminate\Datab...\Database\Query\Builder expected by parameter $table of Illuminate\Database\Query\Builder::from(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

200
                ])->from(/** @scrutinizer ignore-type */ 'name')
Loading history...
201
                    ->where('n_file', '=', $tree1->id());
202
            });
203
204
            DB::query()->from('dates')->insertUsing([
205
                'd_file',
206
                'd_gid',
207
                'd_day',
208
                'd_month',
209
                'd_mon',
210
                'd_year',
211
                'd_julianday1',
212
                'd_julianday2',
213
                'd_fact',
214
                'd_type',
215
            ], static function (Builder $query) use ($tree1, $tree2): void {
216
                $query->select([
217
                    new Expression($tree2->id()),
218
                    'd_gid',
219
                    'd_day',
220
                    'd_month',
221
                    'd_mon',
222
                    'd_year',
223
                    'd_julianday1',
224
                    'd_julianday2',
225
                    'd_fact',
226
                    'd_type',
227
                ])->from('dates')
0 ignored issues
show
'dates' of type string is incompatible with the type Closure|Illuminate\Datab...\Database\Query\Builder expected by parameter $table of Illuminate\Database\Query\Builder::from(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

227
                ])->from(/** @scrutinizer ignore-type */ 'dates')
Loading history...
228
                    ->where('d_file', '=', $tree1->id());
229
            });
230
231
            DB::query()->from('link')->insertUsing([
232
                'l_file',
233
                'l_from',
234
                'l_type',
235
                'l_to',
236
            ], static function (Builder $query) use ($tree1, $tree2): void {
237
                $query->select([
238
                    new Expression($tree2->id()),
239
                    'l_from',
240
                    'l_type',
241
                    'l_to',
242
                ])->from('link')
0 ignored issues
show
'link' of type string is incompatible with the type Closure|Illuminate\Datab...\Database\Query\Builder expected by parameter $table of Illuminate\Database\Query\Builder::from(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

242
                ])->from(/** @scrutinizer ignore-type */ 'link')
Loading history...
243
                    ->whereNotIn('l_from', [Header::RECORD_TYPE, 'TRLR'])
244
                    ->where('l_file', '=', $tree1->id());
245
            });
246
247
            FlashMessages::addMessage(I18N::translate('The family trees have been merged successfully.'), 'success');
248
249
            $url = route(ManageTrees::class, ['tree' => $tree2->name()]);
250
        } else {
251
            $url = route(MergeTreesPage::class, [
252
                'tree1_name' => $tree1->name(),
253
                'tree2_name' => $tree2->name(),
254
            ]);
255
        }
256
257
        return redirect($url);
258
    }
259
}
260