xref: /webtrees/app/Location.php (revision c88a5019dff7bc89d58039dfe7af14f8446e6384)
1<?php
2/**
3 * webtrees: online genealogy
4 * Copyright (C) 2019 webtrees development team
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16declare(strict_types=1);
17
18namespace Fisharebest\Webtrees;
19
20use Illuminate\Database\Capsule\Manager as DB;
21use Illuminate\Database\Query\JoinClause;
22use stdClass;
23
24/**
25 * Class Location
26 *
27 * @package Fisharebest\Webtrees
28 */
29class Location
30{
31
32    /**
33     * @var stdClass $record
34     */
35    protected $record;
36
37    /**
38     * Location constructor.
39     *
40     * @param string $gedcomName
41     * @param array  $record
42     */
43    public function __construct($gedcomName, $record = [])
44    {
45        $tmp = $this->getRecordFromName($gedcomName);
46        if ($tmp !== null) {
47            $this->record = $tmp;
48        } elseif (!empty($record)) {
49            $this->record = (object) $record;
50        } else {
51            $this->record = (object) [
52                'fqpn'         => '',
53                'pl_id'        => 0,
54                'pl_parent_id' => 0,
55                'pl_level'     => null,
56                'pl_place'     => '',
57                'pl_long'      => null,
58                'pl_lati'      => null,
59                'pl_zoom'      => null,
60                'pl_icon'      => null,
61            ];
62        }
63    }
64
65    /**
66     * @return bool
67     */
68    public function knownLatLon(): bool
69    {
70        return ($this->record->pl_lati && $this->record->pl_long);
71    }
72
73    /**
74     * @param string $format
75     *
76     * @return string|float
77     */
78    public function getLat($format = 'signed')
79    {
80        switch ($format) {
81            case 'signed':
82                return $this->record->pl_lati ?
83                    (float) strtr($this->record->pl_lati, [
84                        'N' => '',
85                        'S' => '-',
86                        ',' => '.',
87                    ]) : $this->record->pl_lati;
88            default:
89                return $this->record->pl_lati;
90        }
91    }
92
93    /**
94     * @param string $format
95     *
96     * @return string|float
97     */
98    public function getLon($format = 'signed')
99    {
100        switch ($format) {
101            case 'signed':
102                return $this->record->pl_long ?
103                    (float) strtr($this->record->pl_long, [
104                        'E' => '',
105                        'W' => '-',
106                        ',' => '.',
107                    ]) : $this->record->pl_long;
108            default:
109                return $this->record->pl_long;
110        }
111    }
112
113    /**
114     * @return array
115     */
116    public function getLatLonJSArray(): array
117    {
118        return [
119            $this->getLat('signed'),
120            $this->getLon('signed'),
121        ];
122    }
123
124    /**
125     * GeoJSON requires the parameters to be in the order longitude, latitude
126     *
127     * @return array
128     */
129    public function getGeoJsonCoords(): array
130    {
131        return [
132            $this->getLon('signed'),
133            $this->getLat('signed'),
134        ];
135    }
136
137    /**
138     * @return int
139     */
140    public function getId(): int
141    {
142        return $this->record->pl_id;
143    }
144
145    /**
146     * @return int
147     */
148    public function getLevel(): int
149    {
150        return $this->record->pl_level;
151    }
152
153    /**
154     * @return bool
155     */
156    public function isValid(): bool
157    {
158        return $this->record->pl_id !== 0;
159    }
160
161    /**
162     * @return string
163     */
164    public function getPlace(): string
165    {
166        return $this->record->pl_place;
167    }
168
169    /**
170     * @return string|null
171     */
172    public function getZoom()
173    {
174        return $this->record->pl_zoom;
175    }
176
177    /**
178     * @return string|null
179     */
180    public function getIcon()
181    {
182        return $this->record->pl_icon;
183    }
184
185    /**
186     * @return stdClass
187     */
188    public function getRecord(): stdClass
189    {
190        return $this->record;
191    }
192
193    /**
194     * @return int
195     */
196    public function add(): int
197    {
198        $this->record->pl_id = 1 + (int) DB::table('placelocation')->max('pl_id');
199
200        DB::table('placelocation')->insert([
201            'pl_id'        => $this->record->pl_id,
202            'pl_parent_id' => $this->record->pl_parent_id,
203            'pl_level'     => $this->record->pl_level,
204            'pl_place'     => $this->record->pl_place,
205            'pl_long'      => $this->record->pl_long ?? null,
206            'pl_lati'      => $this->record->pl_lati ?? null,
207            'pl_zoom'      => $this->record->pl_zoom ?? null,
208            'pl_icon'      => $this->record->pl_icon ?? null,
209        ]);
210
211        return $this->record->pl_id;
212    }
213
214    /**
215     * @param stdClass $new_data
216     *
217     * @return void
218     */
219    public function update(stdClass $new_data)
220    {
221        DB::table('placelocation')
222            ->where('pl_id', '=', $this->record->pl_id)
223            ->update([
224                'pl_lati' => $new_data->pl_lati ?? $this->record->pl_lati,
225                'pl_long' => $new_data->pl_long ?? $this->record->pl_long,
226                'pl_zoom' => $new_data->pl_zoom ?? $this->record->pl_zoom,
227                'pl_icon' => $new_data->pl_icon ?? $this->record->pl_icon,
228            ]);
229    }
230
231    /**
232     * @param string $gedcomName
233     *
234     * @return null|stdClass
235     */
236    private function getRecordFromName(string $gedcomName)
237    {
238        $places = explode(Place::GEDCOM_SEPARATOR, $gedcomName);
239
240        $query = DB::table('placelocation AS pl0')
241            ->where('pl0.pl_place', '=', $places[0])
242            ->select(['pl0.*']);
243
244        array_shift($places);
245
246        foreach ($places as $n => $place) {
247            $query->join('placelocation AS pl' . ($n + 1), function (JoinClause $join) use ($n, $place): void {
248                $join
249                    ->on('pl' . ($n + 1) . '.pl_id', '=', 'pl' . $n . '.pl_parent_id')
250                    ->where('pl' . ($n + 1) . '.pl_place', '=', $place);
251            });
252        };
253
254        return $query->first();
255    }
256}
257