Passed
Push — master ( c9a927...3e5f5a )
by Greg
05:29
created

FamilyFactory   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 84
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 24
c 1
b 0
f 0
dl 0
loc 84
rs 10
wmc 7

4 Methods

Rating   Name   Duplication   Size   Complexity  
A mapper() 0 7 1
A gedcom() 0 6 1
A new() 0 3 1
A make() 0 21 4
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
18
declare(strict_types=1);
19
20
namespace Fisharebest\Webtrees\Factories;
21
22
use Closure;
23
use Fisharebest\Webtrees\Contracts\FamilyFactoryInterface;
24
use Fisharebest\Webtrees\Factory;
25
use Fisharebest\Webtrees\Family;
26
use Fisharebest\Webtrees\Gedcom;
27
use Fisharebest\Webtrees\Tree;
28
use Illuminate\Database\Capsule\Manager as DB;
29
use stdClass;
30
31
use function assert;
32
use function preg_match;
33
34
/**
35
 * Make a Family object.
36
 */
37
class FamilyFactory extends AbstractGedcomRecordFactory implements FamilyFactoryInterface
38
{
39
    private const TYPE_CHECK_REGEX = '/^0 @[^@]+@ ' . Family::RECORD_TYPE . '/';
40
41
    /**
42
     * Create a family.
43
     *
44
     * @param string      $xref
45
     * @param Tree        $tree
46
     * @param string|null $gedcom
47
     *
48
     * @return Family|null
49
     */
50
    public function make(string $xref, Tree $tree, string $gedcom = null): ?Family
51
    {
52
        return $this->cache->remember(__CLASS__ . $xref . '@' . $tree->id(), function () use ($xref, $tree, $gedcom) {
53
            $gedcom  = $gedcom ?? $this->gedcom($xref, $tree);
54
            $pending = $this->pendingChanges($tree)->get($xref);
55
56
            if ($gedcom === null && ($pending === null || !preg_match(self::TYPE_CHECK_REGEX, $pending))) {
57
                return null;
58
            }
59
60
            $xref = $this->extractXref($gedcom ?? $pending, $xref);
61
62
            // Preload all the family members using a single database query.
63
            preg_match_all('/\n1 (?:HUSB|WIFE|CHIL) @(' . Gedcom::REGEX_XREF . ')@/', $gedcom . "\n" . $pending, $match);
64
            DB::table('individuals')
65
                ->where('i_file', '=', $tree->id())
66
                ->whereIn('i_id', $match[1])
67
                ->get()
68
                ->map(Factory::individual()->mapper($tree));
69
70
            return new Family($xref, $gedcom ?? '', $pending, $tree);
71
        });
72
    }
73
74
    /**
75
     * Create a Family object from a row in the database.
76
     *
77
     * @param Tree $tree
78
     *
79
     * @return Closure
80
     */
81
    public function mapper(Tree $tree): Closure
82
    {
83
        return function (stdClass $row) use ($tree): Family {
84
            $family = $this->make($row->f_id, $tree, $row->f_gedcom);
85
            assert($family instanceof Family);
86
87
            return $family;
88
        };
89
    }
90
91
    /**
92
     * Create a Family object from raw GEDCOM data.
93
     *
94
     * @param string      $xref
95
     * @param string      $gedcom  an empty string for new/pending records
96
     * @param string|null $pending null for a record with no pending edits,
97
     *                             empty string for records with pending deletions
98
     * @param Tree        $tree
99
     *
100
     * @return Family
101
     */
102
    public function new(string $xref, string $gedcom, ?string $pending, Tree $tree): Family
103
    {
104
        return new Family($xref, $gedcom, $pending, $tree);
105
    }
106
107
    /**
108
     * Fetch GEDCOM data from the database.
109
     *
110
     * @param string $xref
111
     * @param Tree   $tree
112
     *
113
     * @return string|null
114
     */
115
    protected function gedcom(string $xref, Tree $tree): ?string
116
    {
117
        return DB::table('families')
118
            ->where('f_id', '=', $xref)
119
            ->where('f_file', '=', $tree->id())
120
            ->value('f_gedcom');
121
    }
122
}
123