xref: /webtrees/app/Module/ModuleDataFixTrait.php (revision ce42304a0e3b715b5830d587f136ecd5ca69f11b)
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\Module;
21
22use Fisharebest\Webtrees\Family;
23use Fisharebest\Webtrees\GedcomRecord;
24use Fisharebest\Webtrees\Individual;
25use Fisharebest\Webtrees\Media;
26use Fisharebest\Webtrees\Note;
27use Fisharebest\Webtrees\Repository;
28use Fisharebest\Webtrees\Source;
29use Fisharebest\Webtrees\Submitter;
30use Fisharebest\Webtrees\Tree;
31use Illuminate\Database\Capsule\Manager as DB;
32use Illuminate\Database\Query\Builder;
33use Illuminate\Support\Collection;
34use stdClass;
35
36/**
37 * Trait ModuleDataFixTrait - default implementation of ModuleDataFixTrait
38 */
39trait ModuleDataFixTrait
40{
41    /**
42     * Options form.
43     *
44     * @param Tree $tree
45     *
46     * @return string
47     */
48    public function fixOptions(Tree $tree): string
49    {
50        return '';
51    }
52
53    /**
54     * A list of all records that need examining.  This may include records
55     * that do not need updating, if we can't detect this quickly using SQL.
56     *
57     * @param Tree                 $tree
58     * @param array<string,string> $params
59     *
60     * @return Collection<stdClass>
61     */
62    public function recordsToFix(Tree $tree, array $params): Collection
63    {
64        $families     = $this->familiesToFix($tree, $params);
65        $individuals  = $this->individualsToFix($tree, $params);
66        $media        = $this->mediaToFix($tree, $params);
67        $notes        = $this->notesToFix($tree, $params);
68        $repositories = $this->repositoriesToFix($tree, $params);
69        $sources      = $this->sourcesToFix($tree, $params);
70        $submitters   = $this->submittersToFix($tree, $params);
71
72        $records = new Collection();
73
74        if ($families !== null) {
75            $records = $records->concat($this->mergePendingRecords($families, $tree, Family::RECORD_TYPE));
76        }
77
78        if ($individuals !== null) {
79            $records = $records->concat($this->mergePendingRecords($individuals, $tree, Individual::RECORD_TYPE));
80        }
81
82        if ($media !== null) {
83            $records = $records->concat($this->mergePendingRecords($media, $tree, Media::RECORD_TYPE));
84        }
85
86        if ($notes !== null) {
87            $records = $records->concat($this->mergePendingRecords($notes, $tree, Note::RECORD_TYPE));
88        }
89
90        if ($repositories !== null) {
91            $records = $records->concat($this->mergePendingRecords($repositories, $tree, Repository::RECORD_TYPE));
92        }
93
94        if ($sources !== null) {
95            $records = $records->concat($this->mergePendingRecords($sources, $tree, Source::RECORD_TYPE));
96        }
97
98        if ($submitters !== null) {
99            $records = $records->concat($this->mergePendingRecords($submitters, $tree, Submitter::RECORD_TYPE));
100        }
101
102        return $records
103            ->unique()
104            ->sort(static function (stdClass $x, stdClass $y) {
105                return $x->xref <=> $y->xref;
106            });
107    }
108
109    /**
110     * Does a record need updating?
111     *
112     * @param GedcomRecord         $record
113     * @param array<string,string> $params
114     *
115     * @return bool
116     */
117    public function doesRecordNeedUpdate(GedcomRecord $record, array $params): bool
118    {
119        return false;
120    }
121
122    /**
123     * Show the changes we would make
124     *
125     * @param GedcomRecord         $record
126     * @param array<string,string> $params
127     *
128     * @return string
129     */
130    public function previewUpdate(GedcomRecord $record, array $params): string
131    {
132        return $record->fullName();
133    }
134
135    /**
136     * Fix a record
137     *
138     * @param GedcomRecord         $record
139     * @param array<string,string> $params
140     *
141     * @return void
142     */
143    public function updateRecord(GedcomRecord $record, array $params): void
144    {
145    }
146
147    /**
148     * XREFs of family records that might need fixing.
149     *
150     * @param Tree                 $tree
151     * @param array<string,string> $params
152     *
153     * @return Collection<string>|null
154     */
155    protected function familiesToFix(Tree $tree, array $params): ?Collection
156    {
157        return null;
158    }
159
160    /**
161     * XREFs of individual records that might need fixing.
162     *
163     * @param Tree                 $tree
164     * @param array<string,string> $params
165     *
166     * @return Collection<string>|null
167     */
168    protected function individualsToFix(Tree $tree, array $params): ?Collection
169    {
170        return null;
171    }
172
173    /**
174     * XREFs of media records that might need fixing.
175     *
176     * @param Tree                 $tree
177     * @param array<string,string> $params
178     *
179     * @return Collection<string>|null
180     */
181    protected function mediaToFix(Tree $tree, array $params): ?Collection
182    {
183        return null;
184    }
185
186    /**
187     * XREFs of note records that might need fixing.
188     *
189     * @param Tree                 $tree
190     * @param array<string,string> $params
191     *
192     * @return Collection<string>|null
193     */
194    protected function notesToFix(Tree $tree, array $params): ?Collection
195    {
196        return null;
197    }
198
199    /**
200     * XREFs of repository records that might need fixing.
201     *
202     * @param Tree                 $tree
203     * @param array<string,string> $params
204     *
205     * @return Collection<string>|null
206     */
207    protected function repositoriesToFix(Tree $tree, array $params): ?Collection
208    {
209        return null;
210    }
211
212    /**
213     * XREFs of source records that might need fixing.
214     *
215     * @param Tree                 $tree
216     * @param array<string,string> $params
217     *
218     * @return Collection<string>|null
219     */
220    protected function sourcesToFix(Tree $tree, array $params): ?Collection
221    {
222        return null;
223    }
224
225    /**
226     * XREFs of submitter records that might need fixing.
227     *
228     * @param Tree                 $tree
229     * @param array<string,string> $params
230     *
231     * @return Collection<string>|null
232     */
233    protected function submittersToFix(Tree $tree, array $params): ?Collection
234    {
235        return null;
236    }
237
238    /**
239     * Merge pending changes of a given type.  We need to check all pending records.
240     *
241     * @param Collection<string> $records
242     * @param Tree               $tree
243     * @param string             $type
244     *
245     * @return Collection<stdClass>
246     */
247    private function mergePendingRecords(Collection $records, Tree $tree, string $type): Collection
248    {
249        $pending = DB::table('change')
250            ->where('gedcom_id', '=', $tree->id())
251            ->where('status', '=', 'pending')
252            ->where(static function (Builder $query) use ($type): void {
253                $query
254                    ->where('old_gedcom', 'LIKE', '%@ ' . $type . '%')
255                    ->orWhere('new_gedcom', 'LIKE', '%@ ' . $type . '%');
256            })
257            ->pluck('xref');
258
259        return $records
260            ->concat($pending)
261            ->map(static function (string $xref) use ($type): stdClass {
262                return (object) ['xref' => $xref, 'type' => $type];
263            });
264    }
265}
266