浏览代码

Geocoder types fixes +unit tests

alan bount 11 年之前
父节点
当前提交
ae5025784e

+ 22 - 13
Lib/GeocodeLib.php

@@ -397,27 +397,24 @@ class GeocodeLib {
 				}
 
 				$accuracy = $this->_getMaxAccuracy($result['result']);
+				$accuracyText = $this->accuracyTypes[$accuracy];
 
 				if ($this->_isNotAccurateEnough($accuracy)) {
-					$accuracy = $this->accuracyTypes[$accuracy];
 					$minAccuracy = $this->accuracyTypes[$this->options['min_accuracy']];
-					$this->setError(__('Accuracy not good enough (%s instead of at least %s)', $accuracy, $minAccuracy));
+					$this->setError(__('Accuracy not good enough (%s instead of at least %s)', $accuracyText, $minAccuracy));
 					$this->result = $result['result'];
 					return false;
 				}
 
 				if (!empty($this->options['expect'])) {
-					$types = (array)$accuracy;
-
-					$validExpectation = false;
-					foreach ($types as $type) {
-						if (in_array($type, (array)$this->options['expect'])) {
-							$validExpectation = true;
-							break;
-						}
-					}
+					$fields = (empty($result['result']['types']) ? array() : Hash::filter($result['result']['types']));
+					$found = array_intersect($fields, (array) $this->options['expect']);
+					$validExpectation = !empty($found);
 					if (!$validExpectation) {
-						$this->setError(__('Expectation not reached (%s instead of at least %s)', $accuracy, implode(', ', (array)$this->options['expect'])));
+						$this->setError(__('Expectation not reached (we have %s instead of at least %s)',
+							implode(', ', $found),
+							implode(', ', (array) $this->options['expect'])
+						));
 						$this->result = $result['result'];
 						return false;
 					}
@@ -571,8 +568,11 @@ class GeocodeLib {
 	 * Flattens result array and returns clean record
 	 * keys:
 	 * - formatted_address, type, country, country_code, country_province, country_province_code, locality, sublocality, postal_code, route, lat, lng, location_type, viewport, bounds
+	 *
+	 * @param mixed $record any level of input, whole raw array or records or single record
+	 * @return array $record organized & normalized
 	 */
-	protected function _transformData($record) {
+	public function _transformData($record) {
 		if (!is_array($record)) {
 			return $record;
 		}
@@ -584,6 +584,8 @@ class GeocodeLib {
 		}
 
 		$res = array();
+
+		// handle and organize address_components
 		$components = array();
 		if (!isset($record['address_components'][0])) {
 			$record['address_components'] = array($record['address_components']);
@@ -654,6 +656,13 @@ class GeocodeLib {
 			$res['route'] = '';
 		}
 
+		// determine accuracy types
+		if (array_key_exists('types', $record)) {
+			$res['types'] = $record['types'];
+		} else {
+			$res['types'] = array();
+		}
+
 		//TODO: add more
 
 		$res['lat'] = $record['geometry']['location']['lat'];

+ 6 - 5
Model/Behavior/GeocoderBehavior.php

@@ -132,7 +132,6 @@ class GeocoderBehavior extends ModelBehavior {
 		}
 
 		$geocode = $this->_geocode($addressData, $this->settings[$Model->alias]);
-		//debug(compact('addressData', 'geocode'));
 
 		if (empty($geocode) && !empty($this->settings[$Model->alias]['allowEmpty'])) {
 			return true;
@@ -142,10 +141,8 @@ class GeocoderBehavior extends ModelBehavior {
 		}
 
 		// if both are 0, thats not valid, otherwise continue
-		if (!empty($geocode['lat']) || !empty($geocode['lng'])) { /** HACK to prevent 0 inserts of incorrect runs - 2009-04-07 ms */
-			$Model->data[$Model->alias][$this->settings[$Model->alias]['lat']] = $geocode['lat'];
-			$Model->data[$Model->alias][$this->settings[$Model->alias]['lng']] = $geocode['lng'];
-		} else {
+		if (empty($geocode['lat']) && empty($geocode['lng'])) {
+			/** HACK to prevent 0 inserts of incorrect runs - 2009-04-07 ms */
 			if (isset($Model->data[$Model->alias][$this->settings[$Model->alias]['lat']])) {
 				unset($Model->data[$Model->alias][$this->settings[$Model->alias]['lat']]);
 			}
@@ -160,6 +157,10 @@ class GeocoderBehavior extends ModelBehavior {
 			}
 		}
 
+		// valid lat/lng found
+		$Model->data[$Model->alias][$this->settings[$Model->alias]['lat']] = $geocode['lat'];
+		$Model->data[$Model->alias][$this->settings[$Model->alias]['lng']] = $geocode['lng'];
+
 		if (!empty($this->settings[$Model->alias]['formatted_address'])) {
 			$Model->data[$Model->alias][$this->settings[$Model->alias]['formatted_address']] = $geocode['formatted_address'];
 		} else {

+ 114 - 0
Test/Case/Lib/GeocodeLibTest.php

@@ -15,6 +15,53 @@ Configure::write('Google', array(
 
 class GeocodeLibTest extends MyCakeTestCase {
 
+
+	public $apiMockupReverseGeocode40206 = array(
+		'reverseGeocode' => array(
+			'lat' => '38.2643',
+			'lng' => '-85.6999',
+			'params' => array(
+				'address' => '40206',
+				'latlng' => '',
+				'region' => '',
+				'language' => 'en',
+				'bounds' => '',
+				'sensor' => 'false',
+				'key' => 'AIzaSyAcQWSeMp_RF9W2_g2vOfLlUNCieHtHfFA',
+				'result_type' => 'sublocality'
+			)
+		),
+		'_fetch' => 'https://maps.googleapis.com/maps/api/geocode/json?address=40206&latlng=38.2643%2C-85.6999&language=en&sensor=false',
+		'raw' => '{
+			"results" : [
+				{
+					"address_components" : [
+						{ "long_name" : "40206", "short_name" : "40206", "types" : [ "postal_code" ] },
+						{ "long_name" : "Louisville", "short_name" : "Louisville", "types" : [ "locality", "political" ] },
+						{ "long_name" : "Kentucky", "short_name" : "KY", "types" : [ "administrative_area_level_1", "political" ] },
+						{ "long_name" : "United States", "short_name" : "US", "types" : [ "country", "political" ] }
+					],
+					"formatted_address" : "Louisville, KY 40206, USA",
+					"geometry" : {
+						"bounds" : {
+							"northeast" : { "lat" : 38.2852558, "lng" : -85.664309 },
+							"southwest" : { "lat" : 38.2395658, "lng" : -85.744801 }
+						},
+						"location" : { "lat" : 38.26435780000001, "lng" : -85.69997889999999 },
+						"location_type" : "APPROXIMATE",
+						"viewport" : {
+							"northeast" : { "lat" : 38.2852558, "lng" : -85.664309 },
+							"southwest" : { "lat" : 38.2395658, "lng" : -85.744801 }
+						}
+					},
+					"types" : [ "postal_code" ]
+				}
+			],
+			"status" : "OK"
+		}',
+	);
+
+
 	public function setUp() {
 		parent::setUp();
 
@@ -257,7 +304,74 @@ class GeocodeLibTest extends MyCakeTestCase {
 		}
 	}
 
+	public function test_transformData() {
+		// non-full records
+		$data = array('record' => 'OK');
+		$this->assertEqual($this->Geocode->_transformData($data), $data);
+		$data = array();
+		$this->assertEqual($this->Geocode->_transformData($data), $data);
+		$data = '';
+		$this->assertEqual($this->Geocode->_transformData($data), $data);
+		$data = 'abc';
+		$this->assertEqual($this->Geocode->_transformData($data), $data);
+
+		// full record
+		$expect = array(
+			'results' => array(
+				0 => array (
+					'formatted_address' => 'Louisville, KY 40206, USA',
+					// organized location components
+					'country' => 'United States',
+					'country_code' => 'US',
+					'country_province' => 'Kentucky',
+					'country_province_code' => 'KY',
+					'postal_code' => '40206',
+					'locality' => 'Louisville',
+					'sublocality' => '',
+					'route' => '',
+					// vetted "types"
+					'types' => array (
+						0 => 'postal_code',
+					),
+					// simple lat/lng
+					'lat' => 38.264357800000013,
+					'lng' => -85.699978899999991,
+					'location_type' => 'APPROXIMATE',
+					'viewport' => array (
+						'sw' => array (
+							'lat' => 38.239565800000001,
+							'lng' => -85.744800999999995,
+						),
+						'ne' => array (
+							'lat' => 38.285255800000002,
+							'lng' => -85.664309000000003,
+						),
+					),
+					'bounds' => array (
+						'sw' => array (
+							'lat' => 38.239565800000001,
+							'lng' => -85.744800999999995,
+						),
+						'ne' => array (
+							'lat' => 38.285255800000002,
+							'lng' => -85.664309000000003,
+						),
+					),
+					// injected static maxAccuracy
+					'maxAccuracy' => 5,
+				),
+			),
+			'status' => 'OK',
+		);
+		$data = json_decode($this->apiMockupReverseGeocode40206['raw'], true);
+		$this->assertEqual($this->Geocode->_transformData($data), $expect);
+
+		// multiple full records
+		// TODO:...
+	}
+
 	public function testGetResult() {
+
 	}
 
 }

+ 1 - 5
Test/Case/Model/Behavior/GeocoderBehaviorTest.php

@@ -237,10 +237,8 @@ class GeocoderBehaviorTest extends CakeTestCase {
 			'city' => 'Bibersfeld'
 		);
 		$res = $this->Comment->save($data);
-		//debug($this->Comment->Behaviors->Geocoder->Geocode->error()).BR;
-
+		//debug($this->Comment->Behaviors->Geocoder->Geocode->error());
 		//debug($res);
-
 		//debug($this->Comment->Behaviors->Geocoder->Geocode->debug());
 		$this->assertTrue(empty($res['Comment']['lat']) && empty($res['Comment']['lng']));
 
@@ -250,9 +248,7 @@ class GeocoderBehaviorTest extends CakeTestCase {
 		);
 		$res = $this->Comment->save($data);
 		//debug($this->Comment->Behaviors->Geocoder->Geocode->error()).BR;
-
 		//debug($res);
-
 		//debug($this->Comment->Behaviors->Geocoder->Geocode->debug());
 		$this->assertTrue(!empty($res['Comment']['lat']) && !empty($res['Comment']['lng']));
 	}