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(Gedcom::PLACE_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