xref: /webtrees/app/Statistics/Repository/GedcomRepository.php (revision afa67798854828b1edc33dd077960ec2b18e6140)
1<?php
2
3/**
4 * webtrees: online genealogy
5 * Copyright (C) 2021 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 <https://www.gnu.org/licenses/>.
16 */
17
18declare(strict_types=1);
19
20namespace Fisharebest\Webtrees\Statistics\Repository;
21
22use Exception;
23use Fisharebest\Webtrees\Carbon;
24use Fisharebest\Webtrees\Fact;
25use Fisharebest\Webtrees\Registry;
26use Fisharebest\Webtrees\Header;
27use Fisharebest\Webtrees\Statistics\Repository\Interfaces\GedcomRepositoryInterface;
28use Fisharebest\Webtrees\Tree;
29use Illuminate\Database\Capsule\Manager as DB;
30
31use function str_contains;
32
33/**
34 * A repository providing methods for GEDCOM related statistics.
35 */
36class GedcomRepository implements GedcomRepositoryInterface
37{
38    /**
39     * @var Tree
40     */
41    private $tree;
42
43    /**
44     * Constructor.
45     *
46     * @param Tree $tree
47     */
48    public function __construct(Tree $tree)
49    {
50        $this->tree = $tree;
51    }
52
53    /**
54     * Get information from the GEDCOM's HEAD record.
55     *
56     * @return array<string>
57     */
58    private function gedcomHead(): array
59    {
60        $title   = '';
61        $version = '';
62        $source  = '';
63
64        $head = Registry::headerFactory()->make('HEAD', $this->tree);
65
66        if ($head instanceof Header) {
67            $sour = $head->facts(['SOUR'])->first();
68
69            if ($sour instanceof Fact) {
70                $source  = $sour->value();
71                $title   = $sour->attribute('NAME');
72                $version = $sour->attribute('VERS');
73            }
74        }
75
76        return [
77            $title,
78            $version,
79            $source,
80        ];
81    }
82
83    /**
84     * @return string
85     */
86    public function gedcomFilename(): string
87    {
88        return $this->tree->name();
89    }
90
91    /**
92     * @return int
93     */
94    public function gedcomId(): int
95    {
96        return $this->tree->id();
97    }
98
99    /**
100     * @return string
101     */
102    public function gedcomTitle(): string
103    {
104        return e($this->tree->title());
105    }
106
107    /**
108     * @return string
109     */
110    public function gedcomCreatedSoftware(): string
111    {
112        return $this->gedcomHead()[0];
113    }
114
115    /**
116     * @return string
117     */
118    public function gedcomCreatedVersion(): string
119    {
120        $head = $this->gedcomHead();
121
122        // Fix broken version string in Family Tree Maker
123        if (str_contains($head[1], 'Family Tree Maker ')) {
124            $p       = strpos($head[1], '(') + 1;
125            $p2      = strpos($head[1], ')');
126            $head[1] = substr($head[1], $p, $p2 - $p);
127        }
128
129        // Fix EasyTree version
130        if ($head[2] === 'EasyTree') {
131            $head[1] = substr($head[1], 1);
132        }
133
134        return $head[1];
135    }
136
137    /**
138     * @return string
139     * @throws Exception
140     */
141    public function gedcomDate(): string
142    {
143        $head = Registry::headerFactory()->make('HEAD', $this->tree);
144
145        if ($head instanceof Header) {
146            $fact = $head->facts(['DATE'])->first();
147
148            if ($fact instanceof Fact) {
149                return Carbon::make($fact->value())->local()->isoFormat('LL');
150            }
151        }
152
153        return '';
154    }
155
156    /**
157     * @return string
158     */
159    public function gedcomUpdated(): string
160    {
161        $row = DB::table('change')
162            ->where('gedcom_id', '=', $this->tree->id())
163            ->where('status', '=', 'accepted')
164            ->orderBy('change_id', 'DESC')
165            ->select(['change_time'])
166            ->first();
167
168        if ($row === null) {
169            return $this->gedcomDate();
170        }
171
172        return Carbon::make($row->change_time)->local()->isoFormat('LL');
173    }
174
175    /**
176     * @return string
177     */
178    public function gedcomRootId(): string
179    {
180        return $this->tree->getPreference('PEDIGREE_ROOT_ID');
181    }
182}
183