]> git.openstreetmap.org Git - nominatim.git/blob - lib-php/AddressDetails.php
Merge remote-tracking branch 'upstream/master'
[nominatim.git] / lib-php / AddressDetails.php
1 <?php
2
3 namespace Nominatim;
4
5 require_once(CONST_LibDir.'/ClassTypes.php');
6
7 /**
8  * Detailed list of address parts for a single result
9  */
10 class AddressDetails
11 {
12     private $iPlaceID;
13     private $aAddressLines;
14
15     public function __construct(&$oDB, $iPlaceID, $sHousenumber, $mLangPref)
16     {
17         $this->iPlaceID = $iPlaceID;
18
19         if (is_array($mLangPref)) {
20             $mLangPref = $oDB->getArraySQL($oDB->getDBQuotedList($mLangPref));
21         }
22
23         if (!isset($sHousenumber)) {
24             $sHousenumber = -1;
25         }
26
27         $sSQL = 'SELECT *,';
28         $sSQL .= ' get_name_by_language(name,'.$mLangPref.') as localname';
29         $sSQL .= ' FROM get_addressdata('.$iPlaceID.','.$sHousenumber.')';
30         $sSQL .= ' ORDER BY rank_address DESC, isaddress DESC';
31
32         $this->aAddressLines = $oDB->getAll($sSQL);
33     }
34
35     private static function isAddress($aLine)
36     {
37         return $aLine['isaddress'] || $aLine['type'] == 'country_code';
38     }
39
40     public function getAddressDetails($bAll = false)
41     {
42         if ($bAll) {
43             return $this->aAddressLines;
44         }
45
46         return array_filter($this->aAddressLines, array(__CLASS__, 'isAddress'));
47     }
48
49     public function getLocaleAddress()
50     {
51         $aParts = array();
52         $sPrevResult = '';
53
54         foreach ($this->aAddressLines as $aLine) {
55             if ($aLine['isaddress'] && $sPrevResult != $aLine['localname']) {
56                 $sPrevResult = $aLine['localname'];
57                 $aParts[] = $sPrevResult;
58             }
59         }
60
61         return join(', ', $aParts);
62     }
63
64     public function getAddressNames($sCountry = null)
65     {
66         $aAddress = array();
67
68         foreach ($this->aAddressLines as $aLine) {
69             if (!self::isAddress($aLine)) {
70                 continue;
71             }
72
73             $sTypeLabel = ClassTypes\getLabelTag($aLine);
74
75             $sName = null;
76             if (isset($aLine['localname']) && $aLine['localname']!=='') {
77                 $sName = $aLine['localname'];
78             } elseif (isset($aLine['housenumber']) && $aLine['housenumber']!=='') {
79                 $sName = $aLine['housenumber'];
80             }
81
82             if (isset($sName)) {
83                 if (!isset($aAddress[$sTypeLabel])
84                     || $aLine['class'] == 'place'
85                 ) {
86                     $aAddress[$sTypeLabel] = $sName;
87                 }
88             }
89         }
90
91         return $aAddress;
92     }
93
94     /**
95      * Annotates the given json with geocodejson address information fields.
96      *
97      * @param array  $aJson  Json hash to add the fields to.
98      *
99      * Geocodejson has the following fields:
100      *  street, locality, postcode, city, district,
101      *  county, state, country
102      *
103      * Postcode and housenumber are added by type, district is not used.
104      * All other fields are set according to address rank.
105      */
106     public function addGeocodeJsonAddressParts(&$aJson)
107     {
108         foreach (array_reverse($this->aAddressLines) as $aLine) {
109             if (!$aLine['isaddress']) {
110                 continue;
111             }
112
113             if (!isset($aLine['localname']) || $aLine['localname'] == '') {
114                 continue;
115             }
116
117             if ($aLine['type'] == 'postcode' || $aLine['type'] == 'postal_code') {
118                 $aJson['postcode'] = $aLine['localname'];
119                 continue;
120             }
121
122             if ($aLine['type'] == 'house_number') {
123                 $aJson['housenumber'] = $aLine['localname'];
124                 continue;
125             }
126
127             if ($this->iPlaceID == $aLine['place_id']) {
128                 continue;
129             }
130
131             $iRank = (int)$aLine['rank_address'];
132
133             if ($iRank > 25 && $iRank < 28) {
134                 $aJson['street'] = $aLine['localname'];
135             } elseif ($iRank >= 22 && $iRank <= 25) {
136                 $aJson['locality'] = $aLine['localname'];
137             } elseif ($iRank >= 17 && $iRank <= 21) {
138                 $aJson['district'] = $aLine['localname'];
139             } elseif ($iRank >= 13 && $iRank <= 16) {
140                 $aJson['city'] = $aLine['localname'];
141             } elseif ($iRank >= 10 && $iRank <= 12) {
142                 $aJson['county'] = $aLine['localname'];
143             } elseif ($iRank >= 5 && $iRank <= 9) {
144                 $aJson['state'] = $aLine['localname'];
145             } elseif ($iRank == 4) {
146                 $aJson['country'] = $aLine['localname'];
147             }
148         }
149     }
150
151     public function getAdminLevels()
152     {
153         $aAddress = array();
154         foreach (array_reverse($this->aAddressLines) as $aLine) {
155             if (self::isAddress($aLine)
156                 && isset($aLine['admin_level'])
157                 && $aLine['admin_level'] < 15
158                 && !isset($aAddress['level'.$aLine['admin_level']])
159             ) {
160                 $aAddress['level'.$aLine['admin_level']] = $aLine['localname'];
161             }
162         }
163         return $aAddress;
164     }
165
166     public function debugInfo()
167     {
168         return $this->aAddressLines;
169     }
170 }