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