/
class.tx_wecmap_cache.php
346 lines (304 loc) · 12.5 KB
/
class.tx_wecmap_cache.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
<?php
/***************************************************************
* Copyright notice
*
* (c) 2005-2009 Christian Technology Ministries International Inc.
* All rights reserved
*
* This file is part of the Web-Empowered Church (WEC)
* (http://WebEmpoweredChurch.org) ministry of Christian Technology Ministries
* International (http://CTMIinc.org). The WEC is developing TYPO3-based
* (http://typo3.org) free software for churches around the world. Our desire
* is to use the Internet to help offer new life through Jesus Christ. Please
* see http://WebEmpoweredChurch.org/Jesus.
*
* You can redistribute this file and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation;
* either version 2 of the License, or (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This file is distributed in the hope that it will be useful for ministry,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the file!
***************************************************************/
/**
* Main address lookup class for the wec_map extension. Looks up existing
* values in cache tables or initiates service chain to perform a lookup.
* Also provides basic administrative functions for managing entries in the
* cache.
*/
class tx_wecmap_cache {
static function lookup($street, $city, $state, $zip, $country, $key='', $forceLookup=false) {
$fakeObject = null;
return self::lookupWithCallback($street, $city, $state, $zip, $country, $key, $forceLookup, $fakeObject);
}
/**
* Looks up the latitude and longitude of a specified address. Cache tables
* are searched first, followed by external service lookups.
*
* @param string The street address.
* @param string The city name.
* @param string The state name.
* @param string This ZIP code.
* @param string The country name.
* @param string The optional API key to use in the lookup.
* @param boolean Force a new lookup for address.
* @return array Lat/long array for specified address. Null if lookup fails.
*/
static function lookupWithCallback($street, $city, $state, $zip, $country, $key='', $forceLookup=false, &$pObj) {
/* Do some basic normalization on the address */
self::normalizeAddress($street, $city, $state, $zip, $country);
/* If we have enough address information, try to geocode. If not, return null. */
if(self::isEmptyAddress($street, $city, $state, $zip, $country)) {
$latlong = null;
} else {
/* Look up the address in the cache table. */
$latlong = self::find($street, $city, $state, $zip, $country);
/* Didn't find a cached match */
if (is_null($latlong)) {
/* Intiate service chain to find lat/long */
$serviceChain='';
while (is_object($lookupObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstanceService('geocode', '', $serviceChain))) {
$serviceChain.=','.$lookupObj->getServiceKey();
$latlong = $lookupObj->lookup($street, $city, $state, $zip, $country, $key);
if(method_exists($pObj, 'callback_lookupThroughGeocodeService')) {
$pObj->callback_lookupThroughGeocodeService();
}
/* If we found a match, quit. Otherwise proceed to next best service */
if($latlong) {
break;
}
}
/* Insert the lat/long into the cache. */
self::insert($street, $city, $state, $zip, $country, $latlong['lat'], $latlong['long']);
$latlong['lat'] = trim($latlong['lat'],'0');
$latlong['long'] = trim($latlong['long'],'0');
}
/* Return the lat/long, either from cache table for from fresh lookup */
if ($latlong['lat'] == 0 and $latlong['long'] == 0){
$latlong = null;
}
}
return $latlong;
}
/**
* Performs basic normalize on the address compontents. Should be called
* before any function searches cached data by address name or inserts
* values into the cache. All parameters are passed by reference and
* normalized.
*
* @param string The street address.
* @param string The city name.
* @param string The state name.
* @param string This ZIP code.
* @param string The country name.
* @param string The optional API key to use in the lookup.
* @return none
*/
static function normalizeAddress(&$street, &$city, &$state, &$zip, &$country) {
// pseudo normalize data: first letter uppercase.
// @todo: get rid of this once we implement normalization properly
$street = ucwords($street);
$city = ucwords($city);
$state = ucwords($state);
// some zip codes contain letters, so just upper case them all
$zip = strtoupper($zip);
// if length of country string is 3 or less, it's probably an abbreviation;
// make it all upper case then
if(strlen($country) < 4) {
$country = strtoupper($country);
} else {
$country= ucwords($country);
}
// to somehow normalize the data we get, we will check for country codes like DEU that the geocoder
// doesn't understand and look up a real country name from static_info_countries
// 1. check if static_info_tables is available
if ( \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('static_info_tables')) {
// 2. check the length of the country and do lookup only if it's 2 or 3 characters
$length = strlen($country);
if($length == 2) {
// try to find a country with that two character code
$rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('cn_short_en', 'static_countries', 'cn_iso_2='.$GLOBALS['TYPO3_DB']->fullQuoteStr($country,static_countries));
$newCountry = $rows[0]['cn_short_en'];
if(!empty($newCountry)) $country = $newCountry;
} else if ($length == 3) {
// try to find a country with that two character code
$rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('cn_short_en', 'static_countries', 'cn_iso_3='.$GLOBALS['TYPO3_DB']->fullQuoteStr($country,static_countries));
$newCountry = $rows[0]['cn_short_en'];
if(!empty($newCountry)) $country = $newCountry;
} else {
// try to find a country with that two character code
$rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('cn_short_en', 'static_countries', 'cn_short_local='.$GLOBALS['TYPO3_DB']->fullQuoteStr($country,static_countries));
$newCountry = $rows[0]['cn_short_en'];
if(!empty($newCountry)) $country = $newCountry;
}
}
// if we still have no country, use the default one
if(empty($country)) {
$country = tx_wecmap_backend::getExtConf('defaultCountry');
// TODO: devlog start
if(TYPO3_DLOG) {
\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('Using default country: '.$country, 'wec_map_geocode');
}
// devlog end
}
}
/**
* Returns the current geocoding status. Geocoding may be successfull,
* failed, or may not have been attempted.
*
* @param string The street address.
* @param string The city name.
* @param string The state name.
* @param string This ZIP code.
* @param string The country name.
* @return integer Status code. -1=Failed, 0=Not Completed, 1=Successfull.
*/
static function status($street, $city, $state, $zip, $country) {
/* Look up the address in the cache table */
$latlong = self::find($street, $city, $state, $zip, $country);
/* Found a cached match */
if ($latlong) {
if($latlong['lat']==0 and $latlong['long']==0) {
$statusCode = -1; /* Previous lookup failed */
} else {
$statusCode = 1; /* Previous lookup succeeded */
}
} else {
$statusCode = 0; /* Lookup has not been performed */
}
return $statusCode;
}
/**
* Looks up the latitude and longitude of a specified address in the cache
* table only.
*
* @param string The street address.
* @param string The city name.
* @param string The state name.
* @param string This ZIP code.
* @param string The country name.
* @return array Lat/long array for specified address. Null if lookup fails.
*/
static function find($street, $city, $state, $zip, $country) {
$hash = self::hash($street, $city, $state, $zip, $country);
$result = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'tx_wecmap_cache', ' address_hash="'.$hash.'"');
if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
$latlong = array('lat' => $row['latitude'], 'long' => $row['longitude']);
return $latlong;
} else {
return null;
}
}
/**
* Inserts an address with a specified latitude and longitdue into the cache table.
*
* @param string The street address.
* @param string The city name.
* @param string The state name.
* @param string This ZIP code.
* @param string The country name.
* @param string Latidude.
* @param string Longitude.
* @return none
*/
static function insert($street, $city, $state, $zip, $country, $lat, $long) {
/* Check if value is already in DB */
if (self::find($street,$city,$state,$zip,$country)) {
/* Update existing entry */
$latlong = array('latitude' => $lat, 'longitude' => $long);
$result = $GLOBALS['TYPO3_DB']->exec_UPDATEquery('tx_wecmap_cache', "address_hash='".self::hash($street, $city, $state, $zip, $country)."'", $latlong);
} else {
/* Insert new entry */
$insertArray = array();
$insertArray['address_hash'] = self::hash($street, $city, $state, $zip, $country);
$insertArray['address'] = $street.' '.$city.' '.$state.' '.$zip.' '.$country;
$insertArray['latitude'] = $lat;
$insertArray['longitude'] = $long;
/* Write address to cache table */
$result = $GLOBALS['TYPO3_DB']->exec_INSERTquery('tx_wecmap_cache', $insertArray);
}
}
/**
* Update a cached entry based on its address hash.
*
* @param string Address hash.
* @param float New latitude.
* @param float New longitude.
* @return none
*/
static function updateByUID($uid, $lat, $long) {
$latlong = array('latitude' => $lat, 'longitude' => $long);
$result = $GLOBALS['TYPO3_DB']->exec_UPDATEquery('tx_wecmap_cache', 'address_hash='.$GLOBALS['TYPO3_DB']->fullQuoteStr($uid, 'tx_wecmap_cache'), $latlong);
}
/**
* Deletes a cached entry based on its address hash.
*
* @return none
*/
static function deleteByUID($uid) {
$result = $GLOBALS['TYPO3_DB']->exec_DELETEquery('tx_wecmap_cache', 'address_hash='.$GLOBALS['TYPO3_DB']->fullQuoteStr($uid, 'tx_wecmap_cache') );
}
/**
* Deletes all cached entries.
*
* @return none
*/
static function deleteAll() {
$result = $GLOBALS['TYPO3_DB']->exec_DELETEquery('tx_wecmap_cache','');
}
/**
* Deletes a specified address from the cache table.
*
* @param string The street address.
* @param string The city name.
* @param string The state name.
* @param string This ZIP code.
* @param string The country name.
* @return none
*/
static function delete($street, $city, $state, $zip, $country) {
$result = $GLOBALS['TYPO3_DB']->exec_DELETEquery('tx_wecmap_cache', "address_hash='".self::hash($street, $city, $state, $zip, $country)."'");
}
/**
* Creates the address hash, which acts as a unique identifier for the cache table.
*
* @param string The street address.
* @param string The city name.
* @param string The state name.
* @param string This ZIP code.
* @param string The country name.
* @return string MD5 hash of the address.
*/
static function hash($street, $city, $state, $zip, $country) {
$address_string = $street.' '.$city.' '.$state.' '.$zip.' '.$country;
return md5($address_string);
}
/**
* Checks if the minimum amount of address data is available before
* geocoding.
*
* @param string The street address.
* @param string The city name.
* @param string The state name.
* @param string This ZIP code.
* @param string The country name.
* @return string True if an address is empty. False otherwise.
*/
static function isEmptyAddress($street, $city, $state, $zip, $country) {
if($street == '' and $city == '' and $state == '' and $zip == '' and $country == '') {
$isEmptyAddress = true;
} else {
$isEmptyAddress = false;
}
return $isEmptyAddress;
}
}
if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/wec_map/class.tx_wecmap_cache.php']) {
include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/wec_map/class.tx_wecmap_cache.php']);
}