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