xref: /webtrees/app/Factories/XrefFactory.php (revision 6f4ec3cadc983f0a7294108c634bef48846b4311)
1b4a2f885SGreg Roach<?php
2b4a2f885SGreg Roach
3b4a2f885SGreg Roach/**
4b4a2f885SGreg Roach * webtrees: online genealogy
5d11be702SGreg Roach * Copyright (C) 2023 webtrees development team
6b4a2f885SGreg Roach * This program is free software: you can redistribute it and/or modify
7b4a2f885SGreg Roach * it under the terms of the GNU General Public License as published by
8b4a2f885SGreg Roach * the Free Software Foundation, either version 3 of the License, or
9b4a2f885SGreg Roach * (at your option) any later version.
10b4a2f885SGreg Roach * This program is distributed in the hope that it will be useful,
11b4a2f885SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
12b4a2f885SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13b4a2f885SGreg Roach * GNU General Public License for more details.
14b4a2f885SGreg 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/>.
16b4a2f885SGreg Roach */
17b4a2f885SGreg Roach
18b4a2f885SGreg Roachdeclare(strict_types=1);
19b4a2f885SGreg Roach
20b4a2f885SGreg Roachnamespace Fisharebest\Webtrees\Factories;
21b4a2f885SGreg Roach
22b4a2f885SGreg Roachuse Fisharebest\Webtrees\Contracts\XrefFactoryInterface;
23*6f4ec3caSGreg Roachuse Fisharebest\Webtrees\DB;
24b4a2f885SGreg Roachuse Fisharebest\Webtrees\Site;
25b4a2f885SGreg Roach
26b4a2f885SGreg Roach/**
27b4a2f885SGreg Roach * Make an XREF.
28b4a2f885SGreg Roach */
29b4a2f885SGreg Roachclass XrefFactory implements XrefFactoryInterface
30b4a2f885SGreg Roach{
31b4a2f885SGreg Roach    /**
32b4a2f885SGreg Roach     * Create a new XREF.
33b4a2f885SGreg Roach     *
34b4a2f885SGreg Roach     * @param string $record_type
35b4a2f885SGreg Roach     *
36b4a2f885SGreg Roach     * @return string
37b4a2f885SGreg Roach     */
38b4a2f885SGreg Roach    public function make(string $record_type): string
39b4a2f885SGreg Roach    {
40b4a2f885SGreg Roach        return $this->generate('X', '');
41b4a2f885SGreg Roach    }
42b4a2f885SGreg Roach
43b4a2f885SGreg Roach    /**
44b4a2f885SGreg Roach     * @param string $prefix
45b4a2f885SGreg Roach     * @param string $suffix
46b4a2f885SGreg Roach     *
47b4a2f885SGreg Roach     * @return string
48b4a2f885SGreg Roach     */
49b4a2f885SGreg Roach    protected function generate(string $prefix, string $suffix): string
50b4a2f885SGreg Roach    {
51b4a2f885SGreg Roach        // Lock the row, so that only one new XREF may be generated at a time.
528a0b11f9SGreg Roach        $num = (int) DB::table('site_setting')
53b4a2f885SGreg Roach            ->where('setting_name', '=', 'next_xref')
54b4a2f885SGreg Roach            ->lockForUpdate()
558a0b11f9SGreg Roach            ->value('setting_value');
56b4a2f885SGreg Roach
57b4a2f885SGreg Roach        $increment = 1.0;
5813598780SGreg Roach
59b4a2f885SGreg Roach        do {
6013598780SGreg Roach            $num += (int) $increment;
61b4a2f885SGreg Roach
62b4a2f885SGreg Roach            // This exponential increment allows us to scan over large blocks of
63b4a2f885SGreg Roach            // existing data in a reasonable time.
64b4a2f885SGreg Roach            $increment *= 1.01;
65b4a2f885SGreg Roach
66b4a2f885SGreg Roach            $xref = $prefix . $num . $suffix;
67b4a2f885SGreg Roach
68b4a2f885SGreg Roach            // Records may already exist with this sequence number.
69b4a2f885SGreg Roach            $already_used =
70b4a2f885SGreg Roach                DB::table('individuals')->where('i_id', '=', $xref)->exists() ||
71b4a2f885SGreg Roach                DB::table('families')->where('f_id', '=', $xref)->exists() ||
72b4a2f885SGreg Roach                DB::table('sources')->where('s_id', '=', $xref)->exists() ||
73b4a2f885SGreg Roach                DB::table('media')->where('m_id', '=', $xref)->exists() ||
74b4a2f885SGreg Roach                DB::table('other')->where('o_id', '=', $xref)->exists() ||
75b4a2f885SGreg Roach                DB::table('change')->where('xref', '=', $xref)->exists();
76b4a2f885SGreg Roach        } while ($already_used);
77b4a2f885SGreg Roach
78b4a2f885SGreg Roach        Site::setPreference('next_xref', (string) $num);
79b4a2f885SGreg Roach
80b4a2f885SGreg Roach        return $xref;
81b4a2f885SGreg Roach    }
82b4a2f885SGreg Roach}
83