xref: /webtrees/app/Services/PendingChangesService.php (revision 22e73debfe88ce217451588465f714b2b8a966ab)
1<?php
2
3/**
4 * webtrees: online genealogy
5 * Copyright (C) 2019 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\Services;
21
22use Fisharebest\Webtrees\Carbon;
23use Fisharebest\Webtrees\Functions\FunctionsImport;
24use Fisharebest\Webtrees\GedcomRecord;
25use Fisharebest\Webtrees\Tree;
26use Illuminate\Database\Capsule\Manager as DB;
27use Illuminate\Database\Query\Builder;
28use Illuminate\Database\Query\Expression;
29use InvalidArgumentException;
30use Psr\Http\Message\ServerRequestInterface;
31
32/**
33 * Manage pending changes
34 */
35class PendingChangesService
36{
37    /**
38     * Accept all changes to a tree.
39     *
40     * @param Tree $tree
41     *
42     * @return void
43     */
44    public function acceptTree(Tree $tree): void
45    {
46        $changes = DB::table('change')
47            ->where('gedcom_id', '=', $tree->id())
48            ->where('status', '=', 'pending')
49            ->orderBy('change_id')
50            ->get();
51
52        foreach ($changes as $change) {
53            if ($change->new_gedcom === '') {
54                // delete
55                FunctionsImport::updateRecord($change->old_gedcom, $tree, true);
56            } else {
57                // add/update
58                FunctionsImport::updateRecord($change->new_gedcom, $tree, false);
59            }
60
61            DB::table('change')
62                ->where('change_id', '=', $change->change_id)
63                ->update(['status' => 'accepted']);
64        }
65    }
66
67    /**
68     * Accept all changes to a record.
69     *
70     * @param GedcomRecord $record
71     */
72    public function acceptRecord(GedcomRecord $record): void
73    {
74        $changes = DB::table('change')
75            ->where('gedcom_id', '=', $record->tree()->id())
76            ->where('xref', '=', $record->xref())
77            ->where('status', '=', 'pending')
78            ->orderBy('change_id')
79            ->get();
80
81        foreach ($changes as $change) {
82            if ($change->new_gedcom === '') {
83                // delete
84                FunctionsImport::updateRecord($change->old_gedcom, $record->tree(), true);
85            } else {
86                // add/update
87                FunctionsImport::updateRecord($change->new_gedcom, $record->tree(), false);
88            }
89
90            DB::table('change')
91                ->where('change_id', '=', $change->change_id)
92                ->update(['status' => 'accepted']);
93        }
94    }
95
96    /**
97     * Accept a change (and previous changes) to a record.
98     *
99     * @param GedcomRecord $record
100     * @param string $change_id
101     */
102    public function acceptChange(GedcomRecord $record, string $change_id): void
103    {
104        $changes = DB::table('change')
105            ->where('gedcom_id', '=', $record->tree()->id())
106            ->where('xref', '=', $record->xref())
107            ->where('change_id', '<=', $change_id)
108            ->where('status', '=', 'pending')
109            ->orderBy('change_id')
110            ->get();
111
112        foreach ($changes as $change) {
113            if ($change->new_gedcom === '') {
114                // delete
115                FunctionsImport::updateRecord($change->old_gedcom, $record->tree(), true);
116            } else {
117                // add/update
118                FunctionsImport::updateRecord($change->new_gedcom, $record->tree(), false);
119            }
120
121            DB::table('change')
122                ->where('change_id', '=', $change->change_id)
123                ->update(['status' => 'accepted']);
124        }
125    }
126
127    /**
128     * Reject all changes to a tree.
129     *
130     * @param Tree $tree
131     */
132    public function rejectTree(Tree $tree): void
133    {
134        DB::table('change')
135            ->where('gedcom_id', '=', $tree->id())
136            ->where('status', '=', 'pending')
137            ->update(['status' => 'rejected']);
138    }
139
140    /**
141     * Reject a change (subsequent changes) to a record.
142     *
143     * @param GedcomRecord $record
144     * @param string       $change_id
145     */
146    public function rejectChange(GedcomRecord $record, string $change_id): void
147    {
148        DB::table('change')
149            ->where('gedcom_id', '=', $record->tree()->id())
150            ->where('xref', '=', $record->xref())
151            ->where('change_id', '>=', $change_id)
152            ->where('status', '=', 'pending')
153            ->update(['status' => 'rejected']);
154    }
155
156    /**
157     * Reject all changes to a record.
158     *
159     * @param GedcomRecord $record
160     */
161    public function rejectRecord(GedcomRecord $record): void
162    {
163        DB::table('change')
164            ->where('gedcom_id', '=', $record->tree()->id())
165            ->where('xref', '=', $record->xref())
166            ->where('status', '=', 'pending')
167            ->update(['status' => 'rejected']);
168    }
169
170    /**
171     * Generate a query for filtering the changes log.
172     *
173     * @param ServerRequestInterface $request
174     *
175     * @return Builder
176     */
177    public function changesQuery(ServerRequestInterface $request): Builder
178    {
179        $tree = $request->getAttribute('tree');
180        assert($tree instanceof Tree, new InvalidArgumentException());
181
182        $from     = $request->getQueryParams()['from'] ?? '';
183        $to       = $request->getQueryParams()['to'] ?? '';
184        $type     = $request->getQueryParams()['type'] ?? '';
185        $oldged   = $request->getQueryParams()['oldged'] ?? '';
186        $newged   = $request->getQueryParams()['newged'] ?? '';
187        $xref     = $request->getQueryParams()['xref'] ?? '';
188        $username = $request->getQueryParams()['username'] ?? '';
189        $search   = $request->getQueryParams()['search'] ?? [];
190        $search   = $search['value'] ?? '';
191
192        $query = DB::table('change')
193            ->leftJoin('user', 'user.user_id', '=', 'change.user_id')
194            ->join('gedcom', 'gedcom.gedcom_id', '=', 'change.gedcom_id')
195            ->select(['change.*', new Expression("COALESCE(user_name, '<none>') AS user_name"), 'gedcom_name'])
196            ->where('gedcom_name', '=', $tree->name());
197
198        if ($search !== '') {
199            $query->where(static function (Builder $query) use ($search): void {
200                $query
201                    ->whereContains('old_gedcom', $search)
202                    ->whereContains('new_gedcom', $search, 'or');
203            });
204        }
205
206        if ($from !== '') {
207            $query->where('change_time', '>=', $from);
208        }
209
210        if ($to !== '') {
211            // before end of the day
212            $query->where('change_time', '<', Carbon::make($to)->addDay());
213        }
214
215        if ($type !== '') {
216            $query->where('status', '=', $type);
217        }
218
219        if ($oldged !== '') {
220            $query->whereContains('old_gedcom', $oldged);
221        }
222        if ($newged !== '') {
223            $query->whereContains('new_gedcom', $oldged);
224        }
225
226        if ($xref !== '') {
227            $query->where('xref', '=', $xref);
228        }
229
230        if ($username !== '') {
231            $query->whereContains('user_name', $username);
232        }
233
234        return $query;
235    }
236}
237