1<?php 2/** 3 * webtrees: online genealogy 4 * Copyright (C) 2018 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 stdClass; 21 22/** 23 * Class Location 24 * 25 * @package Fisharebest\Webtrees 26 */ 27class Location 28{ 29 30 /** 31 * @var stdClass $record 32 */ 33 protected $record; 34 35 /** 36 * Location constructor. 37 * 38 * @param string $gedcomName 39 * @param array $record 40 */ 41 public function __construct($gedcomName, $record = []) 42 { 43 $tmp = $this->getRecordFromName($gedcomName); 44 if ($tmp !== null) { 45 $this->record = $tmp; 46 } elseif (!empty($record)) { 47 $this->record = (object) $record; 48 } else { 49 $this->record = (object) [ 50 'fqpn' => '', 51 'pl_id' => 0, 52 'pl_parent_id' => 0, 53 'pl_level' => null, 54 'pl_place' => '', 55 'pl_long' => null, 56 'pl_lati' => null, 57 'pl_zoom' => null, 58 'pl_icon' => null, 59 ]; 60 } 61 } 62 63 /** 64 * @return bool 65 */ 66 public function knownLatLon(): bool 67 { 68 return ($this->record->pl_lati && $this->record->pl_long); 69 } 70 71 /** 72 * @param string $format 73 * 74 * @return string|float 75 */ 76 public function getLat($format = 'signed') 77 { 78 switch ($format) { 79 case 'signed': 80 return $this->record->pl_lati ? 81 (float) strtr($this->record->pl_lati, [ 82 'N' => '', 83 'S' => '-', 84 ',' => '.', 85 ]) : $this->record->pl_lati; 86 default: 87 return $this->record->pl_lati; 88 } 89 } 90 91 /** 92 * @param string $format 93 * 94 * @return string|float 95 */ 96 public function getLon($format = 'signed') 97 { 98 switch ($format) { 99 case 'signed': 100 return $this->record->pl_long ? 101 (float) strtr($this->record->pl_long, [ 102 'E' => '', 103 'W' => '-', 104 ',' => '.', 105 ]) : $this->record->pl_long; 106 default: 107 return $this->record->pl_long; 108 } 109 } 110 111 /** 112 * @return array 113 */ 114 public function getLatLonJSArray(): array 115 { 116 return [ 117 $this->getLat('signed'), 118 $this->getLon('signed'), 119 ]; 120 } 121 122 /** 123 * GeoJSON requires the parameters to be in the order longitude, latitude 124 * 125 * @return array 126 */ 127 public function getGeoJsonCoords(): array 128 { 129 return [ 130 $this->getLon('signed'), 131 $this->getLat('signed'), 132 ]; 133 } 134 135 /** 136 * @return string 137 */ 138 public function getId(): string 139 { 140 return $this->record->pl_id; 141 } 142 143 /** 144 * @return string 145 */ 146 public function getLevel(): string 147 { 148 return $this->record->pl_level; 149 } 150 151 /** 152 * @return bool 153 */ 154 public function isValid(): bool 155 { 156 return $this->record->pl_id !== 0; 157 } 158 159 /** 160 * @return string 161 */ 162 public function getPlace(): string 163 { 164 return $this->record->pl_place; 165 } 166 167 /** 168 * @return string|null 169 */ 170 public function getZoom() 171 { 172 return $this->record->pl_zoom; 173 } 174 175 /** 176 * @return string|null 177 */ 178 public function getIcon() 179 { 180 return $this->record->pl_icon; 181 } 182 183 /** 184 * @return stdClass 185 */ 186 public function getRecord(): stdClass 187 { 188 return $this->record; 189 } 190 191 /** 192 * @return int 193 */ 194 public function add() 195 { 196 $this->record->pl_id = Database::prepare("SELECT IFNULL(MAX(pl_id)+1, 1) FROM `##placelocation`") 197 ->execute() 198 ->fetchOne(); 199 200 Database::prepare( 201 "INSERT INTO `##placelocation` (pl_id, pl_parent_id, pl_level, pl_place, pl_long, pl_lati, pl_zoom, pl_icon) VALUES(:id, :parent_id, :level, :place, :long, :lati, :zoom, :icon)" 202 )->execute([ 203 'id' => $this->record->pl_id, 204 'parent_id' => $this->record->pl_parent_id, 205 'level' => $this->record->pl_level, 206 'place' => $this->record->pl_place, 207 'long' => $this->record->pl_long ?? null, 208 'lati' => $this->record->pl_lati ?? null, 209 'zoom' => $this->record->pl_zoom ?? null, 210 'icon' => $this->record->pl_icon ?? null, 211 ]); 212 213 return $this->record->pl_id; 214 } 215 216 /** 217 * @param stdClass $new_data 218 */ 219 public function update(stdClass $new_data) 220 { 221 Database::prepare( 222 "UPDATE `##placelocation` SET pl_lati=:lati, pl_long=:long, pl_zoom=:zoom, pl_icon=:icon WHERE pl_id=:id" 223 )->execute([ 224 'lati' => $new_data->pl_lati ?? $this->record->pl_lati, 225 'long' => $new_data->pl_long ?? $this->record->pl_long, 226 'zoom' => $new_data->pl_zoom ?? $this->record->pl_zoom, 227 'icon' => $new_data->pl_icon ?? $this->record->pl_icon, 228 'id' => $this->record->pl_id, 229 ]); 230 } 231 232 /** 233 * @param string $gedcomName 234 * 235 * @return null|stdClass 236 */ 237 private function getRecordFromName(string $gedcomName) 238 { 239 return Database::prepare(" 240 SELECT 241 CONCAT_WS(:separator, t1.pl_place, t2.pl_place, t3.pl_place, t4.pl_place, t5.pl_place, t6.pl_place, t7.pl_place, t8.pl_place) AS fqpn, 242 t1.pl_level, t1.pl_place, t1.pl_id, t1.pl_parent_id, t1.pl_lati, t1.pl_long, t1.pl_zoom, t1.pl_icon 243 FROM `##placelocation` AS t1 244 LEFT JOIN `##placelocation` AS t2 ON t1.pl_parent_id = t2.pl_id 245 LEFT JOIN `##placelocation` AS t3 ON t2.pl_parent_id = t3.pl_id 246 LEFT JOIN `##placelocation` AS t4 ON t3.pl_parent_id = t4.pl_id 247 LEFT JOIN `##placelocation` AS t5 ON t4.pl_parent_id = t5.pl_id 248 LEFT JOIN `##placelocation` AS t6 ON t5.pl_parent_id = t6.pl_id 249 LEFT JOIN `##placelocation` AS t7 ON t6.pl_parent_id = t7.pl_id 250 LEFT JOIN `##placelocation` AS t8 ON t7.pl_parent_id = t8.pl_id 251 HAVING fqpn = :gedcomName; 252 ")->execute([ 253 'separator' => Place::GEDCOM_SEPARATOR, 254 'gedcomName' => $gedcomName, 255 ])->fetchOneRow(); 256 } 257} 258