Passed
Branch feature/2.0 (d2af8f)
by Jonathan
13:07
created

SosaRecordsService   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 125
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 59
c 1
b 0
f 0
dl 0
loc 125
rs 10
wmc 9

5 Methods

Rating   Name   Duplication   Size   Complexity  
A deleteAll() 0 6 1
A deleteAncestorsFrom() 0 10 1
A generation() 0 3 1
A getSosaNumbers() 0 8 1
A insertOrUpdate() 0 48 5
1
<?php
2
3
/**
4
 * webtrees-lib: MyArtJaub library for webtrees
5
 *
6
 * @package MyArtJaub\Webtrees
7
 * @subpackage Sosa
8
 * @author Jonathan Jaubart <[email protected]>
9
 * @copyright Copyright (c) 2009-2020, Jonathan Jaubart
10
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3
11
 */
12
13
declare(strict_types=1);
14
15
namespace MyArtJaub\Webtrees\Module\Sosa\Services;
16
17
use Fisharebest\Webtrees\Individual;
18
use Fisharebest\Webtrees\Tree;
19
use Fisharebest\Webtrees\User;
20
use Illuminate\Database\Capsule\Manager as DB;
21
use Illuminate\Support\Collection;
22
23
/**
24
 * Service for CRUD operations on Sosa records
25
 *
26
 */
27
class SosaRecordsService
28
{
29
    /**
30
     * Maximum number of generation the database is able to hold.
31
     * @var int MAX_DB_GENERATIONS
32
     */
33
    public const MAX_DB_GENERATIONS = 64;
34
    
35
    /**
36
     * Calculate the generation of a sosa
37
     * Sosa 1 is of generation 1.
38
     *
39
     * @param int $sosa
40
     * @return int
41
     */
42
    public function generation(int $sosa) : int
43
    {
44
        return (int) log($sosa, 2) + 1;
45
    }
46
    
47
    /**
48
     * Returns all Sosa numbers associated to an Individual
49
     * 
50
     * @param Tree $tree
51
     * @param User $user
52
     * @param Individual $indi
53
     * @return Collection
54
     */
55
    public function getSosaNumbers(Tree $tree, User $user, Individual $indi) : Collection
56
    {
57
        return DB::table('maj_sosa')
58
            ->select(['majs_sosa', 'majs_gen'])
59
            ->where('majs_gedcom_id', '=', $tree->id())
60
            ->where('majs_user_id', '=', $user->id())
61
            ->where('majs_i_id', '=', $indi->xref())
62
            ->get()->pluck('majs_gen', 'majs_sosa');
63
    }
64
    
65
    /**
66
     * Remove all Sosa entries related to the gedcom file and user
67
     * 
68
     * @param Tree $tree
69
     * @param User $user
70
     */
71
    public function deleteAll(Tree $tree, User $user) : void
72
    {
73
        DB::table('maj_sosa')
74
            ->where('majs_gedcom_id', '=', $tree->id())
75
            ->where('majs_user_id', '=', $user->id())
76
            ->delete();
77
    }
78
    
79
    /**
80
     * 
81
     * @param Tree $tree
82
     * @param User $user
83
     * @param int $sosa
84
     */
85
    public function deleteAncestorsFrom(Tree $tree, User $user, int $sosa) : void
86
    {
87
        DB::table('maj_sosa')
88
            ->where('majs_gedcom_id', '=', $tree->id())
89
            ->where('majs_user_id', '=', $user->id())
90
            ->where('majs_sosa', '>=', $sosa)
91
            ->whereRaw(
92
                'FLOOR(majs_sosa / (POW(2, (majs_gen - :gen)))) = :sosa',
93
                ['gen' => $this->generation($sosa), 'sosa' => $sosa])
94
            ->delete();
95
    }
96
    
97
    /**
98
     * Insert (or update if already existing) a list of Sosa individuals
99
     * 
100
     * @param Tree $tree
101
     * @param User $user
102
     * @param array $sosa_records
103
     */
104
    public function insertOrUpdate(Tree $tree, User $user, array $sosa_records) {
105
        $mass_update = DB::connection()->getDriverName() === 'mysql';
106
        
107
        $bindings_placeholders = $bindings_values = [];
108
        foreach($sosa_records as $i => $row) {
109
            $gen = $this->generation($row['sosa']);
110
            if($gen <=  self::MAX_DB_GENERATIONS) {
111
                if($mass_update) {
112
                    $bindings_placeholders[] = '(:tree_id'.$i.', :user_id'.$i.', :sosa'.$i.','.
113
                        ' :indi_id'.$i.', :gen'.$i.', :byear'.$i.', :byearest'.$i.', :dyear'.$i.', :dyearest'.$i.')';
114
                    $bindings_values = array_merge(
115
                        $bindings_values,
116
                        [
117
                            'tree_id'.$i => $tree->id(),
118
                            'user_id'.$i => $user->id(),
119
                            'sosa'.$i => $row['sosa'],
120
                            'indi_id'.$i => $row['indi'],
121
                            'gen'.$i => $gen,
122
                            'byear'.$i => $row['birth_year'],
123
                            'byearest'.$i => $row['birth_year_est'],
124
                            'dyear'.$i => $row['death_year'],
125
                            'dyearest'.$i => $row['death_year_est']
126
                        ]);
127
                } else {
128
                    DB::table('maj_sosa')->updateOrInsert(
129
                        [ 'majs_gedcom_id' => $tree->id(), 'majs_user_id' => $user->id(), 'majs_sosa' => $row['sosa']],
130
                        [
131
                            'majs_i_id' => $row['indi'],
132
                            'majs_gen' => $gen,
133
                            'majs_birth_year' => $row['birth_year'],
134
                            'majs_birth_year_est' => $row['birth_year_est'],
135
                            'majs_death_year' => $row['death_year'],
136
                            'majs_death_year_est' => $row['death_year_est']
137
                        ]);
138
                }
139
            }
140
        }
141
        
142
        if($mass_update) {
143
            DB::connection()->statement(
144
                'INSERT INTO `' . DB::connection()->getTablePrefix() . 'maj_sosa`' .
145
                ' (majs_gedcom_id, majs_user_id, majs_sosa,' .
146
                '   majs_i_id, majs_gen, majs_birth_year, majs_birth_year_est, majs_death_year, majs_death_year_est)' .
147
                ' VALUES ' . implode(',', $bindings_placeholders) .
148
                ' ON DUPLICATE KEY UPDATE majs_i_id = VALUES(majs_i_id), majs_gen = VALUES(majs_gen),' .
149
                '   majs_birth_year = VALUES(majs_birth_year), majs_birth_year_est = VALUES(majs_birth_year_est),' . 
150
                '   majs_death_year = VALUES(majs_death_year), majs_death_year_est = VALUES(majs_death_year_est)',
151
                $bindings_values);
152
        }
153
    }
154
    
155
}
156