xref: /webtrees/app/Module/ModuleDataFixTrait.php (revision 76d39c55735cfa9ad0972b0dd530e96b051f9ebe)
1ce42304aSGreg Roach<?php
2ce42304aSGreg Roach
3ce42304aSGreg Roach/**
4ce42304aSGreg Roach * webtrees: online genealogy
589f7189bSGreg Roach * Copyright (C) 2021 webtrees development team
6ce42304aSGreg Roach * This program is free software: you can redistribute it and/or modify
7ce42304aSGreg Roach * it under the terms of the GNU General Public License as published by
8ce42304aSGreg Roach * the Free Software Foundation, either version 3 of the License, or
9ce42304aSGreg Roach * (at your option) any later version.
10ce42304aSGreg Roach * This program is distributed in the hope that it will be useful,
11ce42304aSGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
12ce42304aSGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13ce42304aSGreg Roach * GNU General Public License for more details.
14ce42304aSGreg Roach * You should have received a copy of the GNU General Public License
1589f7189bSGreg Roach * along with this program. If not, see <https://www.gnu.org/licenses/>.
16ce42304aSGreg Roach */
17ce42304aSGreg Roach
18ce42304aSGreg Roachdeclare(strict_types=1);
19ce42304aSGreg Roach
20ce42304aSGreg Roachnamespace Fisharebest\Webtrees\Module;
21ce42304aSGreg Roach
22ce42304aSGreg Roachuse Fisharebest\Webtrees\Family;
23ce42304aSGreg Roachuse Fisharebest\Webtrees\GedcomRecord;
24ce42304aSGreg Roachuse Fisharebest\Webtrees\Individual;
257684867eSGreg Roachuse Fisharebest\Webtrees\Location;
26ce42304aSGreg Roachuse Fisharebest\Webtrees\Media;
27ce42304aSGreg Roachuse Fisharebest\Webtrees\Note;
28ce42304aSGreg Roachuse Fisharebest\Webtrees\Repository;
29ce42304aSGreg Roachuse Fisharebest\Webtrees\Source;
30ce42304aSGreg Roachuse Fisharebest\Webtrees\Submitter;
31ce42304aSGreg Roachuse Fisharebest\Webtrees\Tree;
32ce42304aSGreg Roachuse Illuminate\Database\Capsule\Manager as DB;
33ce42304aSGreg Roachuse Illuminate\Database\Query\Builder;
34ce42304aSGreg Roachuse Illuminate\Support\Collection;
35*76d39c55SGreg Roachuse stdClass;
36ce42304aSGreg Roach
37ce42304aSGreg Roach/**
38ce42304aSGreg Roach * Trait ModuleDataFixTrait - default implementation of ModuleDataFixTrait
39ce42304aSGreg Roach */
40ce42304aSGreg Roachtrait ModuleDataFixTrait
41ce42304aSGreg Roach{
42ce42304aSGreg Roach    /**
43ce42304aSGreg Roach     * Options form.
44ce42304aSGreg Roach     *
45ce42304aSGreg Roach     * @param Tree $tree
46ce42304aSGreg Roach     *
47ce42304aSGreg Roach     * @return string
48ce42304aSGreg Roach     */
49a09ea7ccSGreg Roach    public function fixOptions(/** @scrutinizer ignore-unused */ Tree $tree): string
50ce42304aSGreg Roach    {
51ce42304aSGreg Roach        return '';
52ce42304aSGreg Roach    }
53ce42304aSGreg Roach
54ce42304aSGreg Roach    /**
55ce42304aSGreg Roach     * A list of all records that need examining.  This may include records
56ce42304aSGreg Roach     * that do not need updating, if we can't detect this quickly using SQL.
57ce42304aSGreg Roach     *
58ce42304aSGreg Roach     * @param Tree                 $tree
59ce42304aSGreg Roach     * @param array<string,string> $params
60ce42304aSGreg Roach     *
6136779af1SGreg Roach     * @return Collection<int,object>
62ce42304aSGreg Roach     */
63ce42304aSGreg Roach    public function recordsToFix(Tree $tree, array $params): Collection
64ce42304aSGreg Roach    {
65ce42304aSGreg Roach        $families     = $this->familiesToFix($tree, $params);
66ce42304aSGreg Roach        $individuals  = $this->individualsToFix($tree, $params);
677684867eSGreg Roach        $locations    = $this->locationsToFix($tree, $params);
68ce42304aSGreg Roach        $media        = $this->mediaToFix($tree, $params);
69ce42304aSGreg Roach        $notes        = $this->notesToFix($tree, $params);
70ce42304aSGreg Roach        $repositories = $this->repositoriesToFix($tree, $params);
71ce42304aSGreg Roach        $sources      = $this->sourcesToFix($tree, $params);
72ce42304aSGreg Roach        $submitters   = $this->submittersToFix($tree, $params);
73ce42304aSGreg Roach
74ce42304aSGreg Roach        $records = new Collection();
75ce42304aSGreg Roach
76ce42304aSGreg Roach        if ($families !== null) {
77ce42304aSGreg Roach            $records = $records->concat($this->mergePendingRecords($families, $tree, Family::RECORD_TYPE));
78ce42304aSGreg Roach        }
79ce42304aSGreg Roach
80ce42304aSGreg Roach        if ($individuals !== null) {
81ce42304aSGreg Roach            $records = $records->concat($this->mergePendingRecords($individuals, $tree, Individual::RECORD_TYPE));
82ce42304aSGreg Roach        }
83ce42304aSGreg Roach
847684867eSGreg Roach        if ($locations !== null) {
857684867eSGreg Roach            $records = $records->concat($this->mergePendingRecords($locations, $tree, Location::RECORD_TYPE));
867684867eSGreg Roach        }
877684867eSGreg Roach
88ce42304aSGreg Roach        if ($media !== null) {
89ce42304aSGreg Roach            $records = $records->concat($this->mergePendingRecords($media, $tree, Media::RECORD_TYPE));
90ce42304aSGreg Roach        }
91ce42304aSGreg Roach
92ce42304aSGreg Roach        if ($notes !== null) {
93ce42304aSGreg Roach            $records = $records->concat($this->mergePendingRecords($notes, $tree, Note::RECORD_TYPE));
94ce42304aSGreg Roach        }
95ce42304aSGreg Roach
96ce42304aSGreg Roach        if ($repositories !== null) {
97ce42304aSGreg Roach            $records = $records->concat($this->mergePendingRecords($repositories, $tree, Repository::RECORD_TYPE));
98ce42304aSGreg Roach        }
99ce42304aSGreg Roach
100ce42304aSGreg Roach        if ($sources !== null) {
101ce42304aSGreg Roach            $records = $records->concat($this->mergePendingRecords($sources, $tree, Source::RECORD_TYPE));
102ce42304aSGreg Roach        }
103ce42304aSGreg Roach
104ce42304aSGreg Roach        if ($submitters !== null) {
105ce42304aSGreg Roach            $records = $records->concat($this->mergePendingRecords($submitters, $tree, Submitter::RECORD_TYPE));
106ce42304aSGreg Roach        }
107ce42304aSGreg Roach
108ce42304aSGreg Roach        return $records
109ce42304aSGreg Roach            ->unique()
110f70bcff5SGreg Roach            ->sort(static function (object $x, object $y) {
111ce42304aSGreg Roach                return $x->xref <=> $y->xref;
112ce42304aSGreg Roach            });
113ce42304aSGreg Roach    }
114ce42304aSGreg Roach
115ce42304aSGreg Roach    /**
116ce42304aSGreg Roach     * Does a record need updating?
117ce42304aSGreg Roach     *
118ce42304aSGreg Roach     * @param GedcomRecord         $record
119ce42304aSGreg Roach     * @param array<string,string> $params
120ce42304aSGreg Roach     *
121ce42304aSGreg Roach     * @return bool
122ce42304aSGreg Roach     */
123a09ea7ccSGreg Roach    public function doesRecordNeedUpdate(/** @scrutinizer ignore-unused */ GedcomRecord $record, /** @scrutinizer ignore-unused */ array $params): bool
124ce42304aSGreg Roach    {
125ce42304aSGreg Roach        return false;
126ce42304aSGreg Roach    }
127ce42304aSGreg Roach
128ce42304aSGreg Roach    /**
129ce42304aSGreg Roach     * Show the changes we would make
130ce42304aSGreg Roach     *
131ce42304aSGreg Roach     * @param GedcomRecord         $record
132ce42304aSGreg Roach     * @param array<string,string> $params
133ce42304aSGreg Roach     *
134ce42304aSGreg Roach     * @return string
135ce42304aSGreg Roach     */
136a09ea7ccSGreg Roach    public function previewUpdate(GedcomRecord $record, /** @scrutinizer ignore-unused */ array $params): string
137ce42304aSGreg Roach    {
138ce42304aSGreg Roach        return $record->fullName();
139ce42304aSGreg Roach    }
140ce42304aSGreg Roach
141ce42304aSGreg Roach    /**
142ce42304aSGreg Roach     * Fix a record
143ce42304aSGreg Roach     *
144ce42304aSGreg Roach     * @param GedcomRecord         $record
145ce42304aSGreg Roach     * @param array<string,string> $params
146ce42304aSGreg Roach     *
147ce42304aSGreg Roach     * @return void
148ce42304aSGreg Roach     */
149a09ea7ccSGreg Roach    public function updateRecord(/** @scrutinizer ignore-unused */ GedcomRecord $record, /** @scrutinizer ignore-unused */ array $params): void
150ce42304aSGreg Roach    {
151ce42304aSGreg Roach    }
152ce42304aSGreg Roach
153ce42304aSGreg Roach    /**
154ce42304aSGreg Roach     * XREFs of family records that might need fixing.
155ce42304aSGreg Roach     *
156ce42304aSGreg Roach     * @param Tree                 $tree
157ce42304aSGreg Roach     * @param array<string,string> $params
158ce42304aSGreg Roach     *
15936779af1SGreg Roach     * @return Collection<int,string>|null
160ce42304aSGreg Roach     */
161be410956SGreg Roach    protected function familiesToFix(/** @scrutinizer ignore-unused */ Tree $tree, /** @scrutinizer ignore-unused */ array $params): ?Collection
162ce42304aSGreg Roach    {
163ce42304aSGreg Roach        return null;
164ce42304aSGreg Roach    }
165ce42304aSGreg Roach
166ce42304aSGreg Roach    /**
1677684867eSGreg Roach     * @param Tree                 $tree
1687684867eSGreg Roach     * @param array<string,string> $params
1697684867eSGreg Roach     *
1707684867eSGreg Roach     * @return Builder
1717684867eSGreg Roach     */
1727684867eSGreg Roach    protected function familiesToFixQuery(Tree $tree, array $params): Builder
1737684867eSGreg Roach    {
1747684867eSGreg Roach        $query = DB::table('families')
1755062b1caSJonathan Jaubart            ->where('f_file', '=', $tree->id());
1767684867eSGreg Roach
1777684867eSGreg Roach        if (isset($params['start'], $params['end'])) {
1785062b1caSJonathan Jaubart            $query->whereBetween('f_id', [$params['start'], $params['end']]);
1797684867eSGreg Roach        }
1807684867eSGreg Roach
1817684867eSGreg Roach        return $query;
1827684867eSGreg Roach    }
1837684867eSGreg Roach
1847684867eSGreg Roach    /**
185ce42304aSGreg Roach     * XREFs of individual records that might need fixing.
186ce42304aSGreg Roach     *
187ce42304aSGreg Roach     * @param Tree                 $tree
188ce42304aSGreg Roach     * @param array<string,string> $params
189ce42304aSGreg Roach     *
19036779af1SGreg Roach     * @return Collection<int,string>|null
191ce42304aSGreg Roach     */
192a09ea7ccSGreg Roach    protected function individualsToFix(/** @scrutinizer ignore-unused */ Tree $tree, /** @scrutinizer ignore-unused */ array $params): ?Collection
193ce42304aSGreg Roach    {
194ce42304aSGreg Roach        return null;
195ce42304aSGreg Roach    }
196ce42304aSGreg Roach
197ce42304aSGreg Roach    /**
1987684867eSGreg Roach     * @param Tree                 $tree
1997684867eSGreg Roach     * @param array<string,string> $params
2007684867eSGreg Roach     *
2017684867eSGreg Roach     * @return Builder
2027684867eSGreg Roach     */
2037684867eSGreg Roach    protected function individualsToFixQuery(Tree $tree, array $params): Builder
2047684867eSGreg Roach    {
2057684867eSGreg Roach        $query = DB::table('individuals')
2067684867eSGreg Roach            ->where('i_file', '=', $tree->id());
2077684867eSGreg Roach
2087684867eSGreg Roach        if (isset($params['start'], $params['end'])) {
2097684867eSGreg Roach            $query->whereBetween('i_id', [$params['start'], $params['end']]);
2107684867eSGreg Roach        }
2117684867eSGreg Roach
2127684867eSGreg Roach        return $query;
2137684867eSGreg Roach    }
2147684867eSGreg Roach
2157684867eSGreg Roach    /**
2167684867eSGreg Roach     * XREFs of location records that might need fixing.
2177684867eSGreg Roach     *
2187684867eSGreg Roach     * @param Tree                 $tree
2197684867eSGreg Roach     * @param array<string,string> $params
2207684867eSGreg Roach     *
22136779af1SGreg Roach     * @return Collection<int,string>|null
2227684867eSGreg Roach     */
223a09ea7ccSGreg Roach    protected function locationsToFix(/** @scrutinizer ignore-unused */ Tree $tree, /** @scrutinizer ignore-unused */ array $params): ?Collection
2247684867eSGreg Roach    {
2257684867eSGreg Roach        return null;
2267684867eSGreg Roach    }
2277684867eSGreg Roach
2287684867eSGreg Roach    /**
2297684867eSGreg Roach     * @param Tree                 $tree
2307684867eSGreg Roach     * @param array<string,string> $params
2317684867eSGreg Roach     *
2327684867eSGreg Roach     * @return Builder
2337684867eSGreg Roach     */
2347684867eSGreg Roach    protected function locationsToFixQuery(Tree $tree, array $params): Builder
2357684867eSGreg Roach    {
2367684867eSGreg Roach        $query = DB::table('other')
2377684867eSGreg Roach            ->where('o_type', '=', Location::RECORD_TYPE)
2387684867eSGreg Roach            ->where('o_file', '=', $tree->id());
2397684867eSGreg Roach
2407684867eSGreg Roach        if (isset($params['start'], $params['end'])) {
2417684867eSGreg Roach            $query->whereBetween('o_id', [$params['start'], $params['end']]);
2427684867eSGreg Roach        }
2437684867eSGreg Roach
2447684867eSGreg Roach        return $query;
2457684867eSGreg Roach    }
2467684867eSGreg Roach
2477684867eSGreg Roach    /**
248ce42304aSGreg Roach     * XREFs of media records that might need fixing.
249ce42304aSGreg Roach     *
250ce42304aSGreg Roach     * @param Tree                 $tree
251ce42304aSGreg Roach     * @param array<string,string> $params
252ce42304aSGreg Roach     *
25336779af1SGreg Roach     * @return Collection<int,string>|null
254ce42304aSGreg Roach     */
255a09ea7ccSGreg Roach    protected function mediaToFix(/** @scrutinizer ignore-unused */ Tree $tree, /** @scrutinizer ignore-unused */ array $params): ?Collection
256ce42304aSGreg Roach    {
257ce42304aSGreg Roach        return null;
258ce42304aSGreg Roach    }
259ce42304aSGreg Roach
260ce42304aSGreg Roach    /**
2617684867eSGreg Roach     * @param Tree                 $tree
2627684867eSGreg Roach     * @param array<string,string> $params
2637684867eSGreg Roach     *
2647684867eSGreg Roach     * @return Builder
2657684867eSGreg Roach     */
2667684867eSGreg Roach    protected function mediaToFixQuery(Tree $tree, array $params): Builder
2677684867eSGreg Roach    {
2687684867eSGreg Roach        $query = DB::table('media')
2697684867eSGreg Roach            ->where('m_file', '=', $tree->id());
2707684867eSGreg Roach
2717684867eSGreg Roach        if (isset($params['start'], $params['end'])) {
2727684867eSGreg Roach            $query->whereBetween('m_id', [$params['start'], $params['end']]);
2737684867eSGreg Roach        }
2747684867eSGreg Roach
2757684867eSGreg Roach        return $query;
2767684867eSGreg Roach    }
2777684867eSGreg Roach
2787684867eSGreg Roach    /**
279ce42304aSGreg Roach     * XREFs of note records that might need fixing.
280ce42304aSGreg Roach     *
281ce42304aSGreg Roach     * @param Tree                 $tree
282ce42304aSGreg Roach     * @param array<string,string> $params
283ce42304aSGreg Roach     *
28436779af1SGreg Roach     * @return Collection<int,string>|null
285ce42304aSGreg Roach     */
286a09ea7ccSGreg Roach    protected function notesToFix(/** @scrutinizer ignore-unused */ Tree $tree, /** @scrutinizer ignore-unused */ array $params): ?Collection
287ce42304aSGreg Roach    {
288ce42304aSGreg Roach        return null;
289ce42304aSGreg Roach    }
290ce42304aSGreg Roach
291ce42304aSGreg Roach    /**
2927684867eSGreg Roach     * @param Tree                 $tree
2937684867eSGreg Roach     * @param array<string,string> $params
2947684867eSGreg Roach     *
2957684867eSGreg Roach     * @return Builder
2967684867eSGreg Roach     */
2977684867eSGreg Roach    protected function notesToFixQuery(Tree $tree, array $params): Builder
2987684867eSGreg Roach    {
2997684867eSGreg Roach        $query = DB::table('other')
3007684867eSGreg Roach            ->where('o_type', '=', Note::RECORD_TYPE)
3017684867eSGreg Roach            ->where('o_file', '=', $tree->id());
3027684867eSGreg Roach
3037684867eSGreg Roach        if (isset($params['start'], $params['end'])) {
3047684867eSGreg Roach            $query->whereBetween('o_id', [$params['start'], $params['end']]);
3057684867eSGreg Roach        }
3067684867eSGreg Roach
3077684867eSGreg Roach        return $query;
3087684867eSGreg Roach    }
3097684867eSGreg Roach
3107684867eSGreg Roach    /**
311ce42304aSGreg Roach     * XREFs of repository records that might need fixing.
312ce42304aSGreg Roach     *
313ce42304aSGreg Roach     * @param Tree                 $tree
314ce42304aSGreg Roach     * @param array<string,string> $params
315ce42304aSGreg Roach     *
31636779af1SGreg Roach     * @return Collection<int,string>|null
317ce42304aSGreg Roach     */
318a09ea7ccSGreg Roach    protected function repositoriesToFix(/** @scrutinizer ignore-unused */ Tree $tree, /** @scrutinizer ignore-unused */ array $params): ?Collection
319ce42304aSGreg Roach    {
320ce42304aSGreg Roach        return null;
321ce42304aSGreg Roach    }
322ce42304aSGreg Roach
323ce42304aSGreg Roach    /**
3247684867eSGreg Roach     * @param Tree                 $tree
3257684867eSGreg Roach     * @param array<string,string> $params
3267684867eSGreg Roach     *
3277684867eSGreg Roach     * @return Builder
3287684867eSGreg Roach     */
3297684867eSGreg Roach    protected function repositoriesToFixQuery(Tree $tree, array $params): Builder
3307684867eSGreg Roach    {
3317684867eSGreg Roach        $query = DB::table('other')
3327684867eSGreg Roach            ->where('o_type', '=', Repository::RECORD_TYPE)
3337684867eSGreg Roach            ->where('o_file', '=', $tree->id());
3347684867eSGreg Roach
3357684867eSGreg Roach        if (isset($params['start'], $params['end'])) {
3367684867eSGreg Roach            $query->whereBetween('o_id', [$params['start'], $params['end']]);
3377684867eSGreg Roach        }
3387684867eSGreg Roach
3397684867eSGreg Roach        return $query;
3407684867eSGreg Roach    }
3417684867eSGreg Roach
3427684867eSGreg Roach    /**
343ce42304aSGreg Roach     * XREFs of source records that might need fixing.
344ce42304aSGreg Roach     *
345ce42304aSGreg Roach     * @param Tree                 $tree
346ce42304aSGreg Roach     * @param array<string,string> $params
347ce42304aSGreg Roach     *
34836779af1SGreg Roach     * @return Collection<int,string>|null
349ce42304aSGreg Roach     */
350a09ea7ccSGreg Roach    protected function sourcesToFix(/** @scrutinizer ignore-unused */ Tree $tree, /** @scrutinizer ignore-unused */ array $params): ?Collection
351ce42304aSGreg Roach    {
352ce42304aSGreg Roach        return null;
353ce42304aSGreg Roach    }
354ce42304aSGreg Roach
355ce42304aSGreg Roach    /**
3567684867eSGreg Roach     * @param Tree                 $tree
3577684867eSGreg Roach     * @param array<string,string> $params
3587684867eSGreg Roach     *
3597684867eSGreg Roach     * @return Builder
3607684867eSGreg Roach     */
3617684867eSGreg Roach    protected function sourcesToFixQuery(Tree $tree, array $params): Builder
3627684867eSGreg Roach    {
3637684867eSGreg Roach        $query = DB::table('sources')
3647684867eSGreg Roach            ->where('s_file', '=', $tree->id());
3657684867eSGreg Roach
3667684867eSGreg Roach        if (isset($params['start'], $params['end'])) {
3677684867eSGreg Roach            $query->whereBetween('s_id', [$params['start'], $params['end']]);
3687684867eSGreg Roach        }
3697684867eSGreg Roach
3707684867eSGreg Roach        return $query;
3717684867eSGreg Roach    }
3727684867eSGreg Roach
3737684867eSGreg Roach    /**
374ce42304aSGreg Roach     * XREFs of submitter records that might need fixing.
375ce42304aSGreg Roach     *
376ce42304aSGreg Roach     * @param Tree                 $tree
377ce42304aSGreg Roach     * @param array<string,string> $params
378ce42304aSGreg Roach     *
37936779af1SGreg Roach     * @return Collection<int,string>|null
380ce42304aSGreg Roach     */
381a09ea7ccSGreg Roach    protected function submittersToFix(/** @scrutinizer ignore-unused */ Tree $tree, /** @scrutinizer ignore-unused */ array $params): ?Collection
382ce42304aSGreg Roach    {
383ce42304aSGreg Roach        return null;
384ce42304aSGreg Roach    }
385ce42304aSGreg Roach
386ce42304aSGreg Roach    /**
3877684867eSGreg Roach     * @param Tree                 $tree
3887684867eSGreg Roach     * @param array<string,string> $params
3897684867eSGreg Roach     *
3907684867eSGreg Roach     * @return Builder
3917684867eSGreg Roach     */
3927684867eSGreg Roach    protected function submittersToFixQuery(Tree $tree, array $params): Builder
3937684867eSGreg Roach    {
3947684867eSGreg Roach        $query = DB::table('other')
3957684867eSGreg Roach            ->where('o_type', '=', Submitter::RECORD_TYPE)
3967684867eSGreg Roach            ->where('o_file', '=', $tree->id());
3977684867eSGreg Roach
3987684867eSGreg Roach        if (isset($params['start'], $params['end'])) {
3997684867eSGreg Roach            $query->whereBetween('o_id', [$params['start'], $params['end']]);
4007684867eSGreg Roach        }
4017684867eSGreg Roach
4027684867eSGreg Roach        return $query;
4037684867eSGreg Roach    }
4047684867eSGreg Roach
4057684867eSGreg Roach    /**
406ce42304aSGreg Roach     * Merge pending changes of a given type.  We need to check all pending records.
407ce42304aSGreg Roach     *
40836779af1SGreg Roach     * @param Collection<int,string> $records
409ce42304aSGreg Roach     * @param Tree                   $tree
410ce42304aSGreg Roach     * @param string                 $type
411ce42304aSGreg Roach     *
412*76d39c55SGreg Roach     * @return Collection<int,stdClass>
413ce42304aSGreg Roach     */
414ce42304aSGreg Roach    private function mergePendingRecords(Collection $records, Tree $tree, string $type): Collection
415ce42304aSGreg Roach    {
416ce42304aSGreg Roach        $pending = DB::table('change')
417ce42304aSGreg Roach            ->where('gedcom_id', '=', $tree->id())
418ce42304aSGreg Roach            ->where('status', '=', 'pending')
419ce42304aSGreg Roach            ->where(static function (Builder $query) use ($type): void {
420ce42304aSGreg Roach                $query
421ce42304aSGreg Roach                    ->where('old_gedcom', 'LIKE', '%@ ' . $type . '%')
422ce42304aSGreg Roach                    ->orWhere('new_gedcom', 'LIKE', '%@ ' . $type . '%');
423ce42304aSGreg Roach            })
424ce42304aSGreg Roach            ->pluck('xref');
425ce42304aSGreg Roach
426ce42304aSGreg Roach        return $records
427ce42304aSGreg Roach            ->concat($pending)
428f70bcff5SGreg Roach            ->map(static function (string $xref) use ($type): object {
429ce42304aSGreg Roach                return (object) ['xref' => $xref, 'type' => $type];
430ce42304aSGreg Roach            });
431ce42304aSGreg Roach    }
432ce42304aSGreg Roach}
433