1a25f0a04SGreg Roach<?php 2dd04c183SGreg Roachnamespace Fisharebest\Webtrees; 3a25f0a04SGreg Roach 4a25f0a04SGreg Roach/** 5a25f0a04SGreg Roach * webtrees: online genealogy 6a25f0a04SGreg Roach * Copyright (C) 2015 webtrees development team 7a25f0a04SGreg Roach * This program is free software: you can redistribute it and/or modify 8a25f0a04SGreg Roach * it under the terms of the GNU General Public License as published by 9a25f0a04SGreg Roach * the Free Software Foundation, either version 3 of the License, or 10a25f0a04SGreg Roach * (at your option) any later version. 11a25f0a04SGreg Roach * This program is distributed in the hope that it will be useful, 12a25f0a04SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 13a25f0a04SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14a25f0a04SGreg Roach * GNU General Public License for more details. 15a25f0a04SGreg Roach * You should have received a copy of the GNU General Public License 16a25f0a04SGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>. 17a25f0a04SGreg Roach */ 18a25f0a04SGreg Roach 19a25f0a04SGreg Roach/** 20a25f0a04SGreg Roach * Class Place - Gedcom Place functionality. 21a25f0a04SGreg Roach */ 22a25f0a04SGreg Roachclass Place { 23a25f0a04SGreg Roach const GEDCOM_SEPARATOR = ', '; 2484caa210SGreg Roach 2584caa210SGreg Roach /** 2684caa210SGreg Roach * @var string[] e.g. array('Westminster', 'London', 'England') 2784caa210SGreg Roach */ 2884caa210SGreg Roach private $gedcom_place; 2984caa210SGreg Roach 3084caa210SGreg Roach /** 3184caa210SGreg Roach * @var Tree We may have the same place name in different trees 3284caa210SGreg Roach */ 3384caa210SGreg Roach private $tree; 34a25f0a04SGreg Roach 35a25f0a04SGreg Roach /** 36a25f0a04SGreg Roach * @param string $gedcom_place 3784caa210SGreg Roach * @param Tree $tree 38a25f0a04SGreg Roach */ 39*2769ecbeSGreg Roach public function __construct($gedcom_place, Tree $tree) { 40a25f0a04SGreg Roach if ($gedcom_place) { 41a25f0a04SGreg Roach $this->gedcom_place = explode(self::GEDCOM_SEPARATOR, $gedcom_place); 42a25f0a04SGreg Roach } else { 43a25f0a04SGreg Roach // Empty => "Top level" 44a25f0a04SGreg Roach $this->gedcom_place = array(); 45a25f0a04SGreg Roach } 4664b16745SGreg Roach $this->tree = $tree; 47a25f0a04SGreg Roach } 48a25f0a04SGreg Roach 49a25f0a04SGreg Roach /** 50a25f0a04SGreg Roach * @return integer 51a25f0a04SGreg Roach */ 52a25f0a04SGreg Roach public function getPlaceId() { 53a25f0a04SGreg Roach $place_id = 0; 54a25f0a04SGreg Roach foreach (array_reverse($this->gedcom_place) as $place) { 55a25f0a04SGreg Roach $place_id = Database::prepare( 56a25f0a04SGreg Roach "SELECT SQL_CACHE p_id FROM `##places` WHERE p_parent_id = :parent_id AND p_place = :place AND p_file = :tree_id" 57a25f0a04SGreg Roach )->execute(array( 58a25f0a04SGreg Roach 'parent_id' => $place_id, 59a25f0a04SGreg Roach 'place' => $place, 6064b16745SGreg Roach 'tree_id' => $this->tree->getTreeId(), 61a25f0a04SGreg Roach ))->fetchOne(); 62a25f0a04SGreg Roach } 63a25f0a04SGreg Roach 64a25f0a04SGreg Roach return $place_id; 65a25f0a04SGreg Roach } 66a25f0a04SGreg Roach 67a25f0a04SGreg Roach /** 68a25f0a04SGreg Roach * @return Place 69a25f0a04SGreg Roach */ 70a25f0a04SGreg Roach public function getParentPlace() { 7184caa210SGreg Roach return new Place(implode(self::GEDCOM_SEPARATOR, array_slice($this->gedcom_place, 1)), $this->tree); 72a25f0a04SGreg Roach } 73a25f0a04SGreg Roach 74a25f0a04SGreg Roach /** 75a25f0a04SGreg Roach * @return Place[] 76a25f0a04SGreg Roach */ 77a25f0a04SGreg Roach public function getChildPlaces() { 78a25f0a04SGreg Roach $children = array(); 79a25f0a04SGreg Roach if ($this->getPlaceId()) { 80a25f0a04SGreg Roach $parent_text = self::GEDCOM_SEPARATOR . $this->getGedcomName(); 81a25f0a04SGreg Roach } else { 82a25f0a04SGreg Roach $parent_text = ''; 83a25f0a04SGreg Roach } 84a25f0a04SGreg Roach 85a25f0a04SGreg Roach $rows = Database::prepare( 86a25f0a04SGreg Roach "SELECT SQL_CACHE p_place FROM `##places`" . 87a25f0a04SGreg Roach " WHERE p_parent_id = :parent_id AND p_file = :tree_id" . 88a25f0a04SGreg Roach " ORDER BY p_place COLLATE :collation" 89a25f0a04SGreg Roach )->execute(array( 90a25f0a04SGreg Roach 'parent_id' => $this->getPlaceId(), 9164b16745SGreg Roach 'tree_id' => $this->tree->getTreeId(), 92a25f0a04SGreg Roach 'collation' => I18N::$collation, 93a25f0a04SGreg Roach ))->fetchOneColumn(); 94a25f0a04SGreg Roach foreach ($rows as $row) { 9584caa210SGreg Roach $children[] = new Place($row . $parent_text, $this->tree); 96a25f0a04SGreg Roach } 97a25f0a04SGreg Roach 98a25f0a04SGreg Roach return $children; 99a25f0a04SGreg Roach } 100a25f0a04SGreg Roach 101a25f0a04SGreg Roach /** 102a25f0a04SGreg Roach * @return string 103a25f0a04SGreg Roach */ 104a25f0a04SGreg Roach public function getURL() { 105a25f0a04SGreg Roach $url = 'placelist.php'; 106a25f0a04SGreg Roach foreach (array_reverse($this->gedcom_place) as $n => $place) { 107a25f0a04SGreg Roach $url .= $n ? '&' : '?'; 108a25f0a04SGreg Roach $url .= 'parent%5B%5D=' . rawurlencode($place); 109a25f0a04SGreg Roach } 11064b16745SGreg Roach $url .= '&ged=' . $this->tree->getNameHtml(); 111a25f0a04SGreg Roach 112a25f0a04SGreg Roach return $url; 113a25f0a04SGreg Roach } 114a25f0a04SGreg Roach 115a25f0a04SGreg Roach /** 116a25f0a04SGreg Roach * @return string 117a25f0a04SGreg Roach */ 118a25f0a04SGreg Roach public function getGedcomName() { 119a25f0a04SGreg Roach return implode(self::GEDCOM_SEPARATOR, $this->gedcom_place); 120a25f0a04SGreg Roach } 121a25f0a04SGreg Roach 122a25f0a04SGreg Roach /** 123a25f0a04SGreg Roach * @return string 124a25f0a04SGreg Roach */ 125a25f0a04SGreg Roach public function getPlaceName() { 126a25f0a04SGreg Roach $place = reset($this->gedcom_place); 127a25f0a04SGreg Roach 128a25f0a04SGreg Roach return $place ? '<span dir="auto">' . Filter::escapeHtml($place) . '</span>' : I18N::translate('unknown'); 129a25f0a04SGreg Roach } 130a25f0a04SGreg Roach 131a25f0a04SGreg Roach /** 132a25f0a04SGreg Roach * @return bool 133a25f0a04SGreg Roach */ 134a25f0a04SGreg Roach public function isEmpty() { 135a25f0a04SGreg Roach return empty($this->gedcom_place); 136a25f0a04SGreg Roach } 137a25f0a04SGreg Roach 138a25f0a04SGreg Roach /** 139a25f0a04SGreg Roach * @return string 140a25f0a04SGreg Roach */ 141a25f0a04SGreg Roach public function getFullName() { 142a25f0a04SGreg Roach if (true) { 143a25f0a04SGreg Roach // If a place hierarchy is a single entity 144a25f0a04SGreg Roach return '<span dir="auto">' . Filter::escapeHtml(implode(I18N::$list_separator, $this->gedcom_place)) . '</span>'; 145a25f0a04SGreg Roach } else { 146a25f0a04SGreg Roach // If a place hierarchy is a list of distinct items 147a25f0a04SGreg Roach $tmp = array(); 148a25f0a04SGreg Roach foreach ($this->gedcom_place as $place) { 149a25f0a04SGreg Roach $tmp[] = '<span dir="auto">' . Filter::escapeHtml($place) . '</span>'; 150a25f0a04SGreg Roach } 151a25f0a04SGreg Roach 152a25f0a04SGreg Roach return implode(I18N::$list_separator, $tmp); 153a25f0a04SGreg Roach } 154a25f0a04SGreg Roach } 155a25f0a04SGreg Roach 156a25f0a04SGreg Roach /** 157a25f0a04SGreg Roach * For lists and charts, where the full name won’t fit. 158a25f0a04SGreg Roach * 159a25f0a04SGreg Roach * @return string 160a25f0a04SGreg Roach */ 161a25f0a04SGreg Roach public function getShortName() { 16264b16745SGreg Roach $SHOW_PEDIGREE_PLACES = $this->tree->getPreference('SHOW_PEDIGREE_PLACES'); 163a25f0a04SGreg Roach 164a25f0a04SGreg Roach if ($SHOW_PEDIGREE_PLACES >= count($this->gedcom_place)) { 165a25f0a04SGreg Roach // A short place name - no need to abbreviate 166a25f0a04SGreg Roach return $this->getFullName(); 167a25f0a04SGreg Roach } else { 168a25f0a04SGreg Roach // Abbreviate the place name, for lists 16964b16745SGreg Roach if ($this->tree->getPreference('SHOW_PEDIGREE_PLACES_SUFFIX')) { 170a25f0a04SGreg Roach // The *last* $SHOW_PEDIGREE_PLACES components 171a25f0a04SGreg Roach $short_name = implode(self::GEDCOM_SEPARATOR, array_slice($this->gedcom_place, -$SHOW_PEDIGREE_PLACES)); 172a25f0a04SGreg Roach } else { 173a25f0a04SGreg Roach // The *first* $SHOW_PEDIGREE_PLACES components 174a25f0a04SGreg Roach $short_name = implode(self::GEDCOM_SEPARATOR, array_slice($this->gedcom_place, 0, $SHOW_PEDIGREE_PLACES)); 175a25f0a04SGreg Roach } 176a25f0a04SGreg Roach // Add a tool-tip showing the full name 177a25f0a04SGreg Roach return '<span title="' . Filter::escapeHtml($this->getGedcomName()) . '" dir="auto">' . Filter::escapeHtml($short_name) . '</span>'; 178a25f0a04SGreg Roach } 179a25f0a04SGreg Roach } 180a25f0a04SGreg Roach 181a25f0a04SGreg Roach /** 182a25f0a04SGreg Roach * For the "view all" option of placelist.php and find.php 183a25f0a04SGreg Roach * 184a25f0a04SGreg Roach * @return string 185a25f0a04SGreg Roach */ 186a25f0a04SGreg Roach public function getReverseName() { 187a25f0a04SGreg Roach $tmp = array(); 188a25f0a04SGreg Roach foreach (array_reverse($this->gedcom_place) as $place) { 189a25f0a04SGreg Roach $tmp[] = '<span dir="auto">' . Filter::escapeHtml($place) . '</span>'; 190a25f0a04SGreg Roach } 191a25f0a04SGreg Roach 192a25f0a04SGreg Roach return implode(I18N::$list_separator, $tmp); 193a25f0a04SGreg Roach } 194a25f0a04SGreg Roach 195a25f0a04SGreg Roach /** 19684caa210SGreg Roach * @param Tree $tree 197a25f0a04SGreg Roach * 198a25f0a04SGreg Roach * @return string[] 199a25f0a04SGreg Roach */ 20084caa210SGreg Roach public static function allPlaces($tree) { 201a25f0a04SGreg Roach $places = array(); 202a25f0a04SGreg Roach $rows = 203a25f0a04SGreg Roach Database::prepare( 204a25f0a04SGreg Roach "SELECT SQL_CACHE CONCAT_WS(', ', p1.p_place, p2.p_place, p3.p_place, p4.p_place, p5.p_place, p6.p_place, p7.p_place, p8.p_place, p9.p_place)" . 205a25f0a04SGreg Roach " FROM `##places` AS p1" . 206a25f0a04SGreg Roach " LEFT JOIN `##places` AS p2 ON (p1.p_parent_id = p2.p_id)" . 207a25f0a04SGreg Roach " LEFT JOIN `##places` AS p3 ON (p2.p_parent_id = p3.p_id)" . 208a25f0a04SGreg Roach " LEFT JOIN `##places` AS p4 ON (p3.p_parent_id = p4.p_id)" . 209a25f0a04SGreg Roach " LEFT JOIN `##places` AS p5 ON (p4.p_parent_id = p5.p_id)" . 210a25f0a04SGreg Roach " LEFT JOIN `##places` AS p6 ON (p5.p_parent_id = p6.p_id)" . 211a25f0a04SGreg Roach " LEFT JOIN `##places` AS p7 ON (p6.p_parent_id = p7.p_id)" . 212a25f0a04SGreg Roach " LEFT JOIN `##places` AS p8 ON (p7.p_parent_id = p8.p_id)" . 213a25f0a04SGreg Roach " LEFT JOIN `##places` AS p9 ON (p8.p_parent_id = p9.p_id)" . 21484caa210SGreg Roach " WHERE p1.p_file = :tree_id" . 215288566a3SGreg Roach " ORDER BY CONCAT_WS(', ', p9.p_place, p8.p_place, p7.p_place, p6.p_place, p5.p_place, p4.p_place, p3.p_place, p2.p_place, p1.p_place) COLLATE :collate" 216a25f0a04SGreg Roach ) 21784caa210SGreg Roach ->execute(array( 218288566a3SGreg Roach 'tree_id' => $tree->getTreeId(), 219288566a3SGreg Roach 'collate' => I18N::$collation, 22084caa210SGreg Roach ))->fetchOneColumn(); 221a25f0a04SGreg Roach foreach ($rows as $row) { 22284caa210SGreg Roach $places[] = new Place($row, $tree); 223a25f0a04SGreg Roach } 224a25f0a04SGreg Roach return $places; 225a25f0a04SGreg Roach } 226a25f0a04SGreg Roach 227a25f0a04SGreg Roach /** 228a25f0a04SGreg Roach * @param string $filter 22984caa210SGreg Roach * @param Tree $tree 230a25f0a04SGreg Roach * 231a25f0a04SGreg Roach * @return Place[] 232a25f0a04SGreg Roach */ 233*2769ecbeSGreg Roach public static function findPlaces($filter, Tree $tree) { 234a25f0a04SGreg Roach $places = array(); 235a25f0a04SGreg Roach $rows = 236a25f0a04SGreg Roach Database::prepare( 237a25f0a04SGreg Roach "SELECT SQL_CACHE CONCAT_WS(', ', p1.p_place, p2.p_place, p3.p_place, p4.p_place, p5.p_place, p6.p_place, p7.p_place, p8.p_place, p9.p_place)" . 238a25f0a04SGreg Roach " FROM `##places` AS p1" . 239a25f0a04SGreg Roach " LEFT JOIN `##places` AS p2 ON (p1.p_parent_id = p2.p_id)" . 240a25f0a04SGreg Roach " LEFT JOIN `##places` AS p3 ON (p2.p_parent_id = p3.p_id)" . 241a25f0a04SGreg Roach " LEFT JOIN `##places` AS p4 ON (p3.p_parent_id = p4.p_id)" . 242a25f0a04SGreg Roach " LEFT JOIN `##places` AS p5 ON (p4.p_parent_id = p5.p_id)" . 243a25f0a04SGreg Roach " LEFT JOIN `##places` AS p6 ON (p5.p_parent_id = p6.p_id)" . 244a25f0a04SGreg Roach " LEFT JOIN `##places` AS p7 ON (p6.p_parent_id = p7.p_id)" . 245a25f0a04SGreg Roach " LEFT JOIN `##places` AS p8 ON (p7.p_parent_id = p8.p_id)" . 246a25f0a04SGreg Roach " LEFT JOIN `##places` AS p9 ON (p8.p_parent_id = p9.p_id)" . 24784caa210SGreg Roach " WHERE CONCAT_WS(', ', p1.p_place, p2.p_place, p3.p_place, p4.p_place, p5.p_place, p6.p_place, p7.p_place, p8.p_place, p9.p_place) LIKE CONCAT('%', :filter_1, '%') AND CONCAT_WS(', ', p1.p_place, p2.p_place, p3.p_place, p4.p_place, p5.p_place, p6.p_place, p7.p_place, p8.p_place, p9.p_place) NOT LIKE CONCAT('%,%', :filter_2, '%') AND p1.p_file = :tree_id" . 248a25f0a04SGreg Roach " ORDER BY CONCAT_WS(', ', p1.p_place, p2.p_place, p3.p_place, p4.p_place, p5.p_place, p6.p_place, p7.p_place, p8.p_place, p9.p_place) COLLATE '" . I18N::$collation . "'" 24984caa210SGreg Roach )->execute(array( 25084caa210SGreg Roach 'filter_1' => preg_quote($filter), 25184caa210SGreg Roach 'filter_2' => preg_quote($filter), 25284caa210SGreg Roach 'tree_id' => $tree->getTreeId() 25384caa210SGreg Roach ))->fetchOneColumn(); 254a25f0a04SGreg Roach foreach ($rows as $row) { 25584caa210SGreg Roach $places[] = new Place($row, $tree); 256a25f0a04SGreg Roach } 257a25f0a04SGreg Roach return $places; 258a25f0a04SGreg Roach } 259a25f0a04SGreg Roach} 260